Skip to content

[FEATURE] Save and load free flight simulations that use MuJoCo assets #267

Description

@camUrban

Problem Statement

A FreeFlightUnsteadyProblem built with mujoco_assets cannot be saved: save() raises, because the MuJoCo engine is rebuilt on load from the stored XML string alone, whose asset references would be unresolvable. This blocks saving any free flight simulation whose body geometry comes from a mesh file, such as an STL supplied through mujoco_assets.

Separately, the guard behind that refusal has a gap. A model whose extra_xml fragments reference a mesh by absolute on-disk path compiles without mujoco_assets, because MuJoCo falls back to the filesystem, and such a simulation saves without complaint today. The resulting file is a trap: it loads only while the referenced file still exists at that machine-specific path, and the failure surfaces as a MuJoCo file-open error long after the expensive run is gone. This is exactly the failure mode the guard exists to prevent, so these saves should be caught the same way.

Location(s): pterasoftware/_serialization.py, pterasoftware/_mujoco_model.py, pterasoftware/problems.py

Proposed Solution

  1. Serialize the assets faithfully. Add a bytes case to _serialize_value and _deserialize_value that encodes contents as base64, the same pattern _ndarray_to_dict already uses for array buffers. Serialize the _mujoco_assets dict instead of skipping it, and remove the save-time refusal. On load, _rebuild_engine passes the restored dict to mujoco.MjModel.from_xml_string as the assets parameter, mirroring the existing branch in MuJoCoModel.__init__. Saved files stay fully self-contained, and load never touches the filesystem.
  2. Complete the save guard. At save time, raise if the model XML contains file references that are not covered by the assets dict, so a save can never produce a file that only loads while some on-disk file survives at a hard-coded path.
  3. Strengthen the existing mujoco_assets validation in FreeFlightUnsteadyProblem to require each virtual filename to be a bare basename with a nonempty extension, rejecting path separators and absolute-path shapes. MuJoCo selects its asset decoder from the extension, so the extension is load-bearing, and the basename requirement keeps machine-specific paths out of saved files.
  4. Bump _FORMAT_VERSION and update the docstrings in problems.py, _mujoco_model.py, and _serialization.py that document the current refusal.

Additional Context

Verified empirically against the pinned MuJoCo version: absolute paths in the XML compile from disk with no assets dict, relative paths fail for string-built models, and extension-less virtual filenames fail even with an explicit content_type attribute. The commit that added the refusal (368e2a8) anticipated this work, noting that "A faithful asset round trip can be added later if a real need appears."

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingfeatureNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions