Datasets¶
Motion datasets load human or robot motion (motion capture, retargeted clips, hand-object recordings) into the
BatchMotionSequence layout the motion manager plays back. Each loader is a DatasetBase
subclass that fetches its files, parses them, caches the result and applies DatasetModifiers. The
motion datasets guide covers downloading, licences and the runnable examples.
from eden.datasets import DATASET_REGISTRY, LAFAN1RetargetedG1Dataset
from eden.options.datasets import DatasetOptions
Datasets and modifiers register under a snake-case key derived from the class name.
Base class and registry¶
Base class and registry for motion datasets backed by HuggingFace repos.
Attributes¶
Classes¶
DatasetBase
¶
DatasetBase(options: DatasetOptions, device: device)
Bases: ConfigurableMixin[DatasetOptions], FilterMixin
Base class for motion datasets backed by a HuggingFace repo.
| PARAMETER | DESCRIPTION |
|---|---|
registry
|
HuggingFace namespace (user or organisation) that hosts the dataset repo.
Subclasses should set this to enable automatic downloads, e.g.
TYPE:
|
dataset
|
HuggingFace dataset repository name, e.g.
TYPE:
|
raw_data_path
|
Path to the raw data directory. When set, it is used as-is and must
already exist — a missing explicit path raises rather than downloading.
When None and the class defines
TYPE:
|
processed_data_path
|
Path to the processed data file used by this dataset.
TYPE:
|
target_framerate
|
The target framerate of the motion. This must match the simulation frequency. Defaults to 50.0.
TYPE:
|
drop_first_n_frames
|
Number of frames to drop from the start of each raw sequence during
TYPE:
|
drop_last_n_frames
|
Number of frames to drop from the end of each raw sequence during
TYPE:
|
modifiers
|
Offline transforms applied after cache load or raw prepare; never baked into the cache.
TYPE:
|
include_pattern
|
Regexes
TYPE:
|
exclude_pattern
|
Regexes
TYPE:
|
include_list_file
|
YAML/JSON lists of motion files to keep / drop (see :func:
TYPE:
|
exclude_list_file
|
YAML/JSON lists of motion files to keep / drop (see :func:
TYPE:
|
recalculate_velocities
|
Re-estimate velocities by finite differences of the (retimed) positions instead of carrying the source velocities through. Defaults to True.
TYPE:
|
strict_cache_identity
|
Refuse a cache that predates one of
TYPE:
|
body_model_params
|
Also load the parametric body-model pose and shape (MANO / SMPL family) of the sequences that have one, as
TYPE:
|
body_model_dir
|
Directory of the body-model files (e.g.
TYPE:
|
Class Attributes
file_extension: str
The extension of the motion files.
motion_sequence_keys: tuple[str, ...]
The distinct names of the actors present in the dataset.
motion_dofs_name: dict[str, list[str]]
Per actor (motion_sequence_keys entry), the names of the stored dofs_pos columns, in order.
motion_links_name: dict[str, list[str]]
Per actor, the names of the stored link rows, in order.
_hf_allow_patterns: tuple[str, ...] | None
Glob patterns limiting what the automatic download fetches from the HF
repo. None fetches the whole repo. Set this when the repo holds
splits this loader never reads.
_hf_data_subdir: str | None
Directory inside the downloaded (and, if applicable, unpacked) repo
that holds this loader's motion files, as a relative /-separated
path. None reads the repo root.
Notes
The automatic download runs three independent stages, each opt-in:
_hf_allow_patterns decides what is fetched, _post_download_process
unpacks archives in place and returns the root, and _hf_data_subdir
narrows that root to the directory this loader reads. Only the download
path goes through them — an explicit raw_data_path is used as given,
so it must already point at the equivalent of the narrowed directory.
The two layout attributes are private class attributes, not options: a repo's layout belongs to the loader that reads it, so a retarget for another robot or split is a subclass declaring its own. Both are checked when the class is defined.
Source code in eden/datasets/base.py
Attributes¶
modifiers
class-attribute
instance-attribute
¶
modifiers: tuple[DatasetModifierOptions, ...] | list[DatasetModifierOptions] = ()
Methods:¶
prepare
abstractmethod
¶
select_trajectories
¶
Select a subset of trajectories from the loaded dataset, discarding the rest.
| PARAMETER | DESCRIPTION |
|---|---|
trajectories_idx
|
The trajectory indices to keep. |
Source code in eden/datasets/base.py
motion_labels
¶
The per-clip label list self.metadata[key], one entry per loaded trajectory.
| PARAMETER | DESCRIPTION |
|---|---|
key
|
A per-clip metadata key the dataset declares in
TYPE:
|
Source code in eden/datasets/base.py
select_dofs
¶
Select a subset of dofs from the loaded dataset, discarding the rest.
motion_dofs_name is selected with the same indices, so a name keeps labelling its own
column after a subset or a reorder.
| PARAMETER | DESCRIPTION |
|---|---|
dofs_idx_dict
|
The dofs indices to keep, in the order to keep them. |
Source code in eden/datasets/base.py
select_links
¶
Select a subset of links from the loaded dataset, discarding the rest.
motion_links_name is selected with the same indices, so a name keeps labelling its own
row after a subset or a reorder.
| PARAMETER | DESCRIPTION |
|---|---|
links_idx_dict
|
The links indices to keep, in the order to keep them. |
Source code in eden/datasets/base.py
compute_dofs_pos_range
¶
compute_dofs_pos_range(entity_name: str, *, margin: float = 0.15, margin_overrides: dict[str, float] | None = None) -> dict[str, tuple[float, float]]
Per-DOF (min - m, max + m) over every loaded demo frame.
Mirrors dexmachina's demo_data.get_joint_init_limits (the limits half).
Output keys come from self.motion_dofs_name[entity_name]; values are
plain Python floats so the dict can be passed to
EntityOptions.soft_dofs_pos_limits without binding to a device at
config time.
Configuration-time only: forces a GPU→CPU sync via .cpu().tolist(),
so callers should resolve the dict once during config build (not per
step).
| PARAMETER | DESCRIPTION |
|---|---|
entity_name
|
Key into
TYPE:
|
margin
|
Default pad applied to both ends. Dexmachina's default is 0.15.
TYPE:
|
margin_overrides
|
Substring → margin. If a DOF name contains a key, its value
replaces |
| RAISES | DESCRIPTION |
|---|---|
KeyError if ``entity_name`` is not a registered motion sequence key.
|
|
ValueError if the entity has no ``dofs_pos`` data, zero DOFs, or
|
|
``motion_dofs_name`` desynchronized from ``dofs_pos`` (a name list
|
|
that does not name every column).
|
|
Source code in eden/datasets/base.py
compute_dofs_pos_at
¶
Per-DOF qpos at frame of demo sequence sequence_idx.
Companion to :meth:compute_dofs_pos_range for the per-clip
default_dofs_pos override (dexmachina set_custom_init_qpos).
Defaults to the first frame of the first loaded sequence — the
dexmachina convention is one clip per task, so this is the common
case. When the dataset holds multiple clips, pass sequence_idx to
pick the one this task config targets; TaskMod configs select a clip
explicitly.
Configuration-time only: forces a GPU→CPU sync via .cpu().tolist(),
so callers should resolve the dict once during config build (not per
step).
Returns {dof_name: q} as plain Python floats.
| RAISES | DESCRIPTION |
|---|---|
KeyError if ``entity_name`` is not a registered motion sequence key.
|
|
ValueError on any of: no ``dofs_pos`` data, ``motion_dofs_name``
|
|
desynchronized from ``dofs_pos`` (a name list that does not name every column),
|
|
or ``frame`` / ``sequence_idx`` negative or out of range. Dataset-level
|
|
desync is checked **before** ``frame`` / ``sequence_idx`` bounds so the
|
|
deeper config error surfaces first.
|
|
Source code in eden/datasets/base.py
save_cached
¶
save_cached(data_path: str | None = None)
Save the processed dataset to data_path in the current cache format (_CACHE_FORMAT_VERSION).
The on-disk layout is a single torch.save call over a plain dict
with a _meta envelope (matching the project's config-serialisation
convention in eden/utils/configs.py)::
{
"_meta": {
"_format_version": 4,
"eden": {"version": ..., "commit": ...}, "genesis": {...},
"target_framerate": ..., "motion_sequence_keys": [...],
"motion_dofs_name": ..., "motion_links_name": ...,
"cache_identity": {...}, "frame_window": ..., "cache_semantics": ...,
"all_motion_files": [...], ..., # plus the dataset's own metadata keys
},
"sequences": {key: state_dict, ...},
}
Each per-key state_dict is produced by
BatchMotionSequence.to_state_dict() and contains only tensors and
primitive Python types — no custom objects — so the file is
torch.load(mmap=True)-loadable. Multiple DDP ranks on the same
node share the OS page cache instead of each materialising a private
copy of the motion library.
Source code in eden/datasets/base.py
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 | |
load_cached
¶
Load the processed dataset from a cache file in the current format (_CACHE_FORMAT_VERSION).
Uses torch.load(mmap=True) so tensors are page-cached at the OS
level instead of materialised into per-process buffers — repeated
loads (e.g. across DDP ranks on the same node) avoid re-reading the
file from disk and avoid duplicating it in RAM.
Source code in eden/datasets/base.py
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | |
Functions:¶
cache_identity
¶
cache_identity(dataset: DatasetBase) -> dict[str, Any]
The prepare-shaping settings a cache was built with, for the _meta envelope.
Public because a dataset that derives its own default processed_data_path has to key
that path by the same settings :meth:DatasetBase.load_cached hard-checks against it.
Reading both off this one function is what stops the two drifting: a field added to
_cache_identity_fields then starts keying a new cache file in the same commit that
starts rejecting the old one, rather than turning two valid configs into one contested
path that each rejects for the other.
| PARAMETER | DESCRIPTION |
|---|---|
dataset
|
Dataset to read the values from. Only ever reads attributes that have class-level defaults, so an uninitialized instance is a valid argument.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, Any]
|
Field name to :func: |
Source code in eden/datasets/base.py
Options¶
Dataset and dataset-modifier configuration options.
Classes¶
DatasetModifierOptions
¶
Bases: DynamicConfigurableOptions
Options for dataset modifiers.
| PARAMETER | DESCRIPTION |
|---|---|
motion_sequence_keys
|
Keys in
|
Source code in eden/options/options.py
DatasetOptions
¶
Bases: DynamicConfigurableOptions
Dataset options.
| PARAMETER | DESCRIPTION |
|---|---|
registry
|
HuggingFace namespace (user or organisation) that hosts the dataset repo.
Subclasses should set this to enable automatic downloads, e.g.
|
dataset
|
HuggingFace dataset repository name, e.g.
|
raw_data_path
|
Path to the raw data directory. When provided it is used as-is and must
already exist — a missing explicit path raises rather than downloading.
When None and the dataset class defines
|
processed_data_path
|
Path to the processed (cached) data file.
|
target_framerate
|
The target framerate of the motion.
|
drop_first_n_frames
|
Frames dropped from the start of each raw clip during
|
drop_last_n_frames
|
Frames dropped from the end of each raw clip during
|
modifiers
|
Ordered sequence of offline transforms applied to the loaded motion sequences after cache load or raw prepare. Modifiers are not baked into the processed cache — changing the config re-applies them on next load.
|
include_pattern
|
Regex applied to each motion file's basename via
|
exclude_pattern
|
Regex applied to each motion file's basename via
|
include_list_file
|
Path to a YAML or JSON file enumerating motion files to keep. The file
may be (a) a flat list of paths/basenames, (b) a list of dicts each
with a
|
exclude_list_file
|
Path to a YAML or JSON file enumerating motion files to drop. Same
accepted shapes and matching rules as
|
Source code in eden/options/options.py
Attributes¶
modifiers
class-attribute
instance-attribute
¶
modifiers: tuple[DatasetModifierOptions, ...] | list[DatasetModifierOptions] = ()
Humanoid motion¶
AMASSRetargetedG1Dataset
¶
AMASSRetargetedG1Dataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the AMASS retargeted G1 dataset.
Source code in eden/datasets/base.py
Attributes¶
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'g1': G1_DOFS29_TRACKED_LINKS_NAME}
Methods:¶
prepare
¶
Source code in eden/datasets/amass_dataset.py
LAFAN1RetargetedG1Dataset
¶
LAFAN1RetargetedG1Dataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the LAFAN1 retargeted G1 dataset.
Source code in eden/datasets/base.py
Attributes¶
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'g1': G1_DOFS29_TRACKED_LINKS_NAME}
Methods:¶
prepare
¶
Prepare the LAFAN1 retargeting dataset; the CSVs carry base + DOFs only, so links come from FK.
Source code in eden/datasets/lafan1_dataset.py
SEEDRetargetedG1Dataset
¶
SEEDRetargetedG1Dataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the SEED motion library retargeted to the Unitree G1.
https://huggingface.co/datasets/bones-studio/seed
SEED ships three splits (SOMA Uniform BVH, SOMA Proportional BVH, and the
G1 MuJoCo-compatible CSV split). This loader only consumes the G1 CSV
split, distributed inside g1.tar.gz (~23 GB).
Notes
The HuggingFace repo is gated; users must request access on HuggingFace
and have a token configured (huggingface-cli login) before the
automatic download will succeed.
CSV layout (one file per motion, header row + one row per frame at 120 fps):
Frame, root_translate{X,Y,Z}, root_rotate{X,Y,Z}, <29 DOFs>
where translation is in centimetres and the DOF columns are joint angles
in degrees in the same order as motion_dofs_name['g1'] below. The
root rotation columns are XYZ Euler magnitudes in degrees, but the
rotation is composed in intrinsic ZYX order (R = Rz · Ry · Rx) — the
Maya export convention. Reading them as intrinsic XYZ produces a
visually plausible standing pose at frame 0 but lifts one foot off the
ground mid-clip, while ZYX keeps the feet planted throughout.
Source code in eden/datasets/base.py
Attributes¶
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'g1': G1_DOFS29_TRACKED_LINKS_NAME}
Methods:¶
prepare
¶
Prepare the SEED retargeted G1 dataset; the CSVs carry base + DOFs only, so links come from FK.
Source code in eden/datasets/seed_dataset.py
PHUMADataset
¶
PHUMADataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the PHUMA dataset.
https://huggingface.co/datasets/DAVIAN-Robotics/PHUMA. Unset, raw_data_path downloads its data.zip into
the Hugging Face cache and unzips it there on first use; set it to an already unpacked copy instead.
Source code in eden/datasets/base.py
Attributes¶
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'g1': G1_DOFS29_TRACKED_LINKS_NAME}
Methods:¶
prepare
¶
Prepare the PHUMA dataset.
Reads the ~73k per-motion .npy files in parallel on CPU, packs them
with a single torch.cat per field, then moves the batched sequence to
self.device for the Genesis-based forward-velocity FK pass.
Source code in eden/datasets/phuma_dataset.py
Human-object and human-human interaction¶
OMOMOHolosomaDataset
¶
OMOMOHolosomaDataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the OMOMO data processed by Holosoma pipeline.
Each sequence is stored as an individual .pt file containing an
InterMimic-format tensor of shape (T, 591). The tensor encodes:
- offset 0-2: root position (3)
- offset 3-6: root quaternion in wxyz (4)
- offset 162-317: 52 SMPL-H joint world positions (52 x 3)
- offset 318-324: object pose [x, y, z, qx, qy, qz, qw] (7)
Unlike the original OMOMO pickle format, no FK is required — joint
positions are pre-computed. The 52 joints follow the
:data:SMPLH_KEYPOINTS_NAME order.
Source code in eden/datasets/base.py
Attributes¶
motion_dofs_name
class-attribute
¶
motion_links_name
class-attribute
¶
Methods:¶
prepare
¶
Source code in eden/datasets/omomo_dataset.py
WeaveG1InspireHOIDataset
¶
Bases: DatasetBase
Weave G1-Inspire-HOI reference clips: a G1 + two Inspire RH56DFQ hands tracking an OMOMO object.
| PARAMETER | DESCRIPTION |
|---|---|
split
|
TYPE:
|
objects
|
Load only these objects' files (a subset of :data: |
Source code in eden/datasets/weave_dataset.py
Attributes¶
motion_sequence_keys
class-attribute
¶
motion_dofs_name
class-attribute
¶
motion_dofs_name: dict[str, list[str]] = {'robot': list(WEAVE_JOINT_NAMES[:29]), 'left_hand': _hand_dofs_name('L'), 'right_hand': _hand_dofs_name('R'), 'object': []}
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'robot': list(WEAVE_ROBOT_LINK_NAMES), 'left_hand': _hand_link_names('L'), 'right_hand': _hand_link_names('R'), 'object': []}
Methods:¶
prepare
¶
Source code in eden/datasets/weave_dataset.py
HHIAssistDataset
¶
HHIAssistDataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the HHI-Assist dataset.
The HHI-Assist dataset contains human-human interaction motion capture data recorded with an Optitrack system at 120 Hz. Each interaction consists of a caregiver (CG) and a care recipient (CR), captured as paired BVH files.
References
- https://github.com/vita-epfl/HHI-Assist/
- https://huggingface.co/datasets/jose-barreiros-tri/hhi-assist
Source code in eden/datasets/base.py
Attributes¶
motion_sequence_keys
class-attribute
¶
motion_dofs_name
class-attribute
¶
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'caregiver': HHI_JOINT_NAMES, 'recipient': HHI_JOINT_NAMES}
Methods:¶
prepare
¶
Source code in eden/datasets/hhi_assist_dataset.py
Hand-object manipulation¶
ArcticDataset
¶
ArcticDataset(options: DatasetOptions, device: device)
Bases: DatasetBase
Dataset class for the Arctic dataset.
Arctic dataset contains sequences with a left hand, a right hand, and an object. Each of these entities is represented by a separate MotionSequence.
References
- https://huggingface.co/datasets/Kashu7100/eden_arctic
Source code in eden/datasets/base.py
Attributes¶
motion_sequence_keys
class-attribute
¶
motion_dofs_name
class-attribute
¶
motion_dofs_name: dict[str, list[str]] = {'object': ['rotation'], 'left_hand': [], 'right_hand': []}
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'object': ['bottom', 'top'], 'left_hand': list(MANO_KEYPOINTS_NAME), 'right_hand': list(MANO_KEYPOINTS_NAME)}
Methods:¶
prepare
¶
Prepare the Arctic dataset by reading every raw .npy file in all_motion_files.
| RETURNS | DESCRIPTION |
|---|---|
tuple[dict[str, BatchMotionSequence], dict[str, Any]]
|
The object, left-hand and right-hand sequences by |
Source code in eden/datasets/arctic_dataset.py
DexYCBDataset
¶
DexYCBDataset(options: DatasetOptions, device: device)
Bases: DatasetBase
DexYCB single-hand YCB-grasping dataset.
Each sequence is one MANO hand (left or right) interacting with up to four
YCB objects; the loader keeps only the grasped object indicated by
meta.yml::ycb_grasp_ind. Frames where pose_m is all-zero (no MANO
annotation, typically pre-grasp) are trimmed from the leading edge; clips
whose invalid frames are not contiguously at the start are skipped with a
warning so BatchMotionSequence always sees a contiguous range.
Expected on-disk layout (after extracting dex-ycb-20210415.tar.gz or
the per-subject tarballs from https://dex-ycb.github.io/)::
<root>/<YYYYMMDD-subject-NN>/<YYYYMMDD_HHMMSS>/
├── meta.yml # ycb_ids, ycb_grasp_ind, mano_sides, ...
├── pose.npz # world-frame ground-truth poses
└── <camera_serial>/ # color/depth/per-camera labels (unused here)
pose.npz carries:
pose_y— shape(T, num_objects, 7), layout[qx, qy, qz, qw, tx, ty, tz]. Quaternion in xyzw, converted to Eden's wxyz convention here.pose_m— shape(T, 1, 51), layout[pose(48), trans(3)]in dex-ycb-toolkit's MANO parameterisation (manopth: the global wrist axis-angle, 45 finger PCA coefficients relative to the mean hand, and MANO's translation).pose[0:3]is loaded intobase_quat_w. The loader picks up DexYCB's precomputed MANO joint positions from each clip's<seq>/<master_serial>/labels_*.npz::joint_3dand packs them intolinks_pos_w(21 keypoints in :data:eden.datasets.constants.MANO_KEYPOINTS_NAMEorder);base_pos_wis their wrist. (MANO's translation is not the wrist: the wrist sits a shape-dependent offset, ~9 cm, away from it.)
With body_model_params=True the hand also carries its MANO pose and
shape (body_pose_quat / body_shape, body_model mano_<side>):
the PCA expanded into the 15 finger rotations relative to the flat hand,
and the subject's betas from calibration/mano_<id>/mano.yml. That
needs the MANO model files (body_model_dir) for the PCA basis and the
mean hand.
Raw pose.npz poses live in the master camera's frame (x-right,
y-down, z-forward, the first entry in meta.yml::serials).
calibration_dir (the extracted calibration/ directory) is
required: the loader applies each clip's master-camera extrinsic to
bring poses into the AprilTag world frame (z-up, origin on the
table tag) so a Genesis viewer renders correctly. Preparing the dataset
from raw data without calibration_dir raises FileNotFoundError.
Captures run at 30 fps.
No HuggingFace mirror is provided: the upstream is gated behind a Google
Drive consent form, so users must download and extract manually, then
pass the extracted root as raw_data_path.
References
- https://dex-ycb.github.io/
- https://github.com/NVlabs/dex-ycb-toolkit
| PARAMETER | DESCRIPTION |
|---|---|
calibration_dir
|
Path to DexYCB's
|
ground_initial_pose
|
Translates each clip uniformly along world-Z so the object's world AABB bottom touches z=0 at frame 0; orientation passes through unchanged.
|
apply_mesh_correction
|
Applies :data:
|
models_dir
|
DexYCB's
|
retargeted_label
|
When set, also load each clip's
|
Source code in eden/datasets/base.py
Attributes¶
motion_dofs_name
class-attribute
¶
motion_links_name
class-attribute
¶
Methods:¶
prepare
¶
Source code in eden/datasets/dex_ycb_dataset.py
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 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 | |
object_mesh
¶
The trimesh.Trimesh (metres) that clip object poses of object_name place: its geometry, loaded once
per dataset.
With apply_mesh_correction the poses were moved onto Eden's YCB asset (ycb/models/<name>/textured.obj);
without it they are the release's, on <models_dir>/<name>/textured_simple.obj. With materials, read
again with its material and texture, and not cached: trimesh decodes the 4096^2 texture as it loads it
(~50 MB per object), which only an export of the mesh needs.
Source code in eden/datasets/dex_ycb_dataset.py
load_apriltag_master_calibration
¶
Read <calibration_dir>/extrinsics_<id>/extrinsics.yml.
Returns (T_apriltag_master, master_serial). The apriltag
entry in the file is T_master_apriltag (AprilTag pose in the
master camera's frame); we invert it so left-applying brings
master-cam-frame poses into the z-up AprilTag world.
master_serial is the calibration's top-level master
field, used by downstream code that reads per-camera files
(e.g. MANO keypoints from labels_*.npz).
Source code in eden/datasets/dex_ycb_dataset.py
MANO hand-object releases¶
TACO, OakInk2 and HOT3D ship MANO parameters rather than keypoints, so their loaders need the licence-gated MANO
model files (body_model_dir). They share HandObjectDatasetBase.
Shared base of the MANO hand-object releases (TACO, OakInk2, HOT3D): per-side hand and held-object sequences.
Classes¶
HandObjectDatasetBase
¶
HandObjectDatasetBase(options: DatasetOptions, device: device)
Bases: DatasetBase
Base of the MANO hand-object releases: each clip is the hands of sides and the object each one holds.
Keys: <side>_hand (base = the MANO wrist, links_pos_w = the 21
:data:~eden.datasets.constants.MANO_KEYPOINTS_NAME keypoints) and object_<side> (the held object's pose)
for each side in sides. A clip where one of those hands holds nothing is left out and named in
metadata["skipped"], as is any clip its reader rejects. With body_model_params=True each hand also carries
its MANO pose and shape. The releases ship MANO parameters, not keypoints, so the MANO model files
(body_model_dir) are always needed.
Per-clip metadata: clip_names, recordings, objects_<side> (the held object id); the poses of every
object of a recording come from :meth:recording_object_poses, read on demand from the release.
The file filters (include_pattern, the list files, ...) match each clip's <unit>/<clip name> path, on a
fresh build as on a cache load: a clip is only known once its unit is read, so a build reads every unit first.
| PARAMETER | DESCRIPTION |
|---|---|
sides
|
TYPE:
|
Source code in eden/datasets/base.py
Attributes¶
motion_sequence_keys
class-attribute
¶
motion_dofs_name
class-attribute
¶
motion_dofs_name: dict[str, list[str]] = {k: [] for k in motion_sequence_keys}
motion_links_name
class-attribute
¶
motion_links_name: dict[str, list[str]] = {'right_hand': list(MANO_KEYPOINTS_NAME), 'left_hand': list(MANO_KEYPOINTS_NAME), 'object_right': [], 'object_left': []}
Methods:¶
units
¶
The release's units of work (recordings or sequences), as paths under root; raises naming the expected
layout when root is not the release.
read_unit
¶
The clips of unit; a (name, reason) pair is a clip the reader rejected.
object_mesh
¶
The trimesh.Trimesh (metres) of object obj_id, in the frame its poses place: its geometry, cached.
With materials, read again with its materials and textures, and not cached: trimesh decodes the textures
as it loads them (a 4096^2 texture holds ~50 MB), which only an export of the mesh needs.
Source code in eden/datasets/hand_object_base.py
recording_object_poses
¶
Every object's (T, 4, 4) world pose over the whole recording (read from the release on demand).
Source code in eden/datasets/hand_object_base.py
prepare
¶
Source code in eden/datasets/hand_object_base.py
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 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 | |
near
¶
Distance from each (N, 3) object-frame point to the nearest mesh vertex where below bound, else inf;
points outside the vertices' box padded by bound skip the KD-tree.
Source code in eden/datasets/hand_object_base.py
HandObjectClip
dataclass
¶
HandObjectClip(name: str, recording: str, hands: dict[str, MANOHand], objects: dict[str, str], poses: dict[str, ndarray])
One clip a release's reader cut: hands, the object each holds, and object poses (object -> world).
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Unique clip name.
TYPE:
|
recording
|
The recording it was cut from; clips of one recording share
:meth:
TYPE:
|
hands
|
Hand side -> hand. |
objects
|
Hand side -> the object id it holds (both sides may name one object). |
poses
|
Object id -> (T, 4, 4) pose. |
MANOHand
dataclass
¶
MANOHand(side: str, root_pos: ndarray, root_rotvec: ndarray, finger_pose: ndarray, betas: ndarray, keypoints: ndarray | None = None)
One hand of a clip in the dataset's z-up world, at the release's frame rate.
| PARAMETER | DESCRIPTION |
|---|---|
side
|
TYPE:
|
root_pos
|
(T, 3) MANO root joint (the wrist).
TYPE:
|
root_rotvec
|
(T, 3) global orientation, axis-angle.
TYPE:
|
finger_pose
|
(T, 45) finger axis-angles relative to the flat hand.
TYPE:
|
betas
|
(T, B) or (B,) shape coefficients.
TYPE:
|
keypoints
|
(T, 21, 3) float32 :data:
TYPE:
|
Attributes¶
Methods:¶
frames
¶
The hand on frames idx (a per-frame betas is sliced, a constant one kept).
Source code in eden/datasets/hand_object_base.py
rotated
¶
rotated(R: ndarray) -> MANOHand
The hand with the world rotated by R; finger rotations are local and stay, keypoints are dropped.
Source code in eden/datasets/hand_object_base.py
forward
¶
(T, 16, 3) joints and (T, 778, 3) vertices, float64.
Source code in eden/datasets/hand_object_base.py
keep_keypoints
¶
Store the keypoints of this hand's :meth:forward output, so packing does not run the model again.
Source code in eden/datasets/hand_object_base.py
TacoDataset
¶
TacoDataset(options: DatasetOptions, device: device)
Bases: HandObjectDatasetBase
TACO: one clip per recording, both hands and the tool and target objects.
Layout (github.com/Satorinal/TACO)::
<root>/Hand_Poses/<(action, tool, target)>/<seq>/{right,left}_hand.pkl, {right,left}_hand_shape.pkl
<root>/Object_Poses/<(action, tool, target)>/<seq>/{tool,target}_<id>.npy
<root>/object_models_released/<id>_cm.obj
Hands are MANO relative to the flat hand, with the wrist given; objects (4, 4) per frame; 30 Hz, z-up, turned
180 degrees about z (CHORD's frame). Each hand holds the object it stays nearest to over the clip (both hands
the one object when there is only one). Clip names taco_<action>__<tool>__<target>_<seq>. Needs the MANO
model files (body_model_dir); see :class:~eden.datasets.hand_object_base.HandObjectDatasetBase.
Source code in eden/datasets/base.py
Attributes¶
Methods:¶
units
¶
Source code in eden/datasets/taco_dataset.py
read_unit
¶
Source code in eden/datasets/taco_dataset.py
OakInk2Dataset
¶
OakInk2Dataset(options: DatasetOptions, device: device)
Bases: HandObjectDatasetBase
OakInk2: each recording cut into the stages of its program, one clip per stage.
Layout::
<root>/anno_preview/<seq>.pkl # raw_mano and obj_transf per mocap frame
<root>/program/program_info/<seq>.json # the program's stages: frame spans, objects per hand
<root>/object_repair/align_ds/<id>/model.obj
120 Hz, y-up turned z-up. A stage is the frames from its first span's start to its last span's end (clip
<seq>__stNN). Each hand holds the object its 16 MANO links touch most (a vertex within contact of the
object's mesh, counted per link and frame), as CHORD assigns them, since the program can name the other hand's
object; the program's own object when it touches none. A stage with several objects in one loaded hand
(sides), or with a mocap frame missing from its span, is skipped, as is a recording whose mocap frame ids
step by more than 1 (packed at 120 Hz, it would play too fast).
:meth:recording_object_poses gives every object with a mesh over the whole recording. Needs the MANO model
files (body_model_dir).
| PARAMETER | DESCRIPTION |
|---|---|
contact
|
Distance (m) under which a MANO vertex touches an object.
TYPE:
|
Source code in eden/datasets/base.py
Attributes¶
Methods:¶
units
¶
Source code in eden/datasets/oakink2_dataset.py
read_unit
¶
Source code in eden/datasets/oakink2_dataset.py
recording_object_poses
¶
Hot3dDataset
¶
Hot3dDataset(options: DatasetOptions, device: device)
Bases: HandObjectDatasetBase
HOT3D, read as CHORD's hot3d_loader.py and cut into hand-object segments as its segment_to_atomic.py.
Layout::
<root>/dataset/<recording>/{mano_hand_pose_trajectory.jsonl, dynamic_objects.csv,
headset_trajectory.csv, metadata.json}
<root>/_assets/assets/<uid>.glb
Recordings with hand and object ground truth; one timestamp per 10 ms, 30 Hz; the frames with both hands and
every object (a segment across a missing frame is skipped). Quest3's y-up world is turned z-up, then yawed so the
workspace (the mean of every object position and hand transl) lies along +y from the headset's first position,
turned 90 degrees further (CHORD's frame). Hands are MANO with 15 PCA components relative to the mean hand.
drop_first_n_frames / drop_last_n_frames trim a segment after its pad_frames are added, so they take
the still padding first.
Segments (clip <recording>_segNNN, CHORD's numbering): a hand is active while a fingertip is within
tip_contact of an object (gaps under gap_frames bridged); windows of activity split where the touched
object changes (each frame's object: the one most of both hands' 16 MANO links are nearest to, within
link_contact); segments under min_frames dropped, pad_frames still frames added at both ends. Mode A:
one hand active, B: both on one object, C: on two objects; the segments of modes are kept. In mode B both hands
hold the object; in A only the active hand holds one (so sides='both' skips the segment, its other hand
holding nothing), and in C each hand holds its own. FlashDexRetarget hands every hand the segment's one object,
which labels an idle hand (A) or the other hand's object (C) as held. :meth:recording_object_poses gives every
object over the recording. Needs the MANO model files (body_model_dir).
| PARAMETER | DESCRIPTION |
|---|---|
tip_contact
|
Fingertip-object distance (m) under which a hand is active.
TYPE:
|
link_contact
|
Vertex-object distance (m) under which a MANO link touches an object.
TYPE:
|
gap_frames
|
Inactive gaps shorter than this are bridged.
TYPE:
|
min_frames
|
Shorter segments are dropped.
TYPE:
|
pad_frames
|
Still frames repeated at each end of a segment.
TYPE:
|
modes
|
Segment modes kept ( |
Source code in eden/datasets/base.py
Attributes¶
Methods:¶
units
¶
Source code in eden/datasets/hot3d_dataset.py
read_unit
¶
Source code in eden/datasets/hot3d_dataset.py
recording_object_poses
¶
Source code in eden/datasets/hot3d_dataset.py
Modifiers¶
Offline transforms applied to loaded sequences, in order. DatasetModifierOptions.motion_sequence_keys selects
the sequences each one targets.
Base class and registry for dataset modifiers.
Attributes¶
DATASET_MODIFIER_REGISTRY
module-attribute
¶
DATASET_MODIFIER_REGISTRY = Registry('DATASET_MODIFIER')
Classes¶
DatasetModifier
¶
DatasetModifier(options: T)
Bases: ConfigurableMixin[DatasetModifierOptions]
Base class for composable dataset modifiers.
Dataset modifiers are offline transforms applied to loaded motion sequences
(after cache load or raw prepare) rather than per simulation step. They are
useful for data augmentation and canonicalization — e.g. spatial offsets,
rotations, time warps, or dropping fields that the downstream task does not
need. Modifiers are composed via :class:Compose, similar to
:class:~eden.managers.modifiers.actions.actuators.Compose::
modifiers = [
Translate.configure(offset=(0.0, 0.0, 0.05)),
]
Subclasses override :meth:apply_to_sequence to transform a single
:class:~eden.utils.motion_reference.motion_data.BatchMotionSequence.
The default :meth:apply iterates over the configured keys (or every key
when motion_sequence_keys is None) and delegates to
:meth:apply_to_sequence.
Source code in eden/utils/common.py
Attributes¶
motion_sequence_keys
class-attribute
instance-attribute
¶
Methods:¶
apply
¶
Apply this modifier to every selected key and return the result.
motion_sequence_keys=None (the default) applies to every key;
an explicit empty tuple applies to none and is a deliberate no-op —
use that to temporarily disable a modifier without removing it.
Source code in eden/datasets/modifiers/base.py
apply_to_sequence
¶
Transform a single :class:BatchMotionSequence. Override in subclasses.
Functions:¶
build_modifier
¶
build_modifier(options: DatasetModifierOptions | dict) -> DatasetModifier
Build the modifier options names, by registry name.
options may be the options object or its dict form (a config loaded from YAML).
Source code in eden/datasets/modifiers/base.py
Built-in dataset modifiers.
Attributes¶
Classes¶
Compose
¶
Compose(options: DatasetModifierOptions)
Bases: DatasetModifier
Chain multiple dataset modifiers in sequence.
| PARAMETER | DESCRIPTION |
|---|---|
modifiers
|
Ordered sequence of child modifier configurations. Each modifier's
:meth:
TYPE:
|
Example
::
Compose.configure(
modifiers=[
Translate.configure(offset=(0.0, 0.0, 0.05)),
Translate.configure(
offset=(0.5, 0.0, 0.0),
motion_sequence_keys=("obj",),
),
]
)
Source code in eden/datasets/modifiers/transforms.py
Attributes¶
modifiers
class-attribute
instance-attribute
¶
modifiers: tuple[DatasetModifierOptions, ...] | list[DatasetModifierOptions] = ()
Methods:¶
apply
¶
Source code in eden/datasets/modifiers/transforms.py
Translate
¶
Translate(options: T)
Bases: DatasetModifier
Shift world-frame translations of every motion by a constant offset.
The offset is added to base_pos_w and, if populated, links_pos_w.
Body-frame fields (links_pos_b) and all velocity fields are invariant
under a pure translation and are left untouched.
| PARAMETER | DESCRIPTION |
|---|---|
offset
|
(x, y, z) offset in the dataset world frame. Typical use is a z-only offset to lift trajectories off the ground for a taller robot. |
Source code in eden/utils/common.py
Attributes¶
Methods:¶
apply_to_sequence
¶
Source code in eden/datasets/modifiers/transforms.py
Rotate
¶
Rotate(options: T)
Bases: DatasetModifier
Rotate world-frame fields about a given axis through the world origin.
Rotates every world-frame position, quaternion, linear velocity, and angular
velocity by a single rigid rotation. Body-frame fields (links_*_b) are
invariant under a world rotation and are left untouched.
Because the rotation is about the world origin, combining :class:Rotate
with :class:Translate is order-sensitive — rotate first, then translate
to apply the rotation about the current origin; translate first, then
rotate to orbit the motion about a point.
| PARAMETER | DESCRIPTION |
|---|---|
axis
|
Unit rotation axis in the world frame. Automatically normalized. Default is the Z axis, i.e. a yaw rotation. |
angle_deg
|
Rotation angle in degrees (right-handed about
TYPE:
|
Source code in eden/utils/common.py
Attributes¶
Methods:¶
apply_to_sequence
¶
Source code in eden/datasets/modifiers/transforms.py
MirrorLR
¶
MirrorLR(options: T)
Bases: DatasetModifier
Mirror motion data across a world-frame plane and relabel symmetric parts.
Mirroring is an improper transformation: vectors, pseudovectors, and unit quaternions all follow different sign rules, which this modifier applies automatically. What it cannot know is how the robot's DOFs and links map to each other under reflection — that is robot-specific, and the user provides it as explicit integer swap tables.
For a mirror plane with normal on axis a (e.g. Y for left/right):
- Positions and linear velocities flip component
a. - Angular velocities (pseudovectors under improper transform) flip the other two components.
- Unit quaternions
(w, x, y, z)flip everyxyzcomponent except the one on axisa;wis unchanged.
The sign pattern is applied to both world-frame and body-frame link fields. The body-frame rule follows from applying the same mirror consistently to the base frame; for perfectly symmetric robots this is exact, and for slightly asymmetric ones it is a close approximation — consumers requiring strict accuracy should recompute body-frame fields from world-frame fields downstream.
Ordering within the modifier: axis sign flips → DOF sign flips → DOF swaps
→ link swaps. User-supplied dofs_sign_flip and dofs_swap both
reference the original DOF indices (before swapping).
| PARAMETER | DESCRIPTION |
|---|---|
axis
|
Mirror-plane normal index: 0 = X, 1 = Y (default, left-right), 2 = Z.
TYPE:
|
dofs_swap
|
Pairs of DOF indices to swap after mirroring. Example for a biped:
|
dofs_sign_flip
|
DOF indices whose stored value is negated under mirroring — typically joints that rotate about an axis orthogonal to the mirror plane (e.g. a hip-roll axial joint when mirroring left/right). |
links_swap
|
Pairs of link indices to swap after mirroring. Applied to every
|
Source code in eden/utils/common.py
Attributes¶
Methods:¶
apply_to_sequence
¶
Source code in eden/datasets/modifiers/transforms.py
250 251 252 253 254 255 256 257 258 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 | |
Functions:¶
Temporal dataset modifiers.
Modifiers in this module change the number of frames per motion while keeping
the dataset's target_framerate (and therefore the simulation dt)
fixed. They rebuild the underlying :class:ConcatBatchTensor buffers and
update motion_seq.buffer_length accordingly.
Attributes¶
Classes¶
SpeedScale
¶
SpeedScale(options: T)
Bases: DatasetModifier
Scale playback speed by resampling frames at a fixed target_framerate.
A speed of 2.0 makes the motion play twice as fast — each sequence is
resampled to half the number of frames — while keeping the framerate (and
therefore the simulation dt) unchanged. Because covered distances are
preserved but traversed in half the wall-clock time, every stored velocity
is multiplied by speed.
Position-like fields are interpolated linearly; quaternion fields are interpolated with slerp. Body-frame fields are resampled alongside world-frame fields so consumers that read them stay consistent.
The per-sequence frame count is rounded to max(2, round(T / speed)).
| PARAMETER | DESCRIPTION |
|---|---|
speed
|
Playback-speed factor.
TYPE:
|
Source code in eden/utils/common.py
Attributes¶
Methods:¶
apply_to_sequence
¶
Source code in eden/datasets/modifiers/temporal.py
TrimFrames
¶
TrimFrames(options: T)
Bases: DatasetModifier
Drop leading and trailing frames from every sequence.
Equivalent to DatasetBase.drop_first_n_frames / drop_last_n_frames
but available as a composable post-load modifier — useful for cropping
warm-up or settling frames without re-preparing the cache.
Note
When the dataset has multiple motion_sequence_keys (e.g. robot + object
in a manipulation dataset), apply the same trim to all keys to preserve
the per-sequence length invariant across keys. Selecting a subset via
motion_sequence_keys=(...) will desynchronize the lengths.
| PARAMETER | DESCRIPTION |
|---|---|
trim_first
|
Number of frames to drop from the start of each sequence. Must be >= 0.
TYPE:
|
trim_last
|
Number of frames to drop from the end of each sequence. Must be >= 0.
TYPE:
|
Source code in eden/utils/common.py
Attributes¶
Methods:¶
apply_to_sequence
¶
Source code in eden/datasets/modifiers/temporal.py
Noise-based dataset modifiers.
Attributes¶
Classes¶
Jitter
¶
Jitter(options: T)
Bases: DatasetModifier
Add additive noise to selected motion fields.
Applies independent, per-element noise to every entry of each listed
:class:BatchMotionSequence field. Randomness comes from the global torch
RNG — seed it upstream (e.g. via torch.manual_seed in your script)
for reproducibility.
Quaternion fields are not rejected, but jittering them with additive noise
breaks the unit-norm invariant and should be used carefully — prefer
:class:Rotate for orientation perturbation.
| PARAMETER | DESCRIPTION |
|---|---|
fields
|
:class: |
distribution
|
Noise distribution.
TYPE:
|
std
|
Standard deviation for
TYPE:
|
low
|
Bounds for
TYPE:
|
high
|
Bounds for
TYPE:
|
Source code in eden/utils/common.py
Attributes¶
distribution
class-attribute
instance-attribute
¶
distribution: Literal['gaussian', 'uniform'] = 'gaussian'
Methods:¶
apply_to_sequence
¶
Source code in eden/datasets/modifiers/noise.py
Ground-the-first-frame dataset modifier.
For each motion sequence, set the robot to frame-0's qpos in a transient
Genesis env, read the world-frame AABB's bottom-z, and (if below the
configured margin) shift the entire clip uniformly along +Z so the first
frame sits at-or-above the floor. The shift is a pure translation, so all
velocity and body-frame fields stay invariant — same idiom as
:class:~eden.datasets.modifiers.transforms.Translate, only the offset
is auto-computed per clip from FK instead of being configured up front.
Use this when retargeting can leave clips penetrating the ground at clip start — e.g. AMASS clips retargeted to a robot whose feet sit lower than the source actor, or any pipeline where the source capture's floor plane isn't perfectly aligned with z=0.
It shares the transient-env plumbing (:func:eden.utils.genesis_runtime.transient_robot_env)
with :class:~eden.datasets.modifiers.smooth_start_end.SmoothStartTransition.
Attributes¶
Classes¶
GroundFirstFrame
¶
GroundFirstFrame(options: T)
Bases: DatasetModifier
Shift each clip along +Z so frame-0's world AABB sits at-or-above z=0.
Pipeline per clip:
- Build the robot from
robot_optionsin a transient kinematics env (one env per clip — frame-0 FK runs in a single batched pass). set_qposto(base_pos_w[0], base_quat_w[0], dofs_pos[0]).- Read
robot.get_AABB()[:, 0, 2]per env → per-clip floor min-z. dz = max(0, safety_margin_m - min_z). Clips already above the floor getdz=0and pass through unchanged.- Add
dzto every frame ofbase_pos_w(andlinks_pos_wwhen populated). Body-frame link fields and all velocity fields are invariant under pure translation and are left untouched.
| PARAMETER | DESCRIPTION |
|---|---|
robot_options
|
Eden robot options used to build the transient kinematics env. Must match the robot the dataset is retargeted to (same DOF order, same morph). Required.
TYPE:
|
safety_margin_m
|
Extra clearance above z=0 to enforce.
TYPE:
|
chunk_size
|
Maximum number of clips processed per Genesis env.
TYPE:
|
Notes
Multi-entity datasets: this modifier shifts a single robot key in
place. If the dataset carries paired entities (robot + object) that
must move together, scope the modifier to the robot key with
motion_sequence_keys=(robot_key,) and add a matching shift on
the object key — translating the robot alone would desync them.
Source code in eden/utils/common.py
Attributes¶
Methods:¶
apply
¶
Source code in eden/datasets/modifiers/ground.py
Functions:¶
Smooth start-transition dataset modifier.
Pre-pends every clip with a synthesized stand-still → IK-stepped → SLERP-
merged segment so RSI from a default pose to clip-frame-0 is no longer a
teleport. Ports OpenTrack's StartEndTransitionHandler to Eden's
:class:DatasetModifier API. The actual IK math lives in
:mod:eden.utils.motion_reference.bipedal_ik; this module is the glue that
maps Eden's :class:BatchMotionSequence ↔ a Genesis RigidEntity and
re-FKs link fields after the transition is inserted.
Why a modifier and not a per-step env hook
The IK solve is per-clip and sequential (no benefit from vectorising over envs), and it runs hundreds of forward-kinematics passes per clip. Doing it inside the training loop would thrash wall-time. As a modifier it runs once per dataset load, before training starts. Modifiers are not baked into the processed cache, so the solve is repeated on every load.
What this modifier mutates
The output BatchMotionSequence has per-sequence lengths extended by the
synthesized prefix. Fields rebuilt from scratch:
* base_pos_w, base_quat_w, dofs_pos
* base_lin_vel_w, base_ang_vel_w, dofs_vel (FD from positions)
* links_pos_w, links_quat_w (re-FK through Genesis)
* links_lin_vel_w, links_ang_vel_w (FD from link poses)
* links_pos_b, links_quat_b, links_lin_vel_b,
links_ang_vel_b (recomputed from world-frame + the new base pose)
Attributes¶
Classes¶
SmoothStartTransition
¶
SmoothStartTransition(options: T)
Bases: DatasetModifier
Pre-pend each clip with a synthesized stand-up → step → merge → clip segment.
| PARAMETER | DESCRIPTION |
|---|---|
ik_profile
|
Robot-agnostic IK spec — see :class:
TYPE:
|
motion_links_name_per_key
|
Map |
default_pose_sec
|
Duration (s) of stand-still padding at the start. OpenTrack default: 1.0 s.
TYPE:
|
single_step_threshold_m
|
If the inter-foot distance differs between stance and clip frame 0 by more than this, two steps are synthesized; otherwise one.
TYPE:
|
transition_sec
|
SLERP-merge length between the IK endpoint and clip frame 0.
TYPE:
|
foot_height_m
|
Peak Z bump of the swing foot during the synthesized step.
TYPE:
|
com_xy_offset_m
|
Forward offset of the IK's CoM target relative to the foot midpoint.
TYPE:
|
step_sec
|
Duration of each synthesized step.
TYPE:
|
double_stance_frames
|
Frames of double-stance dwell between successive steps.
TYPE:
|
start_foot
|
Which foot lifts first.
TYPE:
|
max_ik_iters
|
Per-frame IK iteration cap.
TYPE:
|
Source code in eden/utils/common.py
Attributes¶
motion_links_name_per_key
class-attribute
instance-attribute
¶
Methods:¶
apply
¶
Source code in eden/datasets/modifiers/smooth_start_end.py
Functions:¶
TCRS terrain-adaptation dataset modifier.
Runs the TCRS terrain-adaptive motion optimizer
(:mod:eden.extensions.motion_optimization.tcrs) over every clip of a motion dataset:
MPPI foot-swing planning against a terrain height field, support-aware pelvis
height re-targeting, and whole-body Jacobian IK on a MuJoCo model of the
robot. Flat-ground clips come out with footsteps and pelvis height that track
the configured terrain.
The terrain can be described three ways (all reduce to one height field):
TerrainOptions— Eden's procedural terrain (the generator grid is run once, off-scene),EntityOptions— a 3D terrain mesh file, rasterized by downward raycasts atmesh_resolution,str— path to a height-field.npzexported via :func:eden.utils.terrains.io.export_height_field.
The optimization costs minutes per clip and dataset modifiers rerun on every
dataset load (the dataset cache is deliberately saved pre-modifier), so
results are cached on disk keyed by a content hash of (clip data, terrain,
parameters, robot MJCF) — the second load of an unchanged dataset is
near-free. Set cache_dir=None to disable.
This modifier adapts clips 1→1 in place at a single terrain_offset
placement. Upstream-style 1→N random-placement augmentation is out of scope
here; see examples/recipes/motion_optimization/tcrs for batch variant generation.
Attributes¶
Classes¶
TCRSTerrainAdapt
¶
TCRSTerrainAdapt(options: T)
Bases: DatasetModifier
Adapt flat-ground clips to a terrain with the TCRS optimizer.
| PARAMETER | DESCRIPTION |
|---|---|
terrain
|
The terrain to adapt to: procedural
TYPE:
|
robot_options
|
Eden robot options whose
TYPE:
|
terrain_offset
|
SE(2) placement |
mesh_resolution
|
Rasterization cell size in meters when
TYPE:
|
robot_spec
|
A :class:
TYPE:
|
planner
|
A :class:
TYPE:
|
cache_dir
|
Directory for the content-addressed result cache.
TYPE:
|
Notes
links_pos_w/links_quat_w must be populated on the sequence (Eden
mimic datasets fill them via FK). contact_points_w is left untouched
and a warning is emitted when present: world-frame contact points recorded
on flat ground are stale after terrain adaptation.
Source code in eden/utils/common.py
Attributes¶
terrain_offset
class-attribute
instance-attribute
¶
Methods:¶
apply
¶
Source code in eden/datasets/modifiers/terrain_adapt.py
Functions:¶
Body models¶
Parametric body models (MANO, SMPL, SMPL-H, SMPL-X) behind the opt-in body_model_params=True fields, run on a
numpy linear-blend-skinning rig with no smplx dependency.
Parametric body models behind the opt-in body-model fields of a motion sequence.
A dataset loaded with body_model_params=True stores, per sequence that has one, the model's pose and shape:
body_pose_quat (the local rotation of every joint below the root, wxyz, relative to the model's rest pose),
body_shape (betas) and the per-clip body_model name; the root is the sequence's base, base_pos_w
being the root joint's position. This module names the models (:data:BODY_MODELS), converts a release's own
MANO parameterisation into that form, and runs the model back to joints and vertices.
The model files are licence-gated (MANO: mano.is.tue.mpg.de) and never shipped; they are read from a directory the
caller passes (DatasetBase.body_model_dir). The models run on :class:SkinnedBodyModel, a numpy linear-blend-
skinning rig that matches the smplx package to well under a micrometre (tests/datasets/utils) and also
skins rigs outside the SMPL family (OTRetarget's SOMA). A model is read from its .npz when the directory has
one, else its .pkl. The MANO, SMPL and SMPL-H .pkl files pickle a chumpy array or two (shapedirs);
:func:body_model_arrays reads those without chumpy (:class:~eden.utils.chumpy_pickle.ChumpyFreeUnpickler), so
no model file needs an extra.
Attributes¶
BODY_MODELS
module-attribute
¶
BODY_MODELS: dict[str, BodyModelSpec] = {'mano_right': BodyModelSpec('mano', 'right', 15, 'MANO_RIGHT.pkl'), 'mano_left': BodyModelSpec('mano', 'left', 15, 'MANO_LEFT.pkl'), **{f'{family}_{gender}': BodyModelSpec(family, gender, joints, f'{family.upper()}_{gender.upper()}.pkl') for family, joints in (('smpl', 23), ('smplh', 51), ('smplx', 54)) for gender in ('neutral', 'male', 'female')}}
CHORD_TIP_VERTICES
module-attribute
¶
CHORD_TIP_VERTICES: dict[str, int] = {'thumb': 766, 'index': 353, 'middle': 467, 'ring': 576, 'pinky': 695}
Classes¶
BodyModelSpec
dataclass
¶
BodyModelSpec(family: BodyModelFamily, variant: str, num_body_joints: int, file: str)
One parametric body model.
| PARAMETER | DESCRIPTION |
|---|---|
family
|
TYPE:
|
variant
|
The hand side (MANO) or the gender (SMPL family).
TYPE:
|
num_body_joints
|
Joints below the root, i.e.
TYPE:
|
file
|
The model file's name inside the body-model directory.
TYPE:
|
SkinnedBodyModel
¶
SkinnedBodyModel(rest_vertices: ndarray, faces: ndarray, skin_weights: ndarray, parents: ndarray, bind_rot: ndarray, bind_pos: ndarray, joint_names: list[str], posedirs: ndarray | None = None)
A linear-blend-skinning rig with a fixed identity.
| PARAMETER | DESCRIPTION |
|---|---|
rest_vertices
|
TYPE:
|
faces
|
TYPE:
|
skin_weights
|
TYPE:
|
parents
|
TYPE:
|
bind_rot
|
TYPE:
|
bind_pos
|
TYPE:
|
joint_names
|
Joint names. |
posedirs
|
TYPE:
|
Source code in eden/datasets/utils/body_model.py
Attributes¶
posedirs
instance-attribute
¶
Methods:¶
forward
¶
forward(local_rot: ndarray, root_pos: ndarray, chunk: int = 256) -> tuple[ndarray, ndarray, ndarray]
Pose the rig.
| PARAMETER | DESCRIPTION |
|---|---|
local_rot
|
TYPE:
|
root_pos
|
TYPE:
|
chunk
|
Frames skinned per batch (bounds memory).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
vertices
|
TYPE:
|
joint_pos
|
TYPE:
|
joint_rot
|
TYPE:
|
Source code in eden/datasets/utils/body_model.py
skin
¶
skin(joint_rot: ndarray, joint_pos: ndarray, pose_feature: ndarray | None = None, chunk: int = 256) -> ndarray
Skin the mesh to given joint world transforms.
| PARAMETER | DESCRIPTION |
|---|---|
joint_rot
|
TYPE:
|
joint_pos
|
TYPE:
|
pose_feature
|
TYPE:
|
chunk
|
Frames skinned per batch.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
|
Source code in eden/datasets/utils/body_model.py
Functions:¶
mano_model_name
¶
The :data:BODY_MODELS name of the MANO hand on side (right / left).
Source code in eden/datasets/utils/body_model.py
body_model_file
¶
The file of body_model in model_dir (the first of :func:model_file_names present); raises naming
where to get it when either is missing.
Source code in eden/datasets/utils/body_model.py
body_model_arrays
¶
Every array of a body-model file (.npz or .pkl), as plain numpy in the file's own dtypes.
A .pkl that pickles chumpy objects (MANO, SMPL, SMPL-H) is read without chumpy
(:class:~eden.utils.chumpy_pickle.ChumpyFreeUnpickler); its sparse J_regressor is densified. The last two
files read stay cached (a MANO pair; an SMPL-X file holds ~170 MB), keyed by modification time and size so a
replaced file is read again. The returned dict is shared: copy before writing into it.
Source code in eden/datasets/utils/body_model.py
shape_components
¶
shape_components(arrays: dict[str, ndarray], family: BodyModelFamily) -> int
How many of shapedirs' blend shapes are body shape (betas) rather than facial expression.
SMPL-X stacks the shape blend shapes, then the expression ones: 300 + 100 in v1.1, 10 + 10 in v1.0 (the
smplx package's split). The other families' shapedirs are all shape.
Source code in eden/datasets/utils/body_model.py
skinned_body_model
¶
skinned_body_model(path: str | Path, family: BodyModelFamily, betas: ndarray, joint_names: list[str] | None = None, v_template: ndarray | None = None, posedirs: ndarray | None = None) -> SkinnedBodyModel
The rig of one body-model file shaped by betas: SMPL-style bind pose (identity joint frames).
| PARAMETER | DESCRIPTION |
|---|---|
path
|
The model file ( |
family
|
Its family; decides how many of
TYPE:
|
betas
|
Shape coefficients, up to the model's shape components; coefficients past them must be zero.
TYPE:
|
joint_names
|
Names for the joints (default |
v_template
|
A personal template mesh replacing the model's mean shape (GRAB ships each subject as one);
TYPE:
|
posedirs
|
The file's
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SkinnedBodyModel
|
|
Source code in eden/datasets/utils/body_model.py
mano_pose_from_release
¶
mano_pose_from_release(pose: ndarray, model_dir: str | Path | None, side: str, *, num_pca_comps: int | None, flat_hand_mean: bool) -> ndarray
A release's MANO finger pose -> the 45 axis-angles relative to the flat hand that body_pose_quat holds.
| PARAMETER | DESCRIPTION |
|---|---|
pose
|
(T, num_pca_comps) PCA coefficients, or (T, 45) axis-angles when
TYPE:
|
model_dir
|
Directory holding |
side
|
TYPE:
|
num_pca_comps
|
The release's PCA size, or None for axis-angles. All 45 components are still PCA:
TYPE:
|
flat_hand_mean
|
Whether the release's pose is relative to the flat hand (MANO's
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
(T, 45) axis-angles, relative to the flat hand. |
Source code in eden/datasets/utils/body_model.py
axis_angles_to_body_pose_quat
¶
(T, 3 * J) axis-angles -> (T, J, 4) wxyz, float32.
Source code in eden/datasets/utils/body_model.py
body_model_forward
¶
body_model_forward(body_model: str, model_dir: str | Path | None, root_pos: Tensor, root_quat: Tensor, body_pose_quat: Tensor, body_shape: Tensor) -> tuple[Tensor, Tensor]
Joints and vertices of a body-model sequence, its root joint placed on root_pos.
| PARAMETER | DESCRIPTION |
|---|---|
body_model
|
A :data:
TYPE:
|
model_dir
|
Directory holding the model file. |
root_pos
|
(T, 3) root joint positions and (T, 4) wxyz global orientations: the sequence's
TYPE:
|
root_quat
|
(T, 3) root joint positions and (T, 4) wxyz global orientations: the sequence's
TYPE:
|
body_pose_quat
|
(T, J, 4) and (T, B): the sequence's body-model fields. The pose is relative to the rest pose (MANO: the flat hand), and the jaw, eyes and expression of SMPL-X are held at rest.
TYPE:
|
body_shape
|
(T, J, 4) and (T, B): the sequence's body-model fields. The pose is relative to the rest pose (MANO: the flat hand), and the jaw, eyes and expression of SMPL-X are held at rest.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[Tensor, Tensor]
|
(T, J + 1, 3) joints, root first, and (T, V, 3) vertices, float32 on |
Source code in eden/datasets/utils/body_model.py
mano_root_offset
¶
(…, 3) position of MANO's root joint at zero translation: the offset from a release's transl to the wrist.
The root joint is regressed from the shaped template alone, so the offset depends on betas and not on the
pose: wrist = transl + mano_root_offset(betas).
Source code in eden/datasets/utils/body_model.py
mano_vertex_links
¶
(778,) the MANO joint (0-15) each vertex follows most: the argmax of its skinning weights.
Source code in eden/datasets/utils/body_model.py
mano_keypoints
¶
(T, 21, 3) keypoints in :data:~eden.datasets.constants.MANO_KEYPOINTS_NAME order from MANO's (T, 16, 3)
joints and (T, 778, 3) vertices: the 16 joints in MANO's order, then the :data:MANO_TIP_VERTICES tips.
Source code in eden/datasets/utils/body_model.py
BVH parsing¶
BVH (Biovision Hierarchy) file parser with forward kinematics.
Classes¶
BvhJoint
dataclass
¶
BvhJoint(name: str, offset: ndarray, channels: list[str] = list(), children: list[BvhJoint] = list(), parent: BvhJoint | None = None)
BvhData
dataclass
¶
BvhData(root: BvhJoint, joints: list[BvhJoint], joint_names: list[str], framerate: float, num_frames: int, frame_data: ndarray)
Functions:¶
parse_bvh
¶
Parse a BVH file into structured data.
| PARAMETER | DESCRIPTION |
|---|---|
filepath
|
Path to the BVH file.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
BvhData
|
Parsed skeleton hierarchy and motion data. |
Source code in eden/datasets/utils/bvh.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 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 | |
forward_kinematics
¶
Compute global joint positions and orientations via forward kinematics.
| PARAMETER | DESCRIPTION |
|---|---|
bvh
|
Parsed BVH data.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
positions
|
Global positions of all joints.
TYPE:
|
quaternions
|
Global orientations in wxyz format.
TYPE:
|
Source code in eden/datasets/utils/bvh.py
forward_kinematics_matrices
¶
Global joint positions and rotation matrices: :func:forward_kinematics without the quaternion conversion.
A joint's rotation channels compose in the order they are listed (Zrotation Yrotation Xrotation is
Rz @ Ry @ Rx), and its position channels, on any joint, replace the matching axes of its offset: a
SOMA-rig BVH gives every joint all six channels.
| PARAMETER | DESCRIPTION |
|---|---|
bvh
|
Parsed BVH data.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
positions
|
Global positions of all joints.
TYPE:
|
rot_matrices
|
Global orientations.
TYPE:
|
Source code in eden/datasets/utils/bvh.py
Keypoint names¶
Shared constants for motion datasets.
Attributes¶
MANO_KEYPOINTS_NAME
module-attribute
¶
MANO_KEYPOINTS_NAME: tuple[str, ...] = ('wrist', 'index1', 'index2', 'index3', 'middle1', 'middle2', 'middle3', 'pinky1', 'pinky2', 'pinky3', 'ring1', 'ring2', 'ring3', 'thumb1', 'thumb2', 'thumb3', 'thumb_tip', 'index_tip', 'middle_tip', 'ring_tip', 'pinky_tip')
SMPLH_KEYPOINTS_NAME
module-attribute
¶
SMPLH_KEYPOINTS_NAME = ['Pelvis', 'L_Hip', 'L_Knee', 'L_Ankle', 'L_Toe', 'R_Hip', 'R_Knee', 'R_Ankle', 'R_Toe', 'Torso', 'Spine', 'Chest', 'Neck', 'Head', 'L_Thorax', 'L_Shoulder', 'L_Elbow', 'L_Wrist', 'L_Index1', 'L_Index2', 'L_Index3', 'L_Middle1', 'L_Middle2', 'L_Middle3', 'L_Pinky1', 'L_Pinky2', 'L_Pinky3', 'L_Ring1', 'L_Ring2', 'L_Ring3', 'L_Thumb1', 'L_Thumb2', 'L_Thumb3', 'R_Thorax', 'R_Shoulder', 'R_Elbow', 'R_Wrist', 'R_Index1', 'R_Index2', 'R_Index3', 'R_Middle1', 'R_Middle2', 'R_Middle3', 'R_Pinky1', 'R_Pinky2', 'R_Pinky3', 'R_Ring1', 'R_Ring2', 'R_Ring3', 'R_Thumb1', 'R_Thumb2', 'R_Thumb3']
SMPLX_KEYPOINTS_NAME
module-attribute
¶
SMPLX_KEYPOINTS_NAME = ['Pelvis', 'L_Hip', 'R_Hip', 'Spine1', 'L_Knee', 'R_Knee', 'Spine2', 'L_Ankle', 'R_Ankle', 'Spine3', 'L_Foot', 'R_Foot', 'Neck', 'L_Collar', 'R_Collar', 'Head', 'L_Shoulder', 'R_Shoulder', 'L_Elbow', 'R_Elbow', 'L_Wrist', 'R_Wrist']
MOCAP_KEYPOINTS_NAME
module-attribute
¶
MOCAP_KEYPOINTS_NAME = ['Hips', 'Spine', 'Spine1', 'Neck', 'Head', 'LeftShoulder', 'LeftArm', 'LeftForeArm', 'LeftHand', 'LeftHandThumb1', 'LeftHandThumb2', 'LeftHandThumb3', 'LeftHandIndex1', 'LeftHandIndex2', 'LeftHandIndex3', 'LeftHandMiddle1', 'LeftHandMiddle2', 'LeftHandMiddle3', 'LeftHandRing1', 'LeftHandRing2', 'LeftHandRing3', 'LeftHandPinky1', 'LeftHandPinky2', 'LeftHandPinky3', 'RightShoulder', 'RightArm', 'RightForeArm', 'RightHand', 'RightHandThumb1', 'RightHandThumb2', 'RightHandThumb3', 'RightHandIndex1', 'RightHandIndex2', 'RightHandIndex3', 'RightHandMiddle1', 'RightHandMiddle2', 'RightHandMiddle3', 'RightHandRing1', 'RightHandRing2', 'RightHandRing3', 'RightHandPinky1', 'RightHandPinky2', 'RightHandPinky3', 'LeftUpLeg', 'LeftLeg', 'LeftFoot', 'LeftToeBase', 'RightUpLeg', 'RightLeg', 'RightFoot', 'RightToeBase', 'LeftFootMod', 'RightFootMod']
LAFAN1_KEYPOINTS_NAME
module-attribute
¶
LAFAN1_KEYPOINTS_NAME = ['Hips', 'RightUpLeg', 'RightLeg', 'RightFoot', 'RightToeBase', 'LeftUpLeg', 'LeftLeg', 'LeftFoot', 'LeftToeBase', 'Spine', 'Spine1', 'Spine2', 'Neck', 'Head', 'RightShoulder', 'RightArm', 'RightForeArm', 'RightHand', 'LeftShoulder', 'LeftArm', 'LeftForeArm', 'LeftHand']