/joint_states에서 값이 빠졌다고 0으로 채우면, 측정하지 않은 속도를 정지 상태로 바꿔 기록할 수 있습니다. 반대로 숫자 0이 보인다고 모두 센서 측정값인 것도 아닙니다. joint_state_broadcaster가 어떤 인터페이스를 받았고, 어느 필드에 옮겼으며, 추가 관절을 설정했는지 확인해야 값의 뜻을 알 수 있습니다.
이 글은 ROS 2 Kilted의 문서와 구현을 기준으로 메시지를 읽는 방법을 설명합니다. 일반적인 드라이버 연결 구조는 ros2_control 하드웨어 인터페이스 안내에서 이어서 볼 수 있습니다.
온도가 joint_states에 없다고 센서가 고장 난 것은 아니다
Kilted의 joint_state_broadcaster 문서는 두 토픽의 역할을 나눕니다. /joint_states는 position, velocity, effort처럼 관절 운동에 쓰이는 필드를 담습니다. /dynamic_joint_states는 관절마다 인터페이스 이름과 값을 묶으므로 온도나 전압 같은 추가 상태도 표현할 수 있습니다.
가령 손목 드라이버가 위치와 온도를 내보내고 속도는 내보내지 않는다고 가정해 보겠습니다. 위치는 일반 관절 상태에 들어갈 수 있지만, 온도를 찾으려면 동적 관절 상태의 인터페이스 이름을 봐야 합니다. 일반 토픽에 온도 칸이 없다는 사실만으로 통신 실패나 온도 0도를 결론 내릴 수 없습니다.
비교할 때는 두 메시지의 배열 순서가 같다고 가정하지 말고 관절 이름을 먼저 맞춥니다. 그다음 해당 관절에 어떤 인터페이스 이름이 붙었는지 확인합니다. 보기 좋은 숫자 표를 만들기 전에 이름과 값의 대응부터 보존해야 합니다.
빈 배열, NaN, 숫자 0은 같은 상태가 아니다
문서에는 제공하지 않는 운동 인터페이스가 생략되거나 비어 있을 수 있다고 설명되어 있습니다. 다만 실제 표현을 단정하려면 사용 중인 버전의 구현을 더 봐야 합니다. 이번에 확인한 Kilted 소스 코드는 관절 메시지 배열을 NaN으로 초기화하고, 관절에 없는 운동 인터페이스를 참조할 때도 NaN을 반환합니다.
따라서 이 구현에서 위치만 제공하는 관절을 읽으면서 속도 칸이 반드시 빈 배열일 것이라고 기대하면 안 됩니다. 관절 이름은 있는데 특정 값이 NaN인 형태도 구분해야 합니다. NaN은 유효한 숫자 값이 아니라는 표시이지, 그 원인이 센서 고장이라고 확정하는 진단 코드는 아닙니다.
| 받은 내용 | 먼저 구분할 것 | 피해야 할 해석 |
|---|---|---|
| 관절 이름 자체가 없음 | 선택 목록, URDF 필터, 실제 노출 인터페이스 | 해당 관절이 정지했다 |
| 관절은 있고 속도 값이 NaN | 속도 인터페이스 유무, 초기값과 값 갱신 경로 | 속도가 0이다 |
| 온도는 동적 토픽에만 있음 | 일반 메시지와 동적 메시지의 필드 차이 | 일반 토픽에서 센서가 누락됐다 |
| 위치·속도·effort가 모두 0 | 측정값인지 설정으로 추가한 관절인지 | 세 값을 모두 실측했다 |
데이터를 저장하거나 그래프로 옮길 때도 이 차이를 남기는 편이 좋습니다. 결측을 표시할 칸과 유효한 값을 따로 관리하면, 나중에 평균 속도를 계산할 때 미측정 구간을 정지 구간에 섞지 않을 수 있습니다. 이는 데이터 처리 제안이며, 모든 기록기가 자동으로 해 주는 기능은 아닙니다.
extra_joints의 0은 측정 증거가 아니다
공식 문서의 extra_joints는 지정한 추가 관절을 상태 값 0으로 넣는 설정입니다. 확인한 소스도 기존 상태 목록에 없는 추가 관절에 위치·속도·effort의 0을 생성합니다. 화면에 관절을 표시하기 위해 이런 설정을 썼다면, 그 숫자는 실제 하드웨어에서 읽은 결과와 구분해야 합니다.
또한 사용자 정의 인터페이스를 일반 필드로 옮기는 매핑을 사용할 수 있습니다. 이때 effort라는 출력 필드 이름만 보고 값의 출처나 물리 단위를 추정하지 마세요. 어떤 원본 인터페이스를 연결했는지와 드라이버의 단위 정의를 함께 확인해야 합니다. 이름을 옮기는 설정이 측정이나 단위 변환을 새로 수행했다는 뜻은 아닙니다.
토픽이 오는데 값이 이상하다면 이 순서로 좁힌다
먼저 지금 읽는 토픽의 실제 발행자를 확인합니다. use_local_topics를 사용하면 이름이 브로드캐스터의 네임스페이스 아래에 놓일 수 있습니다. 루트의 /joint_states만 살피다가 다른 인스턴스를 읽고 있지 않은지 구분합니다.
다음에는 문제 관절 하나를 골라 드라이버가 내보낸 상태 인터페이스, joints·interfaces 선택, URDF 필터, 사용자 정의 매핑, extra_joints를 이어서 대조합니다. 값이 없어진 위치와 값이 만들어진 위치를 찾는 과정입니다. 모든 관절의 설정을 한꺼번에 바꾸면 어느 변경이 영향을 줬는지 알기 어렵습니다.
마지막으로 메시지가 전혀 오지 않는 경우를 분리합니다. 발행 경로가 준비되지 않았거나 브로드캐스터가 활성화되지 않은 상황과, 메시지는 정상적으로 도착하지만 특정 필드가 없는 상황은 다릅니다. 전달 자체가 문제라면 ROS 2 QoS 호환성과 센서·명령 설정을 확인할 차례입니다.
진단 기록에는 관절 이름, 원본 인터페이스, 수신 필드, 실제 값, 적용 설정과 소프트웨어 버전을 함께 남기세요. 그래야 다음 사람이 0을 보고 정지라고 판단하기 전에 그 값이 어디서 왔는지 확인할 수 있습니다.
문서와 소스 확인일은 2026년 10월 15일입니다. 소스 설명은 위 링크의 고정된 Kilted 커밋에 한정하며, 실제 ROS 노드나 하드웨어를 실행한 시험 결과는 아닙니다.