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
| Param | Default | Notes |
|---|---|---|
session | None | An MCAPReader or anything with R_optical_to_link. Used to auto-fill the rotation. |
config | SkeletonConfig() | Tunable limb lengths and offsets. |
R_optical_to_link | from session | Explicit (3, 3) rotation. Wins over session. |
Methods
estimate
def estimate(
self,
frame, # SyncedFrame
hands=None, # list[HandPose] or None
) -> SkeletonFrame | NoneReturns None when frame.camera_pose is None, the skeleton can't be anchored without it.
reset
def reset(self) -> NoneCurrently 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
| Index | Constant | Name |
|---|---|---|
| 0 | J_HEAD | head |
| 1 | J_NECK | neck |
| 2 | J_SPINE | spine |
| 3 | J_L_SHOULDER | l_shoulder |
| 4 | J_L_ELBOW | l_elbow |
| 5 | J_L_WRIST | l_wrist |
| 6 | J_R_SHOULDER | r_shoulder |
| 7 | J_R_ELBOW | r_elbow |
| 8 | J_R_WRIST | r_wrist |
| 9 | J_MOUNT_CAM | mount_cam |
Default edges: shoulder→elbow→wrist (both sides), neck→both shoulders, spine ties shoulders, mount-cam→neck.
See also
- Skeleton estimation guide
SyncedFrame- Visualization,
viz.log_frame(..., skeleton=...).