Engineering Guides · Module 06
TF2 in ROS 2: static transforms and debugging
tf2 keeps a tree of frames over time. A valid tree has one parent per frame, no cycles and one root.
Assumptions: Numbers in the examples are illustrative and the code is executed by the site’s tests. Facts taken from a cited source are marked; other statements are general engineering knowledge and must be confirmed on the datasheet of the part you use.
1. Engineering problem
Everything in a robot that uses positions relies on tf2. Failures are easy to cause (two publishers for one frame, missing links, stale stamps) and hard to see without tools.
2. When is this needed?
- Adding a sensor to the robot description.
- When a lookup fails with a missing frame or an extrapolation error.
- Before testing navigation or SLAM.
3. Selection and design decisions
Verified in the Jazzy tf2 tutorials: tf2_ros provides static_transform_publisher, usable on the command line or in launch files, taking --x --y --z with either --yaw --pitch --roll or a quaternion (--qx --qy --qz --qw) and --frame-id (parent) and --child-frame-id. Debugging tools are tf2_echo, tf2_monitor and view_frames (tf2_tools). The error “Lookup would require extrapolation into the future” means the requested time is newer than the latest transform.
| Symptom | Likely cause | Tool |
|---|---|---|
| Frame does not exist | Name typo or no publisher | tf2_echo, view_frames |
| Two parents for a frame | Duplicate publishers (URDF and a static publisher) | view_frames, ros2 topic info /tf_static |
| Disconnected trees | A missing link between two frames | view_frames |
| Extrapolation into the future or past | Clock or timestamp mismatch, slow publisher | tf2_monitor, check use_sim_time |
| Transform inverted | Parent and child swapped | tf2_echo against expected sign |
4. Advantages and disadvantages
- URDF with robot_state_publisher keeps fixed links in one description; individual static publishers are quick and scatter the truth.
- Static transforms are latched on
/tf_static; dynamic ones are published repeatedly on/tf. - Quaternion arguments avoid ambiguity in Euler angle conventions.
5. Requirements and constraints
- Every frame has exactly one parent.
- The tree has one root.
- Frame names follow REP 105 (map, odom, base_link) for the main chain.
6. Architecture
map ─▶ odom ─▶ base_link ─┬▶ lidar
└▶ camera ─▶ camera_optical7. Implementation
- Define the fixed links in the URDF or in static publishers, not in both.
- Run
ros2 run tf2_tools view_framesand check the tree. - Use
ros2 run tf2_ros tf2_echo parent childto compare with expected values. - Use
tf2_monitorto check update rates and delays. - Check the tree with a script or checker (below) in CI.
tree = [("map", "odom"), ("odom", "base_link"), ("base_link", "lidar"), ("base_link", "camera"), ("odom", "camera"), ("gps", "antenna")]
parents, issues = {}, []
for p, c in tree:
if c in parents and parents[c] != p:
issues.append(f"{c} has two parents: {parents[c]} and {p}")
parents.setdefault(c, p)
roots = sorted({p for p in parents.values()} - set(parents))
if len(roots) > 1:
issues.append(f"{len(roots)} disconnected trees with roots {roots}")
for c in parents:
seen, x = set(), c
while x in parents:
if x in seen:
issues.append(f"cycle through {x}"); break
seen.add(x); x = parents[x]
print("\n".join(issues) or "tree is valid")Printed (checked by the site’s tests):
camera has two parents: base_link and odom
2 disconnected trees with roots ['gps', 'map']Reading it: the checker flags that camera is given two parents (base_link and odom) and that the tree is split into two with roots gps and map. The frame names are illustrative.
8. Real examples
- Commands (Jazzy):
ros2 run tf2_ros static_transform_publisher --x 0.3 --y 0 --z 0.5 --yaw 0 --pitch 0 --roll 0 --frame-id base_link --child-frame-id lidar(not executed by the site’s tests).
9. Failure scenarios
- Two publishers for the same child frame so the transform flickers.
- A frame without any path to the others.
- Simulation time not enabled on a node, so stamps differ by days.
10. Troubleshooting
- Run view_frames and read the tree before changing anything.
- Look for duplicate publishers with
ros2 topic info /tf_static --verbose. - Compare stamps with the clock; check use_sim_time.
11. Validation
- The checker example prints the lines shown (executed by the site tests).
- view_frames shows a single tree and tf2_echo values match the CAD within tolerance.
12. Engineering checklist
13. Further references
- ROS 2 Jazzy tf2 tutorials: static broadcaster and debugging tf2 problems, read 2026-11-06.
- REP 103: rep-0103.rst, read 2026-11-05.