Allow user-defined visualization geoms to be added to the passive viewer.

Fixes #1023, #1082

PiperOrigin-RevId: 572303635
Change-Id: Ia8399f816f311b38a7b137f5bd4f359f77a1da1c
This commit is contained in:
Saran Tunyasuvunakool
2023-10-10 10:51:29 -07:00
committed by Copybara-Service
parent 1bd6c94e6d
commit 2e15574b58
13 changed files with 112 additions and 56 deletions
+35 -5
View File
@@ -96,13 +96,13 @@ perturbations will not work unless the user explicitly synchronizes incoming eve
The ``launch_passive`` function returns a handle which can be used to interact with the viewer. It has the following
attributes:
- ``scn``, ``cam``, ``opt``, and ``pert`` properties: correspond to :ref:`mjvScene`, :ref:`mjvCamera`,
:ref:`mjvOption`, and :ref:`mjvPerturb` structs, respectively.
- ``cam``, ``opt``, and ``pert`` properties: correspond to :ref:`mjvCamera`, :ref:`mjvOption`, and :ref:`mjvPerturb`
structs, respectively.
- ``lock()``: provides a mutex lock for the viewer as a context manager. Since the viewer operates its own
thread, user code must ensure that it is holding the viewer lock before modifying any physics or visualization
state. These include the ``mjModel`` and ``mjData`` instance passed to ``launch_passive``, and also the ``scn``,
``cam``, ``opt``, and ``pert`` properties of the viewer handle.
state. These include the ``mjModel`` and ``mjData`` instance passed to ``launch_passive``, and also the ``cam``,
``opt``, and ``pert`` properties of the viewer handle.
- ``sync()``: synchronizes state between ``mjModel``, ``mjData``, and GUI user inputs since the previous call to
``sync``. In order to allow user scripts to make arbitrary modifications to ``mjModel`` and ``mjData`` without
@@ -124,6 +124,37 @@ attributes:
- ``is_running()``: returns ``True`` if the viewer window is running and ``False`` if it is closed.
This method can be safely called without locking.
- ``user_scn``: an :ref:`mjvScene` object that allows users to add custom visualization geoms to the rendered scene.
This is separate from the ``mjvScene`` that the viewer uses internally to render the final scene, and is entirely
under the user's control. User scripts can call e.g. :ref:`mjv_initGeom` or :ref:`mjv_makeConnector` to add
visualization geoms to ``user_scn``, and upon the next call to ``sync()``, the viewer will incorporate
these geoms to future rendered images. For example:
.. code-block:: python
with mujoco.viewer.launch_passive(m, d, key_callback=key_callback) as viewer:
while viewer.is_running():
...
# Step the physics.
mujoco.mj_step(m, d)
# Add a 3x3x3 grid of variously colored spheres to the middle of the scene.
viewer.user_scn.ngeom = 0
i = 0
for x, y, z in itertools.product(*((range(-1, 2),) * 3)):
mujoco.mjv_initGeom(
viewer.user_scn.geoms[i],
type=mujoco.mjtGeom.mjGEOM_SPHERE,
size=[0.02, 0, 0],
pos=0.1*np.array([x, y, z]),
mat=np.eye(3).flatten(),
rgba=0.5*np.array([x + 1, y + 1, z + 1, 2])
)
i += 1
viewer.user_scn.ngeom = i
viewer.sync()
...
The viewer handle can also be used as a context manager which calls ``close()`` automatically upon exit. A minimal
example of a user script that uses ``launch_passive`` might look like the following. (Note that example is a simple
illustrative example that does **not** necessarily keep the physics ticking at the correct wallclock rate.)
@@ -183,7 +214,6 @@ pause or resume the run loop when the spacebar is pressed.
viewer.sync()
...
.. _PyUsage:
Basic usage