Add various improvements for resource providers.
PiperOrigin-RevId: 529706437 Change-Id: I20385e031446674584349c301982dbe13b812477
This commit is contained in:
committed by
Copybara-Service
parent
b798f89212
commit
67f0f5154f
@@ -671,6 +671,17 @@ information is then filled-in by the simulator.
|
||||
.. mujoco-include:: mjContact
|
||||
|
||||
|
||||
.. _mjResource:
|
||||
|
||||
mjResource
|
||||
~~~~~~~~~~
|
||||
|
||||
A resource is an abstraction of a file in a filesystem. The name field is the unique name of the resource while the
|
||||
other fields are populated by a :ref:`resource provider <exProvider>`.
|
||||
|
||||
.. mujoco-include:: mjResource
|
||||
|
||||
|
||||
.. _mjVFS:
|
||||
|
||||
mjVFS
|
||||
@@ -960,7 +971,15 @@ triggered by the compiler and the engine during various phases of the computatio
|
||||
|
||||
.. mujoco-include:: mjpPlugin
|
||||
|
||||
.. _mjpResourceProvider:
|
||||
|
||||
mjpResourceProvider
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This data structure contains the definition of a :ref:`resource provider <exProvider>`. It contains a set of callbacks
|
||||
used for opening and reading resources.
|
||||
|
||||
.. mujoco-include:: mjpResourceProvider
|
||||
|
||||
.. _tyFunction:
|
||||
|
||||
@@ -1074,6 +1093,57 @@ mjfItemEnable
|
||||
This is the function type of the predicate function used by the UI framework to determine if each item is enabled or
|
||||
disabled.
|
||||
|
||||
.. _tyRPCallbacks:
|
||||
|
||||
Resource Provider Callbacks
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
These callbacks are used by :ref:`resource providers<exProvider>`.
|
||||
|
||||
.. _mjfOpenResource:
|
||||
|
||||
mjfOpenResource
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
typedef int (*mjfOpenResource)(mjResource* resource);
|
||||
|
||||
This callback is for opeing a resource; returns zero on failure.
|
||||
|
||||
.. _mjfReadResource:
|
||||
|
||||
mjfReadResource
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
typedef int (*mjfReadResource)(mjResource* resource, const void** buffer);
|
||||
|
||||
This callback is for reading a resource. Returns number of bytes stored in buffer and returns -1 on error.
|
||||
|
||||
.. _mjfCloseResource:
|
||||
|
||||
mjfCloseResource
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
typedef void (*mjfCloseResource)(mjResource* resource);
|
||||
|
||||
This callback is for closing a resource, and is responsible for freeing any allocated memory.
|
||||
|
||||
.. _mjfGetResourceDir:
|
||||
|
||||
mjfGetResourceDir
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
typedef void (*mjfGetResourceDir)(mjResource* resource, const char** dir, int* ndir);
|
||||
|
||||
This callback is for returning the directory of a resource, by setting dir to the directory string with ndir being size
|
||||
of directory string.
|
||||
|
||||
.. _tyNotes:
|
||||
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ General
|
||||
- Added :ref:`mj_multiRay` function for intersecting multiple rays emanating from a single point.
|
||||
This is significantly faster than calling :ref:`mj_ray` multiple times.
|
||||
- Increased ``mjMAXUIITEM`` (maximum number of UI elements per section in Simulate) to 100.
|
||||
- Added :ref:`documentation<exProvider>` for resource providers.
|
||||
|
||||
Version 2.3.5 (April 25, 2023)
|
||||
------------------------------
|
||||
@@ -66,7 +67,7 @@ General
|
||||
#. Added midphase and broadphase collision statistics to :ref:`mjData`.
|
||||
#. Added documentation for :ref:`engine plugins<exPlugin>`.
|
||||
#. Added struct information to the ``introspect`` module.
|
||||
#. Added a new extension mechanism called "resource provider" . This extensible mechanism allows MuJoCo
|
||||
#. Added a new extension mechanism called :ref:`resource providers<exProvider>`. This extensible mechanism allows MuJoCo
|
||||
to read assets from data sources other than the local OS filesystem or
|
||||
the :ref:`Virtual file system<Virtualfilesystem>`.
|
||||
|
||||
|
||||
@@ -624,6 +624,9 @@ struct mjResource_ {
|
||||
|
||||
// closing callback from resource provider
|
||||
void (*close)(struct mjResource_* resource);
|
||||
|
||||
// getdir callback from resource provider
|
||||
void (*getdir)(struct mjResource_* resource, const char** dir, int* ndir);
|
||||
};
|
||||
typedef struct mjResource_ mjResource;
|
||||
struct mjOption_ { // physics options
|
||||
@@ -1198,11 +1201,12 @@ struct mjModel_ {
|
||||
};
|
||||
typedef struct mjModel_ mjModel;
|
||||
struct mjpResourceProvider_ {
|
||||
const char* prefix; // prefix for match against a resource name
|
||||
mjfOpenResource open; // opening callback
|
||||
mjfReadResource read; // reading callback
|
||||
mjfCloseResource close; // closing callback
|
||||
void* data; // opaque data pointer (resource invariant)
|
||||
const char* prefix; // prefix for match against a resource name
|
||||
mjfOpenResource open; // opening callback
|
||||
mjfReadResource read; // reading callback
|
||||
mjfCloseResource close; // closing callback
|
||||
mjfGetResourceDir getdir; // getdir callback (optional)
|
||||
void* data; // opaque data pointer (resource invariant)
|
||||
};
|
||||
typedef struct mjpResourceProvider_ mjpResourceProvider;
|
||||
typedef enum mjtPluginCapabilityBit_ {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
Extensions
|
||||
----------
|
||||
|
||||
This section describes MuJoCo's mechanisms for user-authored extensions. At present, extensibility is provided only
|
||||
via **engine plugins**.
|
||||
This section describes MuJoCo's mechanisms for user-authored extensions. At present, extensibility is provided by
|
||||
via :ref:`engine plugins<exPlugin>` and :ref:`resource providers<exProvider>`.
|
||||
|
||||
.. _exPlugin:
|
||||
|
||||
@@ -246,3 +246,130 @@ A future version of this section will include:
|
||||
* How to declare custom MJCF attributes for a plugin.
|
||||
* Things that developers need to keep in mind in order to ensure that plugins function correctly when :ref:`mjData` is
|
||||
copied, stepped, or reset.
|
||||
|
||||
.. _exProvider:
|
||||
|
||||
Resource providers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Resource providers extend MuJoCo to load assets (XML files, meshes, textures, and etc.) that don't necessarily come from
|
||||
the OS filesystem or the Virtual File System (:ref:`mjVFS`). For example, downloading assets from the Internet could be
|
||||
implemented as a resource provider. These extensions are handle abstractly in MuJoCo via the :ref:`mjResource` struct.
|
||||
|
||||
.. _exProviderStructure:
|
||||
|
||||
Overview
|
||||
^^^^^^^^
|
||||
|
||||
Creating a new resource provider works by registering a :ref:`mjpResourceProvider` struct via
|
||||
:ref:`mjp_registerResourceProvider` in a global table. Once a resource provider is registered it can be used by all
|
||||
loading functions. The :ref:`mjpResourceProvider` struct stores three types of fields:
|
||||
|
||||
.. _Uniform Resource Identifier: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
|
||||
|
||||
Resource prefix
|
||||
|
||||
Resources are identified by prefixes in their name. The chosen prefix should have a valid `Uniform Resource
|
||||
Identifier`_ (URI) scheme syntax. Resource names should also have a valid URI syntax, however this isn't enforced. A
|
||||
resource name with the syntax ``{prefix}:{filename}`` will match a provider using the scheme ``prefix``. For
|
||||
instance, a resource provider accessing assets via the Internet might use ``http`` as its scheme. In this case a
|
||||
resource with the name ``http://www.example.com/myasset.obj`` would match against this resource provider. Schemes are
|
||||
case-insensitive so that ``HTTP://www.example.com/myasset.obj`` will also match. Note the importance of the colon.
|
||||
URI syntax requires that a colon follows the prefix in a resource name in order to match against a scheme. For example
|
||||
``https://www.example.com/myasset.obj`` would NOT be a match since the scheme is designated as ``https``.
|
||||
|
||||
Callbacks
|
||||
There are three callbacks that a resource provider is required to implement: :ref:`open<mjfOpenResource>`,
|
||||
:ref:`read<mjfReadResource>`, and :ref:`close<mjfCloseResource>`. A fourth callback :ref:`getdir<mjfGetResourceDir>`
|
||||
which is optional. More details on these callbacks are given below.
|
||||
|
||||
Data Pointer
|
||||
Lastly, there's an opaque data pointer for the provider to pass data into the callbacks. This data pointer is constant
|
||||
within a given model.
|
||||
|
||||
Resource providers work via callbacks:
|
||||
|
||||
- :ref:`mjfOpenResource<mjfOpenResource>`: The open callback takes a single parameter of type :ref:`mjResource`. The
|
||||
name field of the resource should be used to verify that the resource exists and populate the resource data field with
|
||||
any extra information needed for the resource. On failure this callback should return 0 (false) or else 1 (true).
|
||||
- :ref:`mjfReadResource<mjfReadResource>`: The read callback takes as arguments a :ref:`mjResource` and a pointer to a
|
||||
void pointer called the ``buffer``. The read callback should point the ``buffer`` pointer to the location of where the
|
||||
bytes of the resource can be read and return the number of bytes pointed to in the ``buffer``. On failure, this
|
||||
callback should return -1.
|
||||
- :ref:`mjfCloseResource<mjfCloseResource>`: This callback takes a single parameter of type :ref:`mjResource`, and
|
||||
should be used to free any memory allocated in the data field in the supplied resource.
|
||||
- :ref:`mjfGetResourceDir<mjfGetResourceDir>`: This callback is optional and is used to extract the directory from a
|
||||
resource name. For example, the resource name ``http://www.example.com/myasset.obj`` would have
|
||||
``http://www.example.com/`` as its directory.
|
||||
.. _exProviderUsage:
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
When a resource provider is registered, it can be used immediately to open assets. If the asset filename has a prefix
|
||||
that matches with the prefix of a registered provider, then that provider will be used to load the asset.
|
||||
|
||||
.. _exProviderExample:
|
||||
|
||||
Example
|
||||
"""""""
|
||||
|
||||
.. _data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme
|
||||
|
||||
This section provides a basic example of a resource provider that reads from a `data URI scheme`_. First we implement
|
||||
the callbacks:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int data_open_callback(mjResource* resource) {
|
||||
// call some util function to validate
|
||||
if (!is_valid_data_uri(resource->name)) {
|
||||
return 0; // return failure
|
||||
}
|
||||
|
||||
// some upper bound for the data
|
||||
resource->data = mju_malloc(get_data_uri_size(resource->name));
|
||||
if (resource->data == NULL) {
|
||||
return 0; // return failure
|
||||
}
|
||||
|
||||
// fill data from string (some util function)
|
||||
get_data_uri(resource->name, &data);
|
||||
}
|
||||
|
||||
int str_read_callback(mjResource* resource, const void** buffer) {
|
||||
*buffer = resource->data;
|
||||
return get_data_uri_size(resource->name);
|
||||
}
|
||||
|
||||
void str_close_callback(mjResource* resource) {
|
||||
mju_free(resource->data);
|
||||
}
|
||||
|
||||
Next we create the resource provider and register it with MuJoCo:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
mjpResourceProvider resourceProvider = {
|
||||
.prefix = "data",
|
||||
.open = str_open_callback,
|
||||
.read = str_read_callback,
|
||||
.close = str_close_callback,
|
||||
.getdir = NULL
|
||||
};
|
||||
|
||||
// return positive number on success
|
||||
if (!mjp_registerResourceProvider(&resourceProvider)) {
|
||||
// ...
|
||||
// return failure
|
||||
}
|
||||
|
||||
Now we can write assets as strings in our MJCF files:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<asset>
|
||||
<texture name="grid" file="grid.png" type="2d"/>
|
||||
<mesh file="data:model/obj;base65,I215IG9iamVjdA0KdiAxIDAgMA0KdiAwIDEgMA0KdiAwIDAgMQ=="/>
|
||||
...
|
||||
</asset>
|
||||
|
||||
Reference in New Issue
Block a user