gpue commited on
Commit
a091821
·
1 Parent(s): 902cc59

Add GPU support with docker-compose.gpu.yml for enhanced performance

Browse files

- Introduced a new docker-compose.gpu.yml file to enable GPU-accelerated rendering using NVIDIA GPUs and the nvidia-container-toolkit.
- Updated environment variables for improved rendering performance, including higher resolution and frame rate settings.
- Enhanced mujoco_server.py to dynamically adjust rendering settings based on the environment (Docker vs. native).
- Updated README.md with instructions for using the new GPU configuration and performance optimization details.

Files changed (5) hide show
  1. Dockerfile +5 -0
  2. README.md +171 -34
  3. docker-compose.gpu.yml +31 -0
  4. docker-compose.yml +15 -0
  5. mujoco_server.py +22 -2
Dockerfile CHANGED
@@ -28,9 +28,14 @@ RUN pip install --no-cache-dir -r requirements.txt
28
  COPY . .
29
 
30
  # Environment variables for headless rendering
 
31
  ENV MUJOCO_GL=osmesa
32
  ENV PYOPENGL_PLATFORM=osmesa
33
 
 
 
 
 
34
  # Expose port
35
  EXPOSE 3004
36
 
 
28
  COPY . .
29
 
30
  # Environment variables for headless rendering
31
+ # Options: osmesa (software, slow), egl (GPU if available), glx (X11 GPU)
32
  ENV MUJOCO_GL=osmesa
33
  ENV PYOPENGL_PLATFORM=osmesa
34
 
35
+ # Performance tuning
36
+ ENV OMP_NUM_THREADS=4
37
+ ENV MKL_NUM_THREADS=4
38
+
39
  # Expose port
40
  EXPOSE 3004
41
 
README.md CHANGED
@@ -11,8 +11,10 @@ A unified MuJoCo-based robot simulation platform with web interface for multiple
11
 
12
  ### Boston Dynamics Spot (Quadruped)
13
  - 12 degrees of freedom (3 per leg)
14
- - Classical trot gait controller
15
- - Diagonal leg pairing locomotion
 
 
16
 
17
  ## Features
18
 
@@ -23,68 +25,203 @@ A unified MuJoCo-based robot simulation platform with web interface for multiple
23
  - Robot switching without restart
24
  - Keyboard and button controls for locomotion
25
 
26
- ## Installation
27
 
28
- ```bash
29
- # Clone the repository
30
- git clone git@github.com:wandelbotsgmbh/nova-sim.git
31
- cd nova-sim
32
 
 
33
  # Install dependencies
34
  pip install mujoco gymnasium flask flask-socketio opencv-python torch numpy
35
 
36
- # Clone MuJoCo Menagerie for Spot model (in parent directory)
37
- cd ..
38
- git clone https://github.com/google-deepmind/mujoco_menagerie.git
 
 
39
 
40
- # For G1 RL policy, clone unitree_rl_gym (in parent directory)
41
- git clone https://github.com/unitreerobotics/unitree_rl_gym.git
42
  ```
43
 
44
- ## Usage
45
 
46
  ```bash
47
- # Start the server
48
- cd nova-sim
49
- python mujoco_server.py
50
 
51
- # Open browser at http://localhost:3004
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  ```
53
 
54
  ## Controls
55
 
56
- - **WASD / Arrow Keys**: Walk forward/backward, turn left/right
57
- - **Q/E**: Strafe left/right
 
 
 
 
58
  - **Mouse drag**: Rotate camera
59
  - **Scroll wheel**: Zoom camera
60
  - **Robot selector**: Switch between G1 and Spot
 
61
 
62
  ## Project Structure
63
 
64
  ```
65
  nova_sim/
66
- ├── mujoco_server.py # Main Flask server with WebSocket
 
 
 
 
67
  ├── robots/
68
- │ ├── g1/ # Unitree G1 humanoid
69
- │ │ ├── g1_env.py # Gymnasium environment
70
- │ │ ├── scene.xml # MuJoCo scene
71
- │ │ ├── g1_29dof.xml # Robot model
72
- │ │ ├── meshes/ # 3D mesh files
73
- │ │ ── controllers/ # G1 controllers
74
- │ │── rl_policy.py # RL walking policy
75
- │ │ ├── pd_standing.py # Standing controller
76
- │ │ ── keyframe.py # Keyframe controller
77
- │ └── spot/ # Boston Dynamics Spot quadruped
78
- ── spot_env.py # Gymnasium environment
79
- ── controllers/ # Spot controllers
80
- ├── trot_gait.py # Trot gait locomotion
81
- └── pd_standing.py # Standing controller
 
 
 
 
82
  └── README.md
83
  ```
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  ## License
86
 
87
  This project uses models from:
88
  - [MuJoCo Menagerie](https://github.com/google-deepmind/mujoco_menagerie) (BSD-3-Clause)
89
  - [unitree_mujoco](https://github.com/unitreerobotics/unitree_mujoco) (BSD-3-Clause)
90
  - [unitree_rl_gym](https://github.com/unitreerobotics/unitree_rl_gym)
 
 
11
 
12
  ### Boston Dynamics Spot (Quadruped)
13
  - 12 degrees of freedom (3 per leg)
14
+ - Multiple gait controllers:
15
+ - **MPC Gait**: Feedback-based balance control with trot pattern (default)
16
+ - **PyMPC Gait**: Uses Quadruped-PyMPC gait generator (requires extra dependencies)
17
+ - **Trot Gait**: Simple open-loop trot pattern
18
 
19
  ## Features
20
 
 
25
  - Robot switching without restart
26
  - Keyboard and button controls for locomotion
27
 
28
+ ## Quick Start
29
 
30
+ ### Native (Recommended for Development)
 
 
 
31
 
32
+ ```bash
33
  # Install dependencies
34
  pip install mujoco gymnasium flask flask-socketio opencv-python torch numpy
35
 
36
+ # Optional: For PyMPC gait controller
37
+ pip install jax jaxlib quadruped-pympc gym-quadruped
38
+
39
+ # Start the server
40
+ python mujoco_server.py
41
 
42
+ # Open browser at http://localhost:3004
 
43
  ```
44
 
45
+ ### Docker
46
 
47
  ```bash
48
+ # Build and run (CPU/software rendering)
49
+ docker-compose up --build
 
50
 
51
+ # Or with docker run
52
+ docker run -p 3004:3004 nova-sim
53
+ ```
54
+
55
+ ## Docker Configuration
56
+
57
+ ### Performance Optimization
58
+
59
+ Docker uses software rendering (OSMesa) which is slower than native GPU rendering. Configure these environment variables to optimize performance:
60
+
61
+ | Variable | Default | Description |
62
+ |----------|---------|-------------|
63
+ | `RENDER_WIDTH` | 640 | Render width in pixels |
64
+ | `RENDER_HEIGHT` | 360 | Render height in pixels |
65
+ | `TARGET_FPS` | 30 | Target frame rate |
66
+ | `SIM_STEPS_PER_FRAME` | 10 | Physics steps per rendered frame |
67
+ | `OMP_NUM_THREADS` | 4 | OpenMP thread count |
68
+ | `MKL_NUM_THREADS` | 4 | MKL thread count |
69
+
70
+ ### docker-compose.yml (CPU - Default)
71
+
72
+ ```yaml
73
+ services:
74
+ nova-sim:
75
+ build: .
76
+ ports:
77
+ - "3004:3004"
78
+ environment:
79
+ - MUJOCO_GL=osmesa
80
+ - PYOPENGL_PLATFORM=osmesa
81
+ - RENDER_WIDTH=640 # Lower resolution for speed
82
+ - RENDER_HEIGHT=360
83
+ - TARGET_FPS=30
84
+ ```
85
+
86
+ ### docker-compose.gpu.yml (NVIDIA GPU)
87
+
88
+ For significantly better performance, use GPU acceleration:
89
+
90
+ ```bash
91
+ # Requires: NVIDIA GPU + nvidia-container-toolkit
92
+ docker-compose -f docker-compose.gpu.yml up
93
+ ```
94
+
95
+ ```yaml
96
+ services:
97
+ nova-sim:
98
+ build: .
99
+ ports:
100
+ - "3004:3004"
101
+ environment:
102
+ - MUJOCO_GL=egl # GPU rendering
103
+ - PYOPENGL_PLATFORM=egl
104
+ - RENDER_WIDTH=1280 # Full resolution
105
+ - RENDER_HEIGHT=720
106
+ - TARGET_FPS=60
107
+ deploy:
108
+ resources:
109
+ reservations:
110
+ devices:
111
+ - driver: nvidia
112
+ count: 1
113
+ capabilities: [gpu]
114
+ ```
115
+
116
+ ### Performance Comparison
117
+
118
+ | Mode | Resolution | Expected FPS | Notes |
119
+ |------|------------|--------------|-------|
120
+ | Native (macOS/Linux) | 1280x720 | 60+ | Best performance |
121
+ | Docker + GPU (EGL) | 1280x720 | 60 | Requires NVIDIA GPU |
122
+ | Docker + CPU (OSMesa) | 640x360 | 15-20 | Slower, but compatible |
123
+ | Docker + CPU (OSMesa) | 320x180 | 30+ | Very low quality |
124
+
125
+ ### Custom Docker Run
126
+
127
+ ```bash
128
+ # Ultra-low resolution for maximum speed
129
+ docker run -p 3004:3004 \
130
+ -e RENDER_WIDTH=320 \
131
+ -e RENDER_HEIGHT=180 \
132
+ -e MUJOCO_GL=osmesa \
133
+ nova-sim
134
+
135
+ # High quality with GPU
136
+ docker run --gpus all -p 3004:3004 \
137
+ -e RENDER_WIDTH=1920 \
138
+ -e RENDER_HEIGHT=1080 \
139
+ -e MUJOCO_GL=egl \
140
+ nova-sim
141
  ```
142
 
143
  ## Controls
144
 
145
+ - **W / Arrow Up**: Walk forward
146
+ - **S / Arrow Down**: Walk backward
147
+ - **A / Arrow Left**: Turn left
148
+ - **D / Arrow Right**: Turn right
149
+ - **Q**: Strafe left
150
+ - **E**: Strafe right
151
  - **Mouse drag**: Rotate camera
152
  - **Scroll wheel**: Zoom camera
153
  - **Robot selector**: Switch between G1 and Spot
154
+ - **Reset button**: Reset robot to standing pose
155
 
156
  ## Project Structure
157
 
158
  ```
159
  nova_sim/
160
+ ├── mujoco_server.py # Main Flask server with WebSocket
161
+ ├── Dockerfile # Docker build configuration
162
+ ├── docker-compose.yml # CPU/OSMesa configuration
163
+ ├── docker-compose.gpu.yml # GPU/EGL configuration
164
+ ├── requirements.txt # Python dependencies
165
  ├── robots/
166
+ │ ├── g1/ # Unitree G1 humanoid
167
+ │ │ ├── g1_env.py # Gymnasium environment
168
+ │ │ ├── scene.xml # MuJoCo scene
169
+ │ │ ├── g1_29dof.xml # Robot model
170
+ │ │ ├── meshes/ # 3D mesh files
171
+ │ │ ── policy/ # RL policy weights
172
+ │ │── controllers/ # G1 controllers
173
+ │ │ ├── rl_policy.py # RL walking policy
174
+ │ │ ── pd_standing.py # Standing controller
175
+ └── keyframe.py # Keyframe controller
176
+ ── spot/ # Boston Dynamics Spot quadruped
177
+ ── spot_env.py # Gymnasium environment
178
+ ├── model/ # MuJoCo model files
179
+ └── controllers/ # Spot controllers
180
+ │ ├── mpc_gait.py # MPC-inspired gait (default)
181
+ │ ├── quadruped_pympc_controller.py # PyMPC gait
182
+ │ ├── trot_gait.py # Simple trot gait
183
+ │ └── pd_standing.py # Standing controller
184
  └── README.md
185
  ```
186
 
187
+ ## Spot Controller Options
188
+
189
+ The Spot robot supports multiple controller types via the `controller_type` parameter:
190
+
191
+ ```python
192
+ from spot_env import SpotEnv
193
+
194
+ # MPC Gait - Feedback-based balance control (default, no extra deps)
195
+ env = SpotEnv(controller_type='mpc_gait')
196
+
197
+ # PyMPC Gait - Uses Quadruped-PyMPC gait generator (requires jax, gym-quadruped)
198
+ env = SpotEnv(controller_type='pympc')
199
+
200
+ # Trot Gait - Simple open-loop trot pattern
201
+ env = SpotEnv(controller_type='trot')
202
+ ```
203
+
204
+ ## API
205
+
206
+ ### WebSocket Events
207
+
208
+ **Client to Server:**
209
+ - `command`: `{vx, vy, vyaw}` - Velocity command
210
+ - `reset`: Reset robot to initial pose
211
+ - `switch_robot`: `{robot: "g1" | "spot"}` - Switch robot type
212
+
213
+ **Server to Client:**
214
+ - `state`: Robot state data (position, orientation, joint angles)
215
+
216
+ ### HTTP Endpoints
217
+
218
+ - `GET /` - Web interface
219
+ - `GET /video_feed` - MJPEG video stream
220
+
221
  ## License
222
 
223
  This project uses models from:
224
  - [MuJoCo Menagerie](https://github.com/google-deepmind/mujoco_menagerie) (BSD-3-Clause)
225
  - [unitree_mujoco](https://github.com/unitreerobotics/unitree_mujoco) (BSD-3-Clause)
226
  - [unitree_rl_gym](https://github.com/unitreerobotics/unitree_rl_gym)
227
+ - [Quadruped-PyMPC](https://github.com/iit-DLSLab/Quadruped-PyMPC) (BSD-3-Clause)
docker-compose.gpu.yml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ # GPU-accelerated version - requires NVIDIA GPU and nvidia-container-toolkit
4
+ # Usage: docker-compose -f docker-compose.gpu.yml up
5
+
6
+ services:
7
+ nova-sim:
8
+ build: .
9
+ ports:
10
+ - "3004:3004"
11
+ environment:
12
+ # Use EGL for GPU rendering (much faster than OSMesa)
13
+ - MUJOCO_GL=egl
14
+ - PYOPENGL_PLATFORM=egl
15
+ # Higher resolution since GPU can handle it
16
+ - RENDER_WIDTH=1280
17
+ - RENDER_HEIGHT=720
18
+ - TARGET_FPS=60
19
+ - SIM_STEPS_PER_FRAME=5
20
+ # NVIDIA driver
21
+ - NVIDIA_VISIBLE_DEVICES=all
22
+ - NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute
23
+ restart: unless-stopped
24
+ # Enable GPU access
25
+ deploy:
26
+ resources:
27
+ reservations:
28
+ devices:
29
+ - driver: nvidia
30
+ count: 1
31
+ capabilities: [gpu]
docker-compose.yml CHANGED
@@ -6,6 +6,21 @@ services:
6
  ports:
7
  - "3004:3004"
8
  environment:
 
9
  - MUJOCO_GL=osmesa
10
  - PYOPENGL_PLATFORM=osmesa
 
 
 
 
 
 
 
 
11
  restart: unless-stopped
 
 
 
 
 
 
 
6
  ports:
7
  - "3004:3004"
8
  environment:
9
+ # Rendering backend (osmesa = software, slow but compatible)
10
  - MUJOCO_GL=osmesa
11
  - PYOPENGL_PLATFORM=osmesa
12
+ # Performance settings - reduce resolution for faster software rendering
13
+ - RENDER_WIDTH=640
14
+ - RENDER_HEIGHT=360
15
+ - TARGET_FPS=30
16
+ - SIM_STEPS_PER_FRAME=10
17
+ # Threading optimization
18
+ - OMP_NUM_THREADS=4
19
+ - MKL_NUM_THREADS=4
20
  restart: unless-stopped
21
+ # Optional: limit CPU to prevent runaway usage
22
+ # deploy:
23
+ # resources:
24
+ # limits:
25
+ # cpus: '2.0'
26
+ # memory: 2G
mujoco_server.py CHANGED
@@ -18,6 +18,26 @@ app = Flask(__name__)
18
  app.config['SECRET_KEY'] = 'robotsim-secret'
19
  socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  # Current robot type
22
  current_robot = "g1" # or "spot"
23
 
@@ -49,7 +69,7 @@ def init_g1():
49
  """Initialize G1 environment."""
50
  global env_g1
51
  if env_g1 is None:
52
- env_g1 = G1Env(render_mode="rgb_array")
53
  env_g1.reset()
54
  return env_g1
55
 
@@ -64,7 +84,7 @@ def init_spot():
64
  from spot_env import SpotEnv
65
  sys.path.pop(0)
66
  # Use pympc controller if available, otherwise fallback to mpc_gait
67
- env_spot = SpotEnv(render_mode="rgb_array", controller_type='pympc')
68
  env_spot.reset()
69
  return env_spot
70
 
 
18
  app.config['SECRET_KEY'] = 'robotsim-secret'
19
  socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')
20
 
21
+ # Detect if running in Docker (check for /.dockerenv or cgroup)
22
+ def is_running_in_docker():
23
+ if os.path.exists('/.dockerenv'):
24
+ return True
25
+ try:
26
+ with open('/proc/1/cgroup', 'r') as f:
27
+ return 'docker' in f.read()
28
+ except:
29
+ return False
30
+
31
+ IN_DOCKER = is_running_in_docker()
32
+
33
+ # Performance settings from environment
34
+ # Native defaults: 1280x720 @ 60 FPS (GPU accelerated)
35
+ # Docker defaults: 640x360 @ 30 FPS (software rendering)
36
+ RENDER_WIDTH = int(os.environ.get('RENDER_WIDTH', 640 if IN_DOCKER else 1280))
37
+ RENDER_HEIGHT = int(os.environ.get('RENDER_HEIGHT', 360 if IN_DOCKER else 720))
38
+ TARGET_FPS = int(os.environ.get('TARGET_FPS', 30 if IN_DOCKER else 60))
39
+ SIM_STEPS_PER_FRAME = int(os.environ.get('SIM_STEPS_PER_FRAME', 10 if IN_DOCKER else 5))
40
+
41
  # Current robot type
42
  current_robot = "g1" # or "spot"
43
 
 
69
  """Initialize G1 environment."""
70
  global env_g1
71
  if env_g1 is None:
72
+ env_g1 = G1Env(render_mode="rgb_array", width=RENDER_WIDTH, height=RENDER_HEIGHT)
73
  env_g1.reset()
74
  return env_g1
75
 
 
84
  from spot_env import SpotEnv
85
  sys.path.pop(0)
86
  # Use pympc controller if available, otherwise fallback to mpc_gait
87
+ env_spot = SpotEnv(render_mode="rgb_array", width=RENDER_WIDTH, height=RENDER_HEIGHT, controller_type='pympc')
88
  env_spot.reset()
89
  return env_spot
90