Skip to content

fix(conversions): cast geom_type to int in merge_geoms enum check - #32

Open
Guozhongyuan wants to merge 1 commit into
mujocolab:mainfrom
Guozhongyuan:fix/geom-type-enum-membership
Open

Guozhongyuan wants to merge 1 commit into
mujocolab:mainfrom
Guozhongyuan:fix/geom-type-enum-membership

Conversation

@Guozhongyuan

Copy link
Copy Markdown

Problem

merge_geoms() classifies geoms with:

if mj_model.geom_type[geom_id] in (mjtGeom.mjGEOM_MESH, mjtGeom.mjGEOM_SDF):

MjModel.geom_type[i] is a NumPy scalar (np.int32). Tuple membership evaluates
the element on the left (enum_member == np_scalar), and MuJoCo's pybind11 enum
returns False when compared against a NumPy scalar from that side — even though
the identical comparison with the NumPy scalar on the left is True:

>>> import mujoco, numpy as np
>>> E = mujoco.mjtGeom
>>> np.int32(7) == E.mjGEOM_MESH              # numpy scalar on the left
True
>>> E.mjGEOM_MESH == np.int32(7)              # enum on the left — what `in` does
False
>>> np.int32(7) in (E.mjGEOM_MESH, E.mjGEOM_SDF)
False

So the membership test silently fails for every geom type. Mesh and SDF geoms
fall into the create_primitive_mesh() branch and raise:

ValueError: Unsupported shape type: 7

Primitive geoms keep working only because the primitive fallback happens to
reconstruct the same shape. Any model with a mesh geom among its fixed-body
geometries — i.e. almost every real model — crashes when its static geoms are
merged. This also means the SDF routing added in #31 never actually triggers.

merge_geoms_hull() is unaffected because it already compares via int(...),
which is also why this slipped through CI: the existing test_merge_geoms only
merges primitive geoms.

Fix

Cast both sides to int() before the membership test, matching the existing
idiom in merge_geoms_hull(). One-line change plus a regression test.

Testing

  • Added test_merge_geoms_with_mesh_geom, which merges a mjGEOM_MESH geom:
    raises ValueError: Unsupported shape type: 7 before the fix, passes after
    (verified red/green).
  • Full suite: 75 passed.

Reproduced on mujoco 3.14.0, numpy 2.5.3, Python 3.12. The regression was
introduced by #31 (post-v0.0.14, main only), which is why released wheels are
unaffected.

MjModel.geom_type[i] is a numpy scalar; tuple membership evaluates
enum == np_scalar (element on the left), and MuJoCo's pybind11 enum
returns False against numpy scalars. Mesh/SDF geoms therefore silently
took the primitive path and raised 'Unsupported shape type: 7'.
Match the int() idiom already used in merge_geoms_hull().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants