pro6000_xh配置

This commit is contained in:
2026-03-04 16:45:34 +08:00
parent 9325184f4d
commit c7c88e5d8d
85 changed files with 3257 additions and 1316 deletions

View File

@@ -1,12 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"ms-python.python",
"ms-python.vscode-pylance",
"ban.spellright",
"ms-iot.vscode-ros",
"ms-python.black-formatter",
"ms-python.flake8",
]
}

23
.vscode/tasks.json vendored
View File

@@ -1,23 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "setup_python_env",
"type": "shell",
"linux": {
"command": "${input:isaac_path}/python.sh ${workspaceFolder}/.vscode/tools/setup_vscode.py --isaac_path ${input:isaac_path}"
},
"windows": {
"command": "${input:isaac_path}/python.bat ${workspaceFolder}/.vscode/tools/setup_vscode.py --isaac_path ${input:isaac_path}"
}
}
],
"inputs": [
{
"id": "isaac_path",
"description": "Absolute path to the current Isaac Sim installation. If you installed IsaacSim from pip, the import of it failed. Please make sure you run the task with the correct python environment. As fallback, you can directly execute the python script by running: ``python.sh <path-to-your-project>/.vscode/tools/setup_vscode.py``",
"default": "C:/isaacsim",
"type": "promptString"
},
]
}

View File

@@ -4,822 +4,54 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
// For standalone script execution
{
"name": "Python: Current File",
"type": "debugpy",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rl_games/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rl_games/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rsl_rl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rsl_rl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/sb3/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/sb3/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rl_games/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rl_games/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rsl_rl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rsl_rl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-Marl-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/sb3/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-Marl-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/sb3/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rl_games/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rl_games/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rsl_rl/train.py",
"console": "integratedTerminal",
"console": "integratedTerminal"
},
{
"name": "Python: Play Template-Mindbot-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rsl_rl/play.py",
"console": "integratedTerminal",
"name": "Python: Attach (windows-x86_64/linux-x86_64)",
"type": "python",
"request": "attach",
"port": 3000,
"host": "localhost"
},
{
"name": "Python: Train Template-Mindbot-v0 with skrl (AMP)",
"type": "debugpy",
"name": "Python: Train Environment",
"type": "python",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"args" : ["--task", "Isaac-Reach-Franka-v0", "--headless"],
"program": "${workspaceFolder}/scripts/reinforcement_learning/rsl_rl/train.py",
"console": "integratedTerminal"
},
{
"name": "Python: Play Template-Mindbot-v0 with skrl (AMP)",
"type": "debugpy",
"name": "Python: Play Environment",
"type": "python",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"args" : ["--task", "Isaac-Reach-Franka-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/reinforcement_learning/rsl_rl/play.py",
"console": "integratedTerminal"
},
{
"name": "Python: Train Template-Mindbot-v0 with skrl (IPPO)",
"type": "debugpy",
"name": "Python: SinglePytest",
"type": "python",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"module": "pytest",
"args": [
"${file}"
],
"console": "integratedTerminal"
},
{
"name": "Python: Train Template-Mindbot-v0 with skrl (MAPPO)",
"type": "debugpy",
"name": "Python: ALL Pytest",
"type": "python",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"module": "pytest",
"args": ["source/isaaclab/test"],
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
},
{
"name": "Python: Train Template-Mindbot-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/sb3/train.py",
"console": "integratedTerminal",
},
{
"name": "Python: Play Template-Mindbot-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/sb3/play.py",
"console": "integratedTerminal",
},
// For script execution inside a Docker
{
"name": "Docker: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
}
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rl_games/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rl_games/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rsl_rl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rsl_rl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/sb3/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/sb3/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rl_games/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rl_games/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rsl_rl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rsl_rl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-Marl-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/sb3/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-Marl-Direct-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-Marl-Direct-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/sb3/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rl_games/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with rl_games (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rl_games/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/rsl_rl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with rsl_rl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/rsl_rl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with skrl (AMP)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "AMP"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with skrl (IPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "IPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with skrl (MAPPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "MAPPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with skrl (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32", "--algorithm", "PPO"],
"program": "${workspaceFolder}/scripts/skrl/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Train Template-Mindbot-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "4096", "--headless"],
"program": "${workspaceFolder}/scripts/sb3/train.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
{
"name": "Docker: Play Template-Mindbot-v0 with sb3 (PPO)",
"type": "debugpy",
"request": "launch",
"args" : ["--task", "Template-Mindbot-v0", "--num_envs", "32"],
"program": "${workspaceFolder}/scripts/sb3/play.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${env:PYTHONPATH}:${workspaceFolder}"
},
},
"justMyCode": false
}
]
}
}

View File

@@ -1,4 +1,9 @@
{
"files.exclude": {
"**/.mypy_cache": true,
"**/__pycache__": true,
"**/*.egg-info": true
},
"files.associations": {
"*.tpp": "cpp",
"*.kit": "toml",
@@ -40,7 +45,6 @@
"teleoperation",
"xform",
"numpy",
"tensordict",
"flatcache",
"physx",
"dpad",
@@ -51,26 +55,21 @@
"arange",
"discretization",
"trimesh",
"uninstanceable"
"uninstanceable",
"coeff",
"prestartup"
],
// This enables python language server. Seems to work slightly better than jedi:
"python.languageServer": "Pylance",
// We use "black" as a formatter:
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "120"],
// Use flake8 for linting
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-line-length=120"
],
// Use ruff as a formatter and linter
"ruff.configuration": "${workspaceFolder}/pyproject.toml",
// Use docstring generator
"autoDocstring.docstringFormat": "google",
"autoDocstring.guessTypes": true,
// Python environment path
// note: the default interpreter is overridden when user selects a workspace interpreter
// in the status bar. For example, the virtual environment python interpreter
"python.defaultInterpreterPath": "",
"python.defaultInterpreterPath": "${workspaceFolder}/_isaac_sim/python.sh",
// ROS distribution
"ros.distro": "noetic",
// Language specific settings
@@ -81,6 +80,6 @@
"editor.tabSize": 2
},
// Python extra paths
// Note: this is filled up when vscode is set up for the first time
// Note: this is filled up when "./isaaclab.sh -i" is run
"python.analysis.extraPaths": []
}

View File

@@ -12,34 +12,21 @@ This is necessary because Isaac Sim 2022.2.1 onwards does not add the necessary
when the "setup_python_env.sh" is run as part of the vs-code launch configuration.
"""
import argparse
import os
import pathlib
import platform
import re
import sys
import os
import pathlib
PROJECT_DIR = pathlib.Path(__file__).parents[2]
"""Path to the the project directory."""
ISAACLAB_DIR = pathlib.Path(__file__).parents[2]
"""Path to the Isaac Lab directory."""
try:
import isaacsim # noqa: F401
isaacsim_dir = os.environ.get("ISAAC_PATH", "")
except ModuleNotFoundError or ImportError:
# Create a parser to get the isaac-sim path
parser = argparse.ArgumentParser(description="Setup the VSCode settings for the project.")
parser.add_argument("--isaac_path", type=str, help="The absolute path to the Isaac Sim installation.")
args = parser.parse_args()
# parse the isaac-sim directory
isaacsim_dir = args.isaac_path
# check if the isaac-sim directory is provided
if not os.path.exists(isaacsim_dir):
raise FileNotFoundError(
f"Could not find the isaac-sim directory: {isaacsim_dir}. Please provide the correct path to the Isaac Sim"
" installation."
)
isaacsim_dir = os.path.join(ISAACLAB_DIR, "_isaac_sim")
except EOFError:
print("Unable to trigger EULA acceptance. This is likely due to the script being run in a non-interactive shell.")
print("Please run the script in an interactive shell to accept the EULA.")
@@ -49,11 +36,11 @@ except EOFError:
# check if the isaac-sim directory exists
if not os.path.exists(isaacsim_dir):
raise FileNotFoundError(
f"Could not find the isaac-sim directory: {isaacsim_dir}. There are two possible reasons for this:\n\t1. The"
" Isaac Sim directory does not exist as provided CLI path.\n\t2. The script couldn't import the 'isaacsim'"
" package. This could be due to the 'isaacsim' package not being installed in the Python"
" environment.\n\nPlease make sure that the Isaac Sim directory exists or that the 'isaacsim' package is"
" installed."
f"Could not find the isaac-sim directory: {isaacsim_dir}. There are two possible reasons for this:"
f"\n\t1. The Isaac Sim directory does not exist as a symlink at: {os.path.join(ISAACLAB_DIR, '_isaac_sim')}"
"\n\t2. The script could not import the 'isaacsim' package. This could be due to the 'isaacsim' package not "
"being installed in the Python environment.\n"
"\nPlease make sure that the Isaac Sim directory exists or that the 'isaacsim' package is installed."
)
ISAACSIM_DIR = isaacsim_dir
@@ -98,7 +85,7 @@ def overwrite_python_analysis_extra_paths(isaaclab_settings: str) -> str:
path_names = [path_name for path_name in path_names if len(path_name) > 0]
# change the path names to be relative to the Isaac Lab directory
rel_path = os.path.relpath(ISAACSIM_DIR, PROJECT_DIR)
rel_path = os.path.relpath(ISAACSIM_DIR, ISAACLAB_DIR)
path_names = ['"${workspaceFolder}/' + rel_path + "/" + path_name + '"' for path_name in path_names]
else:
path_names = []
@@ -111,7 +98,7 @@ def overwrite_python_analysis_extra_paths(isaaclab_settings: str) -> str:
)
# add the path names that are in the Isaac Lab extensions directory
isaaclab_extensions = os.listdir(os.path.join(PROJECT_DIR, "source"))
isaaclab_extensions = os.listdir(os.path.join(ISAACLAB_DIR, "source"))
path_names.extend(['"${workspaceFolder}/source/' + ext + '"' for ext in isaaclab_extensions])
# combine them into a single string
@@ -144,17 +131,15 @@ def overwrite_default_python_interpreter(isaaclab_settings: str) -> str:
The settings string with overwritten default python interpreter.
"""
# read executable name
python_exe = os.path.normpath(sys.executable)
# replace with Isaac Sim's python.sh or python.bat scripts to make sure python with correct
# source paths is set as default
if f"kit{os.sep}python{os.sep}bin{os.sep}python" in python_exe:
# Check if the OS is Windows or Linux to use appropriate shell file
if platform.system() == "Windows":
python_exe = python_exe.replace(f"kit{os.sep}python{os.sep}bin{os.sep}python3", "python.bat")
else:
python_exe = python_exe.replace(f"kit{os.sep}python{os.sep}bin{os.sep}python3", "python.sh")
python_exe = sys.executable.replace("\\", "/")
# We make an exception for replacing the default interpreter if the
# path (/kit/python/bin/python3) indicates that we are using a local/container
# installation of IsaacSim. We will preserve the calling script as the default, python.sh.
# We want to use python.sh because it modifies LD_LIBRARY_PATH and PYTHONPATH
# (among other envars) that we need for all of our dependencies to be accessible.
if "kit/python/bin/python3" in python_exe:
return isaaclab_settings
# replace the default python interpreter in the Isaac Lab settings file with the path to the
# python interpreter in the Isaac Lab directory
isaaclab_settings = re.sub(
@@ -169,7 +154,7 @@ def overwrite_default_python_interpreter(isaaclab_settings: str) -> str:
def main():
# Isaac Lab template settings
isaaclab_vscode_template_filename = os.path.join(PROJECT_DIR, ".vscode", "tools", "settings.template.json")
isaaclab_vscode_template_filename = os.path.join(ISAACLAB_DIR, ".vscode", "tools", "settings.template.json")
# make sure the Isaac Lab template settings file exists
if not os.path.exists(isaaclab_vscode_template_filename):
raise FileNotFoundError(
@@ -195,13 +180,13 @@ def main():
isaaclab_settings = header_message + isaaclab_settings
# write the Isaac Lab settings file
isaaclab_vscode_filename = os.path.join(PROJECT_DIR, ".vscode", "settings.json")
isaaclab_vscode_filename = os.path.join(ISAACLAB_DIR, ".vscode", "settings.json")
with open(isaaclab_vscode_filename, "w") as f:
f.write(isaaclab_settings)
# copy the launch.json file if it doesn't exist
isaaclab_vscode_launch_filename = os.path.join(PROJECT_DIR, ".vscode", "launch.json")
isaaclab_vscode_template_launch_filename = os.path.join(PROJECT_DIR, ".vscode", "tools", "launch.template.json")
isaaclab_vscode_launch_filename = os.path.join(ISAACLAB_DIR, ".vscode", "launch.json")
isaaclab_vscode_template_launch_filename = os.path.join(ISAACLAB_DIR, ".vscode", "tools", "launch.template.json")
if not os.path.exists(isaaclab_vscode_launch_filename):
# read template launch settings
with open(isaaclab_vscode_template_launch_filename) as f:

View File

@@ -0,0 +1,101 @@
# 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
"""Script to an environment with random action agent."""
"""Launch Isaac Sim Simulator first."""
import argparse
import os
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Random agent for Isaac Lab environments.")
parser.add_argument("--task", type=str, default=None, help="Name of the task.")
parser.add_argument("--output_dir", type=str, default=None, help="Path to the output directory.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
args_cli.headless = True
# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app
"""Rest everything follows."""
import gymnasium as gym
import torch
import isaaclab_tasks # noqa: F401
from isaaclab_tasks.utils import parse_env_cfg
# PLACEHOLDER: Extension template (do not remove this comment)
def main():
"""Random actions agent with Isaac Lab environment."""
# create environment configuration
env_cfg = parse_env_cfg(args_cli.task, device=args_cli.device, num_envs=1, use_fabric=True)
# create environment
env = gym.make(args_cli.task, cfg=env_cfg)
# print info (this is vectorized environment)
print(f"[INFO]: Gym observation space: {env.observation_space}")
print(f"[INFO]: Gym action space: {env.action_space}")
# reset environment
env.reset()
outs = env.unwrapped.get_IO_descriptors
out_observations = outs["observations"]
out_actions = outs["actions"]
out_articulations = outs["articulations"]
out_scene = outs["scene"]
# Make a yaml file with the output
import yaml
name = args_cli.task.lower().replace("-", "_")
name = name.replace(" ", "_")
if not os.path.exists(args_cli.output_dir):
os.makedirs(args_cli.output_dir)
with open(os.path.join(args_cli.output_dir, f"{name}_IO_descriptors.yaml"), "w") as f:
print(f"[INFO]: Exporting IO descriptors to {os.path.join(args_cli.output_dir, f'{name}_IO_descriptors.yaml')}")
yaml.safe_dump(outs, f)
for k in out_actions:
print(f"--- Action term: {k['name']} ---")
k.pop("name")
for k1, v1 in k.items():
print(f"{k1}: {v1}")
for obs_group_name, obs_group in out_observations.items():
print(f"--- Obs group: {obs_group_name} ---")
for k in obs_group:
print(f"--- Obs term: {k['name']} ---")
k.pop("name")
for k1, v1 in k.items():
print(f"{k1}: {v1}")
for articulation_name, articulation_data in out_articulations.items():
print(f"--- Articulation: {articulation_name} ---")
for k1, v1 in articulation_data.items():
print(f"{k1}: {v1}")
for k1, v1 in out_scene.items():
print(f"{k1}: {v1}")
env.step(torch.zeros(env.action_space.shape, device=env.unwrapped.device))
env.close()
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()

View File

@@ -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
"""
Script to print all the available environments in Isaac Lab.
The script iterates over all registered environments and stores the details in a table.
It prints the name of the environment, the entry point and the config file.
All the environments are registered in the `isaaclab_tasks` extension. They start
with `Isaac` in their name.
"""
"""Launch Isaac Sim Simulator first."""
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="List Isaac Lab environments.")
parser.add_argument("--keyword", type=str, default=None, help="Keyword to filter environments.")
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(headless=True)
simulation_app = app_launcher.app
"""Rest everything follows."""
import gymnasium as gym
from prettytable import PrettyTable
import isaaclab_tasks # noqa: F401
def main():
"""Print all environments registered in `isaaclab_tasks` extension."""
# print all the available environments
table = PrettyTable(["S. No.", "Task Name", "Entry Point", "Config"])
table.title = "Available Environments in Isaac Lab"
# set alignment of table columns
table.align["Task Name"] = "l"
table.align["Entry Point"] = "l"
table.align["Config"] = "l"
# count of environments
index = 0
# acquire all Isaac environments names
for task_spec in gym.registry.values():
if "Isaac" in task_spec.id and (args_cli.keyword is None or args_cli.keyword in task_spec.id):
# add details to table
table.add_row([index + 1, task_spec.id, task_spec.entry_point, task_spec.kwargs["env_cfg_entry_point"]])
# increment count
index += 1
print(table)
if __name__ == "__main__":
try:
# run the main function
main()
except Exception as e:
raise e
finally:
# close the app
simulation_app.close()

View File

@@ -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
"""Script to an environment with random action agent."""
"""Launch Isaac Sim Simulator first."""
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Random agent for Isaac Lab environments.")
parser.add_argument(
"--disable_fabric", action="store_true", default=False, help="Disable fabric and use USD I/O operations."
)
parser.add_argument("--num_envs", type=int, default=None, help="Number of environments to simulate.")
parser.add_argument("--task", type=str, default=None, help="Name of the task.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app
"""Rest everything follows."""
import gymnasium as gym
import torch
import isaaclab_tasks # noqa: F401
from isaaclab_tasks.utils import parse_env_cfg
# PLACEHOLDER: Extension template (do not remove this comment)
def main():
"""Random actions agent with Isaac Lab environment."""
# create environment configuration
env_cfg = parse_env_cfg(
args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
)
# create environment
env = gym.make(args_cli.task, cfg=env_cfg)
# print info (this is vectorized environment)
print(f"[INFO]: Gym observation space: {env.observation_space}")
print(f"[INFO]: Gym action space: {env.action_space}")
# reset environment
env.reset()
# simulate environment
while simulation_app.is_running():
# run everything in inference mode
with torch.inference_mode():
# sample actions from -1 to 1
actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1
# apply actions
env.step(actions)
# close the simulator
env.close()
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()

View File

@@ -0,0 +1,319 @@
# 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
"""
Script to run an environment with a pick and lift state machine.
The state machine is implemented in the kernel function `infer_state_machine`.
It uses the `warp` library to run the state machine in parallel on the GPU.
.. code-block:: bash
./isaaclab.sh -p scripts/environments/state_machine/lift_cube_sm.py --num_envs 32
"""
"""Launch Omniverse Toolkit first."""
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Pick and lift state machine for lift environments.")
parser.add_argument(
"--disable_fabric", action="store_true", default=False, help="Disable fabric and use USD I/O operations."
)
parser.add_argument("--num_envs", type=int, default=None, help="Number of environments to simulate.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(headless=args_cli.headless)
simulation_app = app_launcher.app
"""Rest everything else."""
from collections.abc import Sequence
import gymnasium as gym
import torch
import warp as wp
from isaaclab.assets.rigid_object.rigid_object_data import RigidObjectData
import isaaclab_tasks # noqa: F401
from isaaclab_tasks.manager_based.manipulation.lift.lift_env_cfg import LiftEnvCfg
from isaaclab_tasks.utils.parse_cfg import parse_env_cfg
# initialize warp
wp.init()
class GripperState:
"""States for the gripper."""
OPEN = wp.constant(1.0)
CLOSE = wp.constant(-1.0)
class PickSmState:
"""States for the pick state machine."""
REST = wp.constant(0)
APPROACH_ABOVE_OBJECT = wp.constant(1)
APPROACH_OBJECT = wp.constant(2)
GRASP_OBJECT = wp.constant(3)
LIFT_OBJECT = wp.constant(4)
class PickSmWaitTime:
"""Additional wait times (in s) for states for before switching."""
REST = wp.constant(0.2)
APPROACH_ABOVE_OBJECT = wp.constant(0.5)
APPROACH_OBJECT = wp.constant(0.6)
GRASP_OBJECT = wp.constant(0.3)
LIFT_OBJECT = wp.constant(1.0)
@wp.func
def distance_below_threshold(current_pos: wp.vec3, desired_pos: wp.vec3, threshold: float) -> bool:
return wp.length(current_pos - desired_pos) < threshold
@wp.kernel
def infer_state_machine(
dt: wp.array(dtype=float),
sm_state: wp.array(dtype=int),
sm_wait_time: wp.array(dtype=float),
ee_pose: wp.array(dtype=wp.transform),
object_pose: wp.array(dtype=wp.transform),
des_object_pose: wp.array(dtype=wp.transform),
des_ee_pose: wp.array(dtype=wp.transform),
gripper_state: wp.array(dtype=float),
offset: wp.array(dtype=wp.transform),
position_threshold: float,
):
# retrieve thread id
tid = wp.tid()
# retrieve state machine state
state = sm_state[tid]
# decide next state
if state == PickSmState.REST:
des_ee_pose[tid] = ee_pose[tid]
gripper_state[tid] = GripperState.OPEN
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.REST:
# move to next state and reset wait time
sm_state[tid] = PickSmState.APPROACH_ABOVE_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.APPROACH_ABOVE_OBJECT:
des_ee_pose[tid] = wp.transform_multiply(offset[tid], object_pose[tid])
gripper_state[tid] = GripperState.OPEN
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.APPROACH_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.APPROACH_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.APPROACH_OBJECT:
des_ee_pose[tid] = object_pose[tid]
gripper_state[tid] = GripperState.OPEN
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
if sm_wait_time[tid] >= PickSmWaitTime.APPROACH_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.GRASP_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.GRASP_OBJECT:
des_ee_pose[tid] = object_pose[tid]
gripper_state[tid] = GripperState.CLOSE
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.GRASP_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.LIFT_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.LIFT_OBJECT:
des_ee_pose[tid] = des_object_pose[tid]
gripper_state[tid] = GripperState.CLOSE
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.LIFT_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.LIFT_OBJECT
sm_wait_time[tid] = 0.0
# increment wait time
sm_wait_time[tid] = sm_wait_time[tid] + dt[tid]
class PickAndLiftSm:
"""A simple state machine in a robot's task space to pick and lift an object.
The state machine is implemented as a warp kernel. It takes in the current state of
the robot's end-effector and the object, and outputs the desired state of the robot's
end-effector and the gripper. The state machine is implemented as a finite state
machine with the following states:
1. REST: The robot is at rest.
2. APPROACH_ABOVE_OBJECT: The robot moves above the object.
3. APPROACH_OBJECT: The robot moves to the object.
4. GRASP_OBJECT: The robot grasps the object.
5. LIFT_OBJECT: The robot lifts the object to the desired pose. This is the final state.
"""
def __init__(self, dt: float, num_envs: int, device: torch.device | str = "cpu", position_threshold=0.01):
"""Initialize the state machine.
Args:
dt: The environment time step.
num_envs: The number of environments to simulate.
device: The device to run the state machine on.
"""
# save parameters
self.dt = float(dt)
self.num_envs = num_envs
self.device = device
self.position_threshold = position_threshold
# initialize state machine
self.sm_dt = torch.full((self.num_envs,), self.dt, device=self.device)
self.sm_state = torch.full((self.num_envs,), 0, dtype=torch.int32, device=self.device)
self.sm_wait_time = torch.zeros((self.num_envs,), device=self.device)
# desired state
self.des_ee_pose = torch.zeros((self.num_envs, 7), device=self.device)
self.des_gripper_state = torch.full((self.num_envs,), 0.0, device=self.device)
# approach above object offset
self.offset = torch.zeros((self.num_envs, 7), device=self.device)
self.offset[:, 2] = 0.1
self.offset[:, -1] = 1.0 # warp expects quaternion as (x, y, z, w)
# convert to warp
self.sm_dt_wp = wp.from_torch(self.sm_dt, wp.float32)
self.sm_state_wp = wp.from_torch(self.sm_state, wp.int32)
self.sm_wait_time_wp = wp.from_torch(self.sm_wait_time, wp.float32)
self.des_ee_pose_wp = wp.from_torch(self.des_ee_pose, wp.transform)
self.des_gripper_state_wp = wp.from_torch(self.des_gripper_state, wp.float32)
self.offset_wp = wp.from_torch(self.offset, wp.transform)
def reset_idx(self, env_ids: Sequence[int] = None):
"""Reset the state machine."""
if env_ids is None:
env_ids = slice(None)
self.sm_state[env_ids] = 0
self.sm_wait_time[env_ids] = 0.0
def compute(self, ee_pose: torch.Tensor, object_pose: torch.Tensor, des_object_pose: torch.Tensor) -> torch.Tensor:
"""Compute the desired state of the robot's end-effector and the gripper."""
# convert all transformations from (w, x, y, z) to (x, y, z, w)
ee_pose = ee_pose[:, [0, 1, 2, 4, 5, 6, 3]]
object_pose = object_pose[:, [0, 1, 2, 4, 5, 6, 3]]
des_object_pose = des_object_pose[:, [0, 1, 2, 4, 5, 6, 3]]
# convert to warp
ee_pose_wp = wp.from_torch(ee_pose.contiguous(), wp.transform)
object_pose_wp = wp.from_torch(object_pose.contiguous(), wp.transform)
des_object_pose_wp = wp.from_torch(des_object_pose.contiguous(), wp.transform)
# run state machine
wp.launch(
kernel=infer_state_machine,
dim=self.num_envs,
inputs=[
self.sm_dt_wp,
self.sm_state_wp,
self.sm_wait_time_wp,
ee_pose_wp,
object_pose_wp,
des_object_pose_wp,
self.des_ee_pose_wp,
self.des_gripper_state_wp,
self.offset_wp,
self.position_threshold,
],
device=self.device,
)
# convert transformations back to (w, x, y, z)
des_ee_pose = self.des_ee_pose[:, [0, 1, 2, 6, 3, 4, 5]]
# convert to torch
return torch.cat([des_ee_pose, self.des_gripper_state.unsqueeze(-1)], dim=-1)
def main():
# parse configuration
env_cfg: LiftEnvCfg = parse_env_cfg(
"Isaac-Lift-Cube-Franka-IK-Abs-v0",
device=args_cli.device,
num_envs=args_cli.num_envs,
use_fabric=not args_cli.disable_fabric,
)
# create environment
env = gym.make("Isaac-Lift-Cube-Franka-IK-Abs-v0", cfg=env_cfg)
# reset environment at start
env.reset()
# create action buffers (position + quaternion)
actions = torch.zeros(env.unwrapped.action_space.shape, device=env.unwrapped.device)
actions[:, 3] = 1.0
# desired object orientation (we only do position control of object)
desired_orientation = torch.zeros((env.unwrapped.num_envs, 4), device=env.unwrapped.device)
desired_orientation[:, 1] = 1.0
# create state machine
pick_sm = PickAndLiftSm(
env_cfg.sim.dt * env_cfg.decimation, env.unwrapped.num_envs, env.unwrapped.device, position_threshold=0.01
)
while simulation_app.is_running():
# run everything in inference mode
with torch.inference_mode():
# step environment
dones = env.step(actions)[-2]
# observations
# -- end-effector frame
ee_frame_sensor = env.unwrapped.scene["ee_frame"]
tcp_rest_position = ee_frame_sensor.data.target_pos_w[..., 0, :].clone() - env.unwrapped.scene.env_origins
tcp_rest_orientation = ee_frame_sensor.data.target_quat_w[..., 0, :].clone()
# -- object frame
object_data: RigidObjectData = env.unwrapped.scene["object"].data
object_position = object_data.root_pos_w - env.unwrapped.scene.env_origins
# -- target object frame
desired_position = env.unwrapped.command_manager.get_command("object_pose")[..., :3]
# advance state machine
actions = pick_sm.compute(
torch.cat([tcp_rest_position, tcp_rest_orientation], dim=-1),
torch.cat([object_position, desired_orientation], dim=-1),
torch.cat([desired_position, desired_orientation], dim=-1),
)
# reset state machine
if dones.any():
pick_sm.reset_idx(dones.nonzero(as_tuple=False).squeeze(-1))
# close the environment
env.close()
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()

View File

@@ -0,0 +1,341 @@
# 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
"""
Script to demonstrate lifting a deformable object with a robotic arm.
The state machine is implemented in the kernel function `infer_state_machine`.
It uses the `warp` library to run the state machine in parallel on the GPU.
.. code-block:: bash
./isaaclab.sh -p scripts/environments/state_machine/lift_teddy_bear.py
"""
"""Launch Omniverse Toolkit first."""
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Pick and lift a teddy bear with a robotic arm.")
parser.add_argument("--num_envs", type=int, default=1, help="Number of environments to simulate.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(headless=args_cli.headless)
simulation_app = app_launcher.app
# disable metrics assembler due to scene graph instancing
from isaacsim.core.utils.extensions import disable_extension
disable_extension("omni.usd.metrics.assembler.ui")
"""Rest everything else."""
from collections.abc import Sequence
import gymnasium as gym
import torch
import warp as wp
from isaaclab.assets.rigid_object.rigid_object_data import RigidObjectData
import isaaclab_tasks # noqa: F401
from isaaclab_tasks.manager_based.manipulation.lift.lift_env_cfg import LiftEnvCfg
from isaaclab_tasks.utils.parse_cfg import parse_env_cfg
# initialize warp
wp.init()
class GripperState:
"""States for the gripper."""
OPEN = wp.constant(1.0)
CLOSE = wp.constant(-1.0)
class PickSmState:
"""States for the pick state machine."""
REST = wp.constant(0)
APPROACH_ABOVE_OBJECT = wp.constant(1)
APPROACH_OBJECT = wp.constant(2)
GRASP_OBJECT = wp.constant(3)
LIFT_OBJECT = wp.constant(4)
OPEN_GRIPPER = wp.constant(5)
class PickSmWaitTime:
"""Additional wait times (in s) for states for before switching."""
REST = wp.constant(0.2)
APPROACH_ABOVE_OBJECT = wp.constant(0.5)
APPROACH_OBJECT = wp.constant(0.6)
GRASP_OBJECT = wp.constant(0.6)
LIFT_OBJECT = wp.constant(1.0)
OPEN_GRIPPER = wp.constant(0.0)
@wp.func
def distance_below_threshold(current_pos: wp.vec3, desired_pos: wp.vec3, threshold: float) -> bool:
return wp.length(current_pos - desired_pos) < threshold
@wp.kernel
def infer_state_machine(
dt: wp.array(dtype=float),
sm_state: wp.array(dtype=int),
sm_wait_time: wp.array(dtype=float),
ee_pose: wp.array(dtype=wp.transform),
object_pose: wp.array(dtype=wp.transform),
des_object_pose: wp.array(dtype=wp.transform),
des_ee_pose: wp.array(dtype=wp.transform),
gripper_state: wp.array(dtype=float),
offset: wp.array(dtype=wp.transform),
position_threshold: float,
):
# retrieve thread id
tid = wp.tid()
# retrieve state machine state
state = sm_state[tid]
# decide next state
if state == PickSmState.REST:
des_ee_pose[tid] = ee_pose[tid]
gripper_state[tid] = GripperState.OPEN
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.REST:
# move to next state and reset wait time
sm_state[tid] = PickSmState.APPROACH_ABOVE_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.APPROACH_ABOVE_OBJECT:
des_ee_pose[tid] = wp.transform_multiply(offset[tid], object_pose[tid])
gripper_state[tid] = GripperState.OPEN
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.APPROACH_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.APPROACH_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.APPROACH_OBJECT:
des_ee_pose[tid] = object_pose[tid]
gripper_state[tid] = GripperState.OPEN
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.APPROACH_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.GRASP_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.GRASP_OBJECT:
des_ee_pose[tid] = object_pose[tid]
gripper_state[tid] = GripperState.CLOSE
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.GRASP_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.LIFT_OBJECT
sm_wait_time[tid] = 0.0
elif state == PickSmState.LIFT_OBJECT:
des_ee_pose[tid] = des_object_pose[tid]
gripper_state[tid] = GripperState.CLOSE
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.LIFT_OBJECT:
# move to next state and reset wait time
sm_state[tid] = PickSmState.OPEN_GRIPPER
sm_wait_time[tid] = 0.0
elif state == PickSmState.OPEN_GRIPPER:
# des_ee_pose[tid] = object_pose[tid]
gripper_state[tid] = GripperState.OPEN
# wait for a while
if sm_wait_time[tid] >= PickSmWaitTime.OPEN_GRIPPER:
# move to next state and reset wait time
sm_state[tid] = PickSmState.OPEN_GRIPPER
sm_wait_time[tid] = 0.0
# increment wait time
sm_wait_time[tid] = sm_wait_time[tid] + dt[tid]
class PickAndLiftSm:
"""A simple state machine in a robot's task space to pick and lift an object.
The state machine is implemented as a warp kernel. It takes in the current state of
the robot's end-effector and the object, and outputs the desired state of the robot's
end-effector and the gripper. The state machine is implemented as a finite state
machine with the following states:
1. REST: The robot is at rest.
2. APPROACH_ABOVE_OBJECT: The robot moves above the object.
3. APPROACH_OBJECT: The robot moves to the object.
4. GRASP_OBJECT: The robot grasps the object.
5. LIFT_OBJECT: The robot lifts the object to the desired pose. This is the final state.
"""
def __init__(self, dt: float, num_envs: int, device: torch.device | str = "cpu", position_threshold=0.01):
"""Initialize the state machine.
Args:
dt: The environment time step.
num_envs: The number of environments to simulate.
device: The device to run the state machine on.
"""
# save parameters
self.dt = float(dt)
self.num_envs = num_envs
self.device = device
self.position_threshold = position_threshold
# initialize state machine
self.sm_dt = torch.full((self.num_envs,), self.dt, device=self.device)
self.sm_state = torch.full((self.num_envs,), 0, dtype=torch.int32, device=self.device)
self.sm_wait_time = torch.zeros((self.num_envs,), device=self.device)
# desired state
self.des_ee_pose = torch.zeros((self.num_envs, 7), device=self.device)
self.des_gripper_state = torch.full((self.num_envs,), 0.0, device=self.device)
# approach above object offset
self.offset = torch.zeros((self.num_envs, 7), device=self.device)
self.offset[:, 2] = 0.2
self.offset[:, -1] = 1.0 # warp expects quaternion as (x, y, z, w)
# convert to warp
self.sm_dt_wp = wp.from_torch(self.sm_dt, wp.float32)
self.sm_state_wp = wp.from_torch(self.sm_state, wp.int32)
self.sm_wait_time_wp = wp.from_torch(self.sm_wait_time, wp.float32)
self.des_ee_pose_wp = wp.from_torch(self.des_ee_pose, wp.transform)
self.des_gripper_state_wp = wp.from_torch(self.des_gripper_state, wp.float32)
self.offset_wp = wp.from_torch(self.offset, wp.transform)
def reset_idx(self, env_ids: Sequence[int] = None):
"""Reset the state machine."""
if env_ids is None:
env_ids = slice(None)
self.sm_state[env_ids] = 0
self.sm_wait_time[env_ids] = 0.0
def compute(self, ee_pose: torch.Tensor, object_pose: torch.Tensor, des_object_pose: torch.Tensor):
"""Compute the desired state of the robot's end-effector and the gripper."""
# convert all transformations from (w, x, y, z) to (x, y, z, w)
ee_pose = ee_pose[:, [0, 1, 2, 4, 5, 6, 3]]
object_pose = object_pose[:, [0, 1, 2, 4, 5, 6, 3]]
des_object_pose = des_object_pose[:, [0, 1, 2, 4, 5, 6, 3]]
# convert to warp
ee_pose_wp = wp.from_torch(ee_pose.contiguous(), wp.transform)
object_pose_wp = wp.from_torch(object_pose.contiguous(), wp.transform)
des_object_pose_wp = wp.from_torch(des_object_pose.contiguous(), wp.transform)
# run state machine
wp.launch(
kernel=infer_state_machine,
dim=self.num_envs,
inputs=[
self.sm_dt_wp,
self.sm_state_wp,
self.sm_wait_time_wp,
ee_pose_wp,
object_pose_wp,
des_object_pose_wp,
self.des_ee_pose_wp,
self.des_gripper_state_wp,
self.offset_wp,
self.position_threshold,
],
device=self.device,
)
# convert transformations back to (w, x, y, z)
des_ee_pose = self.des_ee_pose[:, [0, 1, 2, 6, 3, 4, 5]]
# convert to torch
return torch.cat([des_ee_pose, self.des_gripper_state.unsqueeze(-1)], dim=-1)
def main():
# parse configuration
env_cfg: LiftEnvCfg = parse_env_cfg(
"Isaac-Lift-Teddy-Bear-Franka-IK-Abs-v0",
device=args_cli.device,
num_envs=args_cli.num_envs,
)
env_cfg.viewer.eye = (2.1, 1.0, 1.3)
# create environment
env = gym.make("Isaac-Lift-Teddy-Bear-Franka-IK-Abs-v0", cfg=env_cfg)
# reset environment at start
env.reset()
# create action buffers (position + quaternion)
actions = torch.zeros(env.unwrapped.action_space.shape, device=env.unwrapped.device)
actions[:, 3] = 1.0
# desired rotation after grasping
desired_orientation = torch.zeros((env.unwrapped.num_envs, 4), device=env.unwrapped.device)
desired_orientation[:, 1] = 1.0
object_grasp_orientation = torch.zeros((env.unwrapped.num_envs, 4), device=env.unwrapped.device)
# z-axis pointing down and 45 degrees rotation
object_grasp_orientation[:, 1] = 0.9238795
object_grasp_orientation[:, 2] = -0.3826834
object_local_grasp_position = torch.tensor([0.02, -0.08, 0.0], device=env.unwrapped.device)
# create state machine
pick_sm = PickAndLiftSm(env_cfg.sim.dt * env_cfg.decimation, env.unwrapped.num_envs, env.unwrapped.device)
while simulation_app.is_running():
# run everything in inference mode
with torch.inference_mode():
# step environment
dones = env.step(actions)[-2]
# observations
# -- end-effector frame
ee_frame_sensor = env.unwrapped.scene["ee_frame"]
tcp_rest_position = ee_frame_sensor.data.target_pos_w[..., 0, :].clone() - env.unwrapped.scene.env_origins
tcp_rest_orientation = ee_frame_sensor.data.target_quat_w[..., 0, :].clone()
# -- object frame
object_data: RigidObjectData = env.unwrapped.scene["object"].data
object_position = object_data.root_pos_w - env.unwrapped.scene.env_origins
object_position += object_local_grasp_position
# -- target object frame
desired_position = env.unwrapped.command_manager.get_command("object_pose")[..., :3]
# advance state machine
actions = pick_sm.compute(
torch.cat([tcp_rest_position, tcp_rest_orientation], dim=-1),
torch.cat([object_position, object_grasp_orientation], dim=-1),
torch.cat([desired_position, desired_orientation], dim=-1),
)
# reset state machine
if dones.any():
pick_sm.reset_idx(dones.nonzero(as_tuple=False).squeeze(-1))
# close the environment
env.close()
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()

View File

@@ -0,0 +1,333 @@
# 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
"""
Script to run an environment with a cabinet opening state machine.
The state machine is implemented in the kernel function `infer_state_machine`.
It uses the `warp` library to run the state machine in parallel on the GPU.
.. code-block:: bash
./isaaclab.sh -p scripts/environments/state_machine/open_cabinet_sm.py --num_envs 32
"""
"""Launch Omniverse Toolkit first."""
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Pick and lift state machine for cabinet environments.")
parser.add_argument(
"--disable_fabric", action="store_true", default=False, help="Disable fabric and use USD I/O operations."
)
parser.add_argument("--num_envs", type=int, default=None, help="Number of environments to simulate.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(headless=args_cli.headless)
simulation_app = app_launcher.app
"""Rest everything else."""
from collections.abc import Sequence
import gymnasium as gym
import torch
import warp as wp
from isaaclab.sensors import FrameTransformer
import isaaclab_tasks # noqa: F401
from isaaclab_tasks.manager_based.manipulation.cabinet.cabinet_env_cfg import CabinetEnvCfg
from isaaclab_tasks.utils.parse_cfg import parse_env_cfg
# initialize warp
wp.init()
class GripperState:
"""States for the gripper."""
OPEN = wp.constant(1.0)
CLOSE = wp.constant(-1.0)
class OpenDrawerSmState:
"""States for the cabinet drawer opening state machine."""
REST = wp.constant(0)
APPROACH_INFRONT_HANDLE = wp.constant(1)
APPROACH_HANDLE = wp.constant(2)
GRASP_HANDLE = wp.constant(3)
OPEN_DRAWER = wp.constant(4)
RELEASE_HANDLE = wp.constant(5)
class OpenDrawerSmWaitTime:
"""Additional wait times (in s) for states for before switching."""
REST = wp.constant(0.5)
APPROACH_INFRONT_HANDLE = wp.constant(1.25)
APPROACH_HANDLE = wp.constant(1.0)
GRASP_HANDLE = wp.constant(1.0)
OPEN_DRAWER = wp.constant(3.0)
RELEASE_HANDLE = wp.constant(0.2)
@wp.func
def distance_below_threshold(current_pos: wp.vec3, desired_pos: wp.vec3, threshold: float) -> bool:
return wp.length(current_pos - desired_pos) < threshold
@wp.kernel
def infer_state_machine(
dt: wp.array(dtype=float),
sm_state: wp.array(dtype=int),
sm_wait_time: wp.array(dtype=float),
ee_pose: wp.array(dtype=wp.transform),
handle_pose: wp.array(dtype=wp.transform),
des_ee_pose: wp.array(dtype=wp.transform),
gripper_state: wp.array(dtype=float),
handle_approach_offset: wp.array(dtype=wp.transform),
handle_grasp_offset: wp.array(dtype=wp.transform),
drawer_opening_rate: wp.array(dtype=wp.transform),
position_threshold: float,
):
# retrieve thread id
tid = wp.tid()
# retrieve state machine state
state = sm_state[tid]
# decide next state
if state == OpenDrawerSmState.REST:
des_ee_pose[tid] = ee_pose[tid]
gripper_state[tid] = GripperState.OPEN
# wait for a while
if sm_wait_time[tid] >= OpenDrawerSmWaitTime.REST:
# move to next state and reset wait time
sm_state[tid] = OpenDrawerSmState.APPROACH_INFRONT_HANDLE
sm_wait_time[tid] = 0.0
elif state == OpenDrawerSmState.APPROACH_INFRONT_HANDLE:
des_ee_pose[tid] = wp.transform_multiply(handle_approach_offset[tid], handle_pose[tid])
gripper_state[tid] = GripperState.OPEN
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= OpenDrawerSmWaitTime.APPROACH_INFRONT_HANDLE:
# move to next state and reset wait time
sm_state[tid] = OpenDrawerSmState.APPROACH_HANDLE
sm_wait_time[tid] = 0.0
elif state == OpenDrawerSmState.APPROACH_HANDLE:
des_ee_pose[tid] = handle_pose[tid]
gripper_state[tid] = GripperState.OPEN
if distance_below_threshold(
wp.transform_get_translation(ee_pose[tid]),
wp.transform_get_translation(des_ee_pose[tid]),
position_threshold,
):
# wait for a while
if sm_wait_time[tid] >= OpenDrawerSmWaitTime.APPROACH_HANDLE:
# move to next state and reset wait time
sm_state[tid] = OpenDrawerSmState.GRASP_HANDLE
sm_wait_time[tid] = 0.0
elif state == OpenDrawerSmState.GRASP_HANDLE:
des_ee_pose[tid] = wp.transform_multiply(handle_grasp_offset[tid], handle_pose[tid])
gripper_state[tid] = GripperState.CLOSE
# wait for a while
if sm_wait_time[tid] >= OpenDrawerSmWaitTime.GRASP_HANDLE:
# move to next state and reset wait time
sm_state[tid] = OpenDrawerSmState.OPEN_DRAWER
sm_wait_time[tid] = 0.0
elif state == OpenDrawerSmState.OPEN_DRAWER:
des_ee_pose[tid] = wp.transform_multiply(drawer_opening_rate[tid], handle_pose[tid])
gripper_state[tid] = GripperState.CLOSE
# wait for a while
if sm_wait_time[tid] >= OpenDrawerSmWaitTime.OPEN_DRAWER:
# move to next state and reset wait time
sm_state[tid] = OpenDrawerSmState.RELEASE_HANDLE
sm_wait_time[tid] = 0.0
elif state == OpenDrawerSmState.RELEASE_HANDLE:
des_ee_pose[tid] = ee_pose[tid]
gripper_state[tid] = GripperState.CLOSE
# wait for a while
if sm_wait_time[tid] >= OpenDrawerSmWaitTime.RELEASE_HANDLE:
# move to next state and reset wait time
sm_state[tid] = OpenDrawerSmState.RELEASE_HANDLE
sm_wait_time[tid] = 0.0
# increment wait time
sm_wait_time[tid] = sm_wait_time[tid] + dt[tid]
class OpenDrawerSm:
"""A simple state machine in a robot's task space to open a drawer in the cabinet.
The state machine is implemented as a warp kernel. It takes in the current state of
the robot's end-effector and the object, and outputs the desired state of the robot's
end-effector and the gripper. The state machine is implemented as a finite state
machine with the following states:
1. REST: The robot is at rest.
2. APPROACH_HANDLE: The robot moves towards the handle of the drawer.
3. GRASP_HANDLE: The robot grasps the handle of the drawer.
4. OPEN_DRAWER: The robot opens the drawer.
5. RELEASE_HANDLE: The robot releases the handle of the drawer. This is the final state.
"""
def __init__(self, dt: float, num_envs: int, device: torch.device | str = "cpu", position_threshold=0.01):
"""Initialize the state machine.
Args:
dt: The environment time step.
num_envs: The number of environments to simulate.
device: The device to run the state machine on.
"""
# save parameters
self.dt = float(dt)
self.num_envs = num_envs
self.device = device
self.position_threshold = position_threshold
# initialize state machine
self.sm_dt = torch.full((self.num_envs,), self.dt, device=self.device)
self.sm_state = torch.full((self.num_envs,), 0, dtype=torch.int32, device=self.device)
self.sm_wait_time = torch.zeros((self.num_envs,), device=self.device)
# desired state
self.des_ee_pose = torch.zeros((self.num_envs, 7), device=self.device)
self.des_gripper_state = torch.full((self.num_envs,), 0.0, device=self.device)
# approach in front of the handle
self.handle_approach_offset = torch.zeros((self.num_envs, 7), device=self.device)
self.handle_approach_offset[:, 0] = -0.1
self.handle_approach_offset[:, -1] = 1.0 # warp expects quaternion as (x, y, z, w)
# handle grasp offset
self.handle_grasp_offset = torch.zeros((self.num_envs, 7), device=self.device)
self.handle_grasp_offset[:, 0] = 0.025
self.handle_grasp_offset[:, -1] = 1.0 # warp expects quaternion as (x, y, z, w)
# drawer opening rate
self.drawer_opening_rate = torch.zeros((self.num_envs, 7), device=self.device)
self.drawer_opening_rate[:, 0] = -0.015
self.drawer_opening_rate[:, -1] = 1.0 # warp expects quaternion as (x, y, z, w)
# convert to warp
self.sm_dt_wp = wp.from_torch(self.sm_dt, wp.float32)
self.sm_state_wp = wp.from_torch(self.sm_state, wp.int32)
self.sm_wait_time_wp = wp.from_torch(self.sm_wait_time, wp.float32)
self.des_ee_pose_wp = wp.from_torch(self.des_ee_pose, wp.transform)
self.des_gripper_state_wp = wp.from_torch(self.des_gripper_state, wp.float32)
self.handle_approach_offset_wp = wp.from_torch(self.handle_approach_offset, wp.transform)
self.handle_grasp_offset_wp = wp.from_torch(self.handle_grasp_offset, wp.transform)
self.drawer_opening_rate_wp = wp.from_torch(self.drawer_opening_rate, wp.transform)
def reset_idx(self, env_ids: Sequence[int] | None = None):
"""Reset the state machine."""
if env_ids is None:
env_ids = slice(None)
# reset state machine
self.sm_state[env_ids] = 0
self.sm_wait_time[env_ids] = 0.0
def compute(self, ee_pose: torch.Tensor, handle_pose: torch.Tensor):
"""Compute the desired state of the robot's end-effector and the gripper."""
# convert all transformations from (w, x, y, z) to (x, y, z, w)
ee_pose = ee_pose[:, [0, 1, 2, 4, 5, 6, 3]]
handle_pose = handle_pose[:, [0, 1, 2, 4, 5, 6, 3]]
# convert to warp
ee_pose_wp = wp.from_torch(ee_pose.contiguous(), wp.transform)
handle_pose_wp = wp.from_torch(handle_pose.contiguous(), wp.transform)
# run state machine
wp.launch(
kernel=infer_state_machine,
dim=self.num_envs,
inputs=[
self.sm_dt_wp,
self.sm_state_wp,
self.sm_wait_time_wp,
ee_pose_wp,
handle_pose_wp,
self.des_ee_pose_wp,
self.des_gripper_state_wp,
self.handle_approach_offset_wp,
self.handle_grasp_offset_wp,
self.drawer_opening_rate_wp,
self.position_threshold,
],
device=self.device,
)
# convert transformations back to (w, x, y, z)
des_ee_pose = self.des_ee_pose[:, [0, 1, 2, 6, 3, 4, 5]]
# convert to torch
return torch.cat([des_ee_pose, self.des_gripper_state.unsqueeze(-1)], dim=-1)
def main():
# parse configuration
env_cfg: CabinetEnvCfg = parse_env_cfg(
"Isaac-Open-Drawer-Franka-IK-Abs-v0",
device=args_cli.device,
num_envs=args_cli.num_envs,
use_fabric=not args_cli.disable_fabric,
)
# create environment
env = gym.make("Isaac-Open-Drawer-Franka-IK-Abs-v0", cfg=env_cfg)
# reset environment at start
env.reset()
# create action buffers (position + quaternion)
actions = torch.zeros(env.unwrapped.action_space.shape, device=env.unwrapped.device)
actions[:, 3] = 1.0
# desired object orientation (we only do position control of object)
desired_orientation = torch.zeros((env.unwrapped.num_envs, 4), device=env.unwrapped.device)
desired_orientation[:, 1] = 1.0
# create state machine
open_sm = OpenDrawerSm(env_cfg.sim.dt * env_cfg.decimation, env.unwrapped.num_envs, env.unwrapped.device)
while simulation_app.is_running():
# run everything in inference mode
with torch.inference_mode():
# step environment
dones = env.step(actions)[-2]
# observations
# -- end-effector frame
ee_frame_tf: FrameTransformer = env.unwrapped.scene["ee_frame"]
tcp_rest_position = ee_frame_tf.data.target_pos_w[..., 0, :].clone() - env.unwrapped.scene.env_origins
tcp_rest_orientation = ee_frame_tf.data.target_quat_w[..., 0, :].clone()
# -- handle frame
cabinet_frame_tf: FrameTransformer = env.unwrapped.scene["cabinet_frame"]
cabinet_position = cabinet_frame_tf.data.target_pos_w[..., 0, :].clone() - env.unwrapped.scene.env_origins
cabinet_orientation = cabinet_frame_tf.data.target_quat_w[..., 0, :].clone()
# advance state machine
actions = open_sm.compute(
torch.cat([tcp_rest_position, tcp_rest_orientation], dim=-1),
torch.cat([cabinet_position, cabinet_orientation], dim=-1),
)
# reset state machine
if dones.any():
open_sm.reset_idx(dones.nonzero(as_tuple=False).squeeze(-1))
# close the environment
env.close()
if __name__ == "__main__":
# run the main execution
main()
# close sim app
simulation_app.close()

View File

@@ -0,0 +1,314 @@
# 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
"""Script to run teleoperation with Isaac Lab manipulation environments.
Supports multiple input devices (e.g., keyboard, spacemouse, gamepad) and devices
configured within the environment (including OpenXR-based hand tracking or motion
controllers)."""
"""Launch Isaac Sim Simulator first."""
import argparse
from collections.abc import Callable
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(
description="Teleoperation for Isaac Lab environments."
)
parser.add_argument(
"--num_envs", type=int, default=1, help="Number of environments to simulate."
)
parser.add_argument(
"--teleop_device",
type=str,
default="keyboard",
help=(
"Teleop device. Set here (legacy) or via the environment config. If using the environment config, pass the"
" device key/name defined under 'teleop_devices' (it can be a custom name, not necessarily 'handtracking')."
" Built-ins: keyboard, spacemouse, gamepad. Not all tasks support all built-ins."
),
)
parser.add_argument("--task", type=str, default=None, help="Name of the task.")
parser.add_argument(
"--sensitivity", type=float, default=1.0, help="Sensitivity factor."
)
parser.add_argument(
"--enable_pinocchio",
action="store_true",
default=False,
help="Enable Pinocchio.",
)
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
app_launcher_args = vars(args_cli)
if args_cli.enable_pinocchio:
# Import pinocchio before AppLauncher to force the use of the version installed by IsaacLab and
# not the one installed by Isaac Sim pinocchio is required by the Pink IK controllers and the
# GR1T2 retargeter
import pinocchio # noqa: F401
if "handtracking" in args_cli.teleop_device.lower():
app_launcher_args["xr"] = True
# launch omniverse app
app_launcher = AppLauncher(app_launcher_args)
simulation_app = app_launcher.app
"""Rest everything follows."""
import logging
import gymnasium as gym
import torch
from isaaclab.devices import (
Se3Gamepad,
Se3GamepadCfg,
Se3Keyboard,
Se3KeyboardCfg,
Se3SpaceMouse,
Se3SpaceMouseCfg,
)
from isaaclab.devices.openxr import remove_camera_configs
from isaaclab.devices.teleop_device_factory import create_teleop_device
from isaaclab.envs import ManagerBasedRLEnvCfg
from isaaclab.managers import TerminationTermCfg as DoneTerm
import isaaclab_tasks # noqa: F401
import mindbot.tasks # noqa: F401
from isaaclab_tasks.manager_based.manipulation.lift import mdp
from isaaclab_tasks.utils import parse_env_cfg
if args_cli.enable_pinocchio:
import isaaclab_tasks.manager_based.locomanipulation.pick_place # noqa: F401
import isaaclab_tasks.manager_based.manipulation.pick_place # noqa: F401
# import logger
logger = logging.getLogger(__name__)
def main() -> None:
"""
Run teleoperation with an Isaac Lab manipulation environment.
Creates the environment, sets up teleoperation interfaces and callbacks,
and runs the main simulation loop until the application is closed.
Returns:
None
"""
# parse configuration
env_cfg = parse_env_cfg(
args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs
)
env_cfg.env_name = args_cli.task
if not isinstance(env_cfg, ManagerBasedRLEnvCfg):
raise ValueError(
"Teleoperation is only supported for ManagerBasedRLEnv environments. "
f"Received environment config type: {type(env_cfg).__name__}"
)
# modify configuration
env_cfg.terminations.time_out = None
if "Lift" in args_cli.task:
# set the resampling time range to large number to avoid resampling
env_cfg.commands.object_pose.resampling_time_range = (1.0e9, 1.0e9)
# add termination condition for reaching the goal otherwise the environment won't reset
env_cfg.terminations.object_reached_goal = DoneTerm(
func=mdp.object_reached_goal
)
if args_cli.xr:
env_cfg = remove_camera_configs(env_cfg)
env_cfg.sim.render.antialiasing_mode = "DLSS"
try:
# create environment
env = gym.make(args_cli.task, cfg=env_cfg).unwrapped
# check environment name (for reach , we don't allow the gripper)
if "Reach" in args_cli.task:
logger.warning(
f"The environment '{args_cli.task}' does not support gripper control. The device command will be"
" ignored."
)
except Exception as e:
logger.error(f"Failed to create environment: {e}")
simulation_app.close()
return
# Flags for controlling teleoperation flow
should_reset_recording_instance = False
teleoperation_active = True
# Callback handlers
def reset_recording_instance() -> None:
"""
Reset the environment to its initial state.
Sets a flag to reset the environment on the next simulation step.
Returns:
None
"""
nonlocal should_reset_recording_instance
should_reset_recording_instance = True
print("Reset triggered - Environment will reset on next step")
def start_teleoperation() -> None:
"""
Activate teleoperation control of the robot.
Enables the application of teleoperation commands to the environment.
Returns:
None
"""
nonlocal teleoperation_active
teleoperation_active = True
print("Teleoperation activated")
def stop_teleoperation() -> None:
"""
Deactivate teleoperation control of the robot.
Disables the application of teleoperation commands to the environment.
Returns:
None
"""
nonlocal teleoperation_active
teleoperation_active = False
print("Teleoperation deactivated")
# Create device config if not already in env_cfg
teleoperation_callbacks: dict[str, Callable[[], None]] = {
"R": reset_recording_instance,
"START": start_teleoperation,
"STOP": stop_teleoperation,
"RESET": reset_recording_instance,
}
# For hand tracking devices, add additional callbacks
if args_cli.xr:
# Default to inactive for hand tracking
teleoperation_active = False
else:
# Always active for other devices
teleoperation_active = True
# Create teleop device from config if present, otherwise create manually
teleop_interface = None
try:
if (
hasattr(env_cfg, "teleop_devices")
and args_cli.teleop_device in env_cfg.teleop_devices.devices
):
teleop_interface = create_teleop_device(
args_cli.teleop_device,
env_cfg.teleop_devices.devices,
teleoperation_callbacks,
)
else:
logger.warning(
f"No teleop device '{args_cli.teleop_device}' found in environment config. Creating default."
)
# Create fallback teleop device
sensitivity = args_cli.sensitivity
if args_cli.teleop_device.lower() == "keyboard":
teleop_interface = Se3Keyboard(
Se3KeyboardCfg(
pos_sensitivity=0.05 * sensitivity,
rot_sensitivity=0.05 * sensitivity,
)
)
elif args_cli.teleop_device.lower() == "spacemouse":
teleop_interface = Se3SpaceMouse(
Se3SpaceMouseCfg(
pos_sensitivity=0.05 * sensitivity,
rot_sensitivity=0.05 * sensitivity,
)
)
elif args_cli.teleop_device.lower() == "gamepad":
teleop_interface = Se3Gamepad(
Se3GamepadCfg(
pos_sensitivity=0.1 * sensitivity,
rot_sensitivity=0.1 * sensitivity,
)
)
else:
logger.error(f"Unsupported teleop device: {args_cli.teleop_device}")
logger.error("Configure the teleop device in the environment config.")
env.close()
simulation_app.close()
return
# Add callbacks to fallback device
for key, callback in teleoperation_callbacks.items():
try:
teleop_interface.add_callback(key, callback)
except (ValueError, TypeError) as e:
logger.warning(f"Failed to add callback for key {key}: {e}")
except Exception as e:
logger.error(f"Failed to create teleop device: {e}")
env.close()
simulation_app.close()
return
if teleop_interface is None:
logger.error("Failed to create teleop interface")
env.close()
simulation_app.close()
return
print(f"Using teleop device: {teleop_interface}")
# reset environment
env.reset()
teleop_interface.reset()
print("Teleoperation started. Press 'R' to reset the environment.")
# simulate environment
while simulation_app.is_running():
try:
# run everything in inference mode
with torch.inference_mode():
# get device command
action = teleop_interface.advance()
# Only apply teleop commands when active
if teleoperation_active:
# process actions
actions = action.repeat(env.num_envs, 1)
# apply actions
env.step(actions)
else:
env.sim.render()
if should_reset_recording_instance:
env.reset()
teleop_interface.reset()
should_reset_recording_instance = False
print("Environment reset complete")
except Exception as e:
logger.error(f"Error during simulation step: {e}")
break
# close the simulator
env.close()
print("Environment closed")
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()

View File

@@ -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
"""Script to run an environment with zero action agent."""
"""Launch Isaac Sim Simulator first."""
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Zero agent for Isaac Lab environments.")
parser.add_argument(
"--disable_fabric", action="store_true", default=False, help="Disable fabric and use USD I/O operations."
)
parser.add_argument("--num_envs", type=int, default=None, help="Number of environments to simulate.")
parser.add_argument("--task", type=str, default=None, help="Name of the task.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app
"""Rest everything follows."""
import gymnasium as gym
import torch
import isaaclab_tasks # noqa: F401
from isaaclab_tasks.utils import parse_env_cfg
# PLACEHOLDER: Extension template (do not remove this comment)
def main():
"""Zero actions agent with Isaac Lab environment."""
# parse configuration
env_cfg = parse_env_cfg(
args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
)
# create environment
env = gym.make(args_cli.task, cfg=env_cfg)
# print info (this is vectorized environment)
print(f"[INFO]: Gym observation space: {env.observation_space}")
print(f"[INFO]: Gym action space: {env.action_space}")
# reset environment
env.reset()
# simulate environment
while simulation_app.is_running():
# run everything in inference mode
with torch.inference_mode():
# compute zero actions
actions = torch.zeros(env.action_space.shape, device=env.unwrapped.device)
# apply actions
env.step(actions)
# close the simulator
env.close()
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()

View File

@@ -19,8 +19,8 @@ MINDBOT_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
# 1. UPDATE THE USD PATH to your local file
# C:\Users\PC\workpalce\maic_usd_assets\twinlab\MIC_sim-3.0\pupet_arm_sim_product\sim_data_acquisition\usds\Collected_robot_2_3\robot_2_4.usd
usd_path="C:/Users/PC/workpalce/maic_usd_assets/robots/mindrobot-1105-lab/mindrobot_cd2.usd",
# usd_path="C:/Users/PC/workpalce/maic_usd_assets/twinlab/MIC_sim-3.0/pupet_arm_sim_product/sim_data_acquisition/usds/Collected_robot_2_3/robot_2_6.usd",
usd_path="/home/maic/LYT/maic_usd_assets/robots/mindrobot-1105-lab/mindrobot_cd2.usd",
# usd_path="/home/maic/LYT/maic_usd_assets/twinlab/MIC_sim-3.0/pupet_arm_sim_product/sim_data_acquisition/usds/Collected_robot_2_3/robot_2_6.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_depenetration_velocity=1.0,
@@ -36,8 +36,8 @@ MINDBOT_CFG = ArticulationCfg(
),
collision_props=sim_utils.CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005, # 尝试从默认值增大到 0.01 或 0.02
rest_offset=0, # 保持略小于 contact_offset
contact_offset=0.0005, # 尝试从默认值增大到 0.01 或 0.02
rest_offset=0, # 保持略小于 contact_offset
),
),
init_state=ArticulationCfg.InitialStateCfg(
@@ -45,7 +45,7 @@ MINDBOT_CFG = ArticulationCfg(
# All are set to 0.0 here, but you should adjust them for a suitable "home" position.
joint_pos={
# Left arm joints
# Left arm joints
# Left arm joints
# 135° -> 2.3562
"l_joint1": 2.3562,
# -70° -> -1.2217
@@ -65,7 +65,7 @@ MINDBOT_CFG = ArticulationCfg(
# "l_joint4": 0.0,
# "l_joint5": 0.0,
# "l_joint6": 0.0,
# Right arm joints
# Right arm joints
# # -45° -> -0.7854
# "r_joint1": -0.7854,
# # 70° -> 1.2217
@@ -95,15 +95,15 @@ MINDBOT_CFG = ArticulationCfg(
# left gripper
# 注意:如果希望初始状态为完全打开,应该设置为 left=0.0, right=0.0
# 当前设置为 right=0.01 表示略微闭合状态
"left_hand_joint_left": 0.0, # 范围:(-0.03, 0.0)0.0=打开,-0.03=闭合
"left_hand_joint_left": 0.0, # 范围:(-0.03, 0.0)0.0=打开,-0.03=闭合
"left_hand_joint_right": 0.0, # 范围:(0.0, 0.03)0.0=打开0.03=闭合
# right gripper
"right_hand_joint_left": 0.0,
"right_hand_joint_right": 0.0,
# trunk
"PrismaticJoint": 0.23, # 0.30
"PrismaticJoint": 0.23, # 0.30
# head
"head_revoluteJoint": 0.0 #0.5236
"head_revoluteJoint": 0.0, # 0.5236
},
# The initial (x, y, z) position of the robot's base in the world
pos=(0, 0, 0.05),
@@ -112,40 +112,46 @@ MINDBOT_CFG = ArticulationCfg(
# 3. DEFINE ACTUATOR GROUPS FOR THE ARMS
# Group for the 6 left arm joints using a regular expression
"left_arm": ImplicitActuatorCfg(
joint_names_expr=["l_joint[1-6]"], # This matches l_joint1, l_joint2, ..., l_joint6
effort_limit_sim=100.0, # Note: Tune this based on your robot's specs
velocity_limit_sim=100.0, # Note: Tune this based on your robot's specs
stiffness=0.0, #10000.0, # Note: Tune this for desired control performance
damping=1000.0, #10000.0, # Note: Tune this for desired control performance
joint_names_expr=[
"l_joint[1-6]"
], # This matches l_joint1, l_joint2, ..., l_joint6
effort_limit_sim=100.0, # Note: Tune this based on your robot's specs
velocity_limit_sim=100.0, # Note: Tune this based on your robot's specs
stiffness=0.0, # 10000.0, # Note: Tune this for desired control performance
damping=1000.0, # 10000.0, # Note: Tune this for desired control performance
),
# Group for the 6 right arm joints using a regular expression
"right_arm": ImplicitActuatorCfg(
joint_names_expr=["r_joint[1-6]"], # This matches r_joint1, r_joint2, ..., r_joint6
effort_limit_sim=100.0, # Note: Tune this based on your robot's specs
velocity_limit_sim=100.0, # Note: Tune this based on your robot's specs
stiffness=10000.0, #10000.0, # Note: Tune this for desired control performance1
damping=1000.0, #10000.0, # Note: Tune this for desired control performance
joint_names_expr=[
"r_joint[1-6]"
], # This matches r_joint1, r_joint2, ..., r_joint6
effort_limit_sim=100.0, # Note: Tune this based on your robot's specs
velocity_limit_sim=100.0, # Note: Tune this based on your robot's specs
stiffness=10000.0, # 10000.0, # Note: Tune this for desired control performance1
damping=1000.0, # 10000.0, # Note: Tune this for desired control performance
),
"head": ImplicitActuatorCfg(
joint_names_expr=["head_revoluteJoint"], stiffness=10000.0, damping=1000.0
),
"head": ImplicitActuatorCfg(joint_names_expr=["head_revoluteJoint"], stiffness=10000.0, damping=1000.0),
"trunk": ImplicitActuatorCfg(
joint_names_expr=["PrismaticJoint"],
stiffness=40000.0, # 从 10000 增:强持位
damping=4000.0, # 从 1000 增:抗振荡
stiffness=40000.0, # 从 10000 增:强持位
damping=4000.0, # 从 1000 增:抗振荡
effort_limit_sim=10000.0,
velocity_limit_sim=0.2,
),
"wheels": ImplicitActuatorCfg(
joint_names_expr=[".*_revolute_Joint"],
stiffness=0.0,
joint_names_expr=[".*_revolute_Joint"],
stiffness=0.0,
damping=100.0,
effort_limit_sim=200.0, # <<<<<< 新增:力矩上限,足够驱动轮子
velocity_limit_sim=50.0, # <<<<<< 新增:速度上限,防止过快
velocity_limit_sim=50.0, # <<<<<< 新增:速度上限,防止过快
),
"grippers": ImplicitActuatorCfg(
joint_names_expr=[".*_hand_joint.*"],
stiffness=10000.0, #10000.0
joint_names_expr=[".*_hand_joint.*"],
stiffness=10000.0, # 10000.0
damping=1000.0,
effort_limit_sim=50.0, # default is 10, gemini said it is too small, so I set it to 50.
effort_limit_sim=50.0, # default is 10, gemini said it is too small, so I set it to 50.
velocity_limit_sim=50.0,
),
},

View File

@@ -0,0 +1,8 @@
# 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
"""Imitation learning tasks."""
import gymnasium as gym # noqa: F401

View File

@@ -0,0 +1,40 @@
# 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
import gymnasium as gym
# from . import agents
from .agents import *
##
# Register Gym environments.
##
##
# MindRobot Left Arm IK-Rel (keyboard teleop)
##
# gym.register(
# id="Isaac-MindRobot-LeftArm-IK-Rel-v0",
# entry_point="isaaclab.envs:ManagerBasedRLEnv",
# kwargs={
# "env_cfg_entry_point": (
# "isaaclab_tasks.manager_based.manipulation.mindrobot."
# "mindrobot_left_arm_ik_env_cfg:MindRobotLeftArmIKRelEnvCfg"
# ),
# "robomimic_bc_cfg_entry_point": "isaaclab_tasks.manager_based.manipulation.mindrobot.agents:robomimic/bc_rnn_low_dim.json",
# },
# disable_env_checker=True,
# )
# ...existing code...
gym.register(
id="Isaac-MindRobot-LeftArm-IK-Rel-v0",
entry_point="isaaclab.envs:ManagerBasedRLEnv",
kwargs={
"env_cfg_entry_point": f"{__name__}.mindrobot_left_arm_ik_env_cfg:MindRobotLeftArmIKEnvCfg",
"robomimic_bc_cfg_entry_point": f"{__name__}.agents:robomimic/bc_rnn_low_dim.json",
},
disable_env_checker=True,
)
# ...existing code...

View File

@@ -0,0 +1,4 @@
# 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

View File

@@ -0,0 +1,219 @@
{
"algo_name": "bc",
"experiment": {
"name": "bc_rnn_image_franka_stack",
"validate": false,
"logging": {
"terminal_output_to_txt": true,
"log_tb": true
},
"save": {
"enabled": true,
"every_n_seconds": null,
"every_n_epochs": 20,
"epochs": [],
"on_best_validation": false,
"on_best_rollout_return": false,
"on_best_rollout_success_rate": true
},
"epoch_every_n_steps": 500,
"env": null,
"additional_envs": null,
"render": false,
"render_video": false,
"rollout": {
"enabled": false
}
},
"train": {
"data": null,
"num_data_workers": 4,
"hdf5_cache_mode": "low_dim",
"hdf5_use_swmr": true,
"hdf5_load_next_obs": false,
"hdf5_normalize_obs": false,
"hdf5_filter_key": null,
"hdf5_validation_filter_key": null,
"seq_length": 10,
"pad_seq_length": true,
"frame_stack": 1,
"pad_frame_stack": true,
"dataset_keys": [
"actions",
"rewards",
"dones"
],
"goal_mode": null,
"cuda": true,
"batch_size": 16,
"num_epochs": 600,
"seed": 101
},
"algo": {
"optim_params": {
"policy": {
"optimizer_type": "adam",
"learning_rate": {
"initial": 0.0001,
"decay_factor": 0.1,
"epoch_schedule": [],
"scheduler_type": "multistep"
},
"regularization": {
"L2": 0.0
}
}
},
"loss": {
"l2_weight": 1.0,
"l1_weight": 0.0,
"cos_weight": 0.0
},
"actor_layer_dims": [],
"gaussian": {
"enabled": false,
"fixed_std": false,
"init_std": 0.1,
"min_std": 0.01,
"std_activation": "softplus",
"low_noise_eval": true
},
"gmm": {
"enabled": true,
"num_modes": 5,
"min_std": 0.0001,
"std_activation": "softplus",
"low_noise_eval": true
},
"vae": {
"enabled": false,
"latent_dim": 14,
"latent_clip": null,
"kl_weight": 1.0,
"decoder": {
"is_conditioned": true,
"reconstruction_sum_across_elements": false
},
"prior": {
"learn": false,
"is_conditioned": false,
"use_gmm": false,
"gmm_num_modes": 10,
"gmm_learn_weights": false,
"use_categorical": false,
"categorical_dim": 10,
"categorical_gumbel_softmax_hard": false,
"categorical_init_temp": 1.0,
"categorical_temp_anneal_step": 0.001,
"categorical_min_temp": 0.3
},
"encoder_layer_dims": [
300,
400
],
"decoder_layer_dims": [
300,
400
],
"prior_layer_dims": [
300,
400
]
},
"rnn": {
"enabled": true,
"horizon": 10,
"hidden_dim": 1000,
"rnn_type": "LSTM",
"num_layers": 2,
"open_loop": false,
"kwargs": {
"bidirectional": false
}
},
"transformer": {
"enabled": false,
"context_length": 10,
"embed_dim": 512,
"num_layers": 6,
"num_heads": 8,
"emb_dropout": 0.1,
"attn_dropout": 0.1,
"block_output_dropout": 0.1,
"sinusoidal_embedding": false,
"activation": "gelu",
"supervise_all_steps": false,
"nn_parameter_for_timesteps": true
}
},
"observation": {
"modalities": {
"obs": {
"low_dim": [
"eef_pos",
"eef_quat",
"gripper_pos"
],
"rgb": [
"table_cam",
"wrist_cam"
],
"depth": [],
"scan": []
},
"goal": {
"low_dim": [],
"rgb": [],
"depth": [],
"scan": []
}
},
"encoder": {
"low_dim": {
"core_class": null,
"core_kwargs": {},
"obs_randomizer_class": null,
"obs_randomizer_kwargs": {}
},
"rgb": {
"core_class": "VisualCore",
"core_kwargs": {
"feature_dimension": 64,
"flatten": true,
"backbone_class": "ResNet18Conv",
"backbone_kwargs": {
"pretrained": false,
"input_coord_conv": false
},
"pool_class": "SpatialSoftmax",
"pool_kwargs": {
"num_kp": 32,
"learnable_temperature": false,
"temperature": 1.0,
"noise_std": 0.0,
"output_variance": false
}
},
"obs_randomizer_class": "CropRandomizer",
"obs_randomizer_kwargs": {
"crop_height": 181,
"crop_width": 181,
"num_crops": 1,
"pos_enc": false
}
},
"depth": {
"core_class": "VisualCore",
"core_kwargs": {},
"obs_randomizer_class": null,
"obs_randomizer_kwargs": {}
},
"scan": {
"core_class": "ScanCore",
"core_kwargs": {},
"obs_randomizer_class": null,
"obs_randomizer_kwargs": {}
}
}
}
}

View File

@@ -0,0 +1,218 @@
{
"algo_name": "bc",
"experiment": {
"name": "bc_rnn_image_franka_stack_cosmos",
"validate": false,
"logging": {
"terminal_output_to_txt": true,
"log_tb": true
},
"save": {
"enabled": true,
"every_n_seconds": null,
"every_n_epochs": 20,
"epochs": [],
"on_best_validation": false,
"on_best_rollout_return": false,
"on_best_rollout_success_rate": true
},
"epoch_every_n_steps": 500,
"env": null,
"additional_envs": null,
"render": false,
"render_video": false,
"rollout": {
"enabled": false
}
},
"train": {
"data": null,
"num_data_workers": 4,
"hdf5_cache_mode": "low_dim",
"hdf5_use_swmr": true,
"hdf5_load_next_obs": false,
"hdf5_normalize_obs": false,
"hdf5_filter_key": null,
"hdf5_validation_filter_key": null,
"seq_length": 10,
"pad_seq_length": true,
"frame_stack": 1,
"pad_frame_stack": true,
"dataset_keys": [
"actions",
"rewards",
"dones"
],
"goal_mode": null,
"cuda": true,
"batch_size": 16,
"num_epochs": 600,
"seed": 101
},
"algo": {
"optim_params": {
"policy": {
"optimizer_type": "adam",
"learning_rate": {
"initial": 0.0001,
"decay_factor": 0.1,
"epoch_schedule": [],
"scheduler_type": "multistep"
},
"regularization": {
"L2": 0.0
}
}
},
"loss": {
"l2_weight": 1.0,
"l1_weight": 0.0,
"cos_weight": 0.0
},
"actor_layer_dims": [],
"gaussian": {
"enabled": false,
"fixed_std": false,
"init_std": 0.1,
"min_std": 0.01,
"std_activation": "softplus",
"low_noise_eval": true
},
"gmm": {
"enabled": true,
"num_modes": 5,
"min_std": 0.0001,
"std_activation": "softplus",
"low_noise_eval": true
},
"vae": {
"enabled": false,
"latent_dim": 14,
"latent_clip": null,
"kl_weight": 1.0,
"decoder": {
"is_conditioned": true,
"reconstruction_sum_across_elements": false
},
"prior": {
"learn": false,
"is_conditioned": false,
"use_gmm": false,
"gmm_num_modes": 10,
"gmm_learn_weights": false,
"use_categorical": false,
"categorical_dim": 10,
"categorical_gumbel_softmax_hard": false,
"categorical_init_temp": 1.0,
"categorical_temp_anneal_step": 0.001,
"categorical_min_temp": 0.3
},
"encoder_layer_dims": [
300,
400
],
"decoder_layer_dims": [
300,
400
],
"prior_layer_dims": [
300,
400
]
},
"rnn": {
"enabled": true,
"horizon": 10,
"hidden_dim": 1000,
"rnn_type": "LSTM",
"num_layers": 2,
"open_loop": false,
"kwargs": {
"bidirectional": false
}
},
"transformer": {
"enabled": false,
"context_length": 10,
"embed_dim": 512,
"num_layers": 6,
"num_heads": 8,
"emb_dropout": 0.1,
"attn_dropout": 0.1,
"block_output_dropout": 0.1,
"sinusoidal_embedding": false,
"activation": "gelu",
"supervise_all_steps": false,
"nn_parameter_for_timesteps": true
}
},
"observation": {
"modalities": {
"obs": {
"low_dim": [
"eef_pos",
"eef_quat",
"gripper_pos"
],
"rgb": [
"table_cam"
],
"depth": [],
"scan": []
},
"goal": {
"low_dim": [],
"rgb": [],
"depth": [],
"scan": []
}
},
"encoder": {
"low_dim": {
"core_class": null,
"core_kwargs": {},
"obs_randomizer_class": null,
"obs_randomizer_kwargs": {}
},
"rgb": {
"core_class": "VisualCore",
"core_kwargs": {
"feature_dimension": 64,
"flatten": true,
"backbone_class": "ResNet18Conv",
"backbone_kwargs": {
"pretrained": false,
"input_coord_conv": false
},
"pool_class": "SpatialSoftmax",
"pool_kwargs": {
"num_kp": 32,
"learnable_temperature": false,
"temperature": 1.0,
"noise_std": 0.0,
"output_variance": false
}
},
"obs_randomizer_class": "CropRandomizer",
"obs_randomizer_kwargs": {
"crop_height": 180,
"crop_width": 180,
"num_crops": 1,
"pos_enc": false
}
},
"depth": {
"core_class": "VisualCore",
"core_kwargs": {},
"obs_randomizer_class": null,
"obs_randomizer_kwargs": {}
},
"scan": {
"core_class": "ScanCore",
"core_kwargs": {},
"obs_randomizer_class": null,
"obs_randomizer_kwargs": {}
}
}
}
}

View File

@@ -0,0 +1,101 @@
{
"algo_name": "bc",
"experiment": {
"name": "bc_rnn_low_dim_mindbot_stack",
"validate": false,
"logging": {
"terminal_output_to_txt": true,
"log_tb": true
},
"save": {
"enabled": true,
"every_n_seconds": null,
"every_n_epochs": 100,
"epochs": [],
"on_best_validation": false,
"on_best_rollout_return": false,
"on_best_rollout_success_rate": true
},
"epoch_every_n_steps": 100,
"env": null,
"additional_envs": null,
"render": false,
"render_video": false,
"rollout": {
"enabled": false
}
},
"train": {
"data": null,
"num_data_workers": 4,
"hdf5_cache_mode": "all",
"hdf5_use_swmr": true,
"hdf5_normalize_obs": false,
"hdf5_filter_key": null,
"hdf5_validation_filter_key": null,
"seq_length": 10,
"dataset_keys": [
"actions"
],
"goal_mode": null,
"cuda": true,
"batch_size": 100,
"num_epochs": 2000,
"seed": 101
},
"algo": {
"optim_params": {
"policy": {
"optimizer_type": "adam",
"learning_rate": {
"initial": 0.001,
"decay_factor": 0.1,
"epoch_schedule": [],
"scheduler_type": "multistep"
},
"regularization": {
"L2": 0.0
}
}
},
"loss": {
"l2_weight": 1.0,
"l1_weight": 0.0,
"cos_weight": 0.0
},
"actor_layer_dims": [],
"gmm": {
"enabled": true,
"num_modes": 5,
"min_std": 0.0001,
"std_activation": "softplus",
"low_noise_eval": true
},
"rnn": {
"enabled": true,
"horizon": 10,
"hidden_dim": 400,
"rnn_type": "LSTM",
"num_layers": 2,
"open_loop": false,
"kwargs": {
"bidirectional": false
}
}
},
"observation": {
"modalities": {
"obs": {
"low_dim": [
"eef_pos",
"eef_quat",
"gripper_pos",
"object"
],
"rgb": [],
"depth": [],
"scan": []
}
}
}
}

View File

@@ -0,0 +1,122 @@
# Copyright (c) 2024, MindRobot Project
# SPDX-License-Identifier: BSD-3-Clause
"""Configuration for MindRobot dual-arm robot."""
import isaaclab.sim as sim_utils
from isaaclab.actuators import ImplicitActuatorCfg
from isaaclab.assets import ArticulationCfg
##
# ✅ 使用你的本地 USD 绝对路径
##
MINDBOT_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
# =====================================================
# ✅ 你的本地 USD 文件路径
# =====================================================
usd_path="C:/Users/PC/workpalce/maic_usd_assets/robots/mindrobot-1105-lab/mindrobot_cd2.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_depenetration_velocity=1.0,
linear_damping=0.5,
angular_damping=0.5,
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
# Allow root to be affected by physics (gravity) so robot won't hover
fix_root_link=False,
enabled_self_collisions=False,
solver_position_iteration_count=16,
solver_velocity_iteration_count=8,
stabilization_threshold=1e-6,
),
collision_props=sim_utils.CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,
rest_offset=0,
),
),
init_state=ArticulationCfg.InitialStateCfg(
joint_pos={
# ====== 左臂关节(主控臂)======
"l_joint1": 2.3562, # 135°
"l_joint2": -1.2217, # -70°
"l_joint3": -1.5708, # -90°
"l_joint4": 1.5708, # 90°
"l_joint5": 1.5708, # 90°
"l_joint6": -1.2217, # -70°
# ====== 右臂关节(静止)======
"r_joint1": 0.0,
"r_joint2": 0.0,
"r_joint3": 0.0,
"r_joint4": 0.0,
"r_joint5": 0.0,
"r_joint6": 0.0,
# ====== 左手夹爪 ======
"left_hand_joint_left": 0.0, # 0.0=打开, -0.03=闭合
"left_hand_joint_right": 0.0, # 0.0=打开, 0.03=闭合
# ====== 右手夹爪 ======
"right_hand_joint_left": 0.0,
"right_hand_joint_right": 0.0,
# ====== 躯干 ======
"PrismaticJoint": 0.26,
# ====== 头部 ======
"head_revoluteJoint": 0.0,
},
# Lower the spawn height to sit on the ground (was 0.05m above ground)
pos=(0, 0, 0.0),
),
actuators={
"left_arm": ImplicitActuatorCfg(
joint_names_expr=["l_joint[1-6]"],
effort_limit_sim=100.0,
velocity_limit_sim=100.0,
# ✅ IK 控制需要高刚度
stiffness=10000.0,
damping=1000.0,
),
"right_arm": ImplicitActuatorCfg(
joint_names_expr=["r_joint[1-6]"],
effort_limit_sim=100.0,
velocity_limit_sim=100.0,
stiffness=10000.0,
damping=1000.0,
),
"head": ImplicitActuatorCfg(
joint_names_expr=["head_revoluteJoint"],
stiffness=10000.0,
damping=1000.0,
),
"trunk": ImplicitActuatorCfg(
joint_names_expr=["PrismaticJoint"],
stiffness=40000.0,
damping=4000.0,
effort_limit_sim=10000.0,
velocity_limit_sim=0.2,
),
"wheels": ImplicitActuatorCfg(
joint_names_expr=[".*_revolute_Joint"],
stiffness=0.0,
damping=100.0,
effort_limit_sim=200.0,
velocity_limit_sim=50.0,
),
# ✅ 夹爪:高刚度确保精准控制
"grippers": ImplicitActuatorCfg(
joint_names_expr=[".*_hand_joint.*"],
stiffness=10000.0,
damping=1000.0,
effort_limit_sim=50.0,
velocity_limit_sim=50.0,
),
},
)
##
# ✅ 专用于 IK 控制的高 PD 版本(可选但推荐)
##
MINDBOT_HIGH_PD_CFG = MINDBOT_CFG.copy()
MINDBOT_HIGH_PD_CFG.actuators["left_arm"].stiffness = 40000.0
MINDBOT_HIGH_PD_CFG.actuators["left_arm"].damping = 4000.0

View File

@@ -0,0 +1,271 @@
# Copyright (c) 2024, MindRobot Project
# SPDX-License-Identifier: BSD-3-Clause
"""MindRobot left arm IK-Rel environment config for teleoperation."""
from __future__ import annotations
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
import isaaclab.sim as sim_utils
from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg
from isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg
from isaaclab.devices import DevicesCfg
from isaaclab.devices.keyboard import Se3KeyboardCfg
from isaaclab.devices.spacemouse import Se3SpaceMouseCfg
from isaaclab.devices.gamepad import Se3GamepadCfg
from isaaclab.envs import ManagerBasedRLEnvCfg
from isaaclab.envs.mdp.actions.actions_cfg import (
BinaryJointPositionActionCfg,
DifferentialInverseKinematicsActionCfg,
)
from isaaclab.managers import ObservationGroupCfg as ObsGroup
from isaaclab.managers import ObservationTermCfg as ObsTerm
from isaaclab.managers import TerminationTermCfg as DoneTerm
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.sensors.frame_transformer.frame_transformer_cfg import FrameTransformerCfg
from isaaclab.sensors.frame_transformer.frame_transformer_cfg import OffsetCfg
from isaaclab.sim.schemas.schemas_cfg import RigidBodyPropertiesCfg
from isaaclab.sim.spawners.from_files.from_files_cfg import GroundPlaneCfg
from isaaclab.utils import configclass
from isaaclab.markers.config import FRAME_MARKER_CFG
from isaaclab.devices.openxr import XrCfg
# 导入基础配置和MDP函数
from isaaclab_tasks.manager_based.manipulation.stack import mdp
# 导入 MindRobot 资产
from .mindrobot_cfg import MINDBOT_HIGH_PD_CFG
# 在文件开头添加
import isaaclab.utils.assets as assets_utils
# # 然后在 scene 配置中使用
# spawn=sim_utils.UsdFileCfg(
# usd_path=f"{assets_utils.ISAAC_NUCLEUS_DIR}/Props/Mounts/SeattleLabTable/table_instanceable.usd"
# ),
# =====================================================================
# Scene Configuration
# =====================================================================
@configclass
class MindRobotTeleopSceneCfg(InteractiveSceneCfg):
"""Minimal scene for MindRobot teleoperation: robot + table + optional cube."""
# Ground plane
plane = AssetBaseCfg(
prim_path="/World/GroundPlane",
init_state=AssetBaseCfg.InitialStateCfg(pos=[0, 0, -1.05]),
spawn=GroundPlaneCfg(),
)
# # Table
# table = AssetBaseCfg(
# prim_path="{ENV_REGEX_NS}/Table",
# init_state=AssetBaseCfg.InitialStateCfg(pos=[0.5, 0, 0], rot=[0.707, 0, 0, 0.707]),
# spawn=sim_utils.UsdFileCfg(
# usd_path=f"{assets_utils.ISAAC_NUCLEUS_DIR}/Props/Mounts/SeattleLabTable/table_instanceable.usd"
# ),
# )
# Optional: Single cube for testing (can be removed if not needed)
cube = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Cube",
spawn=sim_utils.CuboidCfg(
size=(0.04, 0.04, 0.04),
rigid_props=RigidBodyPropertiesCfg(),
mass_props=sim_utils.MassPropertiesCfg(mass=0.1),
collision_props=sim_utils.CollisionPropertiesCfg(),
visual_material=sim_utils.PreviewSurfaceCfg(
diffuse_color=(1.0, 0.0, 0.0)
),
),
init_state=RigidObjectCfg.InitialStateCfg(pos=(0.5, 0.0, 0.45)),
)
# MindRobot
robot: ArticulationCfg = MINDBOT_HIGH_PD_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
# Lighting
light = AssetBaseCfg(
prim_path="/World/light",
spawn=sim_utils.DomeLightCfg(color=(0.75, 0.75, 0.75), intensity=3000.0),
)
# End-effector frame transformer
ee_frame: FrameTransformerCfg = None # Will be set in __post_init__
# =====================================================================
# Actions Configuration
# =====================================================================
@configclass
class MindRobotTeleopActionsCfg:
"""Actions for MindRobot left arm IK teleoperation."""
# Left arm IK control
arm_action = DifferentialInverseKinematicsActionCfg(
asset_name="robot",
joint_names=["l_joint[1-6]"],
body_name="Link_6", # Last link of left arm
controller=DifferentialIKControllerCfg(
command_type="pose",
use_relative_mode=True,
ik_method="dls",
),
scale=0.5,
body_offset=DifferentialInverseKinematicsActionCfg.OffsetCfg(
pos=[0.0, 0.0, 0.0]
),
)
# Left gripper control (binary: open/close)
gripper_action = BinaryJointPositionActionCfg(
asset_name="robot",
joint_names=["left_hand_joint_left", "left_hand_joint_right"],
open_command_expr={
"left_hand_joint_left": 0.0,
"left_hand_joint_right": 0.0,
},
close_command_expr={
"left_hand_joint_left": -0.03,
"left_hand_joint_right": 0.03,
},
)
# =====================================================================
# Observations Configuration
# =====================================================================
@configclass
class MindRobotTeleopObsCfg:
"""Minimal observations for MindRobot teleoperation."""
@configclass
class PolicyCfg(ObsGroup):
"""Observations for policy group - only robot state, no cube dependencies."""
actions = ObsTerm(func=mdp.last_action)
joint_pos = ObsTerm(func=mdp.joint_pos_rel)
joint_vel = ObsTerm(func=mdp.joint_vel_rel)
eef_pos = ObsTerm(func=mdp.ee_frame_pos)
eef_quat = ObsTerm(func=mdp.ee_frame_quat)
gripper_pos = ObsTerm(func=mdp.gripper_pos)
def __post_init__(self):
self.enable_corruption = False
self.concatenate_terms = False
# observation groups
policy: PolicyCfg = PolicyCfg()
# =====================================================================
# Terminations Configuration
# =====================================================================
@configclass
class MindRobotTeleopTerminationsCfg:
"""Minimal terminations for teleoperation - only time_out or none."""
# Optional: Keep time_out for safety, or remove entirely
time_out = DoneTerm(func=mdp.time_out, time_out=True)
# =====================================================================
# Main Environment Configuration
# =====================================================================
@configclass
class EmptyCfg:
pass
@configclass
class MindRobotLeftArmIKEnvCfg(ManagerBasedRLEnvCfg):
"""MindRobot 左臂 IK-Rel 遥操作环境配置(最小化版本)。"""
# Scene settings
scene: MindRobotTeleopSceneCfg = MindRobotTeleopSceneCfg(
num_envs=1,
env_spacing=2.5,
)
# Basic settings
observations: MindRobotTeleopObsCfg = MindRobotTeleopObsCfg()
actions: MindRobotTeleopActionsCfg = MindRobotTeleopActionsCfg()
# MDP settings
terminations: MindRobotTeleopTerminationsCfg = MindRobotTeleopTerminationsCfg()
# Unused managers
commands: EmptyCfg = EmptyCfg()
rewards: EmptyCfg = EmptyCfg()
events: EmptyCfg = EmptyCfg()
curriculum: EmptyCfg = EmptyCfg()
# XR configuration for hand tracking (if needed)
xr: XrCfg = XrCfg(
anchor_pos=(-0.1, -0.5, -1.05),
anchor_rot=(0.866, 0, 0, -0.5),
)
def __post_init__(self):
"""Post initialization."""
super().__post_init__()
# General settings
self.decimation = 2
self.episode_length_s = 50.0
# Simulation settings
self.sim.dt = 0.01 # 100Hz
self.sim.render_interval = 2
# Set MindRobot
self.scene.robot = MINDBOT_HIGH_PD_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
# Configure end-effector frame transformer
marker_cfg = FRAME_MARKER_CFG.copy()
marker_cfg.markers["frame"].scale = (0.1, 0.1, 0.1)
marker_cfg.prim_path = "/Visuals/FrameTransformer"
self.scene.ee_frame = FrameTransformerCfg(
prim_path="{ENV_REGEX_NS}/Robot/rm_65_fb_left/base_link",
debug_vis=False,
visualizer_cfg=marker_cfg,
target_frames=[
FrameTransformerCfg.FrameCfg(
prim_path="{ENV_REGEX_NS}/Robot/rm_65_fb_left/Link_6",
name="end_effector",
offset=OffsetCfg(
pos=[0.0, 0.0, 0.0],
),
),
],
)
# Configure teleoperation devices
self.teleop_devices = DevicesCfg(
devices={
"keyboard": Se3KeyboardCfg(
pos_sensitivity=0.05,
rot_sensitivity=0.05,
sim_device=self.sim.device,
),
"spacemouse": Se3SpaceMouseCfg(
pos_sensitivity=0.05,
rot_sensitivity=0.05,
sim_device=self.sim.device,
),
"gamepad": Se3GamepadCfg(
pos_sensitivity=0.1,
rot_sensitivity=0.1,
sim_device=self.sim.device,
),
}
)
# Gripper parameters for status checking
self.gripper_joint_names = ["left_hand_joint_left", "left_hand_joint_right"]
self.gripper_open_val = 0.0
self.gripper_threshold = 0.005

View File

@@ -21,7 +21,10 @@ from isaaclab.managers import CurriculumTermCfg as CurrTerm
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.utils import configclass
from isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg
from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg, BinaryJointPositionActionCfg
from isaaclab.envs.mdp.actions.actions_cfg import (
DifferentialInverseKinematicsActionCfg,
BinaryJointPositionActionCfg,
)
from isaaclab.sensors import CameraCfg
from . import mdp
@@ -34,10 +37,13 @@ from mindbot.robot.mindbot import MINDBOT_CFG
# ====== 其他物体配置 ======
from isaaclab.sim.spawners.from_files.from_files_cfg import UsdFileCfg
from isaaclab.sim.schemas.schemas_cfg import RigidBodyPropertiesCfg, CollisionPropertiesCfg
from isaaclab.sim.schemas.schemas_cfg import (
RigidBodyPropertiesCfg,
CollisionPropertiesCfg,
)
TABLE_CFG=RigidObjectCfg(
TABLE_CFG = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Table",
init_state=RigidObjectCfg.InitialStateCfg(
pos=[0.95, -0.3, 0.005],
@@ -46,17 +52,17 @@ TABLE_CFG=RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/table/Table_C.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/table/Table_C.usd",
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -65,30 +71,30 @@ LID_CFG = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Lid",
init_state=RigidObjectCfg.InitialStateCfg(
# pos=[0.9523,-0.2512,1.0923],
pos=[0.803 , -0.25, 1.0282],#(0.9988, -0.2977, 1.0498633)
pos=[0.803, -0.25, 1.0282], # (0.9988, -0.2977, 1.0498633)
# rot=[-0.7071, 0.0, 0.0, 0.7071],
rot=[0.0, 0.0, 0.0, 1.0],
lin_vel=[0.0, 0.0, 0.0],
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/assets/Collected_equipment001/Equipment/tube1.usd",
usd_path="/home/maic/LYT/maic_usd_assets/assets/Collected_equipment001/Equipment/tube1.usd",
# scale=(0.2, 0.2, 0.2),
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
max_angular_velocity=1000.0,
max_linear_velocity=1000.0,
max_depenetration_velocity=0.5,#original 5.0
linear_damping=5.0, #original 0.5
angular_damping=5.0, #original 0.5
max_depenetration_velocity=0.5, # original 5.0
linear_damping=5.0, # original 0.5
angular_damping=5.0, # original 0.5
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -104,7 +110,7 @@ LID_CFG = RigidObjectCfg(
# ang_vel=[0.0, 0.0, 0.0],
# ),
# spawn=UsdFileCfg(
# usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/centrifuge/Lid_B.usd",
# usd_path="/home/maic/LYT/maic_usd_assets/equipment/centrifuge/Lid_B.usd",
# # scale=(0.2, 0.2, 0.2),
# rigid_props=RigidBodyPropertiesCfg(
# rigid_body_enabled= True,
@@ -127,9 +133,9 @@ LID_CFG = RigidObjectCfg(
CENTRIFUGE_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/centrifuge/centrifuge.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/centrifuge/centrifuge.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
disable_gravity=False,
max_depenetration_velocity=1.0,
linear_damping=0.5,
angular_damping=0.5,
@@ -140,45 +146,41 @@ CENTRIFUGE_CFG = ArticulationCfg(
solver_velocity_iteration_count=16,
stabilization_threshold=1e-6,
# 【重要】必须要固定底座,否则机器人按盖子时,离心机会翻倒
# fix_root_link=True,
# fix_root_link=True,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
init_state=ArticulationCfg.InitialStateCfg(
# 1. 参照机器人配置,在这里定义初始关节角度
joint_pos={
"r1": math.radians(0.0), # 转子位置(无关紧要)
"r1": math.radians(0.0), # 转子位置(无关紧要)
# 【关键修改】:初始让盖子处于打开状态
# 您的 USD 限位是 (-100, 0)-100度为最大开启
"r2": math.radians(-100.0),
"r2": math.radians(-100.0),
},
pos=(0.80, -0.25, 0.8085),#(0.95, -0.3, 0.8085)
pos=(0.80, -0.25, 0.8085), # (0.95, -0.3, 0.8085)
rot=[-0.7071, 0.0, 0.0, 0.7071],
# rot=[0.0, 0.0, 0.0, 1.0],
),
actuators={
"lid_passive_mechanism": ImplicitActuatorCfg(
joint_names_expr=["r2"],
# 【关键差异说明】
# 机器人的手臂 stiffness 是 10000.0,因为机器人需要精准定位且不晃动。
#
#
# 但是!离心机盖子如果设为 10000它就会像焊死在空中一样机器人根本按不动。
# 这里设为 200.0 左右:
# 1. 力度足以克服重力,让盖子初始保持打开。
# 2. 力度又足够软,当机器人用力下压时,盖子会顺从地闭合。
stiffness=200.0,
stiffness=200.0,
# 阻尼:给一点阻力,模拟液压杆手感,防止像弹簧一样乱晃
damping=20.0,
damping=20.0,
# 确保力矩上限不要太小,否则托不住盖子
effort_limit_sim=1000.0,
effort_limit_sim=1000.0,
velocity_limit_sim=100.0,
),
# 转子可以硬一点,不需要被机器人按动
@@ -187,14 +189,14 @@ CENTRIFUGE_CFG = ArticulationCfg(
stiffness=0.0,
damping=10.0,
),
}
},
)
ROOM_CFG = AssetBaseCfg(
prim_path="{ENV_REGEX_NS}/Room",
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/twinlab/MIC_sim-3.0/244_140/room.usd",
usd_path="/home/maic/LYT/maic_usd_assets/twinlab/MIC_sim-3.0/244_140/room.usd",
),
)
@@ -217,7 +219,9 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# Room: AssetBaseCfg = ROOM_CFG.replace(prim_path="{ENV_REGEX_NS}/Room")
Mindbot: ArticulationCfg = MINDBOT_CFG.replace(prim_path="{ENV_REGEX_NS}/Mindbot")
table: RigidObjectCfg = TABLE_CFG.replace(prim_path="{ENV_REGEX_NS}/Table")
centrifuge: ArticulationCfg = CENTRIFUGE_CFG.replace(prim_path="{ENV_REGEX_NS}/centrifuge")
centrifuge: ArticulationCfg = CENTRIFUGE_CFG.replace(
prim_path="{ENV_REGEX_NS}/centrifuge"
)
lid: RigidObjectCfg = LID_CFG.replace(prim_path="{ENV_REGEX_NS}/Lid")
# lights
dome_light = AssetBaseCfg(
@@ -236,7 +240,7 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# )
"""
# left_hand_camera=CameraCfg(
# prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_fb_left/Link_6/robot___left_8_02/cam_left_hand",
# prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_fb_left/Link_6/robot___left_8_02/cam_left_hand",
# update_period=1/120,
# height=480,
# width=640,
@@ -244,7 +248,7 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# spawn=None,
# )
# right_hand_camera=CameraCfg(
# prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_b_right/Link6/robot___right_8_2/cam_right_hand",
# prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_b_right/Link6/robot___right_8_2/cam_right_hand",
# update_period=1/120,
# height=480,
# width=640,
@@ -252,7 +256,7 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# spawn=None,
# )
# head_camera=CameraCfg(
# prim_path="{ENV_REGEX_NS}/Mindbot/robot_head/cam_head",
# prim_path="{ENV_REGEX_NS}/Mindbot/robot_head/cam_head",
# update_period=1/120,
# height=480,
# width=640,
@@ -260,18 +264,23 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# spawn=None,
# )
# chest_camera=CameraCfg(
# prim_path="{ENV_REGEX_NS}/Mindbot/robot_trunk/cam_chest",
# prim_path="{ENV_REGEX_NS}/Mindbot/robot_trunk/cam_chest",
# update_period=1/120,
# height=480,
# width=640,
# data_types=["rgb"],
# spawn=None,
# )
##
# MDP settings
##
def left_gripper_pos_w(env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")) -> torch.Tensor:
def left_gripper_pos_w(
env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")
) -> torch.Tensor:
asset = env.scene[asset_cfg.name]
body_ids, _ = asset.find_bodies(["left_hand_body"], preserve_order=True)
pos_w = asset.data.body_pos_w[:, body_ids[0]] - env.scene.env_origins
@@ -294,14 +303,12 @@ class ActionsCfg:
# ),
# scale=(0.01, 0.01, 0.01, 0.025, 0.025, 0.025),
# )
right_arm_fixed = mdp.JointPositionActionCfg(
asset_name="Mindbot",
joint_names=["r_joint[1-6]"], # 对应 l_joint1 到 l_joint6
joint_names=["r_joint[1-6]"], # 对应 l_joint1 到 l_joint6
# 1. 缩放设为 0这让 RL 策略无法控制它,它不会动
scale=0.0,
scale=0.0,
# 2. 偏移设为你的目标角度(弧度):这告诉电机“永远停在这里”
# 对应 (135, -70, -90, 90, 90, -70)
offset={
@@ -317,34 +324,35 @@ class ActionsCfg:
grippers_position = mdp.BinaryJointPositionActionCfg(
asset_name="Mindbot",
joint_names=["left_hand_joint_left", "left_hand_joint_right"],
# 修正:使用字典格式
# open_command_expr={"关节名正则": 值}
open_command_expr={"left_hand_joint_left": 0.0, "left_hand_joint_right": 0.0},
# close_command_expr={"关节名正则": 值}
close_command_expr={"left_hand_joint_left": -0.03, "left_hand_joint_right": 0.03},
close_command_expr={
"left_hand_joint_left": -0.03,
"left_hand_joint_right": 0.03,
},
)
trunk_position = mdp.JointPositionActionCfg(
asset_name="Mindbot",
joint_names=["PrismaticJoint"],
scale=0.00,
offset=0.24, # 0.3
clip=None
offset=0.24, # 0.3
clip=None,
)
centrifuge_lid_passive = mdp.JointPositionActionCfg(
asset_name="centrifuge", # 对应场景中的名称
asset_name="centrifuge", # 对应场景中的名称
joint_names=["r2"],
# 将 scale 设为 0意味着 RL 算法输出的任何值都会被乘 0即无法干扰它
scale=0.00,
scale=0.00,
# 将 offset 设为目标角度,这会成为 PD 控制器的恒定 Target
offset= -1.7453,
clip=None
offset=-1.7453,
clip=None,
)
@configclass
class ObservationsCfg:
"""Observation specifications for the MDP."""
@@ -353,15 +361,29 @@ class ObservationsCfg:
class PolicyCfg(ObsGroup):
"""Observations for policy group."""
mindbot_joint_pos_rel = ObsTerm(func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_pos = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_quat = ObsTerm(func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
left_gripper_pos = ObsTerm(func=left_gripper_pos_w,
params={"asset_cfg": SceneEntityCfg("Mindbot", body_names=["left_hand_body"])})
lid_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")})
centrifuge_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("centrifuge")})
mindbot_joint_pos_rel = ObsTerm(
func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_pos = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_quat = ObsTerm(
func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
left_gripper_pos = ObsTerm(
func=left_gripper_pos_w,
params={
"asset_cfg": SceneEntityCfg("Mindbot", body_names=["left_hand_body"])
},
)
lid_pos_abs = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")}
)
centrifuge_pos_abs = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("centrifuge")}
)
def __post_init__(self) -> None:
self.enable_corruption = False
self.concatenate_terms = True
@@ -409,29 +431,36 @@ class EventCfg:
"velocity_range": (0.0, 0.0),
},
)
reset_table=EventTerm(func=mdp.reset_root_state_uniform,mode="reset",
params={"asset_cfg": SceneEntityCfg("table"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_table = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("table"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_centrifuge = EventTerm(
func=mdp.reset_root_state_uniform,
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("centrifuge"),
# "pose_range": {"x": (-0.07, 0.07), "y": (-0.07, 0.07), "yaw": (-0.1, 0.1)},
"pose_range": {"x": (0.0, 0.0), "y": (0.0, 0.0), "z": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)}
}
)
"asset_cfg": SceneEntityCfg("centrifuge"),
# "pose_range": {"x": (-0.07, 0.07), "y": (-0.07, 0.07), "yaw": (-0.1, 0.1)},
"pose_range": {"x": (0.0, 0.0), "y": (0.0, 0.0), "z": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_lid = EventTerm(
func=mdp.reset_root_state_uniform,
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("lid"),
# "pose_range": {"x": (-0.03, 0.03), "y": (-0.03, 0.03), "yaw": (-1.5, 1.5)},
"pose_range": {"x": (0.0, 0.0), "y": (0.0, 0.0), "z": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)}
}
)
"asset_cfg": SceneEntityCfg("lid"),
# "pose_range": {"x": (-0.03, 0.03), "y": (-0.03, 0.03), "yaw": (-1.5, 1.5)},
"pose_range": {"x": (0.0, 0.0), "y": (0.0, 0.0), "z": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
@configclass
@@ -444,12 +473,12 @@ class RewardsCfg:
"lid_cfg": SceneEntityCfg("lid"),
"robot_cfg": SceneEntityCfg("Mindbot"),
"gripper_body_name": "right_hand_body",
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"lid_handle_axis": (0.0, 1.0, 0.0),
"max_angle_deg": 85.0, # 允许60度内的偏差
},
weight=5.0 #original 5.0
weight=5.0, # original 5.0
)
# stage 2
@@ -462,9 +491,9 @@ class RewardsCfg:
"left_gripper_name": "right_hand_l",
"right_gripper_name": "right_hand__r",
"height_offset": 0.115, # Z方向lid 上方 0.1m
"std": 0.3, # 位置对齐的容忍度
"std": 0.3, # 位置对齐的容忍度
},
weight=3.0 #original 3.0
weight=3.0, # original 3.0
)
approach_lid_penalty = RewTerm(
func=mdp.gripper_lid_distance_penalty,
@@ -477,7 +506,7 @@ class RewardsCfg:
},
# weight 为负数表示惩罚。
# 假设距离 0.5m,惩罚就是 -0.5 * 2.0 = -1.0 分。
weight=-1.0
weight=-1.0,
)
# # 【新增】精细对齐 (引导进入 2cm 圈)
# gripper_lid_fine_alignment = RewTerm(
@@ -493,7 +522,7 @@ class RewardsCfg:
# weight=10.0 # 高权重
# )
# gripper_close_interaction = RewTerm(
# gripper_close_interaction = RewTerm(
# func=mdp.gripper_close_when_near,
# params={
# "lid_cfg": SceneEntityCfg("lid"),
@@ -527,12 +556,10 @@ class RewardsCfg:
# "std": 0.1
# },
# # 权重设大一点,告诉它这是最终目标
# weight=10.0
# weight=10.0
# )
@configclass
class TerminationsCfg:
"""Termination terms for the MDP."""
@@ -543,7 +570,7 @@ class TerminationsCfg:
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("Mindbot"), "maximum_height": 2.0},
)
lid_fly_away = DoneTerm(
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("lid"), "maximum_height": 2.0},
@@ -552,25 +579,25 @@ class TerminationsCfg:
# 新增:盖子掉落判定
# 如果盖子掉回桌面(高度接近初始高度),且已经运行了一段时间(避开刚开始重置的瞬间)
lid_dropped = DoneTerm(
func=mdp.base_height_failure, # 复用高度判定函数
func=mdp.base_height_failure, # 复用高度判定函数
params={
"asset_cfg": SceneEntityCfg("lid"),
"minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
"asset_cfg": SceneEntityCfg("lid"),
"minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
},
)
##
# Environment configuration
##
@configclass
class CurriculumCfg:
pass
# action_rate = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "action_rate", "weight": -1e-1, "num_steps": 10000})
# joint_vel = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "joint_vel", "weight": -1e-1, "num_steps": 10000})
@@ -579,10 +606,10 @@ class CurriculumCfg:
# params={
# # 路径rewards管理器 -> 你的奖励项名 -> params字典 -> std键
# "address": "rewards.gripper_lid_position_alignment.params.std",
# # 修改逻辑:使用我们刚才写的函数
# "modify_fn": mdp.annealing_std,
# # 传给函数的参数
# "modify_params": {
# "start_step": 00, # 约 600 轮
@@ -593,6 +620,7 @@ class CurriculumCfg:
# }
# )
@configclass
class MindbotEnvCfg(ManagerBasedRLEnvCfg):
# Scene settings
@@ -610,20 +638,20 @@ class MindbotEnvCfg(ManagerBasedRLEnvCfg):
def __post_init__(self) -> None:
"""Post initialization."""
# general settings
self.decimation = 4 #original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.decimation = 4 # original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.episode_length_s = 10
# viewer settings
self.viewer.eye = (3.5, 0.0, 13.2)#(3.5, 0.0, 3.2)
self.viewer.eye = (3.5, 0.0, 13.2) # (3.5, 0.0, 3.2)
# simulation settings
self.sim.dt = 1 / 120 #original 1 / 60
self.sim.dt = 1 / 120 # original 1 / 60
self.sim.render_interval = self.decimation
# # 1. 基础堆内存
self.sim.physx.gpu_heap_capacity = 256 * 1024 * 1024 # 256MB
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_temp_buffer_capacity = 128 * 1024 * 1024
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
# # 5. 聚合对容量 (针对复杂的 Articulation)
self.sim.physx.gpu_found_lost_pairs_capacity = 16 * 1024 * 1024
self.sim.physx.gpu_found_lost_aggregate_pairs_capacity = 16 * 1024 * 1024

View File

@@ -21,7 +21,10 @@ from isaaclab.managers import CurriculumTermCfg as CurrTerm
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.utils import configclass
from isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg
from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg, BinaryJointPositionActionCfg
from isaaclab.envs.mdp.actions.actions_cfg import (
DifferentialInverseKinematicsActionCfg,
BinaryJointPositionActionCfg,
)
from . import mdp
@@ -33,10 +36,13 @@ from mindbot.robot.mindbot import MINDBOT_CFG
# ====== 其他物体配置 ======
from isaaclab.sim.spawners.from_files.from_files_cfg import UsdFileCfg
from isaaclab.sim.schemas.schemas_cfg import RigidBodyPropertiesCfg, CollisionPropertiesCfg
from isaaclab.sim.schemas.schemas_cfg import (
RigidBodyPropertiesCfg,
CollisionPropertiesCfg,
)
TABLE_CFG=RigidObjectCfg(
TABLE_CFG = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Table",
init_state=RigidObjectCfg.InitialStateCfg(
pos=[0.95, -0.3, 0.005],
@@ -45,17 +51,17 @@ TABLE_CFG=RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/table/Table_C.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/table/Table_C.usd",
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -69,23 +75,23 @@ LID_CFG = RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/ultrasound/ultrasound_lid.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/ultrasound/ultrasound_lid.usd",
# scale=(0.2, 0.2, 0.2),
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
max_angular_velocity=1000.0,
max_linear_velocity=1000.0,
max_depenetration_velocity=0.5,#original 5.0
linear_damping=5.0, #original 0.5
angular_damping=5.0, #original 0.5
max_depenetration_velocity=0.5, # original 5.0
linear_damping=5.0, # original 0.5
angular_damping=5.0, # original 0.5
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -93,13 +99,12 @@ LID_CFG = RigidObjectCfg(
ULTRASOUND_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/ultrasound/ultrasound.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/ultrasound/ultrasound.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_depenetration_velocity=1.0
disable_gravity=False, max_depenetration_velocity=1.0
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=False,#
enabled_self_collisions=False, #
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
stabilization_threshold=1e-6,
@@ -112,13 +117,12 @@ ULTRASOUND_CFG = ArticulationCfg(
"passive_damper": ImplicitActuatorCfg(
# ".*" 表示匹配该USD文件内的所有关节无论是轮子、屏幕转轴还是其他
joint_names_expr=[".*"],
stiffness=0.0,
damping=1000.0,
effort_limit_sim=10000.0,
stiffness=0.0,
damping=1000.0,
effort_limit_sim=10000.0,
velocity_limit_sim=100.0,
),
}
},
)
##
@@ -139,7 +143,9 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# robot
Mindbot: ArticulationCfg = MINDBOT_CFG.replace(prim_path="{ENV_REGEX_NS}/Mindbot")
table: RigidObjectCfg = TABLE_CFG.replace(prim_path="{ENV_REGEX_NS}/Table")
ultrasound: ArticulationCfg = ULTRASOUND_CFG.replace(prim_path="{ENV_REGEX_NS}/ultrasound")
ultrasound: ArticulationCfg = ULTRASOUND_CFG.replace(
prim_path="{ENV_REGEX_NS}/ultrasound"
)
lid: RigidObjectCfg = LID_CFG.replace(prim_path="{ENV_REGEX_NS}/Lid")
# lights
dome_light = AssetBaseCfg(
@@ -152,7 +158,10 @@ class MindbotSceneCfg(InteractiveSceneCfg):
# MDP settings
##
def left_gripper_pos_w(env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")) -> torch.Tensor:
def left_gripper_pos_w(
env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")
) -> torch.Tensor:
asset = env.scene[asset_cfg.name]
body_ids, _ = asset.find_bodies(["left_hand_body"], preserve_order=True)
pos_w = asset.data.body_pos_w[:, body_ids[0]] - env.scene.env_origins
@@ -167,11 +176,11 @@ class ActionsCfg:
left_arm_ee = DifferentialInverseKinematicsActionCfg(
asset_name="Mindbot",
joint_names=["l_joint[1-6]"], # 左臂的6个关节
body_name="left_hand_body", # 末端执行器body名称
body_name="left_hand_body", # 末端执行器body名称
controller=DifferentialIKControllerCfg(
command_type="pose", # 控制位置+姿态
use_relative_mode=True, # 相对模式:动作是增量
ik_method="dls", # Damped Least Squares方法
command_type="pose", # 控制位置+姿态
use_relative_mode=True, # 相对模式:动作是增量
ik_method="dls", # Damped Least Squares方法
),
scale=(0.01, 0.01, 0.01, 0.025, 0.025, 0.025),
)
@@ -197,22 +206,22 @@ class ActionsCfg:
grippers_position = mdp.BinaryJointPositionActionCfg(
asset_name="Mindbot",
joint_names=["left_hand_joint_left", "left_hand_joint_right"],
# 修正:使用字典格式
# open_command_expr={"关节名正则": 值}
open_command_expr={"left_hand_joint_left": 0.0, "left_hand_joint_right": 0.0},
# close_command_expr={"关节名正则": 值}
close_command_expr={"left_hand_joint_left": -0.03, "left_hand_joint_right": 0.03},
close_command_expr={
"left_hand_joint_left": -0.03,
"left_hand_joint_right": 0.03,
},
)
trunk_position = mdp.JointPositionActionCfg(
asset_name="Mindbot",
joint_names=["PrismaticJoint"],
scale=0.00,
offset=0.3,
clip=None
clip=None,
)
@@ -224,15 +233,29 @@ class ObservationsCfg:
class PolicyCfg(ObsGroup):
"""Observations for policy group."""
mindbot_joint_pos_rel = ObsTerm(func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_pos = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_quat = ObsTerm(func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
left_gripper_pos = ObsTerm(func=left_gripper_pos_w,
params={"asset_cfg": SceneEntityCfg("Mindbot", body_names=["left_hand_body"])})
lid_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")})
ultrasound_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("ultrasound")})
mindbot_joint_pos_rel = ObsTerm(
func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_pos = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_quat = ObsTerm(
func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
left_gripper_pos = ObsTerm(
func=left_gripper_pos_w,
params={
"asset_cfg": SceneEntityCfg("Mindbot", body_names=["left_hand_body"])
},
)
lid_pos_abs = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")}
)
ultrasound_pos_abs = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("ultrasound")}
)
def __post_init__(self) -> None:
self.enable_corruption = False
self.concatenate_terms = True
@@ -244,6 +267,7 @@ class ObservationsCfg:
@configclass
class EventCfg:
"""Configuration for events."""
# reset_mindbot_root=EventTerm(
# func=mdp.reset_root_state_uniform,
# mode="reset",
@@ -273,18 +297,39 @@ class EventCfg:
"velocity_range": (0.0, 0.0),
},
)
reset_table=EventTerm(func=mdp.reset_root_state_uniform,mode="reset",
params={"asset_cfg": SceneEntityCfg("table"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_ultrasound = EventTerm(func=mdp.reset_root_state_uniform, mode="reset",
params={"asset_cfg": SceneEntityCfg("ultrasound"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_lid = EventTerm(func=mdp.reset_root_state_uniform, mode="reset",
params={"asset_cfg": SceneEntityCfg("lid"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_table = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("table"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_ultrasound = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("ultrasound"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_lid = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("lid"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
@configclass
class RewardsCfg:
"""Reward terms for the MDP."""
# 姿态对齐奖励: stage 1
# gripper_lid_orientation_alignment = RewTerm(
# func=mdp.gripper_lid_orientation_alignment,
@@ -292,8 +337,8 @@ class RewardsCfg:
# "lid_cfg": SceneEntityCfg("lid"),
# "robot_cfg": SceneEntityCfg("Mindbot"),
# "gripper_body_name": "left_hand_body",
# "gripper_forward_axis": (0.0, 0.0, 1.0),
# "gripper_width_axis": (0.0, 1.0, 0.0),
# "gripper_forward_axis": (0.0, 0.0, 1.0),
# "gripper_width_axis": (0.0, 1.0, 0.0),
# "lid_handle_axis": (0.0, 1.0, 0.0)
# },
# weight=1.0
@@ -305,12 +350,12 @@ class RewardsCfg:
"lid_cfg": SceneEntityCfg("lid"),
"robot_cfg": SceneEntityCfg("Mindbot"),
"gripper_body_name": "left_hand_body",
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"lid_handle_axis": (0.0, 1.0, 0.0),
"max_angle_deg": 85.0, # 允许60度内的偏差
},
weight=5
weight=5,
)
# stage 2
@@ -325,7 +370,7 @@ class RewardsCfg:
"height_offset": 0.07, # Z方向lid 上方 0.1m
"std": 0.3, # 位置对齐的容忍度
},
weight=3.0
weight=3.0,
)
# 【新增】精细对齐 (引导进入 2cm 圈)
@@ -336,13 +381,13 @@ class RewardsCfg:
"robot_cfg": SceneEntityCfg("Mindbot"),
"left_gripper_name": "left_hand__l",
"right_gripper_name": "left_hand_r",
"height_offset": 0.07, # 【注意】这个高度必须非常准,和 interaction 判定高度一致
"std": 0.05, # 非常陡峭的梯度,只在 5-10cm 内有效
"height_offset": 0.07, # 【注意】这个高度必须非常准,和 interaction 判定高度一致
"std": 0.05, # 非常陡峭的梯度,只在 5-10cm 内有效
},
weight=10.0 # 高权重
weight=10.0, # 高权重
)
gripper_close_interaction = RewTerm(
gripper_close_interaction = RewTerm(
func=mdp.gripper_close_when_near,
params={
"lid_cfg": SceneEntityCfg("lid"),
@@ -354,34 +399,32 @@ class RewardsCfg:
"height_offset": 0.04,
"grasp_radius": 0.03,
},
weight=10.0
weight=10.0,
)
lid_lifted_reward = RewTerm(
func=mdp.lid_is_lifted, # 使用 rewards.py 中已有的函数
func=mdp.lid_is_lifted, # 使用 rewards.py 中已有的函数
params={
"lid_cfg": SceneEntityCfg("lid"),
"minimal_height": 1.0, # 根据你的场景调整,比初始高度高 5cm 左右
"minimal_height": 1.0, # 根据你的场景调整,比初始高度高 5cm 左右
},
weight=10.0 # 给一个足够大的权重
weight=10.0, # 给一个足够大的权重
)
lid_lifting_reward = RewTerm(
func=mdp.lid_lift_progress_reward,
params={
"lid_cfg": SceneEntityCfg("lid"),
"initial_height": 0.8, # 请务必核实这个值!在 print 里看一下 lid 的 z 坐标
"initial_height": 0.8, # 请务必核实这个值!在 print 里看一下 lid 的 z 坐标
"target_height_lift": 0.2,
"height_offset": 0.07, # 与其他奖励保持一致
"std": 0.1
"height_offset": 0.07, # 与其他奖励保持一致
"std": 0.1,
},
# 权重设大一点,告诉它这是最终目标
weight=10.0
weight=10.0,
)
@configclass
class TerminationsCfg:
"""Termination terms for the MDP."""
@@ -392,7 +435,7 @@ class TerminationsCfg:
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("Mindbot"), "maximum_height": 2.0},
)
lid_fly_away = DoneTerm(
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("lid"), "maximum_height": 2.0},
@@ -401,25 +444,25 @@ class TerminationsCfg:
# 新增:盖子掉落判定
# 如果盖子掉回桌面(高度接近初始高度),且已经运行了一段时间(避开刚开始重置的瞬间)
lid_dropped = DoneTerm(
func=mdp.base_height_failure, # 复用高度判定函数
func=mdp.base_height_failure, # 复用高度判定函数
params={
"asset_cfg": SceneEntityCfg("lid"),
"minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
"asset_cfg": SceneEntityCfg("lid"),
"minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
},
)
##
# Environment configuration
##
@configclass
class CurriculumCfg:
pass
# action_rate = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "action_rate", "weight": -1e-1, "num_steps": 10000})
# joint_vel = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "joint_vel", "weight": -1e-1, "num_steps": 10000})
@@ -428,10 +471,10 @@ class CurriculumCfg:
# params={
# # 路径rewards管理器 -> 你的奖励项名 -> params字典 -> std键
# "address": "rewards.gripper_lid_position_alignment.params.std",
# # 修改逻辑:使用我们刚才写的函数
# "modify_fn": mdp.annealing_std,
# # 传给函数的参数
# "modify_params": {
# "start_step": 00, # 约 600 轮
@@ -442,6 +485,7 @@ class CurriculumCfg:
# }
# )
@configclass
class MindbotEnvCfg(ManagerBasedRLEnvCfg):
# Scene settings
@@ -459,20 +503,20 @@ class MindbotEnvCfg(ManagerBasedRLEnvCfg):
def __post_init__(self) -> None:
"""Post initialization."""
# general settings
self.decimation = 4 #original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.decimation = 4 # original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.episode_length_s = 10
# viewer settings
self.viewer.eye = (3.5, 0.0, 3.2)
# simulation settings
self.sim.dt = 1 / 120 #original 1 / 60
self.sim.dt = 1 / 120 # original 1 / 60
self.sim.render_interval = self.decimation
# # 1. 基础堆内存
self.sim.physx.gpu_heap_capacity = 256 * 1024 * 1024 # 256MB
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_temp_buffer_capacity = 128 * 1024 * 1024
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
# # 5. 聚合对容量 (针对复杂的 Articulation)
self.sim.physx.gpu_found_lost_pairs_capacity = 16 * 1024 * 1024
self.sim.physx.gpu_found_lost_aggregate_pairs_capacity = 16 * 1024 * 1024

View File

@@ -21,22 +21,28 @@ from isaaclab.managers import CurriculumTermCfg as CurrTerm
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.utils import configclass
from isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg
from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg, BinaryJointPositionActionCfg
from isaaclab.envs.mdp.actions.actions_cfg import (
DifferentialInverseKinematicsActionCfg,
BinaryJointPositionActionCfg,
)
from . import mdp
##
# Pre-defined configs
##
from mindbot.robot.mindbot import MINDBOT_CFG
# ====== 其他物体配置 ======
from isaaclab.sim.spawners.from_files.from_files_cfg import UsdFileCfg
from isaaclab.sim.schemas.schemas_cfg import RigidBodyPropertiesCfg, CollisionPropertiesCfg
from isaaclab.sim.schemas.schemas_cfg import (
RigidBodyPropertiesCfg,
CollisionPropertiesCfg,
)
TABLE_CFG=RigidObjectCfg(
TABLE_CFG = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Table",
init_state=RigidObjectCfg.InitialStateCfg(
pos=[0.95, -0.3, 0.005],
@@ -45,30 +51,29 @@ TABLE_CFG=RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/table/Table_C.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/table/Table_C.usd",
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
DRYINGBOX_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/assets/Collected_Equipment_BB_0B/Equipment/Equipment_BB_13.usd",
usd_path="/home/maic/LYT/maic_usd_assets/assets/Collected_Equipment_BB_0B/Equipment/Equipment_BB_13.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_depenetration_velocity=1.0
disable_gravity=False, max_depenetration_velocity=1.0
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=False,#
enabled_self_collisions=False, #
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
stabilization_threshold=1e-6,
@@ -76,21 +81,19 @@ DRYINGBOX_CFG = ArticulationCfg(
),
),
init_state=ArticulationCfg.InitialStateCfg(
pos=[0.95, -0.45, 0.9],
rot=[-0.7071, 0.0, 0.0, 0.7071]
),
pos=[0.95, -0.45, 0.9], rot=[-0.7071, 0.0, 0.0, 0.7071]
),
# actuators={}
actuators={
"passive_damper": ImplicitActuatorCfg(
# ".*" 表示匹配该USD文件内的所有关节无论是轮子、屏幕转轴还是其他
joint_names_expr=["RevoluteJoint"],
stiffness=10000.0,
damping=1000.0,
effort_limit_sim=10000.0,
stiffness=10000.0,
damping=1000.0,
effort_limit_sim=10000.0,
velocity_limit_sim=100.0,
),
}
},
)
LID_CFG = RigidObjectCfg(
@@ -102,23 +105,23 @@ LID_CFG = RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/ultrasound/ultrasound_lid.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/ultrasound/ultrasound_lid.usd",
# scale=(0.2, 0.2, 0.2),
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
max_angular_velocity=1000.0,
max_linear_velocity=1000.0,
max_depenetration_velocity=0.5,#original 5.0
linear_damping=5.0, #original 0.5
angular_damping=5.0, #original 0.5
max_depenetration_velocity=0.5, # original 5.0
linear_damping=5.0, # original 0.5
angular_damping=5.0, # original 0.5
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -126,13 +129,12 @@ LID_CFG = RigidObjectCfg(
ULTRASOUND_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/ultrasound/ultrasound.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/ultrasound/ultrasound.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_depenetration_velocity=1.0
disable_gravity=False, max_depenetration_velocity=1.0
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=False,#
enabled_self_collisions=False, #
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
stabilization_threshold=1e-6,
@@ -145,13 +147,12 @@ ULTRASOUND_CFG = ArticulationCfg(
"passive_damper": ImplicitActuatorCfg(
# ".*" 表示匹配该USD文件内的所有关节无论是轮子、屏幕转轴还是其他
joint_names_expr=[".*"],
stiffness=0.0,
damping=1000.0,
effort_limit_sim=10000.0,
stiffness=0.0,
damping=1000.0,
effort_limit_sim=10000.0,
velocity_limit_sim=100.0,
),
}
},
)
##
@@ -160,6 +161,7 @@ ULTRASOUND_CFG = ArticulationCfg(
from isaaclab.sensors import CameraCfg
import isaaclab.sim as sim_utils
@configclass
class PullSceneCfg(InteractiveSceneCfg):
"""Configuration for a cart-pole scene."""
@@ -173,7 +175,9 @@ class PullSceneCfg(InteractiveSceneCfg):
# robot
Mindbot: ArticulationCfg = MINDBOT_CFG.replace(prim_path="{ENV_REGEX_NS}/Mindbot")
table: RigidObjectCfg = TABLE_CFG.replace(prim_path="{ENV_REGEX_NS}/Table")
dryingbox: ArticulationCfg = DRYINGBOX_CFG.replace(prim_path="{ENV_REGEX_NS}/Dryingbox")
dryingbox: ArticulationCfg = DRYINGBOX_CFG.replace(
prim_path="{ENV_REGEX_NS}/Dryingbox"
)
# ultrasound: ArticulationCfg = ULTRASOUND_CFG.replace(prim_path="{ENV_REGEX_NS}/ultrasound")
# lid: RigidObjectCfg = LID_CFG.replace(prim_path="{ENV_REGEX_NS}/Lid")
@@ -291,17 +295,22 @@ class PullSceneCfg(InteractiveSceneCfg):
# MDP settings
##
def right_gripper_pos_w(env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")) -> torch.Tensor:
def right_gripper_pos_w(
env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")
) -> torch.Tensor:
asset = env.scene[asset_cfg.name]
body_ids, _ = asset.find_bodies(["right_hand_body"], preserve_order=True)
pos_w = asset.data.body_pos_w[:, body_ids[0]] - env.scene.env_origins
return pos_w
def get_body_pos_rel(env, asset_cfg: SceneEntityCfg) -> torch.Tensor:
asset = env.scene[asset_cfg.name]
body_ids, _ = asset.find_bodies(asset_cfg.body_names, preserve_order=True)
return asset.data.body_pos_w[:, body_ids[0]] - env.scene.env_origins
# 新增:通用获取 body 世界姿态的函数
def get_body_quat_w(env, asset_cfg: SceneEntityCfg) -> torch.Tensor:
asset = env.scene[asset_cfg.name]
@@ -317,16 +326,15 @@ class ActionsCfg:
right_arm_ee = DifferentialInverseKinematicsActionCfg(
asset_name="Mindbot",
joint_names=["r_joint[1-6]"], # 左臂的6个关节
body_name="right_hand_body", # 末端执行器body名称
body_name="right_hand_body", # 末端执行器body名称
controller=DifferentialIKControllerCfg(
command_type="pose", # 控制位置+姿态
use_relative_mode=True, # 相对模式:动作是增量
ik_method="dls", # Damped Least Squares方法
command_type="pose", # 控制位置+姿态
use_relative_mode=True, # 相对模式:动作是增量
ik_method="dls", # Damped Least Squares方法
),
scale=(0.01, 0.01, 0.01, 0.025, 0.025, 0.025),
)
grippers_position = mdp.BinaryJointPositionActionCfg(
asset_name="Mindbot",
joint_names=["right_hand_joint_left", "right_hand_joint_right"],
@@ -334,7 +342,10 @@ class ActionsCfg:
# open_command_expr={"关节名正则": 值}
open_command_expr={"right_hand_joint_left": 0.0, "right_hand_joint_right": 0.0},
# close_command_expr={"关节名正则": 值}
close_command_expr={"right_hand_joint_left": -0.03, "right_hand_joint_right": 0.03},
close_command_expr={
"right_hand_joint_left": -0.03,
"right_hand_joint_right": 0.03,
},
)
trunk_position = mdp.JointPositionActionCfg(
@@ -342,7 +353,7 @@ class ActionsCfg:
joint_names=["PrismaticJoint"],
scale=0.00,
offset=0.25,
clip=None
clip=None,
)
@@ -354,23 +365,41 @@ class ObservationsCfg:
class PolicyCfg(ObsGroup):
"""Observations for policy group."""
mindbot_joint_pos_rel = ObsTerm(func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_pos = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_quat = ObsTerm(func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
right_gripper_pos = ObsTerm(func=right_gripper_pos_w,
params={"asset_cfg": SceneEntityCfg("Mindbot", body_names=["right_hand_body"])})
mindbot_joint_pos_rel = ObsTerm(
func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_pos = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_quat = ObsTerm(
func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
right_gripper_pos = ObsTerm(
func=right_gripper_pos_w,
params={
"asset_cfg": SceneEntityCfg("Mindbot", body_names=["right_hand_body"])
},
)
dryingbox_handle_pos = ObsTerm(
func=get_body_pos_rel,
params={"asset_cfg": SceneEntityCfg("dryingbox", body_names=["Equipment_BB_13_C"])}
func=get_body_pos_rel,
params={
"asset_cfg": SceneEntityCfg(
"dryingbox", body_names=["Equipment_BB_13_C"]
)
},
)
dryingbox_handle_quat = ObsTerm(
func=get_body_quat_w,
params={"asset_cfg": SceneEntityCfg("dryingbox", body_names=["Equipment_BB_13_C"])}
func=get_body_quat_w,
params={
"asset_cfg": SceneEntityCfg(
"dryingbox", body_names=["Equipment_BB_13_C"]
)
},
)
# lid_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")})
# ultrasound_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("ultrasound")})
def __post_init__(self) -> None:
self.enable_corruption = False
self.concatenate_terms = True
@@ -382,6 +411,7 @@ class ObservationsCfg:
@configclass
class EventCfg:
"""Configuration for events."""
# 重置所有关节到 init_state无偏移
reset_mindbot_all_joints = EventTerm(
func=mdp.reset_joints_by_offset,
@@ -402,15 +432,30 @@ class EventCfg:
"velocity_range": (0.0, 0.0),
},
)
reset_table=EventTerm(func=mdp.reset_root_state_uniform,mode="reset",
params={"asset_cfg": SceneEntityCfg("table"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_dryingbox=EventTerm(func=mdp.reset_root_state_uniform,mode="reset",
params={"asset_cfg": SceneEntityCfg("dryingbox"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_table = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("table"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_dryingbox = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("dryingbox"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
@configclass
class RewardsCfg:
"""Reward terms for the MDP."""
# 1. 姿态对齐:保持不变,这是基础
gripper_handle_orientation_alignment = RewTerm(
func=mdp.gripper_handle_orientation_alignment,
@@ -419,12 +464,12 @@ class RewardsCfg:
"robot_cfg": SceneEntityCfg("Mindbot"),
"handle_name": "Equipment_BB_13_C",
"gripper_body_name": "right_hand_body",
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"lid_handle_axis": (0.0, 0.0, 1.0),
"max_angle_deg": 60.0, # 稍微放宽一点,或者保持 30.0,看前期训练难度
"max_angle_deg": 60.0, # 稍微放宽一点,或者保持 30.0,看前期训练难度
},
weight=4.0
weight=4.0,
)
# 2. 位置对齐 (合并了之前的粗略和精细对齐)
# std=0.05 提供了从 15cm 到 0cm 全程较好的梯度,解决了之前的梯度消失问题
@@ -433,13 +478,13 @@ class RewardsCfg:
params={
"dryingbox_cfg": SceneEntityCfg("dryingbox"),
"robot_cfg": SceneEntityCfg("Mindbot"),
"handle_name":"Equipment_BB_13_C",
"handle_name": "Equipment_BB_13_C",
"left_gripper_name": "right_hand_l",
"right_gripper_name": "right_hand__r",
"height_offset": 0.00,
"std": 0.05, # 关键修改0.3太松0.03太紧导致梯度消失0.05是平衡点
},
weight=6.0 # 提高权重,作为主导奖励
weight=6.0, # 提高权重,作为主导奖励
)
# 3. 远距离闭合惩罚 (逻辑已修正)
# 现在它只惩罚“在远处就闭眼”的行为,不会阻挡机器人靠近
@@ -452,27 +497,27 @@ class RewardsCfg:
"left_gripper_name": "right_hand_l",
"right_gripper_name": "right_hand__r",
"joint_names": ["right_hand_joint_left", "right_hand_joint_right"],
"dist_threshold": 0.06, # 2.5cm 保护区,进入后允许闭合
"dist_threshold": 0.06, # 2.5cm 保护区,进入后允许闭合
},
weight=0.5 # 权重降低,作为辅助约束,不要喧宾夺主
weight=0.5, # 权重降低,作为辅助约束,不要喧宾夺主
)
# ... 在 RewardsCfg 类中修改 ...
# 4. 近距离抓取交互 (改用 V2 版本或增加稳定性项)
gripper_close_interaction = RewTerm(
func=mdp.gripper_close_interaction_v2, # 切换到带稳定性的版本
gripper_close_interaction = RewTerm(
func=mdp.gripper_close_interaction_v2, # 切换到带稳定性的版本
params={
"dryingbox_cfg": SceneEntityCfg("dryingbox"),
"robot_cfg": SceneEntityCfg("Mindbot"),
"handle_name":"Equipment_BB_13_C",
"handle_name": "Equipment_BB_13_C",
"left_gripper_name": "right_hand_l",
"right_gripper_name": "right_hand__r",
"joint_names": ["right_hand_joint_left", "right_hand_joint_right"],
"target_close_pos": 0.012,
"target_close_pos": 0.012,
"height_offset": 0.00,
"grasp_radius": 0.05,
},
weight=8.0 # 适当调低一点点,为稳定性奖励腾出空间
weight=8.0, # 适当调低一点点,为稳定性奖励腾出空间
)
# 5. 新增:抓取稳定性奖励 (核心:惩罚抖动)
@@ -483,10 +528,10 @@ class RewardsCfg:
"joint_names": ["right_hand_joint_left", "right_hand_joint_right"],
"vel_threshold": 0.005,
},
weight=4.0 # 只要保持静止就一直给分
weight=4.0, # 只要保持静止就一直给分
)
# 4. 近距离抓取交互 (修正了目标值)
# gripper_close_interaction = RewTerm(
# gripper_close_interaction = RewTerm(
# func=mdp.gripper_close_when_near,
# params={
# "dryingbox_cfg": SceneEntityCfg("dryingbox"),
@@ -495,19 +540,20 @@ class RewardsCfg:
# "left_gripper_name": "right_hand_l",
# "right_gripper_name": "right_hand__r",
# "joint_names": ["right_hand_joint_left", "right_hand_joint_right"],
# # 关键修改:物理接触点计算
# # 夹爪空载全闭是0.03 (对应0cm)
# # 把手宽3.88cm -> 单侧行程 (6-3.88)/2 = 1.06cm = 0.0106m
# # 设为 0.012 确保接触时计算出的奖励是满分 (ratio >= 1.0)
# "target_close_pos": 0.012,
# "target_close_pos": 0.012,
# "height_offset": 0.00,
# "grasp_radius": 0.05,
# },
# weight=10.0 # 只有成功抓到才给的大奖
# )
# @configclass
# class RewardsCfg:
# """Reward terms for the MDP."""
@@ -519,8 +565,8 @@ class RewardsCfg:
# "robot_cfg": SceneEntityCfg("Mindbot"),
# "handle_name": "Equipment_BB_13_C",
# "gripper_body_name": "right_hand_body",
# "gripper_forward_axis": (0.0, 0.0, 1.0),
# "gripper_width_axis": (0.0, 1.0, 0.0),
# "gripper_forward_axis": (0.0, 0.0, 1.0),
# "gripper_width_axis": (0.0, 1.0, 0.0),
# "lid_handle_axis": (0.0, 0.0, 1.0),
# # 删除了 handle_axis因为新函数中不再使用它
# "max_angle_deg": 30.0, # 建议改为 30.0 或更小85.0 对指向性约束来说太宽松
@@ -530,7 +576,7 @@ class RewardsCfg:
# # stage 2
# # 位置对齐奖励:鼓励夹爪位于 lid 两侧,且 Z 方向在 lid 上方 0.1m
# gripper_handle_position_alignment = RewTerm(
# func=mdp.gripper_handle_position_alignment,
# params={
@@ -596,7 +642,7 @@ class RewardsCfg:
# # },
# # weight=10.0
# # )
# gripper_close_interaction = RewTerm(
# gripper_close_interaction = RewTerm(
# func=mdp.gripper_close_when_near,
# params={
# "dryingbox_cfg": SceneEntityCfg("dryingbox"),
@@ -631,12 +677,10 @@ class RewardsCfg:
# # "std": 0.1
# # },
# # # 权重设大一点,告诉它这是最终目标
# # weight=10.0
# # weight=10.0
# # )
@configclass
class TerminationsCfg:
"""Termination terms for the MDP."""
@@ -647,7 +691,7 @@ class TerminationsCfg:
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("Mindbot"), "maximum_height": 2.0},
)
# lid_fly_away = DoneTerm(
# func=mdp.base_height_failure,
# params={"asset_cfg": SceneEntityCfg("lid"), "maximum_height": 2.0},
@@ -658,23 +702,23 @@ class TerminationsCfg:
# lid_dropped = DoneTerm(
# func=mdp.base_height_failure, # 复用高度判定函数
# params={
# "asset_cfg": SceneEntityCfg("lid"),
# "asset_cfg": SceneEntityCfg("lid"),
# "minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
# },
# )
##
# Environment configuration
##
@configclass
class CurriculumCfg:
pass
# action_rate = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "action_rate", "weight": -1e-1, "num_steps": 10000})
# joint_vel = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "joint_vel", "weight": -1e-1, "num_steps": 10000})
@@ -683,10 +727,10 @@ class CurriculumCfg:
# params={
# # 路径rewards管理器 -> 你的奖励项名 -> params字典 -> std键
# "address": "rewards.gripper_lid_position_alignment.params.std",
# # 修改逻辑:使用我们刚才写的函数
# "modify_fn": mdp.annealing_std,
# # 传给函数的参数
# "modify_params": {
# "start_step": 00, # 约 600 轮
@@ -697,6 +741,7 @@ class CurriculumCfg:
# }
# )
@configclass
class PullEnvCfg(ManagerBasedRLEnvCfg):
# Scene settings
@@ -714,20 +759,20 @@ class PullEnvCfg(ManagerBasedRLEnvCfg):
def __post_init__(self) -> None:
"""Post initialization."""
# general settings
self.decimation = 4 #original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.decimation = 4 # original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.episode_length_s = 10
# viewer settings
self.viewer.eye = (3.5, 0.0, 3.2)
# simulation settings
self.sim.dt = 1 / 120 #original 1 / 60
self.sim.dt = 1 / 120 # original 1 / 60
self.sim.render_interval = self.decimation
# # 1. 基础堆内存
self.sim.physx.gpu_heap_capacity = 256 * 1024 * 1024 # 256MB
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_temp_buffer_capacity = 128 * 1024 * 1024
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
# # 5. 聚合对容量 (针对复杂的 Articulation)
self.sim.physx.gpu_found_lost_pairs_capacity = 16 * 1024 * 1024
self.sim.physx.gpu_found_lost_aggregate_pairs_capacity = 16 * 1024 * 1024

View File

@@ -21,7 +21,10 @@ from isaaclab.managers import CurriculumTermCfg as CurrTerm
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.utils import configclass
from isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg
from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg, BinaryJointPositionActionCfg
from isaaclab.envs.mdp.actions.actions_cfg import (
DifferentialInverseKinematicsActionCfg,
BinaryJointPositionActionCfg,
)
from isaaclab.sensors import CameraCfg
from . import mdp
@@ -34,10 +37,13 @@ from mindbot.robot.mindbot import MINDBOT_CFG
# ====== 其他物体配置 ======
from isaaclab.sim.spawners.from_files.from_files_cfg import UsdFileCfg
from isaaclab.sim.schemas.schemas_cfg import RigidBodyPropertiesCfg, CollisionPropertiesCfg
from isaaclab.sim.schemas.schemas_cfg import (
RigidBodyPropertiesCfg,
CollisionPropertiesCfg,
)
TABLE_CFG=RigidObjectCfg(
TABLE_CFG = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Table",
init_state=RigidObjectCfg.InitialStateCfg(
pos=[0.95, -0.3, 0.005],
@@ -46,17 +52,17 @@ TABLE_CFG=RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/table/Table_C.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/table/Table_C.usd",
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -70,23 +76,23 @@ LID_CFG = RigidObjectCfg(
ang_vel=[0.0, 0.0, 0.0],
),
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/ultrasound/ultrasound_lid.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/ultrasound/ultrasound_lid.usd",
# scale=(0.2, 0.2, 0.2),
rigid_props=RigidBodyPropertiesCfg(
rigid_body_enabled= True,
rigid_body_enabled=True,
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
max_angular_velocity=1000.0,
max_linear_velocity=1000.0,
max_depenetration_velocity=0.5,#original 5.0
linear_damping=5.0, #original 0.5
angular_damping=5.0, #original 0.5
max_depenetration_velocity=0.5, # original 5.0
linear_damping=5.0, # original 0.5
angular_damping=5.0, # original 0.5
disable_gravity=False,
),
collision_props=CollisionPropertiesCfg(
collision_enabled=True,
contact_offset=0.0005,#original 0.02
rest_offset=0
contact_offset=0.0005, # original 0.02
rest_offset=0,
),
),
)
@@ -94,13 +100,13 @@ LID_CFG = RigidObjectCfg(
ROOM_CFG = AssetBaseCfg(
prim_path="{ENV_REGEX_NS}/Room",
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/twinlab/MIC_sim-3.0/244_140/room.usd",
usd_path="/home/maic/LYT/maic_usd_assets/twinlab/MIC_sim-3.0/244_140/room.usd",
),
)
ROOM_CFG = AssetBaseCfg(
prim_path="{ENV_REGEX_NS}/Room",
spawn=UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/twinlab/Collected_lab2/lab.usd",
usd_path="/home/maic/LYT/maic_usd_assets/twinlab/Collected_lab2/lab.usd",
),
)
@@ -113,7 +119,7 @@ ROOM_CFG = AssetBaseCfg(
# ang_vel=[0.0, 0.0, 0.0],
# ),
# spawn=UsdFileCfg(
# usd_path="C:/Users/PC/workpalce/maic_usd_assets/twinlab/MIC_sim-3.0/244_140/room.usd",
# usd_path="/home/maic/LYT/maic_usd_assets/twinlab/MIC_sim-3.0/244_140/room.usd",
# # scale=(0.2, 0.2, 0.2),
# rigid_props=RigidBodyPropertiesCfg(
# rigid_body_enabled= True,
@@ -135,16 +141,14 @@ ROOM_CFG = AssetBaseCfg(
# )
ULTRASOUND_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
usd_path="C:/Users/PC/workpalce/maic_usd_assets/equipment/ultrasound/ultrasound.usd",
usd_path="/home/maic/LYT/maic_usd_assets/equipment/ultrasound/ultrasound.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_depenetration_velocity=1.0
disable_gravity=False, max_depenetration_velocity=1.0
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=False,#
enabled_self_collisions=False, #
solver_position_iteration_count=32,
solver_velocity_iteration_count=16,
stabilization_threshold=1e-6,
@@ -157,13 +161,12 @@ ULTRASOUND_CFG = ArticulationCfg(
"passive_damper": ImplicitActuatorCfg(
# ".*" 表示匹配该USD文件内的所有关节无论是轮子、屏幕转轴还是其他
joint_names_expr=[".*"],
stiffness=0.0,
damping=1000.0,
effort_limit_sim=10000.0,
stiffness=0.0,
damping=1000.0,
effort_limit_sim=10000.0,
velocity_limit_sim=100.0,
),
}
},
)
##
@@ -185,7 +188,9 @@ class MindbotSceneCfg(InteractiveSceneCfg):
Room: AssetBaseCfg = ROOM_CFG.replace(prim_path="{ENV_REGEX_NS}/Room")
Mindbot: ArticulationCfg = MINDBOT_CFG.replace(prim_path="{ENV_REGEX_NS}/Mindbot")
table: RigidObjectCfg = TABLE_CFG.replace(prim_path="{ENV_REGEX_NS}/Table")
ultrasound: ArticulationCfg = ULTRASOUND_CFG.replace(prim_path="{ENV_REGEX_NS}/ultrasound")
ultrasound: ArticulationCfg = ULTRASOUND_CFG.replace(
prim_path="{ENV_REGEX_NS}/ultrasound"
)
lid: RigidObjectCfg = LID_CFG.replace(prim_path="{ENV_REGEX_NS}/Lid")
# lights
dome_light = AssetBaseCfg(
@@ -193,50 +198,55 @@ class MindbotSceneCfg(InteractiveSceneCfg):
spawn=sim_utils.DomeLightCfg(color=(0.9, 0.9, 0.9), intensity=500.0),
)
# head_camera=CameraCfg(
# prim_path="{ENV_REGEX_NS}/Mindbot/robot_head/cam_head",
# prim_path="{ENV_REGEX_NS}/Mindbot/robot_head/cam_head",
# update_period=1/120,
# height=480,
# width=640,
# data_type=["rgb"],
# spawn=None,
# )
left_hand_camera=CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_fb_left/Link_6/robot___left_8_02/cam_left_hand",
update_period=1/120,
left_hand_camera = CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_fb_left/Link_6/robot___left_8_02/cam_left_hand",
update_period=1 / 120,
height=480,
width=640,
data_types=["rgb"],
spawn=None,
)
right_hand_camera=CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_b_right/Link6/robot___right_8_2/cam_right_hand",
update_period=1/120,
right_hand_camera = CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/rm_65_b_right/Link6/robot___right_8_2/cam_right_hand",
update_period=1 / 120,
height=480,
width=640,
data_types=["rgb"],
spawn=None,
)
head_camera=CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/robot_head/cam_head",
update_period=1/120,
head_camera = CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/robot_head/cam_head",
update_period=1 / 120,
height=480,
width=640,
data_types=["rgb"],
spawn=None,
)
chest_camera=CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/robot_trunk/cam_chest",
update_period=1/120,
chest_camera = CameraCfg(
prim_path="{ENV_REGEX_NS}/Mindbot/robot_trunk/cam_chest",
update_period=1 / 120,
height=480,
width=640,
data_types=["rgb"],
spawn=None,
)
# # ##
# MDP settings
##
def left_gripper_pos_w(env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")) -> torch.Tensor:
def left_gripper_pos_w(
env, asset_cfg: SceneEntityCfg = SceneEntityCfg("Mindbot")
) -> torch.Tensor:
asset = env.scene[asset_cfg.name]
body_ids, _ = asset.find_bodies(["left_hand_body"], preserve_order=True)
pos_w = asset.data.body_pos_w[:, body_ids[0]] - env.scene.env_origins
@@ -251,22 +261,22 @@ class ActionsCfg:
left_arm_ee = DifferentialInverseKinematicsActionCfg(
asset_name="Mindbot",
joint_names=["l_joint[1-6]"], # 左臂的6个关节
body_name="left_hand_body", # 末端执行器body名称
body_name="left_hand_body", # 末端执行器body名称
controller=DifferentialIKControllerCfg(
command_type="pose", # 控制位置+姿态
use_relative_mode=True, # 相对模式:动作是增量
ik_method="dls", # Damped Least Squares方法
command_type="pose", # 控制位置+姿态
use_relative_mode=True, # 相对模式:动作是增量
ik_method="dls", # Damped Least Squares方法
),
scale=(0.01, 0.01, 0.01, 0.025, 0.025, 0.025),
)
# right_arm_fixed = mdp.JointPositionActionCfg(
# asset_name="Mindbot",
# joint_names=["r_joint[1-6]"], # 对应 l_joint1 到 l_joint6
# # 1. 缩放设为 0这让 RL 策略无法控制它,它不会动
# scale=0.0,
# scale=0.0,
# # 2. 偏移设为你的目标角度(弧度):这告诉电机“永远停在这里”
# # 对应 (135, -70, -90, 90, 90, -70)
# offset={
@@ -282,22 +292,22 @@ class ActionsCfg:
grippers_position = mdp.BinaryJointPositionActionCfg(
asset_name="Mindbot",
joint_names=["left_hand_joint_left", "left_hand_joint_right"],
# 修正:使用字典格式
# open_command_expr={"关节名正则": 值}
open_command_expr={"left_hand_joint_left": 0.0, "left_hand_joint_right": 0.0},
# close_command_expr={"关节名正则": 值}
close_command_expr={"left_hand_joint_left": -0.03, "left_hand_joint_right": 0.03},
close_command_expr={
"left_hand_joint_left": -0.03,
"left_hand_joint_right": 0.03,
},
)
trunk_position = mdp.JointPositionActionCfg(
asset_name="Mindbot",
joint_names=["PrismaticJoint"],
scale=0.00,
offset=0.3,
clip=None
clip=None,
)
@@ -309,15 +319,29 @@ class ObservationsCfg:
class PolicyCfg(ObsGroup):
"""Observations for policy group."""
mindbot_joint_pos_rel = ObsTerm(func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_pos = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
mindbot_root_quat = ObsTerm(func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")})
left_gripper_pos = ObsTerm(func=left_gripper_pos_w,
params={"asset_cfg": SceneEntityCfg("Mindbot", body_names=["left_hand_body"])})
lid_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")})
ultrasound_pos_abs = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("ultrasound")})
mindbot_joint_pos_rel = ObsTerm(
func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_pos = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
mindbot_root_quat = ObsTerm(
func=mdp.root_quat_w, params={"asset_cfg": SceneEntityCfg("Mindbot")}
)
left_gripper_pos = ObsTerm(
func=left_gripper_pos_w,
params={
"asset_cfg": SceneEntityCfg("Mindbot", body_names=["left_hand_body"])
},
)
lid_pos_abs = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("lid")}
)
ultrasound_pos_abs = ObsTerm(
func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("ultrasound")}
)
def __post_init__(self) -> None:
self.enable_corruption = False
self.concatenate_terms = True
@@ -365,27 +389,34 @@ class EventCfg:
"velocity_range": (0.0, 0.0),
},
)
reset_table=EventTerm(func=mdp.reset_root_state_uniform,mode="reset",
params={"asset_cfg": SceneEntityCfg("table"), "pose_range": {"x": (0.0, 0.0)}, "velocity_range": {"x": (0.0, 0.0)}})
reset_table = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("table"),
"pose_range": {"x": (0.0, 0.0)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_ultrasound = EventTerm(
func=mdp.reset_root_state_uniform,
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("ultrasound"),
"pose_range": {"x": (-0.07, 0.07), "y": (-0.07, 0.07), "yaw": (-0.1, 0.1)},
"velocity_range": {"x": (0.0, 0.0)}
}
)
"asset_cfg": SceneEntityCfg("ultrasound"),
"pose_range": {"x": (-0.07, 0.07), "y": (-0.07, 0.07), "yaw": (-0.1, 0.1)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
reset_lid = EventTerm(
func=mdp.reset_root_state_uniform,
func=mdp.reset_root_state_uniform,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("lid"),
"pose_range": {"x": (-0.03, 0.03), "y": (-0.03, 0.03), "yaw": (-1.5, 1.5)},
"velocity_range": {"x": (0.0, 0.0)}
}
)
"asset_cfg": SceneEntityCfg("lid"),
"pose_range": {"x": (-0.03, 0.03), "y": (-0.03, 0.03), "yaw": (-1.5, 1.5)},
"velocity_range": {"x": (0.0, 0.0)},
},
)
@configclass
@@ -398,12 +429,12 @@ class RewardsCfg:
"lid_cfg": SceneEntityCfg("lid"),
"robot_cfg": SceneEntityCfg("Mindbot"),
"gripper_body_name": "left_hand_body",
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"gripper_forward_axis": (0.0, 0.0, 1.0),
"gripper_width_axis": (0.0, 1.0, 0.0),
"lid_handle_axis": (0.0, 1.0, 0.0),
"max_angle_deg": 85.0, # 允许60度内的偏差
},
weight=5.0 #original 5.0
weight=5.0, # original 5.0
)
# stage 2
@@ -416,9 +447,9 @@ class RewardsCfg:
"left_gripper_name": "left_hand__l",
"right_gripper_name": "left_hand_r",
"height_offset": 0.07, # Z方向lid 上方 0.1m
"std": 0.3, # 位置对齐的容忍度
"std": 0.3, # 位置对齐的容忍度
},
weight=3.0 #original 3.0
weight=3.0, # original 3.0
)
approach_lid_penalty = RewTerm(
func=mdp.gripper_lid_distance_penalty,
@@ -431,7 +462,7 @@ class RewardsCfg:
},
# weight 为负数表示惩罚。
# 假设距离 0.5m,惩罚就是 -0.5 * 2.0 = -1.0 分。
weight=-1.0
weight=-1.0,
)
# 【新增】精细对齐 (引导进入 2cm 圈)
gripper_lid_fine_alignment = RewTerm(
@@ -441,13 +472,13 @@ class RewardsCfg:
"robot_cfg": SceneEntityCfg("Mindbot"),
"left_gripper_name": "left_hand__l",
"right_gripper_name": "left_hand_r",
"height_offset": 0.07, # 【注意】这个高度必须非常准,和 interaction 判定高度一致
"std": 0.05, # 非常陡峭的梯度,只在 5-10cm 内有效
"height_offset": 0.07, # 【注意】这个高度必须非常准,和 interaction 判定高度一致
"std": 0.05, # 非常陡峭的梯度,只在 5-10cm 内有效
},
weight=10.0 # 高权重
weight=10.0, # 高权重
)
gripper_close_interaction = RewTerm(
gripper_close_interaction = RewTerm(
func=mdp.gripper_close_when_near,
params={
"lid_cfg": SceneEntityCfg("lid"),
@@ -459,34 +490,32 @@ class RewardsCfg:
"height_offset": 0.04,
"grasp_radius": 0.03,
},
weight=10.0
weight=10.0,
)
lid_lifted_reward = RewTerm(
func=mdp.lid_is_lifted, # 使用 rewards.py 中已有的函数
func=mdp.lid_is_lifted, # 使用 rewards.py 中已有的函数
params={
"lid_cfg": SceneEntityCfg("lid"),
"minimal_height": 1.0, # 根据你的场景调整,比初始高度高 5cm 左右
"minimal_height": 1.0, # 根据你的场景调整,比初始高度高 5cm 左右
},
weight=10.0 # 给一个足够大的权重
weight=10.0, # 给一个足够大的权重
)
lid_lifting_reward = RewTerm(
func=mdp.lid_lift_progress_reward,
params={
"lid_cfg": SceneEntityCfg("lid"),
"initial_height": 0.8, # 请务必核实这个值!在 print 里看一下 lid 的 z 坐标
"initial_height": 0.8, # 请务必核实这个值!在 print 里看一下 lid 的 z 坐标
"target_height_lift": 0.2,
"height_offset": 0.07, # 与其他奖励保持一致
"std": 0.1
"height_offset": 0.07, # 与其他奖励保持一致
"std": 0.1,
},
# 权重设大一点,告诉它这是最终目标
weight=10.0
weight=10.0,
)
@configclass
class TerminationsCfg:
"""Termination terms for the MDP."""
@@ -497,7 +526,7 @@ class TerminationsCfg:
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("Mindbot"), "maximum_height": 2.0},
)
lid_fly_away = DoneTerm(
func=mdp.base_height_failure,
params={"asset_cfg": SceneEntityCfg("lid"), "maximum_height": 2.0},
@@ -506,25 +535,25 @@ class TerminationsCfg:
# 新增:盖子掉落判定
# 如果盖子掉回桌面(高度接近初始高度),且已经运行了一段时间(避开刚开始重置的瞬间)
lid_dropped = DoneTerm(
func=mdp.base_height_failure, # 复用高度判定函数
func=mdp.base_height_failure, # 复用高度判定函数
params={
"asset_cfg": SceneEntityCfg("lid"),
"minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
"asset_cfg": SceneEntityCfg("lid"),
"minimum_height": 0.79, # 假设初始高度是 0.9,低于 0.88 说明掉下去了或者被砸进去了
},
)
##
# Environment configuration
##
@configclass
class CurriculumCfg:
pass
# action_rate = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "action_rate", "weight": -1e-1, "num_steps": 10000})
# joint_vel = CurrTerm(func=mdp.modify_reward_weight,
# params={"term_name": "joint_vel", "weight": -1e-1, "num_steps": 10000})
@@ -533,10 +562,10 @@ class CurriculumCfg:
# params={
# # 路径rewards管理器 -> 你的奖励项名 -> params字典 -> std键
# "address": "rewards.gripper_lid_position_alignment.params.std",
# # 修改逻辑:使用我们刚才写的函数
# "modify_fn": mdp.annealing_std,
# # 传给函数的参数
# "modify_params": {
# "start_step": 00, # 约 600 轮
@@ -547,6 +576,7 @@ class CurriculumCfg:
# }
# )
@configclass
class MindbotEnvCfg(ManagerBasedRLEnvCfg):
# Scene settings
@@ -564,20 +594,20 @@ class MindbotEnvCfg(ManagerBasedRLEnvCfg):
def __post_init__(self) -> None:
"""Post initialization."""
# general settings
self.decimation = 4 #original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.decimation = 4 # original 2 # 从 2 增加到 4控制频率从 25Hz 降到 12.5Hz
self.episode_length_s = 10
# viewer settings
self.viewer.eye = (0, 2.5, 2.6)#(3.5, 0.0, 3.2)
self.viewer.eye = (0, 2.5, 2.6) # (3.5, 0.0, 3.2)
# simulation settings
self.sim.dt = 1 / 120 #original 1 / 60
self.sim.dt = 1 / 120 # original 1 / 60
self.sim.render_interval = self.decimation
# # 1. 基础堆内存
self.sim.physx.gpu_heap_capacity = 256 * 1024 * 1024 # 256MB
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_collision_stack_size = 1024 * 1024 * 1024
self.sim.physx.gpu_temp_buffer_capacity = 128 * 1024 * 1024
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
self.sim.physx.gpu_max_rigid_contact_count = 16 * 1024 * 1024 # 200万个接触点
self.sim.physx.gpu_max_rigid_patch_count = 1024 * 1024 # 32万个 patch
# # 5. 聚合对容量 (针对复杂的 Articulation)
self.sim.physx.gpu_found_lost_pairs_capacity = 16 * 1024 * 1024
self.sim.physx.gpu_found_lost_aggregate_pairs_capacity = 16 * 1024 * 1024