Skip to content

4.9 C99 Trajectory APIs

Overview

The C99 Trajectory APIs cover offline trajectories, CSV conversion, trajectory recording and replay, path recording and execution, and real-time trajectory control. Real-time trajectory APIs use the Arm_RealTimeTrajectory_* prefix.

Header file:

  • include/c_arm_trajectory.h

Prerequisites and Execution Order

CategoryDescription
Session requirementEvery API requires a valid ArmHandle* ; call Arm_Connect() successfully before service calls.
Offline trajectoryCall in this order: SetOfflineTrajectoryFile , PrepareOfflineTrajectory , then ExecuteOfflineTrajectory . The prepare stage moves the robot to the trajectory start point.
CSV conversionTransformCsvToTrajectory submits a conversion task, and CheckTransformStatus queries the conversion state. The conversion response text is written to the caller-provided char* buffer.
Trajectory recordingRecordBegin enters recording state, and RecordFinish ends recording and writes the record. Replay uses ReplayStart and ReplayStop .
Path recordingPathRecordBegin starts recording .path/.traj ; PathRecordFinish ends the recording.
Real-time trajectoryCall in this order: enter control mode, set FIFO, send trajectory fragments, stop control, then exit control mode.
Motion APIsPrepareOfflineTrajectory , ExecuteOfflineTrajectory , ReplayStart , MovePath , and real-time trajectory sending all drive robot motion.

API Signatures

Arm_Trajectory_SetOfflineTrajectoryFile

c
int Arm_Trajectory_SetOfflineTrajectoryFile(ArmHandle* h, const char* path);
ItemDescription
DescriptionSets the offline trajectory file path.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
path : const char* , file path on the controller side or the path required by the interface
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_PrepareOfflineTrajectory

c
int Arm_Trajectory_PrepareOfflineTrajectory(ArmHandle* h);
ItemDescription
DescriptionPrepares the offline trajectory and moves the robot to the start point.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_ExecuteOfflineTrajectory

c
int Arm_Trajectory_ExecuteOfflineTrajectory(ArmHandle* h);
ItemDescription
DescriptionExecutes the offline trajectory.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_TransformCsvToTrajectory

c
int Arm_Trajectory_TransformCsvToTrajectory(ArmHandle* h, const char* fileName, const char* separator, const char* ioFlag, char* outResponse, size_t bufSize);
ItemDescription
DescriptionConverts a CSV trajectory file into a controller-executable trajectory file.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
fileName : const char* , CSV file name or path on the controller side
separator : const char* , CSV separator, commonly "," or " "
ioFlag : const char* , IO conversion flag; the default convention is "2"
outResponse : char* , response-text output buffer allocated by the caller
bufSize : size_t , output buffer size, including space for the trailing \0
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesString output uses the caller-provided buffer. If the buffer is too small, the function reports that through the status code.

Arm_Trajectory_CheckTransformStatus

c
int Arm_Trajectory_CheckTransformStatus(ArmHandle* h, const char* fileName, ArmTransformStatus* outStatus);
ItemDescription
DescriptionQueries CSV-to-trajectory conversion status.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
fileName : const char* , file name or path on the controller side
outStatus : ArmTransformStatus* , status output pointer
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_RecordBegin

c
int Arm_Trajectory_RecordBegin(ArmHandle* h, const char* name);
ItemDescription
DescriptionStarts trajectory reproduction recording.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , trajectory record name; must not be NULL
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_RecordFinish

c
int Arm_Trajectory_RecordFinish(ArmHandle* h, const char* name);
ItemDescription
DescriptionFinishes trajectory reproduction recording.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , trajectory record name; must not be NULL
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_ReplayStart

c
int Arm_Trajectory_ReplayStart(ArmHandle* h, const char* name);
ItemDescription
DescriptionStarts trajectory replay.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , trajectory record name; must not be NULL
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_ReplayStop

c
int Arm_Trajectory_ReplayStop(ArmHandle* h, const char* name);
ItemDescription
DescriptionStops trajectory replay.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , trajectory record name; must not be NULL
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_RecordDelete

c
int Arm_Trajectory_RecordDelete(ArmHandle* h, const char* name);
ItemDescription
DescriptionDeletes a trajectory record.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , trajectory record name; must not be NULL
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_GetRecordList

