659.96 robot_state_publisher를 이용한 TF 자동 발행

1. 개요

robot_state_publisher는 URDF로 정의된 로봇 모델을 기반으로 TF2 변환을 자동으로 발행하는 ROS2 노드이다. 이 노드는 URDF의 고정 관절(fixed joint)에 대한 정적 변환을 /tf_static으로 발행하고, 가동 관절(revolute, continuous, prismatic)에 대한 동적 변환을 /tf로 발행한다. robot_state_publisher/joint_states 토픽을 구독하여 관절 상태 데이터를 수신하며, 이를 URDF의 운동학 모델과 결합하여 각 링크의 포즈를 계산한다.

2. 동작 원리

2.1 입력과 출력

입력출력
robot_description 매개변수 (URDF/Xacro 문자열)/tf 토픽 (동적 변환)
/joint_states 토픽 (sensor_msgs/msg/JointState)/tf_static 토픽 (정적 변환)
/robot_description 토픽 (URDF 문자열 재발행)

2.2 처리 흐름

  1. 초기화: robot_description 매개변수에서 URDF를 파싱하여 운동학 트리를 구성한다.
  2. 정적 변환 발행: 모든 fixed 관절의 변환을 /tf_static으로 발행한다. 이 변환은 한 번만 발행되며 TF2 버퍼에 영구적으로 유지된다.
  3. 관절 상태 수신: /joint_states 토픽을 구독하여 각 가동 관절의 현재 위치를 수신한다.
  4. 순운동학 계산: 수신된 관절 위치를 URDF의 운동학 모델에 적용하여 각 링크의 포즈를 계산한다.
  5. 동적 변환 발행: 계산된 포즈를 /tf 토픽으로 발행한다.

3. 런치 파일에서의 사용

3.1 기본 사용법

from launch import LaunchDescription
from launch_ros.actions import Node
import xacro
import os


def generate_launch_description():
    # URDF 파일 로드
    urdf_file = os.path.join(
        get_package_share_directory('my_robot'),
        'urdf', 'my_robot.urdf.xacro')

    robot_description = xacro.process_file(urdf_file).toxml()

    return LaunchDescription([
        Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            name='robot_state_publisher',
            parameters=[{
                'robot_description': robot_description,
                'publish_frequency': 50.0,
                'use_tf_static': True,
                'ignore_timestamp': False,
            }],
            output='screen',
        ),
    ])

3.2 주요 매개변수

매개변수유형기본값설명
robot_descriptionstring(필수)URDF 문자열
publish_frequencydouble20.0동적 TF 발행 주파수 (Hz)
use_tf_staticbooltrue고정 관절을 /tf_static으로 발행할지 여부
ignore_timestampboolfalseJointState 메시지의 타임스탬프 무시 여부

4. JointState 메시지

4.1 메시지 구조

std_msgs/Header header
  builtin_interfaces/Time stamp
  string frame_id

string[] name           # 관절 이름 배열
float64[] position      # 관절 위치 배열 (rad 또는 m)
float64[] velocity      # 관절 속도 배열 (rad/s 또는 m/s)
float64[] effort        # 관절 힘/토크 배열 (N·m 또는 N)

robot_state_publishernameposition 필드만을 사용하여 TF 변환을 계산한다.

4.2 관절 이름의 일치

JointState 메시지의 name 필드에 포함된 관절 이름은 URDF에서 정의한 관절 이름과 정확히 일치하여야 한다. 불일치 시 해당 관절의 변환이 갱신되지 않는다.

5. 정적 변환과 동적 변환의 분리

5.1 정적 변환 (use_tf_static: true)

고정 관절의 변환을 /tf_static 토픽으로 발행하면 다음과 같은 이점이 있다.

  1. 네트워크 부하 감소: 정적 변환은 한 번만 발행되므로 주기적 발행에 의한 네트워크 부하가 없다.
  2. 항상 가용: /tf_static은 래치(latch) 특성의 QoS를 사용하므로, 나중에 구독하는 노드도 변환을 수신할 수 있다.

5.2 동적 변환

가동 관절의 변환은 /joint_states 갱신 시마다 /tf로 발행된다. 발행 주파수는 publish_frequency 매개변수와 /joint_states 수신 빈도 중 작은 값에 의하여 결정된다.

6. 고정 관절만 있는 경우

센서 프레임만을 정의하는 로봇(예: 고정형 센서 스테이션)이나, 모든 관절이 고정인 경우에도 robot_state_publisher를 사용할 수 있다. 이 경우 /joint_states 토픽이 필요하지 않으며, 정적 변환만 발행된다.

# 고정 관절만 있는 경우 (joint_state_publisher 불필요)
Node(
    package='robot_state_publisher',
    executable='robot_state_publisher',
    parameters=[{'robot_description': robot_description}],
)

7. 검증

7.1 TF2 트리 확인

# 발행되는 프레임 확인
ros2 run tf2_tools view_frames

# 특정 프레임 간 변환 확인
ros2 run tf2_ros tf2_echo base_link laser_link

7.2 URDF 재발행 확인

# robot_description 토픽에서 URDF 확인
ros2 topic echo /robot_description --once

8. 요약

robot_state_publisher는 URDF 기반의 TF2 변환 자동 발행 노드로, 고정 관절의 정적 변환과 가동 관절의 동적 변환을 구분하여 발행한다. /joint_states 토픽에서 관절 상태를 수신하여 순운동학을 계산하고, 결과를 TF2 변환으로 발행함으로써 URDF와 TF2 사이의 자동 연동을 구현한다.


참고 문헌 및 출처

  • robot_state_publisher 패키지, https://github.com/ros/robot_state_publisher (ROS2 Humble 브랜치)
  • ROS2 공식 문서, “Using Robot State Publisher”, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/Using-robot-state-publisher.html (ROS2 Humble Hawksbill)
  • sensor_msgs/msg/JointState API 문서, https://docs.ros2.org/latest/api/sensor_msgs/msg/JointState.html