Commit Graph

46 Commits

Author SHA1 Message Date
Yuval Tassa 0ce8f7b06b Replace functionally opaque Viscous Pause with functionally transparent "Viscous posing mode" toggle.
PiperOrigin-RevId: 947527204
Change-Id: I122a9730fa22ac9e8809762046a89fb0a774d827
2026-07-14 01:50:13 -07:00
Google DeepMind fbf031a7d5 Replace functionally opaque Viscous Pause with functionally transparent "Viscous posing mode" toggle.
PiperOrigin-RevId: 946298154
Change-Id: Ia06dd6346ac1002000f2d0b1cf9498ffb0d5f8bd
2026-07-11 13:47:48 -07:00
Yuval Tassa 724a6c6623 Replace functionally opaque Viscous Pause with functionally transparent "Viscous posing mode" toggle.
PiperOrigin-RevId: 946286636
Change-Id: I3e542b12bb57c67f3f194d7bcfdffe39de4f2b94
2026-07-11 13:00:59 -07:00
Matija Kecman ee28b334ef Add a Studio example for rendering time-delayed ghost overlays.
This example demonstrates how to use Studio's `extra_geoms` feature to render semi-transparent, time-delayed copies of the model's geoms, creating a "ghost" effect.

PiperOrigin-RevId: 943672439
Change-Id: I8ae640672945b55dd25dd3d444f52d0b2fa7f0f8
2026-07-06 22:25:04 -07:00
Matija Kecman 8079ab3d4d Refactor Viewer to be a base class owning the communication with the simulation, handler registry, core visualization objects and the render function
ViewerApp is simplified, interacting with the endpoint and handlers through the Viewer instance. This change makes it possible to write simulation viewers without using the UI/UX provided by ViewerApp (which should be renamed StudioApp)

PiperOrigin-RevId: 943642660
Change-Id: Id8eb3d4e6a27ceda93833367fec4699fa6bc838e
2026-07-06 20:50:29 -07:00
Matija Kecman 4cb14bef47 Resolve string-based type annotations in message handlers.
When `from __future__ import annotations` is active or forward references are used as strings, type annotations are not directly class objects. This change uses `get_type_hints` to resolve these string annotations to their actual types, ensuring correct validation of message handler signatures.

PiperOrigin-RevId: 942608060
Change-Id: Ic2b214ee85e835616cc3a18ec2699eba6deebb6a
2026-07-04 16:03:26 -07:00
Matija Kecman bdc9e9cce3 Fix bug where backspace intended for an imgui widget reset the environment
PiperOrigin-RevId: 942496281
Change-Id: I8c5d315d22a7c01dbe69f19833964f25141e9663
2026-07-04 07:40:27 -07:00
Matija Kecman 7c0d527005 Support extra_geoms argument
PiperOrigin-RevId: 942283363
Change-Id: I7e0c3aa845c0d2ae1c4390fd5cc01d6ff2741720
2026-07-03 16:39:22 -07:00
Matija Kecman 16f2276fe2 Increase priority of ViewerApp ModelEvent handler
PiperOrigin-RevId: 942274710
Change-Id: Ib894420e2d8f1e57a1da2d953c944316a1ff42ae
2026-07-03 16:02:14 -07:00
Haroon Qureshi 4ecfe5c1f3 Add FontGlobalScale binding.
PiperOrigin-RevId: 942113414
Change-Id: Id87ce552e717d118574befd00dac65ca71e3ba0d
2026-07-03 06:24:40 -07:00
Matija Kecman 0dfa4b509a Refactor Studio customization and message dispatch to use decorator-based handlers
This change replaces fixed callback protocols (e.g., ViewerGuiHook, ViewerUpdateHook, SimEventHandler) with a general-purpose, priority-based message and event handling mechanism.

Key changes:
- Handler decorator and registry: Introduced the `@messages.handler(priority=...)` decorator and `HandlerRegistry` (`handler_registry.py`). Methods marked as handlers are automatically discovered and dispatched by priority (CRITICAL, USER, LIBRARY, INTERNAL) or method resolution order.
- Local lifecycle events: Added `ViewerAppInitEvent`, `BuildGuiEvent`, and `UpdateEvent` to `messages.py`. Custom GUI rendering and per-frame update logic can now be implemented as standard event handlers without needing separate interface protocols.
- Streamlined launch and app APIs: Replaced individual hook and handler arguments in `launch_passive`, `ViewerApp`, and `ViewerHandle` with unified `viewer_handlers` and `sim_handlers` lists.
- Module restructuring: Extracted simulation-side message handling and `ViewerHandle` from `sim_app.py` into a dedicated `viewer_handle.py` module, removing `sim_app.py`.
- Sample updates: Migrated existing examples (such as `implot.py`) to use the new handler pattern and lifecycle events.

PiperOrigin-RevId: 941729322
Change-Id: I93e7c0edf0a13a8dc854f9e2083451f7c25a1825
2026-07-02 09:14:41 -07:00
Haroon Qureshi 1ca64b441b Add binding for DockSpaceOverMainViewport.
PiperOrigin-RevId: 941727670
Change-Id: Idfecadf5a44b237f8c72493a7294bddfcd948ae5
2026-07-02 09:09:51 -07:00
Matija Kecman 6e8a79c657 Refactor Studio implot sample to use a new message passing and launch APIs
Deleted async examples since they add noise and are not particularly useful

PiperOrigin-RevId: 941117641
Change-Id: I4f621801f652e0b410a7acf905cda58143dc3fb0
2026-07-01 08:42:30 -07:00
Saran Tunyasuvunakool a07ae6f849 Make MuJoCo Python bindings compatible with free-threading.
Introduce a new header `gil.h` defining `MutexLockIfGilDisabled` to support thread-safety in both standard and free-threaded CPython builds.

Protect critical shared states and registries:
- Guard global Python callback pointers in `callbacks.cc` using a mutex. Move `gil_scoped_acquire` into local blocks around refcount modifications to prevent `longjmp` from bypassing destructors.
- Protect raw pointer maps in `structs_wrappers.cc` with static mutexes.
- Replace TOCTOU race in `mjcb_time` initialization with thread-safe `std::call_once`.
- Add synchronization to lazy indexer array cache initialization in `indexers.cc` and `indexer_xmacro.h`.
- Protect vector mutations in `StructListBase::PopulateUpTo` in `structs.h` with a mutex.
- Revert unnecessary atomic changes to threadpool counters.
- Declare free-threading compatibility by passing `pybind11::mod_gil_not_used()` to all extension modules.

Fixes #3259
Fixes #3256
Fixes #2978

PiperOrigin-RevId: 941101502
Change-Id: Iec4ce58afcbc75d4b0be6a9a21fc8a47854242e3
2026-07-01 08:08:42 -07:00
Matija Kecman cab191755a Add MuJoCo Studio threaded/passive launch function
PiperOrigin-RevId: 941043766
Change-Id: I5b75d0a2b183d402e8ce221883c2734255e87f0f
2026-07-01 05:50:32 -07:00
Matija Kecman f73e1b6865 Add sim_app.py and viewer_app.py to Studio.
- `sim_app.py` provides a SimEventHook and a Handle class for the simulation process to interact with the viewer, including sending state snapshots and processing viewer events.

- `viewer_app.py` implements the main viewer application logic, handling user input, building the Dear ImGui GUI, and managing communication with the simulation process. It also includes hooks for custom viewer behavior.

PiperOrigin-RevId: 940994701
Change-Id: I82786872cd885b15454843b3a4d1160ff0b4be2b
2026-07-01 03:50:55 -07:00
Matija Kecman a1b0d2c933 Add a Viewer-to-Sim Snapshot channel and convert relevant messages.
The ViewerEndpoint can now send Snapshot messages to the SimEndpoint. The SimEndpoint has a new method, `get_viewer_snapshots`, to retrieve these. Thsi channel will be used for UI state needed for the simulation (e.g., `MjOption` and `StepControl`).

