File size: 7,614 Bytes
b520531
 
124e415
 
 
 
 
 
 
 
 
 
b520531
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
---
language:
- en
license: apache-2.0
pipeline_tag: robotics
tags:
- OpenRAL
- rskill
- ros2
- mobile_base
- nav2
inference: false
---

# rskill-nav2-navigate-to-pose

> **OpenRAL rSkill** β€” wraps the upstream `nav2_msgs/action/NavigateToPose`
> action server as an OpenRAL rSkill so the Reasoner can dispatch
> mobile-base navigation through the same `ExecuteSkill` path used by
> VLA skills. **Result-only mode** β€” Nav2's behaviour tree publishes
> `/cmd_vel` directly to the base controller; no `Action` chunk flows
> through OpenRAL's safety supervisor.

This package uses `kind: ros_action` (see
[ADR-0024](../../docs/adr/0024-ros-wrapped-rskills.md)) with
`ros_integration.result_trajectory_field: null` to put the
[`ROSActionRskill`](../../python/rskill/src/openral_rskill/ros_action_rskill.py)
adapter into result-only mode: it sends the goal, awaits the action
result, and raises `ROSRskillGoalSatisfied` on success. Compare with
the sibling [`rskill-moveit-joints`](../rskill-moveit-joints/)
skill, which sets `result_trajectory_field` and replays a joint
trajectory one waypoint at a time.

## What this skill does

Navigates the mobile base to a fixed `geometry_msgs/PoseStamped` target
in the `map` frame via Nav2's `NavigateToPose` action. The default goal
points at the map origin; override `ros_integration.default_goal_json`
in a per-deployment copy for real targets.

| Field | Value |
| --- | --- |
| Actions | `navigate` |
| Objects | _none_ |
| Scenes  | `indoor` |
| Embodiment | mobile-manipulator and similar mobile-base embodiments |

## How it works

`ROSActionRskill` is a thin `rSkillBase` shim around an `ActionClient`:

1. `_configure_impl` lazy-imports `nav2_msgs.action.NavigateToPose`,
   opens an `ActionClient` on `/navigate_to_pose` from the
   `RskillRunnerNode`-supplied node handle, and parses
   `ros_integration.default_goal_json` once.
2. On the first `_step_impl(world_state)` call the adapter sends the
   goal, polls the goal-accept + result futures while the host node's
   main rclpy spin services callbacks, and β€” because
   `result_trajectory_field is None` β€” raises
   `ROSRskillGoalSatisfied` immediately on success. The runner catches
   it specifically and closes the `ExecuteSkill` goal with
   `success=True`.

### Observation β†’ action contract (result-only mode)

| Direction | Key | Shape | Notes |
| --- | --- | --- | --- |
| in  | `world_state.joint_state` | unused | Nav2 consumes its own sensor topics (laser, odom, camera) |
| out | _none via OpenRAL_ | β€” | Nav2's behaviour tree publishes `/cmd_vel` directly to the base controller |

**Safety implication.** No `ActionChunk` is published on
`/openral/candidate_action`, so the OpenRAL safety supervisor does NOT
see Nav2's velocity commands. Collision avoidance relies entirely on
Nav2's costmap + behaviour tree. The follow-up that brings velocity
streams under the supervisor's envelope is tracked in ADR-0024's
Β§Out-of-scope and depends on (a) a mobile-base HAL declaring
`body_twist` in `supported_control_modes` (none exist in-tree today),
and (b) a velocity / jerk envelope landing in the supervisor (it
currently checks per-joint position only).

## How it was trained / Upstream provenance

Nothing is trained β€” this rSkill wraps the upstream Nav2 stack.

