Skip to content

4.5 C99 Program 프로그램 인터페이스

개요

C99 Program 은 프로그램 시작, 중지, 일시정지, 재개, 실행 중인 프로그램 조회, BasScript 실행, 프로그램 포인트 읽기/쓰기를 다룹니다.

대응 헤더 파일:

  • include/c_arm_program.h
  • include/c_arm_types.h

인터페이스 시그니처

Arm_Program_Start

c
int Arm_Program_Start(ArmHandle* h, const char* programName);
항목설명
설명지정한 프로그램을 시작합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 시작할 프로그램 이름이며 NULL 이면 안 됩니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_Program_Stop

c
int Arm_Program_Stop(ArmHandle* h, const char* programName);
항목설명
설명지정한 프로그램 또는 현재 프로그램을 중지합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름입니다. NULL 또는 빈 문자열을 전달하면 현재 실행 중인 프로그램을 중지합니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_Program_Pause

c
int Arm_Program_Pause(ArmHandle* h, const char* programName);
항목설명
설명지정한 프로그램 또는 현재 프로그램을 일시정지합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름입니다. NULL 또는 빈 문자열을 전달하면 현재 실행 중인 프로그램을 일시정지합니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_Program_Resume

c
int Arm_Program_Resume(ArmHandle* h, const char* programName);
항목설명
설명지정한 프로그램 또는 현재 프로그램을 재개합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름입니다. NULL 또는 빈 문자열을 전달하면 현재 일시정지된 프로그램을 재개합니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_Program_GetAllRunning

c
int Arm_Program_GetAllRunning(ArmHandle* h, ArmRunningProgramInfo* outArray, size_t maxCount, size_t* outCount);
항목설명
설명현재 실행 중인 프로그램 목록을 조회합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
outArray : ArmRunningProgramInfo* , 호출자가 할당하는 출력 배열입니다.
maxCount : size_t , 출력 배열 용량이며 호출자가 최대 몇 개의 요소를 받을 수 있는지를 나타냅니다.
outCount : size_t* , 출력 개수 포인터이며 성공 시 실제 개수를 기록합니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.
비고배열 출력은 호출자가 할당합니다. maxCount 는 용량을 나타내고, outCount 는 실제 개수를 반환합니다.

Arm_Program_ExecuteBasScript

c
int Arm_Program_ExecuteBasScript(ArmHandle* h, const char** lines, size_t lineCount);
항목설명
설명BAS 스크립트 텍스트 행을 실행합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
lines : const char** , BAS 스크립트 텍스트 행 배열입니다. lineCount > 0 이면 배열과 각 행이 모두 NULL 이면 안 됩니다.
lineCount : size_t , 스크립트 텍스트 행 개수입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_Program_ExecuteBasScriptEx

c
int Arm_Program_ExecuteBasScriptEx(ArmHandle* h, const ArmBasScript* script);
항목설명
설명구조화된 BasScript 객체를 실행합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
script : const ArmBasScript* , 구조화된 BasScript 스크립트 파라미터입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_ProgramPose_Read

c
int Arm_ProgramPose_Read(ArmHandle* h, const char* programName, int32_t index, int32_t programType, ArmProgramPose* outPose);
항목설명
설명지정한 프로그램 포인트를 읽습니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름이며 NULL 이면 안 됩니다.
index : int32_t , 프로그램 포인트 인덱스입니다.
programType : int32_t , 프로그램 타입이며 값은 ArmProgramType 을 참고합니다.
outPose : ArmProgramPose* , 자세 출력 구조체 포인터입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_ProgramPose_Write

c
int Arm_ProgramPose_Write(ArmHandle* h, const char* programName, int32_t index, int32_t programType, const ArmProgramPose* pose);
항목설명
설명지정한 프로그램 포인트를 씁니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름이며 NULL 이면 안 됩니다.
index : int32_t , 프로그램 포인트 인덱스입니다.
programType : int32_t , 프로그램 타입이며 값은 ArmProgramType 을 참고합니다.
pose : const ArmProgramPose* , 쓸 프로그램 포인트입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_ProgramPose_Add

c
int Arm_ProgramPose_Add(ArmHandle* h, const char* programName, int32_t index, int32_t programType, const ArmProgramPose* pose);
항목설명
설명프로그램 포인트를 추가합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름이며 NULL 이면 안 됩니다.
index : int32_t , 새 포인트를 삽입할 인덱스입니다.
programType : int32_t , 프로그램 타입이며 값은 ArmProgramType 을 참고합니다.
pose : const ArmProgramPose* , 추가할 프로그램 포인트입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_ProgramPose_ReadAll

c
int Arm_ProgramPose_ReadAll(ArmHandle* h, const char* programName, int32_t programType, ArmProgramPose* outArray, size_t maxCount, size_t* outCount);
항목설명
설명지정한 프로그램의 모든 포인트를 읽습니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름이며 NULL 이면 안 됩니다.
programType : int32_t , 프로그램 타입이며 값은 ArmProgramType 을 참고합니다.
outArray : ArmProgramPose* , 호출자가 할당하는 출력 배열입니다.
maxCount : size_t , 출력 배열 용량이며 호출자가 최대 몇 개의 요소를 받을 수 있는지를 나타냅니다.
outCount : size_t* , 출력 개수 포인터이며 성공 시 실제 개수를 기록합니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.
비고배열 출력은 호출자가 할당합니다. maxCount 는 용량을 나타내고, outCount 는 실제 개수를 반환합니다.

Arm_ProgramPose_WriteBatch

c
int Arm_ProgramPose_WriteBatch(ArmHandle* h, const char* programName, const ArmProgramPose* poses, size_t count);
항목설명
설명프로그램 포인트를 일괄로 씁니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
programName : const char* , 프로그램 이름이며 NULL 이면 안 됩니다.
poses : const ArmProgramPose* , 프로그램 포인트 배열입니다. count > 0 이면 NULL 이면 안 됩니다.
count : size_t , 배열 요소 개수입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

Arm_ProgramPose_Convert

c
int Arm_ProgramPose_Convert(ArmHandle* h, const ArmProgramPose* inPose, int32_t fromType, int32_t toType, ArmProgramPose* outPose);
항목설명
설명프로그램 포인트 타입을 변환합니다.
요청 파라미터h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.
inPose : const ArmProgramPose* , 입력 자세 또는 포인트 구조체 포인터입니다.
fromType : int32_t , 원본 포인트 타입입니다.
toType : int32_t , 대상 포인트 타입입니다.
outPose : ArmProgramPose* , 자세 출력 구조체 포인터입니다.
반환값STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다.

의미 규칙

ArmProgramType

열거값설명
ARM_PROGRAM_USER0사용자 프로그램
ARM_PROGRAM_BLOCK1블록 프로그램

ArmRunningProgramInfo

필드타입설명
threadIdint32_t프로그램 실행 스레드 ID
programNamechar[128]프로그램 이름
xpathchar[256]프로그램 노드 경로
programStatusint32_t프로그램 실행 상태
programTypechar[32]프로그램 타입 문자열

ArmBasScript

필드타입설명
nameconst char*스크립트 이름입니다. NULL 이면 빈 문자열로 처리합니다.
linesconst char**스크립트 텍스트 행 배열
lineCountsize_t스크립트 텍스트 행 개수
flagIfint32_tIF 구조 닫힘 카운트
flagSwitchint32_tSWITCH 구조 닫힘 카운트
flagWhileint32_tWHILE 구조 닫힘 카운트

ArmProgramPose

필드타입설명
idint32_t프로그램 포인트 ID
namechar[128]프로그램 포인트 이름
commentchar[256]프로그램 포인트 비고
poseArmMotionPose포인트 자세 데이터
ufint32_t사용자 좌표계 번호
tfint32_t도구 좌표계 번호

프로그램 실행

시나리오규칙
Arm_Program_Start프로그램이 없으면 PROGRAM_NOT_FOUND 를 반환합니다.
Arm_Program_Stop / Pause / ResumeprogramNameNULL 또는 빈 문자열을 전달하면 현재 프로그램에 적용됩니다.
Arm_Program_GetAllRunningoutArray == NULL 인 count-only 모드를 지원합니다.
Arm_Program_ExecuteBasScript호출자가 전달한 텍스트 행을 그대로 실행합니다.
Arm_Program_ExecuteBasScriptEx먼저 ArmBasScript 의 구조 닫힘 상태를 검증하고, 검증이 통과되면 RETURN / END 를 자동으로 보완합니다.

프로그램 포인트

시나리오반환
프로그램이 없음PROGRAM_NOT_FOUND
포인트가 없음PROGRAM_POSE_NOT_FOUND
블록 프로그램 포인트 일괄 쓰기UNSUPPORTED_FILETYPE
빈 배열 일괄 쓰기INVALID_PARAMETER

Arm_ProgramPose_ReadAll()outArray == NULL 인 count-only 모드를 지원합니다. 버퍼 용량이 실제 포인트 수보다 작으면 BUFFER_TOO_SMALL 을 반환합니다. 쓰기, 추가, 일괄 쓰기는 컨트롤러 프로그램 내용을 변경하므로 실행 전에 대상 프로그램과 포인트 인덱스를 확인해야 합니다.

최소 호출 예제

c
#include <stdio.h>  // 실행 중인 프로그램 개수 출력을 위해 printf를 포함합니다.
#include "c_arm_api.h"  // C99 SDK 최상위 헤더를 포함합니다.
int main(void)  // 예제 프로그램 진입점
{  // 예제 main 함수 시작
    ArmHandle* h = Arm_Create();  // C99 세션 핸들을 생성합니다.
    ArmRunningProgramInfo programs[8] = {0};  // 실행 중인 프로그램 배열을 준비합니다.
    size_t count = 0U;  // 프로그램 개수 수신을 준비합니다.
    if (h == NULL) {  // 핸들 생성 실패 여부를 확인합니다.
        return 1;  // 생성 실패 시 종료합니다.
    }  // 핸들 검사 종료
    if (Arm_Connect(h, "10.27.1.2", "10.27.1.102") != 0) {  // 컨트롤러에 연결합니다.
        Arm_Destroy(h);  // 연결 실패 시 핸들을 해제합니다.
        return 1;  // 오류를 반환합니다.
    }  // 연결 검사 종료
    int ret = Arm_Program_GetAllRunning(h, programs, 8, &count);  // 실행 중인 프로그램을 조회합니다.
    printf("running_count=%zu\n", count);  // 실행 중인 프로그램 개수를 출력합니다.
    Arm_Disconnect(h);  // 연결을 해제합니다.
    Arm_Destroy(h);  // 핸들을 폐기합니다.
    return ret == 0 ? 0 : 1;  // 조회 결과에 따라 반환합니다.
}  // 예제 main 함수 종료

시나리오 예제

실행 중인 프로그램 조회

c
size_t requiredCount = 0U;  // 실행 중인 프로그램 개수 수신을 준비합니다.
int countRet = Arm_Program_GetAllRunning(h, NULL, 0, &requiredCount);  // 개수만 조회합니다.
ArmRunningProgramInfo programs[16] = {0};  // 실행 중인 프로그램 배열을 준비합니다.
size_t actualCount = 0U;  // 실제 기록된 개수를 준비합니다.
int listRet = Arm_Program_GetAllRunning(h, programs, 16, &actualCount);  // 실행 중인 프로그램 상세 정보를 조회합니다.
(void)countRet;  // 예제에서 개수 조회 상태 코드를 유지합니다.
(void)listRet;  // 예제에서 목록 조회 상태 코드를 유지합니다.

BasScript 텍스트 실행

c
const char* lines[] = {  // BAS 스크립트 텍스트 행을 준비합니다.
    "WAIT SEC 0.1"  // 0.1초 대기합니다.
};  // 스크립트 행 배열 종료
/* int execRet = Arm_Program_ExecuteBasScript(h, lines, 1); */  // 스크립트 실행은 컨트롤러 상태를 변경하므로 확인 후 실행합니다.
ArmBasScript script = {0};  // 구조화된 스크립트 파라미터를 준비합니다.
script.name = "demo.bas";  // 스크립트 이름을 설정합니다.
script.lines = lines;  // 스크립트 행 배열을 설정합니다.
script.lineCount = 1;  // 스크립트 행 개수를 설정합니다.
/* int execExRet = Arm_Program_ExecuteBasScriptEx(h, &script); */  // 구조화된 스크립트 실행은 확인 후 실행합니다.

프로그램 포인트 읽기/쓰기

c
ArmProgramPose pose = {0};  // 프로그램 포인트 구조체를 준비합니다.
int readRet = Arm_ProgramPose_Read(h, "demo", 1, ARM_PROGRAM_USER, &pose);  // 1번 프로그램 포인트를 읽습니다.
ArmProgramPose converted = {0};  // 변환된 프로그램 포인트를 준비합니다.
int convertRet = Arm_ProgramPose_Convert(h, &pose, ARM_POSE_TYPE_JOINT, ARM_POSE_TYPE_CART, &converted);  // 포인트 타입을 변환합니다.
ArmProgramPose poses[2] = {0};  // 일괄 쓰기 포인트 배열을 준비합니다.
/* int writeRet = Arm_ProgramPose_Write(h, "demo", 1, ARM_PROGRAM_USER, &pose); */  // 포인트 쓰기는 프로그램을 변경하므로 확인 후 실행합니다.
/* int addRet = Arm_ProgramPose_Add(h, "demo", 2, ARM_PROGRAM_USER, &pose); */  // 포인트 추가는 프로그램을 변경하므로 확인 후 실행합니다.
/* int batchRet = Arm_ProgramPose_WriteBatch(h, "demo", poses, 2); */  // 포인트 일괄 쓰기는 프로그램을 변경하므로 확인 후 실행합니다.
(void)readRet;  // 예제에서 읽기 상태 코드를 유지합니다.
(void)convertRet;  // 예제에서 변환 상태 코드를 유지합니다.

프로그램 실행 제어

c
/* int startRet = Arm_Program_Start(h, "demo"); */  // 프로그램 시작은 컨트롤러 실행 상태를 변경하므로 확인 후 실행합니다.
/* int pauseRet = Arm_Program_Pause(h, NULL); */  // 현재 프로그램 일시정지는 확인 후 실행합니다.
/* int resumeRet = Arm_Program_Resume(h, NULL); */  // 현재 프로그램 재개는 확인 후 실행합니다.
/* int stopRet = Arm_Program_Stop(h, NULL); */  // 현재 프로그램 중지는 확인 후 실행합니다.

예제 코드

c99/program_execution/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_program] 创建句柄失败 / 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_program] 连接失败 / Connect failed, 状态码 / Status code: %d\n", ret);
        Arm_Destroy(handle);
        return 1;
    }
    printf("[c99_program] 机器人连接成功 / Robot connected successfully\n");

    // [ZH] 查询全部运行中程序。
    // [EN] Query all running programs.
    ArmRunningProgramInfo runningPrograms[8] = {0};
    size_t runningCount = 0U;
    ret = Arm_Program_GetAllRunning(handle, runningPrograms, 8U, &runningCount);
    printf("[c99_program] GetAllRunning 状态码 / GetAllRunning status code: %d, 数量 / Count: %zu\n", ret, runningCount);
    for (size_t index = 0U; index < runningCount; ++index) {
        printf("[c99_program] 运行中程序 / Running program #%zu: thread_id=%d, name=%s, xpath=%s, status=%d, type=%s\n",
            index,
            runningPrograms[index].threadId,
            runningPrograms[index].programName,
            runningPrograms[index].xpath,
            runningPrograms[index].programStatus,
            runningPrograms[index].programType);
    }

    // [ZH] 直接执行程序控制接口。
    // [EN] Execute the program control APIs directly.
    ret = Arm_Program_Start(handle, "demo.bas");
    printf("[c99_program] Start 状态码 / Start status code: %d\n", ret);
    ret = Arm_Program_Pause(handle, "demo.bas");
    printf("[c99_program] Pause 状态码 / Pause status code: %d\n", ret);
    ret = Arm_Program_Resume(handle, "demo.bas");
    printf("[c99_program] Resume 状态码 / Resume status code: %d\n", ret);
    ret = Arm_Program_Stop(handle, "demo.bas");
    printf("[c99_program] Stop 状态码 / Stop status code: %d\n", ret);

    // [ZH] 顺序执行 BAS 脚本接口。
    // [EN] Execute the BAS script APIs in sequence.
    const char* lines[3] = {
        "PRINT \"SDK example\"",
        "WAIT 0.1",
        "END"
    };
    ArmBasScript script = {0};
    script.name = "example_bas_script.bas";
    script.lines = lines;
    script.lineCount = 3U;
    ret = Arm_Program_ExecuteBasScript(handle, lines, 3U);
    printf("[c99_program] ExecuteBasScript 状态码 / ExecuteBasScript status code: %d\n", ret);
    ret = Arm_Program_ExecuteBasScriptEx(handle, &script);
    printf("[c99_program] ExecuteBasScriptEx 状态码 / ExecuteBasScriptEx status code: %d\n", ret);

    // [ZH] 构造程序点位并顺序执行全部 ProgramPose 接口。
    // [EN] Build a program pose and execute all ProgramPose APIs in sequence.
    ArmProgramPose pose = {0};
    ArmProgramPose readPose = {0};
    ArmProgramPose convertedPose = {0};
    ArmProgramPose poseList[8] = {0};
    size_t poseCount = 0U;
    pose.id = 1;
    snprintf(pose.name, sizeof(pose.name), "P1");
    snprintf(pose.comment, sizeof(pose.comment), "sdk example");
    pose.pose.poseType = ARM_POSE_TYPE_JOINT;
    pose.pose.jointSize = 6;
    pose.uf = 0;
    pose.tf = 0;
    ret = Arm_Motion_GetCurrentPose(handle, ARM_POSE_TYPE_JOINT, &pose.pose);
    printf("[c99_program] GetCurrentPose(for pose) 状态码 / GetCurrentPose(for pose) status code: %d\n", ret);
    ret = Arm_ProgramPose_Convert(handle, &pose, ARM_POSE_TYPE_JOINT, ARM_POSE_TYPE_CART, &convertedPose);
    printf("[c99_program] ProgramPose_Convert 状态码 / ProgramPose_Convert status code: %d\n", ret);
    ret = Arm_ProgramPose_Read(handle, "demo.bas", 1, ARM_PROGRAM_USER, &readPose);
    printf("[c99_program] ProgramPose_Read 状态码 / ProgramPose_Read status code: %d, id=%d, name=%s\n", ret, readPose.id, readPose.name);
    ret = Arm_ProgramPose_Write(handle, "demo.bas", 1, ARM_PROGRAM_USER, &pose);
    printf("[c99_program] ProgramPose_Write 状态码 / ProgramPose_Write status code: %d\n", ret);
    ret = Arm_ProgramPose_Add(handle, "demo.bas", 2, ARM_PROGRAM_USER, &pose);
    printf("[c99_program] ProgramPose_Add 状态码 / ProgramPose_Add status code: %d\n", ret);
    ret = Arm_ProgramPose_ReadAll(handle, "demo.bas", ARM_PROGRAM_USER, poseList, 8U, &poseCount);
    printf("[c99_program] ProgramPose_ReadAll 状态码 / ProgramPose_ReadAll status code: %d, 数量 / Count: %zu\n", ret, poseCount);
    if (poseCount == 0U) {
        poseList[0] = pose;
        poseCount = 1U;
    }
    ret = Arm_ProgramPose_WriteBatch(handle, "demo.bas", poseList, poseCount);
    printf("[c99_program] ProgramPose_WriteBatch 状态码 / ProgramPose_WriteBatch status code: %d\n", ret);

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