Use tf2_ros::MessageFilter when a stamped sensor message may arrive before the transform needed to interpret it. The filter retains the message and releases it to the processing callback when the required transform becomes available. It asks about the message’s timestamp, so waiting for TF does not replace the measurement time with the reception time.
Imagine a laser scan arriving just before the corresponding transform from the robot-state publisher. Processing immediately can fail even though both streams are functioning. Waiting for the right transform can solve that ordering problem; substituting the latest transform changes the geometric question.
Follow the timestamp through the filter
The pinned Rolling implementation reads the incoming frame identifier and timestamp through message traits. It rejects an empty frame identifier, queues the message and requests the transform toward each configured target frame at that timestamp.
When the required transformations are available, the filter passes the original message through. The consumer still performs the intended data transformation or processing. The filter coordinates availability; it does not turn a scan into a different coordinate representation on its own.
This differs from the two-time tf2 lookup, which explicitly relates a historical source frame to a target frame at another time. Here the initial question is when a callback may process its stamped input, before deciding which coordinate relationship to request.
Three limits control different things
The implementation exposes a queue size, a transform-wait timeout and a tolerance. These should not be treated as interchangeable ways to make a delayed stream work.
| Setting or condition | What it controls | What to inspect |
|---|---|---|
| Queue size | How many waiting messages are retained | Input rate and transform delay |
| Buffer timeout | How long a requested transform may be awaited | Whether the transform is late or never produced |
| Tolerance | An additional required transform time after the message stamp | The interval the consumer actually needs |
| Transform-cache coverage | Which historical times can still be resolved | Clock agreement and age of arriving messages |
At this revision, a nonzero tolerance adds a request at stamp + tolerance as well as the request at the stamp. Increasing it asks for more temporal coverage. It is not permission to accept an arbitrary timestamp error.
For a hypothetical 30 Hz stream delayed by 0.2 seconds, about six new messages arrive during that delay. This arithmetic can inform an initial queue estimate, but bursts, scheduling and the actual delay distribution still need measurement. A larger queue also retains more old work. The source documents zero queue size as unbounded, so use an explicit capacity when memory and processing age matter.
Diagnose why a message left the queue
The checked source drops the oldest queued message when adding a new one would exceed the configured capacity. It distinguishes that queue-full case from an empty frame ID and messages that are older than the available transform history. These conditions call for different fixes. In the checked callback, an exception from the transform future is mapped to OutTheBack; inspect the underlying transform error as well as the reported filter reason.
A queue-full pattern suggests examining arrival rate and transform availability together. An empty frame name points toward message construction. A timestamp older than the cache calls for checking clock agreement and delay before increasing memory. Replacing every failed lookup with “latest” would hide these distinctions.
Do not assume that an API name from an older example is callable in the current header. In this pinned file, the registerFailureCallback declaration is inside a disabled preprocessor block. Use the diagnostic facilities available in the installed version when collecting drop evidence.
Keep freshness as a consumer decision
A released message has satisfied the filter’s transform-availability condition. The application still needs to decide whether the measurement is recent enough for its current use. Record capture time, callback time, target frame and the processing-age decision together.
The source was checked October 16, 2026. No ROS node or delay-injection experiment was run here. A useful proposed check delays TF while keeping sensor timestamps unchanged, then observes callback timing and queue drops; a separate stale-message case tests the consumer’s age rule.