Skip to the lesson
FixTheRobot Explore Robotics / Localization & SLAM / M7 SLAM with ROS 2 / M7-T3

Localization & SLAM · Theory · M7

M7-T3 — Sensor Topics and Message Timing

SLAM needs to know when a measurement was taken. A scan stamped at the wrong time is a scan taken from the wrong place.

  • Lesson 3 of 8
  • Module 7: SLAM with ROS 2
  • Theory
  • About 10 minutes to read

A transform tree says where frames are; a time stamp says when. Every sensor message in ROS carries a header with a frame id and a stamp, and a SLAM node uses the stamp to look up where the robot was at the moment of measurement. Get the stamp wrong by a fraction of a second and the data is projected from a pose the robot was never in, or the lookup fails and the message is silently dropped. This lesson covers what the stamp means, how quality-of-service settings decide whether messages arrive at all, and how timing errors show up.

Learning objectives

After this lesson, you should be able to:

  • State what a header stamp must represent and estimate the error caused by a wrong stamp.
  • Apply the QoS compatibility rules for sensor and map topics and predict whether a connection forms.
  • Explain transform lookup, the buffer, and the causes of extrapolation errors.
  • Measure rate, jitter and delay of a topic and recognise the signatures of timing faults.

The problem and the intuition

A photograph of a speeding car is useful only if you know when it was taken. If the label says the photo was taken a tenth of a second later than it really was, you will place the car a tenth of a second too far along. A lidar scan is the same: it is a photograph of the surroundings from the robot’s pose at the moment of the scan. SLAM asks TF “where was the robot when this scan was taken?”. With the right stamp the answer is right; with a stamp that is late by the transport latency, it is the pose where the robot was when the message arrived.

The second half of the story is delivery. ROS 2 decides which publishers and subscribers connect using quality-of-service (QoS) profiles. If they are incompatible, the connection is simply not made, and (in some versions) the only trace is a warning. A sensor driver that publishes with best effort and a node that subscribes with reliable never exchange a single message.

Two questions decide whether a message is used: does the data connect (topic, type, QoS), and does it make sense in time (stamp, frame, buffer)?

Timestamps and transform lookupA timeline with transform samples at fifty hertz and a scan stamped at its measurement time. The lookup succeeds when the scan stamp lies between transform samples. A scan stamped after the newest transform needs extrapolation and is dropped; a scan stamped before the buffer is dropped too. TF samples (50 Hz) scan stamp OK stamp in the future→ extrapolation error older than buffer oldestnewest A lookup needs t_oldest ≤ t_scan ≤ t_newest for every link of the chain.The stamp must be when the data was measured, not when it arrived.
Transform lookup: the stamp must lie inside the buffered range of the transform chain.

The rules: stamps, QoS, filters, lookups

Problem. Deliver sensor data to the SLAM node so that every message is received, stamped with the time of measurement, in a frame whose transform to the map is available at that time.

Assumptions. The system has one clock (wall time on hardware; /clock in simulation); drivers can report the measurement time; transforms are published at a steady rate; the buffer is long enough for the processing latency.

What the stamp must be

header.stamp is the time at which the data was measured. For a camera, the middle of the exposure; for a spinning lidar, the start (or in some drivers the end) of the sweep, with per-point times for deskewing (M5-T2). It is not the time the driver received the packet, nor the time the message was published. If a driver only knows the arrival time, the stamp is late by the unknown latency L, and the SLAM node projects the scan from the pose at t + L. The resulting error is:

effect of a stamp delay L
position error≈v⋅L\text{position error}\approx v\cdot L
bearing error≈ω⋅L\text{bearing error}\approx \omega \cdot L
error of a point at range r≈v⋅L+r⋅ω⋅L\text{error of}\,a\,\text{point at range}\,r\approx v\cdot L+r\cdot \omega \cdot L

Clock and simulated time

In simulation, Gazebo publishes /clock and every node must have use_sim_time: true. Mixing wall time and sim time gives stamps that differ by decades, or time that jumps when the simulation is paused or reset. On hardware, all computers must share a clock (chrony, NTP or PTP), otherwise stamps from different machines disagree by seconds.

Quality of service

Each endpoint declares reliability (RELIABLE or BEST_EFFORT), durability (VOLATILE or TRANSIENT_LOCAL), and history (KEEP_LAST with a depth). The rules for a publisher P and a subscriber S:

QoS compatibility rules
SettingP offersS requestsConnects?
ReliabilityRELIABLERELIABLE or BEST_EFFORTYes
ReliabilityBEST_EFFORTBEST_EFFORTYes
ReliabilityBEST_EFFORTRELIABLENo: the subscriber demands what the publisher cannot give
DurabilityTRANSIENT_LOCALTRANSIENT_LOCAL or VOLATILEYes (a late joiner gets the last message only if S is transient local)
DurabilityVOLATILETRANSIENT_LOCALNo

The conventions of REP 2003 (and the qos_profile_sensor_data preset) are: sensor streams (scans, images, IMU) use BEST_EFFORT, VOLATILE, a small depth, so that a slow consumer drops old data instead of building a queue; maps and static transforms use RELIABLE, TRANSIENT_LOCAL so that a node that starts late still receives the last map. The map topic is thus the classic late-joiner case: an RViz display or Nav2 costmap that subscribes with VOLATILE misses a map published once before it started.

Synchronising and looking up

  • message_filters. ApproximateTime and ExactTime synchronisers match messages from different topics by stamp (for example camera and lidar, or two cameras). A slop that is too small drops pairs; too large mixes frames.
  • tf2 buffer. Stores transforms for a duration (10 s by default; SLAM Toolbox lets you set tf_buffer_duration). lookupTransform(target, source, time) interpolates between samples that bracket time. If time is newer than the newest sample, it must extrapolate, which is refused.
  • tf2 message filter. Holds a message until the transform for its stamp is available (up to a timeout), so that short transform latency does not drop scans; a long delay does.
stamp
header time: when the data was measured.
L
latency between measurement and the stamp (zero when the driver stamps correctly).
jitter
variation of the interval between consecutive messages around its mean.
extrapolation
looking up a transform at a time outside the buffered samples; refused by tf2.

Measuring timing

ros2 topic hz /scan        # rate, min/max/std of the interval
ros2 topic delay /scan     # now minus header.stamp (needs a header)
ros2 topic bw /scan        # bandwidth
ros2 topic info /scan -v   # QoS of every publisher and subscriber

Signatures of timing faults

Timing faults and remedies
SignatureLikely causeRemedy
topic delay is large and constant (e.g. 0.12 s)Driver stamps on arrival, or the clock offset between machinesUse the driver’s hardware time, synchronise clocks
topic delay negativeStamps in the future: clock ahead of the receiver, or sim-time mismatchFix the clock source
Stamps jump back or repeatSimulation reset, driver restart, duplicate publishersReset the SLAM node; remove the duplicate
Stamp zero (0.0)Node forgot to fill the headerFix the node; zero means “latest” to some APIs and “1970” to others
Rate drops, big gapsCPU starved, wireless link, QoS reliable with backpressureReduce load, use best effort for sensors
No messages at all, no errorIncompatible QoSros2 topic info -v, align the profiles

A worked example: the size of a stamp delay, and the arithmetic of a jitter log

  1. A stamp delay. A lidar driver stamps scans at arrival; the USB transport and buffering add L = 0.1 s. The robot moves at v = 0.5 m/s and rotates at ω = 1 rad/s (a brisk turn). The position error is v·L = 0.05 m. The bearing error is ω·L = 0.1 rad ≈ 5.7°. A wall point at range r = 5 m is placed r·ω·L = 0.5 m wrong. A scan matcher would see the walls smeared by tens of centimetres during every turn, and the map would show doubled walls.
  2. Reading a jitter log. Six consecutive scan stamps (seconds): 10.000, 10.100, 10.201, 10.300, 10.400, 10.650. The intervals are 0.100, 0.101, 0.099, 0.100, 0.250. The median interval is 0.100 s (10 Hz). The last interval is 2.5 times the median: one or two scans were lost. If the next stamp were 10.640, an earlier time than the previous one, that would be non-monotonic and a driver or clock problem.
  3. A lookup that fails. The odometry transform is published at 50 Hz; the newest sample is at t = 100.000 s. A scan stamped 100.012 s arrives. The next transform sample is due at 100.020 s, so the lookup fails with “extrapolation into the future”. The tf2 message filter holds the scan for up to the timeout (a couple of tenths of a second in SLAM Toolbox: transform_timeout) and succeeds once the 100.020 sample arrives; with a timeout of zero the scan is dropped. A scan stamped 100.5 s because the clock is half a second ahead would be dropped every time.
  4. A QoS mismatch. The lidar driver publishes /scan with BEST_EFFORT (the sensor convention). A custom node subscribes with the default RELIABLE profile. ros2 topic list shows the topic, ros2 topic hz /scan from the command line (which uses a compatible profile) shows 10 Hz, and the custom node receives nothing. The log may print “New publisher discovered on topic ‘/scan’, offering incompatible QoS”. The fix is to subscribe with qos_profile_sensor_data.
  5. A late joiner. The map server publishes /map once with TRANSIENT_LOCAL. RViz starts later with a VOLATILE subscription and shows nothing; changing its display to “Transient Local” durability, or republishing, fixes it. The same applies to /tf_static and Nav2’s static layer.

