Support classical motion planners (cuRobo, MoveIt2) as Policy providers
enhancementpolicy
## Summary
Ship classical motion planners as first-class `Policy` providers. The `Policy` ABC is already provider-agnostic and the non-VLA contract (docstring + well-known `**kwargs` goal keys) landed in #300. What remains is two reference implementations behind opt-in extras, both routed through the same `create_policy(...)` factory used for VLA providers:
1. **`CuroboPolicy`** under `[curobo]` — GPU motion generation, in-process.
2. **`MoveIt2Policy`** under `[moveit2]` — thin ZMQ client to a ROS 2 sidecar (mirrors `Gr00tPolicy(host=..., port=...)`).
Both set `requires_images = False`, read goals from the `**kwargs` contract (`target_pose`, `target_joints`, `world_update`), and fall back to `_parse_target(instruction)` for LLM-agent compatibility.
> Consolidates #299 (umbrella), #301 (cuRobo), #302 (MoveIt2) into a single ticket. Subtask 1 (API cleanup / non-VLA docstring + kwargs surface) already shipped in #300.
## Motivation
Users running industrial / contact-light tasks want **deterministic collision-aware motion planning** rather than a learned VLA policy:
- "Reach to (x, y, z) without hitting the table" — cuRobo / MoveIt2 do this in 30–100 ms with full collision checking.
- LLM-agent composition: the agent can pick *which* provider per step (cuRobo for the global reach, GR00T for the contact-rich grasp).
- Reproducible / certifiable motions for regulated environments where neural-net stochasticity is unacceptable.
Today only VLA-style providers ship (`mock`, `groot`, `lerobot_local`); `MockPolicy` is the lone `requires_images=False` example.
## What already exists (post-#300)
- `Policy.get_actions(observation_dict, instruction, **kwargs) -> list[dict]` — generic.
- `requires_images: bool` opt-out (default `True`; `MockPolicy` returns `False`).
- `register_policy(name, loader, aliases)` in `policies/factory.py` — third-party providers without core changes.
- `hardware_robot.py` policy execution loop is provider-agnostic.
- Documented `**kwargs` goal keys: `target_pose: [x, y, z, qw, qx, qy, qz]`, `target_joints: dict[str, float]`, `world_update: dict | None`.
---
## Part A — `CuroboPolicy` under `[curobo]` extra
- [ ] New module `strands_robots/policies/curobo/policy.py` — `CuroboPolicy(Policy)`.
- [ ] At init: `MotionGenConfig.load_from_robot_config(robot_yaml, world_config, ...)` → `MotionGen` instance.
- [ ] `requires_images = False`; `get_actions` reads `observation.state` (no images), pulls goal from `kwargs["target_pose"]` / `kwargs["target_joints"]`, falls back to `_parse_target(instruction)`.
- [ ] Cache the full trajectory; yield `action_horizon`-sized chunks per `get_actions` call to match the 50 Hz execution loop.
- [ ] Register in `strands_robots/registry/policies.json` with shorthand `cumotion`, alias `curobo`.
- [ ] `pyproject.toml` extra `[curobo]` pinning `nvidia-curobo>=0.7.4,<0.8.0`.
- [ ] Smoke test `tests/policies/curobo/` — `create_policy("curobo", ...)` with a stub `MotionGen` (no GPU).
- [ ] Integration test `tests_integ/policies/curobo/` — plan a UR5e reach, assert collision-free, execute in sim.
- [ ] README "Non-VLA Policies" gains a `CuroboPolicy` example.
## Part B — `MoveIt2Policy` under `[moveit2]` extra (service mode)
The `Policy` is a **thin client**; ROS 2 / MoveIt2 lives in a sidecar so users without ROS 2 sourced are unaffected.
**Wire protocol** (ZMQ + msgpack, mirroring `Gr00tPolicy`):
```
request = {joint_state: [...], target_pose | target_joints, planning_group: str}
response = {trajectory: [[t, q0, q1, ...], ...], success: bool, status: str}
```
- [ ] `strands_robots/policies/moveit2/policy.py` — `MoveIt2Policy(Policy)` client.
- [ ] `strands_robots/policies/moveit2/server/` — ROS 2 node example (Python, `moveit_py`).
- [ ] `requires_images = False`; client reads goal from the `**kwargs` contract (`target_pose`, `target_joints`, `world_update`).
- [ ] `pyproject.toml` extra `[moveit2]` (client only: `pyzmq`, `msgpack`); ROS 2 deps stay out of `pyproject.toml`.
- [ ] Docker compose for the server side; document `ros2 run` invocation as the alternative.
- [ ] Register in `strands_robots/registry/policies.json` with shorthand `moveit2`, alias `moveit`.
- [ ] Smoke test `tests/policies/moveit2/` — `create_policy("moveit2", host=..., port=...)` against a stubbed ZMQ socket.
- [ ] Integration test `tests_integ/policies/moveit2/`, gated on a `moveit2` integ marker — plan + execute a collision-free reach via the ZMQ sidecar.
- [ ] README "Non-VLA Policies" gains a `MoveIt2Policy` example.
## Part C — Mesh dispatch for sim peers (follow-up, may split)
`tell()` only dispatches to `start_task` / `_execute_task_sync`, which are HardwareRobot-only. Sim peers receiving `tell()` for policy execution should map to `Simulation.start_policy` / `run_policy` so cuRobo/MoveIt2 work end-to-end on sim peers too. Track as a sister issue if it grows.
## Out of scope
- Real-time guarantees (both planners give best-effort; safety guarantees are user-side).
- Replacing existing VLA providers.
- Bundling cuRobo/MoveIt2 as core deps — both stay opt-in extras.
## Acceptance criteria
- [ ] `register_policy("curobo", ...)` works end-to-end against a UR5e in sim.
- [ ] `MoveIt2Policy(host=..., port=...)` plans + executes a reach against a sim peer.
- [ ] At least one `tests_integ/` test per provider plans + executes a collision-free reach (MoveIt2 gated on its marker).
- [ ] `MockPolicy` + `CuroboPolicy` + `MoveIt2Policy` all pass the same `Policy`-shape contract test from #300.
- [ ] LLM-agent demo: `start_task(..., policy_provider="curobo"|"moveit2", target_pose=[...])` runs the trajectory.
## References
- ABC + kwargs contract: #300
- `strands_robots/policies/base.py` — Policy ABC (post-#300 kwargs surface)
- `strands_robots/policies/factory.py` — `register_policy`
- `strands_robots/policies/mock.py` — non-VLA reference (`requires_images=False`)
- `strands_robots/policies/groot/policy.py` — `Gr00tPolicy(host=..., port=...)` service-mode reference
- `strands_robots/hardware_robot.py` — provider-agnostic execution loop
- `strands_robots/registry/policies.json` — built-in provider registry
- cuRobo: https://curobo.org/ · MoveIt2: https://github.com/moveit/moveit2
---
_Supersedes and consolidates #299, #301, #302._
关闭于 2026-06-14 0 条评论