File size: 8,489 Bytes
b520531
 
 
18faa4f
b520531
 
 
 
 
 
 
 
 
18faa4f
 
 
b520531
 
 
18faa4f
b520531
 
 
 
 
 
 
fa9f6ae
b520531
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18faa4f
b520531
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18faa4f
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
187
188
189
190
191
192
193
194
195
196
# rSkill manifest — Nav2 NavigateToPose (kind: ros_action, result-only)
#
# Wraps the upstream `nav2_msgs/action/NavigateToPose` action server as
# an OpenRAL rSkill.
#
# RESULT-ONLY MODE
# ----------------
# `ros_integration.result_trajectory_field` is omitted, which puts the
# adapter into result-only mode: it sends the goal, awaits the action
# result, and raises `ROSRskillGoalSatisfied` on success. NO `Action`
# chunk is emitted to `/openral/candidate_action`. Nav2's own behaviour
# tree publishes `cmd_vel` directly to the base controller, BYPASSING
# the OpenRAL safety supervisor for those velocity commands. Collision
# avoidance relies entirely on Nav2's costmap. Bringing velocity-stream
# safety under the supervisor's check is an explicit out-of-scope
# follow-up for the ROS-wrapped rSkills design (no in-tree HAL exposes `body_twist` in
# `supported_control_modes` today, so this is also blocked on a
# mobile-base HAL landing — issue tracked separately).
#
# Per-dispatch structured parameters. The LLM tool palette
# surfaces this schema to the provider; the reasoner attaches the
# generated payload as ``goal_params_json`` on the ExecuteSkill goal;
# the wrapped-action adapter deep-merges it over the
# ``default_goal_json`` below at configure-time. Omit fields you want
# from the manifest default.

schema_version: "0.1"
name: "OpenRAL/rskill-nav2-mobile_base-navigate_to_pose"
version: "0.1.0"
license: "apache-2.0"
role: "s1"
kind: "ros_action"

# `mobile_base` is the canonical CLASS tag for any robot with a planar
# base + ``body_twist`` actuator (defined in ``openral_core.schemas``
# alongside the robot-specific tags). A robot must (a) declare this tag
# in its ``robots/<id>/robot.yaml`` and (b) be reachable by a running
# Nav2 stack on this deployment for the skill to actually resolve.
# Robot-specific tags (``panda_mobile`` etc.) intentionally do NOT
# appear here — Nav2's behaviour is base-agnostic, so the manifest
# stays generic and any mobile_base robot can target it.
embodiment_tags:
  - "mobile_base"

# Body twist is what Nav2's behaviour-tree controllers ultimately
# publish on `/cmd_vel`. Declaring it here is the honest description of
# what the wrapped server commands; the OpenRAL ActionChunk path is NOT
# used (see result-only mode above).
actuators_required:
  - kind: "body_twist"
    control_mode_semantics:
      mode: "absolute"

# `chunk_size: 1` is REQUIRED for kind: ros_action even in result-only
# mode (the schema validator enforces it uniformly across both modes).
chunk_size: 1

# Navigation is long-horizon — a full run can take 30+ seconds. The
# adapter waits ×5 of this as the action-result deadline, so allow
# enough headroom (60 s here → 300 s wait ceiling).
latency_budget:
  per_chunk_ms: 60000.0

# Surfaced to the Reasoner LLM tool palette.
description: >
  Navigate the mobile base to a target pose via Nav2's NavigateToPose.
  Supports BOTH absolute and relative goals via pose.header.frame_id:
  "map" = absolute world coordinates (drive to (3.5, 2.1)); "base_link"
  = relative to current pose, used for turns / forward / back-up
  (Nav2 transforms via tf2 on goal accept — the LLM does NOT need to
  compose quaternions against the live pose). Result-only mode: Nav2
  publishes cmd_vel directly; collision avoidance relies on its costmap.
actions:
  - "navigate"
objects: []
scenes:
  - "indoor"

# Provenance — required by the rSkill doc validator's publish gate.
# See sibling moveit-plan-arm manifest for the rationale on using
# `paper_url` rather than `source_repo` for ROS-wrapped rSkills.
paper_url: "https://docs.nav2.org/"

ros_integration:
  package: "nav2_msgs"
  interface_type: "NavigateToPose"
  interface_name: "/navigate_to_pose"
  # OMITTED → result-only mode (the adapter awaits the result and
  # raises ROSRskillGoalSatisfied without emitting any Action chunk).
  result_trajectory_field: null
  # Default = "stay where you are" (identity offset in base_link).
  # Picked so a misconfigured dispatch is a no-op (Nav2 reports
  # "Reached the goal" without moving) rather than a wild drive to
  # the map origin. The reasoner MUST override at least one of
  # ``pose.position.{x,y}`` or ``pose.orientation.{z,w}`` to actually
  # command motion.
  default_goal_json: |
    {
      "pose": {
        "header": {
          "frame_id": "base_link"
        },
        "pose": {
          "position": {"x": 0.0, "y": 0.0, "z": 0.0},
          "orientation": {"x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0}
        }
      },
      "behavior_tree": ""
    }
  ros_dependencies:
    - "ros-${ROS_DISTRO}-nav2-bringup"
    - "ros-${ROS_DISTRO}-nav2-msgs"

# Per-skill JSON Schema surfaced to the Reasoner LLM tool
# palette. The LLM produces a JSON object matching this schema; the
# adapter deep-merges over ``default_goal_json`` at configure-time.
#
# The schema unifies absolute and relative goals: pick ``frame_id``
# to choose, fill in position + orientation as offsets in that frame.
# Nav2's bt_navigator transforms the goal to the planning frame on
# accept via tf2, so the LLM does not need to compose quaternions
# against the live robot pose — declare the offset in ``base_link``
# and Nav2 does the math.
goal_params_schema:
  type: object
  description: >
    Target pose for Nav2's NavigateToPose action. Position +
    orientation are interpreted in ``pose.header.frame_id`` (Nav2
    transforms to its planning frame on accept).
  properties:
    pose:
      type: object
      properties:
        header:
          type: object
          properties:
            frame_id:
              type: string
              enum: ["map", "odom", "base_link"]
              description: >
                Frame the position + orientation are expressed in.
                ``map`` = absolute world goal (use when you know the
                world coordinate, e.g. "drive to (3.5, 2.1)").
                ``base_link`` = relative to current pose (use for
                turn / forward / back-up commands — position is the
                offset in metres ahead/left/up of the robot, and
                orientation is the rotation from current heading).
                ``odom`` = relative-ish (drifts over time, prefer
                ``base_link``).
          required: ["frame_id"]
        pose:
          type: object
          properties:
            position:
              type: object
              properties:
                x:
                  type: number
                  description: >
                    Target x (m). In ``base_link`` frame this is
                    forward distance (positive = ahead, negative =
                    backward). In ``map`` frame this is the absolute
                    world x coordinate.
                y:
                  type: number
                  description: >
                    Target y (m). In ``base_link`` frame this is
                    leftward distance (positive = left). In ``map``
                    frame this is the absolute world y coordinate.
                z:
                  type: number
                  description: "Target z (m); ground robots use 0."
              required: ["x", "y"]
            orientation:
              type: object
              description: >
                Target orientation as a quaternion. For ground robots
                the only non-zero components are ``z = sin(yaw/2)``
                and ``w = cos(yaw/2)`` (yaw rotation around vertical
                axis). In ``base_link`` frame the quaternion is the
                rotation FROM current heading; in ``map`` frame it
                is the absolute world heading.
                Common values for ``base_link`` turns:
                  - identity (no rotation):     z=0,        w=1
                  - +90° (counter-clockwise):   z=0.7071,   w=0.7071
                  - -90° (clockwise):           z=-0.7071,  w=0.7071
                  - 180°:                       z=1.0,      w=0
              properties:
                x: { type: number, description: "Quaternion x component." }
                y: { type: number, description: "Quaternion y component." }
                z: { type: number, description: "Quaternion z component (sin(yaw/2) for a pure yaw rotation)." }
                w: { type: number, description: "Quaternion w component (cos(yaw/2) for a pure yaw rotation)." }
          required: ["position", "orientation"]
      required: ["pose"]
  required: ["pose"]