Skip to content

Transform lookup with per-edge latest fallback #981

Description

@nirwester

Description

A common requirement is to request the transform between two arbitrary frames at a specific timestamp, but, when that timestamp cannot be resolved, fall back to the freshest available data rather than waiting for updates across the entire chain.

The desired behavior would be:

  • Attempt the normal time-coherent lookup at the requested timestamp.
  • If that timestamp cannot be resolved, determine the frame chain between source and target.
  • Retrieve the exact or latest available transform for each edge independently.
  • Compose those transforms.
  • Return the timestamps of the individual transforms that were used.

This would have deliberately different temporal semantics from the existing:

lookupTransform(target_frame, source_frame, TimePointZero)

which resolves to the latest common timestamp at which the complete transform chain can be evaluated.

Motivation

There are applications where requiring a common timestamp is unnecessarily restrictive.
For example, several transform publishers may operate independently at different frequencies: a consumer may care primarily that every transform in the chain is sufficiently recent rather than that every edge can be evaluated at exactly the same timestamp.

Typical use cases include:

  • low-latency control or state-estimation consumers;
  • systems where transform publishers are not synchronized;
  • diagnostics which need to know the freshness of every edge in a transform chain.

The caller would explicitly opt into the fact that the resulting transform is not always temporally coherent in the usual tf2 sense -> this would be a separate API and would not change the semantics of lookupTransform.

Design / Implementation Considerations

For example:

TransformWithChain lookupTransformBestEffort(
  const std::string & target_frame,
  const std::string & source_frame,
  const TimePoint & requested_time);

with a result such as:

struct TransformChainEntry
{
  std::string parent_frame;
  std::string child_frame;
  TimePoint stamp;
  bool is_static;
};

struct TransformWithChain
{
  TransformStamped transform;
  std::vector<TransformChainEntry> chain;
  bool time_coherent;
};

It may be preferable for the composed transform's timestamp to remain zero if no exact lookup at the proposed ts is possible, but I don't have a strong preference.

Additional Information

Would such an explicitly non-time-coherent lookup be considered useful functionality for tf2::BufferCore?

Implementing this kind of behavior out of it with the current API is quite tricky (trying a normal lookup, then as fallback figuring out the chain through other methods and repeadetly call lookupTransform with and without TimePointZero), and likely way less efficient than what could be done with a native implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions