Skip to content

Commit

Permalink
Adds a validity check for configclasses (isaac-sim#1214)
Browse files Browse the repository at this point in the history
# Description

Added a mechanism to check for the validity of a configclass object.
A configclass object is valid if it contains no MISSING attributes.

## Type of change

- New feature (non-breaking change which adds functionality)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
  • Loading branch information
Dhoeller19 authored Oct 23, 2024
1 parent 6bc4d0a commit bd4cd3b
Show file tree
Hide file tree
Showing 53 changed files with 414 additions and 222 deletions.
34 changes: 19 additions & 15 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@ name: Build & deploy docs

on:
push:
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
check-secrets:
name: Check secrets
runs-on: ubuntu-latest
outputs:
trigger-deploy: ${{ steps.trigger-deploy.outputs.defined }}
steps:
- id: trigger-deploy
env:
REPO_NAME: ${{ secrets.REPO_NAME }}
BRANCH_REF: ${{ secrets.BRANCH_REF }}
if: "${{ github.repository == env.REPO_NAME && github.ref == env.BRANCH_REF }}"
run: echo "defined=true" >> "$GITHUB_OUTPUT"

build-docs:
name: Build Docs
runs-on: ubuntu-latest
needs: [check-secrets]

steps:
- name: Checkout code
Expand All @@ -24,8 +41,8 @@ jobs:
run: pip install -r requirements.txt

- name: Check branch docs building
if: ${{ github.event_name == 'pull_request' }}
working-directory: ./docs
if: needs.check-secrets.outputs.trigger-deploy != 'true'
run: make current-docs

- name: Generate multi-version docs
Expand All @@ -40,19 +57,6 @@ jobs:
name: docs-html
path: ./docs/_build

check-secrets:
name: Check secrets
runs-on: ubuntu-latest
outputs:
trigger-deploy: ${{ steps.trigger-deploy.outputs.defined }}
steps:
- id: trigger-deploy
env:
REPO_NAME: ${{ secrets.REPO_NAME }}
BRANCH_REF: ${{ secrets.BRANCH_REF }}
if: "${{ github.repository == env.REPO_NAME && github.ref == env.BRANCH_REF }}"
run: echo "defined=true" >> "$GITHUB_OUTPUT"

deploy-docs:
name: Deploy Docs
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@

def skip_member(app, what, name, obj, skip, options):
# List the names of the functions you want to skip here
exclusions = ["from_dict", "to_dict", "replace", "copy", "__post_init__"]
exclusions = ["from_dict", "to_dict", "replace", "copy", "validate", "__post_init__"]
if name in exclusions:
return True
return None
Expand Down
16 changes: 3 additions & 13 deletions docs/source/tutorials/03_envs/create_manager_rl_env.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ For this tutorial, we use the cartpole environment defined in ``omni.isaac.lab_t

.. literalinclude:: ../../../../source/extensions/omni.isaac.lab_tasks/omni/isaac/lab_tasks/manager_based/classic/cartpole/cartpole_env_cfg.py
:language: python
:emphasize-lines: 63-68, 124-149, 152-162, 165-169, 187-192
:emphasize-lines: 117-141, 144-154, 172-174
:linenos:

The script for running the environment ``run_cartpole_rl_env.py`` is present in the
Expand Down Expand Up @@ -117,13 +117,8 @@ For various goal-conditioned tasks, it is useful to specify the goals or command
handled through the :class:`managers.CommandManager`. The command manager handles resampling and updating the
commands at each step. It can also be used to provide the commands as an observation to the agent.

For this simple task, we do not use any commands. This is specified by using a command term with the
:class:`envs.mdp.NullCommandCfg` configuration. However, you can see an example of command definitions in the
locomotion or manipulation tasks.

.. literalinclude:: ../../../../source/extensions/omni.isaac.lab_tasks/omni/isaac/lab_tasks/manager_based/classic/cartpole/cartpole_env_cfg.py
:language: python
:pyobject: CommandsCfg
For this simple task, we do not use any commands. Hence, we leave this attribute as its default value, which is None.
You can see an example of how to define a command manager in the other locomotion or manipulation tasks.

Defining curriculum
-------------------
Expand All @@ -134,11 +129,6 @@ we provide a :class:`managers.CurriculumManager` class that can be used to defin

In this tutorial we don't implement a curriculum for simplicity, but you can see an example of a
curriculum definition in the other locomotion or manipulation tasks.
We use a simple pass-through curriculum to define a curriculum manager that does not modify the environment.

.. literalinclude:: ../../../../source/extensions/omni.isaac.lab_tasks/omni/isaac/lab_tasks/manager_based/classic/cartpole/cartpole_env_cfg.py
:language: python
:pyobject: CurriculumCfg

Tying it all together
---------------------
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/omni.isaac.lab/config/extension.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

# Note: Semantic Versioning is used: https://semver.org/
version = "0.26.0"
version = "0.27.0"

# Description
title = "Isaac Lab framework for Robot Learning"
Expand Down
17 changes: 17 additions & 0 deletions source/extensions/omni.isaac.lab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
Changelog
---------

0.27.0 (2024-10-14)
~~~~~~~~~~~~~~~~~~~

Added
^^^^^

* Added a method to :class:`~omni.isaac.lab.utils.configclass` to check for attributes with values of
type ``MISSING``. This is useful when the user wants to check if a certain attribute has been set or not.
* Added the configuration validation check inside the constructor of all the core classes
(such as sensor base, asset base, scene and environment base classes).
* Added support for environments without commands by leaving the attribute
:attr:`omni.isaac.lab.envs.ManagerBasedRLEnvCfg.commands` as None. Before, this had to be done using
the class :class:`omni.isaac.lab.command_generators.NullCommandGenerator`.
* Moved the ``meshes`` attribute in the :class:`omni.isaac.lab.sensors.RayCaster` class from class variable to instance variable.
This prevents the meshes to overwrite each other.


0.26.0 (2024-10-16)
~~~~~~~~~~~~~~~~~~~

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ def __init__(self, cfg: AssetBaseCfg):
Raises:
RuntimeError: If no prims found at input prim path or prim path expression.
"""
# check that the config is valid
cfg.validate()
# store inputs
self.cfg = cfg
# flag for whether the asset is initialized
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ class InitialStateCfg:
Defaults to (1.0, 0.0, 0.0, 0.0).
"""

class_type: type[AssetBase] = MISSING
"""The associated asset class.
class_type: type[AssetBase] = None
"""The associated asset class. Defaults to None, which means that the asset will be spawned
but cannot be interacted with via the asset class.
The class should inherit from :class:`omni.isaac.lab.assets.asset_base.AssetBase`.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ def __init__(self, cfg: DirectMARLEnvCfg, render_mode: str | None = None, **kwar
RuntimeError: If a simulation context already exists. The environment must always create one
since it configures the simulation context and controls the simulation.
"""
# check that the config is valid
cfg.validate()
# store inputs to class
self.cfg = cfg
# store the render mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ def __init__(self, cfg: DirectRLEnvCfg, render_mode: str | None = None, **kwargs
RuntimeError: If a simulation context already exists. The environment must always create one
since it configures the simulation context and controls the simulation.
"""
# check that the config is valid
cfg.validate()
# store inputs to class
self.cfg = cfg
# store the render mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class DirectRLEnvCfg:
Please refer to the :class:`omni.isaac.lab.scene.InteractiveSceneCfg` class for more details.
"""

events: object = None
events: object | None = None
"""Event settings. Defaults to None, in which case no events are applied through the event manager.
Please refer to the :class:`omni.isaac.lab.managers.EventManager` class for more details.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def __init__(self, cfg: ManagerBasedEnvCfg):
RuntimeError: If a simulation context already exists. The environment must always create one
since it configures the simulation context and controls the simulation.
"""
# check that the config is valid
cfg.validate()
# store inputs to class
self.cfg = cfg
# initialize internal variables
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ class ManagerBasedRLEnvCfg(ManagerBasedEnvCfg):
Please refer to the :class:`omni.isaac.lab.managers.TerminationManager` class for more details.
"""

curriculum: object = MISSING
"""Curriculum settings.
curriculum: object | None = None
"""Curriculum settings. Defaults to None, in which case no curriculum is applied.
Please refer to the :class:`omni.isaac.lab.managers.CurriculumManager` class for more details.
"""

commands: object = MISSING
"""Command settings.
commands: object | None = None
"""Command settings. Defaults to None, in which case no commands are generated.
Please refer to the :class:`omni.isaac.lab.managers.CommandManager` class for more details.
"""
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,11 @@ def reset(self, env_ids: Sequence[int] | None = None) -> None:
# check if specific environment ids are provided
if env_ids is None:
env_ids = slice(None)
else:
env_ids = env_ids[:, None]
super().reset(env_ids)
# reset history to current joint positions
self._prev_applied_actions[env_ids, :] = self._asset.data.joint_pos[env_ids[:, None], self._joint_ids]
self._prev_applied_actions[env_ids, :] = self._asset.data.joint_pos[env_ids, self._joint_ids]

def process_actions(self, actions: torch.Tensor):
# apply affine transformations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,46 @@ class UniformVelocityCommandCfg(CommandTermCfg):

asset_name: str = MISSING
"""Name of the asset in the environment for which the commands are generated."""
heading_command: bool = MISSING
"""Whether to use heading command or angular velocity command.

heading_command: bool = False
"""Whether to use heading command or angular velocity command. Defaults to False.
If True, the angular velocity command is computed from the heading error, where the
target heading is sampled uniformly from provided range. Otherwise, the angular velocity
command is sampled uniformly from provided range.
"""
heading_control_stiffness: float = MISSING
"""Scale factor to convert the heading error to angular velocity command."""
rel_standing_envs: float = MISSING
"""Probability threshold for environments where the robots that are standing still."""
rel_heading_envs: float = MISSING
"""Probability threshold for environments where the robots follow the heading-based angular velocity command
(the others follow the sampled angular velocity command)."""

heading_control_stiffness: float = 1.0
"""Scale factor to convert the heading error to angular velocity command. Defaults to 1.0."""

rel_standing_envs: float = 0.0
"""The sampled probability of environments that should be standing still. Defaults to 0.0."""

rel_heading_envs: float = 1.0
"""The sampled probability of environments where the robots follow the heading-based angular velocity command
(the others follow the sampled angular velocity command). Defaults to 1.0.
This parameter is only used if :attr:`heading_command` is True.
"""

@configclass
class Ranges:
"""Uniform distribution ranges for the velocity commands."""

lin_vel_x: tuple[float, float] = MISSING # min max [m/s]
lin_vel_y: tuple[float, float] = MISSING # min max [m/s]
ang_vel_z: tuple[float, float] = MISSING # min max [rad/s]
heading: tuple[float, float] = MISSING # min max [rad]
lin_vel_x: tuple[float, float] = MISSING
"""Range for the linear-x velocity command (in m/s)."""

lin_vel_y: tuple[float, float] = MISSING
"""Range for the linear-y velocity command (in m/s)."""

ang_vel_z: tuple[float, float] = MISSING
"""Range for the angular-z velocity command (in rad/s)."""

heading: tuple[float, float] | None = None
"""Range for the heading command (in rad). Defaults to None.
This parameter is only used if :attr:`~UniformVelocityCommandCfg.heading_command` is True.
"""

ranges: Ranges = MISSING
"""Distribution ranges for the velocity commands."""
Expand Down Expand Up @@ -91,15 +108,17 @@ class Ranges:
"""Normal distribution ranges for the velocity commands."""

mean_vel: tuple[float, float, float] = MISSING
"""Mean velocity for the normal distribution.
"""Mean velocity for the normal distribution (in m/s).
The tuple contains the mean linear-x, linear-y, and angular-z velocity.
"""

std_vel: tuple[float, float, float] = MISSING
"""Standard deviation for the normal distribution.
"""Standard deviation for the normal distribution (in m/s).
The tuple contains the standard deviation linear-x, linear-y, and angular-z velocity.
"""

zero_prob: tuple[float, float, float] = MISSING
"""Probability of zero velocity for the normal distribution.
Expand All @@ -118,6 +137,7 @@ class UniformPoseCommandCfg(CommandTermCfg):

asset_name: str = MISSING
"""Name of the asset in the environment for which the commands are generated."""

body_name: str = MISSING
"""Name of the body in the asset for which the commands are generated."""

Expand All @@ -131,12 +151,23 @@ class UniformPoseCommandCfg(CommandTermCfg):
class Ranges:
"""Uniform distribution ranges for the pose commands."""

pos_x: tuple[float, float] = MISSING # min max [m]
pos_y: tuple[float, float] = MISSING # min max [m]
pos_z: tuple[float, float] = MISSING # min max [m]
roll: tuple[float, float] = MISSING # min max [rad]
pitch: tuple[float, float] = MISSING # min max [rad]
yaw: tuple[float, float] = MISSING # min max [rad]
pos_x: tuple[float, float] = MISSING
"""Range for the x position (in m)."""

pos_y: tuple[float, float] = MISSING
"""Range for the y position (in m)."""

pos_z: tuple[float, float] = MISSING
"""Range for the z position (in m)."""

roll: tuple[float, float] = MISSING
"""Range for the roll angle (in rad)."""

pitch: tuple[float, float] = MISSING
"""Range for the pitch angle (in rad)."""

yaw: tuple[float, float] = MISSING
"""Range for the yaw angle (in rad)."""

ranges: Ranges = MISSING
"""Ranges for the commands."""
Expand Down Expand Up @@ -175,8 +206,10 @@ class Ranges:

pos_x: tuple[float, float] = MISSING
"""Range for the x position (in m)."""

pos_y: tuple[float, float] = MISSING
"""Range for the y position (in m)."""

heading: tuple[float, float] = MISSING
"""Heading range for the position commands (in rad).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from collections.abc import Sequence
from typing import TYPE_CHECKING

import omni.log

import omni.isaac.lab.utils.math as math_utils
from omni.isaac.lab.assets import Articulation
from omni.isaac.lab.managers import CommandTerm
Expand Down Expand Up @@ -49,10 +51,25 @@ def __init__(self, cfg: UniformVelocityCommandCfg, env: ManagerBasedEnv):
Args:
cfg: The configuration of the command generator.
env: The environment.
Raises:
ValueError: If the heading command is active but the heading range is not provided.
"""
# initialize the base class
super().__init__(cfg, env)

# check configuration
if self.cfg.heading_command and self.cfg.ranges.heading is None:
raise ValueError(
"The velocity command has heading commands active (heading_command=True) but the `ranges.heading`"
" parameter is set to None."
)
if self.cfg.ranges.heading and not self.cfg.heading_command:
omni.log.warn(
f"The velocity command has the 'ranges.heading' attribute set to '{self.cfg.ranges.heading}'"
" but the heading command is not active. Consider setting the flag for the heading command to True."
)

# obtain the robot asset
# -- robot
self.robot: Articulation = env.scene[cfg.asset_name]
Expand Down
Loading

0 comments on commit bd4cd3b

Please sign in to comment.