"""Render a qpos trajectory to MP4. Run as a subprocess by rollout.write_video with MUJOCO_GL already set, because MuJoCo fixes its GL backend at import. python render_worker.py model.mjb qpos.npy out.mp4 fps width height camera """ import sys import numpy as np def main(mjb, qpos_path, out, fps, width, height, camera): import imageio.v2 as imageio import mujoco model = mujoco.MjModel.from_binary_path(mjb) data = mujoco.MjData(model) qpos = np.load(qpos_path) # "follow" is a free camera kept above and behind the robot. The scene's own # "track" camera sits 0.35 m above the centre of mass, which ends up inside # the hillside on sloped terrain and renders the ground black. follow = camera == "follow" if follow: cam = mujoco.MjvCamera() cam.azimuth, cam.elevation, cam.distance = 140.0, -15.0, 6.0 else: cam = camera if mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_CAMERA, camera) >= 0 else -1 with mujoco.Renderer(model, height=int(height), width=int(width)) as r, \ imageio.get_writer(out, fps=float(fps), codec="libx264", quality=7, macro_block_size=None) as w: for q in qpos: data.qpos[:] = q mujoco.mj_forward(model, data) if follow: cam.lookat[:] = data.qpos[:3] r.update_scene(data, camera=cam) w.append_data(r.render()) if __name__ == "__main__": main(*sys.argv[1:8])