{ "cells": [ { "cell_type": "markdown", "id": "9ad05586", "metadata": {}, "source": [ "# MuJoCo Quickstart 🤖\n", "\n", "This notebook gets you running MuJoCo simulations in Google Colab with zero setup." ] }, { "cell_type": "code", "execution_count": null, "id": "e98d4497", "metadata": {}, "outputs": [], "source": [ "!pip install -q mujoco mediapy" ] }, { "cell_type": "code", "execution_count": null, "id": "eb91cdc1", "metadata": {}, "outputs": [], "source": [ "import mujoco\n", "import numpy as np\n", "import mediapy\n", "\n", "print(f\"MuJoCo version: {mujoco.__version__}\")" ] }, { "cell_type": "markdown", "id": "748cc7fd", "metadata": {}, "source": [ "## 1. Define a model in MJCF (XML)" ] }, { "cell_type": "code", "execution_count": null, "id": "a0400644", "metadata": {}, "outputs": [], "source": [ "XML = \"\"\"\n", "\n", " \n", "\"\"\"\n", "\n", "model = mujoco.MjModel.from_xml_string(XML)\n", "data = mujoco.MjData(model)\n", "print(f\"Model has {model.nq} DOFs, timestep = {model.opt.timestep}s\")" ] }, { "cell_type": "markdown", "id": "628ad5c8", "metadata": {}, "source": [ "## 2. Simulate and render" ] }, { "cell_type": "code", "execution_count": null, "id": "e0d7df1c", "metadata": {}, "outputs": [], "source": [ "renderer = mujoco.Renderer(model, height=480, width=640)\n", "frames = []\n", "fps = 30\n", "duration = 2.0\n", "\n", "mujoco.mj_resetData(model, data)\n", "data.qvel[0] = 3.0 # initial x velocity\n", "\n", "while data.time < duration:\n", " mujoco.mj_step(model, data)\n", " if len(frames) < data.time * fps:\n", " renderer.update_scene(data)\n", " frames.append(renderer.render().copy())\n", "\n", "renderer.close()\n", "mediapy.show_video(frames, fps=fps)" ] }, { "cell_type": "markdown", "id": "3643a3c8", "metadata": {}, "source": [ "## 3. Add a controller\n", "\n", "Let's control a pendulum with a PD controller." ] }, { "cell_type": "code", "execution_count": null, "id": "383e9e5e", "metadata": {}, "outputs": [], "source": [ "PENDULUM_XML = \"\"\"\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\"\"\"\n", "\n", "model = mujoco.MjModel.from_xml_string(PENDULUM_XML)\n", "data = mujoco.MjData(model)\n", "renderer = mujoco.Renderer(model, height=480, width=640)\n", "\n", "target = np.pi / 4 # 45 degrees\n", "kp, kd = 50.0, 10.0\n", "frames = []\n", "\n", "while data.time < 5.0:\n", " # PD control\n", " data.ctrl[0] = kp * (target - data.qpos[0]) - kd * data.qvel[0]\n", " mujoco.mj_step(model, data)\n", " if len(frames) < data.time * fps:\n", " renderer.update_scene(data)\n", " frames.append(renderer.render().copy())\n", "\n", "renderer.close()\n", "mediapy.show_video(frames, fps=fps)" ] }, { "cell_type": "markdown", "id": "03802786", "metadata": {}, "source": [ "## Next Steps\n", "\n", "- [MJCF Reference](https://mujoco.readthedocs.io/en/stable/XMLreference.html) — build your own models\n", "- [Gymnasium MuJoCo envs](https://gymnasium.farama.org/environments/mujoco/) — RL-ready environments\n", "- [MJX](https://mujoco.readthedocs.io/en/stable/mjx.html) — GPU-parallel simulation with JAX\n", "- [MuJoCo Menagerie](https://github.com/google-deepmind/mujoco_menagerie) — robot model zoo" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }