Commit Graph

62 Commits

Author SHA1 Message Date
Yuval Tassa c232938233 Move the Simulation panel into the platform toolkit.
PiperOrigin-RevId: 965914672
Change-Id: Ib349b77055c57453780818dd4d8f48899b7024d5
2026-08-17 05:40:26 -07:00
Yuval Tassa 11fa4a5b45 Remove the redundant phong_2d reflection material
PiperOrigin-RevId: 965538926
Change-Id: I02a99016d5e69130e3827e898343b656f399ddfb
2026-08-16 07:56:51 -07:00
Matija Kecman fca913b4f5 Optimize and robustify asset prefetching and material loading.
- Parallelize asset prefetching (max 4 workers) with retry logic and on-screen error banner, replacing silent failures and cryptic WASM out-of-bounds crashes with explicit missing-file errors.
- Support binary Uint8Array/ArrayBuffer in C++ asset registry via typed_memory_view, preventing Embind string coercion from corrupting binary shader packages into ASCII text.
- Automatically glob .mat files in CMake instead of maintaining a manual list.
- Add missing reflection materials to prefetch arrays.
- Disable caching for index.html in web server so template/script updates apply on normal page reload without stale cache issues, the file is small so caching had a negligible upside.
- Add null resource and payload validation in ObjectManager::LoadMaterial before constructing Filament materials.

PiperOrigin-RevId: 963364509
Change-Id: I7de79df6a5cede4e54683415ee193f1c5a665286
2026-08-12 04:38:35 -07:00
Matija Kecman f1c8d3a58f Renamed the notion of handler classes to plugin classes in the Studio Python API
This change refactors the Python API to use the term "plugins" instead of "handlers" for classes containing decorated handler methods. The term handler is still used for an annotated method of a plugin class that handles a specific message type. Also improved some documentation.

PiperOrigin-RevId: 962150099
Change-Id: I34a8cc410cd784b088605490cfa3baccea5c9e71
2026-08-10 07:50:36 -07:00
Hana Joo 0aad65868d suppress pyrefly errors in mujoco
Startblock:
  * // Put other blockers before this line to avoid churning.
  * has lgtm
  * is approved
  * and then
  * all comments are resolved
  * and then
PiperOrigin-RevId: 961854282
Change-Id: I9d323a8ef9f36ffe69cc62d449849eac82dc6858
2026-08-09 15:45:36 -07:00
Haroon Qureshi 63b779042c Split Renderer class into explicit "classic" and "filament" classes.
PiperOrigin-RevId: 960272089
Change-Id: I9494472b7b8e838a75beaf0cd68e5ce4b42a80a4
2026-08-06 06:52:37 -07:00
Matija Kecman 84950fa371 MuJoCo Web Viewer: Implement parallel chunked model downloading and in-place model reloading.
This change introduces parallel chunked downloading for large model files (.mjb) directly into WASM linear memory, enables model loading without full page reloads and reduces memory overhead.

Key changes:
- Implement a chunked model endpoint in the Python web server to support range requests.
- Add parallel chunked fetching in the frontend with retry logic and a single-fetch fallback.
- Increase initial WASM memory to 3 GB to accommodate large models and prevent heap fragmentation.
- Support in-place model reloading in the C++ client, including texture cache invalidation when the Filament context is recreated.
- Display a model download progress bar and model parsing/loading banner to the UI.
- Fixes model drag and drop (caused by typo in sessionId, corrected to session_id).

PiperOrigin-RevId: 960249236
Change-Id: Icac89e6a4ca099882aaf9b111744c1b6ab0cc6c1
2026-08-06 05:51:43 -07:00
Matija Kecman b3ef7a8c2f Simplify MuJoCo Studio viewer selection and unify model flags.
This change removes the ViewerMode enum and instead infers whether to launch the Web Viewer or Native Viewer based on the graphics mode (gfx) setting. Specifically, setting gfx to "web" or "webgl" will now launch the Web Viewer (in future "webgpu" would also launch the Web Viewer).

Additionally, this unifies command-line flags across studio scripts and samples by replacing the --mjcf flag with --model (with positional argument fallback) and standardizing absl flags usage. --model is a better name since formats like .mjz and .mjb are also supported by this argument.

PiperOrigin-RevId: 959058940
Change-Id: If4e0ace664ddc6e45cb681d168679148e8c4901d
2026-08-04 09:14:07 -07:00
Saran Tunyasuvunakool b0c3486249 Tweak URL printout in terminal when launching the web viewer.
PiperOrigin-RevId: 958422471
Change-Id: I2d637c615015915eb01b65bb0bad22749886a372
2026-08-03 09:41:25 -07:00
Matija Kecman b389b28b87 Support parsing .mjz files in the Studio parser module
PiperOrigin-RevId: 957616406
Change-Id: I582d23039b4aec745e0525392c062102f4d9ae25
2026-08-01 06:47:01 -07:00
Matija Kecman 0ca53dacf8 Update SDL2 copybara transformations
PiperOrigin-RevId: 957294480
Change-Id: Ied7131cafe83b11379e275ab4287609674251db5
2026-07-31 13:04:33 -07:00
Matija Kecman 6c78c98418 MuJoCo Web Viewer: update code to support the web viewer
PiperOrigin-RevId: 957147035
Change-Id: Ibe5d68b2654a7faac23c297d4f492929209c078d
2026-07-31 08:09:38 -07:00
Matija Kecman a1e90c24b3 MuJoCo Web Viewer: top-level web_viewer.py component
PiperOrigin-RevId: 957119030
Change-Id: If6c8265dfa62f9a6378898644935ee335f3fa8b2
2026-07-31 08:09:05 -07:00
Matija Kecman f8344301e9 MuJoCo Web Viewer: server component
PiperOrigin-RevId: 957086932
Change-Id: Idcac876206a2df7e962481c12c2fc74ff9997948
2026-07-31 08:08:32 -07:00
Matija Kecman f1f52a92b8 Add headless EGL/OSMesa OpenGL UI context rendering for web viewer
PiperOrigin-RevId: 957060514
Change-Id: I8a0df22255c5a938d18e172c638a8c83dfe64b1b
2026-07-31 04:36:14 -07:00
Matija Kecman 4dd70d2367 MuJoCo Web Viewer: add web client containing code that runs in the browser
PiperOrigin-RevId: 956698568
Change-Id: Ia4bebcb25b488d255994018da03e9115187b890c
2026-07-30 13:17:48 -07:00
Haroon Qureshi e662350357 Simple window class for python.
PiperOrigin-RevId: 956544312
Change-Id: I52d0e2f555592bed3889f05a1406e7633eb6d468
2026-07-30 08:39:09 -07:00
Matija Kecman c2e95b4161 Add StatePayload and serialization helpers for web viewer
PiperOrigin-RevId: 956400340
Change-Id: Ibe049afe10eca85e5fb6d718a78863a641b864bb
2026-07-30 03:01:23 -07:00
Matija Kecman e4d0a88ffd Refactor viewer loop and shutdown handling to support conditional rendering and clean exits.
This change introduces a get_frame method to the viewer protocol, replacing the previous is_running check. This allows the viewer loop to skip rendering and lifecycle events when no active frame is ready (for example, when no browser is connected to the web viewer).

Additionally, this change:
- Adds a shutdown hook to ViewerHandle to wait for the viewer to cleanly release resources before exiting.
- Implements an ExitEvent handler in the viewer protocol to stop the run loop.
- Adds an http_port configuration option for the web viewer.
- Prevents double-closing in the viewer.

PiperOrigin-RevId: 954603868
Change-Id: Iaba7d131dc94191de51150464514dd10fa7834b0
2026-07-27 06:55:17 -07:00
Matija Kecman 91d78346e1 Replace the Studio parser module with a pure Python implementation
PiperOrigin-RevId: 953181335
Change-Id: I1d2ce6f27f50aa4c30cce6d43caed80186ddef42
2026-07-23 23:52:56 -07:00
Matija Kecman e0224c6440 studio: share ImGui and ImPlot contexts across python child extension modules.
Each pybind extension module holds its own copy of the ImGui/ImPlot globals (extension modules are loaded RTLD_LOCAL), so the viewer that owns the contexts must share the pointers explicitly. Without this, client plotting GUIs and user plotting scripts (e.g. the implot sample) crash on null context pointers.

PiperOrigin-RevId: 951917287
Change-Id: I639a173c2ae9f1af4feaf57aff7b5c81854b7393
2026-07-21 23:41:20 -07:00
Matija Kecman 8196ca17f8 studio: catch KeyboardInterrupt in samples and format imports.
* Adds exception handler block to simulator samples to allow clean Ctrl+C exits.
* Formats import statements inside code generator validator.

PiperOrigin-RevId: 950821976
Change-Id: I283533d87619d5d9b54d9bec970cdefe538fd752
2026-07-20 07:20:07 -07:00
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
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
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
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 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