4.7 Trajectory Control
4.7.1 Setting the Offline Trajectory File
| Method Name | Trajectory.SetOffLineTrajectoryFile(string path ) |
|---|---|
| Description | Sets the offline trajectory file to be executed. |
| Request Parameters | path : string Offline trajectory file path, such as example file A.trajectoryA.trajectory trajectory file format is a text file, described as follows: - Line 1: 6 represents 6 axes, 0.001 represents 1ms interval between two points, 8093 represents a total of 8093 trajectory points - Line 2: Represents the initial positions of the 6 axes - Lines 3-8095: Represent trajectory points, including positions, velocities, accelerations, torque feedforward, do ports, and values of do ports for the 6 axes - do_port represents the used do port (range 1-24) - do_port is -1, indicating no IO signal will be triggered at this position - do_port is 1, do_state is 1, indicating do1 port will trigger ON signal at this position - do_port is 1, do_state is 0, indicating do1 port will trigger OFF signal at this position Users upload the offline file to the robot controller root directory using FileManager.upload, then execute the trajectory using instructions 4.7.2 and 4.7.3 |
| Return Value | StatusCode: Set operation execution result |
| Compatible robot software version | Collaborative (Copper): v7.5.0.0+ Industrial (Bronze): v7.5.0.0+ |
4.7.2 Moving the Robot to the Start Point of the Offline Trajectory
| Method Name | Trajectory.PrepareOfflineTrajectory() |
|---|---|
| Description | Moves the robot to the start point of the offline trajectory at a safe speed. |
| Request Parameters | None |
| Return Value | StatusCode: Prepare operation execution result |
| Compatible robot software version | Collaborative (Copper): v7.5.0.0+ Industrial (Bronze): v7.5.0.0+ |
4.7.3 Starting Execution of the Offline Trajectory File
| Method Name | Trajectory.ExecuteOfflineTrajectory() |
|---|---|
| Description | Starts the execution of the offline trajectory file. |
| Request Parameters | None |
| Return Value | StatusCode: Execute operation execution result |
| Compatible robot software version | Collaborative (Copper): v7.5.0.0+ Industrial (Bronze): v7.5.0.0+ |
4.7.4 Convert CSV Trajectory File to Trajectory Format
| Method | Trajectory.TransformCsvToTrajectory(string fileName ) |
|---|---|
| Description | Converts a trajectory CSV file into the trajectory format and saves it to the controller's trajectory file directory. |
| Request Parameter | fileName : string – name of the CSV trajectory file. |
| Return Value | string: path of the converted trajectory file. StatusCode: result of the conversion operation. |
| Compatible Robot Software Versions | Collaborative (Copper): v7.5.0.0+ Industrial (Bronze): v7.5.0.0+ |
4.7.5 Query Trajectory Conversion Status
| Method | Trajectory.CheckTransformStatus(string fileName ) |
|---|---|
| Description | Queries the working status of the TransformCsvToTrajectory process. |
| Request Parameter | fileName : string – result returned by the TransformCsvToTrajectory interface. |
| Return Value | TransformState: conversion state. StatusCode: result of the query operation. |
| Compatible Robot Software Versions | Collaborative (Copper): v7.5.0.0+ Industrial (Bronze): v7.5.0.0+ |
Example Code
cs
using System.IO;
using Agilebot.IR;
using Agilebot.IR.Trajectory;
using Agilebot.IR.Types;
public class OfflineTrajectory
{
public static StatusCode Run(string controllerIP, bool useLocalProxy = true)
{
// [ZH] 初始化捷勃特机器人
// [EN] Initialize the Agilebot robot
Arm controller = new Arm(controllerIP, useLocalProxy);
// [ZH] 连接捷勃特机器人
// [EN] Connect to the Agilebot robot
StatusCode code = controller.ConnectSync();
Console.WriteLine(code != StatusCode.OK ? code.GetDescription() : "连接成功/Successfully connected.");
if (code != StatusCode.OK)
{
return code;
}
try
{
// [ZH] 获取机器人模式
// [EN] Get robot mode
(UserOpMode opMode, StatusCode opCode) = controller.GetOpMode();
if (opCode == StatusCode.OK)
{
Console.WriteLine($"当前机器人模式/Current robot mode: {opMode}");
if (opMode != UserOpMode.AUTO)
{
Console.WriteLine(
$"离线轨迹执行必须在机器人自动模式下/Offline trajectory execution must be in automatic mode"
);
return StatusCode.OtherReason;
}
}
else
{
Console.WriteLine($"获取机器人模式失败/Failed to get robot mode: {opCode.GetDescription()}");
}
// [ZH] 添加程序文件到机器人中
// [EN] Add program file to robot
string file_user_program = GetTestFilePath("test.csv");
StatusCode ret_code = controller.FileManager.Upload(file_user_program, FileType.TmpFile, true);
if (ret_code != StatusCode.OK)
{
Console.WriteLine($"上传文件失败/Upload file failed: {ret_code.GetDescription()}");
return ret_code;
}
Console.WriteLine("文件上传成功/File upload success");
// [ZH] 测试CSV转换为轨迹文件功能
// [EN] Test CSV to trajectory file conversion functionality
string csvFilename = "test.csv";
(string trajFileName, StatusCode transformCode) = controller.Trajectory.TransformCsvToTrajectory(
csvFilename
);
if (transformCode != StatusCode.OK)
{
Console.WriteLine($"CSV转换失败/CSV conversion failed: {transformCode.GetDescription()}");
return transformCode;
}
Console.WriteLine($"CSV转换成功/CSV conversion success, trajectory file: {trajFileName}");
// [ZH] 检查转换状态
// [EN] Check conversion status
var startTime = System.DateTime.Now;
TransformState state;
StatusCode statusCode;
do
{
(state, statusCode) = controller.Trajectory.CheckTransformStatus(
System.IO.Path.GetFileName(trajFileName)
);
if (statusCode != StatusCode.OK)
{
Console.WriteLine($"检查转换状态失败/Check transform status failed: {statusCode.GetDescription()}");
return statusCode;
}
Console.WriteLine($"转换状态/Transform state: {state}");
Thread.Sleep(2000); // 等待2秒
if (System.DateTime.Now - startTime > System.TimeSpan.FromSeconds(60))
{
Console.WriteLine("转换状态检查超时/Transform status check timeout");
break;
}
} while (state != TransformState.TRANSFORM_SUCCESS && state != TransformState.TRANSFORM_FAILED);
if (state == TransformState.TRANSFORM_FAILED)
{
Console.WriteLine("CSV转换失败/CSV conversion failed");
return StatusCode.OtherReason;
}
// [ZH] 转换任务成功并进行了结果查询后 服务端不会继续保存转换任务的状态
// [EN] After the conversion task is successful and the result is queried, the server will not continue to save the conversion task status
(TransformState finalState, StatusCode finalCode) = controller.Trajectory.CheckTransformStatus(
System.IO.Path.GetFileName(trajFileName)
);
if (finalCode != StatusCode.OK)
{
Console.WriteLine($"最终状态检查失败/Final status check failed: {finalCode.GetDescription()}");
return finalCode;
}
Console.WriteLine($"最终转换状态/Final transform state: {finalState}");
// [ZH] 设置轨迹文件
// [EN] Set trajectory file
code = controller.Trajectory.SetOffLineTrajectoryFile("test_torque.trajectory");
if (code != StatusCode.OK)
{
Console.WriteLine($"设置轨迹文件失败/Set trajectory file failed: {code.GetDescription()}");
return code;
}
Console.WriteLine("设置轨迹文件成功/Set trajectory file success");
// [ZH] 准备离线轨迹
// [EN] Prepare offline trajectory
code = controller.Trajectory.PrepareOfflineTrajectory();
if (code != StatusCode.OK)
{
Console.WriteLine($"准备离线轨迹失败/Prepare offline trajectory failed: {code.GetDescription()}");
return code;
}
Console.WriteLine("准备离线轨迹成功/Prepare offline trajectory success");
// [ZH] 等待机器人和伺服器空闲
// [EN] Wait for robot and servo to be idle
startTime = System.DateTime.Now;
RobotState robotStatus;
ServoState servoStatus;
StatusCode robotStatusCode;
StatusCode servoStatusCode;
do
{
(robotStatus, robotStatusCode) = controller.GetRobotState();
if (robotStatusCode != StatusCode.OK)
{
Console.WriteLine($"获取机器人状态失败/Get robot state failed: {robotStatusCode.GetDescription()}");
return robotStatusCode;
}
(servoStatus, servoStatusCode) = controller.GetServoState();
if (servoStatusCode != StatusCode.OK)
{
Console.WriteLine($"获取伺服状态失败/Get servo state failed: {servoStatusCode.GetDescription()}");
return servoStatusCode;
}
Console.WriteLine($"机器人状态/Robot state: {robotStatus}, 伺服状态/Servo state: {servoStatus}");
if (robotStatus == RobotState.ROBOT_IDLE && servoStatus == ServoState.SERVO_IDLE)
{
Console.WriteLine("机器人和伺服器已空闲/Robot and servo are idle");
break;
}
Thread.Sleep(2000); // 等待2秒
if (System.DateTime.Now - startTime > System.TimeSpan.FromSeconds(60))
{
Console.WriteLine("等待机器人和伺服器空闲超时/Waiting for robot and servo idle timeout");
break;
}
} while (true);
// [ZH] 执行离线轨迹
// [EN] Execute offline trajectory
code = controller.Trajectory.ExecuteOfflineTrajectory();
if (code == StatusCode.OK)
{
Console.WriteLine("执行离线轨迹成功/Execute offline trajectory success");
Console.WriteLine("机器人开始执行轨迹程序/Robot started executing trajectory program");
}
else
{
Console.WriteLine($"执行离线轨迹失败/Execute offline trajectory failed: {code.GetDescription()}");
}
}
catch (Exception ex)
{
Console.WriteLine(
$"执行过程中发生异常/Exception occurred during execution/Exception occurred during execution: {ex.Message}"
);
code = StatusCode.OtherReason;
}
finally
{
// [ZH] 关闭连接
// [EN] Close the connection
StatusCode disconnectCode = controller.Disconnect();
if (disconnectCode != StatusCode.OK)
{
Console.WriteLine(disconnectCode.GetDescription());
if (code == StatusCode.OK)
code = disconnectCode;
}
}
return code;
}
/// <summary>
/// 获取test_files文件夹中文件的路径示例方法
/// 展示如何获取当前程序目录下的test_files文件夹中的文件路径
/// </summary>
private static string GetTestFilePath(string fileName)
{
// 获取当前程序集的目录
string? codeFilePath = new System.Diagnostics.StackTrace(true).GetFrame(0)?.GetFileName();
if (string.IsNullOrEmpty(codeFilePath))
{
throw new InvalidOperationException("无法获取当前文件路径/Cannot get current file path");
}
string? codeDirectory = Path.GetDirectoryName(codeFilePath);
if (string.IsNullOrEmpty(codeDirectory))
{
throw new InvalidOperationException("无法获取当前目录路径/Cannot get current directory path");
}
// 构建test_files文件夹路径
string testFilesDirectory = Path.Combine(codeDirectory, "test_files");
// 构建文件完整路径
string filePath = Path.Combine(testFilesDirectory, fileName);
return filePath;
}
}