본문으로 건너뛰기

ROS 2 통합

PLEM 로봇은 표준 ROS 2 인터페이스(토픽·서비스·액션)로 제어하고 관측하실 수 있습니다. 이 페이지는 외부 ROS 2 환경을 PLEM 기기에 연결하는 절차와 인터페이스 카탈로그, 클라이언트가 지켜야 할 규약을 다룹니다.

전제

기기 UbuntuROS 2 배포판
22.04 (jammy)Humble
24.04 (noble)Jazzy

로봇 기기의 OS 에 대응하는 같은 ROS 2 배포판의 클라이언트가 지원 구성입니다.

모든 클라이언트는 로봇과 같은 ROS_DOMAIN_ID 와 같은 RMW 를 써야 합니다. 도메인은 기기의 plem Settings 가 소유하되 셸 ROS_DOMAIN_ID 가 있으면 그것이 우선합니다. RMW 는 스택이 강제하지 않으므로, 짐작하지 마시고 아래 plem env 로 로봇 프로세스의 실제 값을 확인하세요.

로봇 기기 안에서 접속하기 (SSH 포함)

가장 간단한 통합 지점은 로봇 기기 자체입니다. 대화형 셸은 PLEM 환경(/opt/plem — rclpy + plem_msgs)이 자동으로 잡혀 있고, 비대화형 SSH 나 CI 는 bash -lc '...' 또는 source /opt/plem/setup.bash 가 필요합니다.

기기의 DDS 는 기본적으로 루프백(lo) 전용입니다. 같은 기기 안의 대용량 전송(카메라 프레임)을 안정화하기 위한 설정입니다(QA 실측: 카메라 RGB 10.9 → 30.0 Hz). 같은 기기라도 로봇 스택과 다른 DDS 환경으로 뜬 셸은 토픽이 안 보일 수 있으므로, 아래 중 하나로 로봇 프로세스의 DDS 환경을 그대로 가져오세요.

# 1회성 조회·호출 — 실행 중 로봇 프로세스의 DDS 환경을 복사해 ros2 를 실행
plem ros2 topic list
plem ros2 action list

# 현재 셸에 영구 적용 (eval 없이 실행하면 무효)
eval "$(plem env)"

다른 호스트에서 접속하기

lo 전용 기본값 때문에 다른 PC 의 ROS 2 클라이언트는 이 기기의 토픽을 에러 없이 못 봅니다. 빈 목록이 나올 뿐 에러가 없으므로, 원격 접속 실패의 1차 확인 대상입니다. 이 프로파일(~/.ros/cyclonedds.xml, 설치와 업데이트가 배치하며 기존 파일은 보존)은 <Domain Id="any"> 로 적용되므로 도메인 번호를 바꾸셔도 lo 전용은 그대로입니다.

크로스-호스트 접속이 필요하면 로봇과 클라이언트 양쪽이 공용 NIC 를 쓰는 CycloneDDS 프로파일을 사용하세요.

  1. 기기의 ~/.ros/cyclonedds.xml 에서 <NetworkInterface name="lo" ...>name 을 실제 NIC 이름(예: eth0)으로 바꾼 프로파일을 준비하세요. 클라이언트 쪽도 같은 방식으로 맞추세요.
  2. 파일을 직접 교체하는 대신 프로세스 단위로 지정하실 수도 있습니다: CYCLONEDDS_URI=file:///path/to/profile.xml. 셸에 영구 export 하는 것은 권장하지 않습니다. 이후 same-host 도구의 기본 프로파일까지 덮습니다.
  3. 프로파일의 <SocketReceiveBufferSize min="10MB"/> 때문에 클라이언트 커널 수신 버퍼가 작으면 노드 생성이 실패할 수 있습니다. sysctl -w net.core.rmem_max=10485760 (영구 적용은 /etc/sysctl.d/) 로 맞추세요.

lo 전용 해제는 same-host 성능 이점과 네트워크 노출을 맞바꾸는 결정입니다. 필요한 기간과 네트워크에서만 적용하시기를 권장합니다.

plem_msgs 설치

PLEM 커스텀 인터페이스를 쓰시려면 클라이언트 환경에 plem_msgs 패키지가 필요합니다. 로봇 기기에는 이미 설치돼 있습니다. 별도 PC 에는 WIM 패키지 저장소(기기 온보딩 시 등록하는 것과 동일)를 등록하신 뒤 설치하세요.

