[Feature]: Preserve MJCF sites through import
What feature or enhancement are you proposing?
Preserve definitions on the link they are attached to, exposed as a read-only RigidLink.sites, defaulting to empty for links parsed from anything other than MJCF.
This does not propose modelling sites as a simulation entity. They would remain entirely passive data — no solver state, no DOFs, no contribution to dynamics, no per-step cost. The request is only that the parsed definitions survive the import rather than being discarded.
The required MuJoCo arrays are already read. parse_equalities in utils/mjcf.py uses mj.site_pos, mj.site_quat, and mj.site_bodyid to resolve site-based weld and connect constraints, converting each site into a relative link position. The proposal is to retain those same values for every site, grouped by site_bodyid, instead of only for the subset referenced by an equality constraint.
Motivation
Sites are a standard MJCF primitive — massless reference frames rigidly attached to a body — and MuJoCo itself is heavily site-addressed. Sensors attach to sites, tendons route through them, site transmission targets them, and equality constraints reference them. Any model authored against those features carries sites as load-bearing structure, not decoration, and models of moderate complexity commonly carry dozens.
Genesis currently resolves sites only where an equality constraint points at one, and drops the rest during import. The information is therefore present in the parse but absent from the resulting model: there is no property of an imported entity from which an authored reference frame can be recovered, even though the frame is fully specified in the source file and Genesis has already read the arrays that define it.
The consequence is that consumers cannot resolve authored attachment points at all — placing a frame where the model says a sensor is mounted, comparing simulated positions against externally measured reference points, or driving inverse kinematics toward an authored target. Each requires only the site's offset in its link frame composed with the link pose, which is a value the importer computes for equality constraints and discards for everything else.
Recovering the offsets outside Genesis means compiling the model a second time with MuJoCo, which risks diverging from the model Genesis actually simulates, since Genesis rewrites assetdir/meshdir, injects default armature/solref, and folds into the contype/conaffinity masks before compiling. Parsing the XML directly is worse, as it would miss class inheritance and resolution.
Potential Benefit
Round-trip fidelity: authored MJCF metadata survives the import rather than being silently lost. Lets downstream code resolve authored attachment points without a second, potentially divergent compile. Reuses parsing already present in parse_equalities; no new dependencies and no new parsing machinery. No simulation behaviour change, no solver state, and no per-step cost — the data is written once at import. No impact on URDF, MSH, or primitive entities, which have no such concept.
What is the expected outcome of the implementation work?
RigidLink.sites returns the sites attached to that link, empty when there are none. Each entry carries at minimum name, and pos / quat expressed in the link frame, with pos respecting the import scale. Links parsed from URDF or primitive entities return empty. Sites on nested bodies are attached to the correct link. No change to any simulation result, including existing site-based equality constraints. Test asserting sites survive import for a fixture with sites on multiple bodies, including nested ones.
Additional information
No response
Source: Genesis-Embodied-AI/genesis-world