c
int Arm_Trajectory_GetRecordList(ArmHandle* h, char outNames[][128], size_t maxCount, size_t* outCount);
ItemDescription
DescriptionQueries the trajectory record list.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
outNames : char , trajectory record-name output array; each name is fixed at 128 bytes
maxCount : size_t , output array capacity, expressed as the maximum number of elements the caller can receive
outCount : size_t* , output-count pointer; on success, receives the actual number of elements
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesThe array output is allocated by the caller. maxCount is the capacity, and outCount returns the actual count.

Arm_Trajectory_GetRecordStartPose

c
int Arm_Trajectory_GetRecordStartPose(ArmHandle* h, const char* name, ArmMotionPose* outPose);
ItemDescription
DescriptionReads the start pose of a trajectory record.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , trajectory record name; must not be NULL
outPose : ArmMotionPose* , pose output-structure pointer
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_PathRecordBegin

c
int Arm_Trajectory_PathRecordBegin(ArmHandle* h, const char* name, const char* comment, double param, double angle);
ItemDescription
DescriptionStarts recording a .path/.traj file.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , path name; must not be NULL
comment : const char* , path-record comment
param : double , path-recording parameter
angle : double , path-recording angle parameter; the default convention is 1.0
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_PathRecordFinish

c
int Arm_Trajectory_PathRecordFinish(ArmHandle* h);
ItemDescription
DescriptionFinishes path recording.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_GetPathStartPose

c
int Arm_Trajectory_GetPathStartPose(ArmHandle* h, const char* name, ArmMotionPose* outPose);
ItemDescription
DescriptionReads the path start pose.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , path name; must not be NULL
outPose : ArmMotionPose* , pose output-structure pointer
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_GetPathState

c
int Arm_Trajectory_GetPathState(ArmHandle* h, const char* const* pathList, size_t pathCount, int* outStates, size_t maxCount);
ItemDescription
DescriptionQueries path states.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
pathList : const char* const* , array of path names
pathCount : size_t , number of path names
outStates : int* , path-state output array
maxCount : size_t , output array capacity, expressed as the maximum number of elements the caller can receive
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesmaxCount must be greater than or equal to pathCount . If capacity is insufficient, a buffer-too-small status code is returned and the output array is left unwritten.

Arm_Trajectory_SetPathPlannerParameter

c
int Arm_Trajectory_SetPathPlannerParameter(ArmHandle* h, double transitionTime, double scalingFactor);
ItemDescription
DescriptionSets path-planner parameters.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
transitionTime : double , path-planner transition time
scalingFactor : double , path-planner scaling factor
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_GetPathPlannerParameter

c
int Arm_Trajectory_GetPathPlannerParameter(ArmHandle* h, double* outTransitionTime, double* outScalingFactor);
ItemDescription
DescriptionReads path-planner parameters.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
outTransitionTime : double* , path-planner transition-time output pointer
outScalingFactor : double* , path-planner scaling-factor output pointer
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_Trajectory_MovePath

c
int Arm_Trajectory_MovePath(ArmHandle* h, const char* name, double vel, double acc);
ItemDescription
DescriptionExecutes path motion.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
name : const char* , path name; must not be NULL
vel : double , path motion velocity; the default convention is 100.0
acc : double , path motion acceleration; the default convention is 1.0
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Real-time Trajectory APIs

Arm_RealTimeTrajectory_EnterTrajectoryControl

c
int Arm_RealTimeTrajectory_EnterTrajectoryControl(ArmHandle* h);
ItemDescription
DescriptionEnters real-time trajectory control mode.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions
NotesAfter entering, send trajectory fragments in real-time trajectory control order, and exit control mode when finished.

Arm_RealTimeTrajectory_SetFifoSize

c
int Arm_RealTimeTrajectory_SetFifoSize(ArmHandle* h, int size);
ItemDescription
DescriptionSets the real-time trajectory FIFO size.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
size : int , FIFO size
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_RealTimeTrajectory_SendTrajectory