PiperOrigin-RevId: 940981799
Change-Id: Ib9bd6ad848cd5479bc49492a34fddd82569cb09f
2026-07-01 03:21:17 -07:00
Matija Kecman 58d6910afa Refactor StepControl and GUI to return change status.
StepControl methods SetSpeed, SetNoiseParameters, and SetPauseState now return a boolean indicating whether the state was actually changed. The GUI functions NoiseGui and StepControlGui also return a boolean reflecting if any parameters were modified. Noise parameters are now directly managed by StepControl rather than being stored in UxState. The StepControlEvent message has been expanded to include all step control parameters. Keyboard event handling has been slightly refactored to better align with event-based updates.

PiperOrigin-RevId: 940656342
Change-Id: I3701623a2fdcfc4c084b5db0ae19048669040de4
2026-06-30 14:21:00 -07:00
Matija Kecman f4b2f76def Updates NativeViewer instantiations in sample scripts to pass a ViewerConfig object
PiperOrigin-RevId: 940654165
Change-Id: I984cb296593e992dd0d99ca44b43c54de4c3e96d
2026-06-30 14:17:02 -07:00
Matija Kecman 3a623aaf33 Internal change.
PiperOrigin-RevId: 940601733
Change-Id: I83855569f85012173c3edf167eca78d236f6cdea
2026-06-30 12:38:11 -07:00
Haroon Qureshi e2d7955437 Enable status bar by default for python studio.
PiperOrigin-RevId: 940557724
Change-Id: I0a4c96a53a0bcfcb5677515705c874d12bfd300d
2026-06-30 11:18:24 -07:00
Matija Kecman 7a84022092 Add ImGui bindings for Docking and window size constraints
PiperOrigin-RevId: 940470346
Change-Id: I731eedd0bd04afbd0c526ed8b27e6fb804596d20
2026-06-30 08:32:46 -07:00
Matija Kecman e0bb2b0665 Introduce message and endpoint abstractions for MuJoCo Studio communication.
-   `messages.py`: Defines base classes for `Message`, `Snapshot`, and `Event`, along with `SnapshotChannel` and `EventChannel` protocols. It also includes concrete message types for state, reset, model, perturbation, pause state, and exit events.
-   `endpoints.py`: Provides `ViewerEndpoint` and `SimEndpoint` classes to manage message routing between the simulation and the viewer via the defined channels. A `make_endpoints` function is included to create both endpoints.

PiperOrigin-RevId: 939659912
Change-Id: I61a52a7d25431bc4ed38a184813882145eb421d1
2026-06-29 00:24:15 -07:00
Matija Kecman f594778813 Refactor viewer initialization and protocol.
Introduced a ViewerConfig dataclass to encapsulate common viewer window parameters. The NativeViewer now accepts a ViewerConfig and no longer requires a model at initialization. The Viewer protocol has been updated to include a close method (renamed from stop) and an upload_image method. Added checks for None models/data in studio event handling.

PiperOrigin-RevId: 939631378
Change-Id: Ibc07d0e775efa0d79ce5552ee52102e943a9b290
2026-06-28 23:07:02 -07:00
Matija Kecman 38956ed95c Handle None values for model and data in StepControl.advance.
The `StepControl.advance` method now checks if the provided `model` or `data` Python objects are `None` before attempting to cast them to `MjModelWrapper` or `MjDataWrapper`, passing `nullptr` to the underlying C++ function if they are `None`.

This fixes an oversight in the python bindings, C++ code already supported null models.

PiperOrigin-RevId: 937243996
Change-Id: Ie67b8603517e7390fb54bfefbfed79ccf7b2bc5e
2026-06-24 04:18:29 -07:00
Haroon Qureshi 5cef2472d5 Remove custom step_fn for StepControl::Advance.
PiperOrigin-RevId: 936609234
Change-Id: I606cf4d71d856cbd260900d63b22c719974c977d
2026-06-23 05:49:20 -07:00
Yuval Tassa e2528cbd93 Rename "Stats" window to "Info" and remove "Stats" dock.
PiperOrigin-RevId: 936026479
Change-Id: I72e4f2cba6df255d5446faedc81727b39ef735bc
2026-06-22 06:38:03 -07:00
Michael Moss 492585ca7a Enable MuJoCo Studio build and packaging on Windows.
Also:
- Patched Filament to support building with Clang, so the default MuJoCo build
  mode doesn't need to change. This should probably be upstreamed.
- Added missing Windows deps to MuJoCo Platform CMake config.
- Updated Studio CMake config to fix unresolved symbols issues on Windows.
PiperOrigin-RevId: 934612701
Change-Id: I3a34a5d274e1452c9cfef0e2868f2788b4b0c7e8
2026-06-18 16:50:31 -07:00
Michael Moss e7ef6528b7 Enable MuJoCo Studio build and packaging on macos.
Also:
- Packages MuJoCo Studio as MuJoCoStudio.app in the MuJoCo.dmg.
- Fixes a Filament compile issue.
- Patches libwebp to fix compile error related to universal builds and forces
  it to build as static.
- Removes the separate, obsolete "build_studio" step.
PiperOrigin-RevId: 934564785
Change-Id: I50c83283b5e138062e37d53926a5a77fdf99dbfa
2026-06-18 15:03:20 -07:00
Michael Moss 8db92ab4a9 Enable building Studio (Linux only) as a component of the main MuJoCo build.
And remove the separate, conditional (and hacky) "build_studio" step.

PiperOrigin-RevId: 934375150
Change-Id: I46514d0f33c17bb29625b818cdde3a285fd2c439
2026-06-18 08:44:16 -07:00
Matija Kecman 81bc303a8f Add an async example using multi threading
PiperOrigin-RevId: 932400523
Change-Id: I6649dfd3a657ce11b7dc6cf130f01be8a85a095c
2026-06-15 05:34:08 -07:00
Matija Kecman 7c22920720 Improve async example and remove Network demo code
- Move SimToView and ViewToSim dataclasses from async.py to viewer_protocol.py (adding a user_data field) to consolidate IPC protocol definitions.
  - Remove the simulated Network class and latency UI controls from async.py to simplify the example and focus on core multiprocessing communication.
  - Use parser.parse() in main() for cleaner and more direct MuJoCo model loading.
  - Add cancel_join_thread() to multiprocessing queues and a join timeout to prevent atexit handlers from blocking during process shutdown.

PiperOrigin-RevId: 932327625
Change-Id: If91777dba934814b3f9faa17f9055869920575d7
2026-06-15 02:31:07 -07:00
Michael Moss 4bb02e299d Resolve Studio assets path dynamically.
PiperOrigin-RevId: 931162732
Change-Id: Ib44a74790facfa797ca2c4f107edb0062a89c117
2026-06-12 08:26:24 -07:00
Matija Kecman 37084a5c0b Release GIL in MuJoCo Studio Python bindings.
This change adds py::gil_scoped_release to various functions in the parser, renderer, sim and ux modules of the MuJoCo Studio Python bindings. This allows other Python threads to execute while these C++ functions, which can sometimes be time-consuming, are running. The two heaviest operations Present() (rendering) and Advance() (physics) now both release the GIL in C++.

