Launch 시스템
개요
PLEM은 RT(실시간) 스레드 분리 아키텍처를 사용합니다.
- RT 드라이버 - 단일 프로세스 내 RT 스레드들 (EtherCAT 1kHz, Controller, IPC Bridge)
- ROS2 노드들 - 여러 독립 노드가 composable하게 실행 (ros2_control, MoveIt, bridge 등)
RT 스레드와 ROS2 노드 간 통신은 POSIX 공유 메모리를 통해 이루어집니다.
런치 파일 위치: 모든 런치 파일은 plem_bringup/launch/ 디렉토리에 위치하며, 모듈식(composable) 구조로 설계되어 개별 실행 및 조합이 가능합니다.
Composable Launch 구조
| 런치 파일 | 역할 | 의존성 |
|---|---|---|
plem_launch.py | 메인 통합 런치 - 모든 컴포넌트 자동 조합 | 모든 하위 런치 포함 |
rt_driver.launch.py | RT 드라이버 (내장/사용자 공용) | 없음 (독립 실행 가능) |
ros2_control.launch.py | ROS2 Control 스택 (하드웨어 인터페이스 + 컨트롤러) | RT 드라이버 필요 |
moveit.launch.py | MoveIt 모션 플래너 | ROS2 Control 필요 |
moveit_only_launch.py | 단일 로봇 MoveIt + ROS2 Control (namespace 격리) | RT 드라이버 필요 |
multi_robot.launch.py | N대 로봇 동시 실행 (각각 독립 namespace) | RT 드라이버 필요 |
설계 원칙:
- 각 런치 파일은 독립적으로 실행 가능 (의존성 충족 시)
plem_launch.py는 하위 런치들을IncludeLaunchDescription으로 조합- 개발 시 개별 컴포넌트만 재시작 가능
시스템 실행
전체 시스템 실행
# 프로덕션 런치 (RT 드라이버 + ROS2 스택 + Python bridge 자동 시작)
ros2 launch plem_bringup plem_launch.py
# 로봇 ID 지정 (namespace 격리)
ros2 launch plem_bringup plem_launch.py robot_id:=indy
# 기록 활성화
ros2 launch plem_bringup plem_launch.py record:=true
# 외부 description 패키지 사용
ros2 launch plem_bringup plem_launch.py description_package:=ur_description
# 내장 로봇 타입 선택 (wim_description 사용 시)
ros2 launch plem_bringup plem_launch.py robot_type:=indy7
주요 런치 인수
| 인수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
robot_id | string | indy | 로봇 인스턴스 ID (ROS2 namespace, IPC prefix) |
description_package | string | wim_description | 로봇 URDF/xacro 패키지 이름 |
robot_type | string | indy7_v2 | 내장 로봇 타입 (wim_description일 때만) |
eth_interface | string | eth0 | EtherCAT 네트워크 인터페이스 |
master_index | int | 0 | EtherCAT 마스터 인덱스 (0=eth0, 1=eth1 등) |
record | bool | true | rosbag2 기록 활성화 |
bag_dir | string | ~/bags/rt_monitoring | rosbag2 저장 디렉토리 |
retention_minutes | int | 60 | bag 파일 보관 기간 (분) |
disk_threshold | int | 70 | 디스크 정리 임계값 (%) |
urdf_file | string | '' | URDF 경로 오버라이드 (외부 패키지용) |
srdf_file | string | '' | SRDF 경로 오버라이드 (외부 패키지용) |
robot_name | string | '' | 로봇 이름 오버라이드 (외부 패키지용) |
패키지는 convention 기반 구조를 따라야 합니다 (상세: Description Protocol 참조). config/, urdf/, meshes/ 디렉토리 구조 필수이며, 자동 검증 및 fallback을 지원합니다.
개별 컴포넌트 실행 (개발용)
# 터미널 1: RT 드라이버만 (내장 드라이버)
ros2 launch plem_bringup rt_driver.launch.py
# 터미널 1: RT 드라이버만 (사용자 정의 드라이버)
ros2 launch plem_bringup rt_driver.launch.py rt_package:=my_robot rt_executable:=my_robot_node
# 터미널 2: ROS2 Control만 (2초 대기 후)
ros2 launch plem_bringup ros2_control.launch.py
# 터미널 3: MoveIt만 (추가 4초 대기 후)
ros2 launch plem_bringup moveit.launch.py
rt_driver.launch.py의 추가 인수:
| 인수 | 기본값 | 설명 |
|---|---|---|
rt_package | bootstrap | RT 드라이버 실행 파일이 포함된 패키지 |
rt_executable | bootstrap_node | 실행 파일 이름 |
robot_id | indy | IPC namespace용 로봇 ID |
eth_interface | eth0 | EtherCAT 네트워크 인터페이스 |
master_index | 0 | EtherCAT 마스터 인덱스 |
rt_priority(기본 98), cycle_time_us(기본 1000) 등 고급 파라미터도 지원됩니다. 전체 목록은 ros2 launch plem_bringup rt_driver.launch.py --show-args 명령으로 확인하세요.
중요:
- RT 드라이버가 공유 메모리를 생성하므로 반드시 먼저 시작해야 합니다.
plem_launch.py는 위 컴포넌트들을 자동으로 순차 실행하는 composable launch입니다.- Python bridge (
plem_ai_server)는plem_launch.py에 통합되어 자동 시작됩니다.
다중 로봇 실행
PLEM은 namespace 격리를 통해 여러 로봇을 동시에 제어합니다.
다중 로봇 통합 런치:
# 기본 설정
ros2 launch plem_bringup multi_robot.launch.py
# 커스텀 인터페이스 지정
ros2 launch plem_bringup multi_robot.launch.py \
interface_a:=eth0 interface_b:=eth1
단일 로봇 MoveIt 런치 (namespace 격리):
# name 파라미터로 모든 노드를 /{name}/ namespace에 배치
ros2 launch plem_bringup moveit_only_launch.py name:=arm_left
plem_launch.py:robot_id파라미터 사용moveit_only_launch.py:name파라미터 사용multi_robot.launch.py:robots파라미터 (comma-separated)
namespace 구조:
| 리소스 | 단일 로봇 | 다중 로봇 (arm_left) |
|---|---|---|
| 토픽 | /indy/joint_states | /arm_left/joint_states |
| 액션 | /indy/wim_rt_driver/set_mode | /arm_left/wim_rt_driver/set_mode |
| IPC | /indy_joint_actual_values | /arm_left_joint_actual_values |
Python Bridge (plem_ai_server)
plem_ai_server는 WebSocket/UDP를 통해 외부 애플리케이션(Android 앱 등)과 통신하는 Python bridge입니다.
주요 기능:
- WebSocket을 통한 로봇 상태 스트리밍 및 명령 수신
- UDP를 통한 로봇 자동 발견
- 연결 끊김 시 자동 브레이크 잠금 (안전 기능)
RESET_ERRORWebSocket 메시지로 에러 초기화PLEM_ROBOT_ID환경 변수로 namespace 설정 (plem_launch.py에서robot_id인수로 자동 전달)
plem_launch.py에 통합: bridge는 별도 런치 파일 없이 메인 런치에서 자동 시작됩니다.
RT 드라이버
역할
- EtherCAT 통신 (1kHz)
- 토크 계산 (PID + 동역학)
- 안전 모니터링
- 공유 메모리 소유자 (생성 및 쓰기)
실행 방식
| 시나리오 | RT 드라이버 | 실행 방법 |
|---|---|---|
| 지원 로봇 (Description Package만) | PLEM 내장 RT 드라이버 | ros2 launch plem_bringup plem_launch.py 또는 scaffold bringup.launch.py |
| 새 제조사 로봇 (C++ Extension) | create_robot으로 생성한 사용자 애플리케이션 | ros2 launch <패키지명> bringup.launch.py (상세: 로봇 통합) |
상태 확인
# RT 드라이버 생존 확인 (1kHz 토픽 발행 여부)
ros2 topic hz /rt_raw
# 루프 지터 모니터링
ros2 topic echo /rt_raw --field loop_jitter_us
ROS2 노드들
주요 노드
| 노드 | 역할 | 런치 파일 | 패키지 | 위치 |
|---|---|---|---|---|
| (RT 드라이버) | RT EtherCAT 드라이버 (1kHz) | rt_driver.launch.py 또는 사용자 애플리케이션 | - | - |
| ros2_control_node | 하드웨어 인터페이스, 컨트롤러 관리 | ros2_control.launch.py | controller_manager | ROS2 Control 표준 |
| robot_state_publisher | URDF 기반 TF 발행 (500Hz) | ros2_control.launch.py | robot_state_publisher | ROS2 표준 |
| joint_trajectory_controller | 궤적 실행 액션 서버 (500Hz) | ros2_control.launch.py | joint_trajectory_controller | ROS2 Control 표준 |
| mode_control_action_server | 모드 제어 액션 서버 | ros2_control.launch.py | PLEM 런타임 | 자동 시작 |
| rt_monitoring_publisher | RT 메트릭 ROS2 발행 (10Hz) | ros2_control.launch.py | PLEM 런타임 | 자동 시작 |
| move_group | MoveIt 모션 계획 | moveit.launch.py | MoveIt2 표준 | 자동 시작 |
| plan_trajectory_action_server | 모션 계획 액션 서버 | moveit.launch.py | PLEM 런타임 | 자동 시작 |
| plem_ai_server | Python WebSocket/UDP 브리지 | plem_launch.py | PLEM 런타임 | 자동 시작 |
모든 런치 파일은 plem_bringup/launch/ 디렉토리에 위치합니다.
실행 중인 노드 확인
# 모든 ROS2 노드 목록
ros2 node list
# 컨트롤러 상태
ros2 control list_controllers
# 하드웨어 인터페이스 상태
ros2 control list_hardware_interfaces
IPC 통신
RT 드라이버와 ROS2 프로세스는 POSIX 공유 메모리로 통신합니다. 사용자가 IPC 채널을 직접 다룰 필요는 없으며, ROS2 토픽(/joint_states, /rt_raw)을 통해 데이터에 접근합니다.
robot_id가 설정된 경우 IPC 경로에 자동으로 prefix가 적용됩니다.
공유 메모리 정리 (트러블슈팅)
# 공유 메모리 영역 확인 (robot_id에 따라 접두사가 다름)
ls -lh /dev/shm/*joint_actual_values /dev/shm/*joint_target_values /dev/shm/*control_* 2>/dev/null
# 공유 메모리 정리 (RT 드라이버 종료 후)
# 기본(robot_id=indy): /dev/shm/indy_joint_actual_values 등
sudo rm -f /dev/shm/indy_* /dev/shm/joint_* 2>/dev/null
ROS2 토픽
모니터링 토픽
| 토픽 | 주기 | 내용 |
|---|---|---|
/joint_states | 500Hz | 조인트 위치, 속도, 노력 |
/rt_raw | 1kHz | RT 루프 지터, 실행 시간, 타이밍 메트릭 |
/rt_events | 이벤트 | 모드 변경, 폴트, 상태 전이 |
/rt_monitor_stats | 10Hz | 큐 통계, 오버플로 카운트 |
/tf | 500Hz | 로봇 기구학 트리 |
모든 토픽에 /{robot_id}/ namespace prefix가 적용됩니다. 예: /{robot_id}/joint_states, /{robot_id}/rt_raw.
토픽 모니터링
# 조인트 상태
ros2 topic echo /joint_states
# RT 지터
ros2 topic echo /rt_raw --field loop_jitter_us
# 모드 변경 이벤트
ros2 topic echo /rt_events
# 토픽 주파수 확인
ros2 topic hz /joint_states
시스템 종료
긴급 종료
로봇 동작 중 비상 상황에서는 다음 절차를 따르세요.
# 1. 권장: launch 실행 터미널에서 Ctrl+C (SIGINT → 정상 종료)
# 2. 강제 종료가 필요한 경우:
sudo pkill -f plem_launch # launch 프로세스 종료
sudo pkill -f bootstrap_node # RT 드라이버 종료 (내장 드라이버)
# 공유 메모리 정리
sudo rm -f /dev/shm/indy_* /dev/shm/joint_* 2>/dev/null
트러블슈팅
RT 드라이버 크래시
증상:
- EtherCAT 통신 중지
- 서보가 SAFE-OP 진입 (브레이크 체결)
- ROS2 노드가 IPC 읽기 실패
복구:
# 전체 시스템 재시작
ros2 launch plem_bringup plem_launch.py
ROS2 노드 크래시
증상:
- RT 드라이버 계속 실행
- IPC 쓰기 성공하지만 reader 없음
- 100ms 후 보호 정지 (명령 신선도 타임아웃)
복구:
# ROS2 노드만 재시작 (RT 드라이버 유지)
ros2 launch plem_bringup ros2_control.launch.py
# 기존 공유 메모리에 자동 재연결
EtherCAT 통신 손실
진단:
# EtherCAT 상태
sudo ethercat slaves
sudo ethercat master
일반적인 원인:
- 케이블 연결 해제
- 서보 전원 손실
- 네트워크 인터페이스 설정 문제
공유 메모리 손상
증상:
- 조인트 상태에 NaN/inf 값
- IPC 읽기 실패 지속
복구:
# 프로세스 종료 (Ctrl+C 권장, 또는 아래 명령)
sudo pkill -f plem_launch
sudo pkill -f bootstrap_node
# 공유 메모리 정리 후 재시작
sudo rm -f /dev/shm/indy_* /dev/shm/joint_* 2>/dev/null
ros2 launch plem_bringup plem_launch.py
요약
핵심 요점:
- RT 스레드 분리: RT 드라이버 내 RT 스레드 (1kHz 제어) + 여러 ROS2 노드 (계획/인터페이스)
- 통신: POSIX 공유 메모리를 통한 RT↔ROS2 데이터 교환
- 실행:
ros2 launch plem_bringup plem_launch.py(자동 시퀀싱) - Composable Launch 구조:
plem_launch.py: 메인 통합 (모든 컴포넌트 + Python bridge)rt_driver.launch.py: RT 드라이버만ros2_control.launch.py: ROS2 Control 스택moveit.launch.py: MoveIt 플래너moveit_only_launch.py: 단일 로봇 MoveIt (namespace 격리)multi_robot.launch.py: 다중 로봇 동시 실행
- 모듈식 설계: 각 컴포넌트를 독립적으로 실행 및 재시작 가능
- Python Bridge:
plem_ai_server가 메인 런치에 통합되어 WebSocket/UDP 통신 제공 - 다중 로봇 지원:
robot_id파라미터로 namespace 및 IPC 경로 격리 - 모니터링:
/{robot_id}/rt_raw(지터),/{robot_id}/joint_states(상태),/{robot_id}/rt_events(이벤트) - 복구: ROS2 노드는 RT 드라이버를 유지하면서 독립적으로 재시작 가능
- 런치 인수:
robot_id: 로봇 인스턴스 ID (namespace, IPC prefix)description_package: 외부 URDF/xacro 패키지 지정robot_type: 내장 로봇 타입 선택 (wim_description일 때만)
다음 단계:
- 액션 서버 - 장시간 실행 작업 처리