Genesis-Embodied-AI/genesis-world · error · ValueError

Compounding joints of types 'FREE' or 'FIXED' with any other

Error message

Compounding joints of types 'FREE' or 'FIXED' with any other joint on the same body not supported

What it means

RigidEntity._add_by_info rejects a link info carrying more than one joint when any of them is a FREE or FIXED joint. FREE and FIXED joints fully determine a link's 6-DoF attachment to its parent, so compounding them with hinge/slide joints on the same body is physically ill-defined and Genesis refuses it at build time.

Source

Thrown at genesis/engine/entities/rigid_entity/rigid_entity.py:1188

                dofs_motion_ang=dofs_motion_ang,
                dofs_motion_vel=dofs_motion_vel,
                dofs_limit=j_info.get("dofs_limit", np.tile([[-np.inf, np.inf]], [n_dofs, 1])),
                dofs_invweight=j_info.get("dofs_invweight", np.zeros(n_dofs)),
                dofs_frictionloss=j_info.get("dofs_frictionloss", np.zeros(n_dofs)),
                dofs_stiffness=j_info.get("dofs_stiffness", np.zeros(n_dofs)),
                dofs_damping=j_info.get("dofs_damping", np.zeros(n_dofs)),
                dofs_armature=j_info.get("dofs_armature", np.zeros(n_dofs)),
                dofs_act_gain=j_info.get("dofs_act_gain", np.zeros(n_dofs)),
                dofs_act_bias=j_info.get("dofs_act_bias", np.zeros((n_dofs, 3))),
                dofs_force_range=j_info.get("dofs_force_range", np.tile([[-np.inf, np.inf]], [n_dofs, 1])),
            )
            joints.append(joint)

        return joints

    def _add_by_info(self, l_info, j_infos, g_infos, morph, surface):
        if len(j_infos) > 1 and any(j_info["type"] in (gs.JOINT_TYPE.FREE, gs.JOINT_TYPE.FIXED) for j_info in j_infos):
            raise ValueError(
                "Compounding joints of types 'FREE' or 'FIXED' with any other joint on the same body not supported"
            )

        parent_idx = l_info["parent_idx"]
        if parent_idx >= 0:
            parent_idx += self._link_start
        root_idx = l_info.get("root_idx")
        if root_idx is not None and root_idx >= 0:
            root_idx += self._link_start
        link_idx = self.n_links + self._link_start
        joint_start = self.n_joints + self._joint_start

        cg_infos, vg_infos = self._postprocess_geoms_info(morph, g_infos, l_info.get("is_robot", False))
        self._align_link(l_info, j_infos, cg_infos, vg_infos, morph, link_idx)

        joints = self._create_joints(j_infos, link_idx, joint_start)

        # Add child link

View on GitHub (pinned to 56e4aa5d82)

Solutions

  1. Edit the model so FREE/FIXED joints appear alone on their body: move the additional hinge/slide joints onto a child body/link.
  2. If the fixed joint was meant to weld a decoration, put that geometry on the same link instead of adding a second fixed joint.
  3. For a floating-base robot, keep exactly one free joint on the root body and no other joint on it.

Example fix

<!-- before: URDF link with fixed + revolute joints -->
<link name="base"/>
<joint name="fix" type="fixed" .../>
<joint name="roll" type="revolute" .../>

<!-- after: weld geometry onto one link, revolute on its own link -->
<link name="base"/>  <!-- fixed joint only, geometry merged here -->
<joint name="roll" type="revolute" parent="base" child="roll_link"/>
Defensive patterns

Strategy: validation

Validate before calling

import xml.etree.ElementTree as ET
# reject bodies with multiple joints incl. free/fixed
for body in root.iter("body"):
    joints = body.findall("joint") + body.findall("freejoint")
    if len(joints) > 1 and any(j.get("type", "free" if j.tag == "freejoint" else None) in ("free", "fixed") for j in joints):
        raise ValueError(f"Body {body.get('name')} compounds FREE/FIXED with other joints")

Prevention

When it happens

Trigger: Loading a URDF/MJCF/morph whose body has multiple <joint> elements where at least one is 'free'/'floating' or 'fixed' (e.g. a URDF link with both a fixed joint and a revolute joint, or an MJCF body with a freejoint plus another joint). Also triggered by _load_primitive/_load_mesh/_load_terrain/_load_scene paths generating compound j_infos.

Common situations: Hand-authored or auto-generated URDF/MJCF files that attach several joints to one link; converting MuJoCo models where a freejoint coexists with hinge joints on the same body; merging links during model simplification.

Related errors


AI-assisted analysis of Genesis-Embodied-AI/genesis-world@56e4aa5d82 (2026-08-28). Data as JSON: /api/errors/5b74e4ebe964d98e. Report an issue: GitHub.