Skip to the lesson
FixTheRobot Explore Robotics / Navigation / M9 Navigation in the Real World / M9-T3

Navigation · Theory · M9

M9-T3 — Frames, Timing and Simulation

A surprising share of navigation failures are not about planning at all: they are about where a coordinate frame is, and what time it is.

  • Lesson 3 of 6
  • Module 9: Navigation in the Real World
  • Theory
  • About 9 minutes to read

The planner can be perfect and the robot can still stop because a transform is half a second old, or drive towards a door that is not there because the map frame jumped. Frame and clock problems look like navigation bugs and are found with different tools. This lesson lists the ones that cost the most time, and how simulation can find them before a robot does.

Learning objectives

After this lesson, you should be able to:

  • Use the map, odom and base_link frames correctly and say which node publishes each transform.
  • Explain how a mixed simulated and wall clock, a transform tolerance that is too tight, or a jump in map to odom shows up as a navigation failure.
  • Estimate the effect of latency and odometry drift on position, and set a transform tolerance sensibly.
  • Plan a simulation test that finds frame, clock and configuration errors before hardware, and say what simulation cannot show.

The intuition

Every question a robot asks is “where is X, relative to me, now?”. The answer needs two things: a chain of transforms that connects X’s frame to the robot’s, and a timestamp at which that chain is valid. A tree of frames provides the first; a clock provides the second. If either is wrong, a perfectly good algorithm gets a wrong answer and still obeys it.

The convention (REP 105) is a chain map → odom → base_link. The odom frame is smooth but drifts: wheel odometry is continuous, and its error grows. The map frame is globally consistent but is corrected in jumps when localization improves its estimate. The transform map → odom is the correction, published by localization (AMCL or SLAM); odom → base_link is published by odometry; sensor frames hang off base_link through the robot description. Planning is done in map, the local controller reacts in odom, so the controller is not startled by a localization correction.

Frames and clocks in a navigation systemA transform tree map to odom to base_link, with the publisher of each link named, and two clocks: simulated time from the simulator and wall time of the computer. Nodes must all use the same one.mapfixed to the worldodomcontinuous, driftsbase_linkmoves with robotsensor framesstatic transforms localizationodometryrobot description use_sim_time = true on EVERY nodetime comes from /clock: 125.4 sstamps and lookups agree one node on wall timeits clock: 1 760 000 000 severy lookup is “in the future” A transform is looked up at a time. Two clocks mean the time you ask for does not exist.
The usual frame tree, and the clock problem: a node on wall time asks for transforms at times that the simulation never reached.

The mathematics

A transform lookup

A lookup asks for the transform from frame A to frame B at time t. The transform buffer holds a history of each link. A lookup succeeds when each link in the chain has data at, or around, t; it fails with an extrapolation or timeout error when it does not. A transform tolerance is how much older than “now” the data may be and still be accepted.

success if
tnow−t{latest}transform≤transformtolerancet_{\text{now}}-t_{\{\text{latest}\}\text{transform}}\le \mathrm{transform}_{\text{tolerance}}
latency error=v⋅(age of the data)\text{latency error}=v\cdot \text{(age of the data)}
distance moved while the data was in flight

Where the time goes

Sources of delay
SourceTypical effectConsequence
Sensor and driver latency10 to 100 msThe scan describes where the robot was
Transform publicationOne update period of the publishermap → odom may be seconds old if localization is slow
Controller period1 / frequencyThe command is held for the whole period
Command chainSmoother, monitor, driver, motorCommand latency τ: 100 to 400 ms is common on networks
Wireless linkTens to hundreds of ms, with spikesStale data and bursts

Frames and what moves them

Frames
FrameBehaviourUsed for
mapFixed to the world; jumps when localization correctsGoals, global plans, the static map
odomContinuous, drifts without boundLocal costmap, local control
base_linkMoves with the robotFootprint, sensor placement
sensor framesFixed to the robot by calibrationSensor data into the costmaps

Simulated time

A simulator publishes its own clock on a topic (/clock); a node with the parameter use_sim_time set to true reads that instead of the computer’s clock. It must be true for every node of the system, because a message stamped in simulated time and a node comparing it with wall time disagree by decades. The simulator can also run slower or faster than real time (a real-time factor), so anything that measures time must use the same clock.

What a test in simulation can find

  • Configuration contradictions: clocks, frames, footprints, plugin names, velocity limits.
  • Wiring errors: topics that do not connect, remaps, lifecycle nodes that never activate.
  • Behaviour logic: recoveries, retries, goals that cannot succeed.
  • Regression: a change that makes a scenario fail that passed yesterday.

It cannot find sensor noise you did not model, floors that slip, wireless links that stall, or people who do not behave as scripted.

A worked example

Two clocks. A simulation has run for 125.4 s. Every simulated message is stamped with times near 125 s. One node (the navigator) is launched with use_sim_time false and reads the computer clock, 1 760 000 000 s. It asks for the transform from map to base_link at its “now”. The buffer’s newest data is at 125.4 s, so the lookup is about 1.76 × 109 s in the future: it times out. In the log you see “timed out waiting for transform”, though every transform is being published. The fix is one parameter, set in one place for the whole launch (project M9-L4, experiment D).

Latency becomes distance. A robot drives at 0.5 m/s with 0.2 s of delay between a scan and the command that uses it:

Latency as distance
position error from delay=0.5 m/s×0.2 s=0.10 m\text{position error from delay}=0.5\,\mathrm{m}/\mathrm{s}\times 0.2\,\mathrm{s}=0.10\,\mathrm{m}
at 1.0 m/s with 0.35 s: 1.0×0.35=0.35 m\text{at}\,1.0\,\mathrm{m}/\mathrm{s}\,\text{with}\,0.35\,\mathrm{s}:\,1.0\times 0.35=0.35\,\mathrm{m}

With a 0.10 m delay error and a 0.12 m clearance requirement, almost the whole margin is consumed by latency; the costmap is describing where the obstacle was relative to where the robot was. This is why transform tolerance and controller frequency are safety parameters.

A jump in map to odom. After 30 m, wheel odometry has drifted 1%: 0.30 m. When localization corrects it, map → odom changes by 0.30 m within one update. A global path in map is now 0.30 m away from the robot in the controller’s frame: a step of 0.30 m in cross-track error, which a pure-pursuit controller answers with a sudden turn (compare incident 3 of lab M1-L1). Planning in map and controlling in odom is the standard remedy: the controller follows the path as the local costmap sees it and absorbs the correction smoothly, and localization is configured so that corrections are small and frequent, not large and rare.

A compute budget. A controller at 20 Hz has 50 ms per cycle. If one cycle costs 60 ms of computer time, the achieved rate in real time is 1 / 0.060 = 16.7 Hz, not 20: the command is held longer than designed and the lookahead margin shrinks. A simulation running at real-time factor 1 shows this; a simulation running at half speed hides it, and the first real-robot trial reveals it.

Engineering implications and limitations

The five questions

When navigation fails with transform errors, ask in order: is there a clock (/clock) and does every node use it? Is every link of the chain being published, and by whom? How old is the newest data of each link? Do the frame names in the parameter files match the robot description (base_link versus base_footprint)? Does the transform tolerance cover the actual latency, without hiding a broken publisher?

Do not hide a fault with tolerance

Increasing the transform tolerance until the errors stop is tempting. It makes the robot act on data that is seconds old. Find out why the data is late first.

One launch, one clock

Set use_sim_time from a single launch argument that reaches every node, including the ones you wrote. A single node that forgets is hard to see in the logs and easy to find with ros2 param get.

Simulation as a gate

Run a fixed set of scenarios in simulation on every change to the parameters or the behaviour tree: the narrowest door, a blocked corridor, a goal that cannot succeed, a restart in the middle of a mission. Treat a failure as you would a failing unit test. Then run the physical trial for the things simulation cannot show (lesson M9-T4 on evaluation).

Parameter names change

The parameters mentioned here (use_sim_time, transform_tolerance, global_frame, robot_base_frame) are stable names in Nav2 at the time of writing, but defaults and where they appear can change between releases. Check the documentation for your distribution.

Common misconceptions

“Transform errors mean TF is broken.”

They usually mean a clock, a name or a publisher is wrong. TF is doing exactly what it was asked to do.

“If it works in simulation it will work on the robot.”

Simulation finds configuration and logic errors. It does not model your sensors, floor, wireless link or people, and its timing can be kinder than real time.

“Increase the transform tolerance until the warnings stop.”

That hides late data instead of fixing it, and the robot then acts on a stale picture of the world.

“Planning and control should both use the map frame.”

Using odom for local control isolates the controller from localization jumps; the global plan is in map, and the two are connected through the transform.

Engineering takeaways

  1. The frame chain is map → odom → base_link; localization publishes the first link, odometry the second.
  2. A lookup needs data at the requested time: mixed clocks or late publishers break it, with errors that look like navigation faults.
  3. Latency becomes distance: v × delay. Compare it with your clearance.
  4. Set use_sim_time on every node from one place; do not widen tolerances to hide late data.
  5. Simulation finds configuration, wiring and logic faults; it cannot replace the real sensors, floor and link.

References and further reading

The standards for coordinate frames and the Nav2 setup documentation.

  • ROS Enhancement Proposal REP 105, “Coordinate Frames for Mobile Platforms”, ros.org/reps/rep-0105.html.
  • Nav2 documentation, “Setting Up Transformations” and “Getting Started”, docs.nav2.org (choose your distribution).
  • S. Macenski, T. Foote, B. Gerkey, C. Lalancette and W. Woodall, “Robot Operating System 2: Design, architecture, and uses in the wild”, Science Robotics 7(66), 2022.
  • T. Foote, “tf: The transform library”, IEEE Conference on Technologies for Practical Robot Applications, 2013.

Knowledge check

Three conceptual questions. Write an answer, then reveal the explanation. Your answers stay in your browser.

Question 1

One Nav2 node is started with use_sim_time false in a simulation. What do you expect to see, and why does it look like a transform problem?

Explanation

Timeouts or extrapolation errors on transform lookups. The node asks for transforms at wall-clock times that do not exist in the simulated-time buffer, so lookups fail though the transforms are published. The fix is use_sim_time true on that node.

Question 2

A robot moves at 0.8 m/s and there is 0.25 s of delay between a scan and the command computed from it. How far does it move in that time, and what does this mean for a 0.15 m clearance requirement?

Explanation

0.8 × 0.25 = 0.20 m, larger than the 0.15 m clearance. The robot reacts to where an obstacle was; speed must come down, the delay must shrink, or the monitor must stop the robot earlier.

Question 3

Why is the local costmap placed in the odom frame while the global costmap is in the map frame?

Explanation

odom is continuous, so the local controller is not disturbed when localization corrects the estimate; map is globally consistent, so the global plan and the static map belong there. The transform map → odom connects them.

What’s next

Next: how to show that a navigation system works, with enough runs to believe the answer.

Practice this lesson

Bring Up Nav2 in Simulation

Run Nav2 on a simulated robot on your own machine, send a goal, and diagnose what you see.

Next lesson

M9-T4 — Evaluating Navigation

Design an evaluation with repeatable scenarios, logged metrics and enough runs to trust the result.

Nothing below is required to finish this lesson.