Skip to content

3.15 CoordinateSystemManager 좌표계 관리

개요

Arm::coordinateSystemManager 은 사용자 좌표계와 도구 좌표계를 관리하는 데 사용됩니다. 공개 기능은 다음과 같습니다.

  1. 좌표계 목록 조회
  2. 단일 좌표계 상세 정보 조회
  3. 좌표계 추가, 업데이트, 삭제
  4. 좌표계 포즈 계산

공개 메서드

cpp
GetCoordinateList(coordinate_system_model::COORDINATE_SYS_TYPE coordinateSysType) -> std::pair<std::vector<coordinate_system_model::CoordinateInfo>, STATUS_CODE>
Get(coordinate_system_model::COORDINATE_SYS_TYPE coordinateSysType, int32_t id) -> std::pair<coordinate_system_model::Coordinate, STATUS_CODE>
Add(coordinate_system_model::COORDINATE_SYS_TYPE coordinateSysType, coordinate_system_model::Coordinate coordinate) -> STATUS_CODE
Update(coordinate_system_model::COORDINATE_SYS_TYPE coordinateSysType, coordinate_system_model::Coordinate coordinate) -> STATUS_CODE
Delete(coordinate_system_model::COORDINATE_SYS_TYPE coordinateSysType, int32_t id) -> STATUS_CODE
Calculate(coordinate_system_model::COORDINATE_SYS_TYPE coordinateSysType, std::vector<coordinate_system_model::Coordinate> coordinate) -> std::pair<CartesianPosition, STATUS_CODE>
메서드입력출력설명
GetCoordinateList좌표계 타입std::pair<std::vector<coordinate_system_model::CoordinateInfo>, STATUS_CODE>목록 가져오기
Get좌표계 타입, IDstd::pair<coordinate_system_model::Coordinate, STATUS_CODE>상세 정보 가져오기
Add좌표계 타입, 좌표계 객체STATUS_CODE추가
Update좌표계 타입, 좌표계 객체STATUS_CODE업데이트
Delete좌표계 타입, IDSTATUS_CODE삭제
Calculate좌표계 타입, 보정점 목록std::pair<CartesianPosition, STATUS_CODE>좌표계 포즈 계산

타입 기준

coordinate_system_model::COORDINATE_SYS_TYPE

헤더 파일: include/coordinate_sys_type.h

coordinate_system_model::COORDINATE_SYS_TYPE 은 좌표계 인터페이스에 현재 조작 대상이 사용자 좌표계인지 도구 좌표계인지 알려 주는 데 사용됩니다. 모든 Get / Add / Update / Delete / Calculate 인터페이스에서 필요합니다.

열거형설명
USER_FRAME0사용자 좌표계. 공작물, 작업 위치 등 사용자 정의 좌표를 설명합니다.
TOOL_FRAME1도구 좌표계. 말단 도구 TCP 좌표를 설명합니다.

coordinate_system_model::CoordinateInfo

필드타입설명
idint32_t좌표계 번호
namestd::string좌표계 이름
commentstd::string비고
groupIdint32_t그룹 ID. 기본값은 1

coordinate_system_model::Coordinate

필드타입설명
idint32_t좌표계 번호
namestd::string좌표계 이름
commentstd::string비고
groupIdint32_t그룹 ID. 기본값은 1
dataCartesianPosition좌표계 포즈. x/y/z/a/b/c 로 표현

사용 전제

  • 먼저 Arm::Connect() 를 완료해야 합니다.
  • Calculate() 는 연결 후 채워지는 로봇 모델 정보에 의존합니다. 연결이 완료되지 않았거나 모델을 사용할 수 없으면 실패합니다.
  • 같은 Arm 세션의 좌표계 요청은 여전히 통합 네트워크 스레드에서 직렬로 실행됩니다.

실패 기준

시나리오반환
연결되지 않았거나 인터페이스 모듈이 초기화되지 않음OTHER_ERR
좌표계 타입이 유효하지 않음INVALID_PARAMETER
Calculate 에 모델 정보가 없음INVALID_PARAMETER

주의 사항: 직교 좌표 각도 래핑

Calculate() 가 반환하는 CartesianPosition 에서 자세 성분 a / b / c (Euler angle)의 값 범위는 **[-180°, 180°]**입니다. 같은 물리 자세가 -180° 또는 180°로 표현될 수 있으며, 두 값은 동등합니다.

두 포즈가 "가까운지" 비교할 때 위치 성분( x / y / z )은 차이의 절댓값을 직접 사용할 수 있지만, 자세 성분은 먼저 360° 래핑 정규화를 해야 합니다. 그렇지 않으면 360°의 가짜 편차가 나타날 수 있습니다.