PiperOrigin-RevId: 930645361
Change-Id: Ib239fb54edc7ac0d8b1d94bec8c57a447d5f4d27
2026-06-11 11:32:09 -07:00
Michael Moss ab17ff5552 Add Python Studio CMake configs and integrate into python build and packaging
PiperOrigin-RevId: 930532579
Change-Id: I2c4b51664475cc8fba92d70d072528843aa03f0c
2026-06-11 08:03:44 -07:00
Michael Moss 41ac783d3a Add ImGui context sharing for UI rendering in Python MuJoCo Studio
PiperOrigin-RevId: 930507935
Change-Id: I7615931f9a71793b049e8b6b442be6a2d726f0b2
2026-06-11 07:10:41 -07:00
Michael Moss 684eccc146 Removed unused constexpr variables in ImPlot Python bindings
PiperOrigin-RevId: 930500399
Change-Id: I95bc9c4b580700d75a48d0784d611913956c0431
2026-06-11 06:53:10 -07:00
Michael Moss fbdf8a6215 Add Copybara rule to transform header paths under experimental.
PiperOrigin-RevId: 930498813
Change-Id: I18d4cdad18cd1f2e23c8ba48ebf2d2e5a3b54168
2026-06-11 06:49:08 -07:00
Matija Kecman 018fbc3223 Release GIL in native viewer.
Adds py::gil_scoped_release no_gil; to mujoco::studio::Viewer methods to release the Python GIL during C++ execution.

PiperOrigin-RevId: 930482271
Change-Id: I590794109418516ec5d9e8b536085560a1d36314
2026-06-11 06:13:45 -07:00
Matija Kecman d068c96d00 Expose ImGuiInputTextFlags_WordWrap to Python.
PiperOrigin-RevId: 930466666
Change-Id: Ic0d5bb39125c3a3986fe28f09d5ba8776c7fc2c7
2026-06-11 05:33:23 -07:00
Matija Kecman edbe6a6f74 Fix memory and resource leaks in failing resource provider open callbacks
When an mjpResourceProvider's open callback returns 0 (failure), MuJoCo does
not invoke the corresponding close callback. Previously, several resource
provider implementations allocated heap memory or system file handles before
encountering an error, failing to clean them up before returning 0. This change addresses these leaks across the codebase and clarifies the API contract.

PiperOrigin-RevId: 929803942
Change-Id: Ib7344033726895cdf037a8d9356ffc183c78c2d3
2026-06-10 06:08:17 -07:00
Matija Kecman 4be41d7b0b Add graphics modes list to viewer protocol
PiperOrigin-RevId: 929157105
Change-Id: I75586c37bc94666800f7822654225bad0717e51c
2026-06-09 06:29:04 -07:00
Matija Kecman 66c0131840 Internal change
PiperOrigin-RevId: 928689775
Change-Id: Idfbbafe44b74acf36ff82a72eabf026d4226d47c
2026-06-08 11:50:55 -07:00
Matija Kecman 49211a05c5 Add support for custom physics step functions in StudioApp.
This change allows users to provide an optional `step_fn` callable to `StudioApp.update` and `StudioApp.update_from_viewer`. When provided, this function is called to advance the physics simulation instead of the default `step_control.advance`.

PiperOrigin-RevId: 925439890
Change-Id: Ia833503f6dd0c22fb8d75af6c5f06757496853e5
2026-06-02 10:27:52 -07:00
Matija Kecman 0e4749501c Allow custom step function in StepControl::Advance.
The StepControl::Advance method now accepts an optional std::function to be used instead of mj_step. This allows for custom simulation logic to be executed within the stepping loop. The Python bindings for StepControl::advance have been updated to support passing a Python callable as the custom step function.

PiperOrigin-RevId: 925393132
Change-Id: Id2820c4b55cbdfee6b01adc2395e99a990d4e7a3
2026-06-02 09:20:06 -07:00
Matija Kecman 4cf4a5665d Configure Copybara export for Dear ImGui and ImPlot Python bindings
Following the export declarations in Dear ImGui and ImPlot METADATA, this change updates MuJoCo's Copybara configuration (copy.bara.sky) to export and transform the Python bindings. `//third_party/dear_imgui/google/py` exports to `python/mujoco/experimental/dear_imgui` and `//third_party/implot/google/py` exports to  `python/mujoco/experimental/implot`.

PiperOrigin-RevId: 925293624
Change-Id: Ie6e32d247a6f7fc24bb36ae7060f2075d8efeb26
2026-06-02 05:32:22 -07:00