Skip to content

Core Types

types

Core data types for SE(3) trajectories and DHB invariants.

Classes

DHBMethod

Bases: Enum

DHB encoding method.

Source code in src/dhb_xr/core/types.py
class DHBMethod(Enum):
    """DHB encoding method."""

    ORIGINAL = "original"  # 3 invariants per component (magnitude + 2 angles)
    DOUBLE_REFLECTION = "double_reflection"  # 4 invariants (magnitude + Euler XYZ)
    QUATERNION = "quaternion"  # 5 invariants (magnitude + unit quaternion)

EncodingMethod

Bases: Enum

Encoding method for initial frame computation.

Source code in src/dhb_xr/core/types.py
class EncodingMethod(Enum):
    """Encoding method for initial frame computation."""

    POSITION = "pos"  # Position-based encoding: use initial position for frame origin
    VELOCITY = "vel"  # Velocity-based encoding: use first position difference for frame origin

InvariantSequence dataclass

DHB invariant sequence (linear + angular).

Source code in src/dhb_xr/core/types.py
@dataclass
class InvariantSequence:
    """DHB invariant sequence (linear + angular)."""

    linear: np.ndarray  # (N-1, k) k=3 original, k=4 DR, k=5 QR
    angular: np.ndarray  # (N-1, k)
    method: Literal["dhb_dr", "dhb_qr", "original"]
    initial_pose: Dict[str, np.ndarray]
    linear_frame_initial: Optional[np.ndarray] = None  # (4,4) if available
    angular_frame_initial: Optional[np.ndarray] = None

    def __post_init__(self) -> None:
        self.linear = np.asarray(self.linear, dtype=np.float64)
        self.angular = np.asarray(self.angular, dtype=np.float64)
        assert self.linear.shape[0] == self.angular.shape[0]
        assert self.linear.shape[1] == self.angular.shape[1]

    @property
    def length(self) -> int:
        return self.linear.shape[0]

    @property
    def invariant_dim(self) -> int:
        return self.linear.shape[1]

    def concatenated(self) -> np.ndarray:
        """(N-1, 2*k) linear and angular stacked."""
        return np.concatenate([self.linear, self.angular], axis=1)
Functions
concatenated
concatenated()

(N-1, 2*k) linear and angular stacked.

Source code in src/dhb_xr/core/types.py
def concatenated(self) -> np.ndarray:
    """(N-1, 2*k) linear and angular stacked."""
    return np.concatenate([self.linear, self.angular], axis=1)

SE3Pose dataclass

Single SE(3) pose: position and quaternion (w, x, y, z).

Source code in src/dhb_xr/core/types.py
@dataclass
class SE3Pose:
    """Single SE(3) pose: position and quaternion (w, x, y, z)."""

    position: np.ndarray  # (3,)
    quaternion: np.ndarray  # (4,) wxyz scalar-first

    def __post_init__(self) -> None:
        self.position = np.asarray(self.position, dtype=np.float64).reshape(3)
        self.quaternion = np.asarray(self.quaternion, dtype=np.float64).reshape(4)
        nq = np.linalg.norm(self.quaternion)
        if nq > 1e-10:
            self.quaternion = self.quaternion / nq

    def to_dict(self) -> Dict[str, np.ndarray]:
        return {"position": self.position.copy(), "quaternion": self.quaternion.copy()}

    @classmethod
    def from_dict(cls, d: Dict[str, np.ndarray]) -> SE3Pose:
        return cls(position=d["position"], quaternion=d["quaternion"])

Trajectory dataclass

SE(3) trajectory: sequence of poses and optional timestamps.

Source code in src/dhb_xr/core/types.py
@dataclass
class Trajectory:
    """SE(3) trajectory: sequence of poses and optional timestamps."""

    poses: List[SE3Pose]
    timestamps: Optional[np.ndarray] = None

    def __len__(self) -> int:
        return len(self.poses)

    @property
    def positions(self) -> np.ndarray:
        """(N, 3) position array."""
        return np.array([p.position for p in self.poses])

    @property
    def quaternions(self) -> np.ndarray:
        """(N, 4) quaternion array (wxyz)."""
        return np.array([p.quaternion for p in self.poses])

    @classmethod
    def from_arrays(
        cls,
        positions: np.ndarray,
        quaternions: np.ndarray,
        timestamps: Optional[np.ndarray] = None,
    ) -> Trajectory:
        """Build from (N,3) positions and (N,4) quaternions (wxyz)."""
        n = len(positions)
        assert len(quaternions) == n
        poses = [
            SE3Pose(position=positions[i], quaternion=quaternions[i])
            for i in range(n)
        ]
        return cls(poses=poses, timestamps=timestamps)
Attributes
positions property
positions

(N, 3) position array.

quaternions property
quaternions

(N, 4) quaternion array (wxyz).

Functions
from_arrays classmethod
from_arrays(positions, quaternions, timestamps=None)

Build from (N,3) positions and (N,4) quaternions (wxyz).

Source code in src/dhb_xr/core/types.py
@classmethod
def from_arrays(
    cls,
    positions: np.ndarray,
    quaternions: np.ndarray,
    timestamps: Optional[np.ndarray] = None,
) -> Trajectory:
    """Build from (N,3) positions and (N,4) quaternions (wxyz)."""
    n = len(positions)
    assert len(quaternions) == n
    poses = [
        SE3Pose(position=positions[i], quaternion=quaternions[i])
        for i in range(n)
    ]
    return cls(poses=poses, timestamps=timestamps)

Key Classes and Enums

DHBMethod

from dhb_xr.core.types import DHBMethod

class DHBMethod(Enum):
    """DHB encoding method variants."""
    DOUBLE_REFLECTION = "double_reflection"  # 4 values per component (Euler-based)
    ORIGINAL = "original"                    # 3 values per component (original DHB)

EncodingMethod

from dhb_xr.core.types import EncodingMethod

class EncodingMethod(Enum):
    """Encoding method for initial frame computation."""
    POSITION = "pos"  # Position-based encoding: use initial position for frame origin
    VELOCITY = "vel"  # Velocity-based encoding: use first position difference for frame origin

Usage

from dhb_xr.core.types import DHBMethod, EncodingMethod

# Use in encoding functions
result = encode_dhb_dr(
    positions, quaternions,
    method=EncodingMethod.POSITION,
    dhb_method=DHBMethod.DOUBLE_REFLECTION
)