Skip to main content

Crate tf_tree

Crate tf_tree 

Source
Expand description

std facade for the tf_tree transform engine.

Re-exports the tf_tree_core engine and adds the allocating conveniences: TreeBuilder, the Tree that owns a HeapArena, the plan-cached Tree::lookup, and Described, a Display wrapper that resolves error ids to frame names.

use tf_tree::{TreeBuilder, InterpPolicy, Stamp, Iso3};

// Topology is declared on the builder; `build()` sizes the arena from exactly
// these edges (static edges reserve no ring slots).
let tree = TreeBuilder::new()
    .static_edge("map", "odom", &Iso3::IDENTITY)
    .build()
    .expect("layout");

// map -> odom is a static identity, so the lookup is identity at any time.
// A typed binding pins the default `SystemDomain` (method-call inference does
// not apply a type parameter's default, so annotate the stamp once).
let now: Stamp = Stamp::from_nanos(0);
let t = tree.lookup("map", "odom", now).unwrap();
assert_eq!(t, Iso3::IDENTITY);

§Minimum supported Rust version

1.87, from [workspace.package] rust-version; just msrv checks this line against README.md, SUPPORT.md and every rust-version.

§Two stability tiers

The crate root is stable. tf_tree::unstable, behind the default-off unstable feature, holds what the arena layout shapes (docs/API.md §2.6, docs/PHASE5.md §1). On the stable tier use Tree::frames and Tree::edges (docs/API.md §3.2).

These pin that ArenaView, EdgeKind and EdgeMeta moved (gated by just test-doc-error-codes); one block each, so one absence cannot pass:

ⓘ
use tf_tree::ArenaView;
ⓘ
use tf_tree::EdgeKind;
ⓘ
use tf_tree::EdgeMeta;

EdgeWriter carries a lifetime (docs/API.md §2.1); OwnedWriter is the storable shape.

§no_std / std split

Arena-generic items (Plan, Step, Guard, Stamp, Domain, Query) live in the no_std tf_tree_core; this crate adds the heap arena, Tree::lookup’s per-thread plan cache and Described.

Tree is Send + Sync but not Clone: it owns its arena backing and a participant-table slot (DEFAULT_MAX_PARTICIPANTS). Share it with an Arc:

use std::sync::Arc;
use tf_tree::{Iso3, Stamp, TreeBuilder};

let tree = Arc::new(
    TreeBuilder::new()
        .static_edge("map", "odom", &Iso3::IDENTITY)
        .build()
        .expect("layout"),
);
let reader = Arc::clone(&tree);
let joined = std::thread::spawn(move || {
    let now: Stamp = Stamp::from_nanos(0);
    reader.lookup("map", "odom", now)
})
.join()
.expect("reader thread");
assert_eq!(joined.unwrap(), Iso3::IDENTITY);

docs/API.md §2.2.

§Set lto = "thin" and codegen-units = 1 in your release profile

[profile.release]
lto = "thin"
codegen-units = 1

Worth about 25% of a depth-3 lookup, since Plan::at crosses a crate boundary; see docs/API.md §2.3.

Modules§

dualquat
Fast SE(3) screw interpolation via unit dual-quaternion powers.
unstable
The unstable tier (docs/API.md §2.6); enabling unstable is the waiver. The unstable tier. Nothing in this module is covered by semver.

Structs§

AdaptiveScratch
Caller-provided scratch for Plan::at_adaptive, sized for the maximum knot set.
Capacity
Ring capacity for one dynamic edge, always a power of two.
Described
A LookupError paired with the Tree that can resolve its ids to names.
EdgeCfg
Per-edge configuration for TreeBuilder::dynamic_edge.
EdgeId
Stable identity of an edge (index into the edge table); append-only, removal is tombstoning (invariant 1 / D10).
EdgeWriter
A claimed edge: the arena record, and the lease that makes its holder’s death observable (docs/PHASE2.md §6.1, docs/decisions/0005 §5).
ErrBound
The per-component error tolerance for Plan::at_adaptive; build with ErrBound::new.
Extrapolated
A pose, and how far past the plan’s newest common sample it was extrapolated (0039): no accessor yields the pose alone.
FrameId
Stable identity of a frame: a NonZeroU32 (0 is the root / “no parent” sentinel). Append-only (invariant 1 / D10): never reused.
FrozenHeader
The .tft container header — docs/PHASE5.md §2.3, NORMATIVE: 128 bytes with 8 reserved, pinned by frozen_header_has_no_padding.
Guard
A batch-evaluation handle: it borrows the arena and pins the topology generation once, so a run of lookups validates against one snapshot.
Iso3
A rigid-body transform in SE(3): a rotation q followed by a translation t. T_parent_child — applying it to a point in child yields the point in parent.
LerpSlerp
tf2-compatible interpolation: translation LERP + rotation SLERP.
Open
The docs/PHASE2.md §3.2 builder.
OwnedWriter
An EdgeWriter that owns its tree — the claim shape for a writer that is stored rather than scoped (docs/decisions/0017, docs/API.md §2.1).
Plan
A compiled lookup(target, source) path.
Publisher
Exclusive writer handle for one edge.
Quat
Unit quaternion, Hamilton convention, scalar (w) first.
Sample
A pose and its derivatives at one instant (docs/PHASE4.md §2.2); the twist is body-frame, in the plan’s source frame (tf_tree_math::twist).
ScLerp
SE(3) screw-geodesic interpolation — the default policy.
SensorDomain
A sensor’s own clock, tag 1.
SimDomain
Simulated time (a /clock publisher, bag replay or physics engine), tag 2.
Stamp
A nanosecond timestamp in domain D; the phantom D costs nothing at runtime.
SteadyDomain
A steady, monotone clock, tag 3 (docs/PHASE5.md §6, TFT019; docs/API.md §5.3).
SystemDomain
The default domain: the host system clock (CLOCK_REALTIME-like), tag 0.
Tree
A transform tree: a fixed-capacity arena plus the ergonomic operations for publishing samples and looking up transforms. Build one with TreeBuilder.
TreeBuilder
Builder for a Tree.
Twist
A body-frame (right) twist: angular velocity ω (rad/s) and linear velocity v (m/s), both in the moving frame. 48 bytes, repr(C), no padding: Pod.
Vec3
A point or vector in R³.

Enums§

AttachMode
Shared-memory attachment surface (Phase 2). Linux-only, behind --features shm. How a process attaches to an existing segment.
AwaitError
Why Tree::await_frames could not produce ids.
BuildError
Failure building a Tree from a TreeBuilder.
ClaimApiError
Failure claiming an edge for writing.
ClaimError
A failed attempt to claim exclusive write access to an edge.
CreatePolicy
Re-exported so a caller need not depend on tf_tree_ipc to name the policy. What open() should do when no arena exists.
EnvVar
An environment variable the rendezvous reads.
ExtrapPolicy
What to do when the requested stamp is newer than every published sample.
FrameError
A failed frame interning.
FrozenError
Why a .tft could not be written or opened. Copy and String-free (docs/PROJECT.md §5).
FrozenFileError
Why a .tft could not be opened or written.
HelloStatus
Outcome of a handshake, as carried in HelloResponse::status.
Inheritance
How Tree::inherit_ownership resolved (§3.5).
InterpPolicy
Selects an interpolation policy from an edge’s stored discriminant (crate::edge::EdgeRecord::interp). Not #[non_exhaustive]; an unknown discriminant collapses to the default in InterpPolicy::from_u8.
IpcError
Everything the rendezvous substrate can fail at.
Layout
How a transform is written into a caller’s buffer.
LayoutError
Error returned when an ArenaLayout cannot be constructed.
LockRole
Which lock-file role a failing operation was for.
LookupError
A lookup or sample failure, from the read path and plan compilation and evaluation (crate::plan). Implements Display and core::error::Error (0040).
NameProblem
Why an arena name was rejected.
OpenError
Why Open::open could not produce a Tree.
ParticipantError
Why a process could not join the arena.
ProcError
Reading a process’s identity out of /proc.
ProcParseError
A /proc/<pid>/stat parse failure, distinct from a read failure.
PushError
A failed push onto an edge’s sample ring.
Query
A temporal query against a compiled Plan (#[non_exhaustive]).
ReparentError
Failure re-parenting a frame at runtime.
RuntimeDirSource
Which candidate of the docs/PHASE2.md §3.1 resolution order a directory came from.
ShmError
Shared-memory attachment surface (Phase 2). Linux-only, behind --features shm. Everything that can go wrong obtaining or validating a shared segment.
Step
One step of a compiled plan.
TopologyError
A failed topology mutation.
WireError
Why a datagram could not be decoded, as distinct from attach policy.

Constants§

ARENA_FILE_ALIGN
Alignment of the arena image within the file (§2.3): 2 MiB, not one page, because a huge page needs congruent virtual address and file offset.
CRASH_SITES
Every docs/PHASE2.md §11.3 crash point compiled into this crate.
MAX_ADAPTIVE_DEPTH
Maximum bisection recursion depth in Plan::at_adaptive.
MAX_DEPTH
Maximum length of a compiled plan: the plan::Step slots a plan::Plan carries by value, counted after constant folding; not the walk’s bound (MAX_PATH_EDGES). Set by 0034.
MAX_KNOTS
Maximum number of knots Plan::at_adaptive may emit.
MAX_PATH_EDGES
Maximum number of raw path edges plan::compile walks, across both sides of the lowest common ancestor. Exceeding it, or folding past MAX_DEPTH, is LookupError::TreeTooDeep; depth tells them apart (docs/PHASE1.md §7.1).

Traits§

Domain
A time domain: a compile-time marker carrying a runtime Domain::TAG byte (docs/PROJECT.md §5 D9; docs/PHASE1.md §8).
Interp
Interpolate between two poses a (at s = 0) and b (at s = 1).

Functions§

arena_format_version
This build’s arena format version (docs/PHASE5.md §1).
arena_layout_hash
This build’s arena layout hash (geometry); checked on attach with the format version.
counters_compiled_in
Whether this build compiled docs/PHASE5.md §5’s diagnostic counters in.
exp_se3
SE(3) exponential: map a twist ξ = [ω, v] to a rigid transform.
exp_so3
SO(3) exponential: map a rotation vector ω (axis × angle) to a unit quaternion.
log_se3
SE(3) logarithm: map a rigid transform to its twist ξ = [ω, v].
log_so3
SO(3) logarithm: map a unit quaternion to its rotation vector ω in the principal branch |ω| ∈ [0, π].
open
Join the running arena, read-only.
quat_from_rot3
The unit quaternion of a row-major 3×3 rotation matrix.
slerp
Shortest-arc spherical linear interpolation of two unit quaternions.
write_affine32
Write iso as a row-major 3x4 f32 affine.
write_mat4
Write iso as a row-major 4x4 f64 matrix.
write_quat
Write iso as [qw qx qy qz tx ty tz].
write_quat_twist
Write iso and twist as [qw qx qy qz tx ty tz | ωx ωy ωz vx vy vz].