Overview
Motion optimization is essential for ensuring physically plausible character motion on terrain. The optimization process:- Takes raw motion data (root position, rotation, joint rotations)
- Applies multiple loss terms weighted by user-specified parameters
- Uses gradient descent to minimize the combined loss
- Returns optimized motion that respects terrain geometry and contact constraints
Core Functions
motion_contact_optimization
Main optimization function that refines motion sequences to eliminate terrain penetration and enforce contact constraints.src_motion_frames(MotionFrames): Input motion sequence with root position, rotation, joint rotations, and contactsbody_points(list): List of sampled points for each body part for collision detectionterrain(SubTerrain): Heightfield terrain representationchar_model(KinCharModel): Character kinematic model for forward kinematicsnum_iters(int): Number of optimization iterations (typically 500-2000)step_size(float): Adam optimizer learning rate (typically 0.001-0.01)w_root_pos(float): Weight for root position preservation lossw_root_rot(float): Weight for root rotation preservation lossw_joint_rot(float): Weight for joint rotation preservation lossw_smoothness(float): Weight for motion smoothness (velocity consistency)w_penetration(float): Weight for preventing body-terrain penetrationw_contact(float): Weight for enforcing contact points touch terrainw_sliding(float): Weight for preventing foot sliding during contactw_body_constraints(float): Weight for body constraint adherencew_jerk(float): Weight for limiting jerk (third derivative of position)body_constraints(list): Per-body list of BodyConstraint objectsmax_jerk(float): Maximum allowable jerk magnitudeexp_name(str): Experiment name for logginguse_wandb(bool): Enable Weights & Biases logginglog_file(str): Path to save optimization log
MotionFrames: Optimized motion sequence
simplified_motion_optimization
Lightweight optimization with only basic regularization and jerk penalty.src_motion_frames(MotionFrames): Input motion sequencechar_model(KinCharModel): Character kinematic modelnum_iters(int): Number of optimization iterationsstep_size(float): Optimizer learning ratew_root_pos(float): Root position preservation weightw_root_rot(float): Root rotation preservation weightw_joint_rot(float): Joint rotation preservation weightw_jerk(float): Jerk penalty weightexp_name(str): Optional experiment nameuse_wandb(bool): Enable wandb logginglog_file(str): Optional log file path
MotionFrames: Optimized motion sequence
Loss Functions
motion_terrain_contact_loss
Computes the full multi-objective loss for terrain-aware motion optimization.- Root Position Loss:
||tgt_root_pos - src_root_pos||²- Keeps root position close to original - Root Rotation Loss:
||angle_diff(tgt_rot, src_rot)||²- Preserves root orientation - Joint Rotation Loss:
||angle_diff(tgt_joints, src_joints)||²- Maintains joint angles - Smoothness Loss:
||tgt_vels - src_vels||²- Enforces velocity consistency - Penetration Loss:
sum(clamp(-sdf, max=0))- Penalizes body-terrain intersection - Contact Loss:
sum(sdf * contact_mask)- Ensures contact bodies touch terrain - Sliding Loss: Pseudo-Huber loss on velocity changes during contact
- Body Constraint Loss: Distance to fixed contact points (e.g., foot placement)
- Jerk Loss:
sum(clamp(||jerk|| - max_jerk, min=0))- Limits acceleration changes
loss(Tensor): Weighted sum of all loss componentslosses(dict): Dictionary mapping LossType enum to individual loss values
motion_terrain_contact_loss_localized
Memory-optimized variant that processes per-frame heightfield patches instead of the full terrain.- Extracts local heightfield patches centered on character position per frame
- Reuses patches across all SDF evaluations for that frame
- Maintains full vectorization while reducing memory footprint
- Recommended for large terrains (>100x100 grid)
simplified_motion_loss
Basic loss function without terrain or contact constraints.- Root position/rotation/joint preservation losses
- Jerk penalty on body positions
Constraint System
BodyConstraint
Dataclass representing a fixed spatial constraint for a body part during specific frames.compute_approx_body_constraints
Automatically generates body constraints from contact labels.- Computes forward kinematics to get body positions
- Identifies consecutive contact periods for hands and feet
- Averages body position during each contact period
- Projects constraint point onto terrain surface using gradient descent
- Returns per-body list of BodyConstraint objects
root_pos(Tensor): Root positions [num_frames, 3]root_rot(Tensor): Root rotations [num_frames, 4]joint_rot(Tensor): Joint rotations [num_frames, num_joints, 4]contacts(Tensor): Binary contact labels [num_frames, num_bodies]char_model(KinCharModel): Character modelterrain(SubTerrain): Terrain for constraint projection
body_constraints(list): Per-body list of BodyConstraint objects
Loss Type Enumeration
Utility Functions
_align_contacts_to_bodies
Expands per-contact-body contact labels to per-body format.build_logger
Creates a WandB logger for optimization tracking.Optimization Process
The kinematic correction process follows this workflow:-
Initialization:
- Clone source motion parameters (root pos/rot, joint DOFs)
- Mark all as
requires_grad = True - Initialize Adam optimizer
-
Forward Pass:
- Convert exponential map rotations to quaternions
- Run forward kinematics to get body positions/rotations
- Compute SDF queries for all body points against terrain
- Evaluate all loss terms
-
Backward Pass:
- Compute gradients via autograd
- Update parameters using Adam
- Log losses every 25 iterations
-
Return:
- Convert optimized parameters to MotionFrames
- Detach gradients and preserve contact labels
Weight Tuning Guidelines
Preservation Weights (1.0-10.0):w_root_pos,w_root_rot,w_joint_rot: Start at 1.0- Increase if motion deviates too much from original
w_penetration: Critical, use 100.0+ for hard constraintsw_contact: Use 10.0-50.0 to ensure feet touch groundw_sliding: Use 5.0-20.0 to prevent foot skating
w_smoothness: Use 0.5-2.0 for general smoothingw_jerk: Use 0.1-1.0 for subtle acceleration limiting
w_body_constraints: Use 50.0 for strong foot fixation
Performance Considerations
- Localized Loss: Use
motion_terrain_contact_loss_localizedfor terrains >50x50 to reduce memory - Body Points: More points = better collision detection but slower (default: ~50 points per body)
- Iterations: 500-1000 typically sufficient, 2000+ for high-quality results
- Batch Processing: Process multiple motions sequentially; optimization is not batched
Related Modules
- Procedural Generation - Path planning for motion synthesis
- Character Model - Kinematic character representation
- Terrain Utilities - Heightfield and SDF operations