diff --git a/doc/changelog.rst b/doc/changelog.rst index d2b5ce53..ecc4a0da 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -8,8 +8,7 @@ Upcoming version (not yet released) .. admonition:: Breaking API changes :class: attention - - The functions ``mjs_detachBody`` and ``mjs_detachDefault`` have been replaced by :ref:`mjs_delete`. Additionally, - `:ref:mjs_detach` was added in order to remove an element from the spec without deleting it. + - The functions ``mjs_detachBody`` and ``mjs_detachDefault`` have been replaced by :ref:`mjs_delete`. - The Python functions ``element.delete`` have been replaced by ``spec.delete(element)``. General diff --git a/doc/programming/modeledit.rst b/doc/programming/modeledit.rst index ac74efdf..95e9c221 100644 --- a/doc/programming/modeledit.rst +++ b/doc/programming/modeledit.rst @@ -96,25 +96,37 @@ Elements cannot be created directly; they are returned to the user by the corres my_geom->type = mjGEOM_BOX; // set geom type my_geom->size[0] = my_geom->size[1] = my_geom->size[2] = 0.5; // set box size mjModel* model = mj_compile(spec, NULL); // compile to mjModel + ... + mj_deleteModel(model); // free model + mj_deleteSpec(spec); // free spec The ``NULL`` second argument to :ref:`mjs_addGeom` is the optional default class pointer. When using defaults procedurally, default classes are passed in explicitly to element constructors. The global defaults of all elements (used when no default class is passed in) can be inspected in `user_init.c `__. +.. _meMemory: + +Memory management +^^^^^^^^^^^^^^^^^ + +As seen in the examples above, model elements are never allocated by the user directly, but rather returned by a +constructor. The library takes ownership of all elements and frees them when the parent :ref:`mjSpec` is deleted using +:ref:`mj_deleteSpec`. The user is only responsible for freeing :ref:`mjSpec` structs. + .. _meAttachment: Attachment ^^^^^^^^^^ -This framework introduces a powerful new feature: attaching and detaching model subtrees. This feature is already used -to power the :ref:`attach` an :ref:`replicate` meta-elements in MJCF. Attachment allows the user -to move or copy a subtree from one model into another, while also copying or moving related referenced assets and -referencing elements from outside the kinematic tree (e.g., actuators and sensors). Similarly, detaching a subtree will -remove all associated elements from the model. The default behavior is to move the child into the parent while -attaching, so subsequent changes to the child will also change the parent. Alternatively, the user can choose to make an -entirely new copy during attach using :ref:`mjs_setDeepCopy`. This flag is temporarily set to true while parsing XMLs. -It is possible to :ref:`attach a body to a frame`: +This framework introduces a powerful new feature: attaching and deleting model subtrees. This feature is already used to +power the :ref:`attach` an :ref:`replicate` meta-elements in MJCF. Attachment allows the user to +move or copy a subtree from one model into another, while also copying or moving related referenced assets and +referencing elements from outside the kinematic tree (e.g., actuators and sensors). Similarly, deleting a subtree will +remove all associated elements from the model. The default behavior ("shallow copy") is to move the child into the +parent while attaching, so subsequent changes to the child will also change the parent. Alternatively, the user can +choose to make an entirely new copy during attach using :ref:`mjs_setDeepCopy`. This flag is temporarily set to true +while parsing XMLs. It is possible to :ref:`attach a body to a frame`: .. code-block:: C diff --git a/doc/python.rst b/doc/python.rst index 7e669959..c6490edc 100644 --- a/doc/python.rst +++ b/doc/python.rst @@ -605,7 +605,7 @@ Element removal ^^^^^^^^^^^^^^^ The method ``delete()`` removes the corresponding element from the spec, e.g. ``spec.delete(spec.geom('my_geom'))`` will remove the geom named "my_geom" and all of the elements that reference it. For elements that can have children (bodies -and defaults), ``delete`` removes also all of their children. When detaching body subtrees, all elements which reference +and defaults), ``delete`` also removes all of their children. When deleting body subtrees, all elements which reference elements in the subtree, will also be removed. Tree traversal diff --git a/include/mujoco/mujoco.h b/include/mujoco/mujoco.h index 95dbda7d..1ad172a7 100644 --- a/include/mujoco/mujoco.h +++ b/include/mujoco/mujoco.h @@ -1438,7 +1438,7 @@ MJAPI mjsLight* mjs_addLight(mjsBody* body, const mjsDefault* def); // Add frame to body. MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe); -// Detach but not delete object corresponding to the given element, return 0 on success. +// Remove object corresponding to the given element, return 0 on success. MJAPI int mjs_delete(mjSpec* spec, mjsElement* element); diff --git a/python/mujoco/introspect/functions.py b/python/mujoco/introspect/functions.py index e2c6d9bc..fe0742df 100644 --- a/python/mujoco/introspect/functions.py +++ b/python/mujoco/introspect/functions.py @@ -9175,7 +9175,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([ ), ), ), - doc='Detach but not delete object corresponding to the given element, return 0 on success.', # pylint: disable=line-too-long + doc='Remove object corresponding to the given element, return 0 on success.', # pylint: disable=line-too-long )), ('mjs_addActuator', FunctionDecl( diff --git a/src/user/user_api.cc b/src/user/user_api.cc index af4c18f6..0857f804 100644 --- a/src/user/user_api.cc +++ b/src/user/user_api.cc @@ -340,7 +340,7 @@ int mj_copyBack(mjSpec* s, const mjModel* m) { -// detach body from mjSpec, return 0 on success +// remove body from mjSpec, return 0 on success int mjs_delete(mjSpec* s, mjsElement* element) { mjCModel* model = static_cast(s->element); if (!element) { diff --git a/src/user/user_api.h b/src/user/user_api.h index cbc2f715..cfc33c60 100644 --- a/src/user/user_api.h +++ b/src/user/user_api.h @@ -103,7 +103,7 @@ MJAPI mjsLight* mjs_addLight(mjsBody* body, const mjsDefault* def); // Add frame to body. MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe); -// Detach but not delete object corresponding to the given element, return 0 on success. +// Remove object corresponding to the given element, return 0 on success. MJAPI int mjs_delete(mjSpec* s, mjsElement* element);