Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 95 additions & 6 deletions docs/source/overview/developer-guide/template.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,22 @@ Here are some general commands to get started with it:

* Install the project (in editable mode).

.. code:: bash
.. tab-set::
:sync-group: os

python -m pip install -e source/<given-project-name>
.. tab-item:: :icon:`fa-brands fa-linux` Linux
:sync: linux

.. code-block:: bash

python -m pip install -e source/<given-project-name>

.. tab-item:: :icon:`fa-brands fa-windows` Windows
:sync: windows

.. code-block:: batch

python -m pip install -e source\<given-project-name>

* List the tasks available in the project.

Expand All @@ -79,14 +92,90 @@ Here are some general commands to get started with it:
If the task names change, it may be necessary to update the search pattern ``"Template-"``
(in the ``scripts/list_envs.py`` file) so that they can be listed.

.. code:: bash
.. tab-set::
:sync-group: os

.. tab-item:: :icon:`fa-brands fa-linux` Linux
:sync: linux

.. code-block:: bash

python scripts/list_envs.py

.. tab-item:: :icon:`fa-brands fa-windows` Windows
:sync: windows

.. code-block:: batch

python scripts/list_envs.py
python scripts\list_envs.py

* Run a task.

.. code:: bash
.. tab-set::
:sync-group: os

python scripts/<specific-rl-library>/train.py --task=<Task-Name>
.. tab-item:: :icon:`fa-brands fa-linux` Linux
:sync: linux

.. code-block:: bash

python scripts/<specific-rl-library>/train.py --task=<Task-Name>

.. tab-item:: :icon:`fa-brands fa-windows` Windows
:sync: windows

.. code-block:: batch

python scripts\<specific-rl-library>\train.py --task=<Task-Name>

For more details, please follow the instructions in the generated project's ``README.md`` file.

Internal task usage (once generated)
---------------------------------------

Once the internal task is generated, it will be available along with the rest of the Isaac Lab tasks.

Here are some general commands to get started with it:

.. note::

If Isaac Lab is not installed in a conda environment or in a (virtual) Python environment, use ``./isaaclab.sh -p``
(or ``isaaclab.bat -p`` on Windows) instead of ``python`` to run the commands below.

* List the tasks available in Isaac Lab.

.. tab-set::
:sync-group: os

.. tab-item:: :icon:`fa-brands fa-linux` Linux
:sync: linux

.. code-block:: bash

python scripts/environments/list_envs.py

.. tab-item:: :icon:`fa-brands fa-windows` Windows
:sync: windows

.. code-block:: batch

python scripts\environments\list_envs.py

* Run a task.

.. tab-set::
:sync-group: os

.. tab-item:: :icon:`fa-brands fa-linux` Linux
:sync: linux

.. code-block:: bash

python scripts/reinforcement_learning/<specific-rl-library>/train.py --task=<Task-Name>

.. tab-item:: :icon:`fa-brands fa-windows` Windows
:sync: windows

.. code-block:: batch

python scripts\reinforcement_learning\<specific-rl-library>\train.py --task=<Task-Name>
27 changes: 11 additions & 16 deletions tools/template/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
# SPDX-License-Identifier: BSD-3-Clause

import enum
import glob
import os
from collections.abc import Callable

import rich.console
import rich.table
from common import ROOT_DIR, TEMPLATE_DIR
from generator import generate
from common import ROOT_DIR
from generator import generate, get_algorithms_per_rl_library
from InquirerPy import inquirer, separator


Expand Down Expand Up @@ -144,16 +143,6 @@ class State(str, enum.Enum):
No = "[red]no[/red]"


def _get_algorithms_per_rl_library():
data = {"rl_games": [], "rsl_rl": [], "skrl": [], "sb3": []}
for file in glob.glob(os.path.join(TEMPLATE_DIR, "agents", "*_cfg")):
for rl_library in data.keys():
basename = os.path.basename(file).replace("_cfg", "")
if basename.startswith(f"{rl_library}_"):
data[rl_library].append(basename.replace(f"{rl_library}_", "").upper())
return data


def main() -> None:
"""Main function to run template generation from CLI."""
cli_handler = CLIHandler()
Expand Down Expand Up @@ -207,10 +196,12 @@ def main() -> None:
default=supported_workflows,
)
workflow = [{"name": item.split(" | ")[0].lower(), "type": item.split(" | ")[1].lower()} for item in workflow]
single_agent_workflow = [item for item in workflow if item["type"] == "single-agent"]
multi_agent_workflow = [item for item in workflow if item["type"] == "multi-agent"]

