Retargeting¶
Retargeting maps motion captured on one morphology (human keypoints, SMPL-family bodies, MANO hands, interaction
meshes) onto an Eden robot. The four solvers are RetargetingBase subclasses configured by a RetargeterOptions, and the
FlashDexRetarget pipeline is a set of functions with its own options; each imports its backend lazily. The retargeting guide covers eden retarget and the
body backends; the dex retargeting guide covers hands.
from eden.extensions.retargeting.base import RetargetingBase
from eden.options.extensions.retargeting import RetargeterOptions
| Backend | Maps | CLI |
|---|---|---|
DexRetargeter |
MANO hand keypoints → a dexterous robot hand | eden retarget dex |
OmniRetargeter |
human motion with an interaction mesh → a humanoid (Laplacian deformation) | eden retarget omniretarget |
OTRetargeter |
a human surface and objects → a robot and objects (optimal transport) | eden retarget otretarget |
SomaRetargeter |
SMPL / SMPL-H / SMPL-X / SOMA → a floating-base humanoid (Unitree G1, LimX Oli), through the eden-soma-retargeter library |
eden retarget soma |
| FlashDexRetarget | MANO hand-object demos → a bimanual robot-hand motion.pt |
eden retarget flashdex |
Base class and options¶
RetargetingBase
¶
RetargetingBase(env: EnvBase, options: RetargeterOptions)
Bases: ConfigurableMixin[RetargeterOptions]
Abstract base class for retargeting backends.
Resolves entity_name against env.entities at construction (raising on an unknown name);
subclasses implement :meth:retarget_motion.
Source code in eden/extensions/retargeting/base.py
RetargeterOptions
¶
Bases: DynamicConfigurableOptions
Options for retargeting extensions.
| PARAMETER | DESCRIPTION |
|---|---|
entity_name
|
The name of the entity to perform retargeting for.
TYPE:
|
Source code in eden/options/options.py
Shared constants for retargeting.
Attributes¶
JOINTS_MAP_UNITREE_G1
module-attribute
¶
JOINTS_MAP_UNITREE_G1 = {'smplh': {'Pelvis': 'pelvis', 'L_Hip': 'left_hip_pitch_link', 'R_Hip': 'right_hip_pitch_link', 'L_Knee': 'left_knee_link', 'R_Knee': 'right_knee_link', 'L_Shoulder': 'left_shoulder_roll_link', 'R_Shoulder': 'right_shoulder_roll_link', 'L_Elbow': 'left_elbow_link', 'R_Elbow': 'right_elbow_link', 'L_Ankle': 'left_ankle_pitch_link', 'R_Ankle': 'right_ankle_pitch_link', 'L_Toe': 'left_ankle_roll_link', 'R_Toe': 'right_ankle_roll_link', 'L_Wrist': 'left_wrist_yaw_link', 'R_Wrist': 'right_wrist_yaw_link'}, 'smplx': {'Pelvis': 'pelvis', 'L_Hip': 'left_hip_pitch_link', 'R_Hip': 'right_hip_pitch_link', 'L_Knee': 'left_knee_link', 'R_Knee': 'right_knee_link', 'L_Shoulder': 'left_shoulder_roll_link', 'R_Shoulder': 'right_shoulder_roll_link', 'L_Elbow': 'left_elbow_link', 'R_Elbow': 'right_elbow_link', 'L_Ankle': 'left_ankle_pitch_link', 'R_Ankle': 'right_ankle_pitch_link', 'L_Foot': 'left_ankle_roll_link', 'R_Foot': 'right_ankle_roll_link', 'L_Wrist': 'left_wrist_yaw_link', 'R_Wrist': 'right_wrist_yaw_link'}, 'mocap': {'Spine1': 'pelvis', 'LeftUpLeg': 'left_hip_pitch_link', 'LeftLeg': 'left_knee_link', 'LeftToeBase': 'left_ankle_roll_link', 'RightUpLeg': 'right_hip_pitch_link', 'RightLeg': 'right_knee_link', 'RightToeBase': 'right_ankle_roll_link', 'LeftArm': 'left_shoulder_roll_link', 'LeftForeArm': 'left_elbow_link', 'LeftHandMiddle3': 'left_sphere_hand_link', 'RightArm': 'right_shoulder_roll_link', 'RightForeArm': 'right_elbow_link', 'RightHandMiddle3': 'right_sphere_hand_link', 'LeftFoot': 'left_ankle_pitch_link', 'RightFoot': 'right_ankle_pitch_link'}, 'lafan1': {'Spine1': 'pelvis', 'LeftUpLeg': 'left_hip_pitch_link', 'RightUpLeg': 'right_hip_pitch_link', 'LeftLeg': 'left_knee_link', 'RightLeg': 'right_knee_link', 'LeftArm': 'left_shoulder_roll_link', 'RightArm': 'right_shoulder_roll_link', 'LeftForeArm': 'left_elbow_link', 'RightForeArm': 'right_elbow_link', 'LeftFoot': 'left_ankle_pitch_link', 'RightFoot': 'right_ankle_pitch_link', 'LeftToeBase': 'left_ankle_roll_link', 'RightToeBase': 'right_ankle_roll_link', 'LeftHand': 'left_wrist_yaw_link', 'RightHand': 'right_wrist_yaw_link'}}
JOINTS_MAP_BOOSTER_T1
module-attribute
¶
JOINTS_MAP_BOOSTER_T1 = {'smplh': {'Pelvis': 'Trunk', 'L_Hip': 'Hip_Pitch_Left', 'R_Hip': 'Hip_Pitch_Right', 'L_Knee': 'Shank_Left', 'R_Knee': 'Shank_Right', 'L_Shoulder': 'AL1', 'R_Shoulder': 'AR1', 'L_Elbow': 'left_hand_link', 'R_Elbow': 'right_hand_link', 'L_Ankle': 'Ankle_Cross_Left', 'R_Ankle': 'Ankle_Cross_Right', 'L_Toe': 'left_foot_sphere_5_link', 'R_Toe': 'right_foot_sphere_5_link', 'L_Wrist': 'left_wrist_yaw_link', 'R_Wrist': 'right_wrist_yaw_link'}, 'mocap': {'Spine1': 'Trunk', 'LeftUpLeg': 'Hip_Pitch_Left', 'LeftLeg': 'Shank_Left', 'LeftToeBase': 'left_foot_sphere_5_link', 'RightUpLeg': 'Hip_Pitch_Right', 'RightLeg': 'Shank_Right', 'RightToeBase': 'right_foot_sphere_5_link', 'LeftArm': 'AL1', 'LeftForeArm': 'left_hand_link', 'LeftHandMiddle3': 'left_hand_sphere_link', 'RightArm': 'AR1', 'RightForeArm': 'right_hand_link', 'RightHandMiddle3': 'right_hand_sphere_link', 'LeftFoot': 'Ankle_Cross_Left', 'RightFoot': 'Ankle_Cross_Right'}, 'lafan1': {'Spine1': 'Trunk', 'LeftUpLeg': 'Hip_Pitch_Left', 'RightUpLeg': 'Hip_Pitch_Right', 'LeftLeg': 'Shank_Left', 'RightLeg': 'Shank_Right', 'LeftArm': 'AL1', 'RightArm': 'AR1', 'LeftForeArm': 'left_hand_link', 'RightForeArm': 'right_hand_link', 'LeftFoot': 'Ankle_Cross_Left', 'RightFoot': 'Ankle_Cross_Right', 'LeftToeBase': 'left_foot_sphere_5_link', 'RightToeBase': 'right_foot_sphere_5_link', 'LeftHand': 'left_hand_sphere_link', 'RightHand': 'right_hand_sphere_link'}}
TOE_NAMES_BY_FORMAT
module-attribute
¶
TOE_NAMES_BY_FORMAT = {'lafan1': ['LeftToeBase', 'RightToeBase'], 'smplh': ['L_Toe', 'R_Toe'], 'mocap': ['LeftToeBase', 'RightToeBase'], 'smplx': ['L_Foot', 'R_Foot']}
DexRetargeter¶
Eden RetargetingBase wrapper around the dex-retargeting port.
Combines one of three SLSQP optimizers (position / vector / dexpilot) with
the upstream SeqRetargeting semantics (mean-of-limits warm start, output
low-pass filter) into a single DexRetargeter entity-extension.
Typical usage:
.. code-block:: python
retargeter = DexRetargeter(
env=env,
options=DexRetargeter.configure(
entity_name="robot",
type="vector",
target_origin_link_names=["wrist", "wrist", "wrist", "wrist"],
target_task_link_names=["index_tip", "middle_tip", "ring_tip", "pinky_tip"],
target_link_human_indices=np.array([[0, 0, 0, 0], [8, 12, 16, 20]]),
scaling_factor=1.6,
),
)
qpos = retargeter.retarget(ref_value) # one frame
qpos_seq = retargeter.retarget_motion(ref_seq) # batch
Attributes¶
Classes¶
DexRetargeter
¶
DexRetargeter(env: 'EnvBase', options: RetargeterOptions)
Bases: RetargetingBase
Port of dex-retargeting backed by Genesis kinematics.
| PARAMETER | DESCRIPTION |
|---|---|
type
|
Retargeting algorithm to instantiate.
TYPE:
|
target_joint_names
|
Subset of |
target_link_human_indices
|
Indices into the human hand keypoint array.
-
TYPE:
|
target_link_names
|
Position-retargeting only. Robot links whose world positions match
the human keypoints selected by |
target_origin_link_names
|
Vector-retargeting only. Each vector goes from origin to task. |
target_task_link_names
|
Vector-retargeting only. Each vector goes from origin to task. |
finger_tip_link_names
|
DexPilot only. Five (or fewer) fingertip links. |
wrist_link_name
|
DexPilot only. The wrist / palm reference link.
TYPE:
|
scaling_factor
|
Human-to-robot scale (applies to
TYPE:
|
huber_delta
|
Huber loss beta and quadratic regularization weight on
TYPE:
|
normal_delta
|
Huber loss beta and quadratic regularization weight on
TYPE:
|
project_dist
|
DexPilot fingertip projection thresholds.
TYPE:
|
escape_dist
|
DexPilot fingertip projection thresholds.
TYPE:
|
has_joint_limits
|
Pass entity DOF limits to
TYPE:
|
low_pass_alpha
|
Output smoothing in
TYPE:
|
Source code in eden/extensions/retargeting/dex_retargeter/retargeter.py
Attributes¶
type
class-attribute
instance-attribute
¶
type: Literal['position', 'vector', 'dexpilot'] = 'vector'
target_joint_names
class-attribute
instance-attribute
¶
target_link_human_indices
class-attribute
instance-attribute
¶
target_link_human_indices: Optional[ndarray] = None
target_link_names
class-attribute
instance-attribute
¶
target_origin_link_names
class-attribute
instance-attribute
¶
target_task_link_names
class-attribute
instance-attribute
¶
finger_tip_link_names
class-attribute
instance-attribute
¶
filter
instance-attribute
¶
filter: Optional[LPFilter] = LPFilter(self.low_pass_alpha) if 0 <= self.low_pass_alpha <= 1 else None
joint_names
property
¶
Full DOF name list of the underlying entity (dofs_name order).
Methods:¶
retarget
¶
Retarget one frame and return a full-DOF qpos (in dofs_name order).
ref_value is the optimizer-specific Cartesian reference: positions
(n, 3) for position; vectors (n, 3) for vector and
dexpilot. fixed_qpos holds the non-target joints (optimizer.idx_fixed order;
zeros when None).
Source code in eden/extensions/retargeting/dex_retargeter/retargeter.py
retarget_motion
¶
Retarget a whole trajectory.
| PARAMETER | DESCRIPTION |
|---|---|
ref_sequence
|
TYPE:
|
fixed_qpos_sequence
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
qpos
|
Full-DOF qpos per frame in
TYPE:
|
Source code in eden/extensions/retargeting/dex_retargeter/retargeter.py
reset
¶
Forget previous-frame state (last_qpos, filter).
set_qpos
¶
Manually seed last_qpos (e.g. from the simulator's current state).
get_qpos
¶
Source code in eden/extensions/retargeting/dex_retargeter/retargeter.py
extract_ref_value
staticmethod
¶
extract_ref_value(joint_pos: ndarray, target_link_human_indices: ndarray, retargeting_type: str) -> ndarray
Build the optimizer's ref_value from a 21-keypoint MANO array.
Same logic as upstream's detect_from_video.py snippet so existing
MediaPipe pipelines drop in cleanly.
Source code in eden/extensions/retargeting/dex_retargeter/retargeter.py
Functions:¶
SLSQP-based retargeting optimizers, Genesis-backed.
Ported from dex_retargeting.optimizer (AnyTeleop / DexPilot). The
algorithm — Huber loss over keypoint positions or relative vectors, optimized
with nlopt's SLSQP and analytic gradients built from positional
Jacobians — is unchanged. Only the kinematics layer differs:
- Forward kinematics is performed by calling
entity.set_qpos(qpos). - Jacobians come from
entity.get_jacobian(link)and are already in world frame (Genesis returns the spatial Jacobian), so the upstreamlink_rot @ body_jacobianstep is dropped. - Column ordering follows
entity.dofs_name(Eden reorders internally).
Free-joint detection and the MimicJointKinematicAdaptor from upstream
are intentionally omitted; we expect hands with no base DOFs (fixed-base or
welded onto an arm) with mimic constraints already baked into the URDF.
Classes¶
Optimizer
¶
Optimizer(entity: 'RigidEntity', target_joint_names: List[str], target_link_human_indices: Optional[ndarray])
Base class. Subclasses build the per-frame objective + gradient.
Operates directly on an Eden :class:~eden.entities.rigid.RigidEntity.
All DOF arrays use entity.dofs_name order (the same order
set_qpos and get_jacobian's columns use).
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
Attributes¶
idx_fixed
instance-attribute
¶
target_link_human_indices
instance-attribute
¶
Methods:¶
set_joint_limit
¶
set_joint_limit(joint_limits: ndarray, epsilon: float = 0.001) -> None
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
retarget
¶
Run one SLSQP solve and return the optimized target-joint qpos.
| PARAMETER | DESCRIPTION |
|---|---|
ref_value
|
Optimizer-specific Cartesian reference (positions or vectors).
TYPE:
|
fixed_qpos
|
Values for joints NOT in
TYPE:
|
last_qpos
|
Initial guess and regularization target for this frame.
TYPE:
|
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
get_objective_function
abstractmethod
¶
PositionOptimizer
¶
PositionOptimizer(entity: 'RigidEntity', target_joint_names: List[str], target_link_names: List[str], target_link_human_indices: ndarray, huber_delta: float = 0.02, norm_delta: float = 0.004)
Bases: Optimizer
Match absolute world-frame positions of robot links to keypoints.
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
Attributes¶
Methods:¶
get_objective_function
¶
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
VectorOptimizer
¶
VectorOptimizer(entity: 'RigidEntity', target_joint_names: List[str], target_origin_link_names: List[str], target_task_link_names: List[str], target_link_human_indices: ndarray, huber_delta: float = 0.02, norm_delta: float = 0.004, scaling: float = 1.0)
Bases: Optimizer
Match relative vectors between robot link pairs to keypoint pairs.
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
Attributes¶
huber_loss
instance-attribute
¶
Methods:¶
get_objective_function
¶
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
DexPilotOptimizer
¶
DexPilotOptimizer(entity: 'RigidEntity', target_joint_names: List[str], finger_tip_link_names: List[str], wrist_link_name: str, target_link_human_indices: Optional[ndarray] = None, huber_delta: float = 0.03, norm_delta: float = 0.004, project_dist: float = 0.03, escape_dist: float = 0.05, eta1: float = 0.0001, eta2: float = 0.03, scaling: float = 1.0)
Bases: Optimizer
DexPilot vector retargeting with thumb-to-fingertip projection.
A direct port of dex_retargeting.optimizer.DexPilotOptimizer. Generates
its own link pairs (each fingertip-to-wrist + every fingertip-pair) and
snaps thumb-to-fingertip distances inside project_dist to encourage
pinch grasps. See https://arxiv.org/abs/1910.03135.
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
Attributes¶
huber_loss
instance-attribute
¶
Methods:¶
get_objective_function
¶
Source code in eden/extensions/retargeting/dex_retargeter/optimizer.py
Bundled robot + retargeter presets for dex-retargeting.
Single source of truth shared by the eden retarget dex CLI and the
examples/recipes/retargeting/dex_retargeter scripts. Each :class:HandPreset pairs a
RobotOptions factory with a RetargeterOptions factory. The
RetargeterOptions factories import DexRetargeter lazily (it pulls
nlopt), so importing this module for :data:POSITION_PRESET_NAMES — used to
build the CLI's --preset choices — stays free of the dex-retargeter
extra.
Fingertip link names and MANO keypoint indices are read off the robot's
MetadataOptions (target_hand_links / mano_hand_idx), so adding a
hand only needs a new entry in :data:HAND_PRESETS.
Attributes¶
HAND_PRESETS
module-attribute
¶
HAND_PRESETS: dict[str, HandPreset] = {'xhand1_right_dexpilot': HandPreset(_xhand1_r_robot, _xhand1_right_dexpilot, 'right'), 'xhand1_right_vector': HandPreset(_xhand1_r_robot, _xhand1_right_vector, 'right'), 'xhand1_right_position': HandPreset(_xhand1_r_robot, _xhand1_right_position, 'right'), 'wuji_hand2beta2_right_dexpilot': HandPreset(partial(_wuji_hand2_robot, 'right'), partial(_wuji_hand2_dexpilot, 'right'), 'right'), 'wuji_hand2beta2_left_dexpilot': HandPreset(partial(_wuji_hand2_robot, 'left'), partial(_wuji_hand2_dexpilot, 'left'), 'left')}
POSITION_PRESET_NAMES
module-attribute
¶
Classes¶
URDF↔MANO frame alignment, derived from Eden's up / front fields.
A hand URDF's up and front declarations encode the same kind of
"asset-frame → world-reference" rotation that :func:eden.utils.geom.align_up_and_front
already produces for any Eden entity. For hand robots the convention is:
up= the URDF axis along which the fingers extendfront= the URDF axis along which the palm normal points (= the URDF axis that aligns with world +X after load)
Eden's defaults (up=(0,0,1), front=(1,0,0)) already match XHand1_R's
URDF (fingers along URDF +Z, palm normal along URDF +X), so XHand1_R
loads identity. MANO's right-hand canonical frame is the matching
declaration in MANO-local axes:
- fingers (=
up) along-Xin MANO local - palm normal (=
front) along-Yin MANO local
Applying align_up_and_front twice (once for the robot, once for MANO)
gives a URDF → canonical-world → MANO chain that the retargeter can compose
into a single rotation — no per-robot urdf_to_mano_quat metadata
needed.
This module exposes :func:urdf_to_mano_rot, which returns:
R_mano_to_world— used to rotate MANO-local keypoints into the retargeting (= canonical world) frame so the optimizer's targets line up with the robot's actually-loaded fingertip workspace.q_urdf_to_mano— composed onto the per-frame MANO wrist quat to get the floating-basebase_quat_wthat places the robot at the right world orientation for the saveddofs_posto reproduce MANO fingertips at viz time.
Classes¶
Functions:¶
urdf_to_mano_rot
¶
urdf_to_mano_rot(robot: 'RigidEntity') -> tuple[ndarray, ndarray]
Derive the URDF↔MANO conversion from the robot's up / front.
Returns (R_mano_to_world, q_urdf_to_mano) where:
R_mano_to_world(3x3) — maps MANO-local vectors into the canonical world frame the robot is loaded into viaalign_up_and_front(robot.up, robot.front). Used at retargeting time to bring MANO keypoint targets into the robot's world frame.q_urdf_to_mano(4,) wxyz — composed onto the per-frame MANO wrist quat to produce the floating-basebase_quat_wfor viz.
The robot's MANO side is read from metadata.side (defaults to right).
Source code in eden/extensions/retargeting/dex_retargeter/calibrate.py
Constants for the dex-retargeting port.
Mirrors dex_retargeting.constants but trimmed to what the Eden port
actually consumes. Robot-name enums upstream are tied to YAML config files
shipped with the package; in Eden we plug in any RigidEntity directly, so
those enums are not needed.
Helpers for the dex-retargeting port (e.g. low-pass filter).
OmniRetarget¶
OmniRetarget optimization-based retargeter.
Classes¶
OmniRetargeter
¶
OmniRetargeter(env, options: RetargeterOptions)
Bases: RetargetingBase
Interaction-mesh retargeter backed by Eden/Genesis.
Works on a floating-base entity (qpos [pos, quat_wxyz, joints]) and on a fixed-base or
welded one (qpos joints only). Every name below is checked at construction: a link, DOF,
demo joint or foot_links key the entity or config does not have raises, naming it.
| PARAMETER | DESCRIPTION |
|---|---|
foot_links
|
|
demo_joints
|
Joint names of the demo motion's joint axis (e.g. SMPL-H). |
laplacian_match_links
|
|
link_offsets
|
|
manual_lb
|
Manual joint-limit overrides keyed by DOF name. |
manual_ub
|
Manual joint-limit overrides keyed by DOF name. |
manual_cost
|
Per-joint cost weights keyed by DOF name. |
nominal_tracking_dofs
|
DOF names for nominal-pose tracking. |
foot_sticking_map
|
Maps sticking flag keys (e.g. |
laplacian_weights
|
Weight of every interaction-mesh vertex's Laplacian-deformation term.
TYPE:
|
smooth_weight
|
Weight pulling each frame's solution toward the previous frame's.
TYPE:
|
step_size
|
Trust-region radius for SQP.
TYPE:
|
foot_sticking_tolerance
|
TYPE:
|
foot_z_sticking_tolerance
|
Tolerance for optional Z sticking during active foot contact.
TYPE:
|
foot_ground_z
|
World-frame ground plane height used by optional foot-floor constraint.
TYPE:
|
foot_ground_margin
|
Extra non-penetration margin above
TYPE:
|
collision_detection_threshold
|
TYPE:
|
penetration_tolerance
|
TYPE:
|
w_nominal_tracking_init
|
TYPE:
|
nominal_tracking_tau
|
Exponential decay constant for nominal tracking weight.
TYPE:
|
activate_foot_sticking
|
TYPE:
|
activate_foot_z_sticking
|
Keep a sticking foot's z close to the previous frame's, to reduce vertical jitter during stance.
TYPE:
|
activate_foot_ground_constraint
|
Bound every
TYPE:
|
activate_obj_non_penetration
|
TYPE:
|
activate_joint_limits
|
TYPE:
|
w_root
|
Weight of the root-position tracking term (floating base only; the first
TYPE:
|
n_iter_init
|
Maximum SQP iterations on the first frame and on every later one (both >= 1).
TYPE:
|
n_iter
|
Maximum SQP iterations on the first frame and on every later one (both >= 1).
TYPE:
|
Source code in eden/extensions/retargeting/omniretarget/retargeter.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
Attributes¶
foot_z_sticking_tolerance
class-attribute
instance-attribute
¶
foot_z_sticking_tolerance: float = 0.005
collision_detection_threshold
class-attribute
instance-attribute
¶
collision_detection_threshold: float = 0.1
activate_foot_z_sticking
class-attribute
instance-attribute
¶
activate_foot_z_sticking: bool = False
activate_foot_ground_constraint
class-attribute
instance-attribute
¶
activate_foot_ground_constraint: bool = False
activate_obj_non_penetration
class-attribute
instance-attribute
¶
activate_obj_non_penetration: bool = True
smplh_mapped_joint_indices
instance-attribute
¶
smplh_mapped_joint_indices: list[int] = [self.demo_joints.index(name) for name in self.laplacian_match_links]
nominal_tracking_joint_indices
instance-attribute
¶
nominal_tracking_joint_indices = np.array([self.dofs_name.index(name) for name in self.nominal_tracking_dofs], dtype=int)
nominal_tracking_dof_indices
instance-attribute
¶
Methods:¶
retarget_motion
¶
retarget_motion(human_joint_motions: ndarray, foot_sticking_sequences: list[dict[str, bool]], object_name: str | None = None, object_poses: ndarray | None = None, scale_factor: float = 1.0, q_a_init: ndarray | None = None, q_nominal_list: ndarray | None = None, n_surface_points: int = 100, constant_nominal_weight: bool = True) -> ndarray
Run the full retargeting loop over all frames.
| PARAMETER | DESCRIPTION |
|---|---|
human_joint_motions
|
Human joint positions, shape
TYPE:
|
foot_sticking_sequences
|
TYPE:
|
object_name
|
Entity name in the environment (e.g.
TYPE:
|
object_poses
|
TYPE:
|
scale_factor
|
Ratio
TYPE:
|
q_a_init
|
Optional initial qpos, shape
TYPE:
|
q_nominal_list
|
Optional nominal trajectory, shape
TYPE:
|
n_surface_points
|
Number of surface points to sample from the object entity.
TYPE:
|
constant_nominal_weight
|
If True, use a constant nominal tracking weight; if False, apply exponential decay over frames.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
retargeted
|
TYPE:
|
Source code in eden/extensions/retargeting/omniretarget/retargeter.py
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | |
iterate
¶
iterate(q_n: ndarray, q_t_last: ndarray, target_laplacian: ndarray, adj_list: list[set], obj_pts_local: ndarray, foot_sticking: dict[str, bool], w_nominal_tracking: float, q_nominal_joints: ndarray | None, init_t: bool, n_iter: int, obj_pos: ndarray, obj_quat: ndarray, target_root_pos: ndarray | None = None, object_name: str | None = None) -> tuple[ndarray, float]
Source code in eden/extensions/retargeting/omniretarget/retargeter.py
solve_single_iteration
¶
solve_single_iteration(q_n: ndarray, q_t_last: ndarray, target_laplacian: ndarray, adj_list: list[set], obj_pts_local: ndarray, foot_sticking: dict[str, bool], w_nominal_tracking: float, q_nominal_joints: ndarray | None, init_t: bool, obj_pos: ndarray, obj_quat: ndarray, target_root_pos: ndarray | None = None, p_foot_t_last: dict[str, ndarray] | None = None, object_name: str | None = None) -> tuple[ndarray, float]
Build & solve a single convex sub-problem.
Returns (q_new, cost).
Source code in eden/extensions/retargeting/omniretarget/retargeter.py
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 | |
Functions:¶
G1 (29-DOF) OmniRetarget setup + human-motion preprocessing.
Single source of truth shared by the eden retarget omniretarget CLI and
examples/recipes/retargeting/omniretarget/retarget_robot_only.py: the foot-sticking / link-offset
/ manual-bound tables that configure :class:OmniRetargeter for the Unitree G1,
plus the two motion-preprocessing helpers (height/scale normalization and
foot-sticking detection).
Attributes¶
FOOT_STICKING_LINKS
module-attribute
¶
FOOT_STICKING_LINKS = {'left_sphere_1': 'left_ankle_roll_link', 'left_sphere_2': 'left_ankle_roll_link', 'left_sphere_3': 'left_ankle_roll_link', 'left_sphere_4': 'left_ankle_roll_link', 'right_sphere_1': 'right_ankle_roll_link', 'right_sphere_2': 'right_ankle_roll_link', 'right_sphere_3': 'right_ankle_roll_link', 'right_sphere_4': 'right_ankle_roll_link'}
LINK_OFFSETS
module-attribute
¶
LINK_OFFSETS = {'L_Toe': np.array([0.14, 0.0, -0.03]), 'R_Toe': np.array([0.14, 0.0, -0.03]), 'left_sphere_1': np.array([-0.05, 0.025, -0.03]), 'left_sphere_2': np.array([-0.05, -0.025, -0.03]), 'left_sphere_3': np.array([0.12, 0.03, -0.03]), 'left_sphere_4': np.array([0.12, -0.03, -0.03]), 'right_sphere_1': np.array([-0.05, 0.025, -0.03]), 'right_sphere_2': np.array([-0.05, -0.025, -0.03]), 'right_sphere_3': np.array([0.12, 0.03, -0.03]), 'right_sphere_4': np.array([0.12, -0.03, -0.03])}
MANUAL_LB
module-attribute
¶
MANUAL_LB = {'waist_roll_joint': -0.3, 'waist_pitch_joint': -0.1, 'left_wrist_roll_joint': -0.1, 'left_wrist_pitch_joint': -0.1, 'left_wrist_yaw_joint': -0.05, 'right_wrist_roll_joint': -0.1, 'right_wrist_pitch_joint': -0.1, 'right_wrist_yaw_joint': -0.05}
MANUAL_UB
module-attribute
¶
MANUAL_UB = {'waist_roll_joint': 0.3, 'left_elbow_joint': 1.4, 'left_wrist_roll_joint': 0.2, 'left_wrist_pitch_joint': 0.3, 'left_wrist_yaw_joint': 0.05, 'right_elbow_joint': 1.4, 'right_wrist_roll_joint': 0.2, 'right_wrist_pitch_joint': 0.3, 'right_wrist_yaw_joint': 0.05}
NOMINAL_TRACKING_DOFS
module-attribute
¶
NOMINAL_TRACKING_DOFS = ['left_hip_pitch_joint', 'left_hip_roll_joint', 'left_hip_yaw_joint', 'left_knee_joint', 'left_ankle_pitch_joint', 'left_ankle_roll_joint', 'right_hip_pitch_joint', 'right_hip_roll_joint', 'right_hip_yaw_joint', 'right_knee_joint', 'right_ankle_pitch_joint', 'right_ankle_roll_joint']
FOOT_STICKING_MAP
module-attribute
¶
FOOT_STICKING_MAP = {'L_Toe': ['left_sphere_1', 'left_sphere_2', 'left_sphere_3', 'left_sphere_4'], 'R_Toe': ['right_sphere_1', 'right_sphere_2', 'right_sphere_3', 'right_sphere_4']}
Functions:¶
preprocess_human_motion
¶
preprocess_human_motion(human_joints: ndarray, demo_joints: list[str], toe_names: list[str], scale: float, mat_height: float = 0.1) -> ndarray
Lower the human motion so its lowest toe sits at mat_height (at 0 when it starts below
mat_height), then scale every coordinate by scale to robot size.
Returns a new array; human_joints is left as it was.
Source code in eden/extensions/retargeting/omniretarget/g1_presets.py
extract_foot_sticking_velocity
¶
extract_foot_sticking_velocity(human_joints: ndarray, demo_joints: list[str], toe_names: list[str], velocity_threshold: float = 0.01) -> list[dict[str, bool]]
Flag, per frame, whether each toe's planar displacement since the previous frame is at most
velocity_threshold (metres per frame, not m/s). Frame 0 is never flagged.
Source code in eden/extensions/retargeting/omniretarget/g1_presets.py
Interaction-mesh helpers for OmniRetarget: Delaunay adjacency and Laplacian coordinates.
Functions:¶
compute_delaunay_simplices
¶
Compute Delaunay tetrahedralization, returning simplex indices.
get_adjacency_list
¶
Build an adjacency list from tetrahedra.
Returns a list of sets (one per vertex) containing neighbour indices.
Source code in eden/extensions/retargeting/omniretarget/utils.py
calculate_laplacian_matrix
¶
Compute the (N x N) Laplacian matrix (uniform weights, sparse CSR) of vertices.
adj_list holds each vertex's neighbours, e.g. from :func:get_adjacency_list.
Source code in eden/extensions/retargeting/omniretarget/utils.py
calculate_laplacian_coordinates
¶
calculate_laplacian_coordinates(vertices: ndarray, adj_list: list[set]) -> tuple[csr_matrix, ndarray]
Return (laplacian_matrix, laplacian_coordinates).
Laplacian coordinates = L @ V, capturing per-vertex differential structure of the mesh.
Source code in eden/extensions/retargeting/omniretarget/utils.py
OTRetarget¶
Joint robot and object retargeting from surface interactions via entropic optimal transport. OTRetargeter is the
solver; FloorStance and HandGrasp are its add-ons; the presets bundle G1 and LimX Oli rigs, with or without Wuji
hands.
OTRetarget: joint robot and multi-object motion retargeting via optimal transport (arXiv 2609.36602).
Per frame t the retargeter solves (Eq. 1)::
min_{q_t, {T^o_t}} E_int + E_sty_r + E_sty_o + |q_t (-) q_{t-1}|^2 s.t. C(q_t, {T^o_t})
E_int(Eq. 5-6) carries the demonstration's surface interactions. Every probep(dense surface samples on the robot links and on the objects) reads a proximity triple(d, w, n)from every channelc(the ground and each object): signed distance, witness (closest surface point) and the witness-to-probe direction. Its target triple comes from the human probe it is transported from (src(p), one entropic OT plan per pre-assigned part/link group, solved in the T-pose) or, for an object probe, from the same point of the demonstrated object. Residuals penalise the depth gap, the geodesic witness displacement and the wrong side of the demonstrated contact plane, weighted by proximity kernels and normalised per link.E_sty_r/E_sty_o(Eq. 7) keep the motion style: tracked links follow the human joint orientations through T-pose alignment offsets, and positions derived from those orientations by forward kinematics over the robot's own link lengths (native scale — nothing is rescaled); each object is centred on its demonstrated trajectory.Cholds joint position and velocity limits, signed-distance non-penetration of every probe-channel pair, capsule self-collision, and per-object displacement/corridor boxes.
The robot pose and every free object pose are solved jointly by a trust-region SQP (Eq. 8): Gauss-Newton
Hessian, linearised constraints, one dense QP per iterate (ProxQP, :mod:.solver), 50 iterations on the
cold-started first frame and a few warm-started ones after.
This module is the method alone; it knows nothing of feet or hands. What one kind of embodiment or data needs on top
is an :class:Addon (OTRetargeter.addons): :class:~.stance.FloorStance (legged robots on a floor) and
:class:~.grasp.HandGrasp (dexterous hands). examples/recipes/retargeting/otretarget/README.md tabulates every
departure from the paper, with its measurements.
Classes¶
InteractionObject
dataclass
¶
InteractionObject(name: str, mesh: Trimesh, poses: ndarray, demo_mesh: Trimesh | None = None, fixed: bool = False, weight: float = 1.0)
A manipulated (or static) object of the demonstration.
| ATTRIBUTE | DESCRIPTION |
|---|---|
name |
Channel name (used for the output poses).
TYPE:
|
mesh |
The object geometry in the retargeted scene, in the object frame.
TYPE:
|
poses |
TYPE:
|
demo_mesh |
The geometry the human actually interacted with, when
TYPE:
|
fixed |
Hold the object on its demonstrated trajectory instead of making its pose a decision variable.
TYPE:
|
weight |
The object's
TYPE:
|
RetargetResult
dataclass
¶
RetargetResult(qpos: ndarray, entity_qpos: dict[str, ndarray], object_poses: dict[str, ndarray], fps: float, info: dict[str, ndarray] = dict(), stats: dict[str, float] = dict())
Retargeted trajectories.
| ATTRIBUTE | DESCRIPTION |
|---|---|
qpos |
TYPE:
|
entity_qpos |
The same split per entity, ready for |
object_poses |
|
fps |
Frame rate.
TYPE:
|
info |
Per-frame solver diagnostics ( |
stats |
Whole-run figures: |
Attributes¶
Methods:¶
save
¶
save(path: str) -> None
Write everything to one .npz.
Source code in eden/extensions/retargeting/otretarget/retargeter.py
Targets
dataclass
¶
Targets(distance: ndarray, witness: ndarray, normal: ndarray, geodesic_hat: list | None = None, closed: ndarray | None = None)
Frame
dataclass
¶
Frame(t: int, q_prev: ndarray | None, obj_prev_pos: ndarray, obj_prev_rot: ndarray, demo_pos: ndarray, demo_rot: ndarray, demo_step: ndarray | None, demo_delta: ndarray | None, root_delta: ndarray | None, robot_t: list[Targets], object_t: list[Targets], human_t: list[Targets], style_pos: ndarray, style_rot: ndarray, dt: float, free_cols: ndarray | None = None, stage: str = 'main', extra: dict = dict())
Targets and bounds of one frame's solve. q_prev and the previous object poses are what it is smoothed
toward (q_prev None: not smoothed); free_cols (velocity columns) are the only ones that move when set, and
stage names the solve ("main", or an add-on's stage). extra holds what add-ons put in for their terms.
ProbeSet
dataclass
¶
ProbeSet(kind: str, ci: int, x: ndarray, d: ndarray, grad: ndarray, wit: ndarray, wjac: ndarray, targets: Targets, active: ndarray, collide: ndarray, world: ndarray, R: ndarray, tau: ndarray)
Linearization
dataclass
¶
Linearization(frame: Frame, gn: GaussNewton, obj_pos: ndarray, obj_rot: ndarray, link_pos: ndarray, link_rot: ndarray, link_jac: ndarray, r_world: ndarray, support_C: list, support_l: list)
Run
dataclass
¶
Run(human: HumanSurfaceMotion, objects: list[InteractionObject], out_q: ndarray, out_obj: ndarray, info: dict[str, ndarray])
One retarget_motion call: the demonstration and the outputs written so far.
Addon
¶
Addon(rt: OTRetargeter, options)
Bases: ConfigurableMixin[DynamicConfigurableOptions]
A stage or cost term added to :class:OTRetargeter for one kind of embodiment or data (see addons).
The retargeter calls each hook at a fixed point of its loop; the defaults do nothing. Options are the add-on's class attributes, as for any configurable; an unknown key is an error at construction.
Source code in eden/extensions/retargeting/otretarget/retargeter.py
Attributes¶
Methods:¶
setup
¶
setup(human: HumanSurfaceMotion) -> None
Per demonstration, after the transport plans and the object channels; resets per-clip state.
cold_starts
¶
cold_starts(human: HumanSurfaceMotion, obj_pos: ndarray, obj_rot: ndarray) -> list[ndarray]
Further cold-start configurations of frame 0 (each is solved; rank_start helps pick one).
Source code in eden/extensions/retargeting/otretarget/retargeter.py
rank_start
¶
Rank of one frame-0 solve among n_starts (lower wins; ties go to fewer relaxed QPs, then cost).
frame
¶
frame(human: HumanSurfaceMotion, frame: Frame, forward: bool) -> None
Adjust a frame's targets, or add to frame.extra. forward is True once per frame, in time order.
set_terms
¶
set_terms(lin: Linearization, s: ProbeSet) -> None
terms
¶
terms(lin: Linearization) -> None
after_frame
¶
After frame frame.t is solved: returns (q to continue from, q written out, penetration).
OTRetargeter
¶
OTRetargeter(env: EnvBase, options: RetargeterOptions)
Bases: RetargetingBase
Optimal-transport interaction retargeter for a floating-base rig, with objects.
Rationale and measurements for the options that depart from the paper:
examples/recipes/retargeting/otretarget/README.md.
| PARAMETER | DESCRIPTION |
|---|---|
hand_entity_names
|
Entities welded below |
correspondences
|
TYPE:
|
style_links
|
|
human_root_joint
|
The human joint the rig root's position target sits on (the pelvis;
TYPE:
|
tpose
|
Joint values that put the robot in the human rest T-pose (unlisted joints are zero). |
robot_probe_density
|
|
human_probe_density
|
|
object_probe_density
|
Probes per m^2 on objects (1000 in the paper).
TYPE:
|
min_probes_per_link
|
Floor on probes per link or human part.
TYPE:
|
probe_exclude_links
|
Link regexes that carry no probes. |
use_visual_mesh
|
Sample robot probes and fit capsules on visual meshes.
TYPE:
|
object_solid_voxel
|
Voxel size (m) at which an object mesh whose winding-number sign is not reliable is closed into a solid
before its distance field is baked (:func:
TYPE:
|
sdf_resolution
|
Voxel size of the channel grids (1 cm).
TYPE:
|
exact_band
|
Probes closer than this to a mesh channel read the exact mesh distance, witness and derivatives instead of the grid's (0 keeps the grid everywhere).
TYPE:
|
geodesic_samples
|
Surface samples of each object's geodesic table (all pairs: 4000 samples take 64 MB); the density is
TYPE:
|
max_distance
|
TYPE:
|
kernel_width
|
TYPE:
|
kernel_cap
|
TYPE:
|
ot_epsilon
|
Entropic regularisation of the transport plans (0.1).
TYPE:
|
ot_normal_weight
|
Weight of the normal-agreement term of the transport cost (0: the paper's position-only cost).
TYPE:
|
interaction_weights
|
|
object_interaction_scale
|
Multiplier of those weights for object probes (4).
TYPE:
|
link_weights
|
Per-link |
style_pos_weight
|
TYPE:
|
style_rot_weight
|
TYPE:
|
style_link_weights
|
Per tracked link multiplier of both style weights (default 1): |
object_pos_weight
|
TYPE:
|
object_rot_weight
|
TYPE:
|
object_smooth_weight
|
Weight of each free object's frame-to-frame displacement held to the demonstrated one (not in Eq. 1).
TYPE:
|
smooth_weight
|
Weight of
TYPE:
|
collision_margin
|
TYPE:
|
collision_activation
|
Probe-channel pairs closer than this get a non-penetration row.
TYPE:
|
collision_spacing
|
Non-penetration rows sit on one robot probe per voxel of this size per link (a link smaller than eight voxels gets an eighth of its extent instead).
TYPE:
|
self_collision
|
Add capsule self-collision rows.
TYPE:
|
self_collision_activation
|
Capsule pairs with clearance below this get a row.
TYPE:
|
self_collision_exclude
|
TYPE:
|
capsule_radius_quantile
|
Radius quantile of the capsule fits.
TYPE:
|
joint_velocity_limit
|
Default joint velocity limit (rad/s or m/s).
TYPE:
|
joint_velocity_limits
|
Per-joint overrides. |
joint_limits
|
|
root_speed_slack
|
(m/s) Per axis, the root's displacement stays within the demonstrator's root-joint displacement plus
TYPE:
|
object_corridor
|
|
object_speed_slack
|
(m/s, rad/s) added to the demonstrated per-frame displacement to form |
trust_region
|
Per-DoF step boxes |
penetration_slack
|
A step that drives a probe deeper than it was by more than this (m) is re-solved (see
TYPE:
|
witness_lateral_cap
|
Cap on the lateral curvature factor rho / |c| of the witness residual's Gauss-Newton model.
TYPE:
|
reweight_every
|
Accepted steps between re-evaluations of the reweighted interaction terms within a frame.
TYPE:
|
min_trust_scale
|
Smallest fraction of
TYPE:
|
first_frame_iterations
|
SQP budgets for the cold first frame and the warm-started rest (50, 6).
TYPE:
|
iterations
|
SQP budgets for the cold first frame and the warm-started rest (50, 6).
TYPE:
|
step_tolerance
|
Stop iterating once the step's infinity norm falls below this.
TYPE:
|
ground
|
Add the floor channel; the cold start stands the rig on it.
TYPE:
|
ground_height
|
Floor height (m).
TYPE:
|
addons
|
|
Source code in eden/extensions/retargeting/otretarget/retargeter.py
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | |
Attributes¶
robot_probe_density
class-attribute
instance-attribute
¶
human_probe_density
class-attribute
instance-attribute
¶
interaction_weights
class-attribute
instance-attribute
¶
self_collision_activation
class-attribute
instance-attribute
¶
self_collision_activation: float = 0.03
joint_velocity_limits
class-attribute
instance-attribute
¶
object_speed_slack
class-attribute
instance-attribute
¶
robot_probes
instance-attribute
¶
robot_probes = sample_rig_probes(kin, self.robot_probe_density, self.min_probes_per_link, self.probe_exclude_links, self.use_visual_mesh)
Methods:¶
addon
¶
The add-on name of this retargeter (see addons), or None when it is not configured.
retarget_motion
¶
retarget_motion(human: HumanSurfaceMotion, objects: list[InteractionObject] | None = None, q_init: ndarray | None = None, progress: bool = True) -> RetargetResult
Retarget a demonstration frame by frame.
| PARAMETER | DESCRIPTION |
|---|---|
human
|
The demonstrator's posed surface and skeleton (z-up, metres, native scale).
TYPE:
|
objects
|
Objects of the scene with their demonstrated poses (same frames as
TYPE:
|
q_init
|
TYPE:
|
progress
|
Show a progress bar.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
RetargetResult
|
|
Source code in eden/extensions/retargeting/otretarget/retargeter.py
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | |
solve
¶
One solve of frame from q for an add-on's stage: (q, obj_pos, obj_rot, local, qp_failed).
The object poses are copied; QP counts are not reported.
Source code in eden/extensions/retargeting/otretarget/retargeter.py
Functions:¶
Embodiment presets for OTRetarget: G1 and LimX Oli, with or without Wuji hands; SMPL-X or SOMA demonstrators.
A preset states what the paper calls manual pre-assignment (Sec. III-B, D):
correspondences— which human body parts each group of robot links is matched to; the transport plan is solved per group between the two surface clouds in the T-pose.style_links— the robot links whose world orientation (and FK-derived position) tracks a human joint frame, through an alignment offset measured in the T-pose.tpose— the robot joint values that put it in the human body model's rest T-pose (arms along the lateral axis, palms down, thumbs forward, fingers extended). It is a reference posture only, never executed, so it may lie outside a joint's limits (the G1 elbow does).
Presets name human parts with SMPL-X joints
(:data:~eden.extensions.retargeting.otretarget.human.SMPLX_JOINT_NAMES); :func:for_body_model
translates one to the SOMA rig (BONES-SEED), whose fingers carry an extra metacarpal joint.
Attributes¶
G1_WUJI
module-attribute
¶
G1_WUJI = RigPreset(_WUJI_RIG, _G1_TPOSE, _g1_groups(True), _g1_style(True), 'pelvis', _WUJI_DENSITY, _HUMAN_DENSITY, _WUJI_SELF_COLLISION_EXCLUDE, _WUJI_STYLE_WEIGHTS, _WUJI_INTERACTION_WEIGHTS, _WUJI_JOINT_LIMITS, _WUJI_PALMS, _wuji_tips(), _WUJI_HAND_OPTIONS)
OLI_WUJI
module-attribute
¶
OLI_WUJI = RigPreset(_WUJI_RIG, _OLI_TPOSE, _oli_groups(True), _oli_style(True), 'pelvis', _WUJI_DENSITY, _HUMAN_DENSITY, _WUJI_SELF_COLLISION_EXCLUDE, _WUJI_STYLE_WEIGHTS, _WUJI_INTERACTION_WEIGHTS, _WUJI_JOINT_LIMITS, _WUJI_PALMS, _wuji_tips(), _WUJI_HAND_OPTIONS)
G1
module-attribute
¶
G1 = RigPreset(('robot',), _G1_TPOSE, _g1_groups(False), _g1_style(False), 'pelvis', _BODY_DENSITY, _BODY_DENSITY)
OLI
module-attribute
¶
OLI = RigPreset(('robot',), _OLI_TPOSE, _oli_groups(False), _oli_style(False), 'pelvis', _BODY_DENSITY, _BODY_DENSITY)
PRESETS
module-attribute
¶
SMPLX_TO_SOMA_JOINT
module-attribute
¶
SMPLX_TO_SOMA_JOINT = {k: v[1] if k == 'pelvis' else v[0] for k, v in SMPLX_TO_SOMA_PARTS.items()}
Classes¶
RigPreset
dataclass
¶
RigPreset(entities: tuple[str, ...], tpose: dict[str, float], correspondences: tuple[Group, ...], style_links: dict[str, str], human_root: str = 'pelvis', robot_probe_density: dict[str, float] = dict(), human_probe_density: dict[str, float] = dict(), self_collision_exclude: tuple[tuple[str, str], ...] = (), style_link_weights: dict[str, float] = dict(), interaction_weights: tuple[float, float, float] | None = None, joint_limits: dict[str, tuple[float, float]] = dict(), palms: dict[str, str | list[str]] = dict(), fingertips: dict[str, str] = dict(), hand_options: dict = dict())
Everything embodiment-specific the retargeter needs (see the module docstring).
| ATTRIBUTE | DESCRIPTION |
|---|---|
entities |
Scene entity names of the rig, root first. |
tpose |
Joint values of the T-pose; unlisted joints are zero. |
correspondences |
|
style_links |
|
human_root |
The human joint the rig root is aligned with.
TYPE:
|
robot_probe_density |
|
human_probe_density |
|
self_collision_exclude |
Link-name regex pairs left out of capsule self-collision. |
style_link_weights |
Per tracked link multipliers of the style weights ( |
interaction_weights |
|
joint_limits |
|
palms |
|
fingertips |
|
hand_options |
Further
TYPE:
|
Attributes¶
robot_probe_density
class-attribute
instance-attribute
¶
human_probe_density
class-attribute
instance-attribute
¶
self_collision_exclude
class-attribute
instance-attribute
¶
style_link_weights
class-attribute
instance-attribute
¶
interaction_weights
class-attribute
instance-attribute
¶
joint_limits
class-attribute
instance-attribute
¶
palms
class-attribute
instance-attribute
¶
fingertips
class-attribute
instance-attribute
¶
Methods:¶
retargeter_options
¶
retargeter_options() -> dict
The preset as :class:~eden.extensions.retargeting.otretarget.OTRetargeter configure keywords: a legged
rig on the floor (floor_stance), and its hands when it has palms (hand_grasp).
Source code in eden/extensions/retargeting/otretarget/presets.py
Functions:¶
for_body_model
¶
The preset with its human side expressed in another body model's joints.
| PARAMETER | DESCRIPTION |
|---|---|
preset
|
A preset in SMPL-X joint names.
TYPE:
|
body_model
|
Target body model.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/presets.py
Legged stance on the floor: an add-on of :class:~.retargeter.OTRetargeter (addons={"floor_stance": {...}}).
The paper keeps foot-floor contact in the cost only, as the floor channel's interaction terms, normalised per link and
at the demonstrator's own footprints. On a robot of other proportions that floats the feet, slides them and pulls them
onto the human's stance width. Three additions, each an option below (measurements in
examples/recipes/retargeting/otretarget/README.md):
- Footprint offset — the floor is translation invariant, so where on it a foot lands is posture: each robot probe's floor witness is shifted sideways by how much wider than its human source it sits from the root in the T-pose.
- Support — a body unit (correspondence group) whose demonstrated sole is on the floor keeps its lowest point there, as a constraint.
- No-slip stance — a foot planted on two frames follows the human foot's planar rigid motion about its own contact (anchor probes as constraints), and its floor witnesses move with it.
Classes¶
FloorStance
¶
Bases: Addon
Footprint offset, floor support and no-slip stance on the floor channel (needs ground).
| PARAMETER | DESCRIPTION |
|---|---|
footprint_offset
|
Shift each robot probe's demonstrated floor witness sideways by how far that probe sits from the root in the T-pose beyond where its human source sits from the pelvis (lateral, in the root frame, turned with the demonstrated heading). A probe whose source stays in floor contact keeps the offset it landed with.
TYPE:
|
footprint_contact
|
(m) A probe whose human source is within this of the floor is in contact.
TYPE:
|
support_height
|
(m) On every body unit with a downward-facing probe whose human source is within
TYPE:
|
support_slack
|
(m) On every body unit with a downward-facing probe whose human source is within
TYPE:
|
stick
|
No-slip stance: while probes of a unit have their sources in contact on two consecutive frames, a few of its
probes on the floor (anchors) follow the human foot's planar rigid motion about the robot foot's own contact,
within
TYPE:
|
stick_slack
|
(m) Horizontal displacement allowed per frame beyond the demonstrated one.
TYPE:
|
stick_height
|
(m) Anchors are probes in contact within this of the robot unit's lowest point on the previous solution.
TYPE:
|
stick_release
|
(m) Human foot travel after lift-off over which the floor witnesses return to the footprint targets.
TYPE:
|
stick_anchors
|
Anchors per unit in contact: the lowest one, then each farthest from those already chosen.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/stance.py
Attributes¶
Methods:¶
setup
¶
setup(human: HumanSurfaceMotion) -> None
Source code in eden/extensions/retargeting/otretarget/stance.py
frame
¶
frame(human: HumanSurfaceMotion, frame: Frame, forward: bool) -> None
Source code in eden/extensions/retargeting/otretarget/stance.py
set_terms
¶
set_terms(lin: Linearization, s: ProbeSet) -> None
Source code in eden/extensions/retargeting/otretarget/stance.py
terms
¶
terms(lin: Linearization) -> None
Source code in eden/extensions/retargeting/otretarget/stance.py
Functions:¶
Dexterous-hand grasps: an add-on of :class:~.retargeter.OTRetargeter (addons={"hand_grasp": {...}}).
The interaction terms copy the demonstrated hand-object distances. Where the demonstration is loose (fingers hovering 2-4 cm off a pole, the pole sunk into the palm) or the robot hand is of other proportions, copied distances do not make a grasp: the robot fingers hover, and a hand that starts or ends up on the wrong side of a thin part stays there. Three stages, each an option below (measurements in the recipe README):
- Grasp closure — after each frame's solve, the fingers of a grasping hand close on the object in a solve of their own (hand joints only).
- Palm cold start — frame 0 is also started with the touching palms pulled to the human palms' places; the solve that holds more objects on the human palms' side wins.
- Side re-approach — a palm that holds a thin part on the other side from the human palm's is brought round: the frame is solved again with that arm only and a palm goal, and the earlier frames are re-solved back to where the hand is clear.
Classes¶
HandGrasp
¶
Bases: Addon
Grasp closure, palm cold start and side re-approach of the rig's hands.
| PARAMETER | DESCRIPTION |
|---|---|
palms
|
|
fingertips
|
|
contact
|
(m) Human palm/finger distance that counts as touching.
TYPE:
|
closure
|
(m) While a hand grasps (its human palm, or two of its finger pads, within
TYPE:
|
closure_weight
|
(m^-2 per link) Weight of the closure residual, normalised over the probes of each link.
TYPE:
|
cold_start_palm_weight
|
(m^-2) A second cold start: the posture fit with each palm whose human palm touches a free object at frame 0 also pulled to the human palm's place. Frame 0 is solved from both starts; the solve with more palms facing the object as the human palms do wins, then the one with fewer relaxed QPs, then the lower cost. 0 disables.
TYPE:
|
rest_palm_normal
|
The direction the human palms face in the body model's rest pose (SMPL-X: down, |
side_reapproach
|
After each frame's solve, a palm whose human palm holds a thin part of a free object on the other side of the
palm from the robot palm comes round (see
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/grasp.py
Attributes¶
rest_palm_normal
class-attribute
instance-attribute
¶
Methods:¶
setup
¶
setup(human: HumanSurfaceMotion) -> None
Source code in eden/extensions/retargeting/otretarget/grasp.py
cold_starts
¶
cold_starts(human, obj_pos, obj_rot) -> list[ndarray]
Source code in eden/extensions/retargeting/otretarget/grasp.py
rank_start
¶
Minus the number of touching palms that hold the object on the human palm's side (with two starts or more).
Either start can be the wrong one: without the pull a hand of other reach started on the far side of a lamp pole, with it a palm pulled onto a chair's back rail put the arm through the chair. The cost alone does not see the side: the OMOMO palms sink into poles to their middle.
Source code in eden/extensions/retargeting/otretarget/grasp.py
frame
¶
frame(human: HumanSurfaceMotion, frame: Frame, forward: bool) -> None
Source code in eden/extensions/retargeting/otretarget/grasp.py
set_terms
¶
set_terms(lin: Linearization, s: ProbeSet) -> None
Source code in eden/extensions/retargeting/otretarget/grasp.py
terms
¶
terms(lin: Linearization) -> None
Source code in eden/extensions/retargeting/otretarget/grasp.py
after_frame
¶
Source code in eden/extensions/retargeting/otretarget/grasp.py
Functions:¶
The demonstrator's surface: a skinned body mesh posed per frame, plus its joint frames.
OTRetarget reads interactions off the human surface, not its skeleton (Sec. III-A): probes are
sampled on the posed mesh and each one is assigned to the body part that skins it. The skeleton's
joint frames still drive the style cost (Sec. III-D). :class:HumanSurfaceMotion is that pair, in a
z-up metric world, and is all :class:~eden.extensions.retargeting.otretarget.OTRetargeter needs
from a body model — so SMPL-X (OMOMO, AMASS) and the SOMA rig (BONES-SEED BVH) feed it alike.
:class:~eden.datasets.utils.body_model.SkinnedBodyModel, Eden's linear-blend-skinning rig, poses both:
:func:smplx_motion builds it from an SMPL-X model file, and
:func:~eden.extensions.retargeting.otretarget.sources.load_soma_bvh from the SOMA rig.
Attributes¶
SMPLX_JOINT_NAMES
module-attribute
¶
SMPLX_JOINT_NAMES: tuple[str, ...] = ('pelvis', 'left_hip', 'right_hip', 'spine1', 'left_knee', 'right_knee', 'spine2', 'left_ankle', 'right_ankle', 'spine3', 'left_foot', 'right_foot', 'neck', 'left_collar', 'right_collar', 'head', 'left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow', 'left_wrist', 'right_wrist', 'jaw', 'left_eye', 'right_eye', *(f'left_{f}{i}' for f in ('index', 'middle', 'pinky', 'ring', 'thumb') for i in (1, 2, 3)), *(f'right_{f}{i}' for f in ('index', 'middle', 'pinky', 'ring', 'thumb') for i in (1, 2, 3)))
Y_UP_TO_Z_UP
module-attribute
¶
CANONICAL_TO_ROBOT
module-attribute
¶
Classes¶
HumanSurfaceMotion
dataclass
¶
HumanSurfaceMotion(vertices: ndarray, faces: ndarray, skin_weights: ndarray, joint_names: list[str], joint_pos: ndarray, joint_rot: ndarray, rest_vertices: ndarray, rest_joint_pos: ndarray, rest_joint_rot: ndarray, fps: float)
A posed human surface over time, with its skeleton, in a z-up metric world.
| ATTRIBUTE | DESCRIPTION |
|---|---|
vertices |
TYPE:
|
faces |
TYPE:
|
skin_weights |
TYPE:
|
joint_names |
The |
joint_pos |
TYPE:
|
joint_rot |
TYPE:
|
rest_vertices |
TYPE:
|
rest_joint_pos |
TYPE:
|
rest_joint_rot |
TYPE:
|
fps |
Frame rate.
TYPE:
|
Attributes¶
Methods:¶
joint_index
¶
Index of joint name, raising with the available names if absent.
Source code in eden/extensions/retargeting/otretarget/human.py
translated
¶
translated(offset: ndarray) -> HumanSurfaceMotion
The same motion moved by a constant world offset (3,) (the rest pose is unchanged).
Source code in eden/extensions/retargeting/otretarget/human.py
floor_offset
¶
Height of the floor the feet stand on, read off the motion itself.
The quantile of the per-frame lowest foot-vertex height. With at least one foot down in most
frames (standing, walking, carrying, dancing), the median is the stance height: a capture whose
body fit floats (or sinks) by a constant amount reports that amount, and the short flight phase of
a jump does not move it. A low quantile would instead pick the frames where the fit penetrates.
| PARAMETER | DESCRIPTION |
|---|---|
foot_joints
|
Skeleton joints whose skinned vertices make up the feet. |
quantile
|
Quantile over frames.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/human.py
mirrored
¶
mirrored(vertex_mirror: ndarray, joint_mirror: ndarray, local_mirror: ndarray, normal: ndarray, point: ndarray) -> HumanSurfaceMotion
The mirror image of this motion through a world plane: a left-handed demonstration made right-handed.
A reflection alone would turn the left hand into a right-shaped hand still labelled "left". The image is
re-indexed so that every vertex and joint keeps its anatomical name: vertex k of the result is the
reflection of vertex vertex_mirror[k] (its mirror partner on the body), joint j that of joint
joint_mirror[j]. Joint frames become M R L (M the world reflection, L the reflection in
the joint's own frame), proper rotations again; the rest pose is mirrored about its sagittal plane,
which leaves a symmetric rest frame (and so every style alignment offset) unchanged. Face winding is
reversed so normals still point out of the body.
| PARAMETER | DESCRIPTION |
|---|---|
vertex_mirror
|
TYPE:
|
joint_mirror
|
TYPE:
|
local_mirror
|
TYPE:
|
normal
|
TYPE:
|
point
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/human.py
slice
¶
slice(start: int = 0, stop: int | None = None, step: int = 1) -> HumanSurfaceMotion
The same motion restricted to frames start:stop:step (fps divided by step).
Source code in eden/extensions/retargeting/otretarget/human.py
Functions:¶
smplx_motion
¶
smplx_motion(model_path: str, poses: ndarray, trans: ndarray, betas: ndarray, fps: float, flat_hand_mean: bool = False, up_axis: str = 'y', v_template: ndarray | None = None) -> HumanSurfaceMotion
Pose SMPL-X from axis-angle parameters into a :class:HumanSurfaceMotion.
| PARAMETER | DESCRIPTION |
|---|---|
model_path
|
An
TYPE:
|
poses
|
TYPE:
|
trans
|
TYPE:
|
betas
|
Shape coefficients, up to the model's shape components: 300 for an SMPL-X v1.1 file (300 shape + 100 expression blend shapes), 10 for v1.0 (10 + 10). Coefficients past that must be zero.
TYPE:
|
fps
|
Frame rate.
TYPE:
|
flat_hand_mean
|
False adds the model's mean hand pose to the hand parameters (the
TYPE:
|
up_axis
|
The world up axis of
TYPE:
|
v_template
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
HumanSurfaceMotion
|
|
Source code in eden/extensions/retargeting/otretarget/human.py
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | |
Demonstration readers: dataset files to a :class:HumanSurfaceMotion plus :class:InteractionObject tracks.
- :func:
load_grab_sequence— a raw GRAB capture (SMPL-X with a personal template, PCA hands, the object and the table), z-up, 120 fps. - :func:
mirror_demonstration— a left-handed SMPL-X demonstration made right-handed (body and objects). - :func:
load_omomo_sequence— OMOMO in its canonical SMPL-X form (thesequences_canonical/layout of theeden_omomorelease):human.npz(156-d SMPL-X poses with finger articulation, betas, trans, gender) andobject.npz(axis-angle + translation ofobjects/<name>/<name>.obj), y-up. - :func:
load_soma_bvh— a SOMA-skeleton BVH (BONES-SEED) with the SOMA neutral body skinned onto it.
Attributes¶
SMPLX_FOOT_JOINTS
module-attribute
¶
SMPLX_HAND_JOINTS
module-attribute
¶
SMPLX_HAND_JOINTS = tuple(n for n in SMPLX_JOINT_NAMES if any(part in n for part in ('wrist', 'index', 'middle', 'ring', 'pinky', 'thumb')))
SOMA_FOOT_JOINTS
module-attribute
¶
SOMA_FOOT_JOINTS = ('LeftFoot', 'LeftToeBase', 'LeftToeEnd', 'RightFoot', 'RightToeBase', 'RightToeEnd')
Classes¶
Functions:¶
load_omomo_sequence
¶
load_omomo_sequence(sequence_dir: str, objects_dir: str, smplx_dir: str, fps: float = 30.0, flat_hand_mean: bool = True, ground_human: bool = True) -> tuple[HumanSurfaceMotion, InteractionObject]
Read one canonical OMOMO sequence.
| PARAMETER | DESCRIPTION |
|---|---|
sequence_dir
|
TYPE:
|
objects_dir
|
TYPE:
|
smplx_dir
|
Directory with
TYPE:
|
fps
|
The release's frame rate (30).
TYPE:
|
flat_hand_mean
|
Hand pose convention. The release's hand poses are offsets from a flat hand: read with the mean hand added, the fingers of a box-carrying subject curl ~2 cm into the box.
TYPE:
|
ground_human
|
Move the human vertically so its feet stand on z = 0 (:meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
human
|
TYPE:
|
obj
|
The object with its demonstrated trajectory, z-up.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/sources.py
load_grab_sequence
¶
load_grab_sequence(sequence_path: str, grab_root: str, smplx_dir: str, start: int = 0, stop: int | None = None, step: int = 4, ground: bool = True, table_thickness: float = 0.03) -> tuple[HumanSurfaceMotion, list[InteractionObject]]
Read one raw GRAB capture (grab/<subject>/<object>_<intent>.npz) with its object and table.
The raw release is used, not a re-processed copy: its object poses fit the contact_meshes/*.ply scans
as shipped (InterAct's re-centred objects/*.obj are off by up to 1.4 cm against the same poses), and it
carries the table. Conventions, as in GRAB's own body and object models:
- z-up world, metres, 120 fps;
stepframes are skipped (4 -> 30 fps). - Body: SMPL-X with the subject's personal template (
vtemp) andbetas= 0.fullposealready holds the 45-d hand poses expanded from the 24 PCA components with the mean hand added, so it is read asflat_hand_mean=True. - Object and table:
v_world = v_local @ R(global_orient) + transl, i.e. the column-vector rotation isR(global_orient).T.
The table mesh is a 5.5 mm slab. It is replaced by a table_thickness plate with the same footprint and
the same top face (tilt included), held fixed at its first-frame pose: GRAB's table does not move.
| PARAMETER | DESCRIPTION |
|---|---|
sequence_path
|
TYPE:
|
grab_root
|
The folder the npz's mesh paths are relative to (holding
TYPE:
|
smplx_dir
|
Directory with
TYPE:
|
start
|
Raw (120 fps) frame range and stride.
TYPE:
|
stop
|
Raw (120 fps) frame range and stride.
TYPE:
|
step
|
Raw (120 fps) frame range and stride.
TYPE:
|
ground
|
Move the whole scene (body, object, table) vertically so the feet stand on z = 0. Body, object and table come from one marker capture, so they move together; moving only the body (as for OMOMO) would open a gap between the hand and the object.
TYPE:
|
table_thickness
|
Thickness of the table plate (m).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
human
|
TYPE:
|
objects
|
The object, then the fixed
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/sources.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |
smplx_mirror_maps
¶
SMPL-X's left/right correspondences: the mirror partner of every vertex and every joint.
The model's mean template is symmetric about its sagittal plane (x = 0): each vertex reflected through it lands on another vertex (within 15 um), or on itself on the midline. The partners are found that way and checked to form an involution.
| PARAMETER | DESCRIPTION |
|---|---|
model_path
|
An
TYPE:
|
tolerance
|
Largest allowed gap (m) between a reflected vertex and its partner.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
vertex_mirror
|
TYPE:
|
joint_mirror
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/sources.py
mirror_object
¶
mirror_object(obj: InteractionObject, normal: ndarray, point: ndarray, local_mirror: ndarray = SMPLX_LOCAL_MIRROR) -> InteractionObject
The mirror image of an object track through a world plane (the object of a mirrored demonstration).
v_world = R v + p reflected is (M R L)(L v) + M p + s: the mesh is reflected in its own frame by
L (face winding reversed, so it stays outward-facing) and the pose becomes M R L, a proper rotation.
A chiral object becomes its mirror twin; a symmetric one comes out the same shape.
| PARAMETER | DESCRIPTION |
|---|---|
obj
|
The object track to mirror.
TYPE:
|
normal
|
TYPE:
|
point
|
TYPE:
|
local_mirror
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/sources.py
mirror_demonstration
¶
mirror_demonstration(human: HumanSurfaceMotion, objects: list[InteractionObject], smplx_model_path: str) -> tuple[HumanSurfaceMotion, list[InteractionObject]]
Mirror an SMPL-X demonstration and its objects through the demonstrator's first-frame sagittal plane.
The plane holds the pelvis and the pelvis' forward and up directions at frame 0, so the mirrored person starts where the original did, facing the same way, with every left/right role swapped.
Source code in eden/extensions/retargeting/otretarget/sources.py
load_soma_bvh
¶
load_soma_bvh(bvh_path: str, soma_model_path: str, fps: float = 30.0, ground_human: bool = True) -> HumanSurfaceMotion
Read a SOMA-skeleton BVH (BONES-SEED) and skin the SOMA neutral body onto it.
The BVH drives the SOMA rig's 78 joints directly (same joint names and joint frames); the neutral
mesh of SOMA_neutral.npz is scaled to the actor's overall bone length and skinned to the BVH's
world joint transforms, so every limb, foot included, follows the captured skeleton.
| PARAMETER | DESCRIPTION |
|---|---|
bvh_path
|
A SOMA-rig
TYPE:
|
soma_model_path
|
TYPE:
|
fps
|
Output frame rate; the capture rate must be an integer multiple of it.
TYPE:
|
ground_human
|
Move the motion vertically so the feet stand on z = 0 (:meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
HumanSurfaceMotion
|
|
Source code in eden/extensions/retargeting/otretarget/sources.py
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | |
Untracked supports: the tables and stools a demonstrated object rests on but the capture does not track.
A demonstration such as "put the monitor on the table" tracks the monitor, not the table. Retargeted without the
table, nothing holds the resting object up: within the interaction range the robot's hands pull it down toward
them (up to 22 cm on HiPHI). :func:find_untracked_supports reads each support off the object track and gives
it back as a thin plate, which the retargeter takes as a fixed object.
A support is found where the object rests still above the floor with no hand on it (so it is not being held still in the air), and only if it could be resting on a level surface: one horizontal level of the object (its lowest one, or the seat of an upside-down chair whose backrest hangs over the table edge) must hold the object's centre of mass in plan view, with nothing of the object directly below it. A tilted object touching down on one corner, or one floating a few centimetres over the floor (a capture offset, not furniture), gives no support.
The plate is the support's top only: a block or a slab on legs fills the space where the demonstrator's (and so the robot's) legs stand against the table, and the non-penetration rows then reject every robot step.
Classes¶
Support
dataclass
¶
Support(name: str, height: float, center: ndarray, yaw: float, extents: ndarray, frames: tuple[int, int])
A plate standing in for an untracked support.
| ATTRIBUTE | DESCRIPTION |
|---|---|
name |
The fixed object's name (
TYPE:
|
height |
Height of the plate's top surface (m): the level the object rests on.
TYPE:
|
center |
TYPE:
|
yaw |
Plate heading (rad) about the vertical.
TYPE:
|
extents |
TYPE:
|
frames |
The resting segment |
Attributes¶
Methods:¶
pose
¶
(7,) [pos, quat_wxyz] of the plate's centre.
Source code in eden/extensions/retargeting/otretarget/supports.py
to_dict
¶
to_dict() -> dict
JSON-ready record: name, top height, plate pose [pos, quat_wxyz], extents and source frames.
Source code in eden/extensions/retargeting/otretarget/supports.py
as_object
¶
as_object(n_frames: int) -> InteractionObject
The plate as a fixed :class:InteractionObject over n_frames frames.
Source code in eden/extensions/retargeting/otretarget/supports.py
Functions:¶
find_untracked_supports
¶
find_untracked_supports(obj: InteractionObject, hand_points: ndarray, *, min_height: float = 0.15, floor_gap: float = 0.05, static_speed: float = 0.002, static_turn_deg: float = 0.5, hand_clearance: float = 0.06, min_frames: int = 5, level_band: float = 0.015, horizontal_deg: float = 18.0, com_tolerance: float = 0.01, margin: float = 0.02, clearance: float = 0.01, min_side: float = 0.1, thickness: float = 0.03) -> list[Support]
The untracked supports obj rests on in a demonstration (see the module docstring).
| PARAMETER | DESCRIPTION |
|---|---|
obj
|
The tracked object, z-up, floor at
TYPE:
|
hand_points
|
TYPE:
|
min_height
|
A resting level lower than this is the floor seen through a capture offset, not furniture.
TYPE:
|
floor_gap
|
The object's lowest point must be this far above the floor for a frame to count as resting elevated.
TYPE:
|
static_speed
|
Per-frame translation (m) and rotation (deg) below which the object is still.
TYPE:
|
static_turn_deg
|
Per-frame translation (m) and rotation (deg) below which the object is still.
TYPE:
|
hand_clearance
|
Every hand point must be this far from the object (m): a held object is not resting.
TYPE:
|
min_frames
|
Shortest resting segment.
TYPE:
|
level_band
|
Thickness of one horizontal level of the object (m).
TYPE:
|
horizontal_deg
|
Faces within this angle of horizontal (either facing) make up the levels.
TYPE:
|
com_tolerance
|
How far outside the level's footprint the centre of mass may lie (m).
TYPE:
|
margin
|
The plate reaches this far beyond the level's footprint (m), before clearing hanging parts.
TYPE:
|
clearance
|
Gap kept between the plate and any part of the object below the level (m).
TYPE:
|
min_side
|
A plate narrower than this (after clearing hanging parts) is no support.
TYPE:
|
thickness
|
Plate thickness (m).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[Support]
|
One per distinct support (resting segments at the same place and height share one). |
Source code in eden/extensions/retargeting/otretarget/supports.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
The retargeted robot as one kinematic tree over several Eden entities, with analytic Jacobians.
A dexterous humanoid is usually a composite (G1Wuji, OliWuji): a floating-base body entity
plus hand entities welded to its wrists, each with its own qpos. The solver needs one
configuration and one tangent space across all of them, and the Jacobian of any point on any link
with respect to every degree of freedom that moves it — including the body's joints for a point on a
fingertip, which no single entity's get_jacobian provides.
:class:RigKinematics builds that from the entities' joint anchors and axes. Forward kinematics
stays Genesis' (set_qpos + link poses), so the link frames, joint placements and the meshes
probes are sampled from all come from one source. The tangent space is::
v = [base translation (3, world), base rotation (3, world rotation vector), joints...]
for a floating root (the base block is absent for a fixed one), with the retraction
p <- p + dp and R <- exp(dtheta) R — the same convention the paper uses for object poses, and
independent of how Genesis parameterises its free joint internally.
Classes¶
RigKinematics
¶
Kinematics of a robot spread over a root entity and welded child entities.
| PARAMETER | DESCRIPTION |
|---|---|
env
|
A built env holding the entities (
TYPE:
|
entity_names
|
The root entity first (floating or fixed base), then every entity welded below it. Each child must be attached (no free root of its own) and every joint must be fixed, revolute or prismatic, apart from the root's floating joint. |
| ATTRIBUTE | DESCRIPTION |
|---|---|
link_names |
Every link of the rig, root entity first; names must be unique across the entities. |
n_v |
Tangent dimension (6 for a floating base, plus one per joint).
TYPE:
|
n_q |
Configuration dimension (7 for a floating base, plus one per joint).
TYPE:
|
var_names |
One name per tangent entry ( |
Source code in eden/extensions/retargeting/otretarget/kinematics.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | |
Attributes¶
link_parent
instance-attribute
¶
link_parent = np.array([global_to_local.get(all_links[g].parent_idx, -1) for g in self._link_global], dtype=np.int64)
var_names
instance-attribute
¶
var_names: list[str] = ['base_x', 'base_y', 'base_z', 'base_rx', 'base_ry', 'base_rz'] if self.floating else []
joint_moves_link
instance-attribute
¶
joint_moves_link = np.array([[self._joint_link[k] in chain[li] for k in range(len(self._joint_link))] for li in range(n_links)], dtype=bool).reshape(n_links, len(self._joint_link))
Methods:¶
entity_qpos
¶
entity_qpos(q: ndarray) -> list[ndarray]
Split a rig configuration into each entity's qpos (dofs_name order).
set_configuration
¶
Write configuration q to the entities (runs Genesis forward kinematics).
Source code in eden/extensions/retargeting/otretarget/kinematics.py
link_poses
¶
link_poses() -> tuple[ndarray, ndarray]
World (L, 3) positions and (L, 3, 3) orientations of every rig link at the set configuration.
Source code in eden/extensions/retargeting/otretarget/kinematics.py
integrate
¶
Retract tangent step v onto configuration q (q (+) v).
Source code in eden/extensions/retargeting/otretarget/kinematics.py
difference
¶
Tangent v with q0 (+) v = q1 (q1 (-) q0).
Source code in eden/extensions/retargeting/otretarget/kinematics.py
link_index
¶
Rig index of link name, raising with the available names if absent.
Source code in eden/extensions/retargeting/otretarget/kinematics.py
link_jacobians
¶
Spatial Jacobians of every link: (L, 6, n_v), rows [v of the link origin; omega] (world).
A point p on link l moves with J_v - [p - o_l]x J_omega, so a scalar residual with
world gradient c at p has the row [c; (p - o_l) x c]^T J6_l: residuals on one link can
be accumulated as a 6x6 block before touching the n_v columns.
Source code in eden/extensions/retargeting/otretarget/kinematics.py
Functions:¶
Interaction channels: the surfaces probes read proximity triples (d, w, n) from (Sec. III-B).
A channel is a rigid surface — the ground or a manipulated object — with, in its own frame,
- a signed distance
Phi(x)and a witnessW(x)(the closest surface point), and - a geodesic distance
rho(w; w_hat)between two surface points (the placement residualr^x).
For a mesh, Phi and W are baked once on a voxel grid around the object (1 cm isotropic by
default, reaching max_distance past the surface) and read back by trilinear interpolation, so a
query costs no mesh search and the grid never needs recomputing as the object moves. For the ground,
both are affine and exact. Geodesics are all-pairs shortest paths over the channel's surface point
cloud, interpolated to arbitrary witness points through their nearest samples.
Classes¶
ChannelQuery
dataclass
¶
ChannelQuery(distance: ndarray, witness: ndarray, distance_grad: ndarray, witness_jac: ndarray, valid: ndarray)
Proximity of query points to a channel, all in the channel frame.
| ATTRIBUTE | DESCRIPTION |
|---|---|
distance |
TYPE:
|
witness |
TYPE:
|
distance_grad |
TYPE:
|
witness_jac |
TYPE:
|
valid |
TYPE:
|
Channel
¶
Bases: ABC
A rigid surface probes measure proximity to.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The channel's name (the scene entity name for an object,
TYPE:
|
max_distance
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/channels.py
Attributes¶
Methods:¶
query
abstractmethod
¶
query(points: ndarray) -> ChannelQuery
geodesic
abstractmethod
¶
geodesic(w: ndarray, w_hat: ndarray, n_w: ndarray | None = None, n_hat: ndarray | None = None) -> tuple[ndarray, ndarray]
Geodesic distance rho(w; w_hat) between surface points, and its gradient in w.
| PARAMETER | DESCRIPTION |
|---|---|
w
|
TYPE:
|
w_hat
|
TYPE:
|
n_w
|
TYPE:
|
n_hat
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
rho
|
TYPE:
|
grad
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/channels.py
exact_distance
abstractmethod
¶
exact_distance(points: ndarray) -> tuple[ndarray, ndarray]
Exact (not grid-interpolated) signed distance and closest point, for evaluation.
exact_query
abstractmethod
¶
exact_query(points: ndarray) -> ChannelQuery
Like :meth:query, from the exact surface (for points beyond the baked region).
PlaneChannel
¶
Bases: Channel
The ground: the plane z = 0 of its frame, with +z outside.
Phi(x) = x_z and W(x) = (x_x, x_y, 0) exactly, at any distance; the geodesic between two
plane points is their Euclidean distance.
Source code in eden/extensions/retargeting/otretarget/channels.py
Methods:¶
query
¶
query(points: ndarray) -> ChannelQuery
Source code in eden/extensions/retargeting/otretarget/channels.py
geodesic
¶
geodesic(w: ndarray, w_hat: ndarray, n_w: ndarray | None = None, n_hat: ndarray | None = None) -> tuple[ndarray, ndarray]
Source code in eden/extensions/retargeting/otretarget/channels.py
exact_query
¶
exact_query(points: ndarray) -> ChannelQuery
MeshChannel
¶
MeshChannel(name: str, mesh: Trimesh, max_distance: float, resolution: float = 0.01, geodesic_density: float = 1000.0, solid_voxel: float = 0.0)
Bases: Channel
A rigid mesh, with Phi/W baked on a voxel grid in the mesh frame.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The channel's name.
TYPE:
|
mesh
|
The surface, in the channel (object) frame. The sign comes from the generalised winding number, which is
only right on a closed, consistently oriented surface: on an open scan (a bin) it reads the empty cavity as
solid and flips sign across the opening, so the distance jumps from +5 to -5 cm between two neighbouring
points, and walls scanned as zero-thickness sheets have no inside at all. Pass
TYPE:
|
max_distance
|
TYPE:
|
resolution
|
Grid spacing (m).
TYPE:
|
geodesic_density
|
Surface samples per m^2 for the geodesic table.
TYPE:
|
solid_voxel
|
If > 0 and the winding-number sign of
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/channels.py
Attributes¶
Methods:¶
exact_query
¶
exact_query(points: ndarray) -> ChannelQuery
Exact distance, witness and their derivatives.
The closest point of a triangle mesh slides with the query point only along the feature it lies
on: dW/dx is the tangent projector I - n n^T inside a face, t t^T on an edge (t its
direction) and zero at a vertex. Using the face projector everywhere overstates or misdirects the
witness motion near edges, which a Gauss-Newton step then follows in the wrong direction.
Source code in eden/extensions/retargeting/otretarget/channels.py
query
¶
query(points: ndarray) -> ChannelQuery
Source code in eden/extensions/retargeting/otretarget/channels.py
geodesic
¶
geodesic(w: ndarray, w_hat: ndarray, n_w: ndarray | None = None, n_hat: ndarray | None = None, hat: tuple[ndarray, ndarray] | None = None) -> tuple[ndarray, ndarray]
See :meth:Channel.geodesic; hat is :meth:SurfaceGeodesics.endpoint_weights at w_hat, if known.
Source code in eden/extensions/retargeting/otretarget/channels.py
SurfaceGeodesics
¶
All-pairs geodesic distances over a surface point cloud, interpolated to arbitrary surface points.
The cloud is connected into a graph by k-nearest-neighbour edges between samples whose normals agree (so a thin plate's two faces are not short-circuited through its thickness); components left disconnected — separate shells of one object — are bridged at their closest pair. Distances between samples are Dijkstra shortest paths.
For two arbitrary surface points the distance is interpolated continuously — the solver's
Gauss-Newton model must describe the cost it is accepted against, and a nearest-sample minimum
jumps whenever the nearest set changes. Each endpoint spreads over the samples within
support * spacing with compactly supported weights (1 - r / R)^2; the distance is the sample
table interpolated at both ends, sum_ab alpha_a(w) alpha_b(w_hat) G[a, b]; and, for endpoints a few
spacings apart, it blends by a smoothstep into the straight segment, which is what a geodesic reduces
to locally.
| PARAMETER | DESCRIPTION |
|---|---|
points
|
TYPE:
|
normals
|
TYPE:
|
spacing
|
The mean sample spacing (m).
TYPE:
|
k
|
Graph neighbours per sample.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/channels.py
Attributes¶
table
instance-attribute
¶
Methods:¶
from_mesh
classmethod
¶
from_mesh(mesh: Trimesh, density: float, seed: int = 0) -> SurfaceGeodesics
Sample mesh at density points per m^2 and build the geodesic table on the samples.
Source code in eden/extensions/retargeting/otretarget/channels.py
endpoint_weights
¶
endpoint_weights(x: ndarray, normal: ndarray | None = None, k: int = 16, support: float = 1.5) -> tuple[ndarray, ndarray]
Neighbour indices (M, k) and normalised weights (M, k) of the table at the surface points x.
This is the w_hat end of :meth:distance. Each row depends on its own point only, so a caller whose
targets stay fixed over several :meth:distance calls computes it once and passes it as hat.
Source code in eden/extensions/retargeting/otretarget/channels.py
distance
¶
distance(w: ndarray, w_hat: ndarray, n_w: ndarray | None = None, n_hat: ndarray | None = None, k: int = 16, support: float = 1.5, blend: tuple[float, float] = (2.0, 4.0), soften: float = 0.05, hat: tuple[ndarray, ndarray] | None = None) -> tuple[ndarray, ndarray]
Interpolated geodesic distance and its gradient in w (see the class docstring).
| PARAMETER | DESCRIPTION |
|---|---|
w
|
TYPE:
|
w_hat
|
TYPE:
|
n_w
|
TYPE:
|
n_hat
|
TYPE:
|
k
|
Neighbours examined per endpoint (must cover the support).
TYPE:
|
support
|
Weight support radius, in sample spacings.
TYPE:
|
soften
|
TYPE:
|
blend
|
Chord lengths (in spacings) over which the distance blends from the straight segment (below) to the graph distance (above). |
hat
|
:meth:
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/channels.py
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | |
Functions:¶
winding_sign_is_reliable
¶
Whether the generalised winding number of mesh gives the right inside/outside sign at its surface.
True when, with duplicate vertices merged, the surface has no boundary edge and a consistent orientation, and at
least 98% of surface samples read inside offset behind their face and outside offset in front of it. A
scan stored as loose triangles (every triangle with its own vertices, as the OMOMO objects are) is closed once
merged and passes; Trimesh.is_watertight on the unmerged mesh reads it as open. An open bin, or walls scanned
as zero-thickness sheets (no inside behind the face), fail.
Source code in eden/extensions/retargeting/otretarget/channels.py
watertight_solid
¶
A closed surface around the solid an open or fragmented scan stands for.
Space within voxel of the scan is a shell (a single-sheet wall gets that thickness); free space reachable
from outside the bounding box without crossing the shell is outside, so the cavity of an open bin stays free
space, while space the shell encloses (the inside of a closed box) is solid. The surface is the zero level of
distance - voxel over outside and shell space and -distance inside, extracted by marching cubes on a grid
of spacing voxel: closed, and voxel outside the scanned surface. The result is cached by mesh content.
Source code in eden/extensions/retargeting/otretarget/channels.py
Probe clouds: dense surface samples carried by the human, the robot links and the objects (Sec. III-B).
Every entity carries a probe cloud, sampled uniformly by area. Robot and object probes are rigid in their carrier's frame (a link, an object). Human probes ride a deforming mesh, so they are stored as barycentric coordinates on its triangles and re-posed every frame, each labelled with the body part (the heaviest skinning joint) of the triangle it lies on.
Classes¶
RigidProbes
dataclass
¶
Probes rigidly attached to carriers (robot links or objects).
| ATTRIBUTE | DESCRIPTION |
|---|---|
local |
TYPE:
|
normals |
TYPE:
|
carrier |
TYPE:
|
area |
TYPE:
|
HumanProbes
dataclass
¶
Probes on the human mesh, as barycentric coordinates on its triangles.
| ATTRIBUTE | DESCRIPTION |
|---|---|
corners |
TYPE:
|
bary |
TYPE:
|
part |
TYPE:
|
area |
TYPE:
|
Attributes¶
Methods:¶
positions
¶
Probe positions on a posed mesh: (V, 3) -> (N, 3) or (T, V, 3) -> (T, N, 3).
Source code in eden/extensions/retargeting/otretarget/probes.py
normals
¶
Unit outward normals of the probes' triangles on a posed (V, 3) mesh: (N, 3).
Source code in eden/extensions/retargeting/otretarget/probes.py
Functions:¶
resolve_density
¶
The density of the first pattern in densities that fully matches name.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
A link or body-part name.
TYPE:
|
densities
|
Ordered |
Source code in eden/extensions/retargeting/otretarget/probes.py
sample_surface
¶
sample_surface(mesh: Trimesh, density: float, min_points: int, seed: int = 0) -> tuple[ndarray, ndarray, ndarray, ndarray]
Area-uniform samples of a mesh surface at density points per m^2 (at least min_points).
| RETURNS | DESCRIPTION |
|---|---|
points
|
TYPE:
|
normals
|
TYPE:
|
faces
|
TYPE:
|
bary
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/probes.py
sample_rig_probes
¶
sample_rig_probes(kin: RigKinematics, densities: Mapping[str, float], min_points: int, exclude: list[str] | None = None, use_visual_mesh: bool = True, seed: int = 0) -> RigidProbes
Sample every rig link that has geometry, in its link frame.
| PARAMETER | DESCRIPTION |
|---|---|
kin
|
The rig.
TYPE:
|
densities
|
|
min_points
|
Floor on samples per link, so small links (finger phalanges) still carry probes.
TYPE:
|
exclude
|
Link-name regexes that carry no probes. |
use_visual_mesh
|
Sample the visual meshes (the paper's choice) rather than the collision geometry.
TYPE:
|
seed
|
Sampling seed.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/probes.py
sample_object_probes
¶
sample_object_probes(meshes: list[Trimesh], density: float, min_points: int, seed: int = 0) -> RigidProbes
Sample each object mesh in its own frame; the carrier index is the object's position in meshes.
Source code in eden/extensions/retargeting/otretarget/probes.py
sample_human_probes
¶
sample_human_probes(human: HumanSurfaceMotion, densities: Mapping[str, float], min_points: int, seed: int = 0) -> HumanProbes
Sample the human rest mesh part by part, each part at the density its joint name resolves to.
A triangle belongs to the part of the joint with the largest summed skinning weight over its three vertices.
| PARAMETER | DESCRIPTION |
|---|---|
human
|
The motion (its rest mesh is sampled).
TYPE:
|
densities
|
|
min_points
|
Floor on samples per part.
TYPE:
|
seed
|
Sampling seed.
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/probes.py
Entropic optimal transport between surface point clouds (OTRetarget Sec. III-B, Eq. 3-4).
A demonstration's interaction targets live on the human (or demonstrated-object) surface, the residuals on the robot (or substitute-object) surface. The correspondence between the two is the argmax of an entropically regularised transport plan between the two clouds, each centred and scaled to unit root-mean-square radius so a size mismatch does not decide the matching. Unlike a nearest-neighbour assignment, the marginal constraints force every source sample to receive mass, so limb extremities (fingertips, heels) are not left unmatched.
The paper's cost is the squared distance between the normalised clouds. With outward normals given, the
cost also carries normal_weight * |n_i - n_p|^2: a robot phalanx is not the human one's scaled copy (a
flatter Wuji phalanx against a round human one), and position alone matches about a quarter of a robot
finger's probes to the opposite face of the human finger (pad to nail), whose demonstrated distances then
pull that face of the robot finger away from a grasped object. A weight of 0.5 (squared unit-normal
differences lie in [0, 4], normalised squared distances are ~1) matches 96% of the probes to a like-facing
source at unchanged coverage.
Functions:¶
normalize_cloud
¶
Centre a point cloud on its centroid and scale it to unit root-mean-square radius.
| PARAMETER | DESCRIPTION |
|---|---|
points
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
|
Source code in eden/extensions/retargeting/otretarget/transport.py
sinkhorn
¶
sinkhorn(cost: ndarray, a: ndarray, b: ndarray, epsilon: float, max_iters: int = 2000, tol: float = 1e-09, device: str | device = 'cpu') -> ndarray
Solve min_P <P, C> + eps * sum P (log P - 1) over couplings with marginals a, b.
Log-domain Sinkhorn (Cuturi 2013), stable for small epsilon relative to the cost scale.
| PARAMETER | DESCRIPTION |
|---|---|
cost
|
TYPE:
|
a
|
TYPE:
|
b
|
TYPE:
|
epsilon
|
Entropic regularisation
TYPE:
|
max_iters
|
Iteration budget.
TYPE:
|
tol
|
Stop once the L1 violation of the source marginal falls below this.
TYPE:
|
device
|
Where the iterations run. The caller names it (the retargeter passes its env's device) rather than this
function picking any available GPU, so a
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
|
Source code in eden/extensions/retargeting/otretarget/transport.py
transport_correspondence
¶
transport_correspondence(source: ndarray, target: ndarray, epsilon: float = 0.1, source_normals: ndarray | None = None, target_normals: ndarray | None = None, normal_weight: float = 0.0, source_weights: ndarray | None = None, target_weights: ndarray | None = None, device: str | device = 'cpu') -> ndarray
For each target point, the source point it receives the most mass from (src(p), Eq. 4).
Both clouds are normalised (:func:normalize_cloud) before the squared-Euclidean cost is built.
The marginals are uniform over each cloud's points, or proportional to *_weights (the surface area
a sample stands for) when a cloud is sampled at several densities: uniform marginals would hand the
densely sampled part a larger share of the other surface.
| PARAMETER | DESCRIPTION |
|---|---|
source
|
TYPE:
|
target
|
TYPE:
|
epsilon
|
Entropic regularisation
TYPE:
|
source_normals
|
TYPE:
|
target_normals
|
TYPE:
|
normal_weight
|
Weight of the normal-agreement cost
TYPE:
|
source_weights
|
TYPE:
|
target_weights
|
TYPE:
|
device
|
Where the Sinkhorn iterations run (see :func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
|
Source code in eden/extensions/retargeting/otretarget/transport.py
group_correspondences
¶
group_correspondences(source_points: ndarray, source_labels: list[str], target_points: ndarray, target_labels: list[str], groups: list[tuple[tuple[str, ...], tuple[str, ...]]], epsilon: float = 0.1, source_normals: ndarray | None = None, target_normals: ndarray | None = None, normal_weight: float = 0.0, source_weights: ndarray | None = None, target_weights: ndarray | None = None, device: str | device = 'cpu') -> tuple[ndarray, ndarray]
Solve one transport plan per pre-assigned (source parts, target parts) group.
| PARAMETER | DESCRIPTION |
|---|---|
source_points
|
TYPE:
|
source_labels
|
|
target_points
|
TYPE:
|
target_labels
|
|
groups
|
|
epsilon
|
Entropic regularisation.
TYPE:
|
source_normals
|
Unit outward normals of the samples (see :func:
TYPE:
|
target_normals
|
Unit outward normals of the samples (see :func:
TYPE:
|
normal_weight
|
Weight of the normal-agreement cost.
TYPE:
|
source_weights
|
Sample weights (the area each sample stands for, see :func:
TYPE:
|
target_weights
|
Sample weights (the area each sample stands for, see :func:
TYPE:
|
device
|
Where the Sinkhorn iterations run (see :func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
src
|
TYPE:
|
group
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/transport.py
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | |
Capsule approximations of robot links, for the self-collision constraint (Sec. III-D).
Each link's surface is approximated by one capsule along its principal axis. A pair of links
contributes a non-penetration row phi + n^T (J_a - J_b) dv >= -eps once their capsules come within
an activation distance. Pairs that touch in the reference poses (adjacent links, a hand's palm and
its finger roots) are excluded, as is usual for self-collision filtering.
Classes¶
LinkCapsules
dataclass
¶
One capsule per link, in link frames.
| ATTRIBUTE | DESCRIPTION |
|---|---|
link |
TYPE:
|
a, b |
TYPE:
|
radius |
TYPE:
|
pairs |
TYPE:
|
Functions:¶
fit_capsule
¶
Fit a capsule to surface points: principal axis, radius at a quantile of the distances to it.
| PARAMETER | DESCRIPTION |
|---|---|
points
|
TYPE:
|
radius_quantile
|
Quantile of the points' distance to the axis taken as the radius; below 1 the capsule sits inside protruding features rather than inflating around them.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
a, b : np.ndarray
|
Segment endpoints. |
radius
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/capsules.py
build_link_capsules
¶
build_link_capsules(link_points: dict[int, ndarray], link_parent: ndarray, reference_poses: list[tuple[ndarray, ndarray]], radius_quantile: float = 0.8, exclusion_margin: float = 0.005, link_names: list[str] | None = None, exclude: list[tuple[str, str]] | None = None) -> LinkCapsules
Fit capsules and choose the link pairs to check.
| PARAMETER | DESCRIPTION |
|---|---|
link_points
|
|
link_parent
|
Rig link parent indices.
TYPE:
|
reference_poses
|
Link poses (positions, rotations) at reference configurations; a pair closer than
|
radius_quantile
|
See :func:
TYPE:
|
exclusion_margin
|
Clearance below which a pair counts as touching in a reference pose.
TYPE:
|
link_names
|
Rig link names (indexed like |
exclude
|
|
Source code in eden/extensions/retargeting/otretarget/capsules.py
The numerical core of OTRetarget's trust-region SQP: Gauss-Newton accumulation and the dense QP (ProxQP).
Nothing here knows about probes, channels or robots: residual rows arrive in factored form (:class:Rows) and leave as
the Hessian, gradient and constraint matrices of one QP.
Classes¶
Rows
dataclass
¶
Local
dataclass
¶
Local(H: ndarray, g: ndarray, C: ndarray, l_in: ndarray, hard_lo: ndarray, hard_hi: ndarray, trust: ndarray, terms: dict[str, float], n_active: int, penetration: float, frozen: list, term_grads: dict[str, ndarray], contacts: list = list())
GaussNewton
¶
Accumulates H = sum w J^T J and g = sum w J^T r for the QP, robot rows link by link.
terms names the cost terms (each reported with its value and gradient); add to another name is an error.
Source code in eden/extensions/retargeting/otretarget/solver.py
Attributes¶
Methods:¶
dense
¶
dense(rows: Rows) -> ndarray
The rows as a dense (K, n_x) matrix (for constraints).
Source code in eden/extensions/retargeting/otretarget/solver.py
add
¶
Source code in eden/extensions/retargeting/otretarget/solver.py
add_dense
¶
Source code in eden/extensions/retargeting/otretarget/solver.py
Functions:¶
single_threaded_blas
¶
Context limiting the BLAS pools to one thread: faster for the solve's small products, and reproducible.
Source code in eden/extensions/retargeting/otretarget/solver.py
elastic_shift
¶
Smallest per-row relaxation t >= 0 (in the l1 sense) making C x >= l_in - t feasible in the box.
One LP: min sum t s.t. C x + t >= l_in, lo <= x <= hi, t >= 0. The l1 objective relaxes only
the rows that actually conflict. Returns None if the LP solver fails.
Source code in eden/extensions/retargeting/otretarget/solver.py
solve_qp
¶
min 1/2 x^T H x + g^T x s.t. C x >= l_in, lo <= x <= hi with ProxQP (dense).
Linearised non-penetration rows can contradict each other (probes on both sides of a feature
thinner than the distance grid), making the QP infeasible. When the plain solve does not converge,
the SQP elastic relaxation is applied: :func:elastic_shift finds the smallest (l1) shift of the
conflicting rows that restores feasibility, and the shifted QP is solved instead. If neither solve
yields a finite step, the iterate does not move.
| RETURNS | DESCRIPTION |
|---|---|
x
|
The step, clipped to the box (zero when no solve succeeded).
TYPE:
|
status
|
TYPE:
|
Source code in eden/extensions/retargeting/otretarget/solver.py
Interaction-fidelity metrics of a retargeted motion (OTRetarget Sec. IV-A).
Independently of the solver's probes and grids: every body unit (one correspondence group — a set of
human parts and the robot links matched to them) is measured against every channel (the ground, each
object) at every frame with exact signed distances from the posed human mesh vertices and the robot's
visual-mesh vertices, each unit's distance being that of its closest vertex. Distances are to the channel's
surface, MeshChannel.mesh: for a scan whose winding sign is unreliable that is its watertight solid, one
object_solid_voxel outside the scan, for the demonstration and the robot alike.
With eps_eval = 20 mm, the demonstrated and retargeted interaction sets are
H = {(t, u, c) : (d_hat)+ < eps} and R = {(t, u, c) : (d)+ < eps}; their agreement is reported as
precision |H n R| / |R|, recall |H n R| / |H| and Jaccard |H n R| / |H u R|, and the geometric
accuracy over H as the depth error mean |d - (d_hat)+| and the placement error mean |w - w_hat|.
Ground and object interactions are reported separately, and the object interactions of the units on the
welded hand entities (palm and phalanges: groups whose links all belong to a hand entity) once more on their own
(hand/*), since a whole-body score hides a grasp that misses. A demonstrated witness on a substituted object
(demo_mesh) is carried onto the scene mesh as the retargeter carries it before it is compared. Also reported:
stance clearance and foot skate (the median over stance steps of the mean horizontal speed of the foot vertices
within stance_height of the floor), the 95th-percentile scene penetration (and that of the hand units alone),
the style orientation error, the object drift, and the smoothness of the motion as mean absolute second differences
per frame of the joints, the root position and the human pelvis.
Classes¶
Functions:¶
evaluate_retarget
¶
evaluate_retarget(retargeter: OTRetargeter, human: HumanSurfaceMotion, objects: list[InteractionObject], result: RetargetResult, eps_eval: float = 0.02, stance_height: float = 0.02, max_vertices_per_link: int = 1500) -> dict[str, float]
Score a retarget against its demonstration.
| PARAMETER | DESCRIPTION |
|---|---|
retargeter
|
The retargeter that produced
TYPE:
|
human
|
The demonstration.
TYPE:
|
objects
|
Its objects (demonstrated poses).
TYPE:
|
result
|
The retargeted motion.
TYPE:
|
eps_eval
|
Interaction threshold (20 mm).
TYPE:
|
stance_height
|
A foot is in stance when its lowest point is below this (m).
TYPE:
|
max_vertices_per_link
|
Robot visual-mesh vertices kept per link (evenly subsampled) to bound the cost.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
|
Source code in eden/extensions/retargeting/otretarget/metrics.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
SomaRetargeter¶
SomaRetargeter runs the eden-soma-retargeter library in a worker process. That extra pins a trimesh that only
a checkout's uv override reconciles with Genesis, so install it with uv sync --inexact --extra soma-retargeter
(it cannot be pip-installed).
Eden RetargetingBase wrapper around the eden-soma-retargeter library.
Retargets human motion — SMPL / SMPL-H / SMPL-X (fitted via py-soma-x) or
native SOMA (arrays / save_soma_npz files / SOMA-skeleton BVH) — onto a
floating-base robot (Unitree G1 29-DOF, LimX Oli 31-DOF), returning
Genesis-compatible qpos.
Usage mirrors DexRetargeter / OmniRetargeter:
.. code-block:: python
retargeter = SomaRetargeter(
env=env,
options=SomaRetargeter.configure(
entity_name="robot",
body_model="smplx",
body_model_path="/path/to/SMPLX_NEUTRAL.npz",
target_fps=30.0,
),
)
qpos = retargeter.retarget_motion(poses=..., trans=..., betas=..., source_fps=120.0)
qpos_batch = retargeter.retarget_motions([clip0, clip1, ...])
Why a worker subprocess. Retargeting runs in a persistent Genesis-free worker
process; this class streams clips to it and permutes results into
entity.dofs_name order. The isolation is precautionary — it keeps the Warp
fit's CUDA context and its several GB off the ones Genesis holds — and is an
internal detail: the public API is the same in-process loop as the other
retargeters.
Classes¶
SomaRetargeter
¶
SomaRetargeter(env: 'EnvBase', options: RetargeterOptions)
Bases: RetargetingBase
SMPL/SMPL-H/SMPL-X/SOMA -> robot retargeter (library-backed).
| PARAMETER | DESCRIPTION |
|---|---|
body_model
|
Source motion representation. The smpl family is fitted to the SOMA rig
via py-soma-x;
TYPE:
|
body_model_path
|
Path to the body-model file (
TYPE:
|
gender
|
Default gender; a per-call
TYPE:
|
target_fps
|
FPS every clip is resampled to before retargeting.
TYPE:
|
snap_to_ground
|
Post-process each clip with one constant vertical offset so the lowest point of the robot's collision geometry over the whole motion touches the ground plane (z = 0) — lifts clips whose feet sink below the floor, lowers floating ones. Sweeps the clip through the entity's forward kinematics; the entity's qpos is restored afterwards (velocities zeroed).
TYPE:
|
device
|
Torch/warp device for the worker ("cuda", "cuda:1", "cpu").
TYPE:
|
enable_procedural_transforms
|
Fit through py-soma-x's expanded twist-joint rig instead of the public
78-joint SOMA rig. Off by default (the library defaults it on) because
it requires
TYPE:
|
robot
|
Library identifier of the target robot ("unitree_g1", "limx_oli", or any
robot the library ships a
TYPE:
|
retargeter_kwargs
|
Extra keyword arguments forwarded verbatim to the library
TYPE:
|
Source code in eden/extensions/retargeting/soma_retargeter/retargeter.py
Attributes¶
body_model
class-attribute
instance-attribute
¶
body_model: Literal['smpl', 'smplh', 'smplx', 'soma'] = 'smplx'
gender
class-attribute
instance-attribute
¶
gender: Literal['neutral', 'male', 'female'] = 'neutral'
enable_procedural_transforms
class-attribute
instance-attribute
¶
enable_procedural_transforms: bool = False
joint_names
property
¶
Full DOF name list of the underlying entity (dofs_name order).
Methods:¶
close
¶
Terminate the worker subprocess (idempotent).
Source code in eden/extensions/retargeting/soma_retargeter/retargeter.py
retarget_motion
¶
retarget_motion(poses: ndarray | None = None, trans: ndarray | None = None, transl: ndarray | None = None, betas: ndarray | None = None, gender: str | None = None, source_fps: float | None = None, **extra) -> ndarray
Retarget one clip to Genesis qpos (T, 7 + N) in entity.dofs_name order.
Field names follow SOMA-X conventions. For the smpl family pass
poses / trans / betas / source_fps (+ optional
gender); for native SOMA arrays pass poses / transl /
source_fps. Returned qpos is [x, y, z, qw, qx, qy, qz, joints...],
Z-up, wxyz quaternion, radians.
Source code in eden/extensions/retargeting/soma_retargeter/retargeter.py
retarget_bvh
¶
Retarget a SOMA-skeleton BVH file (e.g. BONES-SEED) to qpos.
retarget_motions
¶
Retarget many clips in one batched IK solve (one env per clip).
Each clip is the keyword dict of a single-clip call
({"poses", "trans", "source_fps", ...} / {"poses", "transl", ...}
/ {"bvh_path": ...}).
Source code in eden/extensions/retargeting/soma_retargeter/retargeter.py
Functions:¶
build_dof_permutation
¶
build_dof_permutation(source_joint_names: Sequence[str], entity_dofs_name: Sequence[str]) -> ndarray
Permutation perm such that out[:, perm] = src maps each source DOF to its entity slot.
Resolves purely by name (independent of Genesis's internal link/DOF order,
which changed BFS->DFS in genesis 1.2.0). A trailing _dof suffix on
source names is tolerated. Raises ValueError on a length mismatch or a
missing joint, listing both name sets.
Source code in eden/extensions/retargeting/soma_retargeter/retargeter.py
FlashDexRetarget¶
The kinematic half of FlashDexRetarget: import a released hand-object dataset, preprocess and filter its clips,
retarget each with physics IK in MuJoCo, and pack the kept clips into motion.pt.
Options for the FlashDexRetarget kinematic-retargeting pipeline (human demos -> motion.pt).
Two stages, each driven by one options object:
- :class:
FDRImportOptions— a released dataset (TACO, OakInk2, HOT3D, DexYCB, each read by its :mod:eden.datasetsloader) -><dataset>/human_demo/<clip>.npzand<dataset>/objects/<id>/visual.obj. - :class:
FDRKinematicRetargetingOptions— those clips -> support disks and reject rules (report.csv), convex object parts, MuJoCo physics IK onto the robot hand, and<dataset>/<robot>/motion.pt.
Defaults are FlashDexRetarget's (Holiday-Robot/FlashDexRetarget config/retarget/*.yaml); the Isaac-only usd
step is gone. eden retarget flashdex builds these from --config / --override the way eden train does.
Attributes¶
FDRSourceOptions
module-attribute
¶
FDRSourceOptions = Annotated[Annotated[FDRTacoSourceOptions, Tag('taco')] | Annotated[FDROakInk2SourceOptions, Tag('oakink2')] | Annotated[FDRHot3dSourceOptions, Tag('hot3d')] | Annotated[FDRDexYCBSourceOptions, Tag('dexycb')], _by_name('source', ('taco', 'oakink2', 'hot3d', 'dexycb'), None)]
FDRConvexOptions
module-attribute
¶
FDRConvexOptions = Annotated[Annotated[FDRCoacdConvexOptions, Tag('coacd')] | Annotated[FDRCuacdConvexOptions, Tag('cuacd')], _by_name('convex', ('coacd', 'cuacd'), 'coacd')]
Classes¶
FDRTacoSourceOptions
¶
Bases: ConfigurableOptions
TACO, read by :class:~eden.datasets.TacoDataset (30 Hz, one clip per recording).
| PARAMETER | DESCRIPTION |
|---|---|
table_z
|
Height to put the surface the objects rest on at;
TYPE:
|
dataset
|
Options of :class: |
Source code in eden/options/options.py
FDROakInk2SourceOptions
¶
Bases: ConfigurableOptions
OakInk2, read by :class:~eden.datasets.OakInk2Dataset (120 Hz, one clip per program stage).
| PARAMETER | DESCRIPTION |
|---|---|
table_z
|
Height to put the surface the objects rest on at;
TYPE:
|
desk_over_recording
|
Fit the support disks on every object of the whole recording (CHORD), not only the clip's own.
TYPE:
|
scales
|
Mesh scale per object id (1.0 when absent): OakInk2's scans of these are off in size. |
dataset
|
Options of :class: |
Source code in eden/options/options.py
Attributes¶
scales
class-attribute
instance-attribute
¶
scales: dict[str, float] = Field(default_factory=lambda: {'O02@0015@00001': 1.1, 'O02@0015@00004': 1.08, 'O02@0015@00007': 1.2, 'O02@0015@00010': 1.2, 'O02@0015@00013': 1.2, 'O02@0015@00019': 1.02, 'O02@0015@00020': 1.05, 'O02@0015@00022': 1.2, 'O02@0015@00025': 1.2, 'O02@0018@00001': 1.05, 'O02@0029@00002': 1.3, 'O02@0029@00009': 1.3, 'O02@0029@00011': 0.9, 'O02@0029@00012': 1.3, 'O02@0206@00001': 1.15, 'O02@0206@00002': 0.95})
FDRHot3dSourceOptions
¶
Bases: ConfigurableOptions
HOT3D, read by :class:~eden.datasets.Hot3dDataset (30 Hz, cut into hand-object segments).
| PARAMETER | DESCRIPTION |
|---|---|
table_z
|
Height to put the surface the objects rest on at;
TYPE:
|
desk_over_recording
|
Fit the support disks on every object of the whole recording, not only the segment's own.
TYPE:
|
dataset
|
Options of :class: |
Source code in eden/options/options.py
Attributes¶
FDRDexYCBSourceOptions
¶
Bases: ConfigurableOptions
DexYCB, read by :class:~eden.datasets.DexYCBDataset (30 Hz, one hand per clip).
Not one of FlashDexRetarget's releases: a single-hand grasp-and-lift source, so import it with sides set to
the hand the subject used (every subject's mano_sides is right in the public release). The release's
root holds <subject>/<sequence>/, calibration/ and models/; poses stay in the AprilTag frame, on the
release's meshes.
| PARAMETER | DESCRIPTION |
|---|---|
table_z
|
Height to put the surface the objects rest on at;
TYPE:
|
dataset
|
Options of :class: |
Source code in eden/options/options.py
FDRImportOptions
¶
Bases: ConfigurableOptions
A released dataset -> <dataset>/human_demo/<clip>.npz + <dataset>/objects/<id>/visual.obj.
| PARAMETER | DESCRIPTION |
|---|---|
source
|
The release and its loader settings, picked by
TYPE:
|
raw
|
The downloaded release's root directory.
TYPE:
|
dataset
|
The dataset directory to write.
TYPE:
|
mano_dir
|
Directory holding
TYPE:
|
sides
|
Hands to import; a clip without an object in each of them is skipped. DexYCB has one hand per clip, so it
needs
TYPE:
|
fps
|
Rate every clip is resampled to.
TYPE:
|
max_obj_rot_step_deg
|
A clip whose object turns more than this in one source frame is skipped (a pose flip).
TYPE:
|
textures
|
Export each object with the release's materials and textures, for rendering
TYPE:
|
Source code in eden/options/options.py
FDRStepsOptions
¶
Bases: ConfigurableOptions
Which steps of the kinematic pipeline run (preprocess always does, when the dataset has clips).
| PARAMETER | DESCRIPTION |
|---|---|
convex
|
Convex decomposition of every object (
TYPE:
|
retarget
|
Physics IK of every kept clip (
TYPE:
|
pack
|
Kept clips ->
TYPE:
|
urdf
|
Object URDFs for simulation (
TYPE:
|
sdf
|
Object SDF grids (
TYPE:
|
Source code in eden/options/options.py
Attributes¶
FDRDeskOptions
¶
Bases: ConfigurableOptions
Support disks (tables, shelves) fitted where the objects rest still; ported from CHORD.
| PARAMETER | DESCRIPTION |
|---|---|
mode
|
TYPE:
|
still_speed
|
Linear speed (m/s) under which an object rests.
TYPE:
|
still_ang_speed
|
Angular speed (rad/s) under which an object rests.
TYPE:
|
min_still_sec
|
Shortest rest that fits a disk.
TYPE:
|
disk_height
|
Height of a fitted disk.
TYPE:
|
phantom_in_disk_frac
|
A disk that another simulated object occupies this fraction of the time is that object, dropped.
TYPE:
|
phantom_z
|
Vertical band (m) of that occupancy test.
TYPE:
|
consolidate_z
|
Overlapping disks within this height difference merge.
TYPE:
|
rest_band
|
An object passes over a disk within |
contact_z
|
With the recording's context: an object stands on a disk within this distance of its top.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
FDROffDiskUntouchedOptions
¶
Bases: ConfigurableOptions
Reject: an untouched object floats where nothing supports it for frames frames below max_height.
Source code in eden/options/options.py
FDRWristAccSpikeOptions
¶
Bases: ConfigurableOptions
Reject: the smooth-frame averaged MANO wrist accelerates faster than max_acc (m/s^2).
Source code in eden/options/options.py
FDRObjBelowDeskOptions
¶
Bases: ConfigurableOptions
Reject: an untouched object starts or ends more than -min_z below the desk.
Source code in eden/options/options.py
FDRTooShortOptions
¶
Bases: ConfigurableOptions
Reject: the clip is shorter than min_sec seconds.
Source code in eden/options/options.py
FDRFirstUnsupportedOptions
¶
Bases: ConfigurableOptions
Reject: an object is not over its own base (base_band of its lowest point, + slack) at the start.
Source code in eden/options/options.py
FDRFilterOptions
¶
Bases: ConfigurableOptions
Reject rules over the imported clips (report.csv).
| PARAMETER | DESCRIPTION |
|---|---|
enable
|
TYPE:
|
contact
|
Distance (m) at which a fingertip or another object touches an object.
TYPE:
|
edge_frames
|
Frames at either end the start/end rules look at.
TYPE:
|
obj_offdisk_untouched
|
An untouched object floats where nothing supports it. |
wrist_acc_spike
|
The MANO wrist accelerates too fast.
TYPE:
|
obj_below_desk
|
An untouched object starts or ends below the desk.
TYPE:
|
too_short
|
The clip is too short.
TYPE:
|
first_unsupported
|
An object topples in the first frames. |
Source code in eden/options/options.py
Attributes¶
obj_offdisk_untouched
class-attribute
instance-attribute
¶
obj_offdisk_untouched: FDROffDiskUntouchedOptions = Field(default_factory=FDROffDiskUntouchedOptions)
wrist_acc_spike
class-attribute
instance-attribute
¶
wrist_acc_spike: FDRWristAccSpikeOptions = Field(default_factory=FDRWristAccSpikeOptions)
obj_below_desk
class-attribute
instance-attribute
¶
obj_below_desk: FDRObjBelowDeskOptions = Field(default_factory=FDRObjBelowDeskOptions)
too_short
class-attribute
instance-attribute
¶
too_short: FDRTooShortOptions = Field(default_factory=FDRTooShortOptions)
first_unsupported
class-attribute
instance-attribute
¶
first_unsupported: FDRFirstUnsupportedOptions = Field(default_factory=FDRFirstUnsupportedOptions)
FDRCoacdParams
¶
Bases: ConfigurableOptions
Keyword arguments of coacd.run_coacd (see CoACD's documentation).
Source code in eden/options/options.py
FDRCoacdConvexOptions
¶
Bases: ConfigurableOptions
CoACD convex decomposition on CPU workers.
| PARAMETER | DESCRIPTION |
|---|---|
force
|
Redo objects whose convex parts were made from their current mesh and these settings (parts made from any other are redone anyway).
TYPE:
|
decimate_faces
|
Decimate a mesh with more faces first (dense scans make CoACD very slow); 0 never.
TYPE:
|
seed
|
CoACD's random seed.
TYPE:
|
coacd
|
TYPE:
|
Source code in eden/options/options.py
Attributes¶
coacd
class-attribute
instance-attribute
¶
coacd: FDRCoacdParams = Field(default_factory=FDRCoacdParams)
FDRCuacdConvexOptions
¶
Bases: ConfigurableOptions
CuACD convex decomposition on GPUs (one process per GPU, about 20 GB each), then CoACD's merge.
| PARAMETER | DESCRIPTION |
|---|---|
force
|
Redo objects whose convex parts were made from their current mesh and these settings (parts made from any other are redone anyway).
TYPE:
|
decimate_faces
|
Decimate a mesh with more faces first; 0 never.
TYPE:
|
gpus
|
Indices into the visible GPUs; |
threshold
|
Concavity threshold.
TYPE:
|
depth
|
Lookahead depth.
TYPE:
|
preprocess_resolution
|
Remeshing resolution for a mesh CuACD cannot take as is.
TYPE:
|
max_convex_hull
|
Parts kept after the merge.
TYPE:
|
Source code in eden/options/options.py
FDRApproachOptions
¶
Bases: ConfigurableOptions
The first IK attempt starts from outside the object instead of from random restarts.
| PARAMETER | DESCRIPTION |
|---|---|
enable
|
Use the approach for attempt 0.
TYPE:
|
backoff
|
Distance (m) behind the wrist target (the back of the hand) the hand starts at.
TYPE:
|
slide_frames
|
Frames over which the hand slides onto the wrist targets.
TYPE:
|
close_frames
|
Frames over which the fingertip targets move onto frame 0's.
TYPE:
|
preshape
|
Fraction of the contact-free start search's finger shape to begin with; 0 opens the hand.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
FDREqualityOptions
¶
Bases: ConfigurableOptions
A MuJoCo equality constraint pulling a robot site onto its mocap target.
Source code in eden/options/options.py
FDRConstraintsOptions
¶
Bases: ConfigurableOptions
The IK's equality constraints: palm weld, fingertip connects and object weld.
| PARAMETER | DESCRIPTION |
|---|---|
palm
|
Weld of the palm site onto the MANO wrist.
TYPE:
|
tip
|
Connect of each fingertip site onto its MANO fingertip.
TYPE:
|
tip_width_ring_pinky
|
Factor on the tip
TYPE:
|
object
|
Stiff weld of each object onto its reference pose.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
palm
class-attribute
instance-attribute
¶
palm: FDREqualityOptions = Field(default_factory=lambda: FDREqualityOptions(torque=10.0, solref=(0.02, 1.0), solimp=(0.0, 0.95, 10.0, 0.5, 2.0)))
tip
class-attribute
instance-attribute
¶
tip: FDREqualityOptions = Field(default_factory=lambda: FDREqualityOptions(torque=1.0, solref=(0.01, 1.0), solimp=(0.0, 0.95, 0.01, 0.5, 2.0)))
object
class-attribute
instance-attribute
¶
object: FDREqualityOptions = Field(default_factory=lambda: FDREqualityOptions(torque=10.0, solref=(0.002, 1.0), solimp=(0.9, 0.95, 0.001, 0.5, 2.0)))
FDRContactOptions
¶
Bases: ConfigurableOptions
Contact settings of the IK model. mjENBL_OVERRIDE is on (as in FlashDexRetarget), so every contact, the
explicit hand/object/support pairs included, takes o_solref, o_solimp and o_friction.
| PARAMETER | DESCRIPTION |
|---|---|
impratio
|
Ratio of frictional to normal constraint impedance.
TYPE:
|
o_solref
|
|
o_solimp
|
|
o_friction
|
Friction of every contact (sliding, sliding, torsional, rolling, rolling); MuJoCo's default. |
Source code in eden/options/options.py
FDRIKSceneOptions
¶
Bases: ConfigurableOptions
The IK model built around the robot MJCF.
| PARAMETER | DESCRIPTION |
|---|---|
armature
|
Armature of every robot joint (heavy joints keep the IK stable).
TYPE:
|
kp_wrist
|
Position gain of the forearm actuators (critically damped at
TYPE:
|
kp_finger
|
Position gain of the finger actuators (critically damped at
TYPE:
|
desk_depth
|
Minimum thickness of a support-disk cylinder.
TYPE:
|
object_density
|
Density of the object bodies.
TYPE:
|
object_armature
|
Free-joint armature of the objects.
TYPE:
|
object_frictionloss
|
Free-joint friction loss of the objects.
TYPE:
|
The
|
|
Source code in eden/options/options.py
Attributes¶
FDRMaxAccOptions
¶
Bases: ConfigurableOptions
Flag: the palm accelerates faster than max_acc (m/s^2).
Source code in eden/options/options.py
FDRMaxDepthOptions
¶
Bases: ConfigurableOptions
Flag: a depth beyond max_depth (m).
Source code in eden/options/options.py
FDRTipTrackingOptions
¶
Bases: ConfigurableOptions
Flag: more than max_frac of the fingertip samples are max_dist (m) from MANO.
Source code in eden/options/options.py
FDRHandDeskPenetrationOptions
¶
Bases: ConfigurableOptions
Flag: the hand is max_depth (m) inside a disk for frames frames after frame after.
Source code in eden/options/options.py
FDRQualityOptions
¶
Bases: ConfigurableOptions
Flags (report.csv) on a retargeted clip; a flagged clip is still packed.
Source code in eden/options/options.py
Attributes¶
palm_acc_spike
class-attribute
instance-attribute
¶
palm_acc_spike: FDRMaxAccOptions = Field(default_factory=FDRMaxAccOptions)
hand_far_below_desk
class-attribute
instance-attribute
¶
hand_far_below_desk: FDRMaxDepthOptions = Field(default_factory=lambda: FDRMaxDepthOptions(max_depth=0.08))
tip_tracking
class-attribute
instance-attribute
¶
tip_tracking: FDRTipTrackingOptions = Field(default_factory=FDRTipTrackingOptions)
hand_obj_penetration
class-attribute
instance-attribute
¶
hand_obj_penetration: FDRMaxDepthOptions = Field(default_factory=lambda: FDRMaxDepthOptions(max_depth=0.02))
hand_desk_penetration
class-attribute
instance-attribute
¶
hand_desk_penetration: FDRHandDeskPenetrationOptions = Field(default_factory=FDRHandDeskPenetrationOptions)
FDRRetargetOptions
¶
Bases: ConfigurableOptions
MuJoCo physics IK: the robot's palm and fingertip sites follow the MANO wrist and fingertips while the hands collide with the objects and support disks.
| PARAMETER | DESCRIPTION |
|---|---|
force
|
Redo clips whose
TYPE:
|
sim_dt
|
MuJoCo timestep.
TYPE:
|
solver_iterations
|
MuJoCo solver iterations.
TYPE:
|
solver_ls_iterations
|
MuJoCo line-search iterations.
TYPE:
|
n_guess
|
Random restarts of a start search.
TYPE:
|
guess_steps
|
Steps each restart runs.
TYPE:
|
guess_jitter
|
Noise (m) on the fingertip targets of a restart.
TYPE:
|
start_settle
|
Frame-0 steps before the clip runs.
TYPE:
|
approach
|
Attempt 0's start from outside the object.
TYPE:
|
settle_steps
|
Steps per frame with the fingertip constraints off and the joints PD-held (contacts push out).
TYPE:
|
recover_tip_err
|
A restart is searched when the recent mean fingertip error exceeds this (m).
TYPE:
|
recover_window
|
Frames that error averages over.
TYPE:
|
recover_cooldown
|
Frames between restarts.
TYPE:
|
attempts
|
IK runs per clip; the best is kept.
TYPE:
|
pen_weight
|
Weight of a run's max hand-object penetration against its mean fingertip error.
TYPE:
|
smooth
|
Moving-average window, centred on each frame, over the kept run (the first
TYPE:
|
constraints
|
Palm, fingertip and object equality constraints.
TYPE:
|
contact
|
Global contact settings.
TYPE:
|
scene
|
The IK model around the robot MJCF.
TYPE:
|
quality
|
Quality flags of the kept run.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
solver_ls_iterations
class-attribute
instance-attribute
¶
solver_ls_iterations: int = Field(50, ge=1)
approach
class-attribute
instance-attribute
¶
approach: FDRApproachOptions = Field(default_factory=FDRApproachOptions)
constraints
class-attribute
instance-attribute
¶
constraints: FDRConstraintsOptions = Field(default_factory=FDRConstraintsOptions)
contact
class-attribute
instance-attribute
¶
contact: FDRContactOptions = Field(default_factory=FDRContactOptions)
scene
class-attribute
instance-attribute
¶
scene: FDRIKSceneOptions = Field(default_factory=FDRIKSceneOptions)
quality
class-attribute
instance-attribute
¶
quality: FDRQualityOptions = Field(default_factory=FDRQualityOptions)
FDRPackOptions
¶
Bases: ConfigurableOptions
motion.pt packing.
| PARAMETER | DESCRIPTION |
|---|---|
contact_threshold
|
A fingertip within this distance (m) of the object mesh is in contact (dilated by one frame).
TYPE:
|
vel_sigma
|
Gaussian smoothing (frames) of the finite-difference velocities.
TYPE:
|
Source code in eden/options/options.py
FDRSdfOptions
¶
Bases: ConfigurableOptions
Object SDF grids over [-extent, extent]^3 in the object frame (signed distance + gradient).
| PARAMETER | DESCRIPTION |
|---|---|
grid_n
|
Grid points per axis; must match the training task's SDF settings.
TYPE:
|
extent
|
Half-size (m) of the grid; must match the training task's SDF settings.
TYPE:
|
device
|
Where warp bakes.
TYPE:
|
gpus
|
Indices into the visible GPUs; |
workers_per_gpu
|
Processes per GPU.
TYPE:
|
Source code in eden/options/options.py
FDRKinematicRetargetingOptions
¶
Bases: ConfigurableOptions
Imported clips -> <dataset>/<robot>/motion.pt for one robot.
| PARAMETER | DESCRIPTION |
|---|---|
dataset
|
The dataset directory (
TYPE:
|
robot
|
The bimanual robot the clips are retargeted to.
TYPE:
|
workers
|
Processes;
TYPE:
|
steps
|
Which steps run.
TYPE:
|
desk
|
Support-disk fitting.
TYPE:
|
filters
|
Reject rules.
TYPE:
|
convex
|
Convex decomposition backend (
TYPE:
|
retarget
|
Physics IK.
TYPE:
|
pack
|
TYPE:
|
sdf
|
Object SDF grids.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
steps
class-attribute
instance-attribute
¶
steps: FDRStepsOptions = Field(default_factory=FDRStepsOptions)
desk
class-attribute
instance-attribute
¶
desk: FDRDeskOptions = Field(default_factory=FDRDeskOptions)
filters
class-attribute
instance-attribute
¶
filters: FDRFilterOptions = Field(default_factory=FDRFilterOptions)
convex
class-attribute
instance-attribute
¶
convex: FDRConvexOptions = Field(default_factory=FDRCoacdConvexOptions)
retarget
class-attribute
instance-attribute
¶
retarget: FDRRetargetOptions = Field(default_factory=FDRRetargetOptions)
pack
class-attribute
instance-attribute
¶
pack: FDRPackOptions = Field(default_factory=FDRPackOptions)
Import: a released dataset -> <dataset>/human_demo/<clip>.npz + <dataset>/objects/<id>/visual.obj.
The release is read by its :mod:eden.datasets loader (TacoDataset, OakInk2Dataset, Hot3dDataset,
DexYCBDataset) with its MANO parameters (body_model_params), in the loader's z-up world at the release's
frame rate; the loader cuts the clips and picks the object each hand holds. Per clip, this runs MANO, moves the
surface the objects rest on to table_z, takes the wrist and fingertip reference the rewards compare against, and
resamples to fps. A clip is skipped when an object flips more than max_obj_rot_step_deg in one source frame.
Attributes¶
SOURCE_DATASETS
module-attribute
¶
SOURCE_DATASETS = {'taco': 'taco_dataset', 'oakink2': 'oak_ink2_dataset', 'hot3d': 'hot3d_dataset', 'dexycb': 'dex_ycb_dataset'}
Classes¶
Functions:¶
open_dataset
¶
open_dataset(cfg: FDRImportOptions) -> DatasetBase
The :mod:eden.datasets loader of cfg.source, built over cfg.raw with its MANO parameters.
Source code in eden/extensions/retargeting/flashdexretarget/importer.py
import_demos
¶
import_demos(cfg: FDRImportOptions) -> list[dict]
cfg.raw (a released dataset, cfg.source) -> <dataset>/human_demo/<clip>.npz and
<dataset>/objects/<id>/visual.obj.
| PARAMETER | DESCRIPTION |
|---|---|
cfg
|
Import settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
One row per clip: its name and frame count and objects, or the reason it was skipped ( |
Source code in eden/extensions/retargeting/flashdexretarget/importer.py
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | |
Kinematic retargeting: imported clips -> <dataset>/<robot>/motion.pt for one robot.
================= ================================================== ===========================================
step does writes (under the dataset)
================= ================================================== ===========================================
preprocess support disks, reject rules <robot>/report.csv
convex convex decomposition (CoACD or CuACD) objects/<id>/convex/*.obj
retarget MuJoCo physics IK <robot>/retargeted/<clip>.npz
pack kept clips into one file <robot>/motion.pt
urdf object URDFs for simulation objects/<id>/object.urdf
sdf object SDF grids objects/<id>/.sdf_cache/
================= ================================================== ===========================================
Classes¶
Functions:¶
run_kinematic_retargeting
¶
run_kinematic_retargeting(cfg: FDRKinematicRetargetingOptions) -> Path | None
Run the enabled steps over cfg.dataset.
The robot's outputs go to <dataset>/<robot>/ (report.csv, retargeted/, motion.pt), so each robot
retargeted from one import keeps its own; human_demo/ and objects/ are shared. A dataset without
human_demo/ but with the robot's motion.pt only gets its objects prepared (convex, sdf).
| PARAMETER | DESCRIPTION |
|---|---|
cfg
|
Pipeline settings. |
| RETURNS | DESCRIPTION |
|---|---|
Path | None
|
|
Source code in eden/extensions/retargeting/flashdexretarget/pipeline.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
Preprocess: support disks and reject rules over every imported clip (writes only the report rows).
Classes¶
Functions:¶
preprocess_clips
¶
preprocess_clips(clips: Path, pool: Path, cfg: FDRKinematicRetargetingOptions, fps: float, workers: int) -> tuple[list[dict], dict[Path, ndarray | None]]
Report rows of every clip, and the kept clips with their support disks.
| PARAMETER | DESCRIPTION |
|---|---|
clips
|
The
TYPE:
|
pool
|
The dataset directory holding
TYPE:
|
cfg
|
Pipeline settings ( |
fps
|
The clips' frame rate.
TYPE:
|
workers
|
Processes.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[list[dict], dict[Path, ndarray | None]]
|
One report row per clip ( |
Source code in eden/extensions/retargeting/flashdexretarget/preprocess.py
Retarget step: every IK attempt of every kept clip as a job of its own, the best attempt per clip saved to
<robot>/retargeted/<clip>.npz and scored for the report.
A saved clip is a cache keyed (cache_key) on everything its IK read: the robot and its model files, the imported
clip's bytes, its support disks, its objects' convex parts and the retarget options (force and the quality
flags, which are scored afresh every run, aside), so a re-import, an updated asset, redone convex parts or a changed
setting redoes it.
Functions:¶
cache_key
¶
cache_key(clip_path: Path, disks: ndarray | None, robot: str, robot_sha1: str, convex_sha1: dict[str, str], cfg) -> dict
What a retargeted clip was made from (cfg: retarget); compared field by field against a saved clip's.
robot_sha1 is :func:~eden.extensions.retargeting.flashdexretarget.scene.robot_sha1 of the clip's hands and
convex_sha1 maps each of its objects to
:func:~eden.extensions.retargeting.flashdexretarget.convex.parts_sha1.
Source code in eden/extensions/retargeting/flashdexretarget/retarget.py
saved_key
¶
The cache_key a retargeted clip was saved with; None when it has none.
Source code in eden/extensions/retargeting/flashdexretarget/retarget.py
key_mismatch
¶
The fields of key a saved clip's key differs in (['cache_key'] when it has none).
Source code in eden/extensions/retargeting/flashdexretarget/retarget.py
retarget_clips
¶
retarget_clips(clips: list[tuple[Path, ndarray | None]], pool: Path, out: Path, robot: str, cfg, fps: float, workers: int, keys: dict[str, dict]) -> list[dict]
IK of (clip file, support disks) pairs into out, a cache: a clip whose saved result has its keys[stem]
(:func:cache_key) is not redone unless cfg.force (cfg: retarget). Every IK run of every clip (cfg.attempts per
clip) is a job of its own, so a long clip takes one run's time. Returns the report rows; retarget_seconds sums a
clip's runs. A clip that fails has an error and no file in out.
Source code in eden/extensions/retargeting/flashdexretarget/retarget.py
Pack: kept retargeted clips -> <dataset>/<robot>/motion.pt, with velocities and fingertip contact labels.
Per-frame arrays are concatenated over clips; clip i covers frames length_starts[i] to
length_starts[i] + motion_num_frames[i]. joint_pos is in the robot MJCF's joint order, which joint_names
lists; robot names the robot and fps the frame rate.
Functions:¶
velocity
¶
Finite difference, Gaussian-smoothed over time (sigma in frames).
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
angular_velocity
¶
World-frame angular velocity of a (T, 3, 3) rotation sequence.
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
tip_contacts
¶
tip_contacts(tips: ndarray, pose: ndarray, verts: ndarray, tree: cKDTree, threshold: float) -> tuple[ndarray, ndarray, ndarray]
Fingertips (T, 5, 3) vs the object: distance to the nearest of its surface points verts (tree over
them; :class:~eden.extensions.retargeting.flashdexretarget.clips.ObjectMeshes surface) (T, 5), contact
flags (distance < threshold, dilated by one frame), and that point in the object frame (T, 5, 3).
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
load_clip
¶
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
joint_names
¶
The robot MJCF's joints in qpos order: the columns of joint_pos.
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
build
¶
build(clips: Path, dataset: Path, motion: Path, fps: float, cfg, robot: str, keys: dict[str, dict]) -> None
Pack the retargeted clips of keys (clip name -> its
:func:~eden.extensions.retargeting.flashdexretarget.retarget.cache_key) into motion (cfg: pack). Its object
mesh directories are relative to motion's directory (../objects/<id> for <dataset>/<robot>/motion.pt).
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
object_meshes
¶
Unique (visual.obj, scale) pairs a motion.pt references, in slot order; root is the motion.pt's directory,
which its mesh directories are relative to.
Source code in eden/extensions/retargeting/flashdexretarget/pack.py
The imported-clip format (<dataset>/human_demo/<clip>.npz) and the object-mesh cache the pipeline shares.
All arrays are at the clip's fps, in a z-up world, in metres; s is right or left:
============================================ =========================== ============================================
key shape content
============================================ =========================== ============================================
fps () frame rate (one per dataset)
mano_s_wrist_pos, mano_s_wrist_rot (T, 3), (T, 3, 3) MANO wrist, rotation in the robot palm's
convention (see :func:mano_reference)
mano_s_joints (T, 20, 3) MANO finger joints and tips,
:data:MANO_JOINT_NAMES order
obj_s_pose, obj_s_id (T, 4, 4), () object pose and its folder under
objects/
obj_s_scale, obj_s_mass () optional mesh scale and mass
============================================ =========================== ============================================
Attributes¶
MANO_JOINT_NAMES
module-attribute
¶
MANO_JOINT_NAMES = tuple(sorted(f'{f}_{p}' for f in FINGERS for p in ('proximal', 'intermediate', 'distal', 'tip')))
THREAD_VARS
module-attribute
¶
WORKER_MODULES
module-attribute
¶
WORKER_MODULES = ('eden.extensions.retargeting.flashdexretarget.preprocess', 'eden.extensions.retargeting.flashdexretarget.retarget')
Classes¶
ObjectMeshes
¶
objects/<id>/visual.obj (scaled) per (object, scale): vertices, convex hull, centre of mass, and the
surface points (surface, the mesh subdivided to :data:SURFACE_SPACING) with their KD-tree (tree), which
measures distances to the surface.
| PARAMETER | DESCRIPTION |
|---|---|
pool
|
The dataset directory holding |
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
Attributes¶
Methods:¶
get
¶
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
Functions:¶
mano_reference
¶
mano_reference(joints: ndarray, verts: ndarray, global_rot: ndarray, side: str) -> tuple[ndarray, ndarray, ndarray]
MANO layer output -> the clip's hand arrays.
| PARAMETER | DESCRIPTION |
|---|---|
joints
|
(T, 16, 3) MANO joints.
TYPE:
|
verts
|
(T, 778, 3) MANO vertices.
TYPE:
|
global_rot
|
(T, 3, 3) MANO global orientation.
TYPE:
|
side
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[ndarray, ndarray, ndarray]
|
Wrist position (T, 3), wrist rotation rebased to the robot palm frame (T, 3, 3), and the 20 named joints
(T, 20, 3) in :data: |
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
single_threaded_workers
¶
single_threaded_workers() -> Iterator[None]
Each of :data:THREAD_VARS the caller has not set is 1 while worker processes start inside, then removed
again: a fresh worker process reads them as it loads numpy (or OpenMP), so N workers keep to N cores, and the
caller's own environment is left as it was.
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
worker_pool
¶
worker_pool(workers: int) -> Iterator[ProcessPoolExecutor]
workers processes for the CPU steps (preprocess, IK), each with one BLAS / OpenMP thread.
They fork from a forkserver, a fresh process that imports :data:WORKER_MODULES once under
:func:single_threaded_workers, not from this one: a fork of this process would keep its thread pools as they
are (numpy's sized to every core), and a spawned worker would spend seconds importing Eden. The server lives as
long as this process, so the thread counts are the ones of the first pool.
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
load_clip
¶
save_clip
¶
Write through a temporary file of this process's own, so an interrupted run never leaves a truncated clip and two runs never write one file.
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
list_clips
¶
sides
¶
num_frames
¶
joints
¶
(T, 20, 3) MANO joints in :data:MANO_JOINT_NAMES order.
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
tips
¶
(T, 5, 3) MANO fingertips, thumb to pinky.
obj_id
¶
obj_scale
¶
obj_pose
¶
shared_object
¶
objects
¶
The clip's distinct object bodies, as hand sides (a shared object counts once).
clip_fps
¶
clip_fps(paths) -> float
The frame rate the clips share (every clip stores its own fps).
Source code in eden/extensions/retargeting/flashdexretarget/clips.py
object_ids
¶
Reject rules over imported clips: the per-clip features they test, and the verdict.
Functions:¶
features
¶
features(clip: dict, meshes: ObjectMeshes, cfg, fps: float) -> dict
Per-clip quantities the reject rules test; cfg: the filters config. Heights are of an object's lowest hull point above the lowest disk top; the floor and the disks under its centre of mass support it.
Source code in eden/extensions/retargeting/flashdexretarget/filters.py
reject_reasons
¶
Source code in eden/extensions/retargeting/flashdexretarget/filters.py
Quality flags of a retargeted clip, from a kinematic replay of its qpos (a flagged clip is still packed).
Attributes¶
Functions:¶
flags
¶
Clip carries qpos (T, nq of the robot MJCF) aligned with its other arrays; cfg: retarget.