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:
* 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.
......@@ -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>
......@@ -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
......@@ -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()
......@@ -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)
......@@ -219,6 +210,7 @@ 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", [])),
......@@ -226,18 +218,21 @@ def main() -> None:
", ".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:
......
......@@ -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"]
......@@ -11,7 +11,7 @@ import sys
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),
......@@ -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.
......
......@@ -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
......
......@@ -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 %}
......
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