대상: ROS 또는 자율주행/로봇 개발 중 좌표계(TF) 관계를 직관적으로 이해하고 싶은 개발자
환경: Ubuntu 20.04 / ROS Noetic / TF2 / RViz
1. 문제/주제 요약
ROS에서 “로봇이 어디에 있는가?”를 표현할 때는 좌표계(Frame) 를 사용합니다.
각 센서와 로봇 본체, 지도는 서로 다른 기준점을 가지며,
이를 연결하는 역할을 하는 것이 tf2 시스템입니다.
특히 자율주행에서 자주 등장하는 세 가지 프레임 —
👉 map, odom, base_link —
이들의 관계를 헷갈려 하는 개발자가 많습니다.
이 글에서는 이 세 프레임의 의미와 관계를 그림 없이도 머릿속에 그려질 만큼 직관적으로 설명합니다.
2. tf / tf2란 무엇인가?
tf는 ROS에서 좌표 변환(Transform) 을 관리하는 프레임워크입니다.
로봇의 각 부분(차체, 센서, 휠 등)을 “좌표계(frame)”로 보고,
이들 간의 위치/자세 관계(translation + rotation) 를 실시간으로 추적합니다.
간단히 말하면:
“카메라는 로봇 본체에서 10cm 앞에 있다.”
“로봇 본체는 지도에서 (x, y, θ)에 있다.”
이런 관계를 ROS가 자동으로 계산해주는 시스템입니다.
3. 대표적인 프레임 구조
일반적인 자율주행 로봇의 TF 트리 구조는 다음과 같습니다:
map ───► odom ───► base_link ───► laser
└──► camera
각 프레임의 역할은 다음과 같습니다 👇
| 프레임 | 기준점 | 역할 |
|---|---|---|
| map | 절대 좌표계 (고정) | 전역 위치 — 로봇이 지도 어디에 있는가 |
| odom | 상대 좌표계 (로봇의 출발점) | 주행 중 누적 오차 포함한 로봇 위치 |
| base_link | 로봇 본체 중심 | 센서/휠/카메라 등의 기준점 |
| laser, camera_link | 센서 장착 위치 | base_link에서의 상대 위치 |
4. 각 프레임의 의미 직관적으로 이해하기
🗺️ 1) map (지도 좌표계)
- 절대 기준
- SLAM, Localization 노드가 관리
- 로봇의 위치를 실제 지도 상의 좌표로 표현
- 지도는 항상 고정된 프레임 (움직이지 않음)
예시:
“지도에서 로봇은 x=3.2m, y=-1.0m 위치에 있다.”
→ map -> base_link 변환으로 표현됩니다.
🧭 2) odom (로봇의 상대 좌표계)
- 로봇이 출발한 지점 기준의 상대 위치
- 주로 Odometry(엔코더, IMU 등)가 관리
- 로봇이 이동하면 오차가 누적됨
예시:
“출발점에서 2m 앞으로, 0.1m 오른쪽으로 이동했다.”
즉, 오도메트리만으로는 시간이 지날수록 오차가 쌓이기 때문에
Localization이 map 프레임을 이용해 이를 보정합니다.
🤖 3) base_link (로봇 본체 중심)
- 로봇의 중심 좌표
- 모든 센서와 휠, 카메라의 기준점
- 실제 로봇이 움직이면
odom -> base_link변환이 실시간으로 바뀜
예시:
“LiDAR는 base_link 기준 x=0.1m, z=0.2m 위에 장착되어 있다.”
이 관계는 static_transform_publisher 나 URDF에서 설정됩니다.
5. 프레임 간 관계 요약
| 관계 | 누가 관리하나 | 의미 |
|---|---|---|
| map → odom | Localization (AMCL, SLAM 등) | 오도메트리 누적 오차 보정 |
| odom → base_link | Odometry (wheel encoder, IMU) | 로봇 이동량 추정 |
| base_link → 센서 | URDF / static transform | 로봇 내부 구조 정의 |
6. 예시: 자율주행 중 위치 추정 과정
1️⃣ 로봇이 출발할 때
odom프레임은 (0,0,0)에서 시작map프레임도 (0,0,0)이지만 아직 정렬되지 않음
2️⃣ 로봇이 1m 이동하면
- 오도메트리는 “1m 전진” →
odom -> base_link변경 - 하지만 SLAM/AMCL은 센서 데이터를 보고 실제는 0.95m 이동했다고 판단
3️⃣ Localization이 보정 수행
map -> odom변환을 미세하게 이동시켜
오도메트리 누적 오차를 보정함
즉,
odom은 계속 “로봇이 인식한 이동량”map은 “센서 기반으로 보정된 실제 위치”map -> odom변환이 “오차 보정값” 역할을 합니다.
7. 실제 ROS 예시
tf2_ros 명령으로 트리 보기:
rosrun tf2_tools view_frames.py
결과 예시:
map
└── odom
└── base_link
├── laser
└── camera_link
변환 조회:
rosrun tf tf_echo map base_link
출력:
At time 12.345
- Translation: [3.2, -1.0, 0.0]
- Rotation: in Quaternion (0.0, 0.0, 0.707, 0.707)
→ 지도(map) 기준으로 로봇(base_link)이 (3.2, -1.0) 위치에 있고
방향은 약 90도 회전되어 있다는 의미입니다.
8. TF 관계를 ROS에서 유지하는 주요 노드
| 역할 | 노드 | 출력 TF |
|---|---|---|
| Odometry 계산 | robot_state_publisher / diff_drive_controller | odom -> base_link |
| Localization (보정) | amcl, slam_toolbox, cartographer | map -> odom |
| 센서 장착 관계 | static_transform_publisher / URDF | base_link -> sensor_frame |
| 시각화 | rviz | 트리 구조 확인 (TF Display) |
9. 실무 비유로 이해하기
| 개념 | 현실 비유 |
|---|---|
map | GPS 좌표 (세상 기준, 절대 위치) |
odom | 차량 내부 네비게이션의 주행 기록 (상대 이동) |
base_link | 차량의 중심 좌표 |
map -> odom | GPS로 네비게이션 오차를 보정하는 과정 |
odom -> base_link | 차량이 실제 움직인 양 (엔코더 기반) |
즉,
odom은 “로봇이 생각하는 위치”,map은 “세상이 알고 있는 위치”입니다.
둘의 차이를 줄여주는 것이 Localization입니다.
10. 정리
| 프레임 | 기준 | 갱신 주체 | 특징 |
|---|---|---|---|
| map | 절대 좌표 | Localization | 고정된 전역 좌표 |
| odom | 상대 좌표 | Odometry | 오차 누적 가능 |
| base_link | 로봇 중심 | TF broadcaster | 센서/모터 기준점 |
| map → odom | Localization | 오차 보정 | |
| odom → base_link | Odometry | 실제 이동량 반영 |
👉 요약
odom은 로봇이 추정한 이동량,map은 센서로 보정된 실제 위치,base_link는 로봇의 기준 프레임.
결국 ROS의 TF는 “로봇의 몸과 세상의 관계를 수학적으로 표현하는 언어”입니다.