You're reading the documentation for a development version. For the latest released version, please have a look at Kilted.

Demos and Tutorials

The mujoco_ros2_control_demos package provides ready-to-run tutorials that demonstrate how to use MuJoCo with ros2_control. Each tutorial builds on the previous one and introduces a new concept.

Note

All tutorials support a headless:=true argument to run without the MuJoCo visualiser window:

ros2 launch mujoco_ros2_control_demos 01_basic_robot.launch.py headless:=true

Tip

Inside the MuJoCo viewer, UI panels can be toggled with Tab or Shift+Tab. All standard MuJoCo keyboard shortcuts are available; press F1 for a short reference.

Tutorial 1: Basic Robot

The simplest setup — launches a two-link arm with position controllers using a pre-defined MJCF model.

ros2 launch mujoco_ros2_control_demos 01_basic_robot.launch.py

Key concepts: Pre-defined MJCF loading, basic ros2_control integration, position control.

Resources: demo_resources/scenes/scene.xml, demo_resources/robot/test_robot.xml

Tutorial 2: MJCF Generation at Runtime

Demonstrates generating MJCF models from URDF at runtime using the conversion script.

# Using external input files
ros2 launch mujoco_ros2_control_demos 02_mjcf_generation.launch.py

# Using mujoco_inputs embedded in the URDF
ros2 launch mujoco_ros2_control_demos 02_mjcf_generation.launch.py use_urdf_inputs:=true

Key concepts: Runtime URDF→MJCF conversion, <mujoco_inputs> tags, external input files.

Resources: demo_resources/mjcf_generation/test_inputs.xml, demo_resources/scenes/scene_info.xml

See URDF to MJCF Conversion for full documentation of the URDF-to-MJCF conversion tool.

Tutorial 3: PID Control

Demonstrates PID controllers with motor actuators for velocity/effort control modes.

ros2 launch mujoco_ros2_control_demos 03_pid_control.launch.py

Key concepts: PID gain configuration, motor actuators, velocity/effort control.

Resources: demo_resources/pid_control/test_robot_pid.xml, config/mujoco_pid.yaml

Refer to Hardware Interface Configuration for the full set of hardware-interface parameters, including pids_config_file.

Tutorial 4: Transmissions

Demonstrates ros2_control transmissions with mechanical reduction ratios.

ros2 launch mujoco_ros2_control_demos 04_transmissions.launch.py

Key concepts: DifferentialTransmission interface, mechanical reduction, actuator-to-joint mapping.

Resources: demo_resources/robot/test_robot.urdf with use_transmissions:=true

Tutorial 5: Base Velocity Plugin

Demonstrates driving a mobile/floating-base robot with BaseVelocityPlugin: a free-floating, wheeled chassis (MJCF <freejoint>) carrying a 1-DOF arm, driven from a cmd_vel topic via a hard velocity override applied directly to the chassis’s free-joint qvel every cycle. The wheels and ground have zero friction, which is now largely cosmetic – propulsion no longer goes through wheel-ground contact at all, so it does not depend on friction either way.

Warning

Because the override is kinematic, it outranks the contact solver: the wall in the scene will not stop the base – it will push through or climb it rather than being stopped by contact, since the commanded velocity is reasserted every cycle regardless of collisions. This is the trade-off for exact, disturbance-immune velocity tracking; see the BaseVelocityPlugin documentation for details.

ros2 launch mujoco_ros2_control_demos 05_base_velocity_plugin.launch.py

# In another terminal, drive the base:
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.2}}" --rate 10

Disturbance immunity: swinging the mounted arm creates a reaction force/torque on the base through the joint, unrelated to ground friction, since it acts directly between the two bodies. Because BaseVelocityPlugin overrides the base’s driven DOFs directly rather than servoing against them, this reaction has no effect on the base’s velocity at all – not approximately, exactly none – so with no cmd_vel active the base stays exactly in place while the arm moves. The arm’s joint is range-limited to a back-and-forth sweep rather than a continuous spin:

ros2 topic pub /arm_position_controller/commands std_msgs/msg/Float64MultiArray "data: [0.7]"
ros2 topic pub /arm_position_controller/commands std_msgs/msg/Float64MultiArray "data: [-0.7]"

Key concepts: BaseVelocityPlugin free-joint velocity override, driving a MJCF <freejoint> body, immunity to reaction forces from a moving mounted joint, floating-base odometry (odom_free_joint_name).

Resources: demo_resources/scenes/scene_mobile_base.xml, demo_resources/mobile_base/mobile_base.xml, demo_resources/mobile_base/mobile_base.urdf, config/mujoco_ros2_control_plugins_base_velocity.yaml

See MuJoCo ROS 2 Control Plugins for the full list of BaseVelocityPlugin parameters.

Combined Demo

The demo.launch.py file combines multiple features and is retained for backwards compatibility and integration testing:

ros2 launch mujoco_ros2_control_demos demo.launch.py
ros2 launch mujoco_ros2_control_demos demo.launch.py use_pid:=true
ros2 launch mujoco_ros2_control_demos demo.launch.py use_mjcf_from_topic:=true
ros2 launch mujoco_ros2_control_demos demo.launch.py test_transmissions:=true

Controlling the Robot

Once any tutorial is running you can send commands and inspect state with standard ROS 2 CLI tools:

# Set joint positions (joint1, joint2)
ros2 topic pub /position_controller/commands std_msgs/msg/Float64MultiArray "data: [0.5, -0.5]"

# Control the gripper
ros2 topic pub /gripper_controller/commands std_msgs/msg/Float64MultiArray "data: [-0.02]"

# Monitor joint states
ros2 topic echo /joint_states

Package Structure

mujoco_ros2_control_demos/
├── launch/
│   ├── 01_basic_robot.launch.py         # Tutorial 1
│   ├── 02_mjcf_generation.launch.py     # Tutorial 2
│   ├── 03_pid_control.launch.py         # Tutorial 3
│   ├── 04_transmissions.launch.py       # Tutorial 4
│   ├── 05_base_velocity_plugin.launch.py # Tutorial 5
│   └── demo.launch.py                  # Combined demo
├── config/
│   ├── controllers.yaml                        # Controller configuration
│   ├── mujoco_pid.yaml                         # PID gains (Tutorial 3)
│   ├── controllers_base_velocity.yaml          # joint_state_broadcaster + arm_position_controller (Tutorial 5)
│   └── mujoco_ros2_control_plugins_base_velocity.yaml  # BaseVelocityPlugin config (Tutorial 5)
└── demo_resources/
    ├── robot/
    │   ├── test_robot.urdf          # Shared URDF description
    │   └── test_robot.xml           # MJCF robot model
    ├── scenes/
    │   ├── scene.xml                # Basic scene (Tutorial 1, 4)
    │   ├── scene_pid.xml            # PID scene (Tutorial 3)
    │   ├── scene_info.xml           # Scene generation info
    │   └── scene_mobile_base.xml    # Mobile base + wall obstacle (Tutorial 5)
    ├── mjcf_generation/
    │   └── test_inputs.xml          # MJCF conversion inputs (Tutorial 2)
    ├── pid_control/
    │   └── test_robot_pid.xml       # Robot with motor actuators
    └── mobile_base/
        ├── mobile_base.xml          # MJCF chassis with freejoint (Tutorial 5)
        └── mobile_base.urdf         # Minimal URDF, no ros2_control joints (Tutorial 5)