By ihsumlee , 9 June 2026
content

Position in the full course

This is the second step of the course.

The full learning order is:

1. ROS 2 node/topic/launch review
2. TF2 frame concept
3. Static sensor frames
4. Dynamic odometry frame
5. URDF + robot_state_publisher
6. SLAM mapping
7. AMCL localization
8. Nav2 path planning
9. RViz goal navigation
10. TF2 debugging in Nav2

In Step 1, you reviewed ROS 2 nodes, topics, messages, and launch files.

In Step 2, you will learn the most important concept before writing TF2 code:

Coordinate frames and TF tree

1. Learning objectives

After this module, you should be able to:

  1. Explain what a coordinate frame is.
  2. Explain why a robot needs many coordinate frames.
  3. Understand the meaning of parent frame and child frame.
  4. Understand the meaning of a TF tree.
  5. Explain the difference between fixed and moving frames.
  6. Use tf2_echo to check the transform between two frames.
  7. Use view_frames to generate a TF tree.
  8. Use RViz2 to visualize TF frames.
  9. Understand the basic Nav2 frame structure:
map β†’ odom β†’ base_link β†’ sensor frames

2. Suggested teaching duration

Suggested duration: 2 hours

| Time | Activity | | ----------- | ----------------------------------------- | | 0–15 min | Review ROS 2 publisher/subscriber concept | | 15–35 min | Explain coordinate frames | | 35–55 min | Explain TF tree using turtlesim | | 55–80 min | Run official TF2 turtlesim demo | | 80–100 min | Use tf2_echo, view_frames, and RViz2 | | 100–115 min | Connect TF2 to Nav2 | | 115–120 min | Summary and homework |


3. Why you need TF2

A robot has many parts:

robot body
wheels
LiDAR
camera
IMU
robot arm
gripper

Each part may have its own coordinate frame.

For example:

base_link      robot body frame
base_laser     LiDAR frame
camera_link    camera frame
imu_link       IMU frame

The robot must know where each part is located.

For example:

Where is the LiDAR relative to the robot body?
Where is the camera relative to the robot body?
Where is the robot body relative to the odometry frame?
Where is the robot relative to the map?

TF2 helps ROS 2 answer these questions.

A simple explanation is:

TF2 tells the robot the position and orientation relationship between coordinate frames.


4. What is a coordinate frame?

A coordinate frame is a local coordinate system.

It usually has:

x-axis
y-axis
z-axis
origin
orientation

For a mobile robot, a common body frame is base_link.

A simple convention is:

x-axis: forward direction
y-axis: left direction
z-axis: upward direction

For example:

          z
          ↑
          |
          |
          o------β†’ x
         /
        /
       y

For a mobile robot:

x forward
y left
z up

So when the robot moves forward, it usually moves in the positive x direction of base_link.


5. Why one robot needs many frames

Imagine your AMR has a LiDAR and a camera.

The robot body frame is:

base_link

The LiDAR frame is:

base_laser

The camera frame is:

camera_link

The LiDAR may be mounted 20 cm in front of the robot center.

The camera may be mounted 30 cm above the robot body.

Therefore, the robot needs to know:

base_link β†’ base_laser
base_link β†’ camera_link

This information is necessary because sensor data is measured in the sensor’s own frame.

For example:

LiDAR data is measured in base_laser frame.
Camera data is measured in camera_link frame.
Robot motion is usually controlled in base_link frame.
Navigation is usually planned in map or odom frame.

TF2 allows ROS 2 to transform data from one frame to another.


6. Parent frame and child frame

A TF relationship usually has two frames:

parent frame
child frame

Example:

base_link β†’ base_laser

This means:

base_link is the parent frame.
base_laser is the child frame.

The transform describes where base_laser is relative to base_link.

Example:

base_laser is 0.20 m in front of base_link.
base_laser is 0.15 m above base_link.

You can write this as:

parent: base_link
child:  base_laser
x: 0.20
y: 0.00
z: 0.15

7. What is a TF tree?

A TF tree is a tree structure that connects all coordinate frames.

For a simple AMR, the TF tree may look like this:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            └── imu_link

This tree tells ROS 2 the relationship between frames.

For example, because the tree connects map to base_laser, ROS 2 can calculate:

Where is the LiDAR in the map?

Even if there is no direct transform:

map β†’ base_laser

ROS 2 can combine transforms:

map β†’ odom
odom β†’ base_link
base_link β†’ base_laser

Therefore:

map β†’ base_laser

can be calculated.


8. Fixed frame and moving frame

There are two important types of frames.

8.1 Fixed frame

A fixed frame does not move relative to its parent.

Example:

base_link β†’ base_laser

The LiDAR is physically mounted on the robot body.

So the relationship between base_link and base_laser is fixed.

Another example:

base_link β†’ camera_link
base_link β†’ imu_link

