6.4 안전 배포 감독기
6.4.1 승격 상태
| 단계 | 모터 | 속도 | 작업공간 | 통과 기준 예시 |
|---|---|---|---|---|
| 0. OFFLINE | 분리 | - | 로그 재생 | NaN 0건, schema/단위 확인 |
| 1. DRY_RUN | 미명령 | 계산만 | 전체를 검사 | 경계 위반률 0, latency 예산 충족 |
| 2. LOW_SPEED | 활성 | 10~20% | 보수적 박스 | 무부하 20회, E-stop 시험 |
| 3. BOUNDED | 활성 | 30~50% | 실제 과업 일부 | 단일 물체 20회, 충돌 0 |
| 4. NOMINAL | 활성 | 승인값 | 승인 작업공간 | 조건별 평가 및 운영 승인 |
승격은 단방향 자동 증가가 아니다. 다음 사건은 즉시 HOLD 또는 FAULT로 강등한다.
- 워치독 timeout 또는 deadline 연속 위반
- NaN/Inf, 관절 이름/차원 불일치
- 작업공간/관절 한계 위반
- E-stop, 모터 오류, 카메라 입력 손실
- 정책/캘리브레이션/URDF 해시 변경
FAULT에서 자동 재개하지 않는다. 원인 기록, 작업공간 확인, 자세 재정렬, 사람 승인 후 낮은 단계부터 다시 시작한다.
6.4.2 작업공간 Bounding Box
베이스 프레임에서 엔드이펙터 위치 가
를 만족해야 한다. 축 정렬 박스는 구현이 쉽지만 장애물과 로봇 자체 충돌을 표현하지 못한다. 따라서 최소한 다음을 결합한다.
- 관절 soft limit
- 엔드이펙터 bounding box
- 테이블 아래 금지
- 최대 관절 변화/속도
- self-collision/환경 collision 검사
- gripper payload와 접근 방향 규칙
정책의 Cartesian target을 단순 clamp하면 방향이 바뀌거나 표면을 따라 미끄러질 수 있다. 큰 위반은 clamp보다 거부와 HOLD가 안전하다.
작업공간 검사는 반드시 어느 좌표계의 값인지와 함께 수행한다. PoseStamped의 frame_id가 base_link와 다르면 숫자만 base 좌표로 재표기해서는 안 된다. 이 장의 교육용 guard는 보수적으로 동일 base_link frame만 허용한다. 다른 frame을 지원하려면 TF2로 메시지 timestamp 시점의 transform을 조회하고, transform timeout/extrapolation은 latched FAULT로 처리한다.
6.4.3 워치독과 생명주기
워치독은 “마지막 메시지가 왔는가”뿐 아니라 current/target의 source timestamp, 수신 시각, 추론 완료, 명령 송신, Follower 상태 피드백을 각각 본다. 서로 다른 timeout 원인을 하나의 stale로 합치지 않는다. position뿐 아니라 quaternion의 finite와 norm도 검증한다.
ROS 2 노드는 구성되지 않은 상태, inactive, active, error를 구분하는 managed lifecycle을 사용할 수 있다. 그러나 lifecycle state 자체가 안전 기능의 인증을 뜻하지 않는다. 실제 토크 차단은 드라이버와 하드웨어 계약으로 검증해야 한다.
code/safety_supervisor.py는 하드웨어 비종속 상태 머신이고 code/ros2_ws/.../workspace_guard.py는 교육용 ROS 2 노드다.
잠깐 점검 — 안전 감독기는 언제 멈춰야 하는가
- 목표가 작업공간 경계를 크게 벗어났을 때 경계값으로 clamp하는 것보다 HOLD가 나은 이유는 무엇인가?
- 정책이나 캘리브레이션 파일의 hash가 바뀌면 이전 승격 상태를 그대로 유지해도 되는가?
확인 포인트: 큰 위반을 clamp하면 의도와 다른 경로를 만들 수 있으므로 명령을 거부하고 원인을 확인한다. 정책·캘리브레이션 변경은 검증했던 시스템 계약을 바꾸므로 낮은 단계에서 다시 승인해야 한다.