sudo apt install plem-msgs # /opt/plem 에 설치 — source /opt/plem/setup.bash 로 오버레이

패키지 이름은 plem-msgs 입니다 (ros-humble-plem-msgs 형태가 아닙니다). 표준 인터페이스만으로는 관절 상태 조회와 그리퍼 사용까지 가능합니다. 다만 팔 구동은 모드 진입(아래 규약)이 필요하고 그 인터페이스가 plem_msgs 이므로, 모션 통합에는 설치가 사실상 필수입니다.

인터페이스 카탈로그

로봇 1대당 자기 네임스페이스 /{robot_id}/ 아래로 노출됩니다. robot_idplem 에서 선택하신 로봇 프로필 이름입니다. PLEM 커스텀 인터페이스는 /{robot_id}/plem/ 아래, ros2_control 표준 인터페이스는 /{robot_id}/ 직하에 있습니다.

제어

이름 (/{robot_id}/ 생략)타입용도
plem/set_modeplem_msgs/action/SetMode로봇 모드 전환 (모션 전 필수 — 아래 규약)
plem/control_commandplem_msgs/srv/SetControlCommand복구 프리미티브 — reset_error · protective_stop(브레이크 체결 = BRAKED 전환) · release_brake · free_drive. 뒤의 셋은 하위 모드·브레이크만 전환합니다(컨트롤러 전환·점유 검사 없음) — 정지·안전 참조
plem/plan_trajectoryplem_msgs/action/PlanTrajectory궤적 계획 — 기본(DETERMINISTIC)은 예측 가능한 산업 모션. 충돌 회피는 motion_intent=COLLISION_AWARE 로 요청하며 지원 모델에서 자기 충돌과 정적 장면까지 회피합니다. 실제 환경(놓인 물체) 회피에는 지각 스택이 더 필요합니다. ROS 2 Humble(JetPack 6) 트레인 한정: Jazzy(JetPack 7) 기기에는 cuMotion 이 아직 프로비저닝되지 않았습니다 — 지원 모델에서 스택을 이 옵션과 함께 기동하면 cuMotion 플러그인을 찾지 못해 기동이 실패합니다(사전 경고 없음)
joint_trajectory_controller/follow_joint_trajectorycontrol_msgs/action/FollowJointTrajectory궤적 실행 (표준) — 완료·안전 규약은 아래 참조
gripper_action_server/gripper_commandcontrol_msgs/action/GripperCommand그리퍼 (전 벤더 공통 이름 — 표준)

상태·관측

이름 (/{robot_id}/ 생략)타입비고
joint_statessensor_msgs/msg/JointState100 Hz
joint_states_throttledsensor_msgs/msg/JointState30 Hz 스로틀 — 기기에 topic_tools 가 설치된 경우에만 뜹니다(없으면 joint_states 를 직접 구독)
joint_trajectory_controller/statecontrol_msgs/msg/JointTrajectoryControllerState궤적 추적 상태 (desired/actual/error) — 실행 중 모니터링
status_broadcaster/robot_modeplem_msgs/msg/RobotMode로봇 모드 (50 Hz)
status_broadcaster/safety_modeplem_msgs/msg/SafetyMode안전 상태 (50 Hz)
gripper_statusplem_msgs/msg/GripperStatus그리퍼 상태
rt_eventsplem_msgs/msg/RtEventRT 이산 이벤트 (fault·상태 전이 — 정지 원인 판독)
rt_diagnosticsplem_msgs/msg/RtDiagnostics제어 사이클 진단, ~1 Hz 창 집계
rt_rawplem_msgs/msg/RtRawBatch사이클 전수 원시 데이터 (BestEffort 배치) — 분석용

모드 상수

RobotMode: BRAKED=0 STOPPING=1 TRAJECTORY=2 FREEDRIVE=3 ERROR=-1
SafetyMode: NORMAL=0 PROTECTIVE_STOP=1

구독 클라이언트는 다섯 값 모두를 처리해야 합니다.

클라이언트 규약

표준 ROS 2 관례 위에서 PLEM 이 요구하는 규약입니다.

모드 먼저

궤적 실행은 로봇이 TRAJECTORY 모드일 때만 수락됩니다. 그 외 모드에서 보낸 FollowJointTrajectory goal 은 거부됩니다(accepted == False, 조용한 무시가 아니라 명시적 거부).

