Unverified Commit 37684694 authored by Toni-SM's avatar Toni-SM Committed by GitHub

Fixes template generator (#2161)

# Description

Fix template generator:
- Fix `rsl_rl` agent configuration
- Don't list `skrl`'s multi-agent algorithms for single-agent tasks
- Don't list `rsl_rl` and `sb3` for multi-agent tasks
- Update docs to include usage steps for the generated internal task

## Type of change

<!-- As you go through the list, delete the ones that are not
applicable. -->

- Bug fix (non-breaking change which fixes an issue)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] 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

<!--
As you go through the checklist above, you can mark something as done by
putting an x character in it

For example,
- [x] I have done this task
- [ ] I have not done this task
-->
parent da5618bb
...@@ -68,9 +68,22 @@ Here are some general commands to get started with it: ...@@ -68,9 +68,22 @@ Here are some general commands to get started with it:
* Install the project (in editable mode). * 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. * List the tasks available in the project.
...@@ -79,14 +92,90 @@ Here are some general commands to get started with it: ...@@ -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-"`` 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. (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. * 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. 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>
...@@ -4,14 +4,13 @@ ...@@ -4,14 +4,13 @@
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
import enum import enum
import glob
import os import os
from collections.abc import Callable from collections.abc import Callable
import rich.console import rich.console
import rich.table import rich.table
from common import ROOT_DIR, TEMPLATE_DIR from common import ROOT_DIR
from generator import generate from generator import generate, get_algorithms_per_rl_library
from InquirerPy import inquirer, separator from InquirerPy import inquirer, separator
...@@ -144,16 +143,6 @@ class State(str, enum.Enum): ...@@ -144,16 +143,6 @@ class State(str, enum.Enum):
No = "[red]no[/red]" 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: def main() -> None:
"""Main function to run template generation from CLI.""" """Main function to run template generation from CLI."""
cli_handler = CLIHandler() cli_handler = CLIHandler()
...@@ -207,10 +196,12 @@ def main() -> None: ...@@ -207,10 +196,12 @@ def main() -> None:
default=supported_workflows, default=supported_workflows,
) )
workflow = [{"name": item.split(" | ")[0].lower(), "type": item.split(" | ")[1].lower()} for item in workflow] 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
rl_library_algorithms = [] 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 # - show supported RL libraries and features
rl_library_table = rich.table.Table(title="Supported RL libraries") rl_library_table = rich.table.Table(title="Supported RL libraries")
rl_library_table.add_column("RL/training feature", no_wrap=True) rl_library_table.add_column("RL/training feature", no_wrap=True)
...@@ -219,6 +210,7 @@ def main() -> None: ...@@ -219,6 +210,7 @@ def main() -> None:
rl_library_table.add_column("skrl") rl_library_table.add_column("skrl")
rl_library_table.add_column("sb3") rl_library_table.add_column("sb3")
rl_library_table.add_row("ML frameworks", "PyTorch", "PyTorch", "PyTorch, JAX", "PyTorch") 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( rl_library_table.add_row(
"Algorithms", "Algorithms",
", ".join(algorithms_per_rl_library.get("rl_games", [])), ", ".join(algorithms_per_rl_library.get("rl_games", [])),
...@@ -226,18 +218,21 @@ def main() -> None: ...@@ -226,18 +218,21 @@ def main() -> None:
", ".join(algorithms_per_rl_library.get("skrl", [])), ", ".join(algorithms_per_rl_library.get("skrl", [])),
", ".join(algorithms_per_rl_library.get("sb3", [])), ", ".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("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("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) rl_library_table.add_row("Fundamental/composite spaces", State.No, State.No, State.Yes, State.No)
cli_handler.output_table(rl_library_table) cli_handler.output_table(rl_library_table)
# - prompt for RL libraries # - 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( selected_rl_libraries = cli_handler.get_choices(
cli_handler.input_checkbox("RL library:", choices=[*supported_rl_libraries, "---", "all"]), cli_handler.input_checkbox("RL library:", choices=[*supported_rl_libraries, "---", "all"]),
default=supported_rl_libraries, default=supported_rl_libraries,
) )
# - prompt for algorithms per RL library # - 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: for rl_library in selected_rl_libraries:
algorithms = algorithms_per_rl_library.get(rl_library, []) algorithms = algorithms_per_rl_library.get(rl_library, [])
if len(algorithms) > 1: if len(algorithms) > 1:
......
...@@ -5,6 +5,11 @@ ...@@ -5,6 +5,11 @@
import os import os
# paths
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 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") TASKS_DIR = os.path.join(ROOT_DIR, "source", "isaaclab_tasks", "isaaclab_tasks")
TEMPLATE_DIR = os.path.join(ROOT_DIR, "tools", "template", "templates") TEMPLATE_DIR = os.path.join(ROOT_DIR, "tools", "template", "templates")
# RL algorithms
SINGLE_AGENT_ALGORITHMS = ["AMP", "PPO"]
MULTI_AGENT_ALGORITHMS = ["IPPO", "MAPPO"]
...@@ -11,7 +11,7 @@ import sys ...@@ -11,7 +11,7 @@ import sys
from datetime import datetime from datetime import datetime
import jinja2 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( jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(TEMPLATE_DIR), loader=jinja2.FileSystemLoader(TEMPLATE_DIR),
...@@ -260,6 +260,28 @@ def _external(specification: dict) -> None: ...@@ -260,6 +260,28 @@ def _external(specification: dict) -> None:
print("-" * 80) 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: def generate(specification: dict) -> None:
"""Generate the project/task. """Generate the project/task.
......
...@@ -9,7 +9,7 @@ from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, R ...@@ -9,7 +9,7 @@ from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, R
@configclass @configclass
class CartpolePPORunnerCfg(RslRlOnPolicyRunnerCfg): class PPORunnerCfg(RslRlOnPolicyRunnerCfg):
num_steps_per_env = 16 num_steps_per_env = 16
max_iterations = 150 max_iterations = 150
save_interval = 50 save_interval = 50
......
...@@ -27,15 +27,15 @@ gym.register( ...@@ -27,15 +27,15 @@ gym.register(
{% for algorithm in rl_library.algorithms %} {% for algorithm in rl_library.algorithms %}
{# configuration file #} {# configuration file #}
{% if rl_library.name == "rsl_rl" %} {% 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 %} {% else %}
{% set agent_config = rl_library.name ~ "_" ~ algorithm ~ "_cfg.yaml" %} {% set agent_config = ":" ~ rl_library.name ~ "_" ~ algorithm ~ "_cfg.yaml" %}
{% endif %} {% endif %}
{# library configuration #} {# library configuration #}
{% if algorithm == "ppo" %} {% 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 %} {% 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 %} {% endif %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment