transforms/
lib.rs

1//! A blazingly fast and efficient coordinate transform library for robotics and computer vision applications.
2//!
3//! This library provides functionality for managing coordinate transformations between different frames
4//! of reference.
5//!
6//! # Architecture
7//!
8//! The library is organized around three main components:
9//!
10//! - **Registry**: The main interface for managing transforms
11//! - **Buffer**: Internal storage for transforms between specific frames
12//! - **Transform**: The core data structure representing spatial transformations
13//!
14//! # Features
15//!
16//! - **Transform Interpolation**: Smooth interpolation between transforms at different timestamps
17//! - **Transform Chaining**: Automatic computation of transforms between indirectly connected frames
18//! - **Static Transforms**: Submitting a timestamp at t=0 will short-circuit the lookup and always return the t=0 transform.
19//! - **Time-based Buffer Management**: Automatic cleanup of old transforms is available with feature = "std", which is default enabled. If the library is used as ```no_std``` then manual cleanup is required. See the examples.
20//!
21//! # Non-Goals
22//!
23//! This library intentionally limits its scope to rigid body transformations (translation and rotation)
24//! commonly used in robotics and computer vision. The following transformations are explicitly not
25//! supported and will not be considered for future implementation:
26//!
27//! - Scaling transformations
28//! - Skew transformations
29//! - Perspective transformations
30//! - Non-rigid transformations
31//! - Affine transformations beyond rigid body motion
32//!
33//! This decision helps maintain the library's focus on its core purpose: providing fast and efficient
34//! rigid body transformations for robotics applications. For more general transformation needs,
35//! consider using a computer graphics or linear algebra library instead.
36//!
37//! # Examples
38//!
39//! ```rust
40//! use transforms::{
41//!     geometry::{Quaternion, Transform, Vector3},
42//!     time::Timestamp,
43//!     Registry,
44//! };
45//!
46//! # #[cfg(feature = "std")]
47//! use core::time::Duration;
48//! # #[cfg(feature = "std")]
49//! let mut registry = Registry::new(Duration::from_secs(60));
50//! # #[cfg(feature = "std")]
51//! let timestamp = Timestamp::now();
52//!
53//! # #[cfg(not(feature = "std"))]
54//! let mut registry = Registry::new();
55//! # #[cfg(not(feature = "std"))]
56//! let timestamp = Timestamp::zero();
57//!
58//! // Create a transform from frame "base" to frame "sensor"
59//! let transform = Transform {
60//!     translation: Vector3::new(1.0, 0.0, 0.0),
61//!     rotation: Quaternion::identity(),
62//!     timestamp,
63//!     parent: "base".into(),
64//!     child: "sensor".into(),
65//! };
66//!
67//! // Add the transform to the registry
68//! registry.add_transform(transform);
69//!
70//! // Retrieve the transform
71//! let result = registry.get_transform("base", "sensor", timestamp).unwrap();
72//!
73//! # #[cfg(not(feature = "std"))]
74//! // Delete old transforms
75//! # #[cfg(not(feature = "std"))]
76//! registry.delete_transforms_before(timestamp);
77//! ```
78//!
79//! # Transform and Data Transformation
80//!
81//! The library provides a `Transform` type that represents spatial transformations between different
82//! coordinate frames. Transforms follow the common robotics convention where transformations are
83//! considered from child to parent frame (e.g., from sensor frame to base frame, or from base frame
84//! to map frame).
85//!
86//! To make your data transformable between different coordinate frames, implement the `Transformable`
87//! trait. This allows you to easily transform your data using the transforms stored in the registry.
88//! ```rust
89//! use transforms::{
90//!     geometry::{Point, Quaternion, Transform, Vector3},
91//!     time::Timestamp,
92//!     Transformable,
93//! };
94//!
95//! // Create a point in the camera frame
96//! let mut point = Point {
97//!     position: Vector3::new(1.0, 0.0, 0.0),
98//!     orientation: Quaternion::identity(),
99//! # #[cfg(not(feature = "std"))]
100//!     timestamp: Timestamp::zero(),
101//! # #[cfg(feature = "std")]
102//!     timestamp: Timestamp::now(),
103//!     frame: "camera".into(),
104//! };
105//!
106//! // Define transform from camera to base frame
107//! let transform = Transform {
108//!     translation: Vector3::new(0.0, 1.0, 0.0),
109//!     rotation: Quaternion::identity(),
110//!     timestamp: point.timestamp,
111//!     parent: "base".into(),
112//!     child: "camera".into(),
113//! };
114//!
115//! // Transform the point from camera frame to base frame
116//! point.transform(&transform).unwrap();
117//! assert_eq!(point.position.x, 1.0);
118//! assert_eq!(point.position.y, 1.0);
119//! ```
120//!
121//! The transform convention follows the common robotics practice where data typically needs to be
122//! transformed from specific sensor reference frames "up" to more general frames like the robot's
123//! base frame or a global map frame.
124//!
125//! # Relationship with ROS2's tf2
126//!
127//! This library draws inspiration from ROS2's tf2 (Transform Framework 2), a widely-used
128//! transform library in the robotics community. While this crate aims to solve the same
129//! fundamental problem of transformation tracking, it does so in its own way.
130//!
131//! ## Similarities with tf2
132//!
133//! - Maintains relationships between coordinate frames in a tree structure
134//! - Buffers transforms over time
135//! - Supports transform lookups between arbitrary frames
136//! - Handles interpolation between transforms
137//!
138//! ## Key Differences
139//!
140//! This library:
141//! - Is a pure Rust implementation, not a wrapper around tf2
142//! - Makes no attempt to perfectly match the ROS2/tf2 API
143//! - Focuses on providing an ergonomic Rust-first experience
144//! - Is independent of ROS2's middleware and communication system
145//!
146//! While the core concepts and functionality align with tf2, this library prioritizes
147//! optimal usage for rust software over maintaining API compatibility with ROS2's tf2. Users
148//! familiar with tf2 will find the concepts familiar, but the implementation details
149//! and API design follow Rust idioms and best practices as best as it can.
150//!
151//! # Performance Considerations
152//!
153//! - Transform lookups are optimized for O(log n) time complexity
154//! - Automatic cleanup of old transforms prevents unbounded memory growth
155//!
156//! # Safety
157//!
158//! This crate uses `#![forbid(unsafe_code)]` to ensure memory safety through pure Rust implementations.
159#![forbid(unsafe_code)]
160#![warn(clippy::pedantic)]
161#![warn(clippy::alloc_instead_of_core)]
162#![warn(clippy::std_instead_of_core)]
163#![cfg_attr(test, allow(clippy::similar_names))]
164#![cfg_attr(test, allow(clippy::too_many_lines))]
165#![cfg_attr(not(feature = "std"), no_std)]
166
167extern crate alloc;
168pub mod core;
169pub mod errors;
170pub mod geometry;
171pub mod time;
172pub use core::Registry;
173pub use geometry::{Transform, Transformable};