권장 비교 방식:

cpp
double posDiff = std::abs(pose1.x - pose2.x);  // 위치 성분은 차이를 직접 비교할 수 있습니다.
double angleDiff = std::fmod(std::abs(pose1.a - pose2.a), 360.0);  // 자세 성분은 먼저 360도 주기 안으로 환산합니다.
if (angleDiff > 180.0) {  // 각도 차이가 180도를 넘는지 판단합니다.
    angleDiff = 360.0 - angleDiff;  // 더 짧은 방향의 각도 차이를 사용합니다.
}  // 각도 차이 정규화 판단을 종료합니다.

이 규칙은 MotionControl , TrajectoryManager , CoordinateSystemManager 등 직교 좌표 포즈를 반환하는 모든 인터페이스에 적용됩니다.

시나리오 예제

아래 조각들은 "조회, 계산, 추가/업데이트, 삭제" 흐름으로 이 페이지의 API를 교차해서 다룹니다. 조각들은 이미 연결에 성공한 arm 객체를 이어받는다고 가정합니다. 추가, 업데이트, 삭제는 컨트롤러 좌표계 구성을 변경하므로 확인한 뒤 실행하십시오.

좌표계 목록 및 상세 정보 조회

cpp
auto [userList, listRet] = arm.coordinateSystemManager.GetCoordinateList(  // 사용자 좌표계 목록을 조회합니다.
    coordinate_system_model::COORDINATE_SYS_TYPE::USER_FRAME  // 사용자 좌표계 타입을 지정합니다.
);  // 좌표계 목록 조회 호출을 종료합니다.
auto [userCoord, getRet] = arm.coordinateSystemManager.Get(  // 지정 사용자 좌표계 상세 정보를 조회합니다.
    coordinate_system_model::COORDINATE_SYS_TYPE::USER_FRAME,  // 사용자 좌표계 타입을 지정합니다.
    1  // 좌표계 ID를 지정합니다.
);  // 좌표계 상세 정보 조회 호출을 종료합니다.
if (listRet == STATUS_CODE::OK || getRet == STATUS_CODE::OK) {  // 좌표계 조회 성공 여부를 판단합니다.
    std::cout << "coordinate_count=" << userList.size() << " name=" << userCoord.name << "\n";  // 좌표계 조회 요약을 출력합니다.
}  // 좌표계 조회 판단을 종료합니다.

좌표계 포즈 계산

cpp
coordinate_system_model::Coordinate point;  // 보정점 객체를 생성합니다.
point.data = CartesianPosition{0, 0, 0, 0, 0, 0};  // 보정점 포즈 예제를 설정합니다.
std::vector<coordinate_system_model::Coordinate> samplePoints = {point, point, point};  // 좌표계 계산에 사용할 보정점 예제를 준비합니다.
auto [calculatedPose, calculateRet] = arm.coordinateSystemManager.Calculate(  // 보정점을 기준으로 좌표계 포즈를 계산합니다.
    coordinate_system_model::COORDINATE_SYS_TYPE::USER_FRAME,  // 사용자 좌표계 타입을 지정합니다.
    samplePoints  // 보정점 목록을 전달합니다.
);  // 좌표계 계산 호출을 종료합니다.

좌표계 추가 및 업데이트

cpp
coordinate_system_model::Coordinate coord;  // 추가 또는 업데이트할 좌표계 객체를 생성합니다.
coord.id = 1;  // 좌표계 ID 예제를 설정합니다.
coord.name = "sdk_user_frame";  // 좌표계 이름을 설정합니다.
coord.comment = "created by sdk example";  // 좌표계 비고를 설정합니다.
coord.groupId = 1;  // 좌표계 그룹 ID를 설정합니다.
coord.data = CartesianPosition{0, 0, 0, 0, 0, 0};  // 좌표계 포즈를 설정합니다.
// STATUS_CODE addRet = arm.coordinateSystemManager.Add(coordinate_system_model::COORDINATE_SYS_TYPE::USER_FRAME, coord);  // 좌표계 추가는 컨트롤러 구성을 변경하므로 확인한 뒤 실행하십시오.
coord.comment = "updated by sdk example";  // 업데이트 호출을 보여 주기 위해 비고 필드를 수정합니다.
// STATUS_CODE updateRet = arm.coordinateSystemManager.Update(coordinate_system_model::COORDINATE_SYS_TYPE::USER_FRAME, coord);  // 좌표계 업데이트는 컨트롤러 구성을 변경하므로 확인한 뒤 실행하십시오.

좌표계 삭제

