카테고리 없음

TF 생성 방법 및 더 깊은 개념

dawon-project 2025. 5. 16. 16:03

우리의 바로 앞에는 놓인 커피가 있다고하자 이때 이 커피의 위치는 사람 입장에서는 앞에 있어! 라고 간단하게 표현할 수 있겠지만 로봇 공학에서는 매우 정밀해야하고 수치로 정확한 위치를 알려줘야한다.

이때 정확한 값을 사용하여 커피의 위치를 제공하려면 테이블의 위치 좌표를 결정할 수 있는 고정된 기준점이 필요하고 이때의 기준점은 기준 좌표 프레임을 의미하고 이 기준 좌표 프레임이 지정되지 않는다면 위치 좌표는 의미가 없다.

왜냐하면 커피는 (3,0) 의 위치에 있어라고 했을때 이때의 (3,0) 좌표는 어디를 기준으로 인지 알 수 없어 어디에 위치했다는 거지? 라는 의문을 가지게 되나 나를 기준으로 (3,0)이라고 정의해 준다면 이때의 커피의 위치는 어디에 있는지 알 수 있다.

이처럼 ROS2에서는 기준 좌표 프레임을 정의해줘야하며 이 기준 좌표 프레임은 물체의 위치를 표현하기에 편리하도록 해주는 도구로 볼 수 있다.

(마치 커피는 그리니치 천문대를 기준으로 (39만km, 38만km) 위치에 있어라고 표현하지 않는 것처럼 말이다. )

 

TF 관련 기본 개념

좌표계/좌표 프레임(Coordinate frame) : 원점이라고 부르는 지점에서 교차하는 직교 축의 집합으로 원점을 기준으로 점의 위치를 설명하는 역할

Frame : 좌표계 ( ex. map, odom, base_link, camera_link)

Transform : 한 프레임에서 다른 프레임으로의 변환 관계(회전 + 이동)

TF Frame : 변환 프레임

TF Tree : 여러 프레임이 계층적으로 연결된 구조

 

TF BroadCaster : 프레임 간의 변환을 주기적으로 브로드 캐스트

TF listener : 다른 노드에서 TF 정보를 구독하여 변환을 확인

TF Transform : 특정 프레임 간 좌표 변환 수행

 

브로드 캐스트(Broadcast) : tf2 라이브러리를 이용하여 프레임(Frame) 간의 변환(Transform) 정보를 네트워크 상에 퍼트리는 행위

  • 브로드캐스트 시 해당 프레임이 존재하는지의 여부는 중요하지 않다
  • 브로드캐스트를 통한 TF 생성 3가지
    • 정의한 TF 프레임 두개가 기존에 둘다 존재하는 경우 퍼블리싱 중인 TF와 간섭을 일으킬 수 있는 새 TF를 게시하게 된다
      -> 이는 TF 간의 충돌을 발생시킬 수 있어서 TF는 고유 이름이어야한다
      (-> 필자의 경우 실수로 TF를 중복으로 정의해서 과거 시간과 미래시간이 충돌하는 문제가 생겼었다.)
    • 정의한 TF 두개의 프레임 중 하나가 존재하고 다른 하나가 존재하지 않는 경우, 존재하지 않는 프레임이 생성된 후 게시되어 존재하는 프레임과의 TF를 생성한다.
    • 정의한 TF 간의 관계 중 두 프레임이 둘다 존재하지 않으면 두 프레임 모두 생성된다.

 

TF는 정적 TF와 동적 TF로 나눌 수 있다.

정적 TF (Static Transform) : 한 번 설정되면 변하지 않는 좌표 관계

  • 정적 변환은 시간이 지나도 변경되지 않는 TF에 사용된다.
  • 정적 변환은 /tf_static 이라는 이름으로 publishing 되고, 변경 사항이 있을 때만 publishing 되므로 시스템의 성능과 리소스 사용에 미치는 영향이 현저히 낮다.
  • 센서처럼 로봇 본체에 고정된 부품 사이의 변환을 나타낼때 사용
  • 아래의 그림처럼 rqt_tf_tree를 통해서 TF 간의 관계를 봤을때 Average rate가 10000.0으로 말도 안되는 발행 주기를 볼 수 있다. 이것의 이유는 정적 TF라 한번 발행하고 변경되지 않는 TF간의 관계이기 때문이다.
    ->axis frame과 leg2 frame은 정적 TF 관계라는 것을 알 수 있다.

TF를 위한 의존성 패키지 설치

# 의존성 패키지 설치
sudo apt install ros-humble-tf-transformations
sudo pip3 install transforms3d

정적 TF 방행 방법 3가지

1. CLI(Command Line Interface) 를 통한 Static Transform 정의

  • X, Y, Z + 오일러 각(Euler Angle)
ros2 run tf2_ros static_transform_publisher --x {x} --y {y} --z {z} --roll {ROLL} --pitch {PITCH} --yaw {YAW} --frame-id {FRAME_ID} --child-frame-id {CHILD_FRAME_ID}
  • X, Y, Z + 쿼터니언(Quaternions)
ros2 run tf2_ros static_transform_publisher --x {X} --y {Y} --z {Z} --qx {QX} --qy {QY} --qz {QZ} --qw {QW} --frame-id {FRAME_ID} --child-frame-id {CHILD_FRAME_ID}

2. launch 파일을 통한 Static Transform 정의

  • CLI에서의 명령어를 launch 파일에서 그대로 표현한 것이다
  • 이 방식을 사용하면 사용자가 일일히 터미널 창에 입력하지 않아도 된다.
  • 대부분 이 방식을 선호한다.

3. Programming Language(C++, Python)을 통한 Static Transform 정의

  • CLI에서의 명령어를 script 파일로 만든 형태이다.

 

 

동적 TF (Dynamic Transform) : 시간에 따라 변하는 좌표 관계

  • 시간 정보(Time stamp)를 포함한다.
  • 추적 가능한 시간 축 기반의 프레임 연결이 가능하다.
  • 이동 중인 로봇의 위치, 관절 변화, 움직이는 센서 등을 나타낼때 사용
  • 아래와 같은 방식으로 생성해준다

 

TF Debugging 방법 3가지

방법 1] tf2_tools 패키지의 view_frames

  • 해당 명령어를 실행하면 약 5초 정도 데이터를 수집하고 수집한 데이터를 바탕으로 TF 관계 파일을 출력해준다.
ros2 run tf2_tools view_frames

 

방법2] rqt_tf_tree

  • 해당 명령어를 실행하면 새로 고침 버튼을 누르면 실시간으로 TF 상태를 확인할 수 있다.
ros2 run rqt_tf_tree rqt_tf_tree

 

방법3] tf2_ros 패키지의 tf_echo

  • ros2 topic echo 를 이용하여 /tf 토픽을 확인할 수 있지만 여러가지 문제점들이 있다.
ros2 topic echo /tf

  • 위 결과에서와 같이 매 초마다 많은 데이터가 퍼블리싱되기 때문에 이 방법으로는 한 프레임에서 다음의 연결된 프레임으로의 TF 변환만 발행하기 때문에 필요한 데이터를 얻기가 어렵거나 불가능하다 ( 예를 들어, 3~4칸 건너뛴 프레임 간의 관계를 확인하기 힘들다.)
  • 그래서 직접 연결되지 않은 두개의 프레임에 관심이 있는 경우 사용하는 것이 tf2_echo 명령어이다.
  • tf2_echo 명령어는 아래와 같이 실행된다.
ros2 run tf2_ros tf2_echo [reference_frame] [target_frame] [echo_rate]
# [reference_frame]: 변환을 시작하는 위치 (예: rgb_camera_link_frame)
# [target_frame]: 변환을 완료할 위치 (예: turtle_chassis)
# [echo_rate]: TF 관계를 출력할 주기 (예: 10)
# 아래의 그림과 같이 TF 상태가 있을 때 tutle_chassis 와 rgb_camera_link_frame 간의 TF 상태를 보려면 아래와 같이 명령어를 사용하면 된다.
ros2 run tf2_ros tf2_echo rgb_camera_link_frame turtle_chassis 10

 

방법4 ] RVIZ2

  • TF가 더 이상 퍼블리싱되지 않으면 회색으로 바뀌고 사라진다.
    • Fixed Frame 올바르게 설정되지 않은 경우 센서 데이터나 TF가 필요한 모든 것을 렌더링하지 않으며, 예를 들어 루트 프레임이 여러 개 있는 경우에도 렌더링하지 않습니다. 이는 멀티 로봇 시스템에서 흔히 발생하는 문제입니다.