본문으로 건너뛰기

4.3 TF2 트리 설계

4.3.1 트리는 하나의 부모를 갖는다

TF2는 시간에 따라 변하는 프레임 관계를 버퍼에 저장한다. 각 child frame은 한 시점에 하나의 parent를 가져야 한다. 같은 camera_link를 두 Node가 서로 다른 부모로 broadcast하면 트리가 흔들리거나 조회 결과가 불안정해진다.

  • 고정 마운트: StaticTransformBroadcaster
  • 관절에 따라 변함: robot_state_publisher 또는 동적 broadcaster
  • 월드 localization: localization/SLAM Node

code/ros2_jazzy/sensor_pipeline/sensor_pipeline/static_camera_tf.py는 tool0 -> camera_link -> camera_optical_frame의 고정 변환을 방송한다. 실제 값은 캘리브레이션 결과로 교체한다.

위 프레임 계약 표는 이 장의 고정 작업대 로봇팔 예시다. 모바일 경로에서는 M09.04와 M15.01의 map → odom → base_link를 구분한다. odom → base_link는 연속적인 지역 추정, map → odom은 전역 보정 역할이며 전역 보정 시 map 기준 위치가 변할 수 있다. 이 구조를 쓸 때 기존 world → base_link broadcaster를 같은 TF 트리에 동시에 추가하지 않는다. 시뮬레이터의 정답 pose와 센서 기반 위치추정도 다른 출처로 기록한다. M18.05의 다중 로봇에서는 토픽 namespace가 TF frame 문자열을 자동으로 변경하지 않는다는 점을 확인한다. 같은 TF 토픽과 버퍼를 공유한다면 로봇별 odom·base 등의 frame ID 충돌을 방지한다. TF 토픽과 버퍼를 로봇별로 격리하는 설계에서는 각 로컬 frame 이름을 유지할 수 있지만, 외부 결과를 합치는 곳에서 로봇 식별과 좌표 변환을 명시한다. 공통 map을 공유한다면 원점·축·지도 버전의 합의를 별도로 확인한다.

4.3.2 timestamp가 있는 조회

“최신 transform”으로 모든 과거 이미지를 변환하면 움직이는 로봇에서 공간 오차가 생긴다. 이미지 header timestamp에 해당하는 transform을 조회한다.

from rclpy.duration import Duration
from rclpy.time import Time

transform = tf_buffer.lookup_transform(
    "base_link",
    image.header.frame_id,
    Time.from_msg(image.header.stamp),
    timeout=Duration(seconds=0.05),
)

Jazzy의 Python API는 메시지의 builtin_interfaces Time 자체 대신 rclpy.time.Time을 받으므로 위처럼 변환한다. 이 변환은 시계 오프셋을 보정하지 않는다. 이미지와 TF가 같은 ROS 시간원·epoch를 사용한다는 전제가 필요하다. 동기 조회 중에도 TF 수신 콜백이 진행될 수 있게 Executor/콜백 구성을 확인하거나 비동기 조회를 사용한다. 단일 실행 스레드를 대기로 막아 놓고 그 스레드에 들어올 TF만 기다리지 않는다. 이 코드는 이미 생성된 buffer와 이미지가 있다는 전제의 API 발췌이며 실제 ROS 실행 결과를 제시하는 것은 아니다.

필요한 transform이 아직 버퍼에 없으면 기다리거나 해당 표본을 누락 처리한다. 미래 extrapolation 오류를 피하려고 timestamp를 0으로 바꾸면 데이터는 흐르지만 의미가 틀릴 수 있다.

4.3.3 TF 진단

ros2 run tf2_tools view_frames
ros2 run tf2_ros tf2_echo base_link camera_optical_frame

예상 출력 예시

At time 1710000000.033
Translation: [0.083, -0.012, 0.115]
Rotation (xyzw): [0.500, -0.500, 0.500, -0.500]

숫자만 보지 말고 RViz의 axes와 알려진 물체의 projection으로 방향을 검증한다.

이 장의 예제 코드·설정 파일 (12)

이 장의 자가 점검·가상실습