',
+ encoding="utf-8",
+ )
+
+
def setup(app):
"""Register Isaac Lab documentation directives."""
+ app.add_config_value("isaaclab_doc_redirects", {}, "html")
+ app.add_config_value("isaaclab_doc_redirect_fragments", {}, "html")
+ app.connect("build-finished", _write_doc_redirects)
app.add_config_value("isaaclab_latest_branch", "develop", "env")
+ app.add_config_value("isaaclab_wheel_version", "", "env")
+ app.add_config_value("isaaclab_wheel_source_tag", "", "env")
app.add_config_value("isaacsim_version", "", "env")
app.add_config_value("torch_version", "", "env")
app.add_config_value("torchvision_version", "", "env")
diff --git a/docs/conf.py b/docs/conf.py
index 4f394a911713..5d185053d93e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -61,6 +61,8 @@
# Latest release branch referenced by installation documentation.
isaaclab_latest_branch = os.getenv("ISAACLAB_LATEST_BRANCH", "develop")
+isaaclab_wheel_version = "3.0.0rc1"
+isaaclab_wheel_source_tag = "v3.0.0-EA"
def _read_pinned_versions() -> dict:
@@ -93,6 +95,7 @@ def _read_pinned_versions() -> dict:
rst_prolog = f"""
.. |isaaclab_latest_branch| replace:: {isaaclab_latest_branch}
+.. |isaaclab_wheel_version| replace:: {isaaclab_wheel_version}
.. |isaacsim_version| replace:: {isaacsim_version}
.. |torch_version| replace:: {torch_version}
.. |torchvision_version| replace:: {torchvision_version}
@@ -393,6 +396,43 @@ def _read_pinned_versions() -> dict:
}
+# Keep published links working after guide consolidation.
+isaaclab_doc_redirects = {
+ "source/features/docker_cloud": "source/workflows/docker/index",
+ "source/how-to/robots": "source/how-to/write_articulation_cfg",
+ "source/tutorials/00_sim/create_empty": "source/how-to/create_empty",
+ "source/tutorials/00_sim/launch_app": "source/how-to/launch_app",
+ "source/tutorials/00_sim/spawn_prims": "source/how-to/spawn_prims",
+ "source/tutorials/01_assets/add_new_robot": "source/how-to/write_articulation_cfg",
+ "source/tutorials/01_assets/run_articulation": "source/how-to/run_articulation",
+ "source/tutorials/01_assets/run_deformable_object": "source/how-to/run_deformable_object",
+ "source/tutorials/01_assets/run_rigid_object": "source/how-to/run_rigid_object",
+ "source/tutorials/01_assets/run_surface_gripper": "source/how-to/run_surface_gripper",
+ "source/tutorials/02_scene/create_scene": "source/how-to/create_scene",
+ "source/tutorials/03_envs/configuring_rl_training": "source/how-to/configuring_rl_training",
+ "source/tutorials/03_envs/create_direct_rl_env": "source/how-to/create_direct_rl_env",
+ "source/tutorials/03_envs/create_manager_base_env": "source/how-to/create_manager_base_env",
+ "source/tutorials/03_envs/create_manager_rl_env": "source/how-to/create_manager_rl_env",
+ "source/tutorials/03_envs/modify_direct_rl_env": "source/how-to/modify_direct_rl_env",
+ "source/tutorials/03_envs/policy_inference_in_usd": "source/how-to/policy_inference_in_usd",
+ "source/tutorials/03_envs/register_rl_env_gym": "source/how-to/register_rl_env_gym",
+ "source/tutorials/03_envs/run_rl_training": "source/how-to/run_rl_training",
+ "source/tutorials/04_sensors/add_sensors_on_robot": "source/how-to/add_sensors_on_robot",
+ "source/tutorials/05_controllers/run_diff_ik": "source/how-to/run_diff_ik",
+ "source/tutorials/05_controllers/run_osc": "source/how-to/run_osc",
+ "source/tutorials/index": "source/how-to/index",
+}
+
+# Sections of the former combined Docker page now live on separate pages.
+isaaclab_doc_redirect_fragments = {
+ "source/features/docker_cloud": {
+ "clusters": "source/workflows/docker/cluster#deployment-cluster",
+ "deployment-cluster": "source/workflows/docker/cluster#deployment-cluster",
+ "cloud-workstations": "source/workflows/docker/cloud#docker-cloud-cloud",
+ "docker-cloud-cloud": "source/workflows/docker/cloud#docker-cloud-cloud",
+ },
+}
+
# -- Advanced configuration -------------------------------------------------
diff --git a/docs/index.rst b/docs/index.rst
index 29f63b620926..8f399b0e8b55 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -30,7 +30,7 @@ adaptability, and support for running in the cloud.
Additionally, Isaac Lab provides a variety of environments, and we are actively working on adding more environments
to the list. These include classic control tasks, fixed-arm and dexterous manipulation tasks, legged locomotion tasks,
and navigation tasks. Browse the registered tasks and build a command in the
-`environment browser `_.
+:doc:`environment browser `.
Isaac lab is developed with specific robot assets that are now **Batteries-included** as part of the platform and are ready to learn! These robots include...
@@ -95,6 +95,7 @@ Table of Contents
source/setup/tutorial
source/setup/demos
source/how-to/index
+ source/workflows/index
source/migration/migrating_to_isaaclab_3-0
@@ -127,7 +128,6 @@ Table of Contents
source/features/imitation-learning/index
source/features/isaac_teleop
- source/features/docker_cloud
source/features/hydra
source/features/multi_gpu
source/features/population_based_training
diff --git a/docs/source/concepts/motion_generators.rst b/docs/source/concepts/motion_generators.rst
index 6f782c238c11..6255b7628d4d 100644
--- a/docs/source/concepts/motion_generators.rst
+++ b/docs/source/concepts/motion_generators.rst
@@ -1,6 +1,8 @@
Motion Generators
=================
+.. currentmodule:: isaaclab.controllers
+
Robotic tasks are typically defined in task-space in terms of desired
end-effector trajectory, while control actions are executed in the
joint-space. This naturally leads to *joint-space* and *task-space*
@@ -159,7 +161,8 @@ It is possible to compute the pseudo-inverse of the Jacobian using different for
* Tanspose pseudo-inverse: :math:`A^{-} = A^T`.
* Adaptive singular-vale decomposition (SVD) pseduo-inverse from :cite:t:`buss2004ik`.
-These implementations are available through the :class:`DifferentialInverseKinematics` class.
+These implementations are available through the :class:`DifferentialIKController` class.
+See :doc:`../how-to/run_diff_ik` for a runnable example.
Impedance controller
~~~~~~~~~~~~~~~~~~~~
@@ -174,7 +177,7 @@ Operational-space controller
Similar to task-space impedance
control but uses the Equation of Motion (EoM) for computing the
-task-space force
+task-space force. See :doc:`../how-to/run_osc` for a runnable example.
Closed-loop proportional force controller
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -205,7 +208,7 @@ different approaches combine the constraints directly into an
optimization problem, thereby providing a holistic solution for motion
generation and control.
-We currently support the following planners:
+Examples of reactive planners include:
- **RMPFlow (lula):** An acceleration-based policy that composes various Reimannian Motion Policies (RMPs) to
solve a hierarchy of tasks :cite:p:`cheng2021rmpflow`. It is capable of performing dynamic collision
@@ -213,13 +216,14 @@ We currently support the following planners:
- **MPC (OCS2):** A receding horizon control policy based on sequential linear-quadratic (SLQ) programming.
It formulates various constraints into a single optimization problem via soft-penalties and uses automatic
- differentiation to compute derivatives of the system dynamics, constraints and costs. Currently, we support
- the MPC formulation for end-effector trajectory tracking in fixed-arm and mobile manipulators. The formulation
- considers a kinematic system model with joint limits and self-collision avoidance :cite:p:`mittal2021articulated`.
+ differentiation to compute derivatives of the system dynamics, constraints and costs. The MPC formulation
+ for end-effector trajectory tracking in fixed-arm and mobile manipulators described in
+ :cite:p:`mittal2021articulated` considers a kinematic system model with joint limits and self-collision avoidance.
+ See the `OCS2 documentation `_ for the external toolbox and examples.
.. warning::
- We wrap around the python bindings for these reactive planners to perform a batched computing of
- robot actions. However, their current implementations are CPU-based which may cause certain
- slowdown for learning.
+ :class:`RmpFlowController` wraps the CPU-based Lula bindings, so its computation can
+ limit throughput in large batches. It also needs the Lula library and robot description
+ files; these dependencies are separate from the selected physics backend.
diff --git a/docs/source/concepts/warp_environments.rst b/docs/source/concepts/warp_environments.rst
index 1174c3a41f0b..59e56aeddb1d 100644
--- a/docs/source/concepts/warp_environments.rst
+++ b/docs/source/concepts/warp_environments.rst
@@ -69,10 +69,18 @@ MDP term for its warp twin). Select the Newton solver explicitly with
- ``Isaac-Velocity-Flat-H1``
- ``Isaac-Velocity-Flat-UnitreeGo2``
+The following contributed tasks also have full twin coverage:
+
+- ``IsaacContrib-Velocity-Flat-AnymalB``
+- ``IsaacContrib-Velocity-Flat-AnymalC``
+- ``IsaacContrib-Velocity-Flat-UnitreeA1``
+- ``IsaacContrib-Velocity-Flat-UnitreeGo1``
+
A missing twin is a hard error listing the affected terms, so a partially
covered task fails at build time rather than silently changing behavior.
-Rough-terrain velocity tasks remain unsupported until
-:class:`~isaaclab.terrains.TerrainImporter` gains Warp APIs.
+Rough-terrain velocity configurations that use ``height_scan`` cannot currently be
+adapted: that observation term has no Warp twin. Check the terms used by a task rather
+than assuming that every terrain configuration has the same limitation.
Quick Start
@@ -101,14 +109,19 @@ Stable-Baselines3.
``--video`` is rejected on the warp path, for both ``train`` and ``play``: video
recording requires the standard torch frontend. To record a rollout, replay the same
- checkpoint with ``--frontend torch``.
+ checkpoint with ``--frontend torch``; see :ref:`how_to_record_video`.
Performance Comparison
~~~~~~~~~~~~~~~~~~~~~~
-Step time comparison between the stable (torch/manager) and warp (CUDA graph captured) variants,
+Historical step time comparison between the stable (torch/manager) and warp (CUDA graph captured) variants,
both running on the Newton physics backend. Measured over 300 iterations with 4096 environments.
+The table covers the measured tasks, not every currently supported task.
+These figures are retained as the original benchmark record, not a measurement of the latest
+``develop`` revision. For updated results, record the hardware and Isaac Lab, Newton, and Warp
+revisions, and compare both frontends on those same revisions. Improvements in shared base
+libraries can benefit both frontends and must not be attributed solely to the Warp frontend.
.. note::
diff --git a/docs/source/features/docker_cloud.rst b/docs/source/features/docker_cloud.rst
deleted file mode 100644
index bbfb9cc0a17e..000000000000
--- a/docs/source/features/docker_cloud.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-.. Copyright (c) 2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
-.. All rights reserved.
-..
-.. SPDX-License-Identifier: BSD-3-Clause
-
-.. _docker-cloud:
-
-Docker/Cloud
-============
-
-Use this page after completing the minimal container or cloud setup in :ref:`isaaclab-installation-root`.
-It contains the operational details for developing in Docker, retaining artifacts, extending images,
-submitting jobs to a cluster, and managing remote workstations.
-
-Isaac Lab provides a Dockerfile and Compose configuration that layer Isaac Lab onto the NVIDIA Isaac
-Sim container. The resulting image is reproducible across Docker hosts and can be converted to an
-Apptainer/Singularity image for shared HPC systems. For public-cloud workstations, Isaac Automator
-provisions Isaac Sim and Isaac Lab on AWS, GCP, Azure, and Alibaba Cloud.
-
-Docker guide
-------------
-
-.. include:: include/docker_details.inc
-
-Worked Docker example
----------------------
-
-.. include:: include/docker_example_details.inc
-
-Clusters
---------
-
-.. include:: include/cluster_details.inc
-
-.. _docker-cloud-cloud:
-
-Cloud workstations
-------------------
-
-.. include:: include/cloud_details.inc
diff --git a/docs/source/features/include/docker_details.inc b/docs/source/features/include/docker_details.inc
deleted file mode 100644
index a133ffe19aff..000000000000
--- a/docs/source/features/include/docker_details.inc
+++ /dev/null
@@ -1,489 +0,0 @@
-.. _deployment-docker:
-
-
-.. rubric:: Docker Guide
-
-.. caution::
-
- The standard Isaac Lab container depends on the Isaac Sim Docker image. By running that container, you are
- implicitly agreeing to the `NVIDIA Software License Agreement`_. If you do not agree to the EULA, do not run
- that container. The kit-less container described below does not contain Isaac Sim or Kit.
-
-.. rubric:: Setup Instructions
-
-.. note::
-
- The following steps are taken from the Isaac Sim documentation on `container installation`_.
- They have been added here for the sake of completeness.
-
-
-.. rubric:: Docker and Docker Compose
-
-We have tested the container using Docker Engine version 26.0.0 and Docker Compose version 2.25.0
-We recommend using these versions or newer.
-
-* To install Docker, please follow the instructions for your operating system on the `Docker website`_.
-* To install Docker Compose, please follow the instructions for your operating system on the `docker compose`_ page.
-* Follow the post-installation steps for Docker on the `post-installation steps`_ page. These steps allow you to run
- Docker without using ``sudo``.
-* To build and run GPU-accelerated containers, you also need install the `NVIDIA Container Toolkit`_.
- Please follow the instructions on the `Container Toolkit website`_ for installation steps.
-
-.. note::
-
- Due to limitations with `snap `_, please make sure
- the Isaac Lab directory is placed under the ``/home`` directory tree when using docker.
-
-
-.. rubric:: Directory Organization
-
-The root of the Isaac Lab repository contains the ``docker`` directory that has various files and scripts
-needed to run Isaac Lab inside a Docker container. A subset of these are summarized below:
-
-* **Dockerfile.base**: Defines the base Isaac Lab image by overlaying its dependencies onto the Isaac Sim Docker image.
- Dockerfiles which end with something else, (i.e. ``Dockerfile.ros2``) build an `image extension <#isaac-lab-image-extensions>`_.
-* **Dockerfile.kitless**: Defines a kit-less image for Newton training without Isaac Sim or Kit.
-* **docker-compose.yaml**: Creates mounts to allow direct editing of Isaac Lab code from the host machine that runs
- the container. It also creates several named volumes such as ``isaac-cache-kit`` to
- store frequently reused resources compiled by Isaac Sim, such as shaders, and to retain logs, data, and documents.
-* **.env.base**: Stores environment variables required for the ``base`` build process and Isaac Sim-based image
- extensions such as ``ros2``.
-* **.env.kitless**: Stores the standalone kit-less image settings. This profile does not load ``.env.base``.
-* **docker-compose.cloudxr-runtime.patch.yaml**: A patch file that is applied to enable CloudXR Runtime support for
- streaming to compatible XR devices. It defines services and volumes for CloudXR Runtime and the base.
-* **.env.cloudxr-runtime**: Environment variables for the CloudXR Runtime support.
-* **container.py**: A utility script that interfaces with tools in ``utils`` to configure and build the image,
- and run and interact with the container.
-
-.. rubric:: Running the Container
-
-.. note::
-
- The docker container copies all the files from the repository into the container at the
- location ``/workspace/isaaclab`` at build time. This means that any changes made to the files in the container would not
- normally be reflected in the repository after the image has been built, i.e. after ``./container.py start`` is run.
-
- For a faster development cycle, we mount the following directories in the Isaac Lab repository into the container
- so that you can edit their files from the host machine:
-
- * **IsaacLab/source**: This is the directory that contains the Isaac Lab source code.
- * **IsaacLab/docs**: This is the directory that contains the source code for Isaac Lab documentation. This is overlaid except
- for the ``_build`` subdirectory where build artifacts are stored.
-
-
-The script ``container.py`` parallels basic ``docker compose`` commands. Each can accept an `image extension argument <#isaac-lab-image-extensions>`_,
-or else they will default to the ``base`` image extension. These commands are:
-
-* **build**: This builds the image for the given profile. It does not bring up the container.
-* **start**: This builds the image and brings up the container in detached mode (i.e. in the background).
-* **enter**: This begins a new bash process in an existing Isaac Lab container, and which can be exited
- without bringing down the container.
-* **config**: This outputs the compose.yaml which would be result from the inputs given to ``container.py start``. This command is useful
- for debugging a compose configuration.
-* **copy**: This copies the ``logs``, ``data_storage`` and ``docs/_build`` artifacts, from the ``isaac-lab-logs``, ``isaac-lab-data`` and ``isaac-lab-docs``
- volumes respectively, to the ``docker/artifacts`` directory. These artifacts persist between docker container instances and are shared between image extensions.
-* **stop**: This brings down the container and removes it.
-
-The following shows how to launch the container in a detached state and enter it:
-
-.. code:: bash
-
- # Launch the container in detached mode
- # We don't pass an image extension arg, so it defaults to 'base'
- ./docker/container.py start
-
- # If we want to add .env or .yaml files to customize our compose config,
- # we can simply specify them in the same manner as the compose cli
- # ./docker/container.py start --file my-compose.yaml --env-file .env.my-vars
-
- # Enter the container
- # We pass 'base' explicitly, but if we hadn't it would default to 'base'
- ./docker/container.py enter base
-
-The Isaac Lab base, ROS 2, cuRobo, and kit-less images run as a non-root user with uid/gid 1000 to keep
-bind-mounted workspaces writable on GitHub runners. If you run one of these images directly with
-``docker run`` and your host uid differs, pass Docker's ``--user "$(id -u):1000"`` option so
-new files on bind mounts are owned by your host user while retaining runtime-home access.
-
-If you are upgrading an existing Compose setup from older root-based images, recreate the named
-volumes before starting the new images. Older cache, log, and data volumes may contain root-owned
-files that the uid/gid 1000 runtime user cannot update. Copy any artifacts you want to keep, then
-remove the old Compose volumes from the ``docker`` directory:
-
-.. code:: bash
-
- docker compose --file docker-compose.yaml --profile base --env-file .env.base down --volumes
-
-To copy files from the base container to the host machine, you can use the following command:
-
-.. code:: bash
-
- # Copy the file /workspace/isaaclab/logs to the current directory
- docker cp isaac-lab-base:/workspace/isaaclab/logs .
-
-The script ``container.py`` provides a wrapper around this command to copy the ``logs`` , ``data_storage`` and ``docs/_build``
-directories to the ``docker/artifacts`` directory. This is useful for copying the logs, data and documentation:
-
-.. code:: bash
-
- # stop the container
- ./docker/container.py stop
-
-
-.. rubric:: CloudXR Runtime Support
-
-To enable CloudXR Runtime for streaming to compatible XR devices, you need to apply the patch file
-``docker-compose.cloudxr-runtime.patch.yaml`` to run CloudXR Runtime container. The patch file defines services and
-volumes for CloudXR Runtime and base. The environment variables required for CloudXR Runtime are specified in the
-``.env.cloudxr-runtime`` file. To start or stop the CloudXR runtime container with base, use the following command:
-
-.. code:: bash
-
- # Start CloudXR Runtime container with base.
- ./docker/container.py start --files docker-compose.cloudxr-runtime.patch.yaml --env-file .env.cloudxr-runtime
-
- # Stop CloudXR Runtime container and base.
- ./docker/container.py stop --files docker-compose.cloudxr-runtime.patch.yaml --env-file .env.cloudxr-runtime
-
-
-.. rubric:: X11 forwarding
-
-The container supports X11 forwarding, which allows the user to run GUI applications from the container
-and display them on the host machine.
-
-The first time a container is started with ``./docker/container.py start``, the script prompts
-the user whether to activate X11 forwarding. This will create a file at ``docker/.container.cfg``
-to store the user's choice for future runs.
-
-If you want to change the choice, you can set the parameter ``X11_FORWARDING_ENABLED`` to '0' or '1'
-in the ``docker/.container.cfg`` file to disable or enable X11 forwarding, respectively. After that, you need to
-re-build the container by running ``./docker/container.py start``. The rebuilding process ensures that the changes
-are applied to the container. Otherwise, the changes will not take effect.
-
-After the container is started, you can enter the container and run GUI applications from it with X11 forwarding enabled.
-The display will be forwarded to the host machine.
-
-
-.. rubric:: Python Interpreter
-
-Every profile installs from ``uv.lock`` into a Python 3.12 virtual environment at
-``/opt/isaaclab-venv``. On the Isaac Sim-based profiles the environment is built on Isaac Sim's
-own interpreter, and Isaac Sim itself stays outside it, reached through the ``_isaac_sim``
-symlink; ``isaaclab.sh`` puts it on the path. In either container, use the following command:
-
-.. code:: bash
-
- python
-
-
-.. rubric:: Understanding the mounted volumes
-
-The ``docker-compose.yaml`` file creates several named volumes that are mounted to the container.
-These are summarized below:
-
-.. list-table::
- :header-rows: 1
- :widths: 23 45 32
-
- * - Volume Name
- - Description
- - Container Path
- * - isaac-cache-kit
- - Stores cached Kit resources
- - /isaac-sim/kit/cache
- * - isaac-cache-ov
- - Stores cached OV resources
- - /root/.cache/ov
- * - isaac-cache-pip
- - Stores cached pip resources
- - /root/.cache/pip
- * - isaac-cache-gl
- - Stores cached GLCache resources
- - /root/.cache/nvidia/GLCache
- * - isaac-cache-compute
- - Stores cached compute resources
- - /root/.nv/ComputeCache
- * - isaac-cache-uv
- - Stores uv downloads for the kit-less profile
- - /home/isaaclab/.cache/uv
- * - isaac-cache-warp
- - Stores Warp kernels for the kit-less profile
- - /home/isaaclab/.cache/warp
- * - isaac-logs
- - Stores logs generated by Omniverse
- - /root/.nvidia-omniverse/logs
- * - isaac-carb-logs
- - Stores logs generated by carb
- - /isaac-sim/kit/logs/Kit/Isaac-Sim
- * - isaac-data
- - Stores data generated by Omniverse
- - /root/.local/share/ov/data
- * - isaac-docs
- - Stores documents generated by Omniverse
- - /root/Documents
- * - isaac-lab-docs
- - Stores documentation of Isaac Lab when built inside the container
- - /workspace/isaaclab/docs/_build
- * - isaac-lab-logs
- - Stores logs generated by Isaac Lab workflows when run inside the container
- - /workspace/isaaclab/logs
- * - isaac-lab-data
- - Stores whatever data users may want to preserve between container runs
- - /workspace/isaaclab/data_storage
-
-To view the contents of these volumes, you can use the following command:
-
-.. code:: bash
-
- # list all volumes
- docker volume ls
- # inspect a specific volume, e.g. isaac-cache-kit
- docker volume inspect isaac-cache-kit
-
-The kit-less profile uses the uv and Warp cache volumes and shares the Isaac Lab documentation, logs,
-and data volumes with the other profiles.
-
-
-.. rubric:: Isaac Lab Container Profiles and Image Extensions
-
-The produced image depends on the arguments passed to ``container.py start`` and ``container.py stop``. These
-commands accept a profile parameter as an additional argument. If no argument is passed, then this parameter
-defaults to ``base``. The valid Compose profiles are ``base``, ``ros2``, and the standalone ``kitless``.
-Only one profile can be passed at a time. The produced image and container will be named
-``isaac-lab-${profile}``, where ``${profile}`` is the profile name.
-
-``suffix`` is an optional string argument to ``container.py`` that specifies a docker image and
-container name suffix, which can be useful for development purposes. By default ``${suffix}`` is the empty string.
-If ``${suffix}`` is a nonempty string, then the produced docker image and container will be named
-``isaac-lab-${profile}-${suffix}``, where a hyphen is inserted between ``${profile}`` and ``${suffix}`` in
-the name. ``suffix`` should not be used with cluster deployments.
-
-.. code:: bash
-
- # start base by default, named isaac-lab-base
- ./docker/container.py start
- # stop base explicitly, named isaac-lab-base
- ./docker/container.py stop base
- # start ros2 container named isaac-lab-ros2
- ./docker/container.py start ros2
- # stop ros2 container named isaac-lab-ros2
- ./docker/container.py stop ros2
-
- # start base container named isaac-lab-base-custom
- ./docker/container.py start base --suffix custom
- # stop base container named isaac-lab-base-custom
- ./docker/container.py stop base --suffix custom
- # start ros2 container named isaac-lab-ros2-custom
- ./docker/container.py start ros2 --suffix custom
- # stop ros2 container named isaac-lab-ros2-custom
- ./docker/container.py stop ros2 --suffix custom
-
-The passed profile argument will build the image defined in ``Dockerfile.${profile}``,
-with the corresponding `profile`_ in ``docker-compose.yaml``. Isaac Sim-based extensions load ``.env.base``
-and their profile-specific environment file, if any. The standalone ``kitless`` profile loads only ``.env.kitless``.
-
-.. rubric:: Published Kit-less Image
-
-Building the kit-less image locally is not required. It is published alongside the Isaac Lab release
-image in the same registry repository, distinguished by a ``-kitless`` tag suffix and carrying the same
-release version tag.
-
-.. code:: bash
-
- docker pull nvcr.io/nvidia/isaac-lab:3.0.0-rc1-kitless
-
-Start a named container in the background. The ``--interactive`` and ``--tty`` options keep the image's Bash
-process running so that you can execute multiple commands in the same container:
-
-.. code:: bash
-
- docker run --name isaac-lab-kitless --detach --interactive --tty --gpus all --network host \
- nvcr.io/nvidia/isaac-lab:3.0.0-rc1-kitless
-
-Train a policy in the running container:
-
-.. code:: bash
-
- docker exec isaac-lab-kitless \
- isaaclab train --rl_library rsl_rl --task Isaac-Cartpole-Direct \
- --num_envs 16 presets=newton_mjwarp --max_iterations 5
-
-Then replay the latest checkpoint in the same container. The Viser web visualizer is reachable through the host
-network; stop playback with :kbd:`Ctrl+C` without stopping the container:
-
-.. code:: bash
-
- docker exec --interactive --tty isaac-lab-kitless \
- isaaclab play --rl_library rsl_rl --task Isaac-Cartpole-Direct \
- --num_envs 16 presets=newton_mjwarp --checkpoint latest --viz viser
-
-Only ``linux/amd64`` images are published. The Dockerfile itself is architecture-agnostic, but the
-published manifest is limited to the architecture that is validated in CI.
-
-.. rubric:: ROS2 Image Extension
-
-In ``Dockerfile.ros2``, the container installs ROS2 Humble via an `apt package`_, and it is sourced in the ``.bashrc``.
-The exact version is specified by the variable ``ROS_APT_PACKAGE`` in the ``.env.ros2`` file,
-defaulting to ``ros-base``. Other relevant ROS2 variables are also specified in the ``.env.ros2`` file,
-including variables defining the `various middleware`_ options.
-
-The container defaults to ``FastRTPS``, but ``CylconeDDS`` is also supported. Each of these middlewares can be
-`tuned`_ using their corresponding ``.xml`` files under ``docker/.ros``.
-
-
-.. dropdown:: Parameters for ROS2 Image Extension
- :icon: code
-
- .. literalinclude:: ../../../docker/.env.ros2
- :language: bash
-
-
-.. rubric:: Using the Kit-less Container
-
-The kit-less container uses Ubuntu 24.04 and Python 3.12 instead of the Isaac Sim base image. It contains
-Newton physics, OVPhysX physics, OVRTX rendering, and the four core RL frameworks: RL Games, RSL-RL,
-Stable-Baselines3, and SKRL. It also carries every Newton viewer -- ``newton``, ``viser``, and ``rerun`` --
-so any of them can be requested with ``--viz``. No visualizer is selected by default, so training runs
-headless unless you ask for one.
-
-The ``kit`` visualizer is the exception: it is provided by Omniverse Kit, which this image does not contain.
-
-To build, start, and enter the image through the same ``container.py`` interface as the Isaac Sim images, run:
-
-.. code:: bash
-
- ./docker/container.py build kitless
- ./docker/container.py start kitless
- ./docker/container.py enter kitless
- ./docker/container.py stop kitless
-
-The Compose profile bind-mounts the repository's ``source``, ``scripts``, ``apps``, and ``tools`` directories.
-It also retains the uv cache, Warp cache, documentation output, logs, and data storage in named volumes. Use
-``./docker/container.py copy kitless`` to copy the retained outputs to the host.
-
-To build the image directly, run:
-
-.. code:: bash
-
- docker build --file docker/Dockerfile.kitless --tag isaac-lab-kitless .
-
-Run a short Cartpole training job to verify the image and NVIDIA Container Toolkit setup:
-
-.. code:: bash
-
- docker run --rm --gpus all --network host isaac-lab-kitless \
- isaaclab train --rl_library rsl_rl \
- --task Isaac-Cartpole-Direct \
- --num_envs 16 \
- presets=newton_mjwarp \
- --max_iterations 5
-
-The image runs as the non-root ``isaaclab`` user with uid/gid 1000.
-
-
-.. rubric:: Running Pre-Built Isaac Lab Container
-
-In Isaac Lab 2.0 release, we introduced a minimal pre-built container that contains a very minimal set
-of Isaac Sim and Omniverse dependencies, along with Isaac Lab 2.0 pre-built into the container.
-This container allows users to pull the container directly from NGC without requiring a local build of
-the docker image. The Isaac Lab source code will be available in this container under ``/workspace/IsaacLab``.
-
-This container is designed for running **headless** only and does not allow for X11 forwarding or running
-with the GUI. Please only use this container for headless training. For other use cases, we recommend
-following the above steps to build your own Isaac Lab docker image.
-
-.. note::
-
- Currently, we only provide docker images with every major release of Isaac Lab.
- For example, we provide the docker image for release 2.0.0 and 2.1.0, but not 2.0.2.
- In the future, we will provide docker images for every minor release of Isaac Lab.
-
-To pull the minimal Isaac Lab container, run:
-
-.. code:: bash
-
- docker pull nvcr.io/nvidia/isaac-lab:3.0.0-rc1
-
-.. attention::
-
- If the pre-built image you use runs as a **non-root** user (uid/gid 1000) -- as Isaac Lab
- 3.0.0-beta2 and later do -- the bind-mounted host directories below must be writable by that
- user. Docker creates any missing bind-mount source directory as ``root``, which the non-root
- runtime user cannot write to, leading to startup errors such as
- ``PermissionError: [Errno 13] Permission denied: '/root/.local/share/ov/data/exts'``.
- Pre-create the host directories and make them writable by uid/gid 1000 before running the
- container:
-
- .. code:: bash
-
- mkdir -p ~/docker/isaac-sim/{cache/kit,cache/ov,cache/pip,cache/glcache,cache/computecache,logs,data,documents}
- sudo chown -R 1000:1000 ~/docker/isaac-sim
-
-To run the Isaac Lab container with an interactive bash session, run:
-
-.. code:: bash
-
- docker run --name isaac-lab --entrypoint bash -it --gpus all -e "ACCEPT_EULA=Y" --rm --network=host \
- -e "PRIVACY_CONSENT=Y" \
- -v ~/docker/isaac-sim/cache/kit:/isaac-sim/kit/cache:rw \
- -v ~/docker/isaac-sim/cache/ov:/root/.cache/ov:rw \
- -v ~/docker/isaac-sim/cache/pip:/root/.cache/pip:rw \
- -v ~/docker/isaac-sim/cache/glcache:/root/.cache/nvidia/GLCache:rw \
- -v ~/docker/isaac-sim/cache/computecache:/root/.nv/ComputeCache:rw \
- -v ~/docker/isaac-sim/logs:/root/.nvidia-omniverse/logs:rw \
- -v ~/docker/isaac-sim/data:/root/.local/share/ov/data:rw \
- -v ~/docker/isaac-sim/documents:/root/Documents:rw \
- nvcr.io/nvidia/isaac-lab:3.0.0-rc1
-
-To enable rendering through X11 forwarding, run:
-
-.. code:: bash
-
- xhost +
- docker run --name isaac-lab --entrypoint bash -it --gpus all -e "ACCEPT_EULA=Y" --rm --network=host \
- -e "PRIVACY_CONSENT=Y" \
- -e DISPLAY \
- -v $HOME/.Xauthority:/root/.Xauthority \
- -v ~/docker/isaac-sim/cache/kit:/isaac-sim/kit/cache:rw \
- -v ~/docker/isaac-sim/cache/ov:/root/.cache/ov:rw \
- -v ~/docker/isaac-sim/cache/pip:/root/.cache/pip:rw \
- -v ~/docker/isaac-sim/cache/glcache:/root/.cache/nvidia/GLCache:rw \
- -v ~/docker/isaac-sim/cache/computecache:/root/.nv/ComputeCache:rw \
- -v ~/docker/isaac-sim/logs:/root/.nvidia-omniverse/logs:rw \
- -v ~/docker/isaac-sim/data:/root/.local/share/ov/data:rw \
- -v ~/docker/isaac-sim/documents:/root/Documents:rw \
- nvcr.io/nvidia/isaac-lab:3.0.0-rc1
-
-To run an example within the container, run:
-
-.. tab-set::
-
- .. tab-item:: uv (Recommended)
-
- .. code:: bash
-
- uv run python scripts/tutorials/00_sim/log_time.py
-
-
- .. tab-item:: isaaclab.sh / isaaclab.bat
-
- .. code:: bash
-
- ./isaaclab.sh -p scripts/tutorials/00_sim/log_time.py
-
-
-.. _`NVIDIA Software License Agreement`: https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-software-license-agreement
-.. _`container installation`: https://docs.isaacsim.omniverse.nvidia.com/latest/installation/install_container.html
-.. _`Docker website`: https://docs.docker.com/desktop/install/linux-install/
-.. _`docker compose`: https://docs.docker.com/compose/install/linux/#install-using-the-repository
-.. _`NVIDIA Container Toolkit`: https://github.com/NVIDIA/nvidia-container-toolkit
-.. _`Container Toolkit website`: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
-.. _`post-installation steps`: https://docs.docker.com/engine/install/linux-postinstall/
-.. _`Isaac Sim container`: https://catalog.ngc.nvidia.com/orgs/nvidia/containers/isaac-sim
-.. _`NGC API key`: https://docs.nvidia.com/ngc/gpu-cloud/ngc-user-guide/index.html#generating-api-key
-.. _`several streaming clients`: https://docs.isaacsim.omniverse.nvidia.com/latest/installation/manual_livestream_clients.html
-.. _`known issue`: https://forums.developer.nvidia.com/t/unable-to-use-webrtc-when-i-run-runheadless-webrtc-sh-in-remote-headless-container/222916
-.. _`profile`: https://docs.docker.com/compose/compose-file/15-profiles/
-.. _`apt package`: https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debians.html#install-ros-2-packages
-.. _`various middleware`: https://docs.ros.org/en/humble/How-To-Guides/Working-with-multiple-RMW-implementations.html
-.. _`tuned`: https://docs.ros.org/en/foxy/How-To-Guides/DDS-tuning.html
diff --git a/docs/source/features/include/docker_example_details.inc b/docs/source/features/include/docker_example_details.inc
deleted file mode 100644
index 2dcc59932926..000000000000
--- a/docs/source/features/include/docker_example_details.inc
+++ /dev/null
@@ -1,138 +0,0 @@
-.. rubric:: Running an example with Docker
-
-From the root of the Isaac Lab repository, the ``docker`` directory contains all the Docker relevant files. These include the three files
-(**Dockerfile**, **docker-compose.yaml**, **.env**) which are used by Docker, and an additional script that we use to interface with them,
-**container.py**.
-
-In this tutorial, we will learn how to use the Isaac Lab Docker container for development. For a detailed description of the Docker setup,
-including installation and obtaining access to an Isaac Sim image, please reference the :ref:`deployment-docker`. For a description
-of Docker in general, please refer to `their official documentation `_.
-
-
-.. rubric:: Building the Container
-
-To build the Isaac Lab container from the root of the Isaac Lab repository, we will run the following:
-
-
-.. code-block:: console
-
- python docker/container.py start
-
-
-The terminal will first pull the base IsaacSim image, build the Isaac Lab image's additional layers on top of it, and run the Isaac Lab container.
-This should take several minutes for the first build but will be shorter in subsequent runs as Docker's caching prevents repeated work.
-If we run the command ``docker container ls`` on the terminal, the output will list the containers that are running on the system. If
-everything has been set up correctly, a container with the ``NAME`` **isaac-lab-base** should appear, similar to below:
-
-
-.. code-block:: console
-
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 483d1d5e2def isaac-lab-base "bash" 30 seconds ago Up 30 seconds isaac-lab-base
-
-
-Once the container is up and running, we can enter it from our terminal.
-
-.. code-block:: console
-
- python docker/container.py enter
-
-
-On entering the Isaac Lab container, we are in the terminal as a non-root user. This environment contains a copy of the
-Isaac Lab repository, but also has access to the directories and libraries of Isaac Sim. We can run experiments from this environment
-using a few convenient aliases that have been put into the runtime user's **.bashrc**. For instance, we have made the **isaaclab.sh** script
-usable from anywhere by typing its alias ``isaaclab``.
-
-Additionally in the container, we have `bind mounted`_ the ``IsaacLab/source`` directory from the
-host machine. This means that if we modify files under this directory from an editor on the host machine, the changes are
-reflected immediately within the container without requiring us to rebuild the Docker image.
-
-We will now run a sample script from within the container to demonstrate how to extract artifacts
-from the Isaac Lab Docker container.
-
-.. rubric:: The Code
-
-The tutorial corresponds to the ``log_time.py`` script in the ``IsaacLab/scripts/tutorials/00_sim`` directory.
-
-.. dropdown:: Code for log_time.py
- :icon: code
-
- .. literalinclude:: ../../../scripts/tutorials/00_sim/log_time.py
- :language: python
- :emphasize-lines: 46-55, 72-79
- :linenos:
-
-
-.. rubric:: The Code Explained
-
-The Isaac Lab Docker container has several `volumes`_ to facilitate persistent storage between the host computer and the
-container. One such volume is the ``/workspace/isaaclab/logs`` directory.
-The ``log_time.py`` script designates this directory as the location to which a ``log.txt`` should be written:
-
-.. literalinclude:: ../../../scripts/tutorials/00_sim/log_time.py
- :language: python
- :start-at: # Specify that the logs must be in logs/docker_tutorial
- :end-at: print(f"[INFO] Logging experiment to directory: {log_dir_path}")
-
-
-As the comments note, :func:`os.path.abspath()` will prepend ``/workspace/isaaclab`` because in
-the Docker container all python execution is done through ``/workspace/isaaclab/isaaclab.sh``.
-The output will be a file, ``log.txt``, with the ``sim_time`` written on a newline at every simulation step:
-
-.. literalinclude:: ../../../scripts/tutorials/00_sim/log_time.py
- :language: python
- :start-at: # Prepare to count sim_time
- :end-at: sim_time += sim_dt
-
-
-.. rubric:: Executing the Script
-
-This command does not select a visualizer, so it runs without a GUI while producing the log:
-
-.. code-block:: bash
-
- isaaclab -p scripts/tutorials/00_sim/log_time.py
-
-If a config or command would otherwise select a visualizer, force-disable all visualizers with
-``--visualizer none`` or ``--viz none``.
-
-Now ``log.txt`` will have been produced at ``/workspace/isaaclab/logs/docker_tutorial``. If we exit the container
-by typing ``exit``, we will return to ``IsaacLab/docker`` in our host terminal environment. We can then enter
-the following command to retrieve our logs from the Docker container and put them on our host machine:
-
-.. code-block:: console
-
- ./container.py copy
-
-
-We will see a terminal readout reporting the artifacts we have retrieved from the container. If we navigate to
-``/isaaclab/docker/artifacts/logs/docker_tutorial``, we will see a copy of the ``log.txt`` file which was produced
-by the script above.
-
-Each of the directories under ``artifacts`` corresponds to Docker `volumes`_ mapped to directories
-within the container and the ``container.py copy`` command copies them from those `volumes`_ to these directories.
-
-We could return to the Isaac Lab Docker terminal environment by running ``container.py enter`` again,
-but we have retrieved our logs and wish to go inspect them. We can stop the Isaac Lab Docker container with the following command:
-
-.. code-block:: console
-
- ./container.py stop
-
-
-This will bring down the Docker Isaac Lab container. The image will persist and remain available for further use, as will
-the contents of any `volumes`_. If we wish to free up the disk space taken by the image, (~20.1GB), and do not mind repeating
-the build process when we next run ``./container.py start``, we may enter the following command to delete the **isaac-lab-base** image:
-
-.. code-block:: console
-
- docker image rm isaac-lab-base
-
-A subsequent run of ``docker image ls`` will show that the image tagged **isaac-lab-base** is now gone. We can repeat the process for the
-underlying NVIDIA container if we wish to free up more space. If a more powerful method of freeing resources from Docker is desired,
-please consult the documentation for the `docker prune`_ commands.
-
-
-.. _volumes: https://docs.docker.com/storage/volumes/
-.. _bind mounted: https://docs.docker.com/storage/bind-mounts/
-.. _docker prune: https://docs.docker.com/config/pruning/
diff --git a/docs/source/tutorials/04_sensors/add_sensors_on_robot.rst b/docs/source/how-to/add_sensors_on_robot.rst
similarity index 95%
rename from docs/source/tutorials/04_sensors/add_sensors_on_robot.rst
rename to docs/source/how-to/add_sensors_on_robot.rst
index e34ab9bbd8f0..00141da0e87c 100644
--- a/docs/source/tutorials/04_sensors/add_sensors_on_robot.rst
+++ b/docs/source/how-to/add_sensors_on_robot.rst
@@ -37,7 +37,7 @@ The tutorial corresponds to the ``add_sensors_on_robot.py`` script in the
.. dropdown:: Code for add_sensors_on_robot.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
+ .. literalinclude:: ../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
:language: python
:emphasize-lines: 72-95, 143-153, 167-168
:linenos:
@@ -85,7 +85,7 @@ set to ``{ENV_REGEX_NS}/Robot/base/front_cam`` where the ``{ENV_REGEX_NS}`` is t
``"Robot"`` is the name of the robot, ``"base"`` is the name of the prim to which the camera is attached,
and ``"front_cam"`` is the name of the prim associated with the camera sensor.
-.. literalinclude:: ../../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
+.. literalinclude:: ../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
:language: python
:start-at: camera = CameraCfg(
:end-before: height_scanner = RayCasterCfg(
@@ -111,7 +111,7 @@ by setting the :attr:`~sensors.SensorBaseCfg.debug_vis` attribute to true.
The entire configuration of the height-scanner is as follows:
-.. literalinclude:: ../../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
+.. literalinclude:: ../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
:language: python
:start-at: height_scanner = RayCasterCfg(
:end-before: contact_forces = ContactSensorCfg(
@@ -140,7 +140,7 @@ simulation steps is stored.
The entire configuration of the contact sensor is as follows:
-.. literalinclude:: ../../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
+.. literalinclude:: ../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
:language: python
:start-at: contact_forces = ContactSensorCfg(
:lines: 1-3
@@ -151,7 +151,7 @@ Running the simulation loop
Similar to when using assets, the buffers and physics handles for the sensors are initialized only
when the simulation is played, i.e., it is important to call ``sim.reset()`` after creating the scene.
-.. literalinclude:: ../../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
+.. literalinclude:: ../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
:language: python
:start-at: # Play the simulator
:end-at: sim.reset()
@@ -163,7 +163,7 @@ periods.
The data from the sensors can be accessed through their ``data`` attribute. As an example, we show how
to access the data for the different sensors created in this tutorial:
-.. literalinclude:: ../../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
+.. literalinclude:: ../../../scripts/tutorials/04_sensors/add_sensors_on_robot.py
:language: python
:start-at: # print information from the sensors
:end-at: print("Received max contact force of: ", torch.max(scene["contact_forces"].data.net_normal_forces_w).item())
@@ -197,7 +197,7 @@ Additionally, you can switch the viewport to the camera view to see the RGB imag
camera sensor. Please check `here `_ for more information
on how to switch the viewport to the camera view.
-.. figure:: ../../_static/tutorials/tutorial_add_sensors.jpg
+.. figure:: ../_static/tutorials/tutorial_add_sensors.jpg
:align: center
:figwidth: 100%
:alt: result of add_sensors_on_robot.py
diff --git a/docs/source/tutorials/03_envs/configuring_rl_training.rst b/docs/source/how-to/configuring_rl_training.rst
similarity index 97%
rename from docs/source/tutorials/03_envs/configuring_rl_training.rst
rename to docs/source/how-to/configuring_rl_training.rst
index 2cd9708efc3a..1542194d7780 100644
--- a/docs/source/tutorials/03_envs/configuring_rl_training.rst
+++ b/docs/source/how-to/configuring_rl_training.rst
@@ -28,7 +28,7 @@ As an example, we will look at the configuration included for the task ``Isaac-C
in the ``isaaclab_tasks`` package. This is the same task that we used in the
:ref:`tutorial-run-rl-training` tutorial.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/__init__.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/__init__.py
:language: python
:lines: 50-64
@@ -95,7 +95,7 @@ reads the configuration instance:
.. dropdown:: Code for train_sb3.py with SB3
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_rl/isaaclab_rl/entrypoints/backends/train_sb3.py
+ .. literalinclude:: ../../../source/isaaclab_rl/isaaclab_rl/entrypoints/backends/train_sb3.py
:language: python
:linenos:
:emphasize-lines: 56-60, 97-98
diff --git a/docs/source/tutorials/03_envs/create_direct_rl_env.rst b/docs/source/how-to/create_direct_rl_env.rst
similarity index 93%
rename from docs/source/tutorials/03_envs/create_direct_rl_env.rst
rename to docs/source/how-to/create_direct_rl_env.rst
index b8d642db6995..eed06269e1e5 100644
--- a/docs/source/tutorials/03_envs/create_direct_rl_env.rst
+++ b/docs/source/how-to/create_direct_rl_env.rst
@@ -3,7 +3,7 @@
.. seealso::
This tutorial is the source of truth for the ``isaaclab-randomizing-with-events`` agent skill
- (`skills/user/domain-randomization-events/ <../../../../skills/user/domain-randomization-events/SKILL.md>`__).
+ (:isaaclab-source:`skills/user/domain-randomization-events/ `).
When you change this page, update the skill so agent guidance stays in sync. See
:doc:`/source/developer-tools/agent_skills`.
@@ -37,7 +37,7 @@ For this tutorial, we use the cartpole environment defined in ``isaaclab_tasks.c
.. dropdown:: Code for cartpole_direct_env.py
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+ .. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:linenos:
@@ -102,7 +102,7 @@ between the environments, adding the actors into the scene, and adding any addit
scene, such as ground plane and lights. These operations should be implemented in the
``_setup_scene(self)`` method.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:pyobject: CartpoleEnv._setup_scene
@@ -162,7 +162,7 @@ a dictionary should be returned that contains ``policy`` as the key, and the ful
observation buffer as the value. For asymmetric policies, the dictionary should also
include the key ``critic`` and the states buffer as the value.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:pyobject: CartpoleEnv._get_observations
@@ -174,7 +174,7 @@ This method is free to implement logic that computes which environments would ne
and which environments have reached the episode length limit. Both results should be
returned by the ``_get_dones(self)`` function, in the form of a tuple of boolean tensors.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:pyobject: CartpoleEnv._get_dones
@@ -182,7 +182,7 @@ Once the indices for environments requiring reset have been computed, the ``_res
function performs the reset operations on those environments. Within this function, new states
for the environments requiring reset should be set directly into simulation.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:pyobject: CartpoleEnv._reset_idx
@@ -193,7 +193,7 @@ There are two APIs that are designed for working with actions. The ``_pre_physic
from the policy as an argument and is called once per RL step, prior to taking any physics steps. This function can
be used to process the actions buffer from the policy and cache the data in a class variable for the environment.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:pyobject: CartpoleEnv._pre_physics_step
@@ -201,7 +201,7 @@ The ``_apply_action(self)`` API is called ``decimation`` number of times for eac
each physics step. This provides more flexibility for environments where actions should be applied
for each physics step.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env.py
:language: python
:pyobject: CartpoleEnv._apply_action
@@ -225,7 +225,7 @@ To run training for the direct workflow Cartpole environment, we can use the fol
./isaaclab.sh train --rl_library rl_games --task=Isaac-Cartpole-Direct
-.. figure:: ../../_static/tutorials/tutorial_create_direct_workflow.jpg
+.. figure:: ../_static/tutorials/tutorial_create_direct_workflow.jpg
:align: center
:figwidth: 100%
:alt: result of train.py
diff --git a/docs/source/tutorials/00_sim/create_empty.rst b/docs/source/how-to/create_empty.rst
similarity index 92%
rename from docs/source/tutorials/00_sim/create_empty.rst
rename to docs/source/how-to/create_empty.rst
index 7fb8248f1ca0..29db20fa87d3 100644
--- a/docs/source/tutorials/00_sim/create_empty.rst
+++ b/docs/source/how-to/create_empty.rst
@@ -21,7 +21,7 @@ The tutorial corresponds to the ``create_empty.py`` script in the ``scripts/tuto
.. dropdown:: Code for create_empty.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/00_sim/create_empty.py
+ .. literalinclude:: ../../../scripts/tutorials/00_sim/create_empty.py
:language: python
:emphasize-lines: 18-30,34,40-44,46-47,51-54,60-61
:linenos:
@@ -47,7 +47,7 @@ For this tutorial, we mainly look at adding the command-line options to a user-d
to it. These include launching the app headless, configuring different Livestream options,
and enabling off-screen rendering.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/create_empty.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/create_empty.py
:language: python
:start-at: import argparse
:end-at: simulation_app = app_launcher.app
@@ -60,7 +60,7 @@ Isaac Sim and other libraries. Here we import the following module:
* :mod:`isaaclab.sim`: A sub-package in Isaac Lab for all the core simulator-related operations.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/create_empty.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/create_empty.py
:language: python
:start-at: from isaaclab.sim import SimulationCfg, SimulationContext
:end-at: from isaaclab.sim import SimulationCfg, SimulationContext
@@ -82,7 +82,7 @@ For this tutorial, we set the physics and rendering time step to 0.01 seconds. T
by passing these quantities to the :class:`sim.SimulationCfg`, which is then used to create an
instance of the simulation context.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/create_empty.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/create_empty.py
:language: python
:start-at: # Initialize the simulation context
:end-at: sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
@@ -117,7 +117,7 @@ while the simulation app is running. The method :meth:`sim.SimulationContext.ste
which dictates whether the step includes updating the rendering-related events or not. By default, this flag is
set to True.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/create_empty.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/create_empty.py
:language: python
:start-at: # Play the simulator
:end-at: sim.step()
@@ -128,7 +128,7 @@ Exiting the simulation
Lastly, the simulation application is stopped and its window is closed by calling
:meth:`isaacsim.SimulationApp.close` method.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/create_empty.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/create_empty.py
:language: python
:start-at: # close sim app
:end-at: simulation_app.close()
@@ -147,7 +147,7 @@ Now that we have gone through the code, let's run the script and see the result:
The simulation should be playing, and the stage should be rendering. To stop the simulation,
you can either close the window, or press ``Ctrl+C`` in the terminal.
-.. figure:: ../../_static/tutorials/tutorial_create_empty.jpg
+.. figure:: ../_static/tutorials/tutorial_create_empty.jpg
:align: center
:figwidth: 100%
:alt: result of create_empty.py
diff --git a/docs/source/tutorials/03_envs/create_manager_base_env.rst b/docs/source/how-to/create_manager_base_env.rst
similarity index 94%
rename from docs/source/tutorials/03_envs/create_manager_base_env.rst
rename to docs/source/how-to/create_manager_base_env.rst
index 6f77d2ee72f3..5d0e30608bfc 100644
--- a/docs/source/tutorials/03_envs/create_manager_base_env.rst
+++ b/docs/source/how-to/create_manager_base_env.rst
@@ -3,7 +3,7 @@
.. seealso::
This tutorial is the source of truth for the ``isaaclab-randomizing-with-events`` agent skill
- (`skills/user/domain-randomization-events/ <../../../../skills/user/domain-randomization-events/SKILL.md>`__).
+ (:isaaclab-source:`skills/user/domain-randomization-events/ `).
When you change this page, update the skill so agent guidance stays in sync. See
:doc:`/source/developer-tools/agent_skills`.
@@ -39,7 +39,7 @@ directory.
.. dropdown:: Code for create_cartpole_base_env.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
+ .. literalinclude:: ../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
:language: python
:emphasize-lines: 47-51, 54-71, 74-108, 111-130, 135-139, 144, 148, 153-154, 160-161
:linenos:
@@ -85,7 +85,7 @@ different control schemes for different aspects of the environment.
In the cartpole environment, we want to control the force applied to the cart to balance the pole.
Thus, we will create an action term that controls the force applied to the cart.
-.. literalinclude:: ../../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
+.. literalinclude:: ../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
:language: python
:pyobject: ActionsCfg
@@ -115,7 +115,7 @@ callable class that computes the observation for that term. It includes other pa
defining the noise model, clipping, scaling, etc. However, we leave these parameters to their
default values for this tutorial.
-.. literalinclude:: ../../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
+.. literalinclude:: ../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
:language: python
:pyobject: ObservationsCfg
@@ -145,7 +145,7 @@ For this example, we define events that randomize the pole's mass on startup. Th
operation is expensive and we don't want to do it on every reset. We also create an event to randomize the initial
joint state of the cartpole and the pole at every reset.
-.. literalinclude:: ../../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
+.. literalinclude:: ../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
:language: python
:pyobject: EventCfg
@@ -161,7 +161,7 @@ parameters such as the timestep, gravity, etc. This is initialized to the defaul
be modified as needed. We recommend doing so by defining the :meth:`__post_init__` method in the
:class:`envs.ManagerBasedEnvCfg` class, which is called after the configuration is initialized.
-.. literalinclude:: ../../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
+.. literalinclude:: ../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
:language: python
:pyobject: CartpoleEnvCfg
@@ -179,7 +179,7 @@ The :class:`envs.ManagerBasedEnv` class does not have any notion of terminations
specific for episodic tasks. Thus, the user is responsible for defining the termination condition
for the environment. In this tutorial, we reset the simulation at regular intervals.
-.. literalinclude:: ../../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
+.. literalinclude:: ../../../scripts/tutorials/03_envs/create_cartpole_base_env.py
:language: python
:pyobject: main
@@ -214,7 +214,7 @@ right corner of the screen named ``"Isaac Lab"``. This window contains different
can be used for debugging and visualization.
-.. figure:: ../../_static/tutorials/tutorial_create_manager_rl_env.jpg
+.. figure:: ../_static/tutorials/tutorial_create_manager_rl_env.jpg
:align: center
:figwidth: 100%
:alt: result of create_cartpole_base_env.py
diff --git a/docs/source/tutorials/03_envs/create_manager_rl_env.rst b/docs/source/how-to/create_manager_rl_env.rst
similarity index 93%
rename from docs/source/tutorials/03_envs/create_manager_rl_env.rst
rename to docs/source/how-to/create_manager_rl_env.rst
index 6aee66b1de8a..fe0ec521c6b8 100644
--- a/docs/source/tutorials/03_envs/create_manager_rl_env.rst
+++ b/docs/source/how-to/create_manager_rl_env.rst
@@ -36,7 +36,7 @@ For this tutorial, we use the cartpole environment defined in ``isaaclab_tasks.c
.. dropdown:: Code for cartpole_manager_env_cfg.py
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
+ .. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
:language: python
:emphasize-lines: 117-141, 144-154, 172-174
:linenos:
@@ -49,7 +49,7 @@ The script for running the environment ``run_cartpole_rl_env.py`` is present in
.. dropdown:: Code for run_cartpole_rl_env.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/03_envs/run_cartpole_rl_env.py
+ .. literalinclude:: ../../../scripts/tutorials/03_envs/run_cartpole_rl_env.py
:language: python
:emphasize-lines: 38-42, 56-57
:linenos:
@@ -85,7 +85,7 @@ For the cartpole task, we will use the following reward terms:
* **Cart Velocity Reward**: Encourage the agent to keep the cart velocity as small as possible.
* **Pole Velocity Reward**: Encourage the agent to keep the pole velocity as small as possible.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
:language: python
:pyobject: RewardsCfg
@@ -108,7 +108,7 @@ The flag :attr:`managers.TerminationsCfg.time_out` specifies whether the term is
or terminated term. These are used to indicate the two types of terminations as described in `Gymnasium's documentation
`_.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
:language: python
:pyobject: TerminationsCfg
@@ -139,7 +139,7 @@ With all the above components defined, we can now create the :class:`ManagerBase
cartpole environment. This is similar to the :class:`ManagerBasedEnvCfg` defined in :ref:`tutorial-create-manager-base-env`,
only with the added RL components explained in the above sections.
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py
:language: python
:pyobject: CartpoleEnvCfg
@@ -152,7 +152,7 @@ The only difference is that we create an instance of :class:`envs.ManagerBasedRL
such as the reward and termination status. The information dictionary also maintains logging of quantities
such as the reward contribution from individual terms, the termination status of each term, the episode length etc.
-.. literalinclude:: ../../../../scripts/tutorials/03_envs/run_cartpole_rl_env.py
+.. literalinclude:: ../../../scripts/tutorials/03_envs/run_cartpole_rl_env.py
:language: python
:pyobject: main
@@ -173,7 +173,7 @@ returns more signals that specify the reward and termination status. Additionall
environments reset themselves when they terminate based on the termination criteria specified in the
configuration.
-.. figure:: ../../_static/tutorials/tutorial_create_manager_rl_env.jpg
+.. figure:: ../_static/tutorials/tutorial_create_manager_rl_env.jpg
:align: center
:figwidth: 100%
:alt: result of run_cartpole_rl_env.py
diff --git a/docs/source/tutorials/02_scene/create_scene.rst b/docs/source/how-to/create_scene.rst
similarity index 95%
rename from docs/source/tutorials/02_scene/create_scene.rst
rename to docs/source/how-to/create_scene.rst
index 217d2b3c1754..e3f67178607c 100644
--- a/docs/source/tutorials/02_scene/create_scene.rst
+++ b/docs/source/how-to/create_scene.rst
@@ -40,7 +40,7 @@ This tutorial corresponds to the ``create_scene.py`` script within
.. dropdown:: Code for create_scene.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/02_scene/create_scene.py
+ .. literalinclude:: ../../../scripts/tutorials/02_scene/create_scene.py
:language: python
:emphasize-lines: 50-63, 68-70, 91-92, 99-100, 105-106, 116-118
:linenos:
@@ -63,7 +63,7 @@ to create the scene.
For the cartpole example, we specify the same scene as in the previous tutorial, but list
them now in the configuration class :class:`CartpoleSceneCfg` instead of manually spawning them.
-.. literalinclude:: ../../../../scripts/tutorials/02_scene/create_scene.py
+.. literalinclude:: ../../../scripts/tutorials/02_scene/create_scene.py
:language: python
:pyobject: CartpoleSceneCfg
@@ -108,7 +108,7 @@ object to its constructor. While creating the configuration instance of ``Cartpo
we specify how many environment copies we want to create using the ``num_envs`` argument.
This will be used to clone the scene for each environment.
-.. literalinclude:: ../../../../scripts/tutorials/02_scene/create_scene.py
+.. literalinclude:: ../../../scripts/tutorials/02_scene/create_scene.py
:language: python
:start-at: # Design scene
:end-at: scene = InteractiveScene(scene_cfg)
@@ -122,7 +122,7 @@ scene elements can be accessed from the :class:`InteractiveScene` object using t
entity. The key is specified through the configuration class for each entity. For example,
the cartpole is specified using the key ``"cartpole"`` in the configuration class.
-.. literalinclude:: ../../../../scripts/tutorials/02_scene/create_scene.py
+.. literalinclude:: ../../../scripts/tutorials/02_scene/create_scene.py
:language: python
:start-at: # Extract scene entities
:end-at: robot = scene["cartpole"]
@@ -167,7 +167,7 @@ This should open a stage with 32 cartpoles swinging around randomly. You can use
mouse to rotate the camera and the arrow keys to move around the scene.
-.. figure:: ../../_static/tutorials/tutorial_creating_a_scene.jpg
+.. figure:: ../_static/tutorials/tutorial_creating_a_scene.jpg
:align: center
:figwidth: 100%
:alt: result of create_scene.py
diff --git a/docs/source/how-to/import_new_asset.rst b/docs/source/how-to/import_new_asset.rst
index 4e01ae8a5751..04e7e8f12d88 100644
--- a/docs/source/how-to/import_new_asset.rst
+++ b/docs/source/how-to/import_new_asset.rst
@@ -48,15 +48,15 @@ Standalone URDF/MJCF importers
The URDF and MJCF converter scripts run without Isaac Sim. The standalone
importers are optional; install them with the ``isaaclab[importers]`` command in
:ref:`installation-importers-extra` before running these scripts.
-Optionally pass ``--viz newton`` (or ``rerun`` / ``viser``) to preview the converted asset in a
+Optionally pass ``--viz newton_gl`` (or ``rerun`` / ``viser``) to preview the converted asset in a
kit-less Isaac Lab visualizer:
.. code-block:: bash
- uv run --extra importers python scripts/tools/convert_urdf.py \
+ uv run --extra importers isaaclab -p scripts/tools/convert_urdf.py \
path/to/robot.urdf path/to/output_dir --merge_joints
- uv run --extra importers python scripts/tools/convert_mjcf.py \
+ uv run --extra importers isaaclab -p scripts/tools/convert_mjcf.py \
path/to/model.xml path/to/output.usd --merge_mesh
If Isaac Sim is installed in the same environment, Isaac Lab uses the Isaac Sim importer
@@ -64,6 +64,42 @@ extensions first. The standalone wheel is used only when the full Isaac Sim runt
available.
+.. _import-new-asset-multi-backend:
+
+Multi-backend assets
+--------------------
+
+A converted asset can carry shared USD physics and backend-specific attributes. The
+Isaac Sim 6.1 standalone URDF and MJCF importers produce layered output such as:
+
+.. code-block:: text
+
+ robot_name.usda interface USD and Physics variant selection
+ payloads/base.usda composed asset
+ payloads/instances.usda reusable geometry
+ payloads/Physics/physics.usda shared physics and compatible backend attributes
+
+Additional physics layers depend on the source asset and importer version. A layer named
+``physx.usda`` or ``mujoco.usda`` does not by itself mean that a variant with that name exists.
+Inspect the interface USD's ``Physics`` variant set before requesting a backend-specific variant.
+
+:attr:`~sim.converters.AssetConverterBaseCfg.physics_variant` defaults to ``physics``.
+The tested Isaac Sim 6.1 output exposes ``physics`` and ``none``; ``none`` omits the physics
+payload. Isaac Lab selects the requested variant explicitly and raises an error if the
+asset has a ``Physics`` variant set without that variant. Do not assume that ``physx``
+or ``mujoco`` is selectable on every converted asset.
+
+``run_multi_physics_conversion``, enabled by default, asks the importer to convert supported
+backend-specific physics attributes. This does not guarantee equivalent solver behavior or
+support for every source feature. Validate masses, inertias, collisions and joint control on
+the intended physics backend.
+
+With ``run_asset_transformer=False``, the tested converters produce flat output without a
+``Physics`` variant set. Isaac Lab leaves that output unchanged rather than selecting a variant.
+For an existing layered asset, :attr:`~sim.UsdFileCfg.variants` can override an available
+selection at spawn time.
+Use :ref:`asset-config-backends` to choose configuration overrides for the selected backend.
+
Using URDF Importer
-------------------
@@ -129,7 +165,8 @@ Asset resolution and output
* :attr:`~sim.converters.UrdfConverterCfg.run_asset_transformer` - Run the asset transformer to convert
the flattened USD into a layered USD (interface USD + payloads). Defaults to ``True``.
* :attr:`~sim.converters.UrdfConverterCfg.run_multi_physics_conversion` - Also emit MuJoCo-compatible joint
- attributes alongside PhysX. Defaults to ``True``.
+ attributes alongside the PhysX ones, so the asset carries both backends. Defaults to ``True``.
+ See :ref:`import-new-asset-multi-backend`.
* :attr:`~sim.converters.UrdfConverterCfg.debug_mode` - Write intermediate conversion artifacts next to the
output USD for inspection. Defaults to ``False``.
@@ -158,14 +195,19 @@ pre-processed URDF and the original URDF are:
* We removed the ```` tag from the URDF. This tag is not supported by the URDF importer.
* We removed the ```` tag from the URDF. This tag is not supported by the URDF importer.
* We removed various collision bodies from the URDF to reduce the complexity of the asset.
-* We changed all the joint's damping and friction parameters to ``0.0``. This ensures that we can perform
- effort-control on the joints without PhysX adding additional damping.
+* We changed all the joint's damping and friction parameters to ``0.0``. On PhysX this ensures that we
+ can perform effort-control on the joints without the imported drive adding damping of its own. On
+ Newton the actuator configuration decides the target mode instead --- see
+ :ref:`import-new-asset-ensure-drives-exist`.
* The ```` URDF tag is **no longer supported** in URDF importer 3.0. Fixed joint
merging is now a Python pre-processing step that merges all fixed joints when
``merge_fixed_joints`` is enabled. If you need to preserve a specific fixed joint, disable
``merge_fixed_joints`` entirely or restructure the URDF to use a non-fixed joint type
(e.g. revolute with zero-range limits).
+Map the ROS package directory with ``--ros_package_path NAME PATH`` so the importer can
+resolve the robot's ``package://`` mesh references, including when fixed joints are merged.
+
The following shows the steps to clone the repository and run the converter:
@@ -183,10 +225,11 @@ The following shows the steps to clone the repository and run the converter:
# go to top of the Isaac Lab repository
cd IsaacLab
# run the converter
- python scripts/tools/convert_urdf.py \
+ uv run --extra importers isaaclab -p scripts/tools/convert_urdf.py \
../anymal_d_simple_description/urdf/anymal.urdf \
source/isaaclab_assets/data/Robots/ANYbotics/ \
--merge_joints \
+ --ros_package_path anymal_d_simple_description ../anymal_d_simple_description \
--joint_stiffness 0.0 \
--joint_damping 0.0 \
--joint_target_type none \
@@ -203,10 +246,11 @@ The following shows the steps to clone the repository and run the converter:
:: go to top of the Isaac Lab repository
cd IsaacLab
:: run the converter
- python scripts\tools\convert_urdf.py ^
+ uv run --extra importers isaaclab -p scripts\tools\convert_urdf.py ^
..\anymal_d_simple_description\urdf\anymal.urdf ^
source\isaaclab_assets\data\Robots\ANYbotics\ ^
--merge_joints ^
+ --ros_package_path anymal_d_simple_description ..\anymal_d_simple_description ^
--joint_stiffness 0.0 ^
--joint_damping 0.0 ^
--joint_target_type none ^
@@ -227,12 +271,15 @@ is derived automatically from the robot name in the URDF):
actually used. Delete stale subdirectories manually (or wipe ``usd_dir``) if you do not
want them to accumulate on disk.
-The examples above pass ``--viz kit`` to open the converted asset in the Isaac Sim viewport, which
-requires a full Isaac Sim installation. Name a kitless backend instead -- ``--viz newton``,
-``--viz rerun``, or ``--viz viser`` -- to preview the asset without Kit. Omit ``--viz`` to exit
-after the conversion completes.
+.. _import-new-asset-preview:
+
+The examples pass ``--viz kit`` to open the converted asset in the Isaac Sim viewport, which
+requires a full Isaac Sim installation. Use ``--viz newton_gl``, ``--viz rerun``, or ``--viz viser``
+for a kit-less preview instead. Omit ``--viz`` to exit as soon as the conversion completes.
-In Isaac Sim, you can press play on the opened window to see the asset in the scene. The asset should fall under gravity. If it blows up, then it might be that you have self-collisions present in the URDF.
+Inspect the converted geometry and articulation in the viewer, then validate dynamics in the
+intended simulation backend. Check self-collisions, masses, inertias, and actuator gains if
+the asset is unstable.
.. figure:: ../_static/tutorials/tutorial_convert_urdf.jpg
@@ -310,7 +357,9 @@ Asset resolution and output
* :attr:`~sim.converters.MjcfConverterCfg.run_asset_transformer` - Run the asset transformer to convert
the flattened USD into a layered USD (interface USD + payloads). Defaults to ``True``.
* :attr:`~sim.converters.MjcfConverterCfg.run_multi_physics_conversion` - Convert compatible MuJoCo
- attributes to PhysX attributes (e.g. actuator gains). Defaults to ``True``.
+ attributes to PhysX attributes (e.g. actuator gains), so the asset carries both backends. Note this
+ is the opposite direction to the URDF importer. Defaults to ``True``.
+ See :ref:`import-new-asset-multi-backend`.
* :attr:`~sim.converters.MjcfConverterCfg.debug_mode` - Write intermediate conversion artifacts next to
the output USD for inspection. Defaults to ``False``.
@@ -339,7 +388,7 @@ The following shows the steps to clone the repository and run the converter:
# go to top of the Isaac Lab repository
cd IsaacLab
# run the converter
- python scripts/tools/convert_mjcf.py \
+ uv run --extra importers isaaclab -p scripts/tools/convert_mjcf.py \
../mujoco_menagerie/unitree_h1/h1.xml \
source/isaaclab_assets/data/Robots/Unitree/h1.usd \
--merge_mesh \
@@ -356,7 +405,7 @@ The following shows the steps to clone the repository and run the converter:
:: go to top of the Isaac Lab repository
cd IsaacLab
:: run the converter
- python scripts\tools\convert_mjcf.py ^
+ uv run --extra importers isaaclab -p scripts\tools\convert_mjcf.py ^
..\mujoco_menagerie\unitree_h1\h1.xml ^
source\isaaclab_assets\data\Robots\Unitree\h1.usd ^
--merge_mesh ^
@@ -376,10 +425,7 @@ Executing the above script will create the USD file inside the
actually used. Delete stale subdirectories manually (or wipe ``usd_dir``) if you do not
want them to accumulate on disk.
-The examples above pass ``--viz kit`` to open the converted asset in the Isaac Sim viewport, which
-requires a full Isaac Sim installation. Name a kitless backend instead -- ``--viz newton``,
-``--viz rerun``, or ``--viz viser`` -- to preview the asset without Kit. Omit ``--viz`` to exit
-after the conversion completes.
+See :ref:`Previewing converted assets ` for the ``--viz`` options.
.. figure:: ../_static/tutorials/tutorial_convert_mjcf.jpg
:align: center
@@ -388,11 +434,22 @@ after the conversion completes.
.. _import-new-asset-ensure-drives-exist:
+.. _ensuring-joint-drives-exist-on-every-joint:
+
+Joint drives on each physics backend
+------------------------------------
+
+The URDF and MJCF importers write joint drives into the USD. How those drives are then
+interpreted depends on the physics backend, and on whether an Isaac Lab actuator configuration
+takes over. (Mesh assets have no joints, so none of this applies to them.)
-Ensuring joint drives exist on every joint
-------------------------------------------
+**PhysX** starts from the imported USD drive properties. Isaac Lab's actuator configuration
+can override the gains and limits before simulation. The ANYmal example above passes
+``--joint_stiffness 0.0 --joint_damping 0.0 --joint_target_type none`` so the imported
+drive does not add PD effort when the asset is used for effort control.
-When an articulation uses an Isaac Lab actuator configuration, Newton resolves
+**Newton** resolves the target mode from the Isaac Lab actuator configuration instead of from the
+USD alone. When an articulation uses an Isaac Lab actuator configuration, Newton resolves
each configured joint's target mode before constructing the solver. For an
:class:`~isaaclab.actuators.ImplicitActuatorCfg`, stiffness-only, damping-only,
both-gain, and zero-gain configurations select position, velocity, combined
@@ -400,8 +457,8 @@ position/velocity, and effort modes respectively. A gain set to ``None`` keeps
the corresponding imported USD value. An explicit actuator configuration uses
effort mode because Isaac Lab computes its effort directly.
-Joints without an Isaac Lab actuator configuration retain their imported USD
-target modes. Consequently, an asset with zero-gain USD drives no longer needs
+Joints without an Isaac Lab actuator configuration retain their imported USD settings.
+Consequently, an asset with zero-gain USD drives no longer needs
:attr:`~isaaclab.sim.schemas.JointDrivePropertiesCfg.ensure_drives_exist` solely
to make configured joints actuate in Newton.
@@ -411,7 +468,6 @@ When enabled, it assigns a minimal placeholder stiffness (``1e-3``) to zero-gain
drives before simulation startup so that every drive exists in the imported
model.
-
Using Mesh Importer
-------------------
@@ -450,12 +506,13 @@ the steps to clone the repository and run the converter:
# go to top of the Isaac Lab repository
cd IsaacLab
# run the converter
- python scripts/tools/convert_mesh.py \
+ uv run isaaclab -p scripts/tools/convert_mesh.py \
../IsaacGymEnvs/assets/trifinger/objects/meshes/cube_multicolor.obj \
source/isaaclab_assets/data/Props/CubeMultiColor/cube_multicolor.usd \
--make-instanceable \
--collision-approximation convexDecomposition \
- --mass 1.0
+ --mass 1.0 \
+ --viz kit
.. tab-item:: :icon:`fa-brands fa-windows` Windows
:sync: windows
@@ -468,24 +525,23 @@ the steps to clone the repository and run the converter:
:: go to top of the Isaac Lab repository
cd IsaacLab
:: run the converter
- python scripts\tools\convert_mesh.py ^
+ uv run isaaclab -p scripts\tools\convert_mesh.py ^
..\IsaacGymEnvs\assets\trifinger\objects\meshes\cube_multicolor.obj ^
source\isaaclab_assets\data\Props\CubeMultiColor\cube_multicolor.usd ^
--make-instanceable ^
--collision-approximation convexDecomposition ^
- --mass 1.0
-
-You may need to press 'F' to zoom in on the asset after import.
+ --mass 1.0 ^
+ --viz kit
-Similar to the URDF and MJCF converter, executing the above script will create two USD files inside the
-``source/isaaclab_assets/data/Props/CubeMultiColor/`` directory. Additionally,
-if you press play on the opened window, you should see the asset fall down under the influence
-of gravity.
+The mesh converter requires Isaac Sim. The command writes the converted USD and its
+instanceable mesh payload under ``source/isaaclab_assets/data/Props/CubeMultiColor/`` and opens
+the Isaac Sim viewport. Select the asset and press ``F`` to frame it in the viewport.
+Omit ``--viz kit`` to convert without opening a preview.
* If you do not set the ``--mass`` flag, then no rigid body properties will be added to the asset.
It will be imported as a static asset.
-* If you also do not set the ``--collision-approximation`` flag, then the asset will not have any collider
- properties as well and will be imported as a visual asset.
+* Set ``--collision-approximation none`` to omit collider properties. The default is
+ ``convexDecomposition``, so omitting this flag still creates collision geometry.
.. figure:: ../_static/tutorials/tutorial_convert_mesh.jpg
diff --git a/docs/source/how-to/index.rst b/docs/source/how-to/index.rst
index a2c141bc44ad..f027347dffdd 100644
--- a/docs/source/how-to/index.rst
+++ b/docs/source/how-to/index.rst
@@ -1,4 +1,5 @@
.. _tutorials:
+.. _tutorials-have-moved:
.. _how-to:
How-to Guides
@@ -41,53 +42,49 @@ How-to Guides
.. container:: guide-entry
- :doc:`Creating an empty scene `
+ :doc:`Creating an empty scene `
Launch an empty simulation and learn the core startup sequence.
.. container:: guide-entry
- :doc:`Spawning prims into the scene `
+ :doc:`Spawning prims into the scene `
Add lights, ground planes, and primitive shapes to a simulation stage.
.. container:: guide-entry
- :doc:`Deep-dive into AppLauncher `
+ :doc:`Deep-dive into AppLauncher `
Configure and launch simulation applications from Python and the command line.
.. container:: guide-group
- .. rubric:: Assets
-
- .. container:: guide-entry
+ .. _asset-authoring:
- :doc:`Adding a new robot to Isaac Lab `
-
- Bring a robot asset into Isaac Lab and define its articulation configuration.
+ .. rubric:: Assets
.. container:: guide-entry
- :doc:`Interacting with a rigid object `
+ :doc:`Interacting with a rigid object `
- Create, reset, and command a rigid object through the simulation API.
+ Create, reset, and command a cone; includes the runnable run_rigid_object.py example.
.. container:: guide-entry
- :doc:`Interacting with an articulation `
+ :doc:`Interacting with an articulation `
Work with joint state, commands, and articulation data.
.. container:: guide-entry
- :doc:`Interacting with a deformable object `
+ :doc:`Interacting with a deformable object `
Spawn and manipulate deformable bodies in a scene.
.. container:: guide-entry
- :doc:`Interacting with a surface gripper `
+ :doc:`Interacting with a surface gripper `
Attach and release rigid objects with a surface gripper.
@@ -99,15 +96,9 @@ How-to Guides
.. container:: guide-entry
- :doc:`Writing an asset configuration `
-
- Turn an imported robot into a reusable articulation configuration.
-
- .. container:: guide-entry
-
- :doc:`Robot configurations `
+ :doc:`Robot and articulation configuration `
- Understand the structure and conventions of supported robot configurations.
+ Reuse or author a robot configuration, with a Jetbot/Dofbot worked example.
.. container:: guide-entry
@@ -133,7 +124,7 @@ How-to Guides
.. container:: guide-entry
- :doc:`Using the interactive scene `
+ :doc:`Using the interactive scene `
Compose assets and sensors with the higher-level interactive scene interface.
@@ -149,49 +140,49 @@ How-to Guides
.. container:: guide-entry
- :doc:`Creating a manager-based base environment `
+ :doc:`Creating a manager-based base environment `
Build a non-RL environment from reusable manager terms.
.. container:: guide-entry
- :doc:`Creating a manager-based RL environment `
+ :doc:`Creating a manager-based RL environment `
Add rewards, terminations, curricula, and commands for reinforcement learning.
.. container:: guide-entry
- :doc:`Creating a direct workflow RL environment `
+ :doc:`Creating a direct workflow RL environment `
Implement an RL task with direct control over the environment loop.
.. container:: guide-entry
- :doc:`Registering an environment `
+ :doc:`Registering an environment `
Register an Isaac Lab task with Gymnasium and expose its configurations.
.. container:: guide-entry
- :doc:`Training with an RL agent `
+ :doc:`Training with an RL agent `
Launch training and inference with a supported reinforcement learning library.
.. container:: guide-entry
- :doc:`Configuring an RL agent `
+ :doc:`Configuring an RL agent `
Customize agent settings and training hyperparameters.
.. container:: guide-entry
- :doc:`Modifying an existing direct RL environment `
+ :doc:`Modifying an existing direct RL environment `
Extend and adjust a direct workflow task without rebuilding it from scratch.
.. container:: guide-entry
- :doc:`Policy inference in a USD environment `
+ :doc:`Policy inference in a USD environment `
Run a trained policy against an environment defined in a USD stage.
@@ -231,7 +222,7 @@ How-to Guides
.. container:: guide-entry
- :doc:`Adding sensors on a robot `
+ :doc:`Adding sensors on a robot `
Add camera, ray-caster, and contact sensors to an environment.
@@ -265,13 +256,13 @@ How-to Guides
.. container:: guide-entry
- :doc:`Using a task-space controller `
+ :doc:`Using a task-space controller `
Control a robot end effector with differential inverse kinematics.
.. container:: guide-entry
- :doc:`Using an operational space controller `
+ :doc:`Using an operational space controller `
Apply operational-space control to a robot manipulator.
diff --git a/docs/source/tutorials/00_sim/launch_app.rst b/docs/source/how-to/launch_app.rst
similarity index 98%
rename from docs/source/tutorials/00_sim/launch_app.rst
rename to docs/source/how-to/launch_app.rst
index 113da2021e0f..655ab30c4708 100644
--- a/docs/source/tutorials/00_sim/launch_app.rst
+++ b/docs/source/how-to/launch_app.rst
@@ -30,7 +30,7 @@ The tutorial corresponds to the ``launch_app.py`` script in the
.. dropdown:: Code for launch_app.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/00_sim/launch_app.py
+ .. literalinclude:: ../../../scripts/tutorials/00_sim/launch_app.py
:language: python
:emphasize-lines: 18-40
:linenos:
@@ -56,7 +56,7 @@ arguments appended. This can then be processed into an :class:`argparse.Namespac
standard :meth:`argparse.ArgumentParser.parse_args` method and passed directly to
:class:`~app.AppLauncher` for instantiation.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/launch_app.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/launch_app.py
:language: python
:start-at: import argparse
:end-at: simulation_app = app_launcher.app
@@ -240,7 +240,7 @@ envar. If a visualization is desired, we could get one via Isaac's `WebRTC Lives
is currently the only supported method of visualization from within the container. The
process can be killed by pressing ``Ctrl+C`` in the launching terminal.
-.. figure:: ../../_static/tutorials/tutorial_launch_app.jpg
+.. figure:: ../_static/tutorials/tutorial_launch_app.jpg
:align: center
:figwidth: 100%
:alt: result of launch_app.py
diff --git a/docs/source/how-to/make_fixed_prim.rst b/docs/source/how-to/make_fixed_prim.rst
index c9e75019de7b..ce385a7ba363 100644
--- a/docs/source/how-to/make_fixed_prim.rst
+++ b/docs/source/how-to/make_fixed_prim.rst
@@ -12,6 +12,10 @@ i.e. the prim should still participate in collisions but its position and orient
The following sections describe how to spawn a prim with physics schemas and make it static in the simulation world.
+Static colliders and fixed articulation roots use shared USD topology on PhysX and Newton.
+Use the shared configurations below for these operations. Backend-specific solver settings are
+covered in :ref:`asset-config-backends`.
+
Static colliders
----------------
@@ -19,20 +23,19 @@ Static colliders are prims that are not affected by physics but can collide with
These don't have any rigid body properties applied on them. However, this also means that they can't be accessed
using the physics tensor API (i.e., through the :class:`assets.RigidObject` class).
-For instance, to spawn a cone static in the simulation world, the following code can be used:
+For instance, to spawn a sphere static in the simulation world, the following code can be used:
.. code-block:: python
import isaaclab.sim as sim_utils
- cone_spawn_cfg = sim_utils.ConeCfg(
+ sphere_spawn_cfg = sim_utils.SphereCfg(
radius=0.15,
- height=0.5,
- collision_props=sim_utils.CollisionPropertiesCfg(),
+ collision_props=sim_utils.CollisionBaseCfg(),
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
)
- cone_spawn_cfg.func(
- "/World/Cone", cone_spawn_cfg, translation=(0.0, 0.0, 2.0), orientation=(0.5, 0.0, 0.5, 0.0)
+ sphere_spawn_cfg.func(
+ "/World/Sphere", sphere_spawn_cfg, translation=(0.0, 0.0, 2.0)
)
@@ -40,26 +43,26 @@ Rigid object
------------
Rigid objects (i.e. object only has a single body) can be made static by setting the parameter
-:attr:`sim.schemas.RigidBodyPropertiesCfg.kinematic_enabled` as True. This will make the object
-kinematic and it will not be affected by physics.
+:attr:`sim.schemas.RigidBodyBaseCfg.kinematic_enabled` as True. This will make the object
+kinematic: its motion is prescribed by user code rather than integrated from gravity and
+forces. Without prescribed motion, it stays fixed. It can still participate in collisions.
-For instance, to spawn a cone static in the simulation world but with rigid body schema on it,
+For instance, to spawn a sphere static in the simulation world but with rigid body schema on it,
the following code can be used:
.. code-block:: python
import isaaclab.sim as sim_utils
- cone_spawn_cfg = sim_utils.ConeCfg(
+ sphere_spawn_cfg = sim_utils.SphereCfg(
radius=0.15,
- height=0.5,
- rigid_props=sim_utils.RigidBodyPropertiesCfg(kinematic_enabled=True),
+ rigid_props=sim_utils.RigidBodyBaseCfg(kinematic_enabled=True),
mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
- collision_props=sim_utils.CollisionPropertiesCfg(),
+ collision_props=sim_utils.CollisionBaseCfg(),
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
)
- cone_spawn_cfg.func(
- "/World/Cone", cone_spawn_cfg, translation=(0.0, 0.0, 2.0), orientation=(0.5, 0.0, 0.5, 0.0)
+ sphere_spawn_cfg.func(
+ "/World/Sphere", sphere_spawn_cfg, translation=(0.0, 0.0, 2.0)
)
@@ -67,115 +70,106 @@ Articulation
------------
Fixing the root of an articulation requires having a fixed joint to the root rigid body link of the articulation.
-This can be achieved by setting the parameter :attr:`sim.schemas.ArticulationRootPropertiesCfg.fix_root_link`
+This can be achieved by setting the parameter :attr:`sim.schemas.ArticulationRootBaseCfg.fix_root_link`
as True. Based on the value of this parameter, the following cases are possible:
* If set to :obj:`None`, the root link is not modified.
* If the articulation already has a fixed root link, this flag will enable or disable the fixed joint.
* If the articulation does not have a fixed root link, this flag will create a fixed joint between the world
- frame and the root link. The joint is created with the name "FixedJoint" under the root link.
+ frame and the root link, under a writable prim in the asset hierarchy.
-For instance, to spawn an ANYmal robot and make it static in the simulation world, the following code can be used:
+For instance, to spawn an ANYmal robot and fix its base while leaving its joints movable, the following code can be used:
.. code-block:: python
import isaaclab.sim as sim_utils
+ from isaaclab.sim.schemas import ArticulationRootBaseCfg
from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR
anymal_spawn_cfg = sim_utils.UsdFileCfg(
usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd",
- activate_contact_sensors=True,
- rigid_props=sim_utils.RigidBodyPropertiesCfg(
- disable_gravity=False,
- retain_accelerations=False,
- linear_damping=0.0,
- angular_damping=0.0,
- max_linear_velocity=1000.0,
- max_angular_velocity=1000.0,
- max_depenetration_velocity=1.0,
- ),
- articulation_props=sim_utils.ArticulationRootPropertiesCfg(
- enabled_self_collisions=True,
- solver_position_iteration_count=4,
- solver_velocity_iteration_count=0,
- fix_root_link=True,
- ),
+ articulation_props=ArticulationRootBaseCfg(fix_root_link=True),
)
anymal_spawn_cfg.func(
"/World/ANYmal", anymal_spawn_cfg, translation=(0.0, 0.0, 0.8), orientation=(0.0, 0.0, 0.0, 1.0)
)
-This will create a fixed joint between the world frame and the root link of the ANYmal robot
-at the prim path ``"/World/ANYmal/base/FixedJoint"`` since the root link is at the path ``"/World/ANYmal/base"``.
+This creates a fixed joint between the world frame and the root link of the ANYmal robot.
+The joint is authored under a writable prim; its exact path depends on the asset's root
+and instancing layout.
+For a spawn configuration using schema fragments, or no ``articulation_props``, set
+``UsdFileCfg(fix_root_link=True, ...)`` instead. When using a legacy properties configuration
+as above, keep ``fix_root_link`` on that configuration. Both paths author the fixed joint
+before the backend imports the articulation.
-Further notes
--------------
+.. _further-notes:
-Given the flexibility of USD asset designing the following possible scenarios are usually encountered:
+.. dropdown:: PhysX articulation-root placement details
-1. **Articulation root schema on the rigid body prim without a fixed joint**:
+ The following parser details explain the PhysX-specific root-placement adjustment. Newton
+ imports the resulting USD joint topology; do not apply PhysX parser heuristics as Newton
+ configuration rules.
- This is the most common and recommended scenario for floating-base articulations. The root prim
- has both the rigid body and the articulation root properties. In this case, the articulation root
- is parsed as a floating-base with the root prim of the articulation ``Link0Xform``.
+ Given the flexibility of USD asset designing the following possible scenarios are usually encountered:
- .. code-block:: text
+ 1. **Articulation root schema on the rigid body prim without a fixed joint**:
- ArticulationXform
- └── Link0Xform (RigidBody and ArticulationRoot schema)
+ This is the most common and recommended scenario for floating-base articulations. The root prim
+ has both the rigid body and the articulation root properties. In this case, the articulation root
+ is parsed as a floating-base with the root prim of the articulation ``Link0Xform``.
-2. **Articulation root schema on the parent prim with a fixed joint**:
+ .. code-block:: text
- This is the expected arrangement for fixed-base articulations. The root prim has only the rigid body
- properties and the articulation root properties are applied to its parent prim. In this case, the
- articulation root is parsed as a fixed-base with the root prim of the articulation ``Link0Xform``.
+ ArticulationXform
+ └── Link0Xform (RigidBody and ArticulationRoot schema)
- .. code-block:: text
+ 2. **Articulation root schema on the parent prim with a fixed joint**:
- ArticulationXform (ArticulationRoot schema)
- └── Link0Xform (RigidBody schema)
- └── FixedJoint (connecting the world frame and Link0Xform)
+ This is the expected arrangement for fixed-base articulations. The root prim has only the rigid body
+ properties and the articulation root properties are applied to its parent prim. In this case, the
+ articulation root is parsed as a fixed-base with the root prim of the articulation ``Link0Xform``.
-3. **Articulation root schema on the parent prim without a fixed joint**:
+ .. code-block:: text
- This is a scenario where the root prim has only the rigid body properties and the articulation root properties
- are applied to its parent prim. However, the fixed joint is not created between the world frame and the root link.
- In this case, the articulation is parsed as a floating-base system. However, the PhysX parser uses its own
- heuristic (such as alphabetical order) to determine the root prim of the articulation. It may select the root prim
- at ``Link0Xform`` or choose another prim as the root prim.
+ ArticulationXform (ArticulationRoot schema)
+ └── Link0Xform (RigidBody schema)
+ └── FixedJoint (connecting the world frame and Link0Xform)
- .. code-block:: text
+ 3. **Articulation root schema on the parent prim without a fixed joint**:
- ArticulationXform (ArticulationRoot schema)
- └── Link0Xform (RigidBody schema)
+ This is a scenario where the root prim has only the rigid body properties and the articulation root properties
+ are applied to its parent prim. However, the fixed joint is not created between the world frame and the root link.
+ In this case, the articulation is parsed as a floating-base system. However, the PhysX parser uses its own
+ heuristic (such as alphabetical order) to determine the root prim of the articulation. It may select the root prim
+ at ``Link0Xform`` or choose another prim as the root prim.
-4. **Articulation root schema on the rigid body prim with a fixed joint**:
+ .. code-block:: text
- While this is a valid scenario, it is not recommended as it may lead to unexpected behavior. In this case,
- the articulation is still parsed as a floating-base system. However, the fixed joint, created between the
- world frame and the root link, is considered as a part of the maximal coordinate tree. This is different from
- PhysX considering the articulation as a fixed-base system. Hence, the simulation may not behave as expected.
+ ArticulationXform (ArticulationRoot schema)
+ └── Link0Xform (RigidBody schema)
- .. code-block:: text
+ 4. **Articulation root schema on the rigid body prim with a fixed joint**:
- ArticulationXform
- └── Link0Xform (RigidBody and ArticulationRoot schema)
- └── FixedJoint (connecting the world frame and Link0Xform)
+ While this is a valid scenario, it is not recommended as it may lead to unexpected behavior. In this case,
+ the articulation is still parsed as a floating-base system. However, the fixed joint, created between the
+ world frame and the root link, is considered as a part of the maximal coordinate tree. This is different from
+ PhysX considering the articulation as a fixed-base system. Hence, the simulation may not behave as expected.
-For floating base articulations, the root prim usually has both the rigid body and the articulation
-root properties. However, directly connecting this prim to the world frame will cause the simulation
-to consider the fixed joint as a part of the maximal coordinate tree. This is different from PhysX
-considering the articulation as a fixed-base system.
+ .. code-block:: text
-Internally, when the parameter :attr:`sim.schemas.ArticulationRootPropertiesCfg.fix_root_link` is set to True
-and the articulation is detected as a floating-base system, the fixed joint is created between the world frame
-the root rigid body link of the articulation. However, to make the PhysX parser consider the articulation as a
-fixed-base system, the articulation root properties are removed from the root rigid body prim and applied to
-its parent prim instead.
+ ArticulationXform
+ └── Link0Xform (RigidBody and ArticulationRoot schema)
+ └── FixedJoint (connecting the world frame and Link0Xform)
-.. note::
+ For floating base articulations, the root prim usually has both the rigid body and the articulation
+ root properties. However, directly connecting this prim to the world frame will cause the simulation
+ to consider the fixed joint as a part of the maximal coordinate tree. This is different from PhysX
+ considering the articulation as a fixed-base system.
- In future release of Isaac Sim, an explicit flag will be added to the articulation root schema from PhysX
- to toggle between fixed-base and floating-base systems. This will resolve the need of the above workaround.
+ Internally, when the parameter :attr:`sim.schemas.ArticulationRootBaseCfg.fix_root_link` is set to True
+ and the articulation is detected as a floating-base system, the fixed joint is created between the world frame
+ the root rigid body link of the articulation. However, to make the PhysX parser consider the articulation as a
+ fixed-base system, the articulation root properties are removed from the root rigid body prim and applied to
+ its parent prim instead.
diff --git a/docs/source/tutorials/03_envs/modify_direct_rl_env.rst b/docs/source/how-to/modify_direct_rl_env.rst
similarity index 87%
rename from docs/source/tutorials/03_envs/modify_direct_rl_env.rst
rename to docs/source/how-to/modify_direct_rl_env.rst
index d1c65ce18d79..380a7ea24b48 100644
--- a/docs/source/tutorials/03_envs/modify_direct_rl_env.rst
+++ b/docs/source/how-to/modify_direct_rl_env.rst
@@ -26,7 +26,7 @@ For this tutorial, we start from the direct workflow Humanoid environment define
.. dropdown:: Code for humanoid_direct_env.py
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/locomotion/humanoid/humanoid_direct_env.py
+ .. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/locomotion/humanoid/humanoid_direct_env.py
:language: python
:linenos:
@@ -57,12 +57,12 @@ Refer to the :ref:`tutorial-register-rl-env-gym` tutorial for more details about
to avoid altering the original configurations.
-.. literalinclude:: ../../refs/snippets/tutorial_modify_direct_rl_env.py
+.. literalinclude:: ../refs/snippets/tutorial_modify_direct_rl_env.py
:language: python
:start-after: [start-init-import]
:end-before: [end-init-import]
-.. literalinclude:: ../../refs/snippets/tutorial_modify_direct_rl_env.py
+.. literalinclude:: ../refs/snippets/tutorial_modify_direct_rl_env.py
:language: python
:start-after: [start-init-register]
:end-before: [end-init-register]
@@ -77,7 +77,7 @@ Since the Unitree H1 robot is included in the Isaac Lab assets extension (``isaa
and do the replacement directly (under the ``H1EnvCfg.robot`` property), as shown below. Note that we also need to modify the
``joint_gears`` property as it holds robot-specific configuration values.
-.. |franka-direct-link| replace:: `Isaac-Open-Drawer-Franka-Direct <../../../../source/isaaclab_tasks/isaaclab_tasks/core/cabinet/cabinet_direct_env.py>`__
+.. |franka-direct-link| replace:: :isaaclab-source:`Isaac-Open-Drawer-Franka-Direct `
.. hint::
@@ -85,14 +85,14 @@ and do the replacement directly (under the ``H1EnvCfg.robot`` property), as show
by using the :class:`~isaaclab.assets.ArticulationCfg` class.
* See the |franka-direct-link| source code for an example of loading and configuring a robot from a USD file.
- * Refer to the `Importing a New Asset <../../how-to/import_new_asset.html>`_ tutorial for details on how to import an asset from URDF or MJCF file, and other formats.
+ * Refer to the :doc:`Importing a New Asset ` tutorial for details on how to import an asset from URDF or MJCF file, and other formats.
-.. literalinclude:: ../../refs/snippets/tutorial_modify_direct_rl_env.py
+.. literalinclude:: ../refs/snippets/tutorial_modify_direct_rl_env.py
:language: python
:start-after: [start-h1_env-import]
:end-before: [end-h1_env-import]
-.. literalinclude:: ../../refs/snippets/tutorial_modify_direct_rl_env.py
+.. literalinclude:: ../refs/snippets/tutorial_modify_direct_rl_env.py
:language: python
:start-after: [start-h1_env-robot]
:end-before: [end-h1_env-robot]
@@ -101,7 +101,7 @@ The robot changed, and with it the number of joints to control or the number of
Therefore, it is also necessary to adjust other values in the environment configuration that depend on the characteristics of the robot,
such as the number of elements in the observation and action space.
-.. literalinclude:: ../../refs/snippets/tutorial_modify_direct_rl_env.py
+.. literalinclude:: ../refs/snippets/tutorial_modify_direct_rl_env.py
:language: python
:start-after: [start-h1_env-spaces]
:end-before: [end-h1_env-spaces]
@@ -143,7 +143,7 @@ where you started the simulation.
./isaaclab.sh play --rl_library rl_games --task Isaac-H1-Direct-v0 --num_envs 64 --viz kit
-.. figure:: ../../_static/tutorials/tutorial_modify_direct_rl_env.jpg
+.. figure:: ../_static/tutorials/tutorial_modify_direct_rl_env.jpg
:align: center
:figwidth: 100%
:alt: result of training Isaac-H1-Direct-v0 task
diff --git a/docs/source/tutorials/03_envs/policy_inference_in_usd.rst b/docs/source/how-to/policy_inference_in_usd.rst
similarity index 63%
rename from docs/source/tutorials/03_envs/policy_inference_in_usd.rst
rename to docs/source/how-to/policy_inference_in_usd.rst
index e2d6133176f5..9a9bd84eab37 100644
--- a/docs/source/tutorials/03_envs/policy_inference_in_usd.rst
+++ b/docs/source/how-to/policy_inference_in_usd.rst
@@ -8,7 +8,8 @@ Policy Inference in USD Environment
.. currentmodule:: isaaclab
-Having learnt how to modify a task in :ref:`tutorial-modify-direct-rl-env`, we will now look at how to run a trained policy in a prebuilt USD scene.
+This deployment example runs a trained policy in a prebuilt USD scene using the training task's
+observations, actions, and robot configuration.
In this tutorial, we will use the RSL RL library and the trained policy from the Humanoid Rough Terrain ``Isaac-Velocity-Rough-H1`` task in a simple warehouse USD.
@@ -18,8 +19,8 @@ The Tutorial Code
For this tutorial, we use the trained policy's checkpoint exported as jit (which is an offline version of the policy).
-The ``H1RoughEnvCfg`` cfg encapsulates the configuration values of the environment, including the assets to
-be instantiated. Calling its ``play_mode`` method applies the play/inference overrides
+The script resolves ``H1RoughEnvCfg`` with ``parse_env_cfg``, including any physics preset passed
+on the command line. Calling its ``play_mode`` method applies the play/inference overrides
(such as a reduced number of environments and disabled observation noise) on top of the training configuration.
In order to use a prebuilt USD environment instead of the terrain generator specified, we make the
@@ -28,14 +29,22 @@ following changes to the config before passing it to the ``ManagerBasedRLEnv``.
.. dropdown:: Code for policy_inference_in_usd.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/03_envs/policy_inference_in_usd.py
+ .. literalinclude:: ../../../scripts/tutorials/03_envs/policy_inference_in_usd.py
:language: python
:linenos:
- :emphasize-lines: 60-69
+ :emphasize-lines: 53-60
-Note that we have set the device to ``CPU`` and disabled the use of Fabric for inferencing.
-This is because when simulating a small number of environment, CPU simulation can often perform faster than GPU simulation.
+The script uses ``--device`` for both policy loading and simulation. It disables Fabric only
+when ``--device cpu`` is explicitly selected.
+The height scanner starts below the warehouse roof so its downward rays measure the floor.
+
+Keep the same physics preset for training, export, and inference. The commands below use
+Newton MJWarp with the ``newton_gl`` visualizer and do not require Isaac Sim. For a PhysX
+checkpoint trained with Isaac Sim, use ``physics=isaacsim_physx`` throughout and install Isaac Sim;
+the Newton GL viewer can still be used.
+Cross-backend policy transfer needs additional validation; see
+:doc:`transfer_policies_between_physx_and_newton`.
The Code Execution
@@ -49,13 +58,13 @@ First, we need to train the ``Isaac-Velocity-Rough-H1`` task by running the foll
.. code-block:: bash
- uv run isaaclab train --rl_library rsl_rl --task Isaac-Velocity-Rough-H1
+ uv run isaaclab train --rl_library rsl_rl --task Isaac-Velocity-Rough-H1 physics=newton_mjwarp
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh train --rl_library rsl_rl --task Isaac-Velocity-Rough-H1
+ ./isaaclab.sh train --rl_library rsl_rl --task Isaac-Velocity-Rough-H1 physics=newton_mjwarp
When the training is finished, we can visualize the result with the following command.
To stop the simulation, you can either close the window, or press ``Ctrl+C`` in the terminal
@@ -67,14 +76,14 @@ where you started the simulation.
.. code-block:: bash
- uv run isaaclab play --rl_library rsl_rl --task Isaac-Velocity-Rough-H1 --num_envs 64 --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/POLICY_FILE.pt --viz kit
+ uv run isaaclab play --rl_library rsl_rl --task Isaac-Velocity-Rough-H1 physics=newton_mjwarp --num_envs 64 --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/POLICY_FILE.pt --viz newton_gl
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh play --rl_library rsl_rl --task Isaac-Velocity-Rough-H1 --num_envs 64 --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/POLICY_FILE.pt --viz kit
+ ./isaaclab.sh play --rl_library rsl_rl --task Isaac-Velocity-Rough-H1 physics=newton_mjwarp --num_envs 64 --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/POLICY_FILE.pt --viz newton_gl
After running the play script, the policy will be exported to jit and onnx files under the experiment logs directory.
@@ -91,19 +100,19 @@ We can then load the warehouse asset and run inference on the H1 robot using the
.. code-block:: bash
- uv run python scripts/tutorials/03_envs/policy_inference_in_usd.py --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/exported/policy.pt --viz kit
+ uv run python scripts/tutorials/03_envs/policy_inference_in_usd.py --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/exported/policy.pt physics=newton_mjwarp --viz newton_gl
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh -p scripts/tutorials/03_envs/policy_inference_in_usd.py --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/exported/policy.pt --viz kit
+ ./isaaclab.sh -p scripts/tutorials/03_envs/policy_inference_in_usd.py --checkpoint logs/rsl_rl/h1_rough/EXPERIMENT_NAME/exported/policy.pt physics=newton_mjwarp --viz newton_gl
-.. figure:: ../../_static/tutorials/tutorial_policy_inference_in_usd.jpg
+.. figure:: ../_static/tutorials/tutorial_policy_inference_in_usd.jpg
:align: center
:figwidth: 100%
- :alt: result of training Isaac-H1-Direct-v0 task
+ :alt: H1 policy running in a warehouse USD scene
In this tutorial, we learnt how to make minor modifications to an existing environment config to run policy inference in a prebuilt usd environment.
diff --git a/docs/source/tutorials/03_envs/register_rl_env_gym.rst b/docs/source/how-to/register_rl_env_gym.rst
similarity index 91%
rename from docs/source/tutorials/03_envs/register_rl_env_gym.rst
rename to docs/source/how-to/register_rl_env_gym.rst
index 92897b555ccb..4746fb80b4e6 100644
--- a/docs/source/tutorials/03_envs/register_rl_env_gym.rst
+++ b/docs/source/how-to/register_rl_env_gym.rst
@@ -14,7 +14,7 @@ class.
.. dropdown:: Environment creation in the previous tutorial
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/03_envs/run_cartpole_rl_env.py
+ .. literalinclude:: ../../../scripts/tutorials/03_envs/run_cartpole_rl_env.py
:language: python
:start-at: # create environment configuration
:end-at: env = ManagerBasedRLEnv(cfg=env_cfg)
@@ -28,7 +28,7 @@ the :meth:`gymnasium.make` function.
.. dropdown:: Environment creation in this tutorial
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
+ .. literalinclude:: ../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
:language: python
:start-at: # parse configuration via Hydra
:end-at: env = gym.make(args_cli.task, cfg=env_cfg)
@@ -44,7 +44,7 @@ implementation lives.
.. dropdown:: Code for simple_agents.py
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
+ .. literalinclude:: ../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
:language: python
:emphasize-lines: 24, 64-75
:linenos:
@@ -81,7 +81,7 @@ Manager-Based Environments
For manager-based environments, the following shows the registration
call for the cartpole environment in the ``isaaclab_tasks.core.cartpole`` sub-package:
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/__init__.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/__init__.py
:language: python
:lines: 14-16,61-75
:emphasize-lines: 5, 6, 9
@@ -116,7 +116,7 @@ manager-based environments.
As an example, the following shows the registration call for the cartpole environment in the
``isaaclab_tasks.core.cartpole`` sub-package:
-.. literalinclude:: ../../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/__init__.py
+.. literalinclude:: ../../../source/isaaclab_tasks/isaaclab_tasks/core/cartpole/__init__.py
:language: python
:lines: 14-16,32-43
:emphasize-lines: 5, 6, 9
@@ -129,7 +129,7 @@ To inform the ``gym`` registry with all the environments provided by the ``isaac
extension, we must import the module at the start of the script. This will execute the ``__init__.py``
file which iterates over all the sub-packages and registers their respective environments.
-.. literalinclude:: ../../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
+.. literalinclude:: ../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
:language: python
:start-at: import isaaclab_tasks # noqa: F401
:end-at: import isaaclab_tasks # noqa: F401
@@ -139,7 +139,7 @@ the default configuration as well as to create the environment instance. In addi
parsed command line arguments such as the number of environments, the simulation device,
and whether to render, are used to override the default configuration.
-.. literalinclude:: ../../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
+.. literalinclude:: ../../../source/isaaclab_rl/isaaclab_rl/entrypoints/simple_agents.py
:language: python
:start-at: # parse configuration via Hydra
:end-at: env = gym.make(args_cli.task, cfg=env_cfg)
@@ -172,7 +172,7 @@ This should open a stage with everything similar to the :ref:`tutorial-create-ma
To stop the simulation, you can either close the window, or press ``Ctrl+C`` in the terminal.
-.. figure:: ../../_static/tutorials/tutorial_register_environment.jpg
+.. figure:: ../_static/tutorials/tutorial_register_environment.jpg
:align: center
:figwidth: 100%
:alt: result of random_agent.py
diff --git a/docs/source/how-to/robots.rst b/docs/source/how-to/robots.rst
deleted file mode 100644
index efa1e0e81540..000000000000
--- a/docs/source/how-to/robots.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-:orphan:
-
-.. _isaac-lab-robots:
-
-Robot Configurations
-=======================
-
-Robots are entirely defined as instances of configurations within Isaac Lab. If you examine ``source/isaaclab_assets/isaaclab_assets/robots``, you will see a number of files, each of which
-contains configurations for the robot in question. The purpose of these individual files is to better define scope for all the different robots, but there is nothing preventing
-you from :ref:`adding your own ` to your project or even to the ``isaaclab`` repository! For example, consider the following configuration for
-the Dofbot
-
-.. code-block:: python
-
- import isaaclab.sim as sim_utils
- from isaaclab.actuators import ImplicitActuatorCfg
- from isaaclab.assets.articulation import ArticulationCfg
- from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
-
- DOFBOT_CONFIG = ArticulationCfg(
- spawn=sim_utils.UsdFileCfg(
- usd_path=f"{ISAAC_NUCLEUS_DIR}/Robots/Dofbot/dofbot.usd",
- rigid_props=sim_utils.RigidBodyPropertiesCfg(
- disable_gravity=False,
- max_depenetration_velocity=5.0,
- ),
- articulation_props=sim_utils.ArticulationRootPropertiesCfg(
- enabled_self_collisions=True, solver_position_iteration_count=8, solver_velocity_iteration_count=0
- ),
- ),
- init_state=ArticulationCfg.InitialStateCfg(
- joint_pos={
- "joint1": 0.0,
- "joint2": 0.0,
- "joint3": 0.0,
- "joint4": 0.0,
- },
- pos=(0.25, -0.25, 0.0),
- ),
- actuators={
- "front_joints": ImplicitActuatorCfg(
- joint_names_expr=["joint[1-2]"],
- joint_effort_limit=100.0,
- joint_velocity_limit=100.0,
- stiffness=10000.0,
- damping=100.0,
- ),
- "joint3_act": ImplicitActuatorCfg(
- joint_names_expr=["joint3"],
- joint_effort_limit=100.0,
- joint_velocity_limit=100.0,
- stiffness=10000.0,
- damping=100.0,
- ),
- "joint4_act": ImplicitActuatorCfg(
- joint_names_expr=["joint4"],
- joint_effort_limit=100.0,
- joint_velocity_limit=100.0,
- stiffness=10000.0,
- damping=100.0,
- ),
- },
- )
-
-This completely defines the dofbot! You could copy this into a ``.py`` file and import it as a module and you would be able to use the dofbot in
-your own lab sims. One common feature you will see in any config defining things with state is the presence of an ``InitialStateCfg``. Remember, the configurations
-are what informs vectorization, and it's the ``InitialStateCfg`` that describes the state of the joints of our robot when it gets created in each environment. The
-``ImplicitActuatorCfg`` defines the joints of the robot using the default actuation model determined by the joint type. Not all joints need to be actuated, but you
-will get warnings if you don't. If you aren't planning on using those undefined joints, you can generally ignore these.
diff --git a/docs/source/tutorials/01_assets/run_articulation.rst b/docs/source/how-to/run_articulation.rst
similarity index 82%
rename from docs/source/tutorials/01_assets/run_articulation.rst
rename to docs/source/how-to/run_articulation.rst
index 2ac09c26b53f..b0034014e675 100644
--- a/docs/source/tutorials/01_assets/run_articulation.rst
+++ b/docs/source/how-to/run_articulation.rst
@@ -7,6 +7,10 @@ Interacting with an articulation
.. currentmodule:: isaaclab
+This runtime example complements :ref:`asset-authoring`. It uses an existing robot
+configuration; see :ref:`how-to-write-articulation-config` to create one and
+:ref:`asset-config-backends` to adapt its spawn properties to PhysX or Newton.
+
This tutorial shows how to interact with an articulated robot in the simulation. It is a continuation of the
:ref:`tutorial-interact-rigid-object` tutorial, where we learned how to interact with a rigid object.
@@ -23,7 +27,7 @@ directory.
.. dropdown:: Code for run_articulation.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/01_assets/run_articulation.py
+ .. literalinclude:: ../../../scripts/tutorials/01_assets/run_articulation.py
:language: python
:emphasize-lines: 58-69, 91-104, 108-111, 116-117
:linenos:
@@ -49,7 +53,7 @@ create this configuration object is provided in the :ref:`how-to-write-articulat
As seen in the previous tutorial, we can spawn the articulation into the scene in a similar fashion by creating
an instance of the :class:`assets.Articulation` class by passing the configuration object to its constructor.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_articulation.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_articulation.py
:language: python
:start-at: # Create separate groups called "Origin1", "Origin2"
:end-at: cartpole = Articulation(cfg=cartpole_cfg)
@@ -72,7 +76,7 @@ To reset the articulation, we first set the root state by calling the :meth:`Art
methods. Similarly, we set the joint states by calling the :meth:`Articulation.write_joint_state_to_sim` method.
Finally, we call the :meth:`Articulation.reset` method to reset any internal buffers and caches.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_articulation.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_articulation.py
:language: python
:start-at: # reset the scene entities
:end-at: robot.reset()
@@ -96,7 +100,7 @@ by calling ``robot.actuators.target_command.set_effort_index``. After setting th
we call the :meth:`Articulation.write_data_to_sim` method to write the data to the simulation buffers.
Finally, we step the simulation.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_articulation.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_articulation.py
:language: python
:start-at: # Apply random action
:end-at: robot.write_data_to_sim()
@@ -108,7 +112,7 @@ Updating the state
Every articulation class contains a :class:`assets.ArticulationData` object. This stores the state of the
articulation. To update the state inside the buffer, we call the :meth:`assets.Articulation.update` method.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_articulation.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_articulation.py
:language: python
:start-at: # Update buffers
:end-at: robot.update(sim_dt)
@@ -118,7 +122,8 @@ The Code Execution
~~~~~~~~~~~~~~~~~~
-To run the code and see the results, let's run the script from the terminal:
+This script uses Isaac Sim PhysX and requires Isaac Sim. The commands below display it with
+the Isaac Sim viewport shown below:
.. tab-set::
@@ -126,20 +131,20 @@ To run the code and see the results, let's run the script from the terminal:
.. code-block:: bash
- uv run python scripts/tutorials/01_assets/run_articulation.py
+ uv run isaaclab -p scripts/tutorials/01_assets/run_articulation.py --viz kit
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh -p scripts/tutorials/01_assets/run_articulation.py
+ ./isaaclab.sh -p scripts/tutorials/01_assets/run_articulation.py --viz kit
This command should open a stage with a ground plane, lights, and two cart-poles that are moving around randomly.
-To stop the simulation, you can either close the window, or press ``Ctrl+C`` in the terminal.
+Press ``Ctrl+C`` in the terminal to stop the simulation.
-.. figure:: ../../_static/tutorials/tutorial_run_articulation.jpg
+.. figure:: ../_static/tutorials/tutorial_run_articulation.jpg
:align: center
:figwidth: 100%
:alt: result of run_articulation.py
@@ -158,16 +163,16 @@ in the ``scripts/demos`` directory. You can run these scripts as:
.. code-block:: bash
# Spawn many different single-arm manipulators
- uv run --extra isaacsim python scripts/demos/arms.py
+ uv run isaaclab -p scripts/demos/arms.py --viz kit
# Spawn many different quadrupeds
- uv run --extra isaacsim python scripts/demos/quadrupeds.py
+ uv run isaaclab -p scripts/demos/quadrupeds.py --viz kit
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
# Spawn many different single-arm manipulators
- ./isaaclab.sh -p scripts/demos/arms.py
+ ./isaaclab.sh -p scripts/demos/arms.py --viz kit
# Spawn many different quadrupeds
- ./isaaclab.sh -p scripts/demos/quadrupeds.py
+ ./isaaclab.sh -p scripts/demos/quadrupeds.py --viz kit
diff --git a/docs/source/tutorials/01_assets/run_deformable_object.rst b/docs/source/how-to/run_deformable_object.rst
similarity index 94%
rename from docs/source/tutorials/01_assets/run_deformable_object.rst
rename to docs/source/how-to/run_deformable_object.rst
index 63fb718cdc28..043bd22b48ad 100644
--- a/docs/source/tutorials/01_assets/run_deformable_object.rst
+++ b/docs/source/how-to/run_deformable_object.rst
@@ -50,7 +50,7 @@ The tutorial corresponds to the ``run_deformable_object.py`` script in the ``scr
.. dropdown:: Code for run_deformable_object.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+ .. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:emphasize-lines: 71-117, 146-151, 153-162, 167-175, 177-178, 184-189
:linenos:
@@ -84,7 +84,7 @@ when the simulation is played.
As seen in the rigid body tutorial, we can spawn the deformable object into the scene in a similar fashion by creating
an instance of the :class:`assets.DeformableObject` class by passing the configuration object to its constructor.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:start-at: # Create separate groups called "env_0", "env_1", ...
:end-at: cube_object = DeformableObject(cfg=cfg)
@@ -113,7 +113,7 @@ attribute, which we left as identity in this tutorial.
We apply transformations to the nodal positions to randomize the initial state of the deformable object.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:start-at: # reset the nodal state of the object
:end-at: nodal_state[..., :3] = cube_object.transform_nodal_pos(nodal_state[..., :3], pos_w, quat_w)
@@ -126,7 +126,7 @@ kinematic targets in the next section.
Finally, we call the :meth:`assets.DeformableObject.reset` method to reset any internal buffers and caches.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:start-at: # write nodal state to simulation
:end-at: cube_object.reset()
@@ -146,7 +146,7 @@ we set the flag to indicate that the target is a kinematic target for that node
These are set into the simulation buffer by calling the :meth:`assets.DeformableObject.write_nodal_kinematic_target_to_sim`
method.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:start-at: # update the kinematic target for cubes at index 0 and 3
:end-at: cube_object.write_nodal_kinematic_target_to_sim_index(nodal_kinematic_target)
@@ -155,7 +155,7 @@ Similar to the rigid object and articulation, we perform the :meth:`assets.Defor
before stepping the simulation. For deformable objects, this method does not apply any external forces to the object.
However, we keep this method for completeness and future extensions.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:start-at: # write internal data to simulation
:end-at: cube_object.write_data_to_sim()
@@ -170,7 +170,7 @@ At a fixed interval, we print the root position of the deformable object to the
earlier, there is no concept of a root state for deformable objects. However, we compute the root position as
the average position of all the nodes in the mesh.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_deformable_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_deformable_object.py
:language: python
:start-at: # update buffers
:end-at: cube_object.data.root_pos_w
@@ -218,7 +218,7 @@ from a height and settling on to the ground. Meanwhile the other two cubes must
should see a marker showing the kinematic target position for the nodes at the bottom-left corner of the cubes.
To stop the simulation, you can either close the window, or press ``Ctrl+C`` in the terminal
-.. figure:: ../../_static/tutorials/tutorial_run_deformable_object.jpg
+.. figure:: ../_static/tutorials/tutorial_run_deformable_object.jpg
:align: center
:figwidth: 100%
:alt: result of run_deformable_object.py
diff --git a/docs/source/tutorials/05_controllers/run_diff_ik.rst b/docs/source/how-to/run_diff_ik.rst
similarity index 88%
rename from docs/source/tutorials/05_controllers/run_diff_ik.rst
rename to docs/source/how-to/run_diff_ik.rst
index 0c6092673d09..e084871794a6 100644
--- a/docs/source/tutorials/05_controllers/run_diff_ik.rst
+++ b/docs/source/how-to/run_diff_ik.rst
@@ -14,6 +14,8 @@ In this tutorial, we will learn how to use a task-space controller to control th
We will use the :class:`controllers.DifferentialIKController` class to track a desired
end-effector pose command.
+This tutorial uses Isaac Sim PhysX and requires an Isaac Sim installation.
+
The Code
~~~~~~~~
@@ -25,7 +27,7 @@ The tutorial corresponds to the ``run_diff_ik.py`` script in the
.. dropdown:: Code for run_diff_ik.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_diff_ik.py
+ .. literalinclude:: ../../../scripts/tutorials/05_controllers/run_diff_ik.py
:language: python
:emphasize-lines: 98-100, 121-136, 155-157, 161-171
:linenos:
@@ -67,7 +69,7 @@ In this tutorial, we will use the damped least-squares method to compute the des
joint positions. Additionally, since we want to track desired end-effector poses, we
will use the absolute pose command mode.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_diff_ik.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_diff_ik.py
:language: python
:start-at: # Create controller
:end-at: diff_ik_controller = DifferentialIKController(diff_ik_cfg, num_envs=scene.num_envs, device=sim.device)
@@ -96,7 +98,7 @@ calls the above methods to obtain the indices. However, it also performs some ad
checks to ensure that the provided names are valid. Thus, it is a safer option to use
this class.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_diff_ik.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_diff_ik.py
:language: python
:start-at: # Specify robot-specific parameters
:end-before: # Define simulation stepping
@@ -113,7 +115,7 @@ The :meth:`~controllers.DifferentialIKController.set_command` method takes in
the desired end-effector pose as a single batched array. The pose is specified in
the robot's base frame.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_diff_ik.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_diff_ik.py
:language: python
:start-at: # reset controller
:end-at: diff_ik_controller.set_command(ik_commands)
@@ -125,7 +127,7 @@ current joint positions. We read the Jacobian matrix from the robot's data, whic
its value computed from the physics engine.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_diff_ik.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_diff_ik.py
:language: python
:start-at: # obtain quantities from simulation
:end-at: joint_pos_des = diff_ik_controller.compute(ee_pos_b, ee_quat_b, jacobian, joint_pos)
@@ -133,7 +135,7 @@ its value computed from the physics engine.
The computed joint position targets can then be applied on the robot, as done in the
previous tutorials.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_diff_ik.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_diff_ik.py
:language: python
:start-at: # apply actions
:end-at: scene.write_data_to_sim()
@@ -147,25 +149,25 @@ Now that we have gone through the code, let's run the script and see the result:
.. tab-set::
- .. tab-item:: uv (Recommended)
+ .. tab-item:: Isaac Sim PhysX (uv)
.. code-block:: bash
- uv run python scripts/tutorials/05_controllers/run_diff_ik.py --robot franka_panda --num_envs 128
+ uv run isaaclab -p scripts/tutorials/05_controllers/run_diff_ik.py --robot franka_panda --num_envs 128 --viz kit
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh -p scripts/tutorials/05_controllers/run_diff_ik.py --robot franka_panda --num_envs 128
+ ./isaaclab.sh -p scripts/tutorials/05_controllers/run_diff_ik.py --robot franka_panda --num_envs 128 --viz kit
The script will start a simulation with 128 robots. The robots will be controlled using the IK controller.
The current and desired end-effector poses should be displayed using frame markers. When the robot reaches
the desired pose, the command should cycle through to the next pose specified in the script.
-.. figure:: ../../_static/tutorials/tutorial_task_space_controller.jpg
+.. figure:: ../_static/tutorials/tutorial_task_space_controller.jpg
:align: center
:figwidth: 100%
:alt: result of run_diff_ik.py
-To stop the simulation, you can either close the window, or press ``Ctrl+C`` in the terminal.
+Press ``Ctrl+C`` in the terminal to stop the simulation.
diff --git a/docs/source/tutorials/05_controllers/run_osc.rst b/docs/source/how-to/run_osc.rst
similarity index 88%
rename from docs/source/tutorials/05_controllers/run_osc.rst
rename to docs/source/how-to/run_osc.rst
index 8dad67eb31cc..cfb31e536c8c 100644
--- a/docs/source/tutorials/05_controllers/run_osc.rst
+++ b/docs/source/how-to/run_osc.rst
@@ -22,6 +22,9 @@ In this tutorial, we will learn how to use an OSC to control the robot.
We will use the :class:`controllers.OperationalSpaceController` class to apply a constant force perpendicular to a
tilted wall surface while tracking a desired end-effector pose in all the other directions.
+This tutorial uses Isaac Sim PhysX and requires an Isaac Sim installation.
+The target quaternions use ``(x, y, z, w)`` order and orient the end-effector toward the tilted wall.
+
The Code
~~~~~~~~
@@ -32,7 +35,7 @@ The tutorial corresponds to the ``run_osc.py`` script in the
.. dropdown:: Code for run_osc.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+ .. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:linenos:
@@ -56,16 +59,16 @@ in mind.
For the motion control, the task space targets could be given as absolute (i.e., defined w.r.t. the robot base,
``target_types: "pose_abs"``) or relative to the end-effector's current pose (i.e., ``target_types: "pose_rel"``).
For the force control, the task space targets could be given as absolute (i.e., defined w.r.t. the robot base,
-``target_types: "force_abs"``). If it is desired to apply pose and force control simultaneously, the ``target_types``
+``target_types: "wrench_abs"``). If it is desired to apply pose and force control simultaneously, the ``target_types``
should be a list such as ``["pose_abs", "wrench_abs"]`` or ``["pose_rel", "wrench_abs"]``.
The axes that the motion and force control will be applied can be specified using the ``motion_control_axes_task`` and
-``force_control_axes_task`` arguments, respectively. These lists should consist of 0/1 for all six axes (position and
+``contact_wrench_control_axes_task`` arguments, respectively. These lists should consist of 0/1 for all six axes (position and
rotation) and be complementary to each other (e.g., for the x-axis, if the ``motion_control_axes_task`` is ``0``, the
-``force_control_axes_task`` should be ``1``).
+``contact_wrench_control_axes_task`` should be ``1``).
For the motion control axes, desired stiffness, and damping ratio values can be specified using the
-``motion_control_stiffness`` and ``motion_damping_ratio_task`` arguments, which can be a scalar (same value for all
+``motion_stiffness_task`` and ``motion_damping_ratio_task`` arguments, which can be a scalar (same value for all
axes) or a list of six scalars, one value corresponding to each axis. If desired, the stiffness and damping ratio
values could be a command parameter (e.g., to learn the values using RL or change them on the go). For this,
``impedance_mode`` should be either ``"variable_kp"`` to include the stiffness values within the command or
@@ -109,7 +112,7 @@ We set the impedance mode to ``"variable_kp"`` to dynamically change the stiffne
damped response). Finally, ``nullspace_control`` is set to use ``"position"`` where the joint set points are provided
to be the center of the joint position limits.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:start-at: # Create the OSC
:end-at: osc = OperationalSpaceController(osc_cfg, num_envs=scene.num_envs, device=sim.device)
@@ -122,7 +125,7 @@ about the robot. This includes the robot's Jacobian matrix, mass/inertia matrix,
force (all in the root frame), and finally, the joint positions and velocities. Moreover, the user should provide
gravity compensation vector and null-space joint position targets if required.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:start-at: # Update robot states
:end-before: # Update the target commands
@@ -141,7 +144,7 @@ concatanated together.
In this tutorial, the desired wrench is already defined w.r.t. the task frame, and the desired pose is transformed
to the task frame as the following:
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:start-at: # Convert the target commands to the task frame
:end-at: return command, task_frame_pose_b
@@ -150,14 +153,14 @@ The OSC command is set with the command vector in the task frame, the end-effect
task (reference) frame pose in the base frame as the following. This information is needed, as the internal
computations are done in the base frame.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:start-at: # set the osc command
:end-at: osc.set_command(command=command, current_ee_pose_b=ee_pose_b, current_task_frame_pose_b=task_frame_pose_b)
The joint effort/torque values are computed using the provided robot states and the desired command as the following:
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:start-at: # compute the joint commands
:end-at: )
@@ -165,7 +168,7 @@ The joint effort/torque values are computed using the provided robot states and
The computed joint effort/torque targets can then be applied on the robot.
-.. literalinclude:: ../../../../scripts/tutorials/05_controllers/run_osc.py
+.. literalinclude:: ../../../scripts/tutorials/05_controllers/run_osc.py
:language: python
:start-at: # apply actions
:end-at: robot.write_data_to_sim()
@@ -178,26 +181,26 @@ You can now run the script and see the result:
.. tab-set::
- .. tab-item:: uv (Recommended)
+ .. tab-item:: Isaac Sim PhysX (uv)
.. code-block:: bash
- uv run python scripts/tutorials/05_controllers/run_osc.py --num_envs 128
+ uv run isaaclab -p scripts/tutorials/05_controllers/run_osc.py --num_envs 128 --viz kit
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh -p scripts/tutorials/05_controllers/run_osc.py --num_envs 128
+ ./isaaclab.sh -p scripts/tutorials/05_controllers/run_osc.py --num_envs 128 --viz kit
The script will start a simulation with 128 robots. The robots will be controlled using the OSC.
The current and desired end-effector poses should be displayed using frame markers in addition to the red tilted wall.
You should see that the robot reaches the desired pose while applying a constant force perpendicular to the wall
surface.
-.. figure:: ../../_static/tutorials/tutorial_operational_space_controller.jpg
+.. figure:: ../_static/tutorials/tutorial_operational_space_controller.jpg
:align: center
:figwidth: 100%
:alt: result of run_osc.py
-To stop the simulation, you can either close the window or press ``Ctrl+C`` in the terminal.
+Press ``Ctrl+C`` in the terminal to stop the simulation.
diff --git a/docs/source/tutorials/01_assets/run_rigid_object.rst b/docs/source/how-to/run_rigid_object.rst
similarity index 86%
rename from docs/source/tutorials/01_assets/run_rigid_object.rst
rename to docs/source/how-to/run_rigid_object.rst
index ad606bd79847..44bd533c7d29 100644
--- a/docs/source/tutorials/01_assets/run_rigid_object.rst
+++ b/docs/source/how-to/run_rigid_object.rst
@@ -8,6 +8,10 @@ Interacting with a rigid object
.. currentmodule:: isaaclab
+This is the first runtime example in :ref:`asset-authoring`: spawn a rigid body, reset its
+state, step the simulation, and read the updated state. Use the authoring guides for
+configuration details and :ref:`tutorial-interact-articulation` for bodies connected by joints.
+
In the previous tutorials, we learned the essential workings of the standalone script and how to
spawn different objects (or *prims*) into the simulation. This tutorial shows how to create and interact
with a rigid object. For this, we will use the :class:`assets.RigidObject` class provided in Isaac Lab.
@@ -20,7 +24,7 @@ The tutorial corresponds to the ``run_rigid_object.py`` script in the ``scripts/
.. dropdown:: Code for run_rigid_object.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/01_assets/run_rigid_object.py
+ .. literalinclude:: ../../../scripts/tutorials/01_assets/run_rigid_object.py
:language: python
:emphasize-lines: 55-74, 76-78, 98-108, 111-112, 118-119, 132-134, 139-140
:linenos:
@@ -63,7 +67,7 @@ each of the ``/World/Origin{i}`` locations. For instance, if ``/World/Origin1``
present in the scene, the rigid object prims are spawned at the locations ``/World/Origin1/Cone`` and
``/World/Origin2/Cone`` respectively.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_rigid_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_rigid_object.py
:language: python
:start-at: # Create separate groups called "Origin1", "Origin2", "Origin3"
:end-at: cone_object = RigidObject(cfg=cone_cfg)
@@ -72,7 +76,7 @@ Since we want to interact with the rigid object, we pass this entity back to the
is then used to interact with the rigid object in the simulation loop. In later tutorials, we will see a more
convenient way to handle multiple scene entities using the :class:`scene.InteractiveScene` class.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_rigid_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_rigid_object.py
:language: python
:start-at: # return the scene information
:end-at: return scene_entities, origins
@@ -101,7 +105,7 @@ attribute, which we left as identity in this tutorial. We then randomize the tra
set the desired state of the rigid object prim using the :meth:`assets.RigidObject.write_root_pose_to_sim` and :meth:`assets.RigidObject.write_root_velocity_to_sim` methods.
As the name suggests, this method writes the root state of the rigid object prim into the simulation buffer.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_rigid_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_rigid_object.py
:language: python
:start-at: # reset root state
:end-at: cone_object.reset()
@@ -113,7 +117,7 @@ Before stepping the simulation, we perform the :meth:`assets.RigidObject.write_d
writes other data, such as external forces, into the simulation buffer. In this tutorial, we do not apply any
external forces to the rigid object, so this method is not necessary. However, it is included for completeness.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_rigid_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_rigid_object.py
:language: python
:start-at: # apply sim data
:end-at: cone_object.write_data_to_sim()
@@ -124,7 +128,7 @@ Updating the state
After stepping the simulation, we update the internal buffers of the rigid object prims to reflect their new state
inside the :class:`assets.RigidObject.data` attribute. This is done using the :meth:`assets.RigidObject.update` method.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_rigid_object.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_rigid_object.py
:language: python
:start-at: # update buffers
:end-at: cone_object.update(sim_dt)
@@ -133,7 +137,8 @@ inside the :class:`assets.RigidObject.data` attribute. This is done using the :m
The Code Execution
~~~~~~~~~~~~~~~~~~
-Now that we have gone through the code, let's run the script and see the result:
+This script uses Isaac Sim PhysX and requires Isaac Sim. The commands below display it with
+the Isaac Sim viewport shown below:
.. tab-set::
@@ -141,21 +146,20 @@ Now that we have gone through the code, let's run the script and see the result:
.. code-block:: bash
- uv run python scripts/tutorials/01_assets/run_rigid_object.py
+ uv run isaaclab -p scripts/tutorials/01_assets/run_rigid_object.py --viz kit
.. tab-item:: isaaclab.sh / isaaclab.bat
.. code-block:: bash
- ./isaaclab.sh -p scripts/tutorials/01_assets/run_rigid_object.py
+ ./isaaclab.sh -p scripts/tutorials/01_assets/run_rigid_object.py --viz kit
This should open a stage with a ground plane, lights, and several green cones. The cones must be dropping from
-a random height and settling on to the ground. To stop the simulation, you can either close the window, or press
-the ``STOP`` button in the UI, or press ``Ctrl+C`` in the terminal
+a random height and settling on to the ground. Press ``Ctrl+C`` in the terminal to stop the simulation.
-.. figure:: ../../_static/tutorials/tutorial_run_rigid_object.jpg
+.. figure:: ../_static/tutorials/tutorial_run_rigid_object.jpg
:align: center
:figwidth: 100%
:alt: result of run_rigid_object.py
diff --git a/docs/source/tutorials/03_envs/run_rl_training.rst b/docs/source/how-to/run_rl_training.rst
similarity index 98%
rename from docs/source/tutorials/03_envs/run_rl_training.rst
rename to docs/source/how-to/run_rl_training.rst
index 72a425d8291a..b661f8ad0831 100644
--- a/docs/source/tutorials/03_envs/run_rl_training.rst
+++ b/docs/source/how-to/run_rl_training.rst
@@ -42,7 +42,7 @@ For this tutorial, we use the training implementation from `Stable-Baselines3`_
.. dropdown:: Code for train_sb3.py
:icon: code
- .. literalinclude:: ../../../../source/isaaclab_rl/isaaclab_rl/entrypoints/backends/train_sb3.py
+ .. literalinclude:: ../../../source/isaaclab_rl/isaaclab_rl/entrypoints/backends/train_sb3.py
:language: python
:linenos:
:emphasize-lines: 97-100, 104-109, 121-137, 145-157, 164-170
diff --git a/docs/source/tutorials/01_assets/run_surface_gripper.rst b/docs/source/how-to/run_surface_gripper.rst
similarity index 94%
rename from docs/source/tutorials/01_assets/run_surface_gripper.rst
rename to docs/source/how-to/run_surface_gripper.rst
index 7d3c411db5be..0eb0626eb78d 100644
--- a/docs/source/tutorials/01_assets/run_surface_gripper.rst
+++ b/docs/source/how-to/run_surface_gripper.rst
@@ -23,7 +23,7 @@ directory.
.. dropdown:: Code for run_surface_gripper.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/01_assets/run_surface_gripper.py
+ .. literalinclude:: ../../../scripts/tutorials/01_assets/run_surface_gripper.py
:language: python
:emphasize-lines: 61-85, 124-125, 128-142, 147-150
:linenos:
@@ -61,7 +61,7 @@ principle applies to the surface gripper. By passing the configuration object to
constructor, the surface gripper is created and can be added to the scene. In practice, the object will only be
initialized when the play button is pressed.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_surface_gripper.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_surface_gripper.py
:language: python
:start-at: # Create separate groups called "Origin1", "Origin2"
:end-at: surface_gripper = SurfaceGripper(cfg=surface_gripper_cfg)
@@ -79,7 +79,7 @@ Resetting the simulation
To reset the surface gripper, we only need to call the :meth:`SurfaceGripper.reset` method which will reset the
internal buffers and caches.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_surface_gripper.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_surface_gripper.py
:language: python
:start-at: # Opens the gripper and makes sure the gripper is in the open state
:end-at: surface_gripper.reset()
@@ -104,7 +104,7 @@ At every step, we randomly sample commands and set them to the gripper by callin
:meth:`SurfaceGripper.write_data_to_sim` method to write the data to the PhysX buffer. Finally, we step
the simulation.
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_surface_gripper.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_surface_gripper.py
:language: python
:start-at: # Sample a random command between -1 and 1.
:end-at: surface_gripper.write_data_to_sim()
@@ -122,7 +122,7 @@ is called.
- ``0`` --> Gripper is Closing
- ``1`` --> Gripper is Closed
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/run_surface_gripper.py
+.. literalinclude:: ../../../scripts/tutorials/01_assets/run_surface_gripper.py
:language: python
:start-at: # Read the gripper state from the simulation
:end-at: surface_gripper_state = surface_gripper.state
@@ -154,7 +154,7 @@ This command should open a stage with a ground plane, lights, and two pick-and-p
In the terminal, you should see the gripper state and the command being printed.
To stop the simulation, you can either close the window, or press ``Ctrl+C`` in the terminal.
-.. figure:: ../../_static/tutorials/tutorial_run_surface_gripper.jpg
+.. figure:: ../_static/tutorials/tutorial_run_surface_gripper.jpg
:align: center
:figwidth: 100%
:alt: result of run_surface_gripper.py
diff --git a/docs/source/tutorials/00_sim/spawn_prims.rst b/docs/source/how-to/spawn_prims.rst
similarity index 93%
rename from docs/source/tutorials/00_sim/spawn_prims.rst
rename to docs/source/how-to/spawn_prims.rst
index 898d092c7f45..334eca949ab4 100644
--- a/docs/source/tutorials/00_sim/spawn_prims.rst
+++ b/docs/source/how-to/spawn_prims.rst
@@ -37,7 +37,7 @@ Let's take a look at the Python script:
.. dropdown:: Code for spawn_prims.py
:icon: code
- .. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+ .. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:emphasize-lines: 40-88, 100-101
:linenos:
@@ -102,7 +102,7 @@ Spawning a ground plane
The :class:`~sim.spawners.from_files.GroundPlaneCfg` configures a grid-like ground plane with
modifiable properties such as its appearance and size.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # Ground-plane
:end-at: cfg_ground.func("/World/defaultGroundPlane", cfg_ground)
@@ -115,7 +115,7 @@ It is possible to spawn `different light prims`_ into the stage. These include d
lights, and cylinder lights. In this tutorial, we spawn a distant light which is a light that is infinitely far away
from the scene and shines in a single direction.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # spawn distant light
:end-at: cfg_light_distant.func("/World/lightDistant", cfg_light_distant, translation=(1, 0, 10))
@@ -128,7 +128,7 @@ Before spawning primitive shapes, we introduce the concept of a transform prim o
contains only transformation properties. It is used to group other prims under it and to transform them as a group.
Here we make an Xform prim to group all the primitive shapes under it.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # create a new xform prim for all objects to be spawned under
:end-at: sim_utils.create_prim("/World/Objects", "Xform")
@@ -139,7 +139,7 @@ properties are disabled.
The first two cones we spawn ``Cone1`` and ``Cone2`` are visual elements and do not have physics enabled.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # spawn a red cone
:end-at: cfg_cone.func("/World/Objects/Cone2", cfg_cone, translation=(-1.0, -1.0, 1.0))
@@ -148,7 +148,7 @@ For the third cone ``ConeRigid``, we add rigid body physics to it by setting the
class. Through these attributes, we can specify the mass, friction, and restitution of the cone. If unspecified, they
default to the default values set by USD Physics.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # spawn a green cone with colliders and rigid body
:end-before: # spawn a blue cuboid with deformable body
@@ -159,7 +159,7 @@ soft bodies like cloth, rubber, or jello. It is important to note that deformabl
GPU simulation and require a mesh object to be spawned with deformable body physics properties and a deformable
physics material. This example uses the PhysX-specific deformable property and material cfgs.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # spawn a blue cuboid with deformable body
:end-before: # spawn a usd file of a table into the scene
@@ -171,7 +171,7 @@ Lastly, it is possible to spawn prims from other file formats such as other USD,
we spawn a USD file of a table into the scene. The table is a mesh prim and has a material prim associated with it.
All of this information is stored in its USD file.
-.. literalinclude:: ../../../../scripts/tutorials/00_sim/spawn_prims.py
+.. literalinclude:: ../../../scripts/tutorials/00_sim/spawn_prims.py
:language: python
:start-at: # spawn a usd file of a table into the scene
:end-at: cfg.func("/World/Objects/Table", cfg, translation=(0.0, 0.0, 1.05))
@@ -206,7 +206,7 @@ The green cone, which has rigid body physics enabled, should fall and collide wi
plane. The other cones are visual elements and should not move. To stop the simulation, you can close the window,
or press ``Ctrl+C`` in the terminal.
-.. figure:: ../../_static/tutorials/tutorial_spawn_prims.jpg
+.. figure:: ../_static/tutorials/tutorial_spawn_prims.jpg
:align: center
:figwidth: 100%
:alt: result of spawn_prims.py
diff --git a/docs/source/how-to/write_articulation_cfg.rst b/docs/source/how-to/write_articulation_cfg.rst
index 26b805fa95b4..7c4b9a1acfe7 100644
--- a/docs/source/how-to/write_articulation_cfg.rst
+++ b/docs/source/how-to/write_articulation_cfg.rst
@@ -1,14 +1,20 @@
:orphan:
+.. _isaac-lab-robots:
+.. _tutorial-add-new-robot:
.. _how-to-write-articulation-config:
+.. _writing-an-asset-configuration:
+.. _robot-configurations:
+.. _adding-a-new-robot-to-isaac-lab:
-Writing an Asset Configuration
-==============================
+Robot and articulation configuration
+====================================
.. currentmodule:: isaaclab
-This guide walks through the process of creating an :class:`~assets.ArticulationCfg`.
+A jointed robot is represented as an articulation in Isaac Lab. This guide covers reusing
+an existing robot configuration and authoring a new :class:`~assets.ArticulationCfg`.
The :class:`~assets.ArticulationCfg` is a configuration object that defines the
properties of an :class:`~assets.Articulation` in Isaac Lab.
@@ -17,6 +23,19 @@ properties of an :class:`~assets.Articulation` in Isaac Lab.
While we only cover the creation of an :class:`~assets.ArticulationCfg` in this guide,
the process is similar for creating any other asset configuration object.
+Reusing a robot configuration
+-----------------------------
+
+Maintained robot configurations live in ``source/isaaclab_assets/isaaclab_assets/robots``.
+Import a configuration from ``isaaclab_assets`` and copy it before changing its spawn
+properties, initial state, or actuators. Keep project-specific configurations in a Python
+module in your own project; they do not need to be added to Isaac Lab.
+
+For example, ``robot_cfg = CARTPOLE_CFG.copy()`` creates an independent configuration.
+Use ``robot_cfg.replace(prim_path="{ENV_REGEX_NS}/Robot")`` when adding it to an
+:class:`~scene.InteractiveSceneCfg`. The physics backend is selected separately from
+this robot configuration, as explained below.
+
We will use the Cartpole example to demonstrate how to create an :class:`~assets.ArticulationCfg`.
The Cartpole is a simple robot that consists of a cart with a pole attached to it. The cart
is free to move along a rail, and the pole is free to rotate about the cart. The file for this configuration example is
@@ -30,6 +49,41 @@ is free to move along a rail, and the pole is free to rotate about the cart. The
:linenos:
+.. _asset-config-backends:
+
+Choosing shared and backend-specific settings
+---------------------------------------------
+
+Use the shared :class:`~assets.ArticulationCfg` for the robot's initial state and actuators.
+The simulation selects the physics backend separately.
+
+For common USD properties, use classes from ``isaaclab.sim.schemas``, such as
+:class:`~sim.schemas.RigidBodyBaseCfg` and :class:`~sim.schemas.ArticulationRootBaseCfg`.
+Use ``isaaclab_physx.sim.schemas.Physx*Cfg`` for PhysX tuning and
+``isaaclab_newton.sim.schemas.Newton*Cfg`` / ``Mujoco*Cfg`` for Newton and MJWarp-specific
+settings. The :ref:`schema-cfgs` guide explains the available classes and their USD namespaces;
+:doc:`../concepts/schema_fragments` shows how to author both backends' attributes
+in one spawn configuration.
+
+The Cartpole below uses the compatibility names ``RigidBodyPropertiesCfg`` and
+``ArticulationRootPropertiesCfg``. Its PhysX solver iterations and sleep thresholds do not
+configure Newton's solver. When adapting it to Newton, retain the shared initial-state and
+actuator configuration and configure the Newton solver separately. For example, to override
+Newton's self-collision setting:
+
+.. code-block:: python
+
+ from isaaclab_assets import CARTPOLE_CFG
+ from isaaclab_newton.sim.schemas import NewtonArticulationRootPropertiesCfg
+
+ robot_cfg = CARTPOLE_CFG.copy()
+ robot_cfg.spawn.articulation_props = NewtonArticulationRootPropertiesCfg(self_collision_enabled=False)
+
+See :doc:`../concepts/solver-tuning/tune_mjwarp` for solver settings,
+:doc:`prepare_asset_for_newton`
+for asset tuning, and :ref:`import-new-asset-multi-backend` for converted USD variants.
+
+
Defining the spawn configuration
--------------------------------
@@ -42,14 +96,15 @@ When spawning an asset from a USD file, we define its :class:`~sim.spawners.from
This configuration object takes in the following parameters:
* :class:`~sim.spawners.from_files.UsdFileCfg.usd_path`: The USD file path to spawn from
-* :class:`~sim.spawners.from_files.UsdFileCfg.rigid_props`: The properties of the articulation's root
-* :class:`~sim.spawners.from_files.UsdFileCfg.articulation_props`: The properties of all the articulation's links
+* :class:`~sim.spawners.from_files.UsdFileCfg.rigid_props`: The properties of the articulation's rigid-body links
+* :class:`~sim.spawners.from_files.UsdFileCfg.articulation_props`: The properties of the articulation root
The last two parameters are optional. If not specified, they are kept at their default values in the USD file.
.. literalinclude:: ../../../source/isaaclab_assets/isaaclab_assets/robots/cartpole.py
:language: python
- :lines: 19-35
+ :start-at: spawn=sim_utils.UsdFileCfg(
+ :end-before: init_state=
:dedent:
To import articulation from a URDF file instead of a USD file, you can replace the
@@ -77,7 +132,8 @@ Meanwhile, the joint positions and velocities are set to 0.0.
.. literalinclude:: ../../../source/isaaclab_assets/isaaclab_assets/robots/cartpole.py
:language: python
- :lines: 36-38
+ :start-at: init_state=
+ :end-before: actuators=
:dedent:
Defining the actuator configuration
@@ -99,7 +155,8 @@ to combine them into a single actuator model.
.. literalinclude:: ../../../source/isaaclab_assets/isaaclab_assets/robots/cartpole.py
:language: python
- :lines: 39-49
+ :start-at: actuators=
+ :end-at: },
:dedent:
@@ -253,3 +310,63 @@ Here's an example of what you'll see::
To keep the cleaniness of logging, :attr:`~isaaclab.assets.ArticulationCfg.actuator_value_resolution_debug_print`
default to False, remember to turn it on when wishes.
+
+
+.. _robot-configuration-example:
+.. _the-code:
+.. _the-code-explained:
+
+Example: configure and run two robots
+-------------------------------------
+
+The runnable example ``scripts/tutorials/01_assets/add_new_robot.py`` contrasts a minimal
+Jetbot configuration with a more detailed Dofbot configuration. Start with an imported USD
+asset (see :doc:`import_new_asset`) and define its spawn properties and actuators. Jetbot
+retains the joint gains authored in the USD by setting stiffness and damping to ``None``.
+Both fields must be specified, even when using these USD defaults:
+
+.. literalinclude:: ../../../scripts/tutorials/01_assets/add_new_robot.py
+ :language: python
+ :start-at: JETBOT_CONFIG =
+ :end-before: DOFBOT_CONFIG =
+
+Dofbot additionally sets initial joint positions, groups joints by name, and specifies
+actuator gains and limits. Its solver iterations and maximum depenetration velocity are
+PhysX-specific; use :ref:`asset-config-backends` when adapting these properties to Newton.
+The keys in ``init_state.joint_pos`` identify USD joints, not actuator groups. Joint names can
+be matched with regular expressions; for example, ``.*`` selects all joints.
+
+.. dropdown:: Expanded Dofbot configuration from the runnable example
+ :icon: code
+
+ .. literalinclude:: ../../../scripts/tutorials/01_assets/add_new_robot.py
+ :language: python
+ :start-at: DOFBOT_CONFIG =
+ :end-before: class NewRobotsSceneCfg
+
+The example adds both configurations to an ``InteractiveSceneCfg``, assigns each robot a
+path under every environment, and constructs the scene. Its loop resets root and joint
+states, sets joint targets, writes commands, steps physics, and updates the scene buffers.
+See :ref:`tutorial-interactive-scene` for scene construction and
+:ref:`tutorial-interact-articulation` for the reset and control loop.
+
+.. dropdown:: Complete runnable example
+ :icon: code
+
+ .. literalinclude:: ../../../scripts/tutorials/01_assets/add_new_robot.py
+ :language: python
+ :linenos:
+
+Run the example in the Isaac Sim viewport:
+
+.. code-block:: bash
+
+ uv run isaaclab -p scripts/tutorials/01_assets/add_new_robot.py --viz kit
+
+This example uses PhysX physics and requires Isaac Sim. The Dofbot gripper is not actuated
+in this example, so a warning about unconfigured joints is expected. Stop the example with ``Ctrl+C``.
+
+.. figure:: ../_static/tutorials/tutorial_add_new_robot_result.jpg
+ :align: center
+ :figwidth: 100%
+ :alt: Jetbot and Dofbot running in the example scene.
diff --git a/docs/source/policy_deployment/index.rst b/docs/source/policy_deployment/index.rst
index cd89350c1773..4fc56fe32bd5 100644
--- a/docs/source/policy_deployment/index.rst
+++ b/docs/source/policy_deployment/index.rst
@@ -8,6 +8,7 @@ Below, you'll find detailed examples of various policies for training and deploy
.. toctree::
:maxdepth: 1
+ ../how-to/policy_inference_in_usd
01_io_descriptors/io_descriptors_101
02_gear_assembly/gear_assembly_policy
03_compass_with_NuRec/compass_navigation_policy_with_NuRec
diff --git a/docs/source/setup/installation/index.rst b/docs/source/setup/installation/index.rst
index f9c7a3006036..5d6c47b71d34 100644
--- a/docs/source/setup/installation/index.rst
+++ b/docs/source/setup/installation/index.rst
@@ -590,6 +590,12 @@ resources as a released wheel:
Use a commit hash or release tag for reproducible environments. A branch name is accepted, but
updating the lockfile can then select a newer Isaac Lab revision and dependency set.
+Installing the published wheel
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use NVIDIA's package index for the |isaaclab_wheel_version| prerelease. Do not use the
+``[tool.uv.sources]`` Git entry from the previous workflow when installing the published wheel.
+
Choose how you want uv to manage the dependency. Both workflows start with the base
``isaaclab`` package; add optional capabilities only when your project needs them.
@@ -601,7 +607,7 @@ Choose how you want uv to manage the dependency. Both workflows start with the b
uv init --python 3.12 my_isaaclab_project
cd my_isaaclab_project
- uv add isaaclab
+ uv add --index https://pypi.nvidia.com isaaclab==3.0.0rc1
.. tab-item:: Standalone uv environment
@@ -615,7 +621,7 @@ Choose how you want uv to manage the dependency. Both workflows start with the b
uv venv --python 3.12 env_isaaclab
source env_isaaclab/bin/activate
- uv pip install isaaclab
+ uv pip install --index https://pypi.nvidia.com isaaclab==3.0.0rc1
.. tab-item:: :icon:`fa-brands fa-windows` Windows (x86_64)
:sync: windows-x86_64
@@ -624,7 +630,7 @@ Choose how you want uv to manage the dependency. Both workflows start with the b
uv venv --python 3.12 env_isaaclab
env_isaaclab\Scripts\activate
- uv pip install isaaclab
+ uv pip install --index https://pypi.nvidia.com isaaclab==3.0.0rc1
.. tab-item:: :icon:`fa-brands fa-linux` Linux (aarch64)
:sync: linux-aarch64
@@ -633,7 +639,7 @@ Choose how you want uv to manage the dependency. Both workflows start with the b
uv venv --python 3.12 env_isaaclab
source env_isaaclab/bin/activate
- uv pip install isaaclab
+ uv pip install --index https://pypi.nvidia.com isaaclab==3.0.0rc1
The project workflow records the dependency in ``pyproject.toml`` and updates ``uv.lock``. Use it
when Isaac Lab is part of an application you maintain; use a standalone environment for exploratory
diff --git a/docs/source/tutorials/01_assets/add_new_robot.rst b/docs/source/tutorials/01_assets/add_new_robot.rst
deleted file mode 100644
index 53c8bba4cb3a..000000000000
--- a/docs/source/tutorials/01_assets/add_new_robot.rst
+++ /dev/null
@@ -1,115 +0,0 @@
-:orphan:
-
-.. _tutorial-add-new-robot:
-
-Adding a New Robot to Isaac Lab
-===============================
-
-.. currentmodule:: isaaclab
-
-Simulating and training a new robot is a multi-step process that starts with importing the robot into Isaac Sim.
-This is covered in depth in the Isaac Sim documentation `here `_.
-Once the robot is imported and tuned for simulation, we must define those interfaces necessary to clone the robot across multiple environments, drive its joints,
-and properly reset it, regardless of the chosen workflow or training framework.
-
-In this tutorial, we will examine how to add a new robot to Isaac Lab. The key step is creating an ``AssetBaseCfg`` that defines
-the interface between the USD articulation of the robot and the learning algorithms available through Isaac Lab.
-
-The Code
-~~~~~~~~
-
-The tutorial corresponds to the ``add_new_robot`` script in the ``scripts/tutorials/01_assets`` directory.
-
-.. dropdown:: Code for add_new_robot.py
- :icon: code
-
- .. literalinclude:: ../../../../scripts/tutorials/01_assets/add_new_robot.py
- :language: python
- :linenos:
-
-The Code Explained
-~~~~~~~~~~~~~~~~~~
-
-Fundamentally, a robot is an articulation with joint drives. To move a robot around in the simulation, we must apply
-targets to its drives and step the sim forward in time. However, to control a robot strictly through joint drives is tedious, especially if
-you want to control anything complex, and doubly so if you want to clone the robot across multiple environments.
-
-To facilitate this, Isaac Lab provides a collection of ``configuration`` classes that define which parts of the USD need
-to be cloned, which parts are actuators to be controlled by an agent, how it should be reset, etc... There are many ways
-you can configure a single robot asset for Isaac Lab depending on how much fine tuning the asset requires. To demonstrate,
-the tutorial script imports two robots: The first robot, the ``Jetbot``, is configured minimally while the second robot, the ``Dofbot``, is configured with additional parameters.
-
-The Jetbot is a simple, two wheeled differential base with a camera on top. The asset is used for a number of demonstrations and
-tutorials in Isaac Sim, so we know it's good to go! To bring it into Isaac lab, we must first define one of these configurations.
-Because a robot is an articulation with joint drives, we define an ``ArticulationCfg`` that describes the robot.
-
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/add_new_robot.py
- :language: python
- :lines: 27-38
-
-This is the minimal configuration for a robot in Isaac Lab. There are only two required parameters: ``spawn`` and ``actuators``.
-
-The ``spawn`` parameter is looking for a ``SpawnerCfg``, and is used to specify the USD asset that defines the robot in the sim.
-The Isaac Lab simulation utilities, ``isaaclab.sim``, provides us with a ``USDFileCfg`` class that consumes a path to our USD
-asset, and generates the ``SpawnerCfg`` we need. In this case, the ``jetbot.usd`` is located
-with the `Isaac Assets `_ under ``Robots/Jetbot/jetbot.usd``.
-
-The ``actuators`` parameter is a dictionary of Actuator Configs and defines what parts of the robot we intend to control with an agent.
-There are many different ways to update the state of a joint in time towards some target. Isaac Lab provides a collection of actuator
-classes that can be used to match common actuator models or even implement your own! In this case, we are using the ``ImplicitActuatorCfg`` class to specify
-the actuators for the robot, because they are simple wheels and the defaults are fine.
-
-Specifying joint name keys for this dictionary can be done to varying levels of specificity.
-The jetbot only has a few joints, and we are just going to use the defaults specified in the USD asset, so we can use a simple regex, ``.*`` to specify all joints.
-Other regex can also be used to group joints and associated configurations.
-
-.. note::
-
- Both stiffness and damping must be specified in the implicit actuator, but a value of ``None`` will use the defaults defined in the USD asset.
-
-While this is the minimal configuration, there are a number of other parameters we could specify
-
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/add_new_robot.py
- :language: python
- :lines: 39-82
-
-This configuration can be used to add a Dofbot to the scene, and it contains some of those parameters.
-The Dofbot is a hobbiest robot arm with several joints, and so we have more options available for configuration.
-The two most notable differences though is the addition of configurations for physics properties, and the initial state of the robot, ``init_state``.
-
-The ``USDFileCfg`` has special parameters for rigid bodies and robots, among others. The ``rigid_props`` parameter expects
-a ``RigidBodyPropertiesCfg`` that allows you to specify body link properties of the robot being spawned relating to its behavior
-as a "physical object" in the simulation. The ``articulation_props`` meanwhile governs the properties relating to the solver
-being used to step the joints through time, and so it expects an ``ArticulationRootPropertiesCfg`` to be configured.
-There are many other physics properties and parameters that can be specified through configurations provided by :class:`isaaclab.sim.schemas`.
-
-The ``ArticulationCfg`` can optionally include the ``init_state`` parameter, that defines the initial state of the articulation.
-The initial state of an articulation is a special, user defined state that is used when the robot is spawned or reset by Isaac Lab.
-The initial joint state, ``joint_pos``, is specified by a dictionary of floats with the USD joint names as keys (**not** the actuator names).
-Something else worth noting here is the coordinate system of the initial position, ``pos``, which is that of the environment.
-In this case, by specifying a position of ``(0.25, -0.25, 0.0)`` we are offsetting the spawn position of the robot **from the origin of the environment**, and not the world.
-
-Armed with the configurations for these robots, we can now add them to the scene and interact with them in the usual way
-for the direct workflow: by defining an ``InteractiveSceneCfg`` containing the articulation configs for the robots ...
-
-
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/add_new_robot.py
- :language: python
- :lines: 85 - 99
-
-
-...and then stepping the simulation while updating the scene entities appropriately.
-
-.. literalinclude:: ../../../../scripts/tutorials/01_assets/add_new_robot.py
- :language: python
- :lines: 101 - 158
-
-
-.. note::
-
- You may see a warning that not all actuators are configured! This is expected because we don't handle the gripper for this tutorial.
-
-.. figure:: ../../_static/tutorials/tutorial_add_new_robot_result.jpg
- :align: center
- :figwidth: 100%
- :alt: The new robots say hi!
diff --git a/docs/source/tutorials/index.rst b/docs/source/tutorials/index.rst
deleted file mode 100644
index 1e4a68befe1c..000000000000
--- a/docs/source/tutorials/index.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-:orphan:
-
-Tutorials Have Moved
-====================
-
-Tutorials and task-focused documentation are now collected in one searchable page. Continue to the
-:doc:`How-to Guides `.
diff --git a/docs/source/features/include/cloud_details.inc b/docs/source/workflows/docker/cloud.rst
similarity index 90%
rename from docs/source/features/include/cloud_details.inc
rename to docs/source/workflows/docker/cloud.rst
index f8810301bfd9..6ac7a781e56e 100644
--- a/docs/source/features/include/cloud_details.inc
+++ b/docs/source/workflows/docker/cloud.rst
@@ -1,4 +1,7 @@
-.. rubric:: Cloud Deployment
+.. _docker-cloud-cloud:
+
+Cloud Deployment
+================
Isaac Lab can be run in various cloud infrastructures with the use of
`Isaac Automator `__ (v4).
@@ -12,7 +15,8 @@ to save on cloud costs, and provides tools to aid the workflow
(uploading and downloading data, autorun scripts, deployment management, etc.).
-.. rubric:: System Requirements
+System Requirements
+-------------------
Isaac Automator requires having ``docker`` pre-installed on the system.
@@ -22,7 +26,8 @@ Isaac Automator requires having ``docker`` pre-installed on the system.
These steps allow you to run Docker without using ``sudo``.
-.. rubric:: Installing Isaac Automator
+Installing Isaac Automator
+--------------------------
For the most up-to-date and complete installation instructions, please refer to
the `Isaac Automator README `__.
@@ -44,7 +49,8 @@ To use Isaac Automator, first clone the repo:
git clone git@github.com:isaac-sim/IsaacAutomator.git
-.. rubric:: Building the Container
+Building the Container
+----------------------
Build the Isaac Automator container:
@@ -68,7 +74,8 @@ Build the Isaac Automator container:
This will build the Isaac Automator container and tag it as ``isaac_automator``.
-.. rubric:: Deploying an Isaac Workstation
+Deploying an Isaac Workstation
+------------------------------
.. tab-set::
:sync-group: os
@@ -127,7 +134,8 @@ Key deployment options:
- ``--from-image`` -- Deploy from a pre-built VM image for faster provisioning
(AWS only at this time).
-.. rubric:: Connecting to the Isaac Workstation
+Connecting to the Isaac Workstation
+-----------------------------------
Deployed Isaac Workstations can be accessed via:
@@ -139,7 +147,8 @@ Connection instructions are displayed at the end of the deployment command
output and saved in ``state//info.txt``.
-.. rubric:: Running Isaac Lab on the Cloud
+Running Isaac Lab on the Cloud
+------------------------------
Isaac Lab is installed from source on the deployed workstation at ``~/IsaacLab``.
To run Isaac Lab commands, open a terminal on the workstation:
@@ -150,7 +159,8 @@ To run Isaac Lab commands, open a terminal on the workstation:
--task=Isaac-Cartpole-Direct
-.. rubric:: Pausing and Resuming
+Pausing and Resuming
+--------------------
You can stop and restart instances to save on cloud costs:
@@ -164,7 +174,8 @@ Use ``./start --quick`` to skip full Ansible provisioning
and only run the autorun script.
-.. rubric:: Uploading and Downloading Data
+Uploading and Downloading Data
+------------------------------
.. code-block:: bash
@@ -175,7 +186,8 @@ and only run the autorun script.
./download
-.. rubric:: Destroying a Deployment
+Destroying a Deployment
+-----------------------
To save costs, destroy deployments when no longer needed:
diff --git a/docs/source/features/include/cluster_details.inc b/docs/source/workflows/docker/cluster.rst
similarity index 74%
rename from docs/source/features/include/cluster_details.inc
rename to docs/source/workflows/docker/cluster.rst
index 3da64a8643fc..ca94a7dcd19b 100644
--- a/docs/source/features/include/cluster_details.inc
+++ b/docs/source/workflows/docker/cluster.rst
@@ -1,7 +1,7 @@
.. _deployment-cluster:
-
-.. rubric:: Cluster Guide
+Running on HPC clusters
+=======================
Clusters are a great way to speed up training and evaluation of learning algorithms.
While the Isaac Lab Docker image can be used to run jobs on a cluster, many clusters only
@@ -10,8 +10,9 @@ ease-of-use on shared multi-user systems and high performance computing (HPC) en
It does not require root privileges to run containers and can be used to run user-defined
containers.
-Singularity is compatible with all Docker images. In this section, we describe how to
-convert the Isaac Lab Docker image into a singularity image and use it to submit jobs to a cluster.
+Singularity is compatible with all Docker images. This page describes how to convert the
+:ref:`Isaac Lab Docker image ` into a singularity image and use it to submit jobs
+to a cluster.
.. attention::
@@ -23,8 +24,8 @@ convert the Isaac Lab Docker image into a singularity image and use it to submit
adapted the instructions for another cluster, please consider contributing to the
documentation.
-
-.. rubric:: Setup Instructions
+Prerequisites
+-------------
In order to export the Docker Image to a singularity image, `apptainer`_ is required.
A detailed overview of the installation procedure for ``apptainer`` can be found in its
@@ -50,50 +51,30 @@ the user cluster password from being requested multiple times.
In the case of issues, please try to switch to those versions.
+Cluster configuration
+---------------------
-.. rubric:: Configuring the cluster parameters
+Configure the cluster-specific parameters in ``docker/cluster/.env.cluster``. Each parameter is
+documented inline in the file:
-First, you need to configure the cluster-specific parameters in ``docker/cluster/.env.cluster`` file.
-The following describes the parameters that need to be configured:
+.. literalinclude:: ../../../../docker/cluster/.env.cluster
+ :language: bash
-.. list-table::
- :header-rows: 1
- :widths: 20 80
+A few constraints are worth calling out:
- * - Parameter
- - Description
- * - CLUSTER_JOB_SCHEDULER
- - The job scheduler/workload manager used by your cluster. Currently, we support 'SLURM' and
- 'PBS' workload managers.
- * - CLUSTER_ISAAC_SIM_CACHE_DIR
- - The directory on the cluster where the Isaac Sim cache is stored. This directory
- has to end on ``docker-isaac-sim``. It will be copied to the compute node
- and mounted into the singularity container. This should increase the speed of starting
- the simulation.
- * - CLUSTER_ISAACLAB_DIR
- - The directory on the cluster where the Isaac Lab logs are stored. This directory has to
- end on ``isaaclab``. It will be copied to the compute node and mounted into
- the singularity container. When a job is submitted, the latest local changes will
- be copied to the cluster to a new directory in the format ``${CLUSTER_ISAACLAB_DIR}_${datetime}``
- with the date and time of the job submission. This allows to run multiple jobs with different code versions at
- the same time.
- * - CLUSTER_LOGIN
- - The login to the cluster. Typically, this is the user and cluster names,
- e.g., ``your_user@euler.ethz.ch``.
- * - CLUSTER_SIF_PATH
- - The path on the cluster where the singularity image will be stored. The image will be
- copied to the compute node but not uploaded again to the cluster when a job is submitted.
- * - REMOVE_CODE_COPY_AFTER_JOB
- - Whether the copied code should be removed after the job is finished or not. The logs from the job will not be deleted
- as these are saved under the permanent ``CLUSTER_ISAACLAB_DIR``. This feature is useful
- to save disk space on the cluster. If set to ``true``, the code copy will be removed.
- * - CLUSTER_PYTHON_EXECUTABLE
- - The path within Isaac Lab to the Python executable that should be executed in the submitted job.
+* ``CLUSTER_ISAAC_SIM_CACHE_DIR`` must end in ``docker-isaac-sim``. It is copied to the compute node
+ and mounted into the singularity container, which speeds up simulation startup.
+* ``CLUSTER_ISAACLAB_DIR`` must end in ``isaaclab``. On submission, the latest local changes are
+ copied to ``${CLUSTER_ISAACLAB_DIR}_${datetime}``, so several jobs can run different code versions
+ at once. Logs are written back to the permanent ``CLUSTER_ISAACLAB_DIR``.
+* ``REMOVE_CODE_COPY_AFTER_JOB`` deletes only that code copy, never the logs. Enable it to save disk
+ space on the cluster.
When a ``job`` is submitted, it will also use variables defined in ``docker/.env.base``, though these
should be correct by default.
-.. rubric:: Exporting to singularity image
+Exporting the Apptainer image
+-----------------------------
Next, we need to export the Docker image to a singularity image and upload
it to the cluster. This step is only required once when the first job is submitted
@@ -118,16 +99,14 @@ specified, the default profile ``base`` will be used.
the ``apptainer build`` command. In case the image creation fails, you can try to create it with root
access by removing the flag in ``docker/cluster/cluster_interface.sh``.
-
-.. rubric:: Defining the job parameters
+Defining job parameters
+-----------------------
The job parameters need to be defined based on the job scheduler used by your cluster.
You only need to update the appropriate script for the scheduler available to you.
-- For SLURM, update the parameters in ``docker/cluster/submit_job_slurm.sh``.
-- For PBS, update the parameters in ``docker/cluster/submit_job_pbs.sh``.
-
-.. rubric:: For SLURM
+SLURM
+~~~~~
The job parameters are defined inside the ``docker/cluster/submit_job_slurm.sh``.
A typical SLURM operation requires specifying the number of CPUs and GPUs, the memory, and
@@ -135,7 +114,7 @@ the time limit. For more information, please check the `SLURM documentation`_.
The default configuration is as follows:
-.. literalinclude:: ../../../docker/cluster/submit_job_slurm.sh
+.. literalinclude:: ../../../../docker/cluster/submit_job_slurm.sh
:language: bash
:lines: 12-19
:linenos:
@@ -148,13 +127,14 @@ must be loaded to allow internet access.
For instance, on ETH Zurich Euler cluster, the ``eth_proxy`` module needs to be loaded. This can be done
by adding the following line to the ``submit_job_slurm.sh`` script:
-.. literalinclude:: ../../../docker/cluster/submit_job_slurm.sh
+.. literalinclude:: ../../../../docker/cluster/submit_job_slurm.sh
:language: bash
:lines: 3-5
:linenos:
:lineno-start: 3
-.. rubric:: For PBS
+PBS
+~~~
The job parameters are defined inside the ``docker/cluster/submit_job_pbs.sh``.
A typical PBS operation requires specifying the number of CPUs and GPUs, and the time limit. For more
@@ -162,14 +142,14 @@ information, please check the `PBS Official Site`_.
The default configuration is as follows:
-.. literalinclude:: ../../../docker/cluster/submit_job_pbs.sh
+.. literalinclude:: ../../../../docker/cluster/submit_job_pbs.sh
:language: bash
:lines: 11-17
:linenos:
:lineno-start: 11
-
-.. rubric:: Submitting a job
+Submitting a job
+----------------
To submit a job on the cluster, the following command can be used:
@@ -195,8 +175,8 @@ ANYmal rough terrain locomotion training can be executed with the following comm
The above will, in addition, also render videos of the training progress and store them under ``isaaclab/logs`` directory.
-
-.. rubric:: For OSMO
+Submitting to OSMO
+------------------
`NVIDIA OSMO`_ is a cloud-native orchestration platform for scheduling robotics workloads. Unlike the
SLURM and PBS workflows above, it runs the Isaac Lab Docker image directly, so no singularity
diff --git a/docs/source/workflows/docker/images.rst b/docs/source/workflows/docker/images.rst
new file mode 100644
index 000000000000..f736cd9fddac
--- /dev/null
+++ b/docs/source/workflows/docker/images.rst
@@ -0,0 +1,186 @@
+.. _docker-images:
+
+Container images
+================
+
+Each :ref:`profile ` builds a different image. They differ in what simulation and
+rendering stack they carry, which decides how large they are and what they can run. This page
+describes the images themselves; to build or run one, name its profile in the
+:ref:`container lifecycle `.
+
+Choosing an image
+-----------------
+
+.. list-table::
+ :header-rows: 1
+ :widths: 12 40 48
+
+ * - Profile
+ - Contains
+ - Use it when
+ * - ``base``
+ - Isaac Lab on the NVIDIA Isaac Sim image, with Kit and RTX rendering
+ - You want the default environment, GUI rendering, or anything that needs Isaac Sim
+ * - ``ros2``
+ - The ``base`` image plus ROS 2 Humble
+ - You are bridging Isaac Lab to ROS 2 nodes
+ * - ``kitless``
+ - Ubuntu 24.04, Python 3.12, Newton and OVPhysX physics, OVRTX rendering, four RL libraries
+ - You are training with Newton and want the smallest image; also the only one with no Isaac Sim EULA
+
+Base image
+----------
+
+``Dockerfile.base`` overlays Isaac Lab's dependencies onto the Isaac Sim container, so it inherits
+Kit, RTX rendering, and the Isaac Sim asset pipeline. The Isaac Sim version it builds against is set
+by ``ISAACSIM_VERSION`` in ``.env.base``; the other variables in that file control paths inside the
+container.
+
+ROS 2 image
+-----------
+
+``Dockerfile.ros2`` installs ROS 2 Humble from an `apt package`_ and sources it in the runtime
+user's ``.bashrc``. ``ROS2_APT_PACKAGE`` in ``.env.ros2`` selects the package set, defaulting to
+``ros-base``. The image defaults to the ``FastRTPS`` middleware; ``CycloneDDS`` is also supported, and
+both can be `tuned`_ through their ``.xml`` files under ``docker/.ros``. See `various middleware`_
+for the trade-offs.
+
+.. dropdown:: Parameters in .env.ros2
+ :icon: code
+
+ .. literalinclude:: ../../../../docker/.env.ros2
+ :language: bash
+
+Kit-less image
+--------------
+
+The kit-less image drops Isaac Sim entirely and builds on Ubuntu 24.04 with Python 3.12. It carries
+Newton physics, OVPhysX physics, OVRTX rendering, and the four core RL frameworks: RL Games, RSL-RL,
+Stable-Baselines3, and SKRL. The ``newton_gl``, ``newton_rtx``, ``viser``, and ``rerun`` visualizers are
+included. Use ``--viz newton_gl`` for local visualization with a display available in the container.
+``--viz newton_gl`` selects the OpenGL rasterizer; ``--viz newton_rtx`` selects the OVRTX
+path tracer. Both can render offscreen without Isaac Sim. Windowed use additionally needs
+a display server accessible inside the container. The deprecated ``--viz newton`` alias
+selects GL; it does not choose between GL and RTX automatically.
+
+Rendering needs NVIDIA graphics driver capabilities in addition to compute. For direct
+``docker run`` commands, pass ``--gpus all -e NVIDIA_DRIVER_CAPABILITIES=all``. The NVIDIA
+Container Toolkit exposes the host driver; avoid mounting a second copy of its Vulkan ICD.
+If multiple drivers are discovered, select the NVIDIA ICD available inside the container
+with ``VK_DRIVER_FILES`` (for example, ``/etc/vulkan/icd.d/nvidia_icd.json``).
+
+No visualizer is selected by default, so
+training runs headless unless you ask for one. The ``kit`` visualizer is the exception: it comes from
+Omniverse Kit, which this image does not contain.
+
+Unlike the other two, it bind-mounts ``apps`` in addition to ``source``, ``scripts``, ``tools``, and
+``docs``, and it keeps a uv cache and a Warp cache of its own.
+
+You do not have to build it locally. It is published alongside each Isaac Lab release in the same
+registry repository, distinguished by a ``-kitless`` tag suffix:
+
+.. code:: bash
+
+ docker pull nvcr.io/nvidia/isaac-lab:3.0.0-rc1-kitless
+
+Running it directly, outside the Compose workflow, is a convenient way to verify the image and your
+NVIDIA Container Toolkit setup. ``--interactive`` and ``--tty`` keep the container's shell alive so
+that several commands can share it:
+
+.. code:: bash
+
+ docker run --name isaac-lab-kitless --detach --interactive --tty --gpus all --network host \
+ -e NVIDIA_DRIVER_CAPABILITIES=all \
+ nvcr.io/nvidia/isaac-lab:3.0.0-rc1-kitless
+
+ docker exec isaac-lab-kitless \
+ isaaclab train --rl_library rsl_rl --task Isaac-Cartpole-Direct \
+ --num_envs 16 presets=newton_mjwarp --max_iterations 5
+
+Replay in a browser with:
+
+.. code:: bash
+
+ docker exec --interactive --tty isaac-lab-kitless \
+ isaaclab play --rl_library rsl_rl --task Isaac-Cartpole-Direct \
+ --num_envs 16 presets=newton_mjwarp --checkpoint latest --viz viser
+
+Viser is reachable through the host network without forwarding a desktop display. Stop playback
+with ``Ctrl+C`` without stopping the container.
+To build the image from the checkout instead of
+pulling it, run ``docker build --file docker/Dockerfile.kitless --tag isaac-lab-kitless .``.
+
+Only ``linux/amd64`` images are published. The Dockerfile itself is architecture-agnostic, but the
+published manifest is limited to the architecture that is validated in CI.
+
+Pre-built image from NGC
+------------------------
+
+A minimal pre-built container carries a small set of Isaac Sim and Omniverse dependencies with Isaac
+Lab already built in, under ``/workspace/isaaclab``. The example below runs without a
+forwarded desktop display. Choose the image profile for the physics and rendering stack
+you need, and configure graphics access separately when rendering.
+
+.. note::
+
+ Use an explicit published version tag for reproducible runs. The examples below use
+ ``3.0.0-rc1``; the corresponding kit-less image uses ``3.0.0-rc1-kitless``.
+
+.. attention::
+
+ Images from 3.0.0-beta2 onward run as a **non-root** user, so those bind-mount directories must be
+ writable by uid/gid 1000. Docker creates any missing one as ``root``, which the runtime user cannot
+ write to, producing errors such as
+ ``PermissionError: [Errno 13] Permission denied: '/root/.local/share/ov/data/exts'``.
+ Create them first:
+
+ .. code:: bash
+
+ mkdir -p ~/docker/isaac-sim/{cache/kit,cache/ov,cache/pip,cache/glcache,cache/computecache,logs,data,documents}
+ sudo chown -R 1000:1000 ~/docker/isaac-sim
+
+Because it is run outside Compose, the Isaac Sim cache directories have to be mounted by hand,
+otherwise every start recompiles shaders:
+
+.. code:: bash
+
+ docker run --name isaac-lab --entrypoint bash -it --gpus all -e "ACCEPT_EULA=Y" --rm --network=host \
+ -e "PRIVACY_CONSENT=Y" \
+ -v ~/docker/isaac-sim/cache/kit:/isaac-sim/kit/cache:rw \
+ -v ~/docker/isaac-sim/cache/ov:/root/.cache/ov:rw \
+ -v ~/docker/isaac-sim/cache/pip:/root/.cache/pip:rw \
+ -v ~/docker/isaac-sim/cache/glcache:/root/.cache/nvidia/GLCache:rw \
+ -v ~/docker/isaac-sim/cache/computecache:/root/.nv/ComputeCache:rw \
+ -v ~/docker/isaac-sim/logs:/root/.nvidia-omniverse/logs:rw \
+ -v ~/docker/isaac-sim/data:/root/.local/share/ov/data:rw \
+ -v ~/docker/isaac-sim/documents:/root/Documents:rw \
+ nvcr.io/nvidia/isaac-lab:3.0.0-rc1
+
+For windowed use, follow the X11 setup in :ref:`deployment-docker`; the container needs
+access to the host display and matching authorization. For direct ``docker run`` use, add
+``-e DISPLAY -e XAUTHORITY=/tmp/isaaclab.xauth`` and the mounts
+``-v /tmp/.X11-unix:/tmp/.X11-unix:rw`` and
+``-v "${XAUTHORITY:-$HOME/.Xauthority}":/tmp/isaaclab.xauth:ro`` to the command above.
+The host authority file must exist and be readable by the container user. Offscreen Newton rendering does
+not require X11. Follow the graphics-driver requirements above for GL or RTX.
+
+Runtime user
+------------
+
+The base, ROS 2, cuRobo, and kit-less images all run as a non-root user with uid/gid 1000, which
+keeps bind-mounted workspaces writable on GitHub runners. When running one of these images directly
+with ``docker run`` from a host account whose uid differs, pass ``--user "$(id -u):1000"`` so that
+new files on bind mounts belong to your host user while the runtime home stays accessible.
+
+Python interpreter
+------------------
+
+Every image installs from ``uv.lock`` into a Python 3.12 virtual environment at
+``/opt/isaaclab-venv``. On the Isaac Sim-based images the environment is built on Isaac Sim's own
+interpreter, and Isaac Sim itself stays outside it, reached through the ``_isaac_sim`` symlink;
+``isaaclab.sh`` puts it on the path. In either case ``python`` on the container's ``PATH`` resolves
+to the right one, so scripts are run the same way regardless of image.
+
+.. _`apt package`: https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debians.html#install-ros-2-packages
+.. _`various middleware`: https://docs.ros.org/en/humble/How-To-Guides/Working-with-multiple-RMW-implementations.html
+.. _`tuned`: https://docs.ros.org/en/foxy/How-To-Guides/DDS-tuning.html
diff --git a/docs/source/workflows/docker/index.rst b/docs/source/workflows/docker/index.rst
new file mode 100644
index 000000000000..3404f7aed87c
--- /dev/null
+++ b/docs/source/workflows/docker/index.rst
@@ -0,0 +1,289 @@
+.. _docker-cloud:
+.. _deployment-docker:
+.. _docker-guide:
+
+Running Isaac Lab in Docker
+===========================
+
+Docker packages Isaac Lab and its dependencies into a reusable environment.
+``docker/container.py`` is the main entry point for running Isaac Lab in a container. It wraps
+``docker compose`` so that you do not have to remember which Dockerfile, environment files, and
+volume mounts belong together -- you name a *profile*, and the script assembles the rest.
+
+The image it builds is also the basis for the other workflows: :ref:`deployment-cluster` converts it
+to an Apptainer image, and :ref:`docker-cloud-cloud` provisions a machine that runs it.
+
+.. caution::
+
+ The standard Isaac Lab container depends on the Isaac Sim Docker image. By running that container, you are
+ implicitly agreeing to the `NVIDIA Software License Agreement`_. If you do not agree to the EULA, do not run
+ that container. The ``kitless`` image contains neither Isaac Sim nor Kit.
+
+Prerequisites
+-------------
+
+Install `Docker Engine `__, `Docker Compose
+`__, and the `NVIDIA Container Toolkit
+`__.
+The container is tested with Docker Engine 26.0.0 and Docker Compose 2.25.0; use these versions or
+newer. Follow the `post-installation steps`_ so that Docker runs without ``sudo``.
+
+The Isaac Sim documentation on `container installation`_ covers the same prerequisites in more
+detail, including how to obtain access to the Isaac Sim image.
+
+.. note::
+
+ Due to limitations with `snap `_, please make sure
+ the Isaac Lab directory is placed under the ``/home`` directory tree when using docker.
+
+Container profiles
+------------------
+
+A profile is a `Docker Compose profile `__:
+``docker-compose.yaml`` tags each service with one, and Compose starts only the services whose
+profile is active. Naming a profile therefore selects a matched set -- one service, one Dockerfile,
+one set of environment files, and one image name:
+
+.. list-table::
+ :header-rows: 1
+ :widths: 12 20 20 24 24
+
+ * - Profile
+ - Compose service
+ - Dockerfile
+ - Environment files
+ - Built on top of
+ * - ``base``
+ - ``isaac-lab-base``
+ - ``Dockerfile.base``
+ - ``.env.base``
+ - the Isaac Sim image
+ * - ``ros2``
+ - ``isaac-lab-ros2``
+ - ``Dockerfile.ros2``
+ - ``.env.base`` + ``.env.ros2``
+ - the ``base`` image, built first
+ * - ``kitless``
+ - ``isaac-lab-kitless``
+ - ``Dockerfile.kitless``
+ - ``.env.kitless``
+ - nothing -- standalone, no Isaac Sim
+
+Every command below takes the profile as its first positional argument and defaults to ``base``.
+Only one profile applies at a time, and the resulting image and container are both named
+``isaac-lab-``. Pass ``--suffix`` to append a name suffix when you want several variants of
+the same profile side by side. Do not use ``--suffix`` with cluster deployments, whose export
+commands expect the unsuffixed image name.
+
+For what each image actually contains and how to choose between them, see :ref:`docker-images`.
+
+.. _container-lifecycle:
+.. _docker-example:
+.. _worked-docker-example:
+
+Start, run, and retrieve results
+--------------------------------
+
+From the repository root on the host, build and start the default ``base`` container,
+then open a shell in it. Append a profile to target a different image:
+
+.. code-block:: bash
+
+ ./docker/container.py start
+ ./docker/container.py enter
+
+Inside the container, run the logging example without a visualizer:
+
+.. code-block:: bash
+
+ uv run isaaclab -p scripts/tutorials/00_sim/log_time.py --viz none
+
+The script writes simulation time at each step to
+``/workspace/isaaclab/logs/docker_tutorial/log.txt``. Stop the script with ``Ctrl+C``
+and type ``exit`` to return to the host shell. Retrieve the results before stopping
+the container:
+
+.. code-block:: bash
+
+ ./docker/container.py copy
+ ./docker/container.py stop
+
+The log is now at ``docker/artifacts/logs/docker_tutorial/log.txt`` on the host.
+The ``stop`` command removes the container and its Compose-managed volumes, including logs
+and caches; copy out anything you need first. The image remains. To remove it after stopping, run ``docker image rm isaac-lab-base``; the next ``start`` rebuilds it. See
+`Docker pruning `__ for other cleanup options.
+
+.. dropdown:: Code for log_time.py
+ :icon: code
+
+ .. literalinclude:: ../../../../scripts/tutorials/00_sim/log_time.py
+ :language: python
+ :linenos:
+
+.. note::
+
+ The image copies the repository to ``/workspace/isaaclab`` at build time, so edits made after the
+ build are not picked up automatically. To keep the development loop fast, the compose file
+ bind-mounts ``source``, ``scripts``, ``docs``, and ``tools`` from the host, so changes to those
+ directories appear inside the container immediately. Everything else requires a rebuild.
+
+``container.py`` command reference
+----------------------------------
+
+Run ``./docker/container.py --help`` to list commands and
+``./docker/container.py --help`` for that command's arguments.
+
+.. list-table::
+ :header-rows: 1
+ :widths: 20 80
+
+ * - Command
+ - Description
+ * - ``build``
+ - Build the image without creating a container.
+ * - ``start``
+ - Build the image and start the container in the background.
+ * - ``enter``
+ - Open a Bash shell in the running container.
+ * - ``config``
+ - Print the merged Compose configuration. Use ``--output-yaml `` to write it to a file instead.
+ * - ``copy``
+ - Copy logs, data, and built documentation to ``docker/artifacts`` on the host.
+ * - ``stop``
+ - Stop and remove the container and its Compose-managed volumes.
+
+Every command accepts the following arguments:
+
+.. list-table::
+ :header-rows: 1
+ :widths: 25 75
+
+ * - Argument
+ - Description
+ * - ``profile``
+ - Optional profile name; defaults to ``base``. Other profiles are ``ros2`` and ``kitless``.
+ * - ``--files [FILE ...]``
+ - Merge additional Compose YAML files after ``docker-compose.yaml``, in the supplied order.
+ * - ``--env-files [FILE ...]``
+ - Merge additional environment files after the profile defaults, in the supplied order.
+ * - ``--suffix [SUFFIX]``
+ - Append ``-SUFFIX`` to the image and container names. Omit it for unsuffixed names.
+ * - ``--info``
+ - Print the resolved container interface configuration instead of running the command.
+ * - ``-h``, ``--help``
+ - Show help and exit.
+
+Extending the Compose configuration
+-----------------------------------
+
+``--files`` and ``--env-files`` merge extra Compose and environment files into the generated
+configuration, which is how optional components are layered on without editing the checked-in files.
+Streaming to XR devices is the worked example -- it adds the CloudXR Runtime service alongside
+``base``:
+
+.. code:: bash
+
+ ./docker/container.py start --files docker-compose.cloudxr-runtime.patch.yaml --env-files .env.cloudxr-runtime
+
+Stop it with the same arguments. The teleoperation setup, firewall rules, and client connection
+steps are covered in :ref:`cloudxr-teleoperation`. Use ``./docker/container.py config`` to print the
+merged result when a combination does not behave as expected.
+
+What persists between runs
+--------------------------
+
+The compose file declares named volumes for Isaac Sim caches, logs, and your own data. They
+remain available while reusing a container, but ``container.py stop`` runs ``docker compose down
+--volumes`` and removes them. Run ``container.py copy`` before ``stop`` to preserve your results
+on the host.
+
+``container.py copy`` extracts the three volumes you are most likely to want on the host --
+``logs``, ``data_storage``, and ``docs/_build`` -- into ``docker/artifacts``. For anything else, use
+``docker cp``, for example ``docker cp isaac-lab-base:/workspace/isaaclab/logs .``.
+
+If you are upgrading from an Isaac Lab image that ran as ``root``, the existing volumes still hold
+root-owned files that the current uid/gid 1000 runtime user cannot write. Copy out anything worth
+keeping, then recreate them from the ``docker`` directory:
+
+.. code:: bash
+
+ docker compose --file docker-compose.yaml --profile base --env-file .env.base down --volumes
+
+.. dropdown:: All named volumes and their container paths
+ :icon: file-directory
+
+ .. list-table::
+ :header-rows: 1
+ :widths: 23 45 32
+
+ * - Volume Name
+ - Description
+ - Container Path
+ * - isaac-cache-kit
+ - Stores cached Kit resources
+ - /isaac-sim/kit/cache
+ * - isaac-data-kit
+ - Stores Kit data
+ - /isaac-sim/kit/data
+ * - isaac-cache-ov
+ - Stores cached OV resources
+ - /root/.cache/ov
+ * - isaac-cache-pip
+ - Stores cached pip resources
+ - /root/.cache/pip
+ * - isaac-cache-gl
+ - Stores cached GLCache resources
+ - /root/.cache/nvidia/GLCache
+ * - isaac-cache-compute
+ - Stores cached compute resources
+ - /root/.nv/ComputeCache
+ * - isaac-cache-uv
+ - Stores uv downloads for the kit-less profile
+ - /home/isaaclab/.cache/uv
+ * - isaac-cache-warp
+ - Stores Warp kernels for the kit-less profile
+ - /home/isaaclab/.cache/warp
+ * - isaac-logs
+ - Stores logs generated by Omniverse
+ - /root/.nvidia-omniverse/logs
+ * - isaac-carb-logs
+ - Stores logs generated by carb
+ - /isaac-sim/kit/logs/Kit/Isaac-Sim
+ * - isaac-data
+ - Stores data generated by Omniverse
+ - /root/.local/share/ov/data
+ * - isaac-docs
+ - Stores documents generated by Omniverse
+ - /root/Documents
+ * - isaac-lab-docs
+ - Stores documentation of Isaac Lab when built inside the container
+ - /workspace/isaaclab/docs/_build
+ * - isaac-lab-logs
+ - Stores logs generated by Isaac Lab workflows when run inside the container
+ - /workspace/isaaclab/logs
+ * - isaac-lab-data
+ - Stores whatever data users may want to preserve between container runs
+ - /workspace/isaaclab/data_storage
+
+ Run ``docker volume ls`` on the host to find the actual names, which include the Compose project
+ prefix, then use ``docker volume inspect ``. The ``kitless`` profile
+ uses the uv and Warp caches and shares the documentation, logs, and data volumes with the others.
+
+Display forwarding with X11
+---------------------------
+
+X11 forwarding lets GUI applications started inside the container display on the host. The first
+``start`` asks whether to enable it and records the answer in ``docker/.container.cfg``. To change it
+later, set ``X11_FORWARDING_ENABLED`` to ``0`` or ``1`` in that file and run ``start`` again -- the
+rebuild is what applies the change.
+
+.. toctree::
+ :maxdepth: 1
+
+ images
+ cluster
+ cloud
+
+.. _`NVIDIA Software License Agreement`: https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-software-license-agreement
+.. _`container installation`: https://docs.isaacsim.omniverse.nvidia.com/latest/installation/install_container.html
+.. _`post-installation steps`: https://docs.docker.com/engine/install/linux-postinstall/
diff --git a/docs/source/workflows/index.rst b/docs/source/workflows/index.rst
new file mode 100644
index 000000000000..714b6c47bf4d
--- /dev/null
+++ b/docs/source/workflows/index.rst
@@ -0,0 +1,40 @@
+.. _workflows:
+
+Workflows
+=========
+
+A workflow is a packaged way to run Isaac Lab somewhere other than a local Python environment. The
+task code, the configuration, and the command line stay the same; only the environment that executes
+them changes. Use this section once Isaac Lab runs locally through
+:ref:`isaaclab-installation-root` and you need a reproducible environment, a job scheduler, or a
+remote GPU.
+
+Every workflow below starts from the same container image, so they build on each other: the cluster
+workflow converts that image to Apptainer, and the cloud workflow provisions a machine that runs it.
+
+.. grid:: 1 1 3 3
+ :gutter: 2
+
+ .. grid-item-card:: **Docker**
+ :link: deployment-docker
+ :link-type: ref
+
+ Build and run Isaac Lab in a container for a reproducible environment on any Docker host.
+ **Start here** -- the other two workflows build on this image.
+
+ .. grid-item-card:: **HPC clusters**
+ :link: deployment-cluster
+ :link-type: ref
+
+ Convert the container to an Apptainer image and submit jobs through SLURM, PBS, or OSMO.
+
+ .. grid-item-card:: **Cloud workstations**
+ :link: docker-cloud-cloud
+ :link-type: ref
+
+ Provision a GPU workstation on AWS, GCP, Azure, or Alibaba Cloud with Isaac Automator.
+
+.. toctree::
+ :maxdepth: 2
+
+ docker/index
diff --git a/scripts/tools/convert_urdf.py b/scripts/tools/convert_urdf.py
index 803dd4979bae..e95d94ec6ef7 100644
--- a/scripts/tools/convert_urdf.py
+++ b/scripts/tools/convert_urdf.py
@@ -43,6 +43,14 @@
parser = argparse.ArgumentParser(description="Utility to convert a URDF into USD format.")
parser.add_argument("input", type=str, help="The path to the input URDF file.")
parser.add_argument("output", type=str, help="The path to store the USD file.")
+parser.add_argument(
+ "--ros_package_path",
+ nargs=2,
+ action="append",
+ default=[],
+ metavar=("NAME", "PATH"),
+ help="Map a ROS package name to its directory for package:// mesh paths. May be repeated.",
+)
parser.add_argument(
"--merge_joints",
"--merge-joints",
@@ -157,6 +165,7 @@ def main():
fix_base=args_cli.fix_base,
merge_fixed_joints=args_cli.merge_joints,
force_usd_conversion=True,
+ ros_package_paths=[{"name": name, "path": os.path.abspath(path)} for name, path in args_cli.ros_package_path],
joint_drive=UrdfConverterCfg.JointDriveCfg(
gains=UrdfConverterCfg.JointDriveCfg.PDGainsCfg(
stiffness=args_cli.joint_stiffness,
diff --git a/scripts/tutorials/03_envs/policy_inference_in_usd.py b/scripts/tutorials/03_envs/policy_inference_in_usd.py
index c9f1e3ce8433..61e61013ee57 100644
--- a/scripts/tutorials/03_envs/policy_inference_in_usd.py
+++ b/scripts/tutorials/03_envs/policy_inference_in_usd.py
@@ -16,27 +16,18 @@
"""
-"""Launch Isaac Sim Simulator first."""
-
-
import argparse
-from isaaclab.app import AppLauncher
+from isaaclab.app import add_launcher_args, launch_simulation
# add argparse arguments
parser = argparse.ArgumentParser(description="Tutorial on inferencing a policy on an H1 robot in a warehouse.")
parser.add_argument("--checkpoint", type=str, help="Path to model checkpoint exported as jit.", required=True)
-# append AppLauncher cli args
-AppLauncher.add_app_launcher_args(parser)
+add_launcher_args(parser)
# parse the arguments, forwarding unrecognized ones as Hydra-style task config overrides
args_cli, hydra_overrides = parser.parse_known_args()
-# launch omniverse app
-app_launcher = AppLauncher(args_cli)
-simulation_app = app_launcher.app
-
-"""Rest everything follows."""
import os
import torch
@@ -64,20 +55,23 @@ def main():
terrain_type="usd",
usd_path=f"{ISAAC_NUCLEUS_DIR}/Environments/Simple_Warehouse/warehouse.usd",
)
+ # The warehouse is enclosed: start the height-scan rays below its roof so they hit the floor.
+ env_cfg.scene.height_scanner.offset.pos = (0.0, 0.0, 2.0)
if args_cli.device == "cpu":
env_cfg.sim.use_fabric = False
- # create environment
- env = ManagerBasedRLEnv(cfg=env_cfg)
+ with launch_simulation(env_cfg, args_cli):
+ # create environment
+ env = ManagerBasedRLEnv(cfg=env_cfg)
- # run inference with the policy
- obs, _ = env.reset()
- with torch.inference_mode():
- while simulation_app.is_running():
- action = policy(obs["policy"])
- obs, _, _, _, _ = env.step(action)
+ # run inference with the policy
+ obs, _ = env.reset()
+ with torch.inference_mode():
+ while env.sim.is_headless_or_exist_active_visualizer():
+ action = policy(obs["policy"])
+ obs, _, _, _, _ = env.step(action)
+ env.close()
if __name__ == "__main__":
main()
- simulation_app.close()
diff --git a/scripts/tutorials/05_controllers/run_osc.py b/scripts/tutorials/05_controllers/run_osc.py
index 5089ec7824c5..f3665010d7ad 100644
--- a/scripts/tutorials/05_controllers/run_osc.py
+++ b/scripts/tutorials/05_controllers/run_osc.py
@@ -147,9 +147,9 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
# Define targets for the arm (x,y,z,qx,qy,qz,qw)
ee_goal_pose_set_tilted_b = torch.tensor(
[
- [0.6, 0.15, 0.3, 0.0, 0.38268343, 0.0, 0.92387953],
- [0.6, -0.3, 0.3, 0.0, 0.38268343, 0.0, 0.92387953],
- [0.8, 0.0, 0.5, 0.0, 0.38268343, 0.0, 0.92387953],
+ [0.6, 0.15, 0.3, 0.92387953, 0.0, 0.38268343, 0.0],
+ [0.6, -0.3, 0.3, 0.92387953, 0.0, 0.38268343, 0.0],
+ [0.8, 0.0, 0.5, 0.92387953, 0.0, 0.38268343, 0.0],
],
device=sim.device,
)
diff --git a/skills/user/convert-direct-to-manager/SKILL.md b/skills/user/convert-direct-to-manager/SKILL.md
index 11bdbd8f5835..502f51be9e45 100644
--- a/skills/user/convert-direct-to-manager/SKILL.md
+++ b/skills/user/convert-direct-to-manager/SKILL.md
@@ -48,7 +48,7 @@ uv run --no-project python tools/skills/cli.py check
## Maintenance
-Keep this skill synchronized with `docs/source/concepts/task_workflows.rst`, `docs/source/tutorials/03_envs/create_manager_rl_env.rst`, direct/manager paired examples under `source/isaaclab_tasks/isaaclab_tasks/core/`, and shared MDP terms under task-specific `mdp/` packages.
+Keep this skill synchronized with `docs/source/concepts/task_workflows.rst`, `docs/source/how-to/create_manager_rl_env.rst`, direct/manager paired examples under `source/isaaclab_tasks/isaaclab_tasks/core/`, and shared MDP terms under task-specific `mdp/` packages.
## References
@@ -57,8 +57,8 @@ Keep this skill synchronized with `docs/source/concepts/task_workflows.rst`, `do
- [Environment building skill](../create-environments/SKILL.md)
- [Isaac Gym migration skill](../migrate-from-isaac-gym/SKILL.md)
- [Task workflows](../../../docs/source/concepts/task_workflows.rst)
-- [Create manager-based RL environment tutorial](../../../docs/source/tutorials/03_envs/create_manager_rl_env.rst)
-- [Register Gym environment tutorial](../../../docs/source/tutorials/03_envs/register_rl_env_gym.rst)
+- [Create manager-based RL environment tutorial](../../../docs/source/how-to/create_manager_rl_env.rst)
+- [Register Gym environment tutorial](../../../docs/source/how-to/register_rl_env_gym.rst)
- [Ant direct environment](../../../source/isaaclab_tasks/isaaclab_tasks/core/locomotion/ant/ant_direct_env.py)
- [Ant direct config](../../../source/isaaclab_tasks/isaaclab_tasks/core/locomotion/ant/ant_direct_env_cfg.py)
- [Ant manager config](../../../source/isaaclab_tasks/isaaclab_tasks/core/locomotion/ant/ant_manager_env_cfg.py)
diff --git a/skills/user/create-environments/SKILL.md b/skills/user/create-environments/SKILL.md
index 5e9c336370d6..265e32292c87 100644
--- a/skills/user/create-environments/SKILL.md
+++ b/skills/user/create-environments/SKILL.md
@@ -50,7 +50,7 @@ uv run --no-project python tools/skills/cli.py check
## Maintenance
-Keep this skill synchronized with `docs/source/concepts/task_workflows.rst`, the environment tutorials under `docs/source/tutorials/03_envs/`, and maintained task examples under `source/isaaclab_tasks/isaaclab_tasks/`. If workflow documentation is missing or stale, update the docs or examples first and keep this skill focused on choosing the right path.
+Keep this skill synchronized with `docs/source/concepts/task_workflows.rst`, the environment tutorials under `docs/source/how-to/`, and maintained task examples under `source/isaaclab_tasks/isaaclab_tasks/`. If workflow documentation is missing or stale, update the docs or examples first and keep this skill focused on choosing the right path.
## References
@@ -58,9 +58,9 @@ Keep this skill synchronized with `docs/source/concepts/task_workflows.rst`, the
- [Examples](examples.md)
- [Manipulation planning skill](../plan-manipulation-tasks/SKILL.md)
- [Task workflows](../../../docs/source/concepts/task_workflows.rst)
-- [Create manager-based base environment tutorial](../../../docs/source/tutorials/03_envs/create_manager_base_env.rst)
-- [Create manager-based RL environment tutorial](../../../docs/source/tutorials/03_envs/create_manager_rl_env.rst)
-- [Register Gym environment tutorial](../../../docs/source/tutorials/03_envs/register_rl_env_gym.rst)
+- [Create manager-based base environment tutorial](../../../docs/source/how-to/create_manager_base_env.rst)
+- [Create manager-based RL environment tutorial](../../../docs/source/how-to/create_manager_rl_env.rst)
+- [Register Gym environment tutorial](../../../docs/source/how-to/register_rl_env_gym.rst)
- [Direct to manager conversion skill](../convert-direct-to-manager/SKILL.md)
-- [Create direct workflow environment tutorial](../../../docs/source/tutorials/03_envs/create_direct_rl_env.rst)
-- [Modify direct workflow environment tutorial](../../../docs/source/tutorials/03_envs/modify_direct_rl_env.rst)
+- [Create direct workflow environment tutorial](../../../docs/source/how-to/create_direct_rl_env.rst)
+- [Modify direct workflow environment tutorial](../../../docs/source/how-to/modify_direct_rl_env.rst)
diff --git a/skills/user/create-environments/examples.md b/skills/user/create-environments/examples.md
index 218ae8634b82..85809201a203 100644
--- a/skills/user/create-environments/examples.md
+++ b/skills/user/create-environments/examples.md
@@ -6,8 +6,8 @@ Use manager-based workflow by default for new Isaac Lab tasks. This is the frame
Start from:
-- `docs/source/tutorials/03_envs/create_manager_base_env.rst`
-- `docs/source/tutorials/03_envs/create_manager_rl_env.rst`
+- `docs/source/how-to/create_manager_base_env.rst`
+- `docs/source/how-to/create_manager_rl_env.rst`
- `source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_manager_env_cfg.py`
- `source/isaaclab_tasks/isaaclab_tasks/core/velocity/velocity_env_cfg.py`
- `source/isaaclab_tasks/isaaclab_tasks/core/velocity/config/go2/rough_env_cfg.py`
@@ -28,7 +28,7 @@ Use direct workflow when the task has custom low-level step/reset logic, must st
Start from:
-- `docs/source/tutorials/03_envs/create_direct_rl_env.rst`
+- `docs/source/how-to/create_direct_rl_env.rst`
- `source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_env_cfg.py`
- `source/isaaclab_tasks/isaaclab_tasks/contrib/anymal_c_direct/anymal_c_env_cfg.py`
@@ -55,5 +55,5 @@ When adding a new Gym task:
Reference:
-- `docs/source/tutorials/03_envs/register_rl_env_gym.rst`
-- `docs/source/tutorials/03_envs/configuring_rl_training.rst`
+- `docs/source/how-to/register_rl_env_gym.rst`
+- `docs/source/how-to/configuring_rl_training.rst`
diff --git a/skills/user/domain-randomization-events/SKILL.md b/skills/user/domain-randomization-events/SKILL.md
index 95b4221c83d1..943b18b13ed2 100644
--- a/skills/user/domain-randomization-events/SKILL.md
+++ b/skills/user/domain-randomization-events/SKILL.md
@@ -62,8 +62,8 @@ Keep this skill synchronized with `source/isaaclab/isaaclab/managers/event_manag
- [Examples](examples.md)
- [Evaluations](evaluations.md)
- [Event manager source](../../../source/isaaclab/isaaclab/managers/event_manager.py)
-- [Direct workflow randomization tutorial](../../../docs/source/tutorials/03_envs/create_direct_rl_env.rst)
-- [Manager-based event terms tutorial](../../../docs/source/tutorials/03_envs/create_manager_base_env.rst)
+- [Direct workflow randomization tutorial](../../../docs/source/how-to/create_direct_rl_env.rst)
+- [Manager-based event terms tutorial](../../../docs/source/how-to/create_manager_base_env.rst)
- [Curriculum utilities guide](../../../docs/source/how-to/curriculums.rst)
- [Core Lift ADR config](../../../source/isaaclab_tasks/isaaclab_tasks/core/lift/adr_curriculum.py)
- [Managers API](../../../docs/source/api/lab/isaaclab.managers.rst)
diff --git a/skills/user/install-isaac-lab/SKILL.md b/skills/user/install-isaac-lab/SKILL.md
index 74d305a3b2f9..6280ccdf1890 100644
--- a/skills/user/install-isaac-lab/SKILL.md
+++ b/skills/user/install-isaac-lab/SKILL.md
@@ -64,7 +64,7 @@ Keep this skill synchronized with the following install docs. If commands or ver
- `docs/source/setup/installation/index.rst` — `installation-method-binary` steps (downloaded Isaac Sim package).
- `docs/source/setup/installation/index.rst` — `installation-method-source` steps (Isaac Sim source build) and the `installation-asset-region-profiles` workflow.
- `docs/source/setup/installation/asset_caching_details.inc` — asset caching notes.
-- `docs/source/features/docker_cloud.rst` — Docker and cloud-workstation deep dive; complements `installation-method-container` and `installation-method-cloud` in `index.rst`.
+- `docs/source/workflows/docker/index.rst` — Docker and cloud-workstation deep dive; complements `installation-method-container` and `installation-method-cloud` in `index.rst`.
- `docs/source/refs/troubleshooting.rst` — hand-off target for post-install diagnostics.
This skill is a router and executor, not a copy of the install pages. Adding install methods, changing version pins, or updating command sequences belongs in the docs above, not in this file.
@@ -81,7 +81,7 @@ This skill is a router and executor, not a copy of the install pages. Adding ins
- Isaac Lab Python package (external projects): section `installation-method-wheel` in `index.rst`
- Downloaded Isaac Sim package (older distros): section `installation-method-binary` in `index.rst`
- Isaac Sim source build: section `installation-method-source` in `index.rst`
-- Docker and HPC clusters: section `installation-method-container` in `index.rst`, deep-dive in `docs/source/features/docker_cloud.rst`
+- Docker and HPC clusters: section `installation-method-container` in `index.rst`, deep-dive in `docs/source/workflows/docker/index.rst`
- Cloud workstations: section `installation-method-cloud` in `index.rst`
- Troubleshooting: `docs/source/refs/troubleshooting.rst`
- Cross-skill hand-off for post-install issues: `isaaclab-setup-troubleshooting`.
diff --git a/skills/user/install-isaac-lab/reference.md b/skills/user/install-isaac-lab/reference.md
index 7d235fc209f8..5684f4a9dfbe 100644
--- a/skills/user/install-isaac-lab/reference.md
+++ b/skills/user/install-isaac-lab/reference.md
@@ -45,7 +45,7 @@ User-stated preferences override the routing and map directly:
| External extension author, Isaac Lab wheel only | `docs/source/setup/installation/index.rst` (`installation-method-wheel`) |
| Newton-only workflow, no Isaac Sim | `docs/source/setup/installation/index.rst` (`installation-legacy-installer`) |
| Managed venv or conda with pip Isaac Sim | `docs/source/setup/installation/index.rst` (`installation-method-python-env`) |
-| Containerized deployment | `docs/source/setup/installation/index.rst` (`installation-method-container`); deep-dive `docs/source/features/docker_cloud.rst` |
+| Containerized deployment | `docs/source/setup/installation/index.rst` (`installation-method-container`); deep-dive `docs/source/workflows/docker/index.rst` |
| Cloud-hosted GPU workstation | `docs/source/setup/installation/index.rst` (`installation-method-cloud`) |
## Express Flow Rules
@@ -110,7 +110,7 @@ Apply at most one documented fix per failed step, retry once, then stop and hand
| `nvidia-smi` missing or driver too old | `docs/source/setup/installation/index.rst` ("System requirements" — driver minimums) |
| Network timeout fetching wheels | Retry the step once; then check proxy/firewall for github.com, pypi.org, pypi.nvidia.com, download.pytorch.org |
| Windows path-too-long errors | Windows tab of the chosen section (long-path support) |
-| Docker step fails with runtime error | `docs/source/features/docker_cloud.rst` (NVIDIA Container Toolkit setup) |
+| Docker step fails with runtime error | `docs/source/workflows/docker/index.rst` (NVIDIA Container Toolkit setup) |
| Import fails after install completes | Hand off to `isaaclab-setup-troubleshooting` |
## Cross-Skill Routing
diff --git a/skills/user/migrate-from-isaac-gym/SKILL.md b/skills/user/migrate-from-isaac-gym/SKILL.md
index cacb1fde3fe5..d28b5af80935 100644
--- a/skills/user/migrate-from-isaac-gym/SKILL.md
+++ b/skills/user/migrate-from-isaac-gym/SKILL.md
@@ -75,5 +75,5 @@ Keep this skill synchronized with the Isaac Gym section in `docs/source/migratio
- [Backend architecture](../../../docs/source/concepts/backend_architecture.rst)
- [Schema cfgs](../../../docs/source/concepts/schema_cfgs.rst)
- [Environment browser](../../../docs/source/setup/environments.rst)
-- [Create direct workflow environment tutorial](../../../docs/source/tutorials/03_envs/create_direct_rl_env.rst)
-- [Create manager-based environment tutorial](../../../docs/source/tutorials/03_envs/create_manager_rl_env.rst)
+- [Create direct workflow environment tutorial](../../../docs/source/how-to/create_direct_rl_env.rst)
+- [Create manager-based environment tutorial](../../../docs/source/how-to/create_manager_rl_env.rst)
diff --git a/skills/user/setup-troubleshooting/SKILL.md b/skills/user/setup-troubleshooting/SKILL.md
index c90b495150ba..d4f6f6f3418d 100644
--- a/skills/user/setup-troubleshooting/SKILL.md
+++ b/skills/user/setup-troubleshooting/SKILL.md
@@ -56,6 +56,6 @@ Keep this skill synchronized with the unified installation guide, the Docker/Clo
- [Quickstart](../../../docs/source/setup/quickstart.rst)
- [Installation](../../../docs/source/setup/installation/index.rst)
- [XR teleoperation setup](../../../docs/source/how-to/cloudxr_teleoperation.rst)
-- [Docker/Cloud](../../../docs/source/features/docker_cloud.rst)
+- [Docker/Cloud](../../../docs/source/workflows/docker/index.rst)
- [Physics backends](../../../docs/source/concepts/physics_backends.rst)
- [Troubleshooting](../../../docs/source/refs/troubleshooting.rst)
diff --git a/skills/user/setup-troubleshooting/reference.md b/skills/user/setup-troubleshooting/reference.md
index 614acf4f6ce6..716af354519b 100644
--- a/skills/user/setup-troubleshooting/reference.md
+++ b/skills/user/setup-troubleshooting/reference.md
@@ -18,7 +18,7 @@ Ask which install path the user is following before prescribing commands. For a
| Pip package | `docs/source/setup/installation/index.rst` |
| Isaac Lab pip package | `docs/source/setup/installation/index.rst` |
| Binary package | `docs/source/setup/installation/index.rst` |
-| Cloud setup | `docs/source/features/docker_cloud.rst` |
+| Cloud setup | `docs/source/workflows/docker/cloud.rst` |
| Legacy installer or setup without Isaac Sim | `docs/source/setup/installation/index.rst` |
| Newton setup | `docs/source/setup/installation/index.rst` and `docs/source/concepts/physics_backends.rst` |
| PhysX setup | `docs/source/setup/installation/index.rst` and `docs/source/concepts/physics_backends.rst` |
diff --git a/skills/user/train-rl-agents/SKILL.md b/skills/user/train-rl-agents/SKILL.md
index 2a1dc792d7a3..4b121a618bd7 100644
--- a/skills/user/train-rl-agents/SKILL.md
+++ b/skills/user/train-rl-agents/SKILL.md
@@ -50,7 +50,7 @@ uv run --no-project python tools/skills/cli.py check
## Maintenance
-Keep this skill synchronized with `docs/source/concepts/reinforcement_learning.rst`, `docs/source/setup/installation/index.rst`, RL training tutorials under `docs/source/tutorials/03_envs/`, and agent configs under `source/isaaclab_tasks/isaaclab_tasks/`. If framework commands or config formats change, update the official training docs or maintained examples first.
+Keep this skill synchronized with `docs/source/concepts/reinforcement_learning.rst`, `docs/source/setup/installation/index.rst`, RL training tutorials under `docs/source/how-to/`, and agent configs under `source/isaaclab_tasks/isaaclab_tasks/`. If framework commands or config formats change, update the official training docs or maintained examples first.
## References
@@ -59,6 +59,6 @@ Keep this skill synchronized with `docs/source/concepts/reinforcement_learning.r
- [Debug RL training skill](../debug-rl-training/SKILL.md)
- [Multi-GPU training skill](../train-multi-gpu/SKILL.md)
- [RL training guide](../../../docs/source/concepts/reinforcement_learning.rst)
-- [Configure RL training tutorial](../../../docs/source/tutorials/03_envs/configuring_rl_training.rst)
-- [Run RL training tutorial](../../../docs/source/tutorials/03_envs/run_rl_training.rst)
+- [Configure RL training tutorial](../../../docs/source/how-to/configuring_rl_training.rst)
+- [Run RL training tutorial](../../../docs/source/how-to/run_rl_training.rst)
- [Task examples](../../../source/isaaclab_tasks/isaaclab_tasks)
diff --git a/skills/user/use-sensors-actuators/SKILL.md b/skills/user/use-sensors-actuators/SKILL.md
index 3eb84ed050c7..ac85e1ece23c 100644
--- a/skills/user/use-sensors-actuators/SKILL.md
+++ b/skills/user/use-sensors-actuators/SKILL.md
@@ -50,7 +50,7 @@ uv run --no-project python tools/skills/cli.py check
Keep this skill synchronized with actuator docs under `docs/source/concepts/`, sensor docs under
`docs/source/concepts/sensors/`, sensor tutorials under
-`docs/source/tutorials/04_sensors/`, API docs under `docs/source/api/`, and maintained task examples
+`docs/source/how-to/`, API docs under `docs/source/api/`, and maintained task examples
under `source/isaaclab_tasks/isaaclab_tasks/`. If sensor support changes for PhysX, Newton, or
renderers, update the docs or source examples first.
@@ -58,7 +58,7 @@ renderers, update the docs or source examples first.
- [Evaluations](evaluations.md)
- [Examples](examples.md)
-- [Add sensors on robot tutorial](../../../docs/source/tutorials/04_sensors/add_sensors_on_robot.rst)
+- [Add sensors on robot tutorial](../../../docs/source/how-to/add_sensors_on_robot.rst)
- [Contact sensor docs](../../../docs/source/concepts/sensors/contact_sensor.rst)
- [Joint wrench sensor docs](../../../docs/source/concepts/sensors/joint_wrench_sensor.rst)
- [Actuators docs](../../../docs/source/concepts/actuators.rst)
diff --git a/skills/user/use-sensors-actuators/examples.md b/skills/user/use-sensors-actuators/examples.md
index b96830763bf9..803a02a3c5f3 100644
--- a/skills/user/use-sensors-actuators/examples.md
+++ b/skills/user/use-sensors-actuators/examples.md
@@ -43,7 +43,7 @@ Use camera or tiled-camera examples before adding visual observations to trainin
Examples to inspect:
- `source/isaaclab_tasks/isaaclab_tasks/core/cartpole/cartpole_direct_camera_env_cfg.py`
-- `docs/source/tutorials/04_sensors/add_sensors_on_robot.rst`
+- `docs/source/how-to/add_sensors_on_robot.rst`
Validation checklist:
diff --git a/tools/test/test_doc_redirects.py b/tools/test/test_doc_redirects.py
new file mode 100644
index 000000000000..df5023e6b9c1
--- /dev/null
+++ b/tools/test/test_doc_redirects.py
@@ -0,0 +1,72 @@
+# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
+# All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""Tests for compatibility URLs after documentation moves."""
+
+import importlib.util
+import json
+import re
+from pathlib import Path
+from types import SimpleNamespace
+
+import pytest
+
+
+@pytest.fixture
+def redirects():
+ path = Path(__file__).resolve().parents[2] / "docs/_extensions/isaaclab_docs.py"
+ spec = importlib.util.spec_from_file_location("isaaclab_docs", path)
+ module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(module)
+ return module._write_doc_redirects
+
+
+def test_redirect_preserves_old_url_and_fragment(tmp_path, redirects):
+ """An old nested URL forwards to its built destination and preserves client state."""
+ target = tmp_path / "source/how-to/example.html"
+ target.parent.mkdir(parents=True)
+ target.write_text("new guide")
+ app = SimpleNamespace(
+ builder=SimpleNamespace(format="html", get_outfilename=lambda doc: str(tmp_path / (doc + ".html"))),
+ config=SimpleNamespace(isaaclab_doc_redirects={"source/tutorials/00_sim/example": "source/how-to/example"}),
+ )
+ redirects(app, None)
+ html = (tmp_path / "source/tutorials/00_sim/example.html").read_text()
+ assert 'href="../../how-to/example.html"' in html
+ assert '["../../how-to/example.html", location.hash]' in html
+ assert "location.replace(target[0] + location.search + target[1])" in html
+ assert target.read_text() == "new guide"
+
+
+def test_redirect_rejects_missing_destination(tmp_path, redirects):
+ """Fail the build instead of publishing a redirect to a missing guide."""
+ app = SimpleNamespace(
+ builder=SimpleNamespace(format="html", get_outfilename=lambda doc: str(tmp_path / (doc + ".html"))),
+ config=SimpleNamespace(isaaclab_doc_redirects={"old": "missing"}),
+ )
+ with pytest.raises(ValueError, match="target was not built: missing"):
+ redirects(app, None)
+ assert not (tmp_path / "old.html").exists()
+
+
+def test_redirect_routes_split_sections_and_rejects_missing_page(tmp_path, redirects):
+ """An old section reaches the page that now contains it, not the default landing page."""
+ for name in ("index", "cluster"):
+ (tmp_path / f"{name}.html").write_text("new guide")
+ app = SimpleNamespace(
+ builder=SimpleNamespace(format="html", get_outfilename=lambda doc: str(tmp_path / (doc + ".html"))),
+ config=SimpleNamespace(
+ isaaclab_doc_redirects={"old": "index"},
+ isaaclab_doc_redirect_fragments={"old": {"clusters": "cluster#deployment-cluster"}},
+ ),
+ )
+ redirects(app, None)
+ html = (tmp_path / "old.html").read_text()
+ routes = json.loads(re.search(r"const sections = (.*);", html).group(1))
+ assert routes["#clusters"] == ["cluster.html", "#deployment-cluster"]
+ assert "location.search" in html
+ (tmp_path / "cluster.html").unlink()
+ with pytest.raises(ValueError, match="target was not built: cluster"):
+ redirects(app, None)