These are usually static transforms.


8.2 Moving frame

A moving frame changes over time.

Example:

odom β†’ base_link

The robot moves in the odometry frame, so the position of base_link relative to odom changes continuously.

Another example from turtlesim:

world β†’ turtle1
world β†’ turtle2

The turtles move in the world frame, so their transforms change over time.


9. Important Nav2 frames

For Nav2, you should understand these frames first:

map
odom
base_link
sensor frames

9.1 base_link

base_link is attached to the robot body.

It usually represents the main body center of the robot.

For an AMR:

base_link is usually near the center of the chassis.

The robot’s velocity command usually controls the motion of base_link.


9.2 odom

odom is the odometry frame.

It is usually continuous and smooth.

The transform is:

odom β†’ base_link

This transform describes how the robot moves according to odometry.

Odometry may come from:

wheel encoder
IMU
visual odometry
sensor fusion
simulation odometry

9.3 map

map is the global map frame.

It is used for localization and navigation.

The transform is:

map β†’ odom

This transform is usually provided by localization or SLAM.

For example:

AMCL publishes map β†’ odom
SLAM Toolbox may publish map β†’ odom

9.4 Sensor frames

Sensor frames describe where sensors are mounted.

Examples:

base_laser
camera_link
imu_link

Common static transforms are:

base_link β†’ base_laser
base_link β†’ camera_link
base_link β†’ imu_link

10. Nav2 TF tree concept

A common Nav2 TF tree is:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            └── imu_link

You should understand this carefully.

Meaning of each transform

| Transform | Meaning | Usually published by | | ------------------------- | ------------------------------------------- | ------------------------------------ | | map β†’ odom | Global correction from localization or SLAM | AMCL or SLAM | | odom β†’ base_link | Robot motion from odometry | Odometry node or robot_localization | | base_link β†’ base_laser | LiDAR mounting position | Static transform or URDF | | base_link β†’ camera_link | Camera mounting position | Static transform or URDF | | base_link β†’ imu_link | IMU mounting position | Static transform or URDF |

Important:

In real Nav2, you usually do not manually publish map β†’ odom if AMCL or SLAM is already running.


11. Practice 1: Install required packages

Open a terminal:

source /opt/ros/jazzy/setup.bash

Install required packages:

sudo apt update
sudo apt install ros-jazzy-turtle-tf2-py ros-jazzy-turtlesim ros-jazzy-tf2-tools ros-jazzy-rviz2

12. Practice 2: Run the TF2 turtlesim demo

Open Terminal 1:

source /opt/ros/jazzy/setup.bash
ros2 launch turtle_tf2_py turtle_tf2_demo.launch.py

You should see two turtles.

Open Terminal 2:

source /opt/ros/jazzy/setup.bash
ros2 run turtlesim turtle_teleop_key

Use the keyboard to move the first turtle.

You should observe:

turtle1 moves by keyboard control.
turtle2 follows turtle1.

Conceptually, this demo has frames like:

world
 β”œβ”€β”€ turtle1
 └── turtle2

The TF2 system knows:

world β†’ turtle1
world β†’ turtle2

Because both turtles are connected to world, TF2 can calculate:

turtle2 β†’ turtle1

This allows turtle2 to know where turtle1 is.


13. Practice 3: List TF topics

Open Terminal 3:

source /opt/ros/jazzy/setup.bash
ros2 topic list

You should see topics similar to:

/tf
/tf_static

Meaning:

/tf contains dynamic transforms.
/tf_static contains static transforms.

Dynamic transforms change over time.

Static transforms usually do not change after being published.


14. Practice 4: Use tf2_echo

Use this command:

ros2 run tf2_ros tf2_echo turtle2 turtle1

This asks:

What is the transform from turtle2 to turtle1?

In other words:

Where is turtle1 relative to turtle2?

You may see output like:

Translation: [x, y, z]
Rotation: in Quaternion [x, y, z, w]

Focus first on translation:

x means forward/backward distance.
y means left/right distance.
z is usually 0 in turtlesim.

Move the turtle and observe how the transform changes.


15. Practice 5: Reverse the frame order

Try:

ros2 run tf2_ros tf2_echo turtle1 turtle2

Compare it with:

ros2 run tf2_ros tf2_echo turtle2 turtle1

These two commands are not the same.

Example:

turtle2 β†’ turtle1

means:

Where is turtle1 relative to turtle2?

But:

turtle1 β†’ turtle2

means:

Where is turtle2 relative to turtle1?

Teaching point:

The order of frames matters.


16. Practice 6: Generate TF tree using view_frames

Run:

ros2 run tf2_tools view_frames

This command listens to TF data and creates a PDF file.

The output file is usually:

frames.pdf

Open the PDF:

xdg-open frames.pdf

You should see a TF tree similar to:

world
 β”œβ”€β”€ turtle1
 └── turtle2

Question:

Which frame is the parent frame?
Which frames are child frames?

Expected answer:

world is the parent frame.
turtle1 and turtle2 are child frames.

17. Practice 7: Visualize TF in RViz2

Open a new terminal:

source /opt/ros/jazzy/setup.bash
rviz2

In RViz2:

1. Set Fixed Frame to world.
2. Click Add.
3. Choose TF.
4. Click OK.

You should see the TF frames.

You can also add Axes display if needed.

Important:

The Fixed Frame tells RViz which frame is used as the reference frame.

For the turtlesim TF2 demo, use:

world

For Nav2, the fixed frame is usually:

map

or sometimes:

odom

depending on the current system.


18. Practice 8: Think like Nav2

Now connect the turtlesim example to Nav2.

In turtlesim:

world
 β”œβ”€β”€ turtle1
 └── turtle2

In Nav2:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            └── camera_link

Comparison:

| Turtlesim | Nav2 | | -------------------------- | -------------------------------- | | world | map or odom | | turtle1 | base_link | | turtle2 | another robot or target frame | | world β†’ turtle1 | odom β†’ base_link | | tf2_echo turtle2 turtle1 | checking relative frame position |

The key idea is the same:

TF2 allows one frame to understand where another frame is.


19. Common TF2 misunderstanding

Misunderstanding 1: A frame is the same as a topic

Wrong idea:

base_link is a topic.

Correct idea:

base_link is a coordinate frame.

A topic carries messages.

A frame is a coordinate system.


Misunderstanding 2: TF2 controls the robot

Wrong idea:

TF2 makes the robot move.

Correct idea:

TF2 does not control the robot.
TF2 only describes coordinate relationships.

The robot moves because a controller sends velocity commands, such as:

/cmd_vel

Misunderstanding 3: map, odom, and base_link are interchangeable

Wrong idea:

map, odom, and base_link are almost the same.

Correct idea:

map is the global reference frame.
odom is the local odometry reference frame.
base_link is attached to the robot body.

Misunderstanding 4: The frame order does not matter

Wrong idea:

tf2_echo turtle1 turtle2

is the same as:

tf2_echo turtle2 turtle1

Correct idea:

The order matters.
The transform direction changes.

20. Classroom discussion questions

  1. Why does a mobile robot need more than one coordinate frame?
  2. What is the difference between base_link and base_laser?
  3. Why is odom β†’ base_link a dynamic transform?
  4. Why is base_link β†’ base_laser usually a static transform?
  5. In Nav2, who usually provides map β†’ odom?
  6. In Nav2, who usually provides odom β†’ base_link?
  7. What is the difference between /tf and /tf_static?
  8. Why does RViz need a Fixed Frame?

21. Practice assignment

Assignment title

Observe and Explain a TF Tree

Task 1: Run the TF2 turtlesim demo

Run:

ros2 launch turtle_tf2_py turtle_tf2_demo.launch.py

Then control the turtle:

ros2 run turtlesim turtle_teleop_key

Task 2: Generate the TF tree

Run:

ros2 run tf2_tools view_frames

Submit a screenshot of the generated TF tree.


Task 3: Use tf2_echo

Run:

ros2 run tf2_ros tf2_echo turtle2 turtle1

Submit a screenshot of the output.


Task 4: Explain the result

Write a short explanation:

The parent frame is:
The child frames are:
The meaning of turtle2 β†’ turtle1 is:
The transform changes when:

Task 5: Connect to Nav2

Draw a simple Nav2 TF tree:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            └── camera_link

Then answer:

Which transform is dynamic?
Which transform is static?
Which transform is related to localization?
Which transform is related to odometry?
Which transforms are related to sensor mounting?

22. Mini quiz

  1. What is a coordinate frame?
  2. What is a TF tree?
  3. What is the parent frame in base_link β†’ base_laser?
  4. What is the child frame in base_link β†’ base_laser?
  5. Is base_link β†’ base_laser usually static or dynamic?
  6. Is odom β†’ base_link usually static or dynamic?
  7. What does tf2_echo turtle2 turtle1 show?
  8. What does view_frames generate?
  9. What is the usual fixed frame in Nav2 RViz?
  10. Why is TF2 important for Nav2?

23. Key summary

In this module, you learned that TF2 manages coordinate frame relationships.

A robot needs many frames because different parts of the robot have different coordinate systems.

A TF tree connects these frames.

For turtlesim, the tree is similar to:

world
 β”œβ”€β”€ turtle1
 └── turtle2

For Nav2, the tree is usually similar to:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            └── imu_link

The most important idea is:

TF2 does not move the robot. TF2 tells the robot where each frame is relative to other frames.

In the next module, you will learn how to publish static sensor frames such as:

base_link β†’ base_laser
base_link β†’ camera_link
base_link β†’ imu_link

Tags