c
int Arm_RealTimeTrajectory_SendTrajectory(ArmHandle* h, const ArmTrajectorySegmentC* seg);
ItemDescription
DescriptionSends a real-time trajectory fragment.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
seg : const ArmTrajectorySegmentC* , real-time trajectory segment-structure pointer
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_RealTimeTrajectory_StopTrajectoryControl

c
int Arm_RealTimeTrajectory_StopTrajectoryControl(ArmHandle* h);
ItemDescription
DescriptionStops real-time trajectory control.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_RealTimeTrajectory_ExitTrajectoryControl

c
int Arm_RealTimeTrajectory_ExitTrajectoryControl(ArmHandle* h);
ItemDescription
DescriptionExits real-time trajectory control mode.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_RealTimeTrajectory_SubscribeJointStream

c
int Arm_RealTimeTrajectory_SubscribeJointStream(ArmHandle* h);
ItemDescription
DescriptionSubscribes to the joint stream.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Arm_RealTimeTrajectory_UnsubscribeJointStream

c
int Arm_RealTimeTrajectory_UnsubscribeJointStream(ArmHandle* h);
ItemDescription
DescriptionUnsubscribes from the joint stream.
Request parametersh : ArmHandle* , C99 session handle, usually created by Arm_Create() ; service APIs require a successful connection first
Return valueInteger STATUS_CODE ; 0 means success, and other values should be handled according to the status-code definitions

Rules

CategoryDescription
Offline trajectorySetOfflineTrajectoryFile sets the controller-side trajectory file, PrepareOfflineTrajectory moves to the start point, and ExecuteOfflineTrajectory executes the trajectory.
CSV conversionTransformCsvToTrajectory outputs response text through char* + bufSize ; common separator values are "," or " " , and the default convention for ioFlag is "2" .
Conversion statusCheckTransformStatus outputs ArmTransformStatus , including IDLE , RUNNING , SUCCESS , FAILED , NOT_FOUND , and UNKNOWN .
Record listGetRecordList uses the fixed-width array char outNames[][128] ; each name is fixed at 128 bytes.
Path stateGetPathState requires maxCount >= pathCount ; if capacity is insufficient, it does not write partial results.
Path planningSetPathPlannerParameter affects later MovePath execution; GetPathPlannerParameter reads the current path transition time and scaling factor.
Real-time trajectoryEnter control, set FIFO, send fragments, stop, and exit must be called in order; subscribing to the joint stream enables real-time feedback.
Trajectory fragmentArmTrajectorySegmentC describes the points sent in the current fragment through point_list and total_points ; seq is the fragment sequence number, and last_fragment indicates whether it is the last fragment.

Firmware Compatibility

FeatureMinimum firmware versionDescription
Arm_Trajectory_PathRecordBegin / Arm_Trajectory_PathRecordFinish1.5.xSupports path recording.
Arm_Trajectory_MovePathLater than 1.5.6Version 1.5.6 and earlier have an abnormal path-replay point-reading issue that may cause path replay to fail.
Arm_Trajectory_RecordBegin / Arm_Trajectory_RecordFinish / Arm_Trajectory_ReplayStart1.5.xSupports trajectory recording and replay.
Arm_Trajectory_SetPathPlannerParameter / Arm_Trajectory_GetPathPlannerParameter1.5.xSupports reading and writing path-planner parameters.

Minimal Example

c
#include <stdio.h>  // Provides printf for printing path-planner parameters.
#include "c_arm_api.h"  // Includes the aggregate C99 SDK header.
int main(void)  // Example program entry point.
{  // Enters the example main function.
    ArmHandle* h = Arm_Create();  // Creates a C99 session handle.
    double transitionTime = 0.0;  // Prepares the transition-time output variable.
    double scalingFactor = 0.0;  // Prepares the scaling-factor output variable.
    if (h == NULL) {  // Checks whether handle creation failed.
        return 1;  // Exits when creation fails.
    }  // Ends the handle check.
    if (Arm_Connect(h, "10.27.1.2", "10.27.1.102") != 0) {  // Connects to the controller.
        Arm_Destroy(h);  // Releases the handle after connection failure.
        return 1;  // Returns an error.
    }  // Ends the connection check.
    int ret = Arm_Trajectory_GetPathPlannerParameter(h, &transitionTime, &scalingFactor);  // Queries path-planner parameters.
    printf("transition=%f scaling=%f\n", transitionTime, scalingFactor);  // Prints planner parameters.
    Arm_Disconnect(h);  // Disconnects from the controller.
    Arm_Destroy(h);  // Destroys the handle.
    return ret == 0 ? 0 : 1;  // Returns according to the query result.
}  // Ends the example main function.

Scenario Examples

c
char names[8][128] = {{0}};  // Prepares the trajectory record-name array.
size_t nameCount = 0U;  // Prepares the record-count output.
ArmMotionPose startPose = {0};  // Prepares the start-pose output.
ArmTransformStatus status = ARM_TRANSFORM_UNKNOWN;  // Prepares the conversion-status output.
double transitionTime = 0.0;  // Prepares the path-planner transition time.
double scalingFactor = 0.0;  // Prepares the path-planner scaling factor.
int listRet = Arm_Trajectory_GetRecordList(h, names, 8, &nameCount);  // Queries the trajectory record list.
int poseRet = Arm_Trajectory_GetRecordStartPose(h, "demo", &startPose);  // Queries the trajectory record start point.
int statusRet = Arm_Trajectory_CheckTransformStatus(h, "demo.csv", &status);  // Queries CSV conversion status.
int plannerRet = Arm_Trajectory_GetPathPlannerParameter(h, &transitionTime, &scalingFactor);  // Queries path-planner parameters.
/* int setFileRet = Arm_Trajectory_SetOfflineTrajectoryFile(h, "/root/robot_data/traj/demo.traj"); */  // Sets the offline trajectory file; execute only after confirmation.
/* int prepareRet = Arm_Trajectory_PrepareOfflineTrajectory(h); */  // Moving to the start point moves the robot; execute only after confirmation.
/* int execRet = Arm_Trajectory_ExecuteOfflineTrajectory(h); */  // Executing the trajectory moves the robot; execute only after confirmation.
/* int transformRet = Arm_Trajectory_TransformCsvToTrajectory(h, "demo.csv", ",", "false", NULL, 0); */  // Converts a trajectory file; execute only after confirmation.
/* int beginRet = Arm_Trajectory_RecordBegin(h, "demo"); */  // Starts trajectory recording; execute only after confirmation.
/* int finishRet = Arm_Trajectory_RecordFinish(h, "demo"); */  // Finishes trajectory recording; execute only after confirmation.
/* int replayRet = Arm_Trajectory_ReplayStart(h, "demo"); */  // Starting replay moves the robot; execute only after confirmation.
/* int replayStopRet = Arm_Trajectory_ReplayStop(h, "demo"); */  // Stops replay; execute only after confirmation.
/* int deleteRet = Arm_Trajectory_RecordDelete(h, "demo"); */  // Deletes the trajectory record; execute only after confirmation.
(void)listRet;  // Keeps the status code in this example.
(void)poseRet;  // Keeps the status code in this example.
(void)statusRet;  // Keeps the status code in this example.
(void)plannerRet;  // Keeps the status code in this example.

Real-time Trajectory

c
ArmTrajectorySegmentC seg = {0};  // Prepares a real-time trajectory fragment.
/* int enterRet = Arm_RealTimeTrajectory_EnterTrajectoryControl(h); */  // Enters real-time trajectory control; execute only after confirmation.
/* int fifoRet = Arm_RealTimeTrajectory_SetFifoSize(h, 64); */  // Sets FIFO size; execute only after confirmation.
/* int sendRet = Arm_RealTimeTrajectory_SendTrajectory(h, &seg); */  // Sending a fragment drives motion; execute only after confirmation.
/* int stopRet = Arm_RealTimeTrajectory_StopTrajectoryControl(h); */  // Stops real-time trajectory control; execute only after confirmation.
/* int exitRet = Arm_RealTimeTrajectory_ExitTrajectoryControl(h); */  // Exits real-time trajectory control; execute only after confirmation.
/* int subRet = Arm_RealTimeTrajectory_SubscribeJointStream(h); */  // Subscribes to the joint stream; execute only after confirmation.
/* int unsubRet = Arm_RealTimeTrajectory_UnsubscribeJointStream(h); */  // Unsubscribes from the joint stream; execute only after confirmation.
(void)seg;  // Keeps the fragment variable in this example.

Sample code

c99/trajectory_basic/src/main.cpp
cpp
#include <stdio.h>
#include <string.h>

extern "C" {
#include "c_arm_api.h"
}

int main(void)
{
    // [ZH] 本示例直接在源码中写死连接地址,不解析命令行参数。
    // [EN] This example hard-codes the connection addresses in the source code and does not parse command-line arguments.
    // [ZH] 创建并连接 SDK 句柄。
    // [EN] Create the SDK handle and connect to the robot.
    ArmHandle* handle = Arm_Create();
    if (handle == NULL) {
        printf("[c99_trajectory] 创建句柄失败 / Failed to create the handle\n");
        return 1;
    }
    int ret = Arm_Connect(handle, "10.27.1.2", "10.27.1.102");
    if (ret != 0) {
        printf("[c99_trajectory] 连接失败 / Connect failed, 状态码 / Status code: %d\n", ret);
        Arm_Destroy(handle);
        return 1;
    }
    printf("[c99_trajectory] 机器人连接成功 / Robot connected successfully\n");

    // [ZH] 顺序执行离线轨迹接口。
    // [EN] Execute the offline trajectory APIs in sequence.
    char transformResponse[512] = {0};
    ArmTransformStatus transformStatus = ARM_TRANSFORM_UNKNOWN;
    ret = Arm_Trajectory_SetOfflineTrajectoryFile(handle, "demo.traj");
    printf("[c99_trajectory] SetOfflineTrajectoryFile 状态码 / SetOfflineTrajectoryFile status code: %d\n", ret);
    ret = Arm_Trajectory_PrepareOfflineTrajectory(handle);
    printf("[c99_trajectory] PrepareOfflineTrajectory 状态码 / PrepareOfflineTrajectory status code: %d\n", ret);
    ret = Arm_Trajectory_ExecuteOfflineTrajectory(handle);
    printf("[c99_trajectory] ExecuteOfflineTrajectory 状态码 / ExecuteOfflineTrajectory status code: %d\n", ret);
    ret = Arm_Trajectory_TransformCsvToTrajectory(handle, "demo.csv", " ", "2", transformResponse, sizeof(transformResponse));
    printf("[c99_trajectory] TransformCsvToTrajectory 状态码 / TransformCsvToTrajectory status code: %d, 返回值 / Response: %s\n", ret, transformResponse);
    ret = Arm_Trajectory_CheckTransformStatus(handle, "demo.csv", &transformStatus);
    printf("[c99_trajectory] CheckTransformStatus 状态码 / CheckTransformStatus status code: %d, 状态 / Status: %d\n", ret, transformStatus);

    // [ZH] 顺序执行录制、回放和路径接口。
    // [EN] Execute the record, replay, and path APIs in sequence.
    char recordNames[8][128] = {{0}};
    size_t recordCount = 0U;
    ArmMotionPose recordPose = {0};
    ArmMotionPose pathPose = {0};
    const char* pathList[1] = {"demo_path"};
    int pathStates[1] = {0};
    double transitionTime = 0.0;
    double scalingFactor = 0.0;
    ret = Arm_Trajectory_RecordBegin(handle, "demo_record");
    printf("[c99_trajectory] RecordBegin 状态码 / RecordBegin status code: %d\n", ret);
    ret = Arm_Trajectory_RecordFinish(handle, "demo_record");
    printf("[c99_trajectory] RecordFinish 状态码 / RecordFinish status code: %d\n", ret);
    ret = Arm_Trajectory_ReplayStart(handle, "demo_record");
    printf("[c99_trajectory] ReplayStart 状态码 / ReplayStart status code: %d\n", ret);
    ret = Arm_Trajectory_ReplayStop(handle, "demo_record");
    printf("[c99_trajectory] ReplayStop 状态码 / ReplayStop status code: %d\n", ret);
    ret = Arm_Trajectory_RecordDelete(handle, "demo_record");
    printf("[c99_trajectory] RecordDelete 状态码 / RecordDelete status code: %d\n", ret);
    ret = Arm_Trajectory_GetRecordList(handle, recordNames, 8U, &recordCount);
    printf("[c99_trajectory] GetRecordList 状态码 / GetRecordList status code: %d, 数量 / Count: %zu\n", ret, recordCount);
    ret = Arm_Trajectory_GetRecordStartPose(handle, "demo_record", &recordPose);
    printf("[c99_trajectory] GetRecordStartPose 状态码 / GetRecordStartPose status code: %d\n", ret);
    ret = Arm_Trajectory_PathRecordBegin(handle, "demo_path", "sdk example", 1.0, 1.0);
    printf("[c99_trajectory] PathRecordBegin 状态码 / PathRecordBegin status code: %d\n", ret);
    ret = Arm_Trajectory_PathRecordFinish(handle);
    printf("[c99_trajectory] PathRecordFinish 状态码 / PathRecordFinish status code: %d\n", ret);
    ret = Arm_Trajectory_GetPathStartPose(handle, "demo_path", &pathPose);
    printf("[c99_trajectory] GetPathStartPose 状态码 / GetPathStartPose status code: %d\n", ret);
    ret = Arm_Trajectory_GetPathState(handle, pathList, 1U, pathStates, 1U);
    printf("[c99_trajectory] GetPathState 状态码 / GetPathState status code: %d, 状态 / State: %d\n", ret, pathStates[0]);
    ret = Arm_Trajectory_SetPathPlannerParameter(handle, 0.2, 1.0);
    printf("[c99_trajectory] SetPathPlannerParameter 状态码 / SetPathPlannerParameter status code: %d\n", ret);
    ret = Arm_Trajectory_GetPathPlannerParameter(handle, &transitionTime, &scalingFactor);
    printf("[c99_trajectory] GetPathPlannerParameter 状态码 / GetPathPlannerParameter status code: %d, transition_time=%.6f, scaling_factor=%.6f\n", ret, transitionTime, scalingFactor);
    ret = Arm_Trajectory_MovePath(handle, "demo_path", 50.0, 1.0);
    printf("[c99_trajectory] MovePath 状态码 / MovePath status code: %d\n", ret);

    // [ZH] 顺序执行实时轨迹接口。
    // [EN] Execute the real-time trajectory APIs in sequence.
    double positions[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    ArmTrajectoryPointC point = {0};
    ArmTrajectorySegmentC segment = {0};
    point.position_list = positions;
    point.position_count = 6;
    segment.point_list = &point;
    segment.total_points = 1U;
    segment.seq = 1U;
    segment.last_fragment = 1U;
    ret = Arm_RealTimeTrajectory_EnterTrajectoryControl(handle);
    printf("[c99_trajectory] EnterTrajectoryControl 状态码 / EnterTrajectoryControl status code: %d\n", ret);
    ret = Arm_RealTimeTrajectory_SetFifoSize(handle, 8);
    printf("[c99_trajectory] SetFifoSize 状态码 / SetFifoSize status code: %d\n", ret);
    ret = Arm_RealTimeTrajectory_SubscribeJointStream(handle);
    printf("[c99_trajectory] SubscribeJointStream 状态码 / SubscribeJointStream status code: %d\n", ret);
    ret = Arm_RealTimeTrajectory_SendTrajectory(handle, &segment);
    printf("[c99_trajectory] SendTrajectory 状态码 / SendTrajectory status code: %d\n", ret);
    ret = Arm_RealTimeTrajectory_StopTrajectoryControl(handle);
    printf("[c99_trajectory] StopTrajectoryControl 状态码 / StopTrajectoryControl status code: %d\n", ret);
    ret = Arm_RealTimeTrajectory_UnsubscribeJointStream(handle);
    printf("[c99_trajectory] UnsubscribeJointStream 状态码 / UnsubscribeJointStream status code: %d\n", ret);
    ret = Arm_RealTimeTrajectory_ExitTrajectoryControl(handle);
    printf("[c99_trajectory] ExitTrajectoryControl 状态码 / ExitTrajectoryControl status code: %d\n", ret);

    // [ZH] 断开连接并销毁句柄。
    // [EN] Disconnect and destroy the handle.
    Arm_Disconnect(handle);
    Arm_Destroy(handle);
    printf("[c99_trajectory] 示例结束 / Example finished\n");
    return 0;
}