Motion Representation#
Motion representation utilities and kinematics helpers.
Skeleton#
Skeleton definitions and utilities used across kimodo.
- class kimodo.skeleton.SkeletonBase(folder=None, name=None, load=True, **kwargs)[source]#
Bases:
<Mock object at 0x7c5620423f40>[]Base class that stores a skeleton hierarchy and helper metadata.
Subclasses define the static joint layout (joint names and parent links) and semantic groups (feet, hands, hips). This class builds index mappings, parent tensors, and convenience helpers used by kinematics, constraints, and motion conversion utilities.
- bone_order_names_with_parents = None#
- hip_joint_names = None#
- __init__(folder=None, name=None, load=True, **kwargs)[source]#
Initialize a skeleton instance and optional neutral-pose assets.
- Parameters:
folder – Folder containing serialized skeleton assets (for example joints.p and optional standard_t_pose_global_offsets_rots.p).
name – Optional runtime name used to validate subclass compatibility.
load – Whether to load tensor assets from folder.
**kwargs – Unused extra config keys kept for config compatibility.
- name = None#
- root_idx = None#
- bone_order_names_no_root = None#
- foot_joint_names = None#
- foot_joint_idx = None#
- hip_joint_idx = None#
- expand_joint_names(joint_names)[source]#
Expand base EE names [LeftFoot, RightFoot, LeftHand, RightHand] actual joint names to constrain position and rotations.
- Parameters:
joint_names – list of list of base EE names to constrain
- Returns:
list of list of joint names to constrain rotations pos_joint_names: list of list of joint names to constrain positions
- Return type:
rot_joint_names
- expand_joint_names_batched(joint_names)[source]#
Expand base EE names [LeftFoot, RightFoot, LeftHand, RightHand] actual joint names to constrain position and rotations.
- Parameters:
joint_names – list of list of base EE names to constrain
- Returns:
list of list of joint names to constrain rotations pos_joint_names: list of list of joint names to constrain positions
- Return type:
rot_joint_names
- property device#
Device where neutral-joint buffers are stored.
Returns ‘cpu’ if neutral_joints is not present.
- fk(local_joint_rots, root_positions)[source]#
Run forward kinematics for this skeleton layout.
- Parameters:
local_joint_rots – Local joint rotation matrices with shape (…, J, 3, 3).
root_positions – Root translations with shape (…, 3).
- Returns:
Tuple of (global_joint_rots, posed_joints, posed_joints_norootpos).
- to_standard_tpose(local_rot_mats)[source]#
Convert local rotations into the skeleton’s standard T-pose frame.
- from_standard_tpose(local_rot_mats)[source]#
Convert local rotations from the skeleton’s standard T-pose frame.
- global_rots_to_local_rots(global_joint_rots)[source]#
Convert global joint rotations to local rotations for this hierarchy.
- get_skel_slice(skeleton)[source]#
Build index mapping from another skeleton into this skeleton order.
- Parameters:
skeleton – Source skeleton whose joint order is used by input tensors.
- Returns:
A list of source indices ordered as self.bone_order_names.
- Raises:
ValueError – If at least one required joint is missing from skeleton.
- class kimodo.skeleton.G1Skeleton34(folder=None, name=None, load=True, **kwargs)[source]#
Bases:
SkeletonBaseUnitree G1 skeleton with 32 articulated joints plus 2 toe endpoints.
- name = 'g1skel34'#
- right_foot_joint_names = ['right_ankle_roll_skel', 'right_toe_base']#
- left_foot_joint_names = ['left_ankle_roll_skel', 'left_toe_base']#
- right_hand_joint_names = ['right_wrist_yaw_skel', 'right_hand_roll_skel']#
- left_hand_joint_names = ['left_wrist_yaw_skel', 'left_hand_roll_skel']#
- hip_joint_names = ['right_hip_pitch_skel', 'left_hip_pitch_skel']#
- bone_order_names_with_parents = [('pelvis_skel', None), ('left_hip_pitch_skel', 'pelvis_skel'), ('left_hip_roll_skel', 'left_hip_pitch_skel'), ('left_hip_yaw_skel', 'left_hip_roll_skel'), ('left_knee_skel', 'left_hip_yaw_skel'), ('left_ankle_pitch_skel', 'left_knee_skel'), ('left_ankle_roll_skel', 'left_ankle_pitch_skel'), ('left_toe_base', 'left_ankle_roll_skel'), ('right_hip_pitch_skel', 'pelvis_skel'), ('right_hip_roll_skel', 'right_hip_pitch_skel'), ('right_hip_yaw_skel', 'right_hip_roll_skel'), ('right_knee_skel', 'right_hip_yaw_skel'), ('right_ankle_pitch_skel', 'right_knee_skel'), ('right_ankle_roll_skel', 'right_ankle_pitch_skel'), ('right_toe_base', 'right_ankle_roll_skel'), ('waist_yaw_skel', 'pelvis_skel'), ('waist_roll_skel', 'waist_yaw_skel'), ('waist_pitch_skel', 'waist_roll_skel'), ('left_shoulder_pitch_skel', 'waist_pitch_skel'), ('left_shoulder_roll_skel', 'left_shoulder_pitch_skel'), ('left_shoulder_yaw_skel', 'left_shoulder_roll_skel'), ('left_elbow_skel', 'left_shoulder_yaw_skel'), ('left_wrist_roll_skel', 'left_elbow_skel'), ('left_wrist_pitch_skel', 'left_wrist_roll_skel'), ('left_wrist_yaw_skel', 'left_wrist_pitch_skel'), ('left_hand_roll_skel', 'left_wrist_yaw_skel'), ('right_shoulder_pitch_skel', 'waist_pitch_skel'), ('right_shoulder_roll_skel', 'right_shoulder_pitch_skel'), ('right_shoulder_yaw_skel', 'right_shoulder_roll_skel'), ('right_elbow_skel', 'right_shoulder_yaw_skel'), ('right_wrist_roll_skel', 'right_elbow_skel'), ('right_wrist_pitch_skel', 'right_wrist_roll_skel'), ('right_wrist_yaw_skel', 'right_wrist_pitch_skel'), ('right_hand_roll_skel', 'right_wrist_yaw_skel')]#
- class kimodo.skeleton.SOMASkeleton30(folder=None, name=None, load=True, **kwargs)[source]#
Bases:
SkeletonBaseCompact 30-joint SOMA variant with reduced hand and end-effector detail.
- name = 'somaskel30'#
- right_foot_joint_names = ['RightFoot', 'RightToeBase']#
- left_foot_joint_names = ['LeftFoot', 'LeftToeBase']#
- right_hand_joint_names = ['RightHand', 'RightHandMiddleEnd']#
- left_hand_joint_names = ['LeftHand', 'LeftHandMiddleEnd']#
- hip_joint_names = ['RightLeg', 'LeftLeg']#
- bone_order_names_with_parents = [('Hips', None), ('Spine1', 'Hips'), ('Spine2', 'Spine1'), ('Chest', 'Spine2'), ('Neck1', 'Chest'), ('Neck2', 'Neck1'), ('Head', 'Neck2'), ('Jaw', 'Head'), ('LeftEye', 'Head'), ('RightEye', 'Head'), ('LeftShoulder', 'Chest'), ('LeftArm', 'LeftShoulder'), ('LeftForeArm', 'LeftArm'), ('LeftHand', 'LeftForeArm'), ('LeftHandThumbEnd', 'LeftHand'), ('LeftHandMiddleEnd', 'LeftHand'), ('RightShoulder', 'Chest'), ('RightArm', 'RightShoulder'), ('RightForeArm', 'RightArm'), ('RightHand', 'RightForeArm'), ('RightHandThumbEnd', 'RightHand'), ('RightHandMiddleEnd', 'RightHand'), ('LeftLeg', 'Hips'), ('LeftShin', 'LeftLeg'), ('LeftFoot', 'LeftShin'), ('LeftToeBase', 'LeftFoot'), ('RightLeg', 'Hips'), ('RightShin', 'RightLeg'), ('RightFoot', 'RightShin'), ('RightToeBase', 'RightFoot')]#
- property somaskel77#
- class kimodo.skeleton.SOMASkeleton77(folder=None, name=None, load=True, **kwargs)[source]#
Bases:
SkeletonBaseHigh-detail 77-joint SOMA skeleton with full finger and toe chains.
- name = 'somaskel77'#
- right_foot_joint_names = ['RightFoot', 'RightToeBase', 'RightToeEnd']#
- left_foot_joint_names = ['LeftFoot', 'LeftToeBase', 'LeftToeEnd']#
- right_hand_joint_names = ['RightHand', 'RightHandThumb1', 'RightHandThumb2', 'RightHandThumb3', 'RightHandThumbEnd', 'RightHandIndex1', 'RightHandIndex2', 'RightHandIndex3', 'RightHandIndex4', 'RightHandIndexEnd', 'RightHandMiddle1', 'RightHandMiddle2', 'RightHandMiddle3', 'RightHandMiddle4', 'RightHandMiddleEnd', 'RightHandRing1', 'RightHandRing2', 'RightHandRing3', 'RightHandRing4', 'RightHandRingEnd', 'RightHandPinky1', 'RightHandPinky2', 'RightHandPinky3', 'RightHandPinky4', 'RightHandPinkyEnd']#
- left_hand_joint_names = ['LeftHand', 'LeftHandThumb1', 'LeftHandThumb2', 'LeftHandThumb3', 'LeftHandThumbEnd', 'LeftHandIndex1', 'LeftHandIndex2', 'LeftHandIndex3', 'LeftHandIndex4', 'LeftHandIndexEnd', 'LeftHandMiddle1', 'LeftHandMiddle2', 'LeftHandMiddle3', 'LeftHandMiddle4', 'LeftHandMiddleEnd', 'LeftHandRing1', 'LeftHandRing2', 'LeftHandRing3', 'LeftHandRing4', 'LeftHandRingEnd', 'LeftHandPinky1', 'LeftHandPinky2', 'LeftHandPinky3', 'LeftHandPinky4', 'LeftHandPinkyEnd']#
- hip_joint_names = ['RightLeg', 'LeftLeg']#
- bone_order_names_with_parents = [('Hips', None), ('Spine1', 'Hips'), ('Spine2', 'Spine1'), ('Chest', 'Spine2'), ('Neck1', 'Chest'), ('Neck2', 'Neck1'), ('Head', 'Neck2'), ('HeadEnd', 'Head'), ('Jaw', 'Head'), ('LeftEye', 'Head'), ('RightEye', 'Head'), ('LeftShoulder', 'Chest'), ('LeftArm', 'LeftShoulder'), ('LeftForeArm', 'LeftArm'), ('LeftHand', 'LeftForeArm'), ('LeftHandThumb1', 'LeftHand'), ('LeftHandThumb2', 'LeftHandThumb1'), ('LeftHandThumb3', 'LeftHandThumb2'), ('LeftHandThumbEnd', 'LeftHandThumb3'), ('LeftHandIndex1', 'LeftHand'), ('LeftHandIndex2', 'LeftHandIndex1'), ('LeftHandIndex3', 'LeftHandIndex2'), ('LeftHandIndex4', 'LeftHandIndex3'), ('LeftHandIndexEnd', 'LeftHandIndex4'), ('LeftHandMiddle1', 'LeftHand'), ('LeftHandMiddle2', 'LeftHandMiddle1'), ('LeftHandMiddle3', 'LeftHandMiddle2'), ('LeftHandMiddle4', 'LeftHandMiddle3'), ('LeftHandMiddleEnd', 'LeftHandMiddle4'), ('LeftHandRing1', 'LeftHand'), ('LeftHandRing2', 'LeftHandRing1'), ('LeftHandRing3', 'LeftHandRing2'), ('LeftHandRing4', 'LeftHandRing3'), ('LeftHandRingEnd', 'LeftHandRing4'), ('LeftHandPinky1', 'LeftHand'), ('LeftHandPinky2', 'LeftHandPinky1'), ('LeftHandPinky3', 'LeftHandPinky2'), ('LeftHandPinky4', 'LeftHandPinky3'), ('LeftHandPinkyEnd', 'LeftHandPinky4'), ('RightShoulder', 'Chest'), ('RightArm', 'RightShoulder'), ('RightForeArm', 'RightArm'), ('RightHand', 'RightForeArm'), ('RightHandThumb1', 'RightHand'), ('RightHandThumb2', 'RightHandThumb1'), ('RightHandThumb3', 'RightHandThumb2'), ('RightHandThumbEnd', 'RightHandThumb3'), ('RightHandIndex1', 'RightHand'), ('RightHandIndex2', 'RightHandIndex1'), ('RightHandIndex3', 'RightHandIndex2'), ('RightHandIndex4', 'RightHandIndex3'), ('RightHandIndexEnd', 'RightHandIndex4'), ('RightHandMiddle1', 'RightHand'), ('RightHandMiddle2', 'RightHandMiddle1'), ('RightHandMiddle3', 'RightHandMiddle2'), ('RightHandMiddle4', 'RightHandMiddle3'), ('RightHandMiddleEnd', 'RightHandMiddle4'), ('RightHandRing1', 'RightHand'), ('RightHandRing2', 'RightHandRing1'), ('RightHandRing3', 'RightHandRing2'), ('RightHandRing4', 'RightHandRing3'), ('RightHandRingEnd', 'RightHandRing4'), ('RightHandPinky1', 'RightHand'), ('RightHandPinky2', 'RightHandPinky1'), ('RightHandPinky3', 'RightHandPinky2'), ('RightHandPinky4', 'RightHandPinky3'), ('RightHandPinkyEnd', 'RightHandPinky4'), ('LeftLeg', 'Hips'), ('LeftShin', 'LeftLeg'), ('LeftFoot', 'LeftShin'), ('LeftToeBase', 'LeftFoot'), ('LeftToeEnd', 'LeftToeBase'), ('RightLeg', 'Hips'), ('RightShin', 'RightLeg'), ('RightFoot', 'RightShin'), ('RightToeBase', 'RightFoot'), ('RightToeEnd', 'RightToeBase')]#
- property relaxed_hands_rest_pose#
- class kimodo.skeleton.SMPLXSkeleton22(folder=None, name=None, load=True, **kwargs)[source]#
Bases:
SkeletonBaseSMPL-X skeleton with body-only 22 joints.
- name = 'smplx22'#
- right_foot_joint_names = ['right_ankle', 'right_foot']#
- left_foot_joint_names = ['left_ankle', 'left_foot']#
- right_hand_joint_names = ['right_wrist']#
- left_hand_joint_names = ['left_wrist']#
- hip_joint_names = ['right_hip', 'left_hip']#
- bone_order_names_with_parents = [('pelvis', None), ('left_hip', 'pelvis'), ('right_hip', 'pelvis'), ('spine1', 'pelvis'), ('left_knee', 'left_hip'), ('right_knee', 'right_hip'), ('spine2', 'spine1'), ('left_ankle', 'left_knee'), ('right_ankle', 'right_knee'), ('spine3', 'spine2'), ('left_foot', 'left_ankle'), ('right_foot', 'right_ankle'), ('neck', 'spine3'), ('left_collar', 'spine3'), ('right_collar', 'spine3'), ('head', 'neck'), ('left_shoulder', 'left_collar'), ('right_shoulder', 'right_collar'), ('left_elbow', 'left_shoulder'), ('right_elbow', 'right_shoulder'), ('left_wrist', 'left_elbow'), ('right_wrist', 'right_elbow')]#
- kimodo.skeleton.batch_rigid_transform(rot_mats, joints, parents, root_idx)[source]#
Perform batch rigid transformation on a skeletal structure.
- Parameters:
rot_mats – Local rotation matrices for each joint: (B, J, 3, 3)
joints – Initial joint positions: (B, J, 3)
parents – Tensor indicating the parent of each joint: (J,)
root_idx (int) – index of the root
- Returns:
Transformed joint positions after applying forward kinematics.
- kimodo.skeleton.fk(
- local_joint_rots,
- root_positions,
- skeleton,
- root_positions_is_global=True,
Compute global joint rotations and positions from local rotations.
- Parameters:
local_joint_rots – Local rotation matrices with shape (…, J, 3, 3).
root_positions – Root translations with shape (…, 3).
skeleton – Skeleton object exposing neutral_joints, joint_parents, and root_idx.
root_positions_is_global – If True, neutral joints are recentered so root translations are interpreted in world space.
- Returns:
Tuple (global_joint_rots, posed_joints, posed_joints_norootpos).
- kimodo.skeleton.build_skeleton(
- nbjoints,
- assets_folder=PosixPath('/home/drempe/projects/motion_foundation_model/kimodo-oss-release/mfm-oss/kimodo/assets/skeletons'),
Instantiate a known skeleton class from its joint count.
Supported joint counts: 30 (SOMA compact), 34 (G1), 77 (SOMA full), 22 (SMPLX).
- Parameters:
nbjoints – Number of joints expected in the skeleton representation.
assets_folder – Base skeleton-assets directory containing per-skeleton subfolders.
- Returns:
A configured SkeletonBase subclass instance.
- Raises:
ValueError – If nbjoints does not match a registered skeleton.
- kimodo.skeleton.global_rots_to_local_rots(global_joint_rots, skeleton)[source]#
Convert global rotations to local rotations using a skeleton hierarchy.
- Parameters:
global_joint_rots – Global rotation matrices with shape (…, J, 3, 3).
skeleton – Skeleton object exposing joint_parents and root_idx.
- Returns:
Local rotation matrices with the same leading shape as the input.
- kimodo.skeleton.to_standard_tpose(local_rot_mats, skeleton)[source]#
Re-express local rotations in the skeleton’s standard T-pose convention.
- Parameters:
local_rot_mats – Local rotation matrices with shape (…, J, 3, 3).
skeleton – Skeleton object exposing global_rot_offsets, joint_parents, root_idx, and nbjoints.
- Returns:
Tuple (new_local_rot_mats, new_global_rot_mats) in the standard frame.
Forward Kinematics#
Forward-kinematics primitives for articulated skeletons.
- kimodo.skeleton.kinematics.fk(
- local_joint_rots,
- root_positions,
- skeleton,
- root_positions_is_global=True,
Compute global joint rotations and positions from local rotations.
- Parameters:
local_joint_rots – Local rotation matrices with shape (…, J, 3, 3).
root_positions – Root translations with shape (…, 3).
skeleton – Skeleton object exposing neutral_joints, joint_parents, and root_idx.
root_positions_is_global – If True, neutral joints are recentered so root translations are interpreted in world space.
- Returns:
Tuple (global_joint_rots, posed_joints, posed_joints_norootpos).
- kimodo.skeleton.kinematics.compute_idx_levels(parents)[source]#
Group joint indices by hierarchy depth for level-wise FK updates.
- Parameters:
parents – Parent index tensor of shape (J,) with root parent -1.
- Returns:
List of index tensors, where each tensor contains joints at one depth.
- kimodo.skeleton.kinematics.batch_rigid_transform(rot_mats, joints, parents, root_idx)[source]#
Perform batch rigid transformation on a skeletal structure.
- Parameters:
rot_mats – Local rotation matrices for each joint: (B, J, 3, 3)
joints – Initial joint positions: (B, J, 3)
parents – Tensor indicating the parent of each joint: (J,)
root_idx (int) – index of the root
- Returns:
Transformed joint positions after applying forward kinematics.
- kimodo.skeleton.kinematics.skeleton_idx_levs(skeleton, device)[source]#
Return the skeleton’s cached FK joint levels on
device, or None if absent.The levels are buffers, so they normally already sit on
device(moved with the module); the.tobelow is a fallback for skeletons used on a foreign device and would compile device_put copies into the FK graph — keep the skeleton on the compute device instead.
- kimodo.skeleton.kinematics.joints_from_global_rots(
- global_joint_rots,
- root_positions,
- skeleton,
- root_positions_is_global=True,
- return_norootpos=False,
Joint positions directly from GLOBAL rotations:
p_j = p_parent + R_g[parent] @ rel_j.fkcomposes global rotations from local ones level by level; when the caller already has the global rotations (decoded from the features) and does not need local rotations, this skips the global->local conversion and all the rotation compositions.- Parameters:
global_joint_rots – Global rotation matrices with shape
(..., J, 3, 3).root_positions – Root translations with shape
(..., 3).skeleton – Skeleton exposing
neutral_joints,joint_parents,root_idx.root_positions_is_global – see
fk.return_norootpos – also return the root-local positions (root at the origin, no dependence on
root_positions) that the posed joints are built from — the FK position loss wants exactly these, so it can consume them directly instead of re-subtracting the root (which would also route gradients throughroot_positionsfor nothing).
- Returns:
Posed joints
(..., J, 3)(identical tofk’sposed_joints); ifreturn_norootposalso the root-local positions(..., J, 3).
Motion Representations#
Base motion representation: feature layout, normalization, and conditioning helpers.
- class kimodo.motion_rep.reps.base.FeatureLayout(
- size_dict,
- last_root_feature,
- local_root_size_dict=<factory>,
Bases:
objectDeclarative feature layout of a motion representation.
A representation is a concatenation of named feature blocks (root first, then body). Declaring the layout as data — instead of subclass attributes set before
super().__init__()— means a new representation (e.g. one with extra scene or object-contact blocks) is a layout + the transform methods, not a base-class contract to reverse-engineer.- size_dict#
Ordered mapping of feature block name -> per-frame
torch.Size. Block order defines the feature vector layout.- Type:
- last_root_feature#
Name of the last block belonging to the (global) root; every block up to and including it forms the root slice, the rest is the body.
- Type:
- local_root_size_dict#
Layout of the derived local-root features (used by
global_root_to_local_root), not part of the stored feature vector.- Type:
- size_dict#
- last_root_feature#
- local_root_size_dict#
- __init__(
- size_dict,
- last_root_feature,
- local_root_size_dict=<factory>,
- class kimodo.motion_rep.reps.base.MotionRepBase(skeleton, fps, stats_path=None, layout=None)[source]#
Bases:
<Mock object at 0x7c56203257b0>[]Base class for motion representations used in generation and conditioning.
Subclasses pass a
FeatureLayoutdescribing their feature blocks and implement transform-specific methods such as__call__,inverse,rotate,translate_2dandcreate_conditions.This is an
nn.Module(holding no parameters) so that theStatsand skeleton buffers follow the model when it is moved to a device, instead of being re-transferred from CPU on every normalize/unnormalize/FK call.- __init__(skeleton, fps, stats_path=None, layout=None)[source]#
Initialize feature slicing metadata and optional normalization stats.
- property root_pos_name#
Name of the 3D root-position feature block (
root_posorsmooth_root_pos).
- get_root_pos(features, fallback_to_smooth=True)[source]#
Extract root positions from a feature tensor.
Supports both
root_posandsmooth_root_posrepresentations.
- recenter_root_motion(
- root_motion,
- center_frame_index,
- is_normalized,
- to_normalize,
- return_center_pos=False,
Translate root x/z so a selected frame becomes the local origin.
Assumes the root feature block starts with a 3D position (
root_posorsmooth_root_pos), likeglobal_root_to_local_root.
- global_root_to_local_root(
- root_features,
- normalized,
- lengths,
Convert global root features to local-root motion features.
- Parameters:
root_features – Root feature tensor containing root position and global heading, shaped
[B, T, D_root].normalized – Whether
root_featuresare normalized.lengths – Optional valid lengths per sequence.
- Returns:
Tensor
[B, T, 4]with local root rotational velocity, planar velocity, and global root height.
- local_root_to_global_root(
- local_root_features,
- normalized,
- lengths=None,
Convert local-root motion features back to global root features.
Exact inverse of
global_root_to_local_root(), up to the integration constants that the local representation does not store: the recovered heading and planar (x, z) position are relative to frame 0 (zero heading and origin at frame 0).- Parameters:
local_root_features – Local-root tensor
[B, T, 4]with rotational velocity, planar velocity, and global root height.normalized – Whether
local_root_featuresare normalized (the returned global root features are then normalized as well).lengths – Optional valid lengths per sequence (unused; kept for symmetry with
global_root_to_local_root).
- Returns:
Tensor
[B, T, D_root]with root position and global heading.
- get_root_heading_angle(features, normalized=False)[source]#
Compute root heading angle from cosine/sine heading features.
With
normalized=Trueonly the two heading channels get unnormalized (arctan2 needs raw values), instead of unnormalizing the whole feature tensor first.featuresmay be the full feature tensor or just the root block — the heading slice indices are valid for both since the root block leads the feature layout.
- get_first_heading_angle(features, normalized)[source]#
Return the frame-0 heading angle for each sequence in the batch.
- Parameters:
features – Motion features of shape
[B, T, motion_rep_dim].normalized – Whether
featuresis normalized.
- Returns:
Tensor of shape
[B]with the per-sequence heading at frame 0.
- rotate_to(
- features,
- target_angle,
- return_delta_angle=False,
Rotate each sequence so frame-0 heading matches
target_angle.
- rotate_to_zero(features, return_delta_angle=False)[source]#
Rotate each sequence so frame-0 heading becomes zero.
- canonicalize_random_heading(
- features,
- return_delta_angle=False,
- return_delta_pos=False,
Canonicalize each sequence to a RANDOM frame-0 heading: frame-0 root
(x, z)goes to the origin (likecanonicalize) but the heading is randomized instead of zeroed — the training-time heading augmentation. Rotation and recentering belong together here: a rotate-only augmentation leaves the window’s world offset in the root features, so models trained directly on loader output (kimodo) see a shifted root distribution.
- translate_2d_to(
- features,
- target_2d_pos,
- return_delta_pos=False,
Translate each sequence so frame-0 root
(x, z)matches a target.
- translate_2d_to_zero(features, return_delta_pos=False)[source]#
Translate each sequence so frame-0 root
(x, z)is at the origin.
- canonicalize(features, normalized=False)[source]#
Canonicalize heading and planar position at frame 0.
- joint_feature_indices(
- feature_name,
- joint_names,
- joint_order=None,
Flat feature indices covering
joint_namesinside a per-joint feature block.The per-joint width (e.g. 3 for positions, 6 for cont6d rotations) is derived from the block size.
joint_orderis the joint ordering of the block; it defaults to the skeleton bone order.This is the single place mapping (feature block, joint) -> feature columns; both the training-time mask builders and the inference-time constraint conditioning rely on it.
Results are memoized per instance (deterministic in
slice_dict/skeleton, which are fixed after init): the mask builders call this per keyframe per sample, and rebuilding the name->index dict each call dominated their cost. The cache stays tiny (one entry per distinct (block, joints, order) combination). Callers must not mutate the returned array.
- concat_root_body(root, body)[source]#
Concatenate root and body features into a full motion feature tensor.
Kimodo motion representation (<skel>_kimodo, formerly *_smooth_root).
Per-frame features relative to a smoothed root trajectory: smooth root position, global root heading
(cos/sin), per-joint local positions (pelvis-origin plus the hips offset from the smooth root),
global joint rotations as cont6d, per-joint velocities, and foot contacts — see the
FeatureLayout in KimodoMotionRep.__init__. __call__ builds features from local rotations
+ root trajectory via FK; inverse reconstructs posed joints; create_conditions maps
constraint sets onto the feature blocks for the denoiser. The root-local channels (root rot-vel /
xz-vel / y) support the canonicalized local-root form used in training.
- class kimodo.motion_rep.reps.kimodo_motionrep.KimodoMotionRep(
- skeleton,
- fps,
- stats_path=None,
- stats=None,
- name=None,
- **kwargs,
Bases:
MotionRepBaseGlobal root / global joints rotations representation, relative to a smooth root.
- __init__(
- skeleton,
- fps,
- stats_path=None,
- stats=None,
- name=None,
- **kwargs,
Initialize feature slicing metadata and optional normalization stats.
- inverse(
- features,
- is_normalized,
- posed_joints_from='rotations',
- return_numpy=False,
- return_all=False,
- need_local_rots=True,
Decode smooth-root features into motion tensors.
return_alladds anall_positionsdict with the joints decoded from the position and rotation blocks ({"positions": ..., "rotations": ...}).need_local_rots=Falseskips the global->local conversion (local_rot_matsis thenNonein the output) — the training losses only consume positions / global rotations.
- create_conditions(
- index_dict,
- data_dict,
- length,
- to_normalize,
- device,
Build sparse conditioning tensors for smooth-root representation.
- Returns:
(observed_motion, motion_mask)wheremotion_maskis bool and unmasked cells ofobserved_motionkeep whatevernormalizeproduced from the zero initialization. This deliberately differs fromArdyMotionRep.create_conditions(float mask, unmasked cells zeroed) — callers are contract-specific.
TMR motion representation: global root, global joints, velocities, and foot contacts.
- class kimodo.motion_rep.reps.tmr_motionrep.TMRMotionRep(skeleton, fps, stats_path=None, name=None)[source]#
Bases:
MotionRepBaseMotion representation with global root and local joint positions.
The local joint positions are rotation invariant (they all face z+)
Feature layout: - root position
(x, y, z)- root heading as(cos(theta), sin(theta))- local joint positions (root and rotation removed) - local joint velocities (rotation removed) - binary foot contacts- __init__(skeleton, fps, stats_path=None, name=None)[source]#
Initialize feature slicing metadata and optional normalization stats.
- inverse(
- features,
- is_normalized,
- posed_joints_from='positions',
- return_numpy=False,
Decode features back to a motion dictionary.
- Parameters:
features – Feature tensor
[B, T, D].is_normalized – Whether input features are normalized.
posed_joints_from – Must be
"positions"for this representation.return_numpy – Whether to convert tensors to numpy arrays.
- Returns:
Dictionary containing reconstructed positions and auxiliary data.
Utilities#
Foot contact detection from joint positions and velocities.
- kimodo.motion_rep.feet.foot_detect_from_pos_and_vel(
- positions,
- velocity,
- skeleton,
- vel_thres,
- height_thresh,
Compute foot contact labels using heuristics combining joint height and velocities.
- Parameters:
positions (torch.Tensor) – [X, T, J, 3] global joint positions
velocity (torch.Tensor) – [X, T, J, 3] velocities (already padded correctly), already multiplied by 1 / dt
vel_thres (float) – threshold for joint velocity
height_thresh (float) – threshold for joint height
- Returns:
[X, T, 4] contact labels for left and right foot joints (heel/toe order follows the skeleton joint index definition), where
1denotes contact.- Return type:
Feature normalization statistics (mean/std) for motion representations.
- class kimodo.motion_rep.stats.Stats(folder=None, load=True, eps=1e-05)[source]#
Bases:
<Mock object at 0x7c562016aa70>[]Utility module for feature normalization statistics.
Normalization follows:
(data - mean) / sqrt(std**2 + eps)
Smooth root trajectory: ADMM-based smoother with margin constraints and get_smooth_root_pos helper.
- class kimodo.motion_rep.smooth_root.TrajectorySmoother(
- margins,
- pos_weight=0.0,
- loop=False,
- admm_iters=100,
- alpha_overrelax=1.0,
- circle_project=False,
Bases:
objectModify trajectories to hit target values while respecting soft constraints.
This smoother keeps the trajectory close to the original positions while minimizing accelerations. Targets are enforced at specified frames via soft constraints.
- __init__(
- margins,
- pos_weight=0.0,
- loop=False,
- admm_iters=100,
- alpha_overrelax=1.0,
- circle_project=False,
Initialize the TrajectorySmoother.
- Parameters:
margins – Array of margin values for each frame. margins[i] < 0: unconstrained margins[i] == 0: pinned on this frame margins[i] > 0: can deviate within the margin
pos_weight – Weight for position preservation
loop – Whether the trajectory should loop
admm_iters – Number of ADMM iterations
- kimodo.motion_rep.smooth_root.smooth_signal(
- x,
- margins,
- pos_weight=0,
- alpha_overrelax=1.8,
- admm_iters=500,
- circle_project=False,
Multigrid trajectory smoothing with margin constraints.
- Parameters:
x – Input trajectory
[T, D]as a NumPy array.margins – Allowed radius around each target frame
[T].pos_weight – Weight for staying close to the original signal.
alpha_overrelax – ADMM over-relaxation coefficient.
admm_iters – ADMM iterations per multigrid level.
circle_project – If
True, project each vector to the unit sphere.
- Returns:
Smoothed trajectory of shape
[T, D].