| Crates.io | cu-transform |
| lib.rs | cu-transform |
| version | 0.9.1 |
| created_at | 2025-08-01 01:24:58.89234+00 |
| updated_at | 2025-09-12 20:22:24.374867+00 |
| description | A coordinate frame transformation library for copper-rs, similar to tf2 in ROS2 |
| homepage | https://github.com/copper-project |
| repository | https://github.com/copper-project/copper-rs |
| max_upload_size | |
| id | 1775951 |
| size | 230,731 |
This library provides spatial transformation functionality for the Copper framework, including both pose (position and orientation) transformations and velocity transformations.
The transform tree maintains a hierarchical relationship between coordinate frames:
use cu_transform::{StampedTransform, TransformTree, Transform3D};
use cu29::clock::CuDuration;
fn tree_lookup() {
// Create a transform tree
let mut tree = TransformTree::<f32>::new();
// Add a transform from "world" to "robot"
let world_to_robot = StampedTransform {
transform: Transform3D::default(), // Identity transform
stamp: CuDuration(1000),
parent_frame: "world".try_into().expect("invalid name"),
child_frame: "robot".try_into().expect("invalid name"),
};
tree.add_transform(world_to_robot).unwrap();
// Look up transform
let transform = tree.lookup_transform("world", "robot", CuDuration(1000)).unwrap();
}
The cu_transform library also supports calculating and transforming velocities:
use cu_transform::{VelocityTransform, TransformTree};
use cu29::clock::CuDuration;
fn velocity_lookup() {
// Create and set up a transform tree with moving frames
// ...
// Look up velocity between frames at a specific time
// This uses caching to speed up repeated lookups
let velocity = tree.lookup_velocity("world", "robot", CuDuration(1500)).unwrap();
// Access linear and angular components
let linear_x = velocity.linear[0]; // Linear velocity in x direction (m/s)
let angular_z = velocity.angular[2]; // Angular velocity around z axis (rad/s)
// For unit-aware applications, use the unit methods
let linear_vel = velocity.linear_velocity(); // Returns velocities with proper units
}
Velocity is computed by differentiating transformations over time:
fn compute_velocity() {
// Assuming we have two transforms at different times
let velocity = transform2.compute_velocity(&transform1);
}
Velocities can be transformed between coordinate frames:
use cu_transform::{transform_velocity, VelocityTransform, Transform3D};
fn frame_transformation() {
// Velocity in frame A
let velocity_a = VelocityTransform {
linear: [1.0, 0.0, 0.0], // 1 m/s in x direction
angular: [0.0, 0.0, 0.5], // 0.5 rad/s around z axis
};
// Transform from frame A to frame B
let transform_a_to_b = Transform3D { /* ... */ };
// Position where the velocity is measured
let position = [0.0, 0.0, 0.0];
// Transform velocity from frame A to frame B
let velocity_b = transform_velocity(&velocity_a, &transform_a_to_b, &position);
}
The velocity transformation follows the standard rigid body motion equations:
Where:
When looking up velocity across multiple frames, the transform tree handles the chain of transformations properly, accumulating both linear and angular velocities correctly.
Both transforms and velocity transforms utilize a high-performance caching system to accelerate repeated lookups:
fn caching_tree() {
// Create a transform tree with custom cache settings
let tree = TransformTree::<f32>::with_cache_settings(
200, // Cache size (max number of entries)
Duration::from_secs(5) // Cache entry lifetime
);
// Lookup operations use the cache automatically
let velocity = tree.lookup_velocity("world", "robot", time);
// Cache is automatically invalidated when:
// - New transforms are added to the tree
// - Cache entries exceed their age limit
// - The cache reaches capacity (uses LRU eviction)
// Clear the cache manually if needed
tree.clear_cache();
// The cache is cleaned automatically at regular intervals,
// but you can trigger cleanup explicitly if needed
tree.cleanup_cache();
}
The velocity cache significantly improves performance for:
The cache keys include frame IDs, timestamp, and a hash of the transform path, ensuring correctness when the transform tree structure changes.