궤적 컨트롤러는 비활성 상태로 로드되고 모드 진입이 활성화하므로, ros2 action list 에 실행 액션이 보인다고 goal 이 수락되는 것은 아닙니다. TRAJECTORY 진입은 plem/set_mode(TRAJECTORY) 로 하세요. plem/control_commandrelease_brake 는 같은 모드 전환을 일으키지만 궤적 컨트롤러를 활성화하지 않아 실행 준비가 끝나지 않습니다.

권장 시퀀스는 plem/set_mode(TRAJECTORY) → plem/plan_trajectory → 결과의 trajectoryfollow_joint_trajectory 로 실행입니다.

직접 작성한 궤적은 충돌 검사를 거치지 않는다

plem/plan_trajectory 를 거치지 않고 직접 작성해 follow_joint_trajectory 로 보낸 궤적은 어떤 충돌·경로 검사도 거치지 않습니다. 사람이 작업영역 밖에 있고 비상정지에 도달 가능한 상태에서, 검증된 동작에만 사용하세요.

실행 성공은 목표 도달이 아니다

FollowJointTrajectorySUCCEEDED 는 목표 도달을 보장하지 않습니다. 도달 tolerance 가 설정돼 있지 않아 time_from_start 경과 시점에 성공으로 보고합니다. 종료 후 joint_states 로 최종 위치를 독립 검증하세요. 서보 한계를 넘는 궤적(과도하게 짧은 time_from_start)은 보내지 마세요.

마지막 포인트의 velocity 가 0 이 아니어도 goal 은 수락됩니다(allow_nonzero_velocity_at_trajectory_end: true). 안전을 위해 마지막 포인트의 velocity 는 0 으로 두는 것을 권장합니다.

정지·복구

제어된 정지는 실행 goal 의 cancel, 즉시 정지는 plem/control_commandprotective_stop(브레이크 체결) 또는 plem/set_mode(BRAKED) 입니다. P-STOP 과 ERROR 상태는 자동 복구되지 않습니다. safety_moderobot_mode 를 감시하시고, 복구는 reset_error(P-STOP/ERROR 전용) 후 모드 재진입으로 하세요.

joint 순서

joint_statesname 배열 순서는 보장되지 않습니다 (실측 예: joint0,1,2,5,3,4). 인덱스 순서를 하드코딩하지 마시고 항상 name 으로 매핑하세요. 명령(joints_rad, JointTrajectory.joint_names)도 같은 원칙입니다.

단위

각도는 radian, 거리는 meter, 회전 표현은 쿼터니언입니다 (SI 일관). 모션 목표 필드명이 단위를 드러냅니다: MotionTarget.joints_rad. degree 값은 rad = deg × π / 180 으로 변환해 보내세요.

스키마 확인

필드 구조는 문서로 옮겨 적지 않습니다. 인터페이스 정의의 단일 진실은 plem_msgs 패키지이며, 환경에서 직접 조회하세요.

ros2 interface show plem_msgs/action/SetMode
ros2 interface show plem_msgs/action/PlanTrajectory # Goal = MotionTarget target + WorkspaceBox workspace
ros2 interface show plem_msgs/msg/MotionTarget # 모션 목표 필드 전체 (move_type·speed_scale 등)
ros2 interface show plem_msgs/srv/SetControlCommand

인터페이스 가용 시점

로봇 스택 기동 시 로봇별 1초 간격으로 ros2_control 과 그리퍼 드라이버가 병렬로 뜨고, PLEM 상태·명령 인터페이스(plem/set_mode·plem/control_command·status_broadcaster·rt_*)는 하드웨어 활성화 때 함께 생성됩니다. plem/plan_trajectory 는 계획 스택(MoveIt)이 수 초 늦게 기동하므로 마지막에 뜹니다. 클라이언트는 wait_for_server 로 대기하세요.

plem/set_mode 전환이 거부되면 두 경우를 구분하세요.

goal 이 아예 수락되지 않으면(accepted == false) 결과 메시지가 없습니다. 이미 그 모드이거나, 안전 상태가 그 전환을 막거나, 다른 모드 goal 이 처리 중인 경우입니다(모드 goal 은 직렬로 보내세요).

수락된 뒤 실패하면 결과의 message 에 사유가 담깁니다. EtherCAT 링크 비정상(로봇 전원·케이블), 다른 제어 주체(teleop)의 점유, 컨트롤러 전환 실패 등이 같은 증상으로 나타나며, robot_mode·safety_mode·rt_events 가 원인을 가릅니다.