{ "cells": [ { "cell_type": "markdown", "id": "b92d071c", "metadata": {}, "source": [ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/tayalmanan28/MuJoCo-Tutorial/blob/main/tutorial/01_basics.ipynb)\n", "\n", "# Tutorial 1: MuJoCo Basics\n", "\n", "Learn the fundamentals: loading models, `MjModel`, `MjData`, and named access.\n", "\n", "**Prerequisites:** [Tutorial 00: What is MuJoCo?](00_what_is_mujoco.ipynb) — you should already understand:\n", "- The Describe → Simulate → Observe pattern\n", "- `MjModel` = blueprint (constant), `MjData` = state (changes)\n", "- `qpos`/`qvel` = positions/velocities of all joints\n", "\n", "This tutorial goes deeper into **inspecting** models and accessing data by name." ] }, { "cell_type": "code", "execution_count": null, "id": "228e3d53", "metadata": {}, "outputs": [], "source": [ "!pip install -q mujoco mediapy" ] }, { "cell_type": "code", "execution_count": null, "id": "740c860e", "metadata": {}, "outputs": [], "source": [ "import mujoco\n", "import numpy as np\n", "import mediapy as media\n", "\n", "print(f\"MuJoCo version: {mujoco.__version__}\")" ] }, { "cell_type": "markdown", "id": "8b6c46a6", "metadata": {}, "source": [ "## Loading a Model\n", "\n", "MuJoCo models are defined in [MJCF](https://mujoco.readthedocs.io/en/stable/XMLreference.html) (XML format).\n", "The smallest valid model is ``. Let's define a simple scene:" ] }, { "cell_type": "code", "execution_count": null, "id": "7edcd2d6", "metadata": {}, "outputs": [], "source": [ "xml = \"\"\"\n", "\n", " \n", " \n", " \n", " \n", "\n", "\"\"\"\n", "model = mujoco.MjModel.from_xml_string(xml)\n", "print(f\"Number of geoms: {model.ngeom}\")" ] }, { "cell_type": "markdown", "id": "05459851", "metadata": {}, "source": [ "## MjModel — The Static Description\n", "\n", "`MjModel` contains everything that **doesn't change** during simulation:\n", "geometry sizes, masses, joint types, colors, etc." ] }, { "cell_type": "code", "execution_count": null, "id": "b036caeb", "metadata": {}, "outputs": [], "source": [ "# Number of geoms and their RGBA colors\n", "print(f\"ngeom: {model.ngeom}\")\n", "print(f\"geom_rgba:\\n{model.geom_rgba}\")" ] }, { "cell_type": "markdown", "id": "39d41b27", "metadata": {}, "source": [ "## Named Access\n", "\n", "The Python bindings provide convenient named accessors:" ] }, { "cell_type": "code", "execution_count": null, "id": "da7aa51d", "metadata": {}, "outputs": [], "source": [ "# Access by name\n", "print(\"green_sphere rgba:\", model.geom('green_sphere').rgba)\n", "print(\"green_sphere id:\", model.geom('green_sphere').id)\n", "print(\"geom 0 name:\", model.geom(0).name)\n", "\n", "# List all geom names\n", "print(\"All geoms:\", [model.geom(i).name for i in range(model.ngeom)])" ] }, { "cell_type": "markdown", "id": "38892698", "metadata": {}, "source": [ "## MjData — The Dynamic State\n", "\n", "`MjData` contains the simulation **state** (time, positions, velocities)\n", "and derived quantities (Cartesian positions, forces, etc.)." ] }, { "cell_type": "code", "execution_count": null, "id": "42c69688", "metadata": {}, "outputs": [], "source": [ "data = mujoco.MjData(model)\n", "\n", "# Derived quantities need explicit computation\n", "print(\"Before mj_kinematics:\", data.geom_xpos)\n", "\n", "mujoco.mj_kinematics(model, data)\n", "print(\"After mj_kinematics:\", data.geom_xpos)\n", "print(\"green_sphere pos:\", data.geom('green_sphere').xpos)" ] }, { "cell_type": "markdown", "id": "16ef6897", "metadata": {}, "source": [ "## Key Takeaways\n", "\n", "- `MjModel` = static description (compiled from XML)\n", "- `MjData` = dynamic state + derived quantities\n", "- Use `mj_forward()` or `mj_kinematics()` to propagate state before reading derived quantities\n", "- Named access: `model.geom('name')`, `data.body('name')`, etc." ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }