diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index ba2074f8..ca4d1c6f 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -19,9 +19,13 @@ The model and all files referenced in it can be loaded from disk or from a VFS w .. mujoco-include:: mj_loadXML Parse XML file in MJCF or URDF format, compile it, return low-level model. + If vfs is not NULL, look up files in vfs before reading from disk. + If error is not NULL, it must have size error_sz. +*Nullable:* ``vfs``, ``error`` + .. _mj_parseXML: `mj_parseXML <#mj_parseXML>`__ @@ -31,6 +35,8 @@ If error is not NULL, it must have size error_sz. Parse spec from XML file. +*Nullable:* ``vfs``, ``error`` + .. _mj_parseXMLString: `mj_parseXMLString <#mj_parseXMLString>`__ @@ -40,6 +46,8 @@ Parse spec from XML file. Parse spec from XML string. +*Nullable:* ``vfs``, ``error`` + .. _mj_compile: `mj_compile <#mj_compile>`__ @@ -332,6 +340,8 @@ center-of-mass but aligned with the world frame. The minimal :ref:`pipeline stag computations to be consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` followed by :ref:`mj_comPos`. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacBody: `mj_jacBody <#mj_jacBody>`__ @@ -342,6 +352,8 @@ by :ref:`mj_comPos`. This and the remaining variants of the Jacobian function call mj_jac internally, with the center of the body, geom or site. They are just shortcuts; the same can be achieved by calling mj_jac directly. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacBodyCom: `mj_jacBodyCom <#mj_jacBodyCom>`__ @@ -351,6 +363,8 @@ site. They are just shortcuts; the same can be achieved by calling mj_jac direct Compute body center-of-mass end-effector Jacobian. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacSubtreeCom: `mj_jacSubtreeCom <#mj_jacSubtreeCom>`__ @@ -369,6 +383,8 @@ Compute subtree center-of-mass end-effector Jacobian. Compute geom end-effector Jacobian. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacSite: `mj_jacSite <#mj_jacSite>`__ @@ -378,6 +394,8 @@ Compute geom end-effector Jacobian. Compute site end-effector Jacobian. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacPointAxis: `mj_jacPointAxis <#mj_jacPointAxis>`__ @@ -387,6 +405,8 @@ Compute site end-effector Jacobian. Compute translation end-effector Jacobian of point, and rotation Jacobian of axis. +*Nullable:* ``jacPoint``, ``jacAxis`` + .. _mj_jacDot: `mj_jacDot <#mj_jacDot>`__ @@ -399,6 +419,8 @@ The minimal :ref:`pipeline stages` required for computation to be consistent with the current generalized positions and velocities ``mjData.{qpos, qvel}`` are :ref:`mj_kinematics`, :ref:`mj_comPos`, :ref:`mj_comVel` (in that order). +*Nullable:* ``jacp``, ``jacr`` + .. _mj_angmomMat: `mj_angmomMat <#mj_angmomMat>`__ @@ -468,8 +490,11 @@ Multiply vector by (inertia matrix)^(1/2). .. mujoco-include:: mj_addM Add inertia matrix to destination matrix. + Destination can be sparse or dense when all int* are NULL. +*Nullable:* ``rownnz``, ``rowadr``, ``colind`` + .. _mj_applyFT: `mj_applyFT <#mj_applyFT>`__ @@ -512,11 +537,13 @@ Returns the smallest signed distance between two geoms and optionally the segmen Returned distances are bounded from above by ``distmax``. |br| If no collision of distance smaller than ``distmax`` is found, the function will return ``distmax`` and ``fromto``, if given, will be set to (0, 0, 0, 0, 0, 0). - .. admonition:: different (correct) behavior under `nativeccd` - :class: note +*Nullable:* ``fromto`` - As explained in :ref:`Collision Detection`, distances are inaccurate when using the - :ref:`legacy CCD pipeline`, and its use is discouraged. +.. admonition:: different (correct) behavior under `nativeccd` + :class: note + + As explained in :ref:`Collision Detection`, distances are inaccurate when using the + :ref:`legacy CCD pipeline`, and its use is discouraged. .. _mj_contactForce: @@ -594,6 +621,7 @@ Scale body masses and inertias to achieve specified total mass. .. mujoco-include:: mj_getPluginConfig Return a config attribute value of a plugin instance; + NULL: invalid plugin instance ID or attribute name .. _mj_loadPluginLibrary: @@ -1051,6 +1079,8 @@ Compute efc_vel, efc_aref. Compute ``efc_state``, ``efc_force``, ``qfrc_constraint``, and (optionally) cone Hessians. If ``cost`` is not ``NULL``, set ``*cost = s(jar)`` where ``jar = Jac*qacc - aref``. +*Nullable:* ``cost`` + .. _Raycollisions: Ray casting @@ -1074,6 +1104,7 @@ rays from a single point. .. mujoco-include:: mj_multiRay Intersect multiple rays emanating from a single point. + Similar semantics to mj_ray, but vec is an array of (nray x 3) directions. .. _mj_ray: @@ -1094,6 +1125,8 @@ If flg_static is 0, static geoms will be excluded. bodyexclude=-1 can be used to indicate that all bodies are included. +*Nullable:* ``geomid`` + .. _mj_rayHfield: `mj_rayHfield <#mj_rayHfield>`__ @@ -1131,6 +1164,8 @@ Intersect ray with pure geom, return nearest distance or -1 if no intersection. Intersect ray with flex, return nearest distance or -1 if no intersection, and also output nearest vertex id. +*Nullable:* ``vertid`` + .. _mju_raySkin: `mju_raySkin <#mju_raySkin>`__ @@ -1141,6 +1176,8 @@ and also output nearest vertex id. Intersect ray with skin, return nearest distance or -1 if no intersection, and also output nearest vertex id. +*Nullable:* ``vertid`` + .. _Printing: Printing @@ -1247,6 +1284,8 @@ Initialize an empty VFS, :ref:`mj_deleteVFS` must be called to deallocate the VF Add file to VFS. The directory argument is optional and can be NULL or empty. Returns 0 on success, 2 on name collision, or -1 when an internal error occurs. +*Nullable:* ``directory`` + .. _mj_addBufferVFS: `mj_addBufferVFS <#mj_addBufferVFS>`__ @@ -1336,6 +1375,8 @@ Copy mjModel, allocate new if dest is NULL. Save model to binary MJB file or memory buffer; buffer has precedence when given. +*Nullable:* ``filename``, ``buffer`` + .. _mj_loadModel: `mj_loadModel <#mj_loadModel>`__ @@ -1344,8 +1385,11 @@ Save model to binary MJB file or memory buffer; buffer has precedence when given .. mujoco-include:: mj_loadModel Load model from binary MJB file. + If vfs is not NULL, look up file in vfs before reading from disk. +*Nullable:* ``vfs`` + .. _mj_deleteModel: `mj_deleteModel <#mj_deleteModel>`__ @@ -1372,6 +1416,7 @@ Return size of buffer needed to hold model. .. mujoco-include:: mj_makeData Allocate mjData corresponding to given model. + If the model buffer is unallocated the initial configuration will not be set. .. _mj_copyData: @@ -1447,6 +1492,7 @@ to mj_markStack must no longer be used afterwards. .. mujoco-include:: mj_stackAllocByte Allocate a number of bytes on mjData stack at a specific alignment. + Call mju_error on stack overflow. .. _mj_stackAllocNum: @@ -1503,6 +1549,8 @@ Set constant fields of mjModel, corresponding to qpos0 configuration. Set actuator_lengthrange for specified actuator; return 1 if ok, 0 if error. +*Nullable:* ``error`` + .. _mj_makeSpec: `mj_makeSpec <#mj_makeSpec>`__ @@ -2059,6 +2107,7 @@ Copy perturb pos,quat from selected body; set scale for perturbation. .. mujoco-include:: mjv_applyPerturbPose Set perturb pos,quat in d->mocap when selected body is mocap, and in d->qpos otherwise. + Write d->qpos only if flg_paused and subtree root for selected body has free joint. .. _mjv_applyPerturbForce: @@ -2128,6 +2177,8 @@ Set default figure. Initialize given geom fields when not NULL, set the rest to their default values. +*Nullable:* ``size``, ``pos``, ``mat``, ``rgba`` + .. _mjv_connector: `mjv_connector <#mjv_connector>`__ @@ -2136,7 +2187,9 @@ Initialize given geom fields when not NULL, set the rest to their default values .. mujoco-include:: mjv_connector Set (type, size, pos, mat) for connector-type geom between given points. + Assume that mjv_initGeom was already called to set all other properties. + Width of mjGEOM_LINE is denominated in pixels. .. _mjv_defaultScene: @@ -2184,6 +2237,8 @@ Update entire scene given model state. Copy mjModel, skip large arrays not required for abstract visualization. +*Nullable:* ``dest`` + .. _mjv_addGeoms: `mjv_addGeoms <#mjv_addGeoms>`__ @@ -2326,6 +2381,7 @@ Make con->currentBuffer current again. .. mujoco-include:: mjr_setBuffer Set OpenGL framebuffer for rendering: mjFB_WINDOW or mjFB_OFFSCREEN. + If only one buffer is available, set that buffer and ignore framebuffer argument. .. _mjr_readPixels: @@ -2336,6 +2392,7 @@ If only one buffer is available, set that buffer and ignore framebuffer argument .. mujoco-include:: mjr_readPixels Read pixels from current OpenGL framebuffer to client buffer. + Viewport is in OpenGL framebuffer; client buffer starts at (0,0). .. _mjr_drawPixels: @@ -2346,6 +2403,7 @@ Viewport is in OpenGL framebuffer; client buffer starts at (0,0). .. mujoco-include:: mjr_drawPixels Draw pixels from client buffer to current OpenGL framebuffer. + Viewport is in OpenGL framebuffer; client buffer starts at (0,0). .. _mjr_blitBuffer: @@ -2356,6 +2414,7 @@ Viewport is in OpenGL framebuffer; client buffer starts at (0,0). .. mujoco-include:: mjr_blitBuffer Blit from src viewpoint in current framebuffer to dst viewport in other framebuffer. + If src, dst have different size and flg_depth==0, color is interpolated with GL_LINEAR. .. _mjr_setAux: @@ -2618,6 +2677,8 @@ These matrices and their dimensions are: termination. Of course, this means that :ref:`solver iterations` should be small, to not tread water at the minimum. This method and the one described above can and should be combined. +*Nullable:* ``A``, ``B``, ``D``, ``C`` + .. _mjd_inverseFD: `mjd_inverseFD <#mjd_inverseFD>`__ @@ -2661,6 +2722,8 @@ using finite-differencing. These matrices and their dimensions are: - The Runge-Kutta 4th-order integrator (``mjINT_RK4``) is not supported. - The noslip solver is not supported. +*Nullable:* ``DfDq``, ``DfDv``, ``DfDa``, ``DsDq``, ``DsDv``, ``DsDa``, ``DmDq`` + .. _mjd_subQuat: `mjd_subQuat <#mjd_subQuat>`__ @@ -2670,6 +2733,8 @@ using finite-differencing. These matrices and their dimensions are: Derivatives of :ref:`mju_subQuat` (quaternion difference). +*Nullable:* ``Da``, ``Db`` + .. _mjd_quatIntegrate: `mjd_quatIntegrate <#mjd_quatIntegrate>`__ @@ -2697,6 +2762,8 @@ to the inputs. Below, :math:`\bar q` denotes the pre-modified quaternion: Note that derivatives depend only on :math:`h` and :math:`v` (in fact, on :math:`s = h v`). All outputs are optional. +*Nullable:* ``Dquat``, ``Dvel``, ``Dscale`` + .. _Plugins-api: Plugins @@ -2718,8 +2785,11 @@ Set default plugin definition. .. mujoco-include:: mjp_registerPlugin Globally register a plugin. This function is thread-safe. + If an identical mjpPlugin is already registered, this function does nothing. + If a non-identical mjpPlugin with the same name is already registered, an mju_error is raised. + Two mjpPlugins are considered identical if all member function pointers and numbers are equal, and the name and attribute strings are all identical, however the char pointers to the strings need not be the same. @@ -2788,6 +2858,7 @@ Return the number of globally registered resource providers. .. mujoco-include:: mjp_getResourceProvider Return the resource provider with the prefix that matches against the resource name. + If no match, return NULL. .. _mjp_getResourceProviderAtSlot: @@ -2798,6 +2869,7 @@ If no match, return NULL. .. mujoco-include:: mjp_getResourceProviderAtSlot Look up a resource provider by slot number returned by mjp_registerResourceProvider. + If invalid slot number, return NULL. .. _Thread: @@ -3395,6 +3467,8 @@ Set res = mat' * diag * mat if diag is not NULL, and res = mat' * mat otherwise. Coordinate transform of 6D motion or force vector in rotation:translation format. rotnew2old is 3-by-3, NULL means no rotation; flg_force specifies force or motion type. +*Nullable:* ``rotnew2old`` + .. _Sparsemath: Sparse math @@ -3539,6 +3613,7 @@ Construct quaternion performing rotation from z-axis to given vector. .. mujoco-include:: mju_mat2Rot Extract 3D rotation from an arbitrary 3x3 matrix by refining the input quaternion. + Returns the number of iterations required to converge .. _mju_euler2Quat: @@ -3796,6 +3871,8 @@ Tree elements Add child body to body, return child. +*Nullable:* ``def`` + .. _mjs_addSite: `mjs_addSite <#mjs_addSite>`__ @@ -3805,6 +3882,8 @@ Add child body to body, return child. Add site to body, return site spec. +*Nullable:* ``def`` + .. _mjs_addJoint: `mjs_addJoint <#mjs_addJoint>`__ @@ -3814,6 +3893,8 @@ Add site to body, return site spec. Add joint to body. +*Nullable:* ``def`` + .. _mjs_addFreeJoint: `mjs_addFreeJoint <#mjs_addFreeJoint>`__ @@ -3832,6 +3913,8 @@ Add freejoint to body. Add geom to body. +*Nullable:* ``def`` + .. _mjs_addCamera: `mjs_addCamera <#mjs_addCamera>`__ @@ -3841,6 +3924,8 @@ Add geom to body. Add camera to body. +*Nullable:* ``def`` + .. _mjs_addLight: `mjs_addLight <#mjs_addLight>`__ @@ -3850,6 +3935,8 @@ Add camera to body. Add light to body. +*Nullable:* ``def`` + .. _mjs_addFrame: `mjs_addFrame <#mjs_addFrame>`__ @@ -3881,6 +3968,8 @@ Non-tree elements Add actuator. +*Nullable:* ``def`` + .. _mjs_addSensor: `mjs_addSensor <#mjs_addSensor>`__ @@ -3908,6 +3997,8 @@ Add flex. Add contact pair. +*Nullable:* ``def`` + .. _mjs_addExclude: `mjs_addExclude <#mjs_addExclude>`__ @@ -3926,6 +4017,8 @@ Add excluded body pair. Add equality. +*Nullable:* ``def`` + .. _mjs_addTendon: `mjs_addTendon <#mjs_addTendon>`__ @@ -3935,6 +4028,8 @@ Add equality. Add tendon. +*Nullable:* ``def`` + .. _mjs_wrapSite: `mjs_wrapSite <#mjs_wrapSite>`__ @@ -4025,6 +4120,8 @@ Add plugin. Add default. +*Nullable:* ``parent`` + .. _AddAssets: Assets @@ -4038,6 +4135,8 @@ Assets Add mesh. +*Nullable:* ``def`` + .. _mjs_addHField: `mjs_addHField <#mjs_addHField>`__ @@ -4074,6 +4173,8 @@ Add texture. Add material. +*Nullable:* ``def`` + .. _mjs_makeMesh: `mjs_makeMesh <#mjs_makeMesh>`__ @@ -4212,6 +4313,7 @@ Return body's first child of given type. If recurse is nonzero, also search the .. mujoco-include:: mjs_nextChild Return body's next child of the same type; return NULL if child is last. + If recurse is nonzero, also search the body's subtree. .. _mjs_firstElement: @@ -4375,6 +4477,8 @@ Get string contents. Get double array contents and optionally its size. +*Nullable:* ``size`` + .. _mjs_getPluginAttributes: `mjs_getPluginAttributes <#mjs_getPluginAttributes>`__ diff --git a/doc/APIreference/functions_override.rst b/doc/APIreference/functions_override.rst index 7f35ed84..61da5a76 100644 --- a/doc/APIreference/functions_override.rst +++ b/doc/APIreference/functions_override.rst @@ -23,6 +23,8 @@ Initialize an empty VFS, :ref:`mj_deleteVFS` must be called to deallocate the VF Add file to VFS. The directory argument is optional and can be NULL or empty. Returns 0 on success, 2 on name collision, or -1 when an internal error occurs. +*Nullable:* ``directory`` + .. _Parseandcompile: The key function here is :ref:`mj_loadXML`. It invokes the built-in parser and compiler, and either returns a pointer to @@ -169,6 +171,8 @@ the effect of spatial tendons, see :github:issue:`832`. Compute ``efc_state``, ``efc_force``, ``qfrc_constraint``, and (optionally) cone Hessians. If ``cost`` is not ``NULL``, set ``*cost = s(jar)`` where ``jar = Jac*qacc - aref``. +*Nullable:* ``cost`` + .. _Support: These are support functions that need access to :ref:`mjModel` and :ref:`mjData`, unlike the utility functions which do @@ -212,11 +216,15 @@ center-of-mass but aligned with the world frame. The minimal :ref:`pipeline stag computations to be consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` followed by :ref:`mj_comPos`. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacBody: This and the remaining variants of the Jacobian function call mj_jac internally, with the center of the body, geom or site. They are just shortcuts; the same can be achieved by calling mj_jac directly. +*Nullable:* ``jacp``, ``jacr`` + .. _mj_jacDot: This function computes the time-derivative of an end-effector kinematic Jacobian computed by :ref:`mj_jac`. @@ -224,6 +232,8 @@ The minimal :ref:`pipeline stages` required for computation to be consistent with the current generalized positions and velocities ``mjData.{qpos, qvel}`` are :ref:`mj_kinematics`, :ref:`mj_comPos`, :ref:`mj_comVel` (in that order). +*Nullable:* ``jacp``, ``jacr`` + .. _mj_angmomMat: This function computes the ``3 x nv`` angular momentum matrix :math:`H(q)`, providing the linear mapping from @@ -245,11 +255,13 @@ Returns the smallest signed distance between two geoms and optionally the segmen Returned distances are bounded from above by ``distmax``. |br| If no collision of distance smaller than ``distmax`` is found, the function will return ``distmax`` and ``fromto``, if given, will be set to (0, 0, 0, 0, 0, 0). - .. admonition:: different (correct) behavior under `nativeccd` - :class: note +*Nullable:* ``fromto`` - As explained in :ref:`Collision Detection`, distances are inaccurate when using the - :ref:`legacy CCD pipeline`, and its use is discouraged. +.. admonition:: different (correct) behavior under `nativeccd` + :class: note + + As explained in :ref:`Collision Detection`, distances are inaccurate when using the + :ref:`legacy CCD pipeline`, and its use is discouraged. .. _mj_fullM: @@ -313,6 +325,8 @@ If flg_static is 0, static geoms will be excluded. bodyexclude=-1 can be used to indicate that all bodies are included. +*Nullable:* ``geomid`` + .. _Interaction: These functions implement abstract mouse interactions, allowing control over cameras and perturbations. Their use is well @@ -654,6 +668,7 @@ These matrices and their dimensions are: termination. Of course, this means that :ref:`solver iterations` should be small, to not tread water at the minimum. This method and the one described above can and should be combined. +*Nullable:* ``A``, ``B``, ``D``, ``C`` .. _mjd_inverseFD: @@ -693,10 +708,14 @@ using finite-differencing. These matrices and their dimensions are: - The Runge-Kutta 4th-order integrator (``mjINT_RK4``) is not supported. - The noslip solver is not supported. +*Nullable:* ``DfDq``, ``DfDv``, ``DfDa``, ``DsDq``, ``DsDv``, ``DsDa``, ``DmDq`` + .. _mjd_subQuat: Derivatives of :ref:`mju_subQuat` (quaternion difference). +*Nullable:* ``Da``, ``Db`` + .. _mjd_quatIntegrate: Derivatives of :ref:`mju_quatIntegrate`. @@ -718,3 +737,5 @@ to the inputs. Below, :math:`\bar q` denotes the pre-modified quaternion: Note that derivatives depend only on :math:`h` and :math:`v` (in fact, on :math:`s = h v`). All outputs are optional. + +*Nullable:* ``Dquat``, ``Dvel``, ``Dscale`` diff --git a/doc/ext/header_reader.py b/doc/ext/header_reader.py index e81f98a8..3d21207d 100644 --- a/doc/ext/header_reader.py +++ b/doc/ext/header_reader.py @@ -37,6 +37,9 @@ _STRUCT_END_REGEX_2 = re.compile(r'^}\s+(?Pmj\w+);') # Precompiled regex for matching a C enum ending. _ENUM_END_REGEX = re.compile(r'^}\s+(?Pmj\w+);') +# Precompiled regex for matching a C type with a nullable annotation. +_NULLABLE_REGEX = re.compile(r'(?P\s*)Nullable:\s*(?P.*)') + @dataclasses.dataclass class ApiDefinition: @@ -120,7 +123,19 @@ def read(lines: List[str]) -> Dict[str, ApiDefinition]: s.end() continue elif line.startswith('//'): - s.doc = f'{s.doc}{line[3:]}' + if len(line) > 3 and line[3].isupper(): + s.doc += '\n' + comment = line[3:] + match = re.match(_NULLABLE_REGEX, comment) + if match: + groups = match.groupdict() + args = [ + f'``{arg.strip()}``' + for arg in groups['args'].split(',') + if arg.strip() + ] + comment = f'{groups["leading_space"]}*Nullable:* {", ".join(args)}' + s.doc = f'{s.doc}{comment}' else: s.end() if s.state == 'FUNCTION': diff --git a/doc/ext/header_reader_test.py b/doc/ext/header_reader_test.py index 25654f82..3fd413cd 100644 --- a/doc/ext/header_reader_test.py +++ b/doc/ext/header_reader_test.py @@ -87,7 +87,7 @@ class MuJoCoApiGeneratorTest(parameterized.TestCase): def test_multi_line_doc(self): self.assertEqual(_API['mj_other_function'].doc, - 'My other function\nThis one has multiple lines\n') + 'My other function\n\nThis one has multiple lines\n') def test_multi_line_function(self): self.assertEqual(_API['mj_other_function'].start, 9) diff --git a/include/mujoco/mujoco.h b/include/mujoco/mujoco.h index 9ab1d2ca..d135af99 100644 --- a/include/mujoco/mujoco.h +++ b/include/mujoco/mujoco.h @@ -96,25 +96,31 @@ MJAPI void mj_deleteVFS(mjVFS* vfs); // Parse XML file in MJCF or URDF format, compile it, return low-level model. // If vfs is not NULL, look up files in vfs before reading from disk. // If error is not NULL, it must have size error_sz. +// Nullable: vfs, error MJAPI mjModel* mj_loadXML(const char* filename, const mjVFS* vfs, char* error, int error_sz); // Parse spec from XML file. +// Nullable: vfs, error MJAPI mjSpec* mj_parseXML(const char* filename, const mjVFS* vfs, char* error, int error_sz); // Parse spec from XML string. +// Nullable: vfs, error MJAPI mjSpec* mj_parseXMLString(const char* xml, const mjVFS* vfs, char* error, int error_sz); // Compile spec to model. +// Nullable: vfs MJAPI mjModel* mj_compile(mjSpec* s, const mjVFS* vfs); // Copy real-valued arrays from model to spec, returns 1 on success. MJAPI int mj_copyBack(mjSpec* s, const mjModel* m); // Recompile spec to model, preserving the state, return 0 on success. +// Nullable: vfs MJAPI int mj_recompile(mjSpec* s, const mjVFS* vfs, mjModel* m, mjData* d); // Update XML data structures with info from low-level model created with mj_loadXML, save as MJCF. // If error is not NULL, it must have size error_sz. +// Nullable: error MJAPI int mj_saveLastXML(const char* filename, const mjModel* m, char* error, int error_sz); // Free last XML model if loaded. Called internally at each load. @@ -122,9 +128,11 @@ MJAPI void mj_freeLastXML(void); // Save spec to XML string, return 0 on success, -1 on failure. // If length of the output buffer is too small, returns the required size. +// Nullable: error MJAPI int mj_saveXMLString(const mjSpec* s, char* xml, int xml_sz, char* error, int error_sz); // Save spec to XML file, return 0 on success, -1 otherwise. +// Nullable: error MJAPI int mj_saveXML(const mjSpec* s, const char* filename, char* error, int error_sz); @@ -170,10 +178,12 @@ MJAPI void mj_defaultVisual(mjVisual* vis); MJAPI mjModel* mj_copyModel(mjModel* dest, const mjModel* src); // Save model to binary MJB file or memory buffer; buffer has precedence when given. +// Nullable: filename, buffer MJAPI void mj_saveModel(const mjModel* m, const char* filename, void* buffer, int buffer_sz); // Load model from binary MJB file. // If vfs is not NULL, look up file in vfs before reading from disk. +// Nullable: vfs MJAPI mjModel* mj_loadModel(const char* filename, const mjVFS* vfs); // Free memory allocation in model. @@ -233,6 +243,7 @@ MJAPI void mj_resetCallbacks(void); MJAPI void mj_setConst(mjModel* m, mjData* d); // Set actuator_lengthrange for specified actuator; return 1 if ok, 0 if error. +// Nullable: error MJAPI int mj_setLengthRange(mjModel* m, mjData* d, int index, const mjLROpt* opt, char* error, int error_sz); @@ -412,6 +423,7 @@ MJAPI void mj_referenceConstraint(const mjModel* m, mjData* d); // Compute efc_state, efc_force, qfrc_constraint, and (optionally) cone Hessians. // If cost is not NULL, set *cost = s(jar) where jar = Jac*qacc-aref. +// Nullable: cost MJAPI void mj_constraintUpdate(const mjModel* m, mjData* d, const mjtNum* jar, mjtNum cost[1], int flg_coneHessian); @@ -449,29 +461,36 @@ MJAPI void mj_mulJacVec(const mjModel* m, const mjData* d, mjtNum* res, const mj MJAPI void mj_mulJacTVec(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum* vec); // Compute 3/6-by-nv end-effector Jacobian of global point attached to given body. +// Nullable: jacp, jacr MJAPI void mj_jac(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, const mjtNum point[3], int body); // Compute body frame end-effector Jacobian. +// Nullable: jacp, jacr MJAPI void mj_jacBody(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int body); // Compute body center-of-mass end-effector Jacobian. +// Nullable: jacp, jacr MJAPI void mj_jacBodyCom(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int body); // Compute subtree center-of-mass end-effector Jacobian. MJAPI void mj_jacSubtreeCom(const mjModel* m, mjData* d, mjtNum* jacp, int body); // Compute geom end-effector Jacobian. +// Nullable: jacp, jacr MJAPI void mj_jacGeom(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int geom); // Compute site end-effector Jacobian. +// Nullable: jacp, jacr MJAPI void mj_jacSite(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int site); // Compute translation end-effector Jacobian of point, and rotation Jacobian of axis. +// Nullable: jacPoint, jacAxis MJAPI void mj_jacPointAxis(const mjModel* m, mjData* d, mjtNum* jacPoint, mjtNum* jacAxis, const mjtNum point[3], const mjtNum axis[3], int body); // Compute 3/6-by-nv Jacobian time derivative of global point attached to given body. +// Nullable: jacp, jacr MJAPI void mj_jacDot(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, const mjtNum point[3], int body); @@ -495,9 +514,11 @@ MJAPI void mj_mulM2(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum // Add inertia matrix to destination matrix. // Destination can be sparse or dense when all int* are NULL. +// Nullable: rownnz, rowadr, colind MJAPI void mj_addM(const mjModel* m, mjData* d, mjtNum* dst, int* rownnz, int* rowadr, int* colind); // Apply Cartesian force and torque (outside xfrc_applied mechanism). +// Nullable: force, torque MJAPI void mj_applyFT(const mjModel* m, mjData* d, const mjtNum force[3], const mjtNum torque[3], const mjtNum point[3], int body, mjtNum* qfrc_target); @@ -510,6 +531,7 @@ MJAPI void mj_objectAcceleration(const mjModel* m, const mjData* d, int objtype, int objid, mjtNum res[6], int flg_local); // Returns smallest signed distance between two geoms and optionally segment from geom1 to geom2. +// Nullable: fromto MJAPI mjtNum mj_geomDistance(const mjModel* m, const mjData* d, int geom1, int geom2, mjtNum distmax, mjtNum fromto[6]); @@ -566,6 +588,7 @@ MJAPI void mj_multiRay(const mjModel* m, mjData* d, const mjtNum pnt[3], const m // Intersect ray (pnt+x*vec, x>=0) with visible geoms, except geoms in bodyexclude. // Return distance (x) to nearest surface, or -1 if no intersection and output geomid. // geomgroup, flg_static are as in mjvOption; geomgroup==NULL skips group exclusion. +// Nullable: geomid MJAPI mjtNum mj_ray(const mjModel* m, const mjData* d, const mjtNum pnt[3], const mjtNum vec[3], const mjtByte* geomgroup, mjtByte flg_static, int bodyexclude, int geomid[1]); @@ -584,12 +607,14 @@ MJAPI mjtNum mju_rayGeom(const mjtNum pos[3], const mjtNum mat[9], const mjtNum // Intersect ray with flex, return nearest distance or -1 if no intersection, // and also output nearest vertex id. +// Nullable: vertid MJAPI mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte flg_vert, mjtByte flg_edge, mjtByte flg_face, mjtByte flg_skin, int flexid, const mjtNum* pnt, const mjtNum* vec, int vertid[1]); // Intersect ray with skin, return nearest distance or -1 if no intersection, // and also output nearest vertex id. +// Nullable: vertid MJAPI mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert, const mjtNum pnt[3], const mjtNum vec[3], int vertid[1]); @@ -654,6 +679,7 @@ MJAPI void mjv_applyPerturbForce(const mjModel* m, mjData* d, const mjvPerturb* MJAPI mjvGLCamera mjv_averageCamera(const mjvGLCamera* cam1, const mjvGLCamera* cam2); // Select geom, flex or skin with mouse, return bodyid; -1: none selected. +// Nullable: geomid, flexid, skinid MJAPI int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt, mjtNum aspectratio, mjtNum relx, mjtNum rely, const mjvScene* scn, mjtNum selpnt[3], @@ -669,6 +695,7 @@ MJAPI void mjv_defaultOption(mjvOption* opt); MJAPI void mjv_defaultFigure(mjvFigure* fig); // Initialize given geom fields when not NULL, set the rest to their default values. +// Nullable: size, pos, mat, rgba MJAPI void mjv_initGeom(mjvGeom* geom, int type, const mjtNum size[3], const mjtNum pos[3], const mjtNum mat[9], const float rgba[4]); @@ -692,6 +719,7 @@ MJAPI void mjv_updateScene(const mjModel* m, mjData* d, const mjvOption* opt, const mjvPerturb* pert, mjvCamera* cam, int catmask, mjvScene* scn); // Copy mjModel, skip large arrays not required for abstract visualization. +// Nullable: dest MJAPI void mjv_copyModel(mjModel* dest, const mjModel* src); // Add geoms from selected categories. @@ -1050,6 +1078,7 @@ MJAPI void mju_sqrMatTD(mjtNum* res, const mjtNum* mat, const mjtNum* diag, int // Coordinate transform of 6D motion or force vector in rotation:translation format. // rotnew2old is 3-by-3, NULL means no rotation; flg_force specifies force or motion type. +// Nullable: rotnew2old MJAPI void mju_transformSpatial(mjtNum res[6], const mjtNum vec[6], int flg_force, const mjtNum newpos[3], const mjtNum oldpos[3], const mjtNum rotnew2old[9]); @@ -1192,6 +1221,7 @@ MJAPI int mju_eig3(mjtNum eigval[3], mjtNum eigvec[9], mjtNum quat[4], const mjt // index (if given) must have allocated size n, but only nfree values are used in output // only the lower triangles of H and R and are read from and written to, respectively // the convenience function mju_boxQPmalloc allocates the required data structures +// Nullable: index, lower, upper MJAPI int mju_boxQP(mjtNum* res, mjtNum* R, int* index, const mjtNum* H, const mjtNum* g, int n, const mjtNum* lower, const mjtNum* upper); @@ -1311,6 +1341,7 @@ MJAPI void mjc_gradient(const mjModel* m, const mjData* d, const mjSDF* s, mjtNu // B: (2*nv+na x nu) // D: (nsensordata x 2*nv+na) // C: (nsensordata x nu) +// Nullable: A, B, C, D MJAPI void mjd_transitionFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg_centered, mjtNum* A, mjtNum* B, mjtNum* C, mjtNum* D); @@ -1329,15 +1360,18 @@ MJAPI void mjd_transitionFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg // notes: // optionally computes mass matrix Jacobian DmDq // flg_actuation specifies whether to subtract qfrc_actuator from qfrc_inverse +// Nullable: DfDq, DfDv, DfDa, DsDq, DsDv, DsDa, DmDq MJAPI void mjd_inverseFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg_actuation, mjtNum *DfDq, mjtNum *DfDv, mjtNum *DfDa, mjtNum *DsDq, mjtNum *DsDv, mjtNum *DsDa, mjtNum *DmDq); // Derivatives of mju_subQuat. +// Nullable: Da, Db MJAPI void mjd_subQuat(const mjtNum qa[4], const mjtNum qb[4], mjtNum Da[9], mjtNum Db[9]); // Derivatives of mju_quatIntegrate. +// Nullable: Dquat, Dvel, Dscale MJAPI void mjd_quatIntegrate(const mjtNum vel[3], mjtNum scale, mjtNum Dquat[9], mjtNum Dvel[9], mjtNum Dscale[3]); @@ -1415,24 +1449,30 @@ MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child, //---------------------------------- Tree elements ------------------------------------------------- // Add child body to body, return child. +// Nullable: def MJAPI mjsBody* mjs_addBody(mjsBody* body, const mjsDefault* def); // Add site to body, return site spec. +// Nullable: def MJAPI mjsSite* mjs_addSite(mjsBody* body, const mjsDefault* def); // Add joint to body. +// Nullable: def MJAPI mjsJoint* mjs_addJoint(mjsBody* body, const mjsDefault* def); // Add freejoint to body. MJAPI mjsJoint* mjs_addFreeJoint(mjsBody* body); // Add geom to body. +// Nullable: def MJAPI mjsGeom* mjs_addGeom(mjsBody* body, const mjsDefault* def); // Add camera to body. +// Nullable: def MJAPI mjsCamera* mjs_addCamera(mjsBody* body, const mjsDefault* def); // Add light to body. +// Nullable: def MJAPI mjsLight* mjs_addLight(mjsBody* body, const mjsDefault* def); // Add frame to body. @@ -1445,6 +1485,7 @@ MJAPI int mjs_delete(mjSpec* spec, mjsElement* element); //---------------------------------- Non-tree elements --------------------------------------------- // Add actuator. +// Nullable: def MJAPI mjsActuator* mjs_addActuator(mjSpec* s, const mjsDefault* def); // Add sensor. @@ -1454,15 +1495,18 @@ MJAPI mjsSensor* mjs_addSensor(mjSpec* s); MJAPI mjsFlex* mjs_addFlex(mjSpec* s); // Add contact pair. +// Nullable: def MJAPI mjsPair* mjs_addPair(mjSpec* s, const mjsDefault* def); // Add excluded body pair. MJAPI mjsExclude* mjs_addExclude(mjSpec* s); // Add equality. +// Nullable: def MJAPI mjsEquality* mjs_addEquality(mjSpec* s, const mjsDefault* def); // Add tendon. +// Nullable: def MJAPI mjsTendon* mjs_addTendon(mjSpec* s, const mjsDefault* def); // Wrap site using tendon. @@ -1493,6 +1537,7 @@ MJAPI mjsKey* mjs_addKey(mjSpec* s); MJAPI mjsPlugin* mjs_addPlugin(mjSpec* s); // Add default. +// Nullable: parent MJAPI mjsDefault* mjs_addDefault(mjSpec* s, const char* classname, const mjsDefault* parent); @@ -1531,6 +1576,7 @@ MJAPI const char* mjs_setToAdhesion(mjsActuator* actuator, double gain); //---------------------------------- Assets -------------------------------------------------------- // Add mesh. +// Nullable: def MJAPI mjsMesh* mjs_addMesh(mjSpec* s, const mjsDefault* def); // Add height field. @@ -1543,6 +1589,7 @@ MJAPI mjsSkin* mjs_addSkin(mjSpec* s); MJAPI mjsTexture* mjs_addTexture(mjSpec* s); // Add material. +// Nullable: def MJAPI mjsMaterial* mjs_addMaterial(mjSpec* s, const mjsDefault* def); // Sets the vertices and normals of a mesh. @@ -1648,6 +1695,7 @@ MJAPI mjString* mjs_getName(mjsElement* element); MJAPI const char* mjs_getString(const mjString* source); // Get double array contents and optionally its size. +// Nullable: size MJAPI const double* mjs_getDouble(const mjDoubleVec* source, int* size); // Get plugin attributes. diff --git a/python/mujoco/introspect/codegen/generate_functions.py b/python/mujoco/introspect/codegen/generate_functions.py index 06beeaf2..d343962f 100644 --- a/python/mujoco/introspect/codegen/generate_functions.py +++ b/python/mujoco/introspect/codegen/generate_functions.py @@ -95,7 +95,11 @@ class MjFunctionVisitor: else: strings = [] for child in node['inner']: - strings.append(self._make_comment(child)) + comment = self._make_comment(child) + nullable_index = comment.find('Nullable:') + if nullable_index != -1: + comment = comment[:nullable_index] + strings.append(comment) return ''.join(strings) def visit(self, node: ClangJsonNode) -> None: