DHB-TI: Time-Invariant Encoding
dhb_ti
DHB-TI: Time-invariant reparameterization.
Reparameterize a trajectory by a geometric progress variable (translational arc-length, angular, or hybrid) and resample at uniform progress knots so that DHB-DR/DHB-QR invariants are approximately independent of execution speed and sampling rate.
Progress variables
- translation: s_{i+1} = s_i + ||Δp_i||
- angular: θ_{i+1} = θ_i + ||Δr_i||
- hybrid: σ_{i+1} = σ_i + α||Δp_i|| + (1-α)||Δr_i||, α in [0,1]
Uniform knots σ_k = k * Σ/(M-1), then interpolate poses at σ_k (position spline, quat SLERP).
Classes
Functions
compute_progress
Compute cumulative progress along the trajectory.
positions: (N, 3), quaternions: (N, 4) wxyz. kind: 'translation' (arc-length), 'angular' (rotation magnitude), 'hybrid'. alpha: weight for translation in hybrid; (1-alpha) for rotation. Ignored if kind != 'hybrid'. min_step: minimum increment per segment to avoid degenerate progress (clamped).
Returns progress (N,) with progress[0] = 0.
Source code in src/dhb_xr/encoder/dhb_ti.py
encode_dhb_dr_ti
encode_dhb_dr_ti(
positions,
quaternions,
M,
progress_kind="hybrid",
alpha=0.5,
method=EncodingMethod.POSITION,
use_default_initial_frames=True,
init_pose=None,
dhb_method=DHBMethod.DOUBLE_REFLECTION,
min_step=_MIN_STEP,
**encode_kw,
)
Time-invariant encode: reparameterize by progress to M samples, then DHB-DR encode.
Returns same structure as encode_dhb_dr (linear_motion_invariants, angular_motion_invariants, initial_pose, ...).
Source code in src/dhb_xr/encoder/dhb_ti.py
encode_dhb_qr_ti
encode_dhb_qr_ti(
positions,
quaternions,
M,
progress_kind="hybrid",
alpha=0.5,
method=EncodingMethod.POSITION,
use_default_initial_frames=True,
init_pose=None,
min_step=_MIN_STEP,
**encode_kw,
)
Time-invariant encode: reparameterize by progress to M samples, then DHB-QR encode.
Returns same structure as encode_dhb_qr.
Source code in src/dhb_xr/encoder/dhb_ti.py
resample_by_progress
resample_by_progress(
positions, quaternions, M, progress_kind="hybrid", alpha=0.5, progress=None, min_step=_MIN_STEP
)
Resample trajectory to M poses at uniform progress knots.
progress_knots: σ_k = k * Σ/(M-1), k = 0,...,M-1. Positions interpolated with cubic spline in progress; orientations with SLERP.
Returns (positions_M, quaternions_M) (M, 3), (M, 4) wxyz.
Source code in src/dhb_xr/encoder/dhb_ti.py
Overview
DHB-TI (Time-Invariant) encoding creates speed-independent representations by reparameterizing trajectories by arc-length before encoding. This ensures that the same motion executed at different speeds produces similar invariants.
Main Functions
encode_dhb_dr_ti
def encode_dhb_dr_ti(
positions: np.ndarray,
quaternions: np.ndarray,
M: int,
progress_kind: str = "hybrid",
alpha: float = 0.5,
method: EncodingMethod = EncodingMethod.POSITION,
use_default_initial_frames: bool = True,
dhb_method: DHBMethod = DHBMethod.DOUBLE_REFLECTION,
robust_mode: bool = False,
) -> Dict[str, Any]:
Encode trajectory to time-invariant DHB-DR invariants.
Parameters:
positions: Trajectory positions (N, 3)quaternions: Trajectory quaternions (N, 4)M: Number of points in reparameterized trajectoryprogress_kind: Progress measure ("translation", "angular", "hybrid")alpha: Weight for hybrid progress (0=translation, 1=angular)- Other parameters same as
encode_dhb_dr
compute_progress
def compute_progress(
positions: np.ndarray,
quaternions: np.ndarray,
kind: str = "hybrid",
alpha: float = 0.5,
) -> np.ndarray:
Compute progress along trajectory for reparameterization.
resample_by_progress
def resample_by_progress(
positions: np.ndarray,
quaternions: np.ndarray,
M: int,
progress: Optional[np.ndarray] = None,
progress_kind: str = "hybrid",
alpha: float = 0.5,
) -> Tuple[np.ndarray, np.ndarray]:
Resample trajectory to M points at uniform progress intervals.
Time-Invariance Example
import numpy as np
from dhb_xr.encoder.dhb_ti import encode_dhb_dr_ti
from dhb_xr.core.types import EncodingMethod, DHBMethod
# Create base trajectory
t = np.linspace(0, 2*np.pi, 100)
positions = np.column_stack([np.cos(t), np.sin(t), t * 0.01])
quaternions = np.tile([1, 0, 0, 0], (100, 1))
# Encode at different speeds
speeds = [50, 100, 200] # Different numbers of points
results = []
for M in speeds:
result = encode_dhb_dr_ti(
positions, quaternions, M,
progress_kind="hybrid",
method=EncodingMethod.POSITION,
dhb_method=DHBMethod.DOUBLE_REFLECTION
)
results.append(result)
# Compare invariants (should be similar despite different speeds)
for i, (M, result) in enumerate(zip(speeds, results)):
print(f"Speed {i+1} (M={M}): linear shape {result['linear_motion_invariants'].shape}")
# Invariants should be very similar
diff_01 = np.linalg.norm(
results[0]['linear_motion_invariants'][:50] -
results[1]['linear_motion_invariants']
)
print(f"Difference between speed 1 and 2: {diff_01:.6f}")