[ROS2 Mastery 9편] 싱글 프레임 및 움직이는 로봇 TF2 브로드캐스팅 실습 가이드
안녕하세요! 자율주행과 로봇 시스템 제어의 세계를 깊이 있게 탐구하고 계신 대학생 및 연구원 여러분. 쿼드(QUAD) 드론연구소의 자료를 바탕으로 진행되는 ‘ROS2 속성 마스터 과정’ 연재 블로그 9편에 오신 것을 진심으로 환영합니다.
지난 8편에서는 로봇 수학의 핵심이자 복잡한 3차원 공간 계산을 우아하게 해결해 주는 TF2(Transform System)의 기본 개념과 트리(Tree) 구조에 대해 이론적으로 학습했습니다.
이제 이론을 바탕으로 직접 손을 움직여볼 차례입니다! 이번 9편에서는 파이썬 코드를 작성하기에 앞서, ROS2에서 기본적으로 제공하는 강력한 커맨드라인 도구와 유틸리티 노드들을 활용하여 ‘정적(Static) 프레임’을 시스템에 띄우고(Broadcast), URDF로 정의된 ‘움직이는 로봇(Dynamic)’의 변환 트리를 시각화하는 전체 과정을 실습해 보겠습니다.
특히 연구 과정에서 수많은 프레임이 꼬였을 때 원인을 분석할 수 있는 핵심 디버깅 도구의 사용법도 상세히 다룰 예정이니, 끝까지 집중해서 따라와 주시기 바랍니다!

정적 변환의 마법사: static_transform_publisher 실습
로봇 시스템을 구축하다 보면, 방 안의 기준점(world)이나 로봇 몸체(base_link)에 고정되어 절대 움직이지 않는 센서(예: LiDAR, 고정 카메라)의 위치를 정의해야 할 때가 많습니다. 이렇게 시간이 지나도 변하지 않는 프레임 간의 관계를 ‘정적 변환(Static Transform)’이라고 합니다.
ROS2는 이러한 정적 변환을 터미널 명령어 한 줄로 즉시 네트워크에 퍼블리시할 수 있는 static_transform_publisher라는 도구를 제공합니다. 이 도구는 실제 개발 환경에서 서로 다른 노드 간의 좌표계를 일치시키기 위한 “접착제” 역할을 하는 매우 유용한 유틸리티입니다.
1. 싱글 프레임 브로드캐스팅 명령어 구조
터미널에서 사용하는 기본 명령어 구조는 다음과 같습니다. 위치 이동(Translation)과 회전(Rotation) 값을 순서대로 입력합니다.
- 구조:
ros2 run tf2_ros static_transform_publisher [x] [y] [z] [yaw] [pitch] [roll] [parent_frame] [child_frame] - 주의사항: 회전 각도(yaw, pitch, roll)는 도(Degree) 단위가 아니라 라디안(Radian) 단위이며, 로컬 좌표계를 기준으로 변환된 순서대로 처리됩니다.
2. 두 대의 로봇 프레임 생성해 보기
실제 명령어를 입력하여 변환 트리를 구성해 봅시다. 첫 번째 터미널을 열고, 최상위 부모인 world 프레임에서 시작하여 robot_1 프레임을 만들어 보겠습니다. robot_1은 원점(0, 0, 0)에 위치하지만, Z축을 기준으로 45도(약 0.785 라디안) 회전한 상태로 설정합니다.
# 첫 번째 터미널: world -> robot_1 (45도 회전)
ros2 run tf2_ros static_transform_publisher 0 0 0 0.785 0 0 world robot_1
이제 사이드카처럼 항상 첫 번째 로봇의 오른쪽(x축 방향)에 1m 떨어져서 따라다니는 두 번째 로봇(robot_2)을 가정해 봅시다. 새 터미널을 열고 아래 명령어를 입력합니다.
# 두 번째 터미널: robot_1 -> robot_2 (x축으로 1m 이동)
ros2 run tf2_ros static_transform_publisher 1 0 0 0 0 0 robot_1 robot_2
이 명령어들이 실행되면, 백그라운드에서 /tf_static 토픽을 통해 우리가 정의한 좌표 변환 정보가 시스템 전체로 브로드캐스트되기 시작합니다.
RViz2를 이용한 3D 변환 트리 시각화
눈에 보이지 않는 좌표계의 구조를 머릿속으로만 상상하는 것은 한계가 있습니다. 방금 우리가 띄운 프레임들이 공간상에 어떻게 배치되어 있는지 ROS2의 강력한 3D 시각화 도구인 RViz2를 통해 확인해 보겠습니다.
세 번째 터미널을 열고 실행합니다.
rviz2

1. RViz2 설정 가이드
- 플러그인 추가: 처음 RViz가 실행되면 빈 화면이 나타납니다. 좌측 하단의 [Add] 버튼을 클릭하고 목록에서 [TF]를 선택하여 추가합니다.
- 고정 프레임 설정: 아직 화면에 아무것도 나타나지 않거나 에러가 뜰 것입니다. RViz에게 “어떤 프레임을 기준(땅)으로 화면을 렌더링할 것인가?”를 알려주어야 합니다. 좌측 패널 상단의 “Global Options”에서 “Fixed Frame” 값을
map에서 방금 우리가 만든 최상위 프레임인world로 변경합니다. - 시각화 확인: “Global Status”가 정상(Ok)으로 바뀌면서, 화면 중앙에 3개의 좌표계 축(world, robot_1, robot_2)과 이들을 연결하는 노란색 선이 나타납니다.
[연구원 관찰 포인트] RViz 화면을 자세히 살펴보면, 각 프레임을 연결하는 노란색 화살표가 부모(world)에서 자식(robot_1)으로 향하는 것이 아니라, 자식 프레임에서 부모 프레임 방향으로 향하고 있다는 것을 알 수 있습니다. 이는 변환 행렬(Transform Matrix)이 자식의 로컬 좌표를 부모의 기준 좌표로 계산해 올리는 수학적 구조를 시각적으로 반영한 것입니다.
첫 번째 터미널로 돌아가서 실행 중인 프로세스를 종료(Ctrl+C)하고, 회전 각도를 90도(1.57 라디안)로 변경하여 다시 실행해 보세요.
ros2 run tf2_ros static_transform_publisher 0 0 0 1.57 0 0 world robot_1
robot_1이 90도로 회전함에 따라, 그에 종속된 자식 프레임인 robot_2의 위치도 robot_1의 X축 방향을 따라 함께 궤도를 그리며 이동하는 것을 실시간으로 확인할 수 있습니다. 이것이 바로 TF2 트리 구조의 강력함입니다!
움직이는 로봇 브로드캐스팅: URDF와 TF2의 결합
단순한 정적 프레임을 넘어서, 실제 관절(Joint)이 움직이는 로봇 팔이나 주행하는 모바일 로봇의 변환은 어떻게 처리할까요? 로봇은 가만히 있지 않고 계속해서 움직이기 때문에 동적 변환(Dynamic Transform)이 필수적입니다.
1. 로봇 모델링 파일 (URDF)의 역할
ROS2에서는 로봇의 크기, 모양, 관절의 구조 등 물리적 특성을 XML 형태의 URDF (Universal Robot Description Format) 파일로 정의합니다. URDF 파일 내부를 살펴보면 단단한 부품인 ‘링크(Link)’들이 ‘관절(Joint)’이라는 부모-자식 트리 구조로 묶여 있습니다. 연구원 여러분은 이미 눈치채셨을 것입니다. URDF의 Link/Joint 구조는 TF2의 Frame/Transform 구조와 완벽하게 1:1로 매칭됩니다!
2. robot_state_publisher의 마법
이러한 유사성 덕분에, 우리가 일일이 관절의 삼각함수를 계산하여 변환을 코딩할 필요가 없습니다. ROS2에는 URDF 파일을 읽어 들여 전체 로봇의 TF 변환을 자동으로 계산하고 브로드캐스트해 주는 robot_state_publisher라는 훌륭한 시스템 노드가 존재합니다.
이 노드는 두 가지 중요한 작업을 수행합니다.
- URDF 배포:
/robot_description토픽을 통해 로봇의 전체 URDF 텍스트 정보를 시스템에 퍼블리시하여 다른 노드나 RViz가 로봇의 형태를 알 수 있게 합니다. - TF 계산 및 퍼블리시: 고정된 관절은 정적 변환(
/tf_static)으로 퍼블리시합니다. 움직이는 관절(회전, 슬라이딩 등)의 경우,/joint_states토픽을 구독(Subscribe)하여 현재 관절의 실시간 각도나 거리 데이터를 수신한 뒤, 동적 변환(/tf)을 계산하여 퍼블리시합니다.
3. 가상 센서를 이용한 움직임 시각화 실습
실제 로봇의 하드웨어가 없다면 모터의 엔코더(센서) 값이 없으므로 /joint_states 데이터가 생성되지 않습니다. 이를 시뮬레이션하기 위해 joint_state_publisher_gui라는 도구를 사용하여 가짜(Fake) 관절 데이터를 생성해 보겠습니다.
(주의: 실습을 위해 이전 단계에서 실행한 RViz 등 모든 터미널을 닫아주세요.)
- 로봇 상태 퍼블리셔 실행: (예제 URDF 파일이 있다고 가정합니다.)
- 가상 조인트 퍼블리셔 GUI 실행: 새 터미널을 엽니다.
- 이 명령어를 실행하면 화면에 로봇의 움직이는 관절들을 조절할 수 있는 슬라이더(Slider) 창이 팝업됩니다.

