Visually render the coordinate axes (X, Y, Z) in the MuJoCo simulation
Browse files- tray_sim.py +41 -7
tray_sim.py
CHANGED
|
@@ -13,7 +13,7 @@ MODEL_PATH = "assets/tray.xml"
|
|
| 13 |
N_OBJECTS = 5 # number of dynamic blocks to randomize
|
| 14 |
PUSH_START_STEP = 50
|
| 15 |
SIM_STEPS = 200
|
| 16 |
-
IMPACT_STEP = 60 #
|
| 17 |
|
| 18 |
|
| 19 |
def classify_stability(data, model):
|
|
@@ -133,12 +133,51 @@ def format_as_natural_language_prompt(scene_description, task_description=None):
|
|
| 133 |
|
| 134 |
return "\n".join(lines)
|
| 135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
|
| 137 |
def run_tray_simulation(seed=0, num_objects=N_OBJECTS, azimuth=45, elevation=-25, distance=0.6):
|
| 138 |
np.random.seed(seed)
|
| 139 |
model = mujoco.MjModel.from_xml_path(MODEL_PATH)
|
| 140 |
data = mujoco.MjData(model)
|
| 141 |
tray_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_BODY, "tray")
|
|
|
|
| 142 |
|
| 143 |
# Apply a transient force to the tray
|
| 144 |
tray_force_applied = True # False # One-time trigger
|
|
@@ -253,8 +292,6 @@ def run_tray_simulation(seed=0, num_objects=N_OBJECTS, azimuth=45, elevation=-25
|
|
| 253 |
json.dump(physics_state, f, indent=2)
|
| 254 |
|
| 255 |
# LLM-friendly prompt output
|
| 256 |
-
#prompt = format_llm_prompt(physics_state)
|
| 257 |
-
|
| 258 |
formatted = format_llm_prompt(physics_state)
|
| 259 |
prompt = format_as_natural_language_prompt(
|
| 260 |
formatted,
|
|
@@ -265,7 +302,4 @@ def run_tray_simulation(seed=0, num_objects=N_OBJECTS, azimuth=45, elevation=-25
|
|
| 265 |
gif_path = os.path.join(tempfile.gettempdir(), f"tray_sim_{seed}.gif")
|
| 266 |
imageio.mimsave(gif_path, frames, fps=20)
|
| 267 |
|
| 268 |
-
#return
|
| 269 |
-
#return gif_path, stability_flags
|
| 270 |
-
#return gif_path, stability_flags, physics_state # optionally also return json_path
|
| 271 |
-
return gif_path, stability_flags, physics_state, prompt, json_path # optionally also return json_path
|
|
|
|
| 13 |
N_OBJECTS = 5 # number of dynamic blocks to randomize
|
| 14 |
PUSH_START_STEP = 50
|
| 15 |
SIM_STEPS = 200
|
| 16 |
+
IMPACT_STEP = 60 # is a good starting point, just after the pusher activates.
|
| 17 |
|
| 18 |
|
| 19 |
def classify_stability(data, model):
|
|
|
|
| 133 |
|
| 134 |
return "\n".join(lines)
|
| 135 |
|
| 136 |
+
def draw_world_axes(scene):
|
| 137 |
+
"""
|
| 138 |
+
Adds red (X), green (Y), and blue (Z) arrows at the origin to visualize coordinate axes.
|
| 139 |
+
"""
|
| 140 |
+
mujoco.mjv_addGeom(
|
| 141 |
+
scene,
|
| 142 |
+
type=mujoco.mjtGeom.mjGEOM_ARROW,
|
| 143 |
+
data=None,
|
| 144 |
+
pos=np.array([0, 0, 0]),
|
| 145 |
+
mat=np.eye(3).flatten(), # Identity rotation
|
| 146 |
+
size=np.array([0.01, 0.01, 0.2]), # shaft_radius, head_radius, length
|
| 147 |
+
rgba=np.array([1.0, 0.0, 0.0, 1.0]), # Red for X
|
| 148 |
+
label=-1,
|
| 149 |
+
textureid=-1
|
| 150 |
+
)
|
| 151 |
+
mujoco.mjv_addGeom(
|
| 152 |
+
scene,
|
| 153 |
+
type=mujoco.mjtGeom.mjGEOM_ARROW,
|
| 154 |
+
data=None,
|
| 155 |
+
pos=np.array([0, 0, 0]),
|
| 156 |
+
mat=np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]]).flatten(), # 90 deg about Z to point Y
|
| 157 |
+
size=np.array([0.01, 0.01, 0.2]),
|
| 158 |
+
rgba=np.array([0.0, 1.0, 0.0, 1.0]), # Green for Y
|
| 159 |
+
label=-1,
|
| 160 |
+
textureid=-1
|
| 161 |
+
)
|
| 162 |
+
mujoco.mjv_addGeom(
|
| 163 |
+
scene,
|
| 164 |
+
type=mujoco.mjtGeom.mjGEOM_ARROW,
|
| 165 |
+
data=None,
|
| 166 |
+
pos=np.array([0, 0, 0]),
|
| 167 |
+
mat=np.array([[0, 0, 1], [0, 1, 0], [-1, 0, 0]]).flatten(), # Pointing up
|
| 168 |
+
size=np.array([0.01, 0.01, 0.2]),
|
| 169 |
+
rgba=np.array([0.0, 0.0, 1.0, 1.0]), # Blue for Z
|
| 170 |
+
label=-1,
|
| 171 |
+
textureid=-1
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
|
| 175 |
def run_tray_simulation(seed=0, num_objects=N_OBJECTS, azimuth=45, elevation=-25, distance=0.6):
|
| 176 |
np.random.seed(seed)
|
| 177 |
model = mujoco.MjModel.from_xml_path(MODEL_PATH)
|
| 178 |
data = mujoco.MjData(model)
|
| 179 |
tray_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_BODY, "tray")
|
| 180 |
+
draw_world_axes(renderer.scene)
|
| 181 |
|
| 182 |
# Apply a transient force to the tray
|
| 183 |
tray_force_applied = True # False # One-time trigger
|
|
|
|
| 292 |
json.dump(physics_state, f, indent=2)
|
| 293 |
|
| 294 |
# LLM-friendly prompt output
|
|
|
|
|
|
|
| 295 |
formatted = format_llm_prompt(physics_state)
|
| 296 |
prompt = format_as_natural_language_prompt(
|
| 297 |
formatted,
|
|
|
|
| 302 |
gif_path = os.path.join(tempfile.gettempdir(), f"tray_sim_{seed}.gif")
|
| 303 |
imageio.mimsave(gif_path, frames, fps=20)
|
| 304 |
|
| 305 |
+
return gif_path, stability_flags, physics_state, prompt, json_path # optionally also return json_path
|
|
|
|
|
|
|
|
|