| Field | Value |
| --- | --- |
| Upstream | [`nav2_msgs/action/NavigateToPose`](https://github.com/ros-navigation/navigation2/blob/main/nav2_msgs/action/NavigateToPose.action) (Apache-2.0) |
| Planner library | [Nav2](https://docs.nav2.org/) (Apache-2.0) |
| Costmap / behaviour tree | Nav2's own subsystems β€” see Nav2 docs |
| Wrapped artefact | rSkill manifest + README β€” no weights |

## Supported robots / embodiments

| Robot | Embodiment tag | Status | Notes |
| --- | --- | --- | --- |
| Panda Mobile | `panda_mobile` | experimental | no HAL accepting `body_twist` ships in-tree yet; resolution depends on the deployment wiring its own mobile-base HAL or running Nav2's controllers against a sim |
| Generic mobile-manipulator | `mobile_manipulator` | experimental | union tag β€” palette filter only |

A real mobile-base HAL (Turtlebot 4, Clearpath Jackal, etc.) is the
prerequisite for full end-to-end execution β€” tracked as a separate
issue.

## Sensors required / Observation contract

This skill consumes nothing through OpenRAL's sensor pipeline. Nav2's
own subscriptions handle:

| Source | Topic | Why Nav2 needs it |
| --- | --- | --- |
| Laser scan | `/scan` (or per-deployment remap) | Costmap obstacle layer |
| Odometry | `/odom` | Localisation + behaviour-tree feedback |
| TF | `/tf`, `/tf_static` | Resolve goal pose in the `map` frame |
| Map | `/map` (or AMCL initial pose) | Global planner |

If your deployment uses a non-default topic remap, surface it on the
Nav2 launch β€” the wrapped action's contract is intact.

## Manifest summary

| Field | Value |
| --- | --- |
| `name` | `OpenRAL/rskill-nav2-navigate-to-pose` |
| `version` | `0.1.0` |
| `license` | `apache-2.0` |
| `kind` | `ros_action` |
| `role` | `s1` |
| `actions` | `[navigate]` |
| `chunk_size` | `1` (schema-enforced for `kind: ros_action`) |
| `latency_budget.per_chunk_ms` | `60000` (navigation is long-horizon; the adapter waits Γ—5 of this on the action result) |
| `ros_integration.package` | `nav2_msgs` |
| `ros_integration.interface_type` | `NavigateToPose` |
| `ros_integration.interface_name` | `/navigate_to_pose` |
| `ros_integration.result_trajectory_field` | _omitted β†’ result-only mode_ |
| `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-nav2-navigate-to-pose/rskill.yaml")
print(pkg.manifest.name, pkg.manifest.kind, pkg.manifest.ros_integration.interface_name)
```

End-to-end, with a real Nav2 launch up (e.g. against a Gazebo /
Turtlebot4 sim):

```bash
# 1. Bring up Nav2 for your mobile-base sim or robot
ros2 launch nav2_bringup tb4_simulation_launch.py

# 2. Bring up the OpenRAL runner against that embodiment
ros2 launch openral_rskill_ros skill_runner.launch.py robot:=panda_mobile

# 3. From the Reasoner (or by hand), dispatch the goal:
ros2 action send_goal /openral/execute_skill openral_msgs/action/ExecuteSkill \
    "{rskill_id: 'OpenRAL/rskill-nav2-navigate-to-pose', deadline_s: 120.0, prompt: 'go to map origin'}"
```

## Limitations / Roadmap

- **Velocity stream bypasses the OpenRAL safety supervisor.** Nav2
  publishes `/cmd_vel` directly. See ADR-0024 Β§Out-of-scope.
- **Goal hard-coded in the manifest.** v1 ships one goal per
  manifest; structured-prompt support is the next ADR.
- **No mobile-base HAL in-tree.** Until one lands, the skill resolves
  only inside deployments that ship their own mobile-base wiring.

## License

The rSkill package itself (this manifest + README) is **Apache-2.0**.
The wrapped Nav2 code (`nav2_msgs` IDL, `navigation2` planners) is
**Apache-2.0** and lives outside this repository β€” installed via
`ros-${ROS_DISTRO}-nav2-bringup`. Per
[ADR-0012](../../docs/adr/0012-open-core-licensing.md) both postures
are commercial-use-permissive.

## See also

- [ADR-0024 β€” ROS-wrapped rSkills](../../docs/adr/0024-ros-wrapped-rskills.md)
- [`openral_rskill.ros_action_rskill`](../../python/rskill/src/openral_rskill/ros_action_rskill.py) β€” adapter source
- [`rskills/rskill-moveit-joints/`](../rskill-moveit-joints/) β€” sibling MoveIt wrapper (trajectory mode)
- [CLAUDE.md Β§3 β€” Architecture Discipline](../../CLAUDE.md)