-
Notifications
You must be signed in to change notification settings - Fork 0
Added curobo v2 planner interface for SkillGen #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,34 +3,78 @@ | |||||||||||||||
|
|
||||||||||||||||
| """Motion-planner backends for SkillGen. | ||||||||||||||||
|
|
||||||||||||||||
| This branch ships the cuRobo v1 backend only. The package exposes the abstract | ||||||||||||||||
| :class:`MotionPlannerBase` and the v1 :class:`CuroboPlanner` / :class:`CuroboPlannerCfg`. | ||||||||||||||||
| Two cuRobo backends ship here, selected by name through :func:`get_planner_backend`: | ||||||||||||||||
|
|
||||||||||||||||
| The planner class is imported lazily so the configuration dataclass and the abstract base can be | ||||||||||||||||
| loaded in sim-free contexts (e.g. unit tests or CLI argument parsing) without pulling in cuRobo | ||||||||||||||||
| or Isaac Lab. | ||||||||||||||||
| * ``"curobo"`` — :class:`CuroboPlanner` / :class:`CuroboPlannerCfg`, built on cuRobo v1. | ||||||||||||||||
| * ``"curobo_v2"`` — :class:`CuroboV2Planner` / :class:`CuroboV2PlannerCfg`, built on cuRobo v2. | ||||||||||||||||
|
|
||||||||||||||||
| Both implement :class:`MotionPlannerBase` and accept the same profile names, so an entry point | ||||||||||||||||
| picks a backend without changing any other logic. | ||||||||||||||||
|
|
||||||||||||||||
| Nothing is imported at module load. Both cuRobo versions install under the ``curobo`` package | ||||||||||||||||
| name at incompatible versions and live in separate environments, so importing a backend that is | ||||||||||||||||
| not installed would fail. Resolution waits until a backend is requested. | ||||||||||||||||
| """ | ||||||||||||||||
|
|
||||||||||||||||
| from __future__ import annotations | ||||||||||||||||
|
|
||||||||||||||||
| from typing import TYPE_CHECKING | ||||||||||||||||
| from typing import TYPE_CHECKING, Any | ||||||||||||||||
|
|
||||||||||||||||
| from isaac_autodata_interfaces.motion_planners.curobo import CuroboPlannerCfg | ||||||||||||||||
| from isaac_autodata_interfaces.motion_planners.motion_planner_base import MotionPlannerBase | ||||||||||||||||
|
|
||||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||||
| from isaac_autodata_interfaces.motion_planners.curobo import CuroboPlanner | ||||||||||||||||
| from isaac_autodata_interfaces.motion_planners.curobo import CuroboPlanner, CuroboPlannerCfg | ||||||||||||||||
| from isaac_autodata_interfaces.motion_planners.curobo_v2 import CuroboV2Planner, CuroboV2PlannerCfg | ||||||||||||||||
|
|
||||||||||||||||
| __all__ = [ | ||||||||||||||||
| "MotionPlannerBase", | ||||||||||||||||
| "CuroboPlanner", | ||||||||||||||||
| "CuroboPlannerCfg", | ||||||||||||||||
| "CuroboV2Planner", | ||||||||||||||||
| "CuroboV2PlannerCfg", | ||||||||||||||||
| "PLANNER_BACKENDS", | ||||||||||||||||
| "get_planner_backend", | ||||||||||||||||
| ] | ||||||||||||||||
|
|
||||||||||||||||
| # Backend name -> (subpackage, planner class name, config class name). | ||||||||||||||||
| _BACKEND_SPECS: dict[str, tuple[str, str, str]] = { | ||||||||||||||||
| "curobo": ("curobo", "CuroboPlanner", "CuroboPlannerCfg"), | ||||||||||||||||
| "curobo_v2": ("curobo_v2", "CuroboV2Planner", "CuroboV2PlannerCfg"), | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| PLANNER_BACKENDS: tuple[str, ...] = tuple(_BACKEND_SPECS) | ||||||||||||||||
| """Names of the selectable planner backends, in registration order. | ||||||||||||||||
|
|
||||||||||||||||
| ``"curobo"`` is the cuRobo v1 backend and the default; ``"curobo_v2"`` is the cuRobo v2 backend. | ||||||||||||||||
| """ | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| def get_planner_backend(name: str) -> tuple[type[MotionPlannerBase], type]: | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win Use a concrete configuration-class type. The public As per coding guidelines, public interfaces must use concrete types instead of bare Proposed annotation-def get_planner_backend(name: str) -> tuple[type[MotionPlannerBase], type]:
+def get_planner_backend(
+ name: str,
+) -> tuple[
+ type[MotionPlannerBase],
+ type[CuroboPlannerCfg] | type[CuroboV2PlannerCfg],
+]:📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Coding guidelines |
||||||||||||||||
| """Resolve a backend name to its planner and configuration classes. | ||||||||||||||||
|
|
||||||||||||||||
| Importing the backend pulls in the matching cuRobo version, so only the requested backend | ||||||||||||||||
| is loaded. | ||||||||||||||||
|
|
||||||||||||||||
| Args: | ||||||||||||||||
| name: Backend name; one of :data:`PLANNER_BACKENDS`. | ||||||||||||||||
|
|
||||||||||||||||
| Returns: | ||||||||||||||||
| The ``(planner_class, config_class)`` pair for the backend. The planner takes | ||||||||||||||||
| ``(datastream, config, env_id)`` and the config exposes ``from_profile`` / | ||||||||||||||||
| ``from_task_name``. | ||||||||||||||||
| """ | ||||||||||||||||
| assert name in _BACKEND_SPECS, f"Unknown planner backend {name!r}. Available: {list(PLANNER_BACKENDS)}" | ||||||||||||||||
| import importlib | ||||||||||||||||
|
|
||||||||||||||||
| subpackage, planner_name, config_name = _BACKEND_SPECS[name] | ||||||||||||||||
| module = importlib.import_module(f"{__name__}.{subpackage}") | ||||||||||||||||
| return getattr(module, planner_name), getattr(module, config_name) | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| def __getattr__(name: str): | ||||||||||||||||
| if name == "CuroboPlanner": | ||||||||||||||||
| from isaac_autodata_interfaces.motion_planners.curobo import CuroboPlanner as _CuroboPlanner | ||||||||||||||||
| def __getattr__(name: str) -> Any: | ||||||||||||||||
| for subpackage, planner_name, config_name in _BACKEND_SPECS.values(): | ||||||||||||||||
| if name in (planner_name, config_name): | ||||||||||||||||
| import importlib | ||||||||||||||||
|
|
||||||||||||||||
| return _CuroboPlanner | ||||||||||||||||
| raise AttributeError(f"module 'motion_planners' has no attribute {name!r}") | ||||||||||||||||
| return getattr(importlib.import_module(f"{__name__}.{subpackage}"), name) | ||||||||||||||||
| raise AttributeError(f"module {__name__!r} has no attribute {name!r}") | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """cuRobo v2 motion-planner backend. | ||
|
|
||
| Implements :class:`MotionPlannerBase` on :class:`curobo.motion_planner.MotionPlanner`. | ||
|
|
||
| The planner is imported lazily so the configuration can be loaded without a simulator, for | ||
| backend selection or CLI argument parsing. Both cuRobo versions install under the ``curobo`` | ||
| package name, so only the selected backend is ever imported. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| if TYPE_CHECKING: | ||
| from isaac_autodata_interfaces.motion_planners.curobo_v2.curobo_v2_planner import CuroboV2Planner | ||
|
|
||
| from isaac_autodata_interfaces.motion_planners.curobo_v2.curobo_v2_planner_cfg import CuroboV2PlannerCfg | ||
|
|
||
| __all__ = [ | ||
| "CuroboV2Planner", | ||
| "CuroboV2PlannerCfg", | ||
| ] | ||
|
|
||
|
|
||
| def __getattr__(name: str): | ||
| if name == "CuroboV2Planner": | ||
| from isaac_autodata_interfaces.motion_planners.curobo_v2.curobo_v2_planner import ( | ||
| CuroboV2Planner as _CuroboV2Planner, | ||
| ) | ||
|
|
||
| return _CuroboV2Planner | ||
| raise AttributeError(f"module 'curobo_v2' has no attribute {name!r}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Sort
__all__to satisfy Ruff RUF022.Ruff reports
__all__as unsorted. Ruff's isort-style order places SCREAMING_SNAKE_CASE first, then CamelCase, then snake_case.♻️ Proposed fix
Run
ruff check --fixon the file to confirm the exact expected order.📝 Committable suggestion
🧰 Tools
🪛 Ruff (0.16.1)
[warning] 29-37:
__all__is not sortedApply an isort-style sorting to
__all__(RUF022)
🤖 Prompt for AI Agents
Source: Linters/SAST tools