Engineering implications and limitations

Engineering implications

  • Prefer driver hardware timestamps. If the sensor supports time synchronisation (PTP, PPS, an external trigger), use it; otherwise estimate and subtract a fixed latency, and verify by turning the robot in front of a wall.
  • Synchronise clocks across machines with chrony or PTP; check offsets with chronyc tracking.
  • Choose QoS deliberately. Sensors: best effort, small depth. Maps, static transforms and parameters: reliable, transient local. Mirror the publisher’s profile in your subscribers or use the presets.
  • Give transforms headroom. Publish odometry TF at 30–50 Hz and set a transform timeout of a few hundred milliseconds in the SLAM node; do not make it so long that you hide real delays.
  • Log timing. Record rate, jitter and delay for each sensor in every run; a change between runs is a symptom of a hardware or load problem.
  • Test with a sharp turn. Timing errors show in rotation, as a smeared or doubled wall; a straight drive hides them.

Limits

These checks assume messages carry usable stamps; some drivers are wrong in ways that only physical tests reveal. DDS vendors differ in how QoS events are reported and in default behaviour under load, and the ROS 2 releases differ in tooling (for example, ros2 topic delay is available in current distributions but not in all older ones). Finally, a correct stamp does not remove motion distortion within a single scan, which needs deskewing (M5-T2).

Common misconceptions

“The stamp is when the message was published.”

It is the time of measurement; publishing time is the receipt time and is not the same.

“If ros2 topic hz shows data, my node receives it.”

The CLI uses a permissive QoS profile; your subscriber may be incompatible.

“Reliable is always safer.”

For high-rate sensors a reliable queue can add latency and starve the system; best effort lets old data drop.

“Time errors of 50–100 ms are irrelevant for a slow robot.”

Rotation magnifies them: 0.1 s at 1 rad/s moves a wall point at 5 m by half a metre.

Engineering takeaways

  1. The header stamp must be the measurement time; a delay L produces errors of v·L in position and ω·L in bearing.
  2. Simulation requires use_sim_time everywhere; hardware requires synchronised clocks.
  3. A BEST_EFFORT publisher cannot serve a RELIABLE subscriber; a VOLATILE publisher cannot serve a TRANSIENT_LOCAL one.
  4. tf2 lookups need the stamp inside the buffered range; future stamps cause extrapolation errors.
  5. Measure rate, delay and jitter with ros2 topic hz and delay, and check QoS with ros2 topic info -v.

References and further reading

Primary papers and authoritative documentation.

Knowledge check

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

Question 1

A driver stamps lidar scans 80 ms late. The robot turns at 0.8 rad/s. How far off is a wall point 6 m away?

Explanation

The bearing error is ω L = 0.8 × 0.08 = 0.064 rad, so a point at 6 m is displaced by about 6 × 0.064 ≈ 0.38 m (plus the translation error v L). Walls smear during turns.

Question 2

A custom node subscribes to /scan with default (RELIABLE) QoS but receives nothing, while ros2 topic hz /scan works. Why?

Explanation

The publisher offers BEST_EFFORT, and a RELIABLE subscriber cannot be satisfied, so no connection is made. The CLI tool subscribes with a compatible profile. Use qos_profile_sensor_data (best effort) in the node.

Question 3

The log shows “extrapolation into the future” for every scan in a simulation. What do you check first?

Explanation

The clock source: whether all nodes, including the SLAM node and the sensor plugin, use use_sim_time. A node on wall time stamps messages decades away from the simulation clock, and no transform covers those times.

What’s next

With wiring, frames and timing in order, the next lesson looks at the SLAM node itself: SLAM Toolbox, its modes, and the parameters that matter.

Practice this lesson

Diagnose Sensor Timestamp Problems

Find clock, stamp and QoS problems that make SLAM drop scans or jump.

Next lesson

M7-T4 — SLAM Toolbox and Mapping Workflows

Configure SLAM Toolbox for online and offline mapping and read its key parameters.

Nothing below is required to finish this lesson.