Documentation pass for model editing, model encoding, and mjz.
PiperOrigin-RevId: 951665744 Change-Id: I1dfe3b40f451cca686431c263815039a9c38efc8
This commit is contained in:
committed by
Copybara-Service
parent
259e6c4dc6
commit
1f1bfa9e4e
@@ -470,6 +470,62 @@ or content type:
|
||||
</asset>
|
||||
|
||||
|
||||
.. _exEncoder:
|
||||
|
||||
Encoders
|
||||
~~~~~~~~
|
||||
|
||||
Encoder plugins extend asset serialization and model saving capabilities beyond native formats (XML, MJB, TXT).
|
||||
Encoders are :ref:`registered <mjPLUGIN_LIB_INIT>` similarly to other MuJoCo plugins.
|
||||
|
||||
MuJoCo ships with a built-in Zip encoder for ``.mjz`` archives (``src/xml/mjz/mjz_encoder.cc``).
|
||||
|
||||
.. _exEncoderInterface:
|
||||
|
||||
Encoder interface
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
An encoder is described by the :ref:`mjpEncoder` struct, which has the following fields:
|
||||
|
||||
``content_type``
|
||||
A MIME-like content type string identifying the output format (e.g. ``"application/zip"``). When :ref:`mj_encode` is
|
||||
called with an explicit ``content_type`` argument, this string is used to find the appropriate encoder.
|
||||
|
||||
``extension``
|
||||
A file extension string (including the dot) used for format matching when no content type is specified. Multiple
|
||||
extensions can be separated by pipes (`|`) such as ``.mjz|.zip``.
|
||||
|
||||
``encode``
|
||||
A callback of type :ref:`mjfEncode` that performs the actual serialization. It receives an :ref:`mjSpec`, an
|
||||
optional compiled :ref:`mjModel`, an optional :ref:`mjVFS`, and an output :ref:`mjResource`. Returns the number of
|
||||
bytes written on success, or -1 on failure.
|
||||
|
||||
``close_resource``
|
||||
An optional callback that frees any memory allocated inside ``mjResource.data`` by the ``encode`` callback.
|
||||
|
||||
.. _exEncoderRegistration:
|
||||
|
||||
Registration
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Encoders must be registered before they can be used via :ref:`mj_encode`. Registration is performed via
|
||||
:ref:`mjp_registerEncoder`. The :ref:`mjp_defaultEncoder` function initializes an :ref:`mjpEncoder` struct with default
|
||||
values. The :ref:`mjPLUGIN_LIB_INIT` macro defines the initialization function that registers the encoder when the
|
||||
plugin library is loaded.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
mjPLUGIN_LIB_INIT(my_format_encoder) {
|
||||
mjpEncoder encoder;
|
||||
mjp_defaultEncoder(&encoder);
|
||||
encoder.content_type = "application/x-myformat";
|
||||
encoder.extension = ".myf";
|
||||
encoder.encode = MyEncode;
|
||||
encoder.close_resource = MyCloseResource;
|
||||
mjp_registerEncoder(&encoder);
|
||||
}
|
||||
|
||||
|
||||
.. _exProvider:
|
||||
|
||||
Resource providers
|
||||
|
||||
+108
-16
@@ -26,6 +26,114 @@ The workflow using :ref:`mjSpec` is:
|
||||
After compilation, the :ref:`mjSpec` remains editable, so steps 2 and 3 are interchangeable.
|
||||
|
||||
|
||||
.. _Load:
|
||||
.. _meLoading:
|
||||
|
||||
Model Parsing & Loading
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As summarized in :ref:`Model instances <Instance>`, model description files (MJCF, MJZ, URDF, USD) are parsed into an
|
||||
:ref:`mjSpec` using :ref:`mj_parse` (or ``mjSpec.from_file()`` / ``mjSpec.from_string()`` in Python). The model format is
|
||||
inferred from the content type or file extension, and parsing into an :ref:`mjSpec` is delegated to the appropriate
|
||||
:ref:`decoder <exDecoder>` plugin.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
char error[1000] = "";
|
||||
mjSpec* spec = mj_parse(vfs, "robot.xml", NULL, NULL, error, sizeof(error));
|
||||
|
||||
For convenience, :ref:`mj_loadXML` (or Python ``MjModel.from_xml_path()``) combines parsing and compilation into a
|
||||
single step, returning a compiled :ref:`mjModel` directly from an XML file or ``.mjz`` archive.
|
||||
|
||||
Alternatively, a pre-compiled :ref:`mjModel` can be loaded directly from a binary MJB file using :ref:`mj_loadModel`
|
||||
(or Python ``MjModel.from_binary_path()``).
|
||||
|
||||
.. _Compile:
|
||||
.. _meCompilation:
|
||||
|
||||
Model Compilation
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once a high-level :ref:`mjSpec` is created---by parsing a file, loading an archive, or constructing it
|
||||
programmatically---it is compiled into an :ref:`mjModel` using :ref:`mj_compile`.
|
||||
|
||||
Compilation is independent of loading, working in the exact same way regardless of how :ref:`mjSpec` was constructed.
|
||||
Both the parser and the compiler perform extensive error checking and abort when the first error is encountered. The
|
||||
parser uses a custom schema to validate file structure, elements, and attributes, while the compiler applies semantic
|
||||
checks and executes a test simulation step to catch runtime errors.
|
||||
|
||||
Parsing and compilation are extremely fast—typically less than a second—making interactive model design, live editing,
|
||||
and rapid reloading seamless.
|
||||
|
||||
.. _Save:
|
||||
.. _meSaving:
|
||||
|
||||
Model Encoding & Saving
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Model specs and compiled models can be serialized to files using :ref:`mj_encode`, or directly saved to XML strings
|
||||
using :ref:`mj_saveXMLString` or :ref:`mj_saveXML`.
|
||||
|
||||
The :ref:`mj_encode` function provides a unified entry point for serializing models:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
char error[1024] = "";
|
||||
mjtSize bytes_written = mj_encode(spec, model, "robot.mjz", NULL, vfs, error, sizeof(error));
|
||||
|
||||
The output format is selected automatically based on the file extension (case-insensitive) or explicit ``content_type``:
|
||||
|
||||
- **MJCF XML** (``.xml``): Flattens the spec into a single MJCF XML file using :ref:`mj_saveXML`. If an explicit
|
||||
:ref:`mjModel` argument is passed, :ref:`mj_encode` will copy modified values back from ``mjModel`` into the spec
|
||||
prior to saving. In the Computation chapter we show an `example <_static/example.xml>`__ MJCF file and the
|
||||
corresponding `saved example <_static/example_saved.xml>`__.
|
||||
- **MJZ Archive** (``.mjz`` or ``.zip``): Bundles the spec and all associated external assets (meshes, textures,
|
||||
included XMLs) into a self-contained Zip archive via the built-in ``mjz_encoder``.
|
||||
- **MJB Binary** (``.mjb``): Serializes the compiled :ref:`mjModel` in MuJoCo binary format via :ref:`mj_saveModel`.
|
||||
MJB files are standalone, do not refer to external files, and load faster than XML, but are version-specific and
|
||||
cannot be decompiled back to XML. Requires a compiled ``model``; does **not** serialize anything from ``spec``.
|
||||
- **TXT** (``.txt``): Writes a human-readable text dump via :ref:`mj_printModel`. Useful for diffing and debugging.
|
||||
Requires a compiled ``model``; does **not** serialize anything from ``spec``.
|
||||
|
||||
Importantly, saved XML will take into account any defined defaults. This is useful when a model has many repeated
|
||||
values, for example if loaded from URDF, which does not support defaults. In such a case one can add default classes,
|
||||
set the class of the relevant elements, and save; the resulting XML will use the defaults and be more human-readable.
|
||||
|
||||
.. _MJZArchives:
|
||||
|
||||
MJZ Archives
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Complex MuJoCo models often consist of multiple files: a main MJCF XML file, included XML sub-trees, and external asset
|
||||
files (meshes, textures, height fields). The **MJZ** format (extension ``.mjz`` or ``.zip``) provides a convenient way
|
||||
to bundle an entire model and all of its referenced assets into a single **Zip archive**.
|
||||
|
||||
Root XML Discovery
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When decoding an ``.mjz`` archive, MuJoCo searches for the root model XML file in the following order:
|
||||
|
||||
1. `<archive_stem>.xml` at the root of the archive (e.g. ``my_model.xml`` inside ``my_model.mjz``). This is
|
||||
considered **best practice**.
|
||||
2. `<archive_stem>/<archive_stem>.xml` inside a top-level directory matching the archive name (e.g.
|
||||
``my_model/my_model.xml``).
|
||||
3. `model.xml` at the root of the archive (common zipped MJCF fallback).
|
||||
|
||||
VFS Requirement
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Parsing and compilation of an ``.mjz`` archive (and all of its contained asset files) require using the **exact same
|
||||
VFS instance**.
|
||||
|
||||
.. _meCustomFormats:
|
||||
|
||||
Custom formats
|
||||
~~~~~~~~~~~~~~
|
||||
Adding support for new file formats can be done with :ref:`mjp_registerDecoder` and :ref:`mjp_registerEncoder`.
|
||||
When :ref:`mj_parse` and :ref:`mj_encode` are called for a non-native extension or content type, the appropriate plugins
|
||||
are found via :ref:`mjp_findDecoder` and :ref:`mjp_findEncoder`. For further details on writing custom format plugins,
|
||||
see :ref:`Decoders <exDecoder>` and :ref:`Encoders <exEncoder>`.
|
||||
|
||||
|
||||
.. _meUsage:
|
||||
|
||||
Usage
|
||||
@@ -59,13 +167,6 @@ In C++, one can use vectors and strings directly:
|
||||
std::string modelname = "my_model";
|
||||
*spec->modelname = modelname;
|
||||
|
||||
Loading a spec from XML can be done as follows:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
std::array<char, 1000> error;
|
||||
mjSpec* s = mj_parseXML(filename, vfs, error.data(), error.size());
|
||||
|
||||
.. _meMjsElements:
|
||||
|
||||
Model elements
|
||||
@@ -258,15 +359,6 @@ already initialized elements.
|
||||
loading pipeline. A future API change could allow defaults to be changed and applied after initialization. If you
|
||||
think this feature is important to you, please let us know on GitHub.
|
||||
|
||||
.. _meSaving:
|
||||
|
||||
XML saving
|
||||
^^^^^^^^^^
|
||||
Specs can be saved to an XML file or string using :ref:`mj_saveXML` or :ref:`mj_saveXMLString`, respectively.
|
||||
Saving requires that the spec first be compiled.
|
||||
Importantly, the saved XML will take into account any defined defaults. This is useful when a model has many repeated
|
||||
values, for example if loaded from URDF, which does not support defaults. In such a case one can add default classes,
|
||||
set the class of the relevant elements, and save; the resulting XML will use the defaults and be more human-readable.
|
||||
|
||||
.. _meRecompilation:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user