# RL library
rl_library_algorithms = []
algorithms_per_rl_library = _get_algorithms_per_rl_library()
algorithms_per_rl_library = get_algorithms_per_rl_library()
# - show supported RL libraries and features
rl_library_table = rich.table.Table(title="Supported RL libraries")
rl_library_table.add_column("RL/training feature", no_wrap=True)
Expand All @@ -219,25 +210,29 @@ def main() -> None:
rl_library_table.add_column("skrl")
rl_library_table.add_column("sb3")
rl_library_table.add_row("ML frameworks", "PyTorch", "PyTorch", "PyTorch, JAX", "PyTorch")
rl_library_table.add_row("Relative performance", "~1X", "~1X", "~1X", "~0.03X")
rl_library_table.add_row(
"Algorithms",
", ".join(algorithms_per_rl_library.get("rl_games", [])),
", ".join(algorithms_per_rl_library.get("rsl_rl", [])),
", ".join(algorithms_per_rl_library.get("skrl", [])),
", ".join(algorithms_per_rl_library.get("sb3", [])),
)
rl_library_table.add_row("Relative performance", "~1X", "~1X", "~1X", "~0.03X")
rl_library_table.add_row("Multi-agent support", State.Yes, State.No, State.Yes, State.No)
rl_library_table.add_row("Distributed training", State.Yes, State.No, State.Yes, State.No)
rl_library_table.add_row("Vectorized training", State.Yes, State.Yes, State.Yes, State.No)
rl_library_table.add_row("Fundamental/composite spaces", State.No, State.No, State.Yes, State.No)
cli_handler.output_table(rl_library_table)
# - prompt for RL libraries
supported_rl_libraries = ["rl_games", "rsl_rl", "skrl", "sb3"]
supported_rl_libraries = (
["rl_games", "rsl_rl", "skrl", "sb3"] if len(single_agent_workflow) else ["rl_games", "skrl"]
)
selected_rl_libraries = cli_handler.get_choices(
cli_handler.input_checkbox("RL library:", choices=[*supported_rl_libraries, "---", "all"]),
default=supported_rl_libraries,
)
# - prompt for algorithms per RL library
algorithms_per_rl_library = get_algorithms_per_rl_library(len(single_agent_workflow), len(multi_agent_workflow))
for rl_library in selected_rl_libraries:
algorithms = algorithms_per_rl_library.get(rl_library, [])
if len(algorithms) > 1:
Expand Down
5 changes: 5 additions & 0 deletions tools/template/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

import os

# paths
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
TASKS_DIR = os.path.join(ROOT_DIR, "source", "isaaclab_tasks", "isaaclab_tasks")
TEMPLATE_DIR = os.path.join(ROOT_DIR, "tools", "template", "templates")

# RL algorithms
SINGLE_AGENT_ALGORITHMS = ["AMP", "PPO"]
MULTI_AGENT_ALGORITHMS = ["IPPO", "MAPPO"]
24 changes: 23 additions & 1 deletion tools/template/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from datetime import datetime

import jinja2
from common import ROOT_DIR, TASKS_DIR, TEMPLATE_DIR
from common import MULTI_AGENT_ALGORITHMS, ROOT_DIR, SINGLE_AGENT_ALGORITHMS, TASKS_DIR, TEMPLATE_DIR

jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(TEMPLATE_DIR),
Expand Down Expand Up @@ -260,6 +260,28 @@ def _external(specification: dict) -> None:
print("-" * 80)


def get_algorithms_per_rl_library(single_agent: bool = True, multi_agent: bool = True):
assert single_agent or multi_agent, "At least one of 'single_agent' or 'multi_agent' must be True"
data = {"rl_games": [], "rsl_rl": [], "skrl": [], "sb3": []}
# get algorithms
for file in glob.glob(os.path.join(TEMPLATE_DIR, "agents", "*_cfg")):
for rl_library in data.keys():
basename = os.path.basename(file).replace("_cfg", "")
if basename.startswith(f"{rl_library}_"):
algorithm = basename.replace(f"{rl_library}_", "").upper()
assert (
algorithm in SINGLE_AGENT_ALGORITHMS or algorithm in MULTI_AGENT_ALGORITHMS
), f"{algorithm} algorithm is not listed in the supported algorithms"
if single_agent and algorithm in SINGLE_AGENT_ALGORITHMS:
data[rl_library].append(algorithm)
if multi_agent and algorithm in MULTI_AGENT_ALGORITHMS:
data[rl_library].append(algorithm)
# remove duplicates and sort
for rl_library in data.keys():
data[rl_library] = sorted(list(set(data[rl_library])))
return data


def generate(specification: dict) -> None:
"""Generate the project/task.

Expand Down
2 changes: 1 addition & 1 deletion tools/template/templates/agents/rsl_rl_ppo_cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, R


@configclass
class CartpolePPORunnerCfg(RslRlOnPolicyRunnerCfg):
class PPORunnerCfg(RslRlOnPolicyRunnerCfg):
num_steps_per_env = 16
max_iterations = 150
save_interval = 50
Expand Down
8 changes: 4 additions & 4 deletions tools/template/templates/tasks/__init__task
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ gym.register(
{% for algorithm in rl_library.algorithms %}
{# configuration file #}
{% if rl_library.name == "rsl_rl" %}
{% set agent_config = rl_library.name ~ "_" ~ algorithm ~ "_cfg:" ~ algorithm|upper ~ "RunnerCfg" %}
{% set agent_config = "." ~ rl_library.name ~ "_" ~ algorithm ~ "_cfg:" ~ algorithm|upper ~ "RunnerCfg" %}
{% else %}
{% set agent_config = rl_library.name ~ "_" ~ algorithm ~ "_cfg.yaml" %}
{% set agent_config = ":" ~ rl_library.name ~ "_" ~ algorithm ~ "_cfg.yaml" %}
{% endif %}
{# library configuration #}
{% if algorithm == "ppo" %}
"{{ rl_library.name }}_cfg_entry_point": f"{agents.__name__}:{{ agent_config }}",
"{{ rl_library.name }}_cfg_entry_point": f"{agents.__name__}{{ agent_config }}",
{% else %}
"{{ rl_library.name }}_{{ algorithm }}_cfg_entry_point": f"{agents.__name__}:{{ agent_config }}",
"{{ rl_library.name }}_{{ algorithm }}_cfg_entry_point": f"{agents.__name__}{{ agent_config }}",
{% endif %}
{% endfor %}
{% endfor %}
Expand Down