AdrianLlopart's picture
docs: HF model card β€” best-of-both front-matter derived from manifest
0364dc0 verified
|
Raw
History Blame Contribute Delete
9.44 kB
---
language:
- en
license: apache-2.0
pipeline_tag: robotics
tags:
- OpenRAL
- rskill
- ros2
- moveit
- franka_panda
- ur5e
- ur10e
- so100_follower
- openarm
- rizon4
- sawyer
- widowx
inference: false
---
# rskill-moveit-look-at
Aim a robot-mounted camera at a 3-D point (ADR-0044 Phase 3; renamed from
`openral/rskill-look-at` under [ADR-0054](../../docs/adr/0054-moveit-goal-builder-library.md)).
A `kind: ros_action` rSkill wrapping `moveit_msgs/action/MoveGroup` β€” like
[`rskill-moveit-joints`](../rskill-moveit-joints/), but the goal is a
`look_at` block instead of raw constraints, and `ros_integration.goal_builder:
look_at` selects the `LookAtRskill` adapter that lowers it into MoveGroup
pose constraints.
## What this skill does
Given a target point and a camera name, plans a collision-aware arm motion
that points the named camera's optical axis at the target β€” so a later
perception query (`locate_in_view`) or manipulation skill sees the object
framed. It is the "look" rung of the ADR-0044 *recall β†’ navigate β†’ look β†’
verify β†’ manipulate* ladder.
## How it works
`ros_integration.goal_builder: look_at` selects `LookAtRskill`
(`openral_rskill.look_at_rskill`), which lowers the `look_at` block at dispatch
time:
1. **Resolve the camera** named by `look_at.camera` (default `"wrist"`) from
the host `RobotDescription.sensors`. No such sensor β†’ `ROSConfigError`
listing the robot's available sensors β€” never a silent guess. A sensor
whose `frame_id` is itself a robot link (franka's LIBERO eye-in-hand on
`panda_hand`) is constrained directly; a sensor with `parent_frame` +
`static_transform_xyz_rpy` (so101-style mount) constrains the parent link
through the declared offset.
2. **Read the camera's current pose over TF2** (the only source of frames) in
the goal frame.
3. **Place the camera goal** β€” in place (pure re-aim, the default) or at
`look_at.standoff_m` from the target along the current line of approach.
4. **Orient it** with `compute_gaze_pose` (ROS optical convention: camera +Z
hits `look_at.target_xyz`; roll about the optical axis left free at
tolerance Ο€ for planner reachability) and submit MoveGroup
`position_constraints` + `orientation_constraints`.
`plan_only: true`, deliberately: OpenRAL's actuation path is the per-waypoint
replay through `/openral/candidate_action` (`chunk_size: 1`, so the safety
supervisor's per-joint envelope check sees every aiming step, and the HAL
actuates). Letting `move_group` also execute on its own controllers would
bypass the kernel and double-drive the arm.
### Observation β†’ action contract
Input is the ADR-0026 `goal_params_json` `look_at` block; output is a joint
trajectory replayed one waypoint per `step()` as a 1-row `JOINT_POSITION`
`Action` chunk.
```json
{"look_at": {"target_xyz": [0.5, 0.0, 0.2], "camera": "wrist"}}
```
Planner settings (`request.group_name`, scaling, attempts) are inherited from
`default_goal_json`. Omit `standoff_m` to re-aim in place; set it to also move
the camera to that distance from the target.
### GPU-accelerated planning (cuMotion, ADR-0065)
On a host that clears the cuMotion GPU floor (`RobotCapabilities.supports_cumotion()`
β€” Ampere+, CUDA β‰₯ 13, ~8 GB VRAM), the runner sets
`MotionPlanRequest.pipeline_id = "isaac_ros_cumotion"` so MoveIt plans with
NVIDIA's CUDA-accelerated cuMotion pipeline; otherwise it falls back to OMPL.
Transparent β€” same skill, no manifest change β€” and it never bypasses the safety
kernel: the planned trajectory still replays through `/openral/candidate_action`
and is validated waypoint-by-waypoint. Install: see
[`docs/contributing/toolchain.md`](../../docs/contributing/toolchain.md) β†’
"GPU motion planning β€” cuMotion".
## How it was trained / Upstream provenance
Nothing is trained β€” this rSkill wraps the upstream MoveIt motion planner and
computes the gaze pose analytically.
| Field | Value |
| --- | --- |
| Upstream | [`moveit_msgs/action/MoveGroup`](https://github.com/moveit/moveit_msgs/blob/master/action/MoveGroup.action) (BSD-3-Clause) |
| Planner library | [MoveIt 2](https://moveit.picknik.ai/) (BSD-3-Clause) |
| Gaze geometry | `openral_world_state.geometry.compute_gaze_pose` (Apache-2.0, in-tree) |
| Collision check | FCL via MoveIt's `PlanningScene` (run during planning) |
| Wrapped artefact | rSkill manifest + README β€” no weights, no preprocessor JSONs |
## Supported robots / embodiments
| Robot | Embodiment tag | Status | Notes |
| --- | --- | --- | --- |
| Franka Panda | `franka_panda` | validated | default goal targets `panda_arm`; camera `wrist` = LIBERO eye-in-hand on `panda_hand` |
| Universal Robots UR5e | `ur5e` | experimental | needs `request.group_name` + `look_at.camera`/`frame_id` overrides |
| Universal Robots UR10e | `ur10e` | experimental | same as UR5e |
| SO-100 follower | `so100_follower` | experimental | needs a MoveIt config; `wrist` cam declares a static mount |
| OpenArm | `openarm` | experimental | bi-manual β€” choose `left_arm`/`right_arm` group |
| Flexiv Rizon4 | `rizon4` | experimental | upstream MoveIt config exists; manifest override needed |
| Rethink Sawyer | `sawyer` | experimental | upstream MoveIt config exists |
| Trossen WidowX | `widowx` | experimental | upstream MoveIt config exists |
A robot must declare the named camera (default `wrist`) in its `robot.yaml`
sensors, or the skill fails at configure with the available-sensor list.
Listed `embodiment_tags` only gate palette visibility; actual resolution needs
`move_group` up for that robot.
## Sensors required / Observation contract
This skill consumes no camera frames through OpenRAL's sensor pipeline β€” it
*aims* a camera, it doesn't read one. It needs the named camera's **frame** to
exist in TF (declared in the robot manifest + published by
`robot_state_publisher`), plus MoveIt's own subscriptions:
| Source | Topic / contract | Why it's needed |
| --- | --- | --- |
| Camera frame | TF `frame_id` of `look_at.camera` (default `wrist`) | Read the camera's current pose; target the gaze |
| Joint state | `/joint_states` | Plan from the live start state |
| Planning scene | `/planning_scene` | Collision check during planning |
| TF | `/tf`, `/tf_static` | Resolve camera + link frames |
## Manifest summary
| Field | Value |
| --- | --- |
| `name` | `OpenRAL/rskill-moveit-look-at` |
| `version` | `0.1.0` |
| `license` | `apache-2.0` |
| `kind` | `ros_action` |
| `role` | `s1` |
| `actions` | `[look]` |
| `chunk_size` | `1` (schema-enforced for `kind: ros_action`) |
| `latency_budget.per_chunk_ms` | `2000` (planning latency) |
| `ros_integration.package` | `moveit_msgs` |
| `ros_integration.interface_type` | `MoveGroup` |
| `ros_integration.interface_name` | `/move_action` |
| `ros_integration.goal_builder` | `look_at` (selects `LookAtRskill`) |
| `ros_integration.result_trajectory_field` | `planned_trajectory.joint_trajectory` |
| `commercial_use_allowed` | `true` (apache-2.0) |
Full schema:
[`openral_core.schemas.RSkillManifest`](../../python/core/src/openral_core/schemas.py).
## Quick start
```python
from openral_rskill.loader import rSkill
pkg = rSkill.from_yaml("rskills/rskill-moveit-look-at/rskill.yaml")
print(pkg.manifest.name, pkg.manifest.ros_integration.goal_builder)
```
End-to-end, with a real MoveIt launch up:
```bash
# 1. Bring up MoveIt for your robot (example: Panda)
ros2 launch moveit_resources_panda_moveit_config demo.launch.py
# 2. Dispatch a look-at goal (aim the wrist camera at a tabletop point):
ros2 action send_goal /openral/execute_rskill openral_msgs/action/ExecuteRskill \
"{rskill_id: 'OpenRAL/rskill-moveit-look-at', deadline_s: 30.0, prompt: 'look at the mug',
goal_params_json: '{\"look_at\": {\"target_xyz\": [0.5, 0.0, 0.2], \"camera\": \"wrist\"}}'}"
```
## Limitations / Roadmap
- **Reachability is the planner's call.** Roll about the optical axis is left
free, but a target outside the arm's dexterous workspace simply fails to
plan β€” there's no base-repositioning fallback here (that's the navigate rung
of the ladder, ADR-0044 Phase 4).
- **Single-camera aim.** One camera per dispatch; multi-camera coverage is a
reasoner-level concern.
- **No velocity / jerk bound at the supervisor.** Same posture as
`rskill-moveit-joints`: the per-joint position envelope runs per
waypoint; richer bounds are tracked separately.
## License
The rSkill package itself (this manifest + README) is **Apache-2.0**. The
wrapped MoveIt code (`moveit_msgs` IDL, `moveit2` planners) is **BSD-3-Clause**
and is installed via `ros-${ROS_DISTRO}-moveit`, outside this repository. Per
[ADR-0012](../../docs/adr/0012-open-core-licensing.md) both postures are
commercial-use-permissive.
## See also
- [ADR-0054 β€” MoveIt goal-builder library + rskill-moveit-* rename](../../docs/adr/0054-moveit-goal-builder-library.md)
- [ADR-0044 β€” look_at skill + grid-refined approach](../../docs/adr/0044-look-at-skill-grid-refined-approach.md)
- [`openral_rskill.look_at_rskill`](../../python/rskill/src/openral_rskill/look_at_rskill.py) β€” adapter source
- [`openral_world_state.geometry`](../../python/world_state/src/openral_world_state/geometry.py) β€” gaze math
- [`rskills/rskill-moveit-joints/`](../rskill-moveit-joints/) β€” sibling joint-space MoveIt wrapper
- [`rskills/rskill-moveit-eef-pose/`](../rskill-moveit-eef-pose/) β€” sibling Cartesian end-effector pose wrapper