API Reference

UpperBodyEstimator

Per-frame skeleton estimation from camera pose plus tracked wrists, with tunable limb lengths.

class UpperBodyEstimator:
    def __init__(
        self,
        session=None,
        config: SkeletonConfig | None = None,
        R_optical_to_link: np.ndarray | None = None,
    )

Solve a 10-joint upper-body skeleton from the camera pose + detected wrist 3D positions using IK. See Skeleton estimation guide.

Constructor

ParamDefaultNotes
sessionNoneAn MCAPReader or anything with R_optical_to_link. Used to auto-fill the rotation.
configSkeletonConfig()Tunable limb lengths and offsets.
R_optical_to_linkfrom sessionExplicit (3, 3) rotation. Wins over session.

Methods

estimate

def estimate(
    self,
    frame,                # SyncedFrame
    hands=None,           # list[HandPose] or None
) -> SkeletonFrame | None

Returns None when frame.camera_pose is None, the skeleton can't be anchored without it.

reset

def reset(self) -> None

Currently a no-op; reserved for future temporal smoothing.

SkeletonConfig

@dataclass
class SkeletonConfig:
    neck_back: float = 0.10           # m
    neck_drop: float = 0.20           # m
    shoulder_drop: float = 0.12       # m
    neck_to_head_up: float = 0.10     # m
    neck_to_shoulder: float = 0.18    # m
    torso_drop: float = 0.45          # m

    upper_arm_ratio: float = 0.55     # fraction of arm_length
    arm_length: float = 0.60          # m, total shoulder→wrist

    up_axis: int = -1                 # -1 = auto-detect, 0/1/2 = X/Y/Z
    edges: list = field(default_factory=lambda: list(DEFAULT_EDGES))

All lengths in metres.

SkeletonFrame

@dataclass
class SkeletonFrame:
    joints: np.ndarray          # (10, 3), NaN for missing
    visible: np.ndarray         # (10,) bool
    edges: list[tuple[int, int]]
    fwd_horiz: np.ndarray | None = None  # (3,) horizontal forward
    up: np.ndarray | None = None         # (3,) world up

    def bone_lines(self) -> list[list[list[float]]]: ...
    def visible_joints(self) -> np.ndarray: ...      # (M, 3)

Joint indices

IndexConstantName
0J_HEADhead
1J_NECKneck
2J_SPINEspine
3J_L_SHOULDERl_shoulder
4J_L_ELBOWl_elbow
5J_L_WRISTl_wrist
6J_R_SHOULDERr_shoulder
7J_R_ELBOWr_elbow
8J_R_WRISTr_wrist
9J_MOUNT_CAMmount_cam

Default edges: shoulder→elbow→wrist (both sides), neck→both shoulders, spine ties shoulders, mount-cam→neck.

See also