- RViz2에서 확인: 다시
rviz2를 실행하고, 이번에는 TF 플러그인뿐만 아니라 [RobotModel] 플러그인도 함께 추가합니다. Description Source를 Topic으로 설정하고/robot_description을 선택하면, 눈앞에 멋진 3D 로봇이 나타납니다. 이제 GUI 창의 슬라이더를 마우스로 드래그해 보세요. 슬라이더의 값이/joint_states토픽을 타고robot_state_publisher로 전달되며, 즉각적으로 계산된 TF 변환이 RViz에 반영되어 로봇 팔이 자연스럽게 움직이는 마법을 경험하실 수 있습니다!
연구원을 위한 필수 디버깅 도구: tf2_tools 활용법
대학원 연구실이나 현장에서 복잡한 로봇 시스템을 다루다 보면, 반드시 “프레임이 꼬였다”, “변환 정보가 누락되었다”는 에러 메시지와 마주하게 됩니다. 실시간으로 빠르게 쏟아지는 /tf 토픽을 터미널에서 echo 명령어로 눈으로 쫓아가는 것은 불가능에 가깝습니다.
이때 문제의 원인을 가장 빠르고 정확하게 분석할 수 있는 도구가 바로 tf2_tools 패키지의 view_frames 스크립트입니다.
1. frames.pdf 구조도 생성하기
현재 로봇의 TF 프레임이 브로드캐스트되고 있는 상태(앞선 실습을 켜둔 상태)에서, 새로운 터미널을 열고 아래 명령어를 입력합니다.
ros2 run tf2_tools view_frames
명령어를 실행하면, 스크립트가 약 5초 동안 현재 ROS2 네트워크를 돌아다니는 모든 변환 데이터를 수신(Listen)하고 분석합니다. 작업이 완료되면 현재 명령어를 실행한 디렉토리에 frames.pdf라는 시각화 파일이 자동 생성됩니다.

2. 디버깅 데이터 분석하기
생성된 PDF 파일을 열어보면 현재 시스템의 전체 TF 트리 구조를 한눈에 파악할 수 있는 다이어그램이 들어있습니다. 다이어그램 내부의 정보는 디버깅에 결정적인 역할을 합니다.
- 연결 무결성: 프레임이 끊어져서 트리가 2개 이상으로 분리되어 있지 않은지(루트 프레임이 1개인지) 한눈에 확인 가능합니다.
- Broadcaster: 해당 프레임을 쏘고 있는 노드의 이름(예:
robot_state_publisher또는static_transform_publisher)이 명시되어 있어, 어떤 노드에서 문제가 발생했는지 추적할 수 있습니다. - Average Rate (Hz): 동적 프레임의 경우 데이터가 초당 몇 번 퍼블리시되는지 확인할 수 있습니다. 주기가 너무 느리면 제어 알고리즘에 심각한 지연이 발생할 수 있습니다.
- 시간 정보 (Unix Epoch Time): 노드에 표시되는 “16314…”로 시작하는 긴 숫자는 유닉스 시간(Epoch Time)을 나타냅니다. 가제보(Gazebo) 시뮬레이터를 사용할 때는 현실 시간이 아닌 시뮬레이터가 켜진 이후의 초 단위 시간이 표시되므로 시간 동기화(Time Sync) 문제를 분석할 때 유용합니다.
마무리하며
이번 [ROS2 Mastery 9편]에서는 TF2 시스템의 핵심인 ‘프레임 브로드캐스팅(Broadcasting)’의 개념을 이론을 넘어 실제 눈으로 확인해 보았습니다.
명령어 한 줄로 생성되는 정적 변환(static_transform_publisher)의 원리부터, URDF 로봇 모델링 파일과 결합하여 동적인 관절의 움직임을 계산해 내는 robot_state_publisher의 훌륭한 아키텍처, 그리고 연구자들의 퇴근 시간을 앞당겨줄 디버깅 도구 view_frames의 활용법까지 깊이 있게 다루었습니다.
지금까지는 ROS2가 기본 제공하는 도구들을 사용했습니다. 하지만 실제 자율주행 알고리즘을 개발하려면 우리가 직접 작성하는 파이썬 코드 안에서 이러한 변환 데이터를 생성하고 퍼블리시할 수 있어야 합니다.
다음 [ROS2 Mastery 10편]에서는 오늘 배운 개념을 바탕으로, Python 노드 내부에서 직접 “정적 브로드캐스터(Static Broadcaster)를 프로그래밍”하는 방법에 대해 상세히 알아보겠습니다.

작성자: 에이든(Aiden), 쿼드(QUAD) 드론연구소 마케팅팀
기고일: 2026.05.31