cpp
// STATUS_CODE deleteRet = arm.coordinateSystemManager.Delete(coordinate_system_model::COORDINATE_SYS_TYPE::USER_FRAME, 1);  // 좌표계 삭제는 컨트롤러 구성을 변경하므로 확인한 뒤 실행하십시오.

예제

cpp17/coordinate_system_basic/src/main.cpp
cpp
#include "query_coordinate_systems/run.h"
#include "calculate_user_frame/run.h"
#include "write_coordinate_systems/run.h"

int main(void)
{
    // [ZH] 默认只调用一个门面方法;如需体验其他接口,请把下一行替换成下面任意一行。
    // [EN] The main function calls only one facade by default. Replace the next line with any line below to try other APIs.
    return RunCoordinateSystemBasicQueryCoordinateSystems();
    // return RunCoordinateSystemBasicCalculateUserFrame();
    // return RunCoordinateSystemBasicWriteCoordinateSystems();
}
c99/coordinate_system_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_coordinate] 创建句柄失败 / 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_coordinate] 连接失败 / Connect failed, 状态码 / Status code: %d\n", ret);
        Arm_Destroy(handle);
        return 1;
    }
    printf("[c99_coordinate] 机器人连接成功 / Robot connected successfully\n");

    // [ZH] 读取工具坐标系列表与第一个坐标系详情。
    // [EN] Read the tool-frame list and the first frame detail.
    ArmCoordinateInfo infoList[8] = {0};
    size_t infoCount = 0U;
    ret = Arm_CoordinateSystem_GetList(handle, ARM_COORDINATE_SYSTEM_TOOL_FRAME, infoList, 8U, &infoCount);
    printf("[c99_coordinate] GetList 状态码 / GetList status code: %d, 数量 / Count: %zu\n", ret, infoCount);
    if (infoCount > 0U) {
        ArmCoordinate detail = {0};
        ret = Arm_CoordinateSystem_Get(handle, ARM_COORDINATE_SYSTEM_TOOL_FRAME, infoList[0].id, &detail);
        printf("[c99_coordinate] Get 状态码 / Get status code: %d, id=%d, name=%s\n", ret, detail.id, detail.name);
    }

    // [ZH] 构造 3 点并计算用户坐标系。
    // [EN] Build three points and calculate a user frame.
    ArmCoordinate calculatePoints[3] = {0};
    for (int index = 0; index < 3; ++index) {
        calculatePoints[index].id = index + 1;
        calculatePoints[index].groupId = 1;
        snprintf(calculatePoints[index].name, sizeof(calculatePoints[index].name), "p%d", index + 1);
        snprintf(calculatePoints[index].comment, sizeof(calculatePoints[index].comment), "sdk example");
        calculatePoints[index].data.x = 1.0 + index * 3.0;
        calculatePoints[index].data.y = 2.0 + index * 3.0;
        calculatePoints[index].data.z = 3.0 + index * 3.0;
        calculatePoints[index].data.a = 10.0 + index * 30.0;
        calculatePoints[index].data.b = 20.0 + index * 30.0;
        calculatePoints[index].data.c = 30.0 + index * 30.0;
    }
    ArmCoordinatePose pose = {0};
    ret = Arm_CoordinateSystem_Calculate(handle, ARM_COORDINATE_SYSTEM_USER_FRAME, calculatePoints, 3U, &pose);
    printf("[c99_coordinate] Calculate 状态码 / Calculate status code: %d, 位姿 / Pose: [%.6f, %.6f, %.6f, %.6f, %.6f, %.6f]\n",
        ret,
        pose.x,
        pose.y,
        pose.z,
        pose.a,
        pose.b,
        pose.c);

    // [ZH] 顺序执行新增、更新和删除接口。
    // [EN] Execute the add, update, and delete APIs in sequence.
    ArmCoordinate userFrame = {0};
    userFrame.id = 10;
    userFrame.groupId = 1;
    snprintf(userFrame.name, sizeof(userFrame.name), "user_demo");
    snprintf(userFrame.comment, sizeof(userFrame.comment), "sdk example");
    userFrame.data = pose;
    ret = Arm_CoordinateSystem_Add(handle, ARM_COORDINATE_SYSTEM_USER_FRAME, &userFrame);
    printf("[c99_coordinate] Add 状态码 / Add status code: %d\n", ret);
    ret = Arm_CoordinateSystem_Update(handle, ARM_COORDINATE_SYSTEM_USER_FRAME, &userFrame);
    printf("[c99_coordinate] Update 状态码 / Update status code: %d\n", ret);
    ret = Arm_CoordinateSystem_Delete(handle, ARM_COORDINATE_SYSTEM_USER_FRAME, userFrame.id);
    printf("[c99_coordinate] Delete 状态码 / Delete status code: %d\n", ret);

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