3.5 안전한 텔레오퍼레이션 루프
M25.06 키보드·도구 접촉·상태/행동 기록에서 활성 입력/신선도와 제한 후 속도 전송·접촉 관측을 구분한다. 아래 관절 위치 HOLD와 속도0은 서로 다른 인터페이스이며 어느 쪽도 실제 정지/힘0의 관측을 자동 생성하지 않는다.
3.5.1 안전 계층
안전은 하나의 if 문이 아니라 독립적인 방어층으로 구성한다.
| 계층 | 검사 | 실패 시 동작 |
|---|---|---|
| 입력 무결성 | 이름, 길이, NaN/Inf, 타임스탬프 | 프레임 폐기 |
| 캘리브레이션 | 장치 ID, 버전, 관절 순서 | 제어 시작 거부 |
| 위치 제한 | 관절별 soft limit | clamp 및 경고 |
| 속도 제한 | 프레임 간 최대 변화 | slew-rate 제한 |
| 통신 워치독 | 마지막 유효 명령의 나이 | hold 또는 torque off |
| 데드맨 스위치 | 조작자 지속 입력 | hold |
| 독립 하드웨어 | 전원 차단/E-stop | 모터 전력 차단 |
code/safe_teleop_core.py는 하드웨어와 분리된 순수 Python 예제다. JointSafetyFilter가 이름 기반 재정렬, 위치 clamp, 속도 제한, timeout을 적용한다. 측정 시작값과 HOLD 자세가 이미 soft limit 안에 있어야 한다. 범위 밖 측정을 clamp해 즉시 복구 명령으로 쓰지 않고 FAULT로 거부한다. dt와 수신 단조 시각의 유한성·양수 기간·시각 역전을 검사하며, 이 예제의 now는 수신 시각이라 원본 센서 stamp 검증을 대신하지 않는다. FAULT의 command는 빈 딕셔너리이며 송신하지 않는다. 이 필터의 오류 표시는 한 번의 입력 거부이고 latched 복귀·승격은 별도 감독기가 담당한다. --dry-run과 같은 단계 없이 실물 송신 함수를 연결하지 않는다.
3.5.2 주기와 지연
목표 제어 주기가 50 Hz라면 한 주기는 20 ms다. 전체 지연은 대략
이다. 평균뿐 아니라 최악 지연과 jitter를 기록해야 한다. 다음 원칙을 적용한다.
- 단조 시계(monotonic clock)로 timeout을 판단한다.
- 수신 메시지의 ROS time과 로컬 수신 시각을 모두 기록한다.
- 늦은 명령을 한꺼번에 재생하지 않고 가장 최신 유효 상태만 사용한다.
- 통신 실패 후 자동 재개하지 말고 재정렬/재승인을 요구한다.