Add mac-sim sensor boundaries #81
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright (c) 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 | |
| name: MLX macOS smoke | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - "codex/**" | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| mlx-import-safety: | |
| name: MLX import safety | |
| runs-on: macos-14 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install uv | |
| run: python -m pip install --upgrade uv | |
| - name: Create import-safety virtual environment | |
| run: uv venv --python 3.11 .venv-import | |
| - name: Install MLX import-safety dependencies | |
| run: | | |
| uv pip install --python .venv-import/bin/python \ | |
| -e source/isaaclab[macos-mlx,dev] \ | |
| -e source/isaaclab_rl[dev] \ | |
| -e source/isaaclab_tasks | |
| - name: Prove MLX path does not require Isaac Sim | |
| run: | | |
| mkdir -p logs/benchmarks/mlx/import-safety | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_rl:source/isaaclab_tasks .venv-import/bin/python - <<'PY' | |
| import importlib.util | |
| import json | |
| from pathlib import Path | |
| forbidden = {} | |
| for module_name in ("isaacsim", "omni", "carb", "pxr"): | |
| forbidden[module_name] = importlib.util.find_spec(module_name) is None | |
| if not all(forbidden.values()): | |
| raise SystemExit(f"Unexpected upstream modules available: {forbidden}") | |
| payload = { | |
| "forbidden_modules_absent": forbidden, | |
| "python": "3.11", | |
| } | |
| Path("logs/benchmarks/mlx/import-safety/specs.json").write_text( | |
| json.dumps(payload, indent=2, sort_keys=True) + "\n", | |
| encoding="utf-8", | |
| ) | |
| print(payload) | |
| PY | |
| - name: Run import-safety regression tests | |
| run: | | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_rl:source/isaaclab_tasks .venv-import/bin/pytest \ | |
| source/isaaclab_rl/test/test_import_safety.py \ | |
| source/isaaclab_rl/test/test_mlx_wrapper.py \ | |
| source/isaaclab/test/backends/test_runtime.py -q | |
| - name: Upload import-safety artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: mlx-import-safety-${{ github.run_id }} | |
| path: logs/benchmarks/mlx/import-safety | |
| if-no-files-found: warn | |
| mlx-cartpole: | |
| name: MLX cartpole backend smoke | |
| runs-on: macos-14 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install uv | |
| run: python -m pip install --upgrade uv | |
| - name: Create virtual environment | |
| run: uv venv --python 3.11 .venv | |
| - name: Install MLX smoke dependencies | |
| run: | | |
| uv pip install --python .venv/bin/python \ | |
| -e source/isaaclab[macos-mlx,dev] \ | |
| -e source/isaaclab_rl[dev] \ | |
| -e source/isaaclab_tasks | |
| - name: Prepare benchmark artifact directory | |
| run: mkdir -p logs/benchmarks/mlx/install-matrix | |
| - name: Run fresh-env install matrix | |
| run: | | |
| uv venv --python 3.11 .venv-core | |
| uv pip install --python .venv-core/bin/python -e source/isaaclab[macos-mlx,dev] | |
| .venv-core/bin/python - <<'PY' | |
| import json | |
| from pathlib import Path | |
| from isaaclab.backends import resolve_runtime_selection, set_runtime_selection | |
| set_runtime_selection(resolve_runtime_selection(compute_backend="mlx", sim_backend="mac-sim", device="cpu")) | |
| from isaaclab.envs import ViewerCfg | |
| payload = {"combo": "core", "viewer_cfg_type": ViewerCfg.__name__} | |
| Path("logs/benchmarks/mlx/install-matrix/core.json").write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") | |
| print(payload) | |
| PY | |
| uv venv --python 3.11 .venv-core-tasks | |
| uv pip install --python .venv-core-tasks/bin/python -e source/isaaclab[macos-mlx,dev] -e source/isaaclab_tasks | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_tasks .venv-core-tasks/bin/python - <<'PY' | |
| import json | |
| from pathlib import Path | |
| from isaaclab.backends import resolve_runtime_selection, set_runtime_selection | |
| set_runtime_selection(resolve_runtime_selection(compute_backend="mlx", sim_backend="mac-sim", device="cpu")) | |
| import isaaclab_tasks | |
| from isaaclab_tasks.utils.parse_cfg import parse_env_cfg | |
| cfg = parse_env_cfg("Isaac-Cartpole-Direct-v0", device="cpu", num_envs=8) | |
| payload = {"combo": "core+tasks", "task_cfg_type": type(cfg).__name__, "task_cfg_num_envs": cfg.num_envs} | |
| Path("logs/benchmarks/mlx/install-matrix/core_tasks.json").write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") | |
| print(payload) | |
| PY | |
| uv venv --python 3.11 .venv-core-rl | |
| uv pip install --python .venv-core-rl/bin/python -e source/isaaclab[macos-mlx,dev] -e source/isaaclab_rl[dev] | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_rl .venv-core-rl/bin/python - <<'PY' | |
| import json | |
| from pathlib import Path | |
| from isaaclab.backends import resolve_runtime_selection, set_runtime_selection | |
| set_runtime_selection(resolve_runtime_selection(compute_backend="mlx", sim_backend="mac-sim", device="cpu")) | |
| import isaaclab_rl.sb3 | |
| import isaaclab_rl.skrl | |
| payload = {"combo": "core+rl", "modules": ["isaaclab_rl.sb3", "isaaclab_rl.skrl"]} | |
| Path("logs/benchmarks/mlx/install-matrix/core_rl.json").write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") | |
| print(payload) | |
| PY | |
| - name: Run public install smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_rl .venv/bin/python - <<'PY' | |
| import json | |
| from pathlib import Path | |
| from isaaclab.backends import resolve_runtime_selection, set_runtime_selection | |
| set_runtime_selection(resolve_runtime_selection(compute_backend="mlx", sim_backend="mac-sim", device="cpu")) | |
| import isaaclab | |
| import isaaclab.backends.mac_sim | |
| import isaaclab.controllers | |
| import isaaclab.envs | |
| import isaaclab.envs.mdp.actions.actions_cfg | |
| import isaaclab.envs.mdp.actions.rmpflow_actions_cfg | |
| import isaaclab.sim | |
| import isaaclab.sim.converters | |
| import isaaclab.sim.schemas | |
| import isaaclab.sim.spawners.from_files | |
| import isaaclab.utils.io | |
| import isaaclab.utils.noise | |
| import isaaclab.utils.types | |
| import isaaclab_tasks | |
| import isaaclab_rl.sb3 | |
| import isaaclab_rl.skrl | |
| from isaaclab.backends.mac_sim import MacCartpoleEnv | |
| from isaaclab.envs import ViewerCfg | |
| from isaaclab_tasks.utils.parse_cfg import parse_env_cfg | |
| env = MacCartpoleEnv() | |
| observations, _ = env.reset() | |
| task_cfg = parse_env_cfg("Isaac-Cartpole-Direct-v0", device="cpu", num_envs=64) | |
| payload = { | |
| "modules": [ | |
| "isaaclab", | |
| "isaaclab.backends.mac_sim", | |
| "isaaclab.controllers", | |
| "isaaclab.envs", | |
| "isaaclab.envs.mdp.actions.actions_cfg", | |
| "isaaclab.envs.mdp.actions.rmpflow_actions_cfg", | |
| "isaaclab.sim", | |
| "isaaclab.sim.converters", | |
| "isaaclab.sim.schemas", | |
| "isaaclab.sim.spawners.from_files", | |
| "isaaclab.utils.io", | |
| "isaaclab.utils.noise", | |
| "isaaclab.utils.types", | |
| "isaaclab_tasks", | |
| "isaaclab_rl.sb3", | |
| "isaaclab_rl.skrl", | |
| ], | |
| "policy_shape": list(observations["policy"].shape), | |
| "task_cfg_type": type(task_cfg).__name__, | |
| "task_cfg_num_envs": task_cfg.num_envs, | |
| "viewer_cfg_type": ViewerCfg.__name__, | |
| "package": isaaclab.__name__, | |
| } | |
| out_path = Path("logs/benchmarks/mlx/install_import_smoke.json") | |
| out_path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8") | |
| print(payload["policy_shape"]) | |
| PY | |
| - name: Run release-surface MLX install smoke | |
| run: | | |
| release_root="$(mktemp -d)" | |
| uv venv --python 3.11 "$release_root/.venv-release" | |
| uv pip install --python "$release_root/.venv-release/bin/python" \ | |
| -e source/isaaclab[macos-mlx] \ | |
| -e source/isaaclab_tasks \ | |
| -e source/isaaclab_rl | |
| RELEASE_ROOT="$release_root" GITHUB_WORKSPACE="$GITHUB_WORKSPACE" "$release_root/.venv-release/bin/python" - <<'PY' | |
| import json | |
| import os | |
| from pathlib import Path | |
| from isaaclab.backends import resolve_runtime_selection, set_runtime_selection | |
| from isaaclab_tasks.utils.parse_cfg import parse_env_cfg | |
| from isaaclab_rl.mlx import evaluate_mlx_task, list_trainable_mlx_tasks | |
| set_runtime_selection(resolve_runtime_selection(compute_backend="mlx", sim_backend="mac-sim", device="cpu")) | |
| rough_cfg = parse_env_cfg("Isaac-Velocity-Rough-H1-v0", device="cpu", num_envs=4) | |
| stack_cfg = parse_env_cfg("Isaac-Stack-Cube-RedGreenBlue-Franka-IK-Rel-v0", device="cpu", num_envs=4) | |
| bin_stack_cfg = parse_env_cfg("Isaac-Stack-Cube-Bin-Franka-IK-Rel-Mimic-v0", device="cpu", num_envs=4) | |
| stack_instance_cfg = parse_env_cfg("Isaac-Stack-Cube-Instance-Randomize-Franka-v0", device="cpu", num_envs=4) | |
| teddy_cfg = parse_env_cfg("Isaac-Lift-Teddy-Bear-Franka-IK-Abs-v0", device="cpu", num_envs=4) | |
| ur10e_cfg = parse_env_cfg("Isaac-Deploy-Reach-UR10e-v0", device="cpu", num_envs=4) | |
| gear_2f140_cfg = parse_env_cfg("Isaac-Deploy-GearAssembly-UR10e-2F140-v0", device="cpu", num_envs=4) | |
| gear_2f85_cfg = parse_env_cfg("Isaac-Deploy-GearAssembly-UR10e-2F85-v0", device="cpu", num_envs=4) | |
| gear_2f140_ros_cfg = parse_env_cfg("Isaac-Deploy-GearAssembly-UR10e-2F140-ROS-Inference-v0", device="cpu", num_envs=4) | |
| gear_2f85_ros_cfg = parse_env_cfg("Isaac-Deploy-GearAssembly-UR10e-2F85-ROS-Inference-v0", device="cpu", num_envs=4) | |
| ur10_long_stack_cfg = parse_env_cfg("Isaac-Stack-Cube-UR10-Long-Suction-IK-Rel-v0", device="cpu", num_envs=4) | |
| ur10_short_stack_cfg = parse_env_cfg("Isaac-Stack-Cube-UR10-Short-Suction-IK-Rel-v0", device="cpu", num_envs=4) | |
| payload = evaluate_mlx_task( | |
| "h1-rough", | |
| num_envs=4, | |
| episodes=1, | |
| episode_length_s=0.25, | |
| max_steps=128, | |
| random_actions=False, | |
| seed=11, | |
| ) | |
| artifact = { | |
| "rough_cfg_type": type(rough_cfg).__name__, | |
| "stack_cfg_type": type(stack_cfg).__name__, | |
| "bin_stack_cfg_type": type(bin_stack_cfg).__name__, | |
| "stack_instance_cfg_type": type(stack_instance_cfg).__name__, | |
| "teddy_cfg_type": type(teddy_cfg).__name__, | |
| "ur10e_cfg_type": type(ur10e_cfg).__name__, | |
| "gear_2f140_cfg_type": type(gear_2f140_cfg).__name__, | |
| "gear_2f85_cfg_type": type(gear_2f85_cfg).__name__, | |
| "gear_2f140_ros_cfg_type": type(gear_2f140_ros_cfg).__name__, | |
| "gear_2f85_ros_cfg_type": type(gear_2f85_ros_cfg).__name__, | |
| "ur10_long_stack_cfg_type": type(ur10_long_stack_cfg).__name__, | |
| "ur10_short_stack_cfg_type": type(ur10_short_stack_cfg).__name__, | |
| "trainable_tasks": list(list_trainable_mlx_tasks()), | |
| "eval_task": payload["task"], | |
| "episodes_completed": payload["episodes_completed"], | |
| "release_root": os.environ["RELEASE_ROOT"], | |
| } | |
| out_path = Path(os.environ["GITHUB_WORKSPACE"]) / "logs" / "benchmarks" / "mlx" / "release_install_smoke.json" | |
| out_path.parent.mkdir(parents=True, exist_ok=True) | |
| out_path.write_text(json.dumps(artifact, indent=2, sort_keys=True) + "\n", encoding="utf-8") | |
| print(artifact) | |
| PY | |
| "$release_root/.venv-release/bin/isaaclab-mlx-runtime-diagnostics" logs/runtime/release-runtime-diagnostics.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task h1-rough \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx-evaluate" \ | |
| --task h1-rough \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-eval-split.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task franka-teddy-bear-lift \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-teddy-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task franka-stack-instance-randomize \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-stack-instance-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task Isaac-Stack-Cube-Bin-Franka-IK-Rel-Mimic-v0 \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-bin-stack-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task Isaac-Deploy-GearAssembly-UR10e-2F140-Play-v0 \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-gear-2f140-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task Isaac-Deploy-GearAssembly-UR10e-2F85-Play-v0 \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-gear-2f85-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task Isaac-Deploy-GearAssembly-UR10e-2F140-ROS-Inference-v0 \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-gear-2f140-ros-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task Isaac-Deploy-GearAssembly-UR10e-2F85-ROS-Inference-v0 \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-gear-2f85-ros-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" evaluate \ | |
| --task ur10-long-suction-stack \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-ur10-long-stack-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx-evaluate" \ | |
| --task ur10-short-suction-stack \ | |
| --num-envs 4 --episodes 1 --episode-length-s 0.25 --max-steps 128 --no-random-actions \ | |
| --json-out logs/runtime/release-ur10-short-stack-eval.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx-train" \ | |
| --task ur10e-gear-assembly-2f140 \ | |
| --num-envs 4 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.25 \ | |
| --checkpoint logs/runtime/release-gear-2f140-policy.npz \ | |
| --json-out logs/runtime/release-gear-2f140-train.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx-train" \ | |
| --task ur10-long-suction-stack \ | |
| --num-envs 4 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.25 \ | |
| --checkpoint logs/runtime/release-ur10-long-stack-policy.npz \ | |
| --json-out logs/runtime/release-ur10-long-stack-train.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx" train \ | |
| --task cartpole \ | |
| --num-envs 4 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.25 \ | |
| --checkpoint logs/runtime/release-cartpole-policy.npz \ | |
| --json-out logs/runtime/release-train.json | |
| "$release_root/.venv-release/bin/isaaclab-mlx-train" \ | |
| --task cartpole \ | |
| --num-envs 4 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.25 \ | |
| --checkpoint logs/runtime/release-cartpole-policy-split.npz \ | |
| --json-out logs/runtime/release-train-split.json | |
| - name: Run MLX backend smoke tests | |
| run: | | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_rl .venv/bin/pytest \ | |
| scripts/tools/test/test_bootstrap_isaac_sources.py \ | |
| scripts/tools/test/test_bootstrap_uv_mlx.py \ | |
| source/isaaclab/test/backends/test_runtime.py \ | |
| source/isaaclab/test/backends/test_task_registry.py \ | |
| source/isaaclab/test/backends/test_kernel_inventory.py \ | |
| source/isaaclab/test/backends/test_kernel_compat.py \ | |
| source/isaaclab/test/backends/test_mac_hotpath.py \ | |
| source/isaaclab/test/backends/test_mac_camera_capture.py \ | |
| source/isaaclab/test/backends/test_mac_sensor_raycast.py \ | |
| source/isaaclab/test/backends/test_mac_stereo_depth.py \ | |
| source/isaaclab/test/backends/test_mac_runtime_diagnostics.py \ | |
| source/isaaclab/test/backends/test_mlx_task_cli.py \ | |
| source/isaaclab/test/backends/test_planner_compat.py \ | |
| source/isaaclab/test/backends/test_ros2_bridge.py \ | |
| source/isaaclab/test/backends/test_mac_semantic_drift.py \ | |
| source/isaaclab_rl/test/test_import_safety.py \ | |
| source/isaaclab_rl/test/test_mlx_cli.py \ | |
| source/isaaclab_rl/test/test_mlx_wrapper.py \ | |
| source/isaaclab/test/backends/test_portability_utils.py \ | |
| source/isaaclab/test/backends/test_mac_benchmark_suite.py \ | |
| source/isaaclab/test/backends/test_mac_state_primitives.py \ | |
| source/isaaclab/test/backends/test_mac_phase_b_support.py \ | |
| source/isaaclab/test/backends/test_mac_cartpole.py \ | |
| source/isaaclab/test/backends/test_mac_cartpole_showcase.py \ | |
| source/isaaclab/test/backends/test_mac_cart_double_pendulum.py \ | |
| source/isaaclab/test/backends/test_mac_quadcopter.py \ | |
| source/isaaclab/test/backends/test_mac_cartpole_camera.py \ | |
| source/isaaclab/test/backends/test_mac_anymal_c.py \ | |
| source/isaaclab/test/backends/test_mac_anymal_c_rough.py \ | |
| source/isaaclab/test/backends/test_mac_franka_reach.py \ | |
| source/isaaclab/test/backends/test_mac_ur10e_deploy_reach.py \ | |
| source/isaaclab/test/backends/test_mac_ur10_stack.py \ | |
| source/isaaclab/test/backends/test_mac_franka_lift.py \ | |
| source/isaaclab/test/backends/test_mac_franka_teddy_bear_lift.py \ | |
| source/isaaclab/test/backends/test_mac_franka_stack_instance_randomize.py \ | |
| source/isaaclab/test/backends/test_mac_franka_stack.py \ | |
| source/isaaclab/test/backends/test_mac_franka_stack_rgb.py \ | |
| source/isaaclab/test/backends/test_mac_franka_bin_stack.py \ | |
| source/isaaclab/test/backends/test_mac_franka_cabinet.py \ | |
| source/isaaclab/test/backends/test_mac_franka_open_drawer.py \ | |
| source/isaaclab/test/backends/test_mac_h1.py -q | |
| - name: Run MLX cart-double-pendulum smoke script | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task cart-double-pendulum \ | |
| --num-envs 8 --episodes 1 --max-steps 256 --random-actions | |
| - name: Run MLX quadcopter smoke script | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task quadcopter \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --thrust-action 0.2 --no-random-actions | |
| - name: Run MLX ANYmal-C flat smoke script | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task anymal-c-flat \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --no-random-actions | |
| - name: Run MLX ANYmal-C rough smoke script | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task anymal-c-rough \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --no-random-actions | |
| - name: Run MLX ANYmal-C flat training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task anymal-c-flat \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/anymal_c_flat_policy.npz --eval-interval 1 | |
| - name: Run MLX ANYmal-C rough training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task anymal-c-rough \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/anymal_c_rough_policy.npz --eval-interval 1 | |
| - name: Run MLX cartpole RGB camera smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task cartpole-rgb-camera \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --no-random-actions | |
| - name: Run MLX cartpole depth camera smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task cartpole-depth-camera \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --no-random-actions | |
| - name: Run MLX H1 flat smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task h1-flat \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --no-random-actions | |
| - name: Run MLX H1 rough smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task h1-rough \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 256 --no-random-actions | |
| - name: Run MLX Franka reach smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-reach \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka reach training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-reach \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_reach_policy.npz --eval-interval 1 | |
| - name: Run MLX UR10e deploy-reach smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task ur10e-deploy-reach \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX UR10e deploy-reach training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task ur10e-deploy-reach \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/ur10e_deploy_reach_policy.npz --eval-interval 1 | |
| - name: Run MLX UR10e gear-assembly 2F140 smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task ur10e-gear-assembly-2f140 \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX UR10e gear-assembly 2F140 training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task ur10e-gear-assembly-2f140 \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/ur10e_gear_assembly_2f140_policy.npz --eval-interval 1 | |
| - name: Run MLX UR10e gear-assembly 2F85 smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task ur10e-gear-assembly-2f85 \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX UR10e gear-assembly 2F85 training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task ur10e-gear-assembly-2f85 \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/ur10e_gear_assembly_2f85_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka lift smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-lift \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka lift training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-lift \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_lift_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka teddy-bear lift smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-teddy-bear-lift \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka teddy-bear lift training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-teddy-bear-lift \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_teddy_bear_lift_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka stack instance-randomize smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-stack-instance-randomize \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka stack instance-randomize training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-stack-instance-randomize \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_stack_instance_randomize_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka stack smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-stack \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka stack training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-stack \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_stack_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka stack RGB smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-stack-rgb \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka stack RGB training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-stack-rgb \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_stack_rgb_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka bin-stack smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-bin-stack \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka bin-stack training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-bin-stack \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_bin_stack_policy.npz --eval-interval 1 | |
| - name: Run MLX Franka cabinet smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/evaluate_task.py \ | |
| --task franka-cabinet \ | |
| --num-envs 8 --episodes 1 --episode-length-s 0.5 --max-steps 512 --no-random-actions | |
| - name: Run MLX Franka cabinet training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task franka-cabinet \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/franka_cabinet_policy.npz --eval-interval 1 | |
| - name: Run MLX H1 flat training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task h1-flat \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/h1_flat_policy.npz --eval-interval 1 | |
| - name: Run MLX H1 rough training smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/reinforcement_learning/mlx/train_task.py \ | |
| --task h1-rough \ | |
| --num-envs 8 --updates 1 --rollout-steps 8 --epochs-per-update 1 --episode-length-s 0.5 \ | |
| --checkpoint logs/mlx/h1_rough_policy.npz --eval-interval 1 | |
| - name: Run public MLX wrapper smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab:source/isaaclab_rl .venv/bin/python - <<'PY' | |
| from isaaclab_rl.mlx import evaluate_mlx_task, list_mlx_tasks, list_trainable_mlx_tasks, train_mlx_task | |
| assert "h1-flat" in list_mlx_tasks() | |
| assert "h1-rough" in list_mlx_tasks() | |
| assert "anymal-c-rough" in list_trainable_mlx_tasks() | |
| assert "h1-rough" in list_trainable_mlx_tasks() | |
| assert "cartpole-rgb-camera" in list_mlx_tasks() | |
| assert "cartpole-depth-camera" in list_mlx_tasks() | |
| assert "franka-reach" in list_mlx_tasks() | |
| assert "ur10e-deploy-reach" in list_mlx_tasks() | |
| assert "ur10e-deploy-reach" in list_trainable_mlx_tasks() | |
| assert "ur10e-gear-assembly-2f140" in list_mlx_tasks() | |
| assert "ur10e-gear-assembly-2f85" in list_mlx_tasks() | |
| assert "ur10e-gear-assembly-2f140" in list_trainable_mlx_tasks() | |
| assert "ur10e-gear-assembly-2f85" in list_trainable_mlx_tasks() | |
| assert "franka-lift" in list_mlx_tasks() | |
| assert "franka-teddy-bear-lift" in list_mlx_tasks() | |
| assert "franka-stack-instance-randomize" in list_mlx_tasks() | |
| assert "franka-stack" in list_mlx_tasks() | |
| assert "franka-stack-rgb" in list_mlx_tasks() | |
| assert "franka-bin-stack" in list_mlx_tasks() | |
| assert "franka-cabinet" in list_mlx_tasks() | |
| assert "franka-open-drawer" in list_mlx_tasks() | |
| train_payload = train_mlx_task( | |
| "ur10e-gear-assembly-2f140", | |
| num_envs=8, | |
| updates=1, | |
| rollout_steps=8, | |
| epochs_per_update=1, | |
| hidden_dim=32, | |
| checkpoint="logs/mlx/ur10e_gear_assembly_2f140_wrapper_policy.npz", | |
| eval_interval=1, | |
| episode_length_s=0.5, | |
| seed=31, | |
| ) | |
| payload = evaluate_mlx_task( | |
| "Isaac-Deploy-GearAssembly-UR10e-2F140-Play-v0", | |
| checkpoint=train_payload["checkpoint_path"], | |
| episodes=1, | |
| episode_length_s=0.5, | |
| seed=31, | |
| ) | |
| assert payload["episodes_completed"] == 1 | |
| print(payload["task"], payload["episodes_completed"]) | |
| PY | |
| - name: Run synthetic MLX stereo depth smoke | |
| run: | | |
| mkdir -p logs/hardware | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python - <<'PY' | |
| from pathlib import Path | |
| import numpy as np | |
| root = Path("logs/hardware") | |
| width = 8 | |
| height = 4 | |
| left_luma = np.tile(np.array([20, 40, 60, 80], dtype=np.uint8), (height, 1)) | |
| right_luma = np.zeros_like(left_luma) | |
| right_luma[:, :-1] = left_luma[:, 1:] | |
| left = np.zeros((height, width // 2, 2), dtype=np.uint8) | |
| right = np.zeros((height, width // 2, 2), dtype=np.uint8) | |
| left[:, :, 0] = left_luma | |
| right[:, :, 0] = right_luma | |
| left[:, :, 1] = 128 | |
| right[:, :, 1] = 128 | |
| frame = np.concatenate([left, right], axis=1) | |
| raw_path = root / "synthetic_stereo.raw" | |
| raw_path.write_bytes(frame.tobytes()) | |
| Path(f"{raw_path}.txt").write_text( | |
| "width=8\nheight=4\nchannels=2\npixel_format=yuyv422\ntimestamp=1\nframe_id=1\n", | |
| encoding="utf-8", | |
| ) | |
| print(raw_path) | |
| PY | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/tools/mac_stereo_depth_smoke.py \ | |
| logs/hardware/synthetic_stereo.raw \ | |
| logs/hardware/synthetic_depth \ | |
| --max-disparity 4 \ | |
| --window-size 1 \ | |
| --fx 700.0 \ | |
| --baseline-mm 120.0 \ | |
| --summary-out logs/hardware/synthetic_depth/summary.json | |
| test -f logs/hardware/synthetic_depth/left_rgb.png | |
| test -f logs/hardware/synthetic_depth/right_rgb.png | |
| test -f logs/hardware/synthetic_depth/disparity.png | |
| test -f logs/hardware/synthetic_depth/summary.json | |
| - name: Run mac planner compatibility smoke | |
| run: | | |
| mkdir -p logs/planner | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/tools/mac_planner_smoke.py \ | |
| logs/planner/mac-planner-smoke.json | |
| test -f logs/planner/mac-planner-smoke.json | |
| - name: Run ROS 2 bridge smoke | |
| run: | | |
| mkdir -p logs/hardware | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/tools/ros2_bridge_smoke.py \ | |
| logs/hardware/ros2-bridge-smoke.jsonl \ | |
| --summary-out logs/hardware/ros2-bridge-smoke-summary.json | |
| test -f logs/hardware/ros2-bridge-smoke.jsonl | |
| test -f logs/hardware/ros2-bridge-smoke-summary.json | |
| - name: Run runtime diagnostics smoke | |
| run: | | |
| mkdir -p logs/runtime | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/tools/mac_runtime_diagnostics.py \ | |
| logs/runtime/mac-runtime-diagnostics.json | |
| test -f logs/runtime/mac-runtime-diagnostics.json | |
| - name: Run uv bootstrap dry-run smoke | |
| run: | | |
| uv run scripts/bootstrap_uv_mlx.py --dry-run --venv .venv-bootstrap-smoke | |
| - name: Run MLX benchmark smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/benchmarks/mlx/benchmark_mac_tasks.py \ | |
| --task-group current-mac-native \ | |
| --num-envs 64 \ | |
| --steps 128 \ | |
| --json-out logs/benchmarks/mlx/smoke.json | |
| - name: Run MLX sensor benchmark smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/benchmarks/mlx/benchmark_mac_tasks.py \ | |
| --task-group sensor-mac-native \ | |
| --num-envs 32 \ | |
| --steps 64 \ | |
| --json-out logs/benchmarks/mlx/sensor-smoke.json | |
| - name: Run MLX full-suite dashboard smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/benchmarks/mlx/benchmark_mac_tasks.py \ | |
| --task-group full \ | |
| --num-envs 8 \ | |
| --steps 8 \ | |
| --train-updates 1 \ | |
| --rollout-steps 4 \ | |
| --epochs-per-update 1 \ | |
| --json-out logs/benchmarks/mlx/full-smoke.json | |
| - name: Verify semantic baseline against full-suite smoke | |
| run: | | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python \ | |
| scripts/benchmarks/mlx/check_semantic_drift.py \ | |
| --results logs/benchmarks/mlx/full-smoke.json \ | |
| --baseline scripts/benchmarks/mlx/baselines/semantic-baseline.json \ | |
| --snapshot-out logs/benchmarks/mlx/full-smoke-semantic-snapshot.json \ | |
| --report-out logs/benchmarks/mlx/full-smoke-semantic-report.json | |
| - name: Verify benchmark artifact payload | |
| run: | | |
| test -f logs/benchmarks/mlx/smoke.json | |
| test -f logs/benchmarks/mlx/smoke-dashboard.json | |
| test -f logs/benchmarks/mlx/smoke-trend.json | |
| test -f logs/benchmarks/mlx/release_install_smoke.json | |
| test -f logs/benchmarks/mlx/sensor-smoke.json | |
| test -f logs/benchmarks/mlx/sensor-smoke-dashboard.json | |
| test -f logs/benchmarks/mlx/sensor-smoke-trend.json | |
| test -f logs/benchmarks/mlx/full-smoke.json | |
| test -f logs/benchmarks/mlx/full-smoke-dashboard.json | |
| test -f logs/benchmarks/mlx/full-smoke-trend.json | |
| test -f logs/benchmarks/mlx/full-smoke-semantic-snapshot.json | |
| test -f logs/benchmarks/mlx/full-smoke-semantic-report.json | |
| PYTHONPATH=.:source/isaaclab .venv/bin/python - <<'PY' | |
| import json | |
| from pathlib import Path | |
| payload = json.loads(Path("logs/benchmarks/mlx/smoke.json").read_text(encoding="utf-8")) | |
| assert payload["task_group"] == "current-mac-native" | |
| assert payload["cpu_fallback_detected"] is False | |
| assert len(payload["benchmarks"]) >= 5 | |
| print(payload["tasks"]) | |
| dashboard = json.loads(Path("logs/benchmarks/mlx/smoke-dashboard.json").read_text(encoding="utf-8")) | |
| assert dashboard["summary"]["rollout_task_count"] == 24 | |
| assert dashboard["summary"]["training_task_count"] == 0 | |
| trend = json.loads(Path("logs/benchmarks/mlx/smoke-trend.json").read_text(encoding="utf-8")) | |
| assert trend["summary"]["task_count"] == 24 | |
| planner_payload = json.loads(Path("logs/planner/mac-planner-smoke.json").read_text(encoding="utf-8")) | |
| assert planner_payload["planner"]["implementation"] == "joint-space-linear-interpolation" | |
| assert planner_payload["plan"]["waypoint_count"] == 6 | |
| ros_payload = json.loads(Path("logs/hardware/ros2-bridge-smoke-summary.json").read_text(encoding="utf-8")) | |
| assert ros_payload["message_count"] == 6 | |
| assert ros_payload["pub_command"][:3] == ["ros2", "topic", "pub"] | |
| assert ros_payload["planner_roundtrip_ok"] is True | |
| assert ros_payload["trajectory_roundtrip_ok"] is True | |
| assert ros_payload["planner_batch_size"] == 2 | |
| assert ros_payload["trajectory_batch_size"] == 2 | |
| stereo_payload = json.loads(Path("logs/hardware/synthetic_depth/summary.json").read_text(encoding="utf-8")) | |
| assert stereo_payload["validated_capture"] is True | |
| assert stereo_payload["disparity_shape"] == [4, 4] | |
| assert stereo_payload["depth_mm_mean"] is not None | |
| assert Path(stereo_payload["left_rgb_path"]).is_file() | |
| runtime_payload = json.loads(Path("logs/runtime/mac-runtime-diagnostics.json").read_text(encoding="utf-8")) | |
| assert runtime_payload["runtime"]["supported_tasks"]["public_task_count"] == 28 | |
| assert runtime_payload["sim"]["supported_tasks"]["current_mac_native_count"] == 26 | |
| sensor_payload = json.loads(Path("logs/benchmarks/mlx/sensor-smoke.json").read_text(encoding="utf-8")) | |
| assert sensor_payload["task_group"] == "sensor-mac-native" | |
| assert sensor_payload["cpu_fallback_detected"] is False | |
| assert len(sensor_payload["benchmarks"]) == 4 | |
| benchmark_by_task = {benchmark["task"]: benchmark for benchmark in sensor_payload["benchmarks"]} | |
| for task in ("cartpole-rgb-camera", "cartpole-depth-camera"): | |
| benchmark = benchmark_by_task[task] | |
| assert benchmark["diagnostics"]["sensor"]["implementation"] == "analytic-cartpole-camera" | |
| assert benchmark["runtime"]["capabilities"]["sensor"]["cameras"] is False | |
| assert benchmark["runtime"]["capabilities"]["sensor"]["analytic_camera_tasks"] is True | |
| assert benchmark["image_shape"][:2] == [100, 100] | |
| assert benchmark["output_signature"]["final_frame_energy"] > 0.0 | |
| for task in ("anymal-c-flat-height-scan", "h1-flat-height-scan"): | |
| benchmark = benchmark_by_task[task] | |
| assert benchmark["sensor_scan_dim"] == 9 | |
| assert benchmark["runtime"]["capabilities"]["sensor"]["raycast"] is True | |
| assert benchmark["diagnostics"]["sensor"]["implementation"] == "analytic-terrain-raycast" | |
| assert benchmark["output_signature"]["height_scan_hit_ratio"] == 1.0 | |
| print(sensor_payload["tasks"]) | |
| release_payload = json.loads(Path("logs/benchmarks/mlx/release_install_smoke.json").read_text(encoding="utf-8")) | |
| assert release_payload["rough_cfg_type"] == "MacH1RoughEnvCfg" | |
| assert release_payload["stack_cfg_type"] == "MacFrankaStackRgbEnvCfg" | |
| assert release_payload["bin_stack_cfg_type"] == "MacFrankaBinStackEnvCfg" | |
| assert release_payload["stack_instance_cfg_type"] == "MacFrankaStackInstanceRandomizeEnvCfg" | |
| assert release_payload["teddy_cfg_type"] == "MacFrankaTeddyBearLiftEnvCfg" | |
| assert release_payload["ur10e_cfg_type"] == "MacUR10eDeployReachEnvCfg" | |
| assert release_payload["gear_2f140_cfg_type"] == "MacUR10eGearAssembly2F140EnvCfg" | |
| assert release_payload["gear_2f85_cfg_type"] == "MacUR10eGearAssembly2F85EnvCfg" | |
| assert release_payload["gear_2f140_ros_cfg_type"] == "MacUR10eGearAssembly2F140RosInferenceEnvCfg" | |
| assert release_payload["gear_2f85_ros_cfg_type"] == "MacUR10eGearAssembly2F85RosInferenceEnvCfg" | |
| assert release_payload["ur10_long_stack_cfg_type"] == "MacUR10LongSuctionStackEnvCfg" | |
| assert release_payload["ur10_short_stack_cfg_type"] == "MacUR10ShortSuctionStackEnvCfg" | |
| assert "anymal-c-rough" in release_payload["trainable_tasks"] | |
| assert "h1-rough" in release_payload["trainable_tasks"] | |
| assert "ur10e-deploy-reach" in release_payload["trainable_tasks"] | |
| assert "ur10e-gear-assembly-2f140" in release_payload["trainable_tasks"] | |
| assert "ur10e-gear-assembly-2f85" in release_payload["trainable_tasks"] | |
| assert "ur10-long-suction-stack" in release_payload["trainable_tasks"] | |
| assert "ur10-short-suction-stack" in release_payload["trainable_tasks"] | |
| assert "franka-teddy-bear-lift" in release_payload["trainable_tasks"] | |
| assert "franka-stack-instance-randomize" in release_payload["trainable_tasks"] | |
| assert "franka-bin-stack" in release_payload["trainable_tasks"] | |
| assert release_payload["eval_task"] == "h1-rough" | |
| assert release_payload["episodes_completed"] == 1 | |
| release_runtime_payload = json.loads(Path("logs/runtime/release-runtime-diagnostics.json").read_text(encoding="utf-8")) | |
| assert release_runtime_payload["runtime"]["supported_tasks"]["public_task_count"] == 28 | |
| assert release_runtime_payload["sim"]["supported_tasks"]["current_mac_native_count"] == 26 | |
| release_eval_payload = json.loads(Path("logs/runtime/release-eval.json").read_text(encoding="utf-8")) | |
| assert release_eval_payload["task"] == "h1-rough" | |
| assert release_eval_payload["episodes_completed"] == 1 | |
| assert release_eval_payload["task_spec"]["task"] == "h1-rough" | |
| assert release_eval_payload["task_spec"]["semantic_contract"] == "aligned" | |
| release_eval_split_payload = json.loads(Path("logs/runtime/release-eval-split.json").read_text(encoding="utf-8")) | |
| assert release_eval_split_payload["task"] == "h1-rough" | |
| assert release_eval_split_payload["episodes_completed"] == 1 | |
| assert release_eval_split_payload["task_spec"]["task"] == "h1-rough" | |
| assert release_eval_split_payload["task_spec"]["semantic_contract"] == "aligned" | |
| release_teddy_eval_payload = json.loads(Path("logs/runtime/release-teddy-eval.json").read_text(encoding="utf-8")) | |
| assert release_teddy_eval_payload["task"] == "franka-teddy-bear-lift" | |
| assert release_teddy_eval_payload["episodes_completed"] == 1 | |
| release_bin_stack_eval_payload = json.loads(Path("logs/runtime/release-bin-stack-eval.json").read_text(encoding="utf-8")) | |
| assert release_bin_stack_eval_payload["task"] == "franka-bin-stack" | |
| assert release_bin_stack_eval_payload["episodes_completed"] == 1 | |
| assert release_bin_stack_eval_payload["task_spec"]["task"] == "franka-bin-stack" | |
| assert release_bin_stack_eval_payload["task_spec"]["semantic_contract"] == "reduced-no-mimic" | |
| assert release_bin_stack_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_gear_2f140_eval_payload = json.loads(Path("logs/runtime/release-gear-2f140-eval.json").read_text(encoding="utf-8")) | |
| assert release_gear_2f140_eval_payload["task"] == "ur10e-gear-assembly-2f140" | |
| assert release_gear_2f140_eval_payload["episodes_completed"] == 1 | |
| assert release_gear_2f140_eval_payload["task_spec"]["semantic_contract"] == "reduced-analytic-assembly" | |
| assert release_gear_2f140_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_gear_2f85_eval_payload = json.loads(Path("logs/runtime/release-gear-2f85-eval.json").read_text(encoding="utf-8")) | |
| assert release_gear_2f85_eval_payload["task"] == "ur10e-gear-assembly-2f85" | |
| assert release_gear_2f85_eval_payload["episodes_completed"] == 1 | |
| assert release_gear_2f85_eval_payload["task_spec"]["semantic_contract"] == "reduced-analytic-assembly" | |
| assert release_gear_2f85_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_gear_2f140_ros_eval_payload = json.loads( | |
| Path("logs/runtime/release-gear-2f140-ros-eval.json").read_text(encoding="utf-8") | |
| ) | |
| assert release_gear_2f140_ros_eval_payload["task"] == "ur10e-gear-assembly-2f140" | |
| assert release_gear_2f140_ros_eval_payload["episodes_completed"] == 1 | |
| assert release_gear_2f140_ros_eval_payload["task_spec"]["semantic_contract"] == "reduced-no-ros-inference" | |
| assert release_gear_2f140_ros_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_gear_2f85_ros_eval_payload = json.loads( | |
| Path("logs/runtime/release-gear-2f85-ros-eval.json").read_text(encoding="utf-8") | |
| ) | |
| assert release_gear_2f85_ros_eval_payload["task"] == "ur10e-gear-assembly-2f85" | |
| assert release_gear_2f85_ros_eval_payload["episodes_completed"] == 1 | |
| assert release_gear_2f85_ros_eval_payload["task_spec"]["semantic_contract"] == "reduced-no-ros-inference" | |
| assert release_gear_2f85_ros_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_ur10_long_stack_eval_payload = json.loads( | |
| Path("logs/runtime/release-ur10-long-stack-eval.json").read_text(encoding="utf-8") | |
| ) | |
| assert release_ur10_long_stack_eval_payload["task"] == "ur10-long-suction-stack" | |
| assert release_ur10_long_stack_eval_payload["episodes_completed"] == 1 | |
| assert release_ur10_long_stack_eval_payload["task_spec"]["semantic_contract"] == "reduced-analytic-suction-stack" | |
| assert release_ur10_long_stack_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_ur10_short_stack_eval_payload = json.loads( | |
| Path("logs/runtime/release-ur10-short-stack-eval.json").read_text(encoding="utf-8") | |
| ) | |
| assert release_ur10_short_stack_eval_payload["task"] == "ur10-short-suction-stack" | |
| assert release_ur10_short_stack_eval_payload["episodes_completed"] == 1 | |
| assert release_ur10_short_stack_eval_payload["task_spec"]["semantic_contract"] == "reduced-analytic-suction-stack" | |
| assert release_ur10_short_stack_eval_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| release_gear_2f140_train_payload = json.loads(Path("logs/runtime/release-gear-2f140-train.json").read_text(encoding="utf-8")) | |
| assert release_gear_2f140_train_payload["task"] == "ur10e-gear-assembly-2f140" | |
| assert release_gear_2f140_train_payload["task_spec"]["semantic_contract"] == "reduced-analytic-assembly" | |
| assert Path(release_gear_2f140_train_payload["checkpoint_path"]).exists() | |
| release_ur10_long_stack_train_payload = json.loads( | |
| Path("logs/runtime/release-ur10-long-stack-train.json").read_text(encoding="utf-8") | |
| ) | |
| assert release_ur10_long_stack_train_payload["task"] == "ur10-long-suction-stack" | |
| assert release_ur10_long_stack_train_payload["task_spec"]["semantic_contract"] == "reduced-analytic-suction-stack" | |
| assert release_ur10_long_stack_train_payload["task_spec"]["upstream_alias_semantics_preserved"] is False | |
| assert Path(release_ur10_long_stack_train_payload["checkpoint_path"]).exists() | |
| release_stack_instance_eval_payload = json.loads( | |
| Path("logs/runtime/release-stack-instance-eval.json").read_text(encoding="utf-8") | |
| ) | |
| assert release_stack_instance_eval_payload["task"] == "franka-stack-instance-randomize" | |
| assert release_stack_instance_eval_payload["episodes_completed"] == 1 | |
| release_train_payload = json.loads(Path("logs/runtime/release-train.json").read_text(encoding="utf-8")) | |
| assert release_train_payload["task"] == "cartpole" | |
| assert release_train_payload["task_spec"]["task"] == "cartpole" | |
| assert release_train_payload["task_spec"]["semantic_contract"] == "aligned" | |
| assert Path(release_train_payload["checkpoint_path"]).exists() | |
| release_train_split_payload = json.loads(Path("logs/runtime/release-train-split.json").read_text(encoding="utf-8")) | |
| assert release_train_split_payload["task"] == "cartpole" | |
| assert release_train_split_payload["task_spec"]["task"] == "cartpole" | |
| assert release_train_split_payload["task_spec"]["semantic_contract"] == "aligned" | |
| assert Path(release_train_split_payload["checkpoint_path"]).exists() | |
| full_payload = json.loads(Path("logs/benchmarks/mlx/full-smoke.json").read_text(encoding="utf-8")) | |
| assert full_payload["task_group"] == "full" | |
| full_dashboard = json.loads(Path("logs/benchmarks/mlx/full-smoke-dashboard.json").read_text(encoding="utf-8")) | |
| assert full_dashboard["summary"]["rollout_task_count"] == 30 | |
| assert full_dashboard["summary"]["training_task_count"] == 1 | |
| full_trend = json.loads(Path("logs/benchmarks/mlx/full-smoke-trend.json").read_text(encoding="utf-8")) | |
| assert full_trend["summary"]["task_count"] == 31 | |
| assert any(entry["kind"] == "training" for entry in full_trend["tasks"]) | |
| semantic_report = json.loads(Path("logs/benchmarks/mlx/full-smoke-semantic-report.json").read_text(encoding="utf-8")) | |
| assert semantic_report["passed"] is True | |
| assert semantic_report["baseline_task_count"] == 30 | |
| assert semantic_report["current_task_count"] == 30 | |
| PY | |
| - name: Upload MLX smoke artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: mlx-macos-smoke-${{ github.run_id }} | |
| path: logs/benchmarks/mlx | |
| if-no-files-found: warn | |
| retention-days: 14 |