@@ -8,17 +8,22 @@ Web-based MuJoCo viewer built on [Viser](https://github.com/nerfstudio-project/v
88
99## Features
1010
11- - ** Interactive simulation** — play, pause, step, reset, and speed control from the browser
1211- ** All primitive geom types** — box, sphere, cylinder, capsule, ellipsoid, and mesh
12+ - ** Textures** — PBR materials, per-face-vertex UV mapping, STL double-sided rendering
1313- ** Two API modes** — built-in simulation loop or user-controlled sync
1414- ** Extensible panels** — add custom GUI panels for sensors, cameras, controls, etc.
15+ - ** Sensor plots** — built-in ` SensorPanel ` with real-time scrolling time series (uPlot)
16+ - ** HUD overlay** — fixed-positioned status text over the 3D viewport
17+ - ** Click-to-select** — click any geom to show its body name; label follows the object
18+ - ** Visibility groups** — toggle MuJoCo geom groups on/off
19+ - ** Granular GUI control** — show/hide simulation controls and visibility panel independently
1520- ** Multi-client** — multiple browser tabs viewing the same simulation
1621- ** Beautiful rendering** — three-point lighting, proper materials, transparency support
1722
1823## Installation
1924
2025``` bash
21- git clone https://github.com/siddhss5 /mj_viser.git
26+ git clone https://github.com/personalrobotics /mj_viser.git
2227cd mj_viser
2328pip install -e .
2429```
@@ -56,28 +61,66 @@ while viewer.is_running():
5661 viewer.sync()
5762```
5863
64+ ### Sensor plots
65+
66+ ``` python
67+ from mj_viser import MujocoViewer, SensorPanel, SensorChannel
68+
69+ viewer = MujocoViewer(model, data)
70+ viewer.add_panel(SensorPanel(
71+ title = " Wrist F/T" ,
72+ channels = [
73+ SensorChannel(0 , " Fx" , " #e74c3c" ),
74+ SensorChannel(1 , " Fy" , " #2ecc71" ),
75+ SensorChannel(2 , " Fz" , " #3498db" ),
76+ ],
77+ window_seconds = 5.0 ,
78+ ))
79+ viewer.launch()
80+ ```
81+
82+ ### HUD overlay
83+
84+ ``` python
85+ viewer.set_hud(" status" , " L: [13N] can_0 | R: — | physics" , " bottom-left" )
86+ ```
87+
88+ ### Click-to-select
89+
90+ ``` python
91+ # Labels appear automatically on click. Register a callback for custom behavior:
92+ viewer.on_select(lambda geom_id , body_name : print (f " Selected: { body_name} " ))
93+ ```
94+
5995### Custom panels
6096
6197``` python
62- import viser
6398from mj_viser import MujocoViewer, PanelBase
99+ import viser
64100
65- class SensorPanel (PanelBase ):
101+ class MyPanel (PanelBase ):
66102 def name (self ) -> str :
67- return " Sensors "
103+ return " My Panel "
68104
69105 def setup (self , gui : viser.GuiApi, viewer : MujocoViewer) -> None :
70106 with gui.add_folder(self .name()):
71- self ._readout = gui.add_text(" Force " , initial_value = " " , disabled = True )
107+ self ._text = gui.add_text(" Status " , initial_value = " " , disabled = True )
72108
73109 def on_sync (self , viewer : MujocoViewer) -> None :
74- self ._readout .value = f " { viewer.data.sensordata[ 0 : 3 ] } "
110+ self ._text .value = f " Time: { viewer.data.time :.2f } "
75111
76112viewer = MujocoViewer(model, data)
77- viewer.add_panel(SensorPanel ())
113+ viewer.add_panel(MyPanel ())
78114viewer.launch()
79115```
80116
117+ ### Granular GUI control
118+
119+ ``` python
120+ # Disable built-in panels for apps that manage their own GUI
121+ viewer = MujocoViewer(model, data, show_sim_controls = False , show_visibility = False )
122+ ```
123+
81124## Examples
82125
83126``` bash
@@ -97,7 +140,7 @@ uv run python examples/custom_panel.py mujoco_menagerie/unitree_g1/scene.xml
97140## Development
98141
99142``` bash
100- git clone https://github.com/siddhss5 /mj_viser.git
143+ git clone https://github.com/personalrobotics /mj_viser.git
101144cd mj_viser
102145uv sync --all-extras
103146uv run pytest
0 commit comments