Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for "Derived" Transforms #1533

Open
Tracked by #1537
jleibs opened this issue Mar 8, 2023 · 1 comment
Open
Tracked by #1537

Support for "Derived" Transforms #1533

jleibs opened this issue Mar 8, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@jleibs
Copy link
Member

jleibs commented Mar 8, 2023

Issue Overview

In the current design, the transform graph must perfectly match the entity path hierarchy.

However, there are situations where the user-data graph transform representation does not match the path hierarchy we want to use for logging data. For example, a URDF file may contain several linkages that logically exist to match the mechanical design of the robot, but are otherwise not interesting to the user.

At present the user must choose between two sub-optimal options:

  • Logging their data to paths that exactly match the transform graph allows them to use the transform values directly, but can lead to overly verbose path hierarchies that restrict freedom of users to organize data logically.
  • On the other hand, deriving path-relative transforms at log-time, as we do in the ROS example, allows the user to choose their own data organization, but sacrifices visibility into the original raw transform values.

Proposal: "Derived" transforms.

The idea is that the value of the transform for that link in the path-hierarchy, rather than being directly fetched from the store, would be derived from some other function at render time. Specifically, this must be a function of time (along with some other data logged to the store). However, the high-level transform semantics are crucially unchanged: the transform (regardless of how its derived) still represents the transform between those two spaces defined by the path hierarchy and is considered fixed for a given instant in time. As such, cross-space projection can be totally independent of of the resolver -- it just needs to know that at a given timepoint on a given timeline, the transform was derived as having a particular value. Additionally the means of derivation need not play a role in space-partitioning and view-construction perspective. The mere fact that a "derived transform" has been logged to a path allows us to do all of the same path-hierarchy analysis we already perform.

The current transforms already fit into this model. They simply use a "default resolver" that returns the latest-at value of the transform logged to that path.

There are two immediate mechanisms of derived transforms that come to mind as being useful...

"graph-lookup" transform

First, raw transforms would be logged with a graph-centric representation.

For example, adopting from a ROS tf system, transforms would be logged to a path derived from their source frame, (e.g. tf/<child_frame_id>) and include a link to their dest frame (e.g. tf/<parent_frame_id>).

rr.log_rigid3_graph_link(source_frame="tf/camera_optical_rgb", dest_frame="tf/camera_link", dest_from_source=...)
rr.log_rigid3_graph_link(source_frame="tf/camera_link", dest_frame="tf/left_wrist_link", dest_from_source=...)
rr.log_rigid3_graph_link(source_frame="tf/left_wrist_link", dest_frame="tf/left_arm_link", dest_from_source=...)
rr.log_rigid3_graph_link(source_frame="tf/left_arm_link", dest_frame="tf/base_link", dest_from_source=...)

Then, a given path can be logged as a derived "graph lookup" transform:

rr.log_rigid3_graph_lookup('robot/camera', parent='tf/base_link', child='tf/camera_optical_rgb')

At resolution time, this would then do a graph walk based on the logged topology.

Parametric transform

Much simpler than graph-based resolution is simple support for parametric transforms.

Once we have derived transforms, we can derive transforms from things like scalar values representing joint rotations or linear actuator offsets.

Exa:

rr.log_scalar('joint/arm', arm_rotation_rad)
rr.log_rigid3d_parametric_rotation("robot/arm", axis=(1,0,0), angle="joint/arm")

This avoids the need for something like the "robot state publisher" in ROS.

@jleibs jleibs added the enhancement New feature or request label Mar 8, 2023
@nikolausWest
Copy link
Member

The parametric transform could potentially be done using some kind of entity reference.

rr.log('joint/arm', rr.components.Angle(radians=arm_rotation_rad))
rr.log("robot/arm", rr.Transform3D(axis=(1,0,0), angle=rr.components.Angle.Reference('joint/arm')))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants