chrisjcc commited on
Commit
3c5f45f
·
1 Parent(s): 848a20e

Multiple randomized dynamic objects. A pusher that activates mid-simulation. Full support for parameterized object count and rendering.

Browse files
Files changed (2) hide show
  1. assets/tray.xml +24 -11
  2. tray_sim.py +30 -8
assets/tray.xml CHANGED
@@ -1,13 +1,26 @@
1
  <mujoco model="tray_sim">
2
- <compiler angle="degree" coordinate="local" />
3
- <option gravity="0 0 -9.81" />
4
- <worldbody>
5
- <body name="tray" pos="0 0 0">
6
- <geom name="tray" type="box" size="0.3 0.3 0.02" rgba="0.5 0.5 0.5 1" />
7
- </body>
8
- <body name="block" pos="0 0 0.3">
9
- <geom name="block" type="box" size="0.02 0.02 0.02" rgba="0.2 0.6 0.8 1" />
10
- <joint name="free" type="free" />
11
- </body>
12
- </worldbody>
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  </mujoco>
 
1
  <mujoco model="tray_sim">
2
+ <compiler angle="degree" coordinate="local" />
3
+ <option gravity="0 0 -9.81" />
4
+ <size njmax="1000" nconmax="500" />
5
+ <worldbody>
6
+ <!-- Static tray -->
7
+ <body name="tray" pos="0 0 0">
8
+ <geom type="box" size="0.3 0.3 0.02" rgba="0.5 0.5 0.5 1"/>
9
+ </body>
10
+
11
+ <!-- Dynamic objects (all with free joints) -->
12
+ <!-- You can randomize and selectively activate them in Python -->
13
+ {% for i in range(10) %}
14
+ <body name="obj{{ i }}" pos="0 0 0.1">
15
+ <geom type="box" size="0.015 0.015 0.015" rgba="{{ 0.1 * i }} {{ 0.2 + 0.05 * i }} {{ 0.7 - 0.05 * i }} 1" />
16
+ <joint type="free" />
17
+ </body>
18
+ {% endfor %}
19
+
20
+ <!-- Pusher -->
21
+ <body name="pusher" pos="0.3 -0.3 0.05">
22
+ <geom type="box" size="0.02 0.02 0.02" rgba="0 0 0 1"/>
23
+ <joint type="free"/>
24
+ </body>
25
+ </worldbody>
26
  </mujoco>
tray_sim.py CHANGED
@@ -5,21 +5,43 @@ import os
5
  import tempfile
6
 
7
  MODEL_PATH = "assets/tray.xml"
 
 
 
8
 
9
- def run_tray_simulation(seed=0):
 
10
  np.random.seed(seed)
11
  model = mujoco.MjModel.from_xml_path(MODEL_PATH)
12
  data = mujoco.MjData(model)
13
 
14
- # Randomize initial object position
15
- data.qpos[:3] = [0.0, 0.0, 0.3 + 0.2 * np.random.rand()] # x, y, z
16
- data.qvel[:] = 0
 
 
 
 
 
17
 
18
- # Use mujoco.Renderer for offscreen rendering
19
- renderer = mujoco.Renderer(model, width=480, height=480)
 
20
 
 
 
21
  frames = []
22
- for _ in range(200):
 
 
 
 
 
 
 
 
 
 
23
  mujoco.mj_step(model, data)
24
  renderer.update_scene(data)
25
  img = renderer.render()
@@ -27,7 +49,7 @@ def run_tray_simulation(seed=0):
27
 
28
  renderer.close()
29
 
30
- # Save as GIF to temp file
31
  gif_path = os.path.join(tempfile.gettempdir(), f"tray_sim_{seed}.gif")
32
  imageio.mimsave(gif_path, frames, fps=20)
33
  return gif_path
 
5
  import tempfile
6
 
7
  MODEL_PATH = "assets/tray.xml"
8
+ N_OBJECTS = 5 # number of dynamic blocks to randomize
9
+ PUSH_START_STEP = 50
10
+ SIM_STEPS = 200
11
 
12
+
13
+ def run_tray_simulation(seed=0, num_objects=N_OBJECTS):
14
  np.random.seed(seed)
15
  model = mujoco.MjModel.from_xml_path(MODEL_PATH)
16
  data = mujoco.MjData(model)
17
 
18
+ # Object initialization
19
+ for i in range(num_objects):
20
+ obj_start = i * 7 # 7 DOF per free joint body
21
+ pos = np.random.uniform(low=[-0.1, -0.1, 0.05], high=[0.1, 0.1, 0.15])
22
+ quat = [1, 0, 0, 0] # no rotation
23
+ data.qpos[obj_start:obj_start+3] = pos
24
+ data.qpos[obj_start+3:obj_start+7] = quat
25
+ data.qvel[i*6:i*6+6] = 0
26
 
27
+ # Locate pusher DOF index (last one in qpos if you have 10 objects)
28
+ pusher_idx = num_objects * 7
29
+ pusher_vel_idx = num_objects * 6
30
 
31
+ # Renderer
32
+ renderer = mujoco.Renderer(model, width=640, height=640)
33
  frames = []
34
+
35
+ keyframes = {0: None, 25: None, 50: None, 200: None}
36
+
37
+ for t in range(SIM_STEPS):
38
+ if t == PUSH_START_STEP:
39
+ # Activate pusher
40
+ data.qvel[pusher_vel_idx:pusher_vel_idx+3] = [-0.05, 0.05, 0.0] # toward center
41
+
42
+ if t in keyframes:
43
+ imageio.imwrite(f"/tmp/frame_{t}.png", img)
44
+
45
  mujoco.mj_step(model, data)
46
  renderer.update_scene(data)
47
  img = renderer.render()
 
49
 
50
  renderer.close()
51
 
52
+ # Save to GIF
53
  gif_path = os.path.join(tempfile.gettempdir(), f"tray_sim_{seed}.gif")
54
  imageio.mimsave(gif_path, frames, fps=20)
55
  return gif_path