[Feature request]: Proposal For Docking
Maintainers usually reply within 15 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 8/100
Research direction
This is a design proposal, so start by reading the Path Server, Plan Executor and Fleet Adapter sections and the TargetNode/TargetOrientation sequence diagram, not by editing code. The issue names site.json, DockRegistry, Progress::MODE_ACTION and several linked PRs (#64, #67-#74, #77, #78) that should be read first. Done means the maintainers agree on the docking design, and only then can the work be split into smaller pieces.
Written by the indexing model from the issue text.
Description
Before proceeding, is there an existing issue or discussion for this?
- I have done a search for similar issues and discussions.
Proposed Implementation For Docking in NGP
Docking is the process via which an AMR approaches a waypoint and aligns itself. During this time the AMR switches from localizing against the global frame and uses a local frame of reference to navigate to its own end point. It may need to reserve more space than just what is allocated by default as there may be multiple attempts at docking. Docking in itself is a robot specific
maneuver and each robot may have its own mechanism to perform docking.
Prior Art
Nav2
Docking is already implemented within Nav2 via the docking service. Robot vendors can implement their own docking service via this API. There is also a dock database which stores poses of known docks and the type of docking server that should be used.
How docking is triggered
How docking is triggered is via the target_node field in the destination message.
In the event the target_node is populated,
and the site.json marks the target node as a Dock node, the robot should
perform a dock sequence.
sequenceDiagram
autonumber
actor User
participant DestServer as DestinationServer
participant PathServer as PathServer
participant PlanExec as PlanExecutor
participant FleetAdapter as FleetAdapter
participant Nav2 as InnerNav2
User->>DestServer: DestinationGoal with TargetNode dock_north_1
DestServer->>PathServer: Destination with TargetNode dock_north_1
activate PathServer
Note over PathServer: Lookup dock_north_1 in DockRegistry (site.json), stamp TargetOrientation on staging wp k-1 and forward TargetNode on dock wp k
PathServer->>PlanExec: Plan (wp 0..k-1 -> staging wp k-1 -> dock wp k)
deactivate PathServer
activate PlanExec
Note over PlanExec: Gate PlanRelease at staging wp k-1 (has TargetOrientation)
PlanExec->>FleetAdapter: SafeZone (target_waypoint k-1, pose -1.0, 1.0, yaw pi/2)
FleetAdapter->>Nav2: NavigateToPose (-1.0, 1.0, yaw pi/2)
Nav2-->>FleetAdapter: NavigateToPose Succeeded
FleetAdapter->>PlanExec: Progress (MODE_NAVIGATING, reached_waypoint k-1)
FleetAdapter->>PathServer: Progress (MODE_NAVIGATING, reached_waypoint k-1)
Note over PlanExec: Staging wp k-1 reached and blockers satisfied, release dock wp k
PlanExec->>FleetAdapter: PlanRelease (waypoint_id k) and SafeZone (target_waypoint k, node dock_north_1)
Note over FleetAdapter: Resolve TargetNode dock_north_1 in DockRegistry -> DockRobot, hold reached_waypoint k-1 and enter MODE_ACTION
FleetAdapter->>PlanExec: Progress (MODE_ACTION, reached_waypoint k-1, target_waypoint k)
FleetAdapter->>PathServer: Progress (MODE_ACTION, reached_waypoint k-1, target_waypoint k)
Note over PathServer: is_executing_action is true (MODE_ACTION and dock TargetNode), exclude robot from replans and mark staging-to-dock segment occupied
FleetAdapter->>Nav2: DockRobot (dock_pose -1.0, 2.0, yaw pi/2)
Nav2-->>FleetAdapter: DockRobot Succeeded
FleetAdapter->>PlanExec: Progress (MODE_IDLE, reached_waypoint k, target_waypoint k)
FleetAdapter->>PathServer: Progress (MODE_IDLE, reached_waypoint k, target_waypoint k)
deactivate PlanExec
An example of dispatching a destination goal with a docking sequence is given in this Python snippet:
import math
from rmf_prototype_msgs.msg import (
DestinationConstraints,
DestinationGoal,
GraphElementKey,
Region,
TargetNode,
TargetOrientation,
TargetRegion,
)
from unique_identifier_msgs.msg import UUID
def make_dock_destination_goal(
x: float,
y: float,
yaw: float,
dock_node_name: str,
session_seed: int = 1,
) -> DestinationGoal:
"""Create a DestinationGoal targeting a dock node defined in the RMF site file."""
goal = DestinationGoal()
goal.session = UUID(uuid=[session_seed & 0xFF] + [0] * 15)
# 1. Specify the spatial target region and docking heading
region = Region()
region.hint = Region.HINT_POINT
region.points = [float(x), float(y)]
orientation = TargetOrientation()
orientation.orientation_radians = float(yaw)
orientation.spread_radians = 0.0
orientation.tolerance_radians = 0.0
target_region = TargetRegion()
target_region.tolerance = 0.25
target_region.region = region
target_region.orientations = [orientation]
# 2. Attach the TargetNode matching the dock location name in the .site.json
target_node = TargetNode()
target_node.key = GraphElementKey(name=[dock_node_name])
target_node.orientations = [orientation]
constraints = DestinationConstraints()
constraints.regions = [target_region]
constraints.nodes = [target_node]
goal.one_of = [constraints]
return goal
# Example: Send robot0 to dock into 'dock_north_1' at (-1.0, 2.0) facing North (pi/2)
dock_goal = make_dock_destination_goal(
x=-1.0,
y=2.0,
yaw=math.pi / 2.0,
dock_node_name='dock_north_1',
session_seed=1,
)
goal_publisher.publish(dock_goal)
Why this isn't just a crossflow action
As established, docking is a robot-specific maneuver. In a single deployment with
multiple robots, the exact docking procedure must be delegated to each robot's fleet adapter / onboard controller (e.g. opennav_docking's DockRobot and UndockRobot actions in Nav2) rather than executed as a generic task-level Crossflow workflow outside the traffic system. In addition, there are tight interactions with spatio-temporal allocation and the multi-agent path planner that require the planner, executor, and fleet adapter to coordinate throughout the maneuver:
-
Staging Pose & Pre-Dock Orientation Gating:
- Before a robot can enter a dock alcove using local sensor/dock feedback, it must first navigate to the dock's staging (entry) waypoint and align to the required approach heading (
TargetOrientation). - If the planner or executor released the dock waypoint immediately as a normal free-space trajectory segment, the robot would attempt to cut the corner into the dock alcove using global localization (
NavigateToPose) or report the staging waypoint as cleared before finishing its in-place rotation. - Instead,
rmf_path_serverstamps the dock approach orientation onto the pre-dock staging waypoint (wp[k-1]), andrmf_plan_executorgatesPlanReleaseatwp[k-1]untilProgressTrackerconfirms both the staging position andTargetOrientationare satisfied.
- Before a robot can enter a dock alcove using local sensor/dock feedback, it must first navigate to the dock's staging (entry) waypoint and align to the required approach heading (
-
Blocking Replanning & Reserving Both Staging and Dock Space (
MODE_ACTION):- Once a robot begins its final docking approach (
wp[k-1] -> wp[k]) or undocking departure (wp[0] -> wp[1]), it transitions to closed-loop local control (DockRobot/UndockRobot) and cannot be rerouted mid-maneuver by the global MAPF planner. - If another robot requests a new plan while the first robot is mid-docking,
rmf_path_servermust:- Exclude the docking/undocking robot from MAPF replanning (
is_executing_action() == true, detected viaProgress::MODE_ACTIONor by matching the active waypoint'sTargetNodeinDockRegistry). - Mark the entire active action segment (
[wp[k-1], wp[k]]) as occupied in the planning grid so other robots route around the alcove or wait, while preserving cross-planTrafficDependencyblockers against the docking robot's active plan.
- Exclude the docking/undocking robot from MAPF replanning (
- Simultaneously,
ProgressTrackerholds the docking robot'sreached_waypointat the pre-dock staging waypoint (k-1) untilDockRobot/UndockRobotcompletes, ensuringrmf_plan_executor's spatial allocation (SafeZonecostmap) keeps both the staging cell and the dock cell reserved for the robot and prevents trailing robots from being released into the staging area prematurely.
- Once a robot begins its final docking approach (
⚠️ Some caveats to note: This method using
TargetNodedoes require the fleet-adapter to have
a special case for docking and be aware of what consists of a docking node.
Implementation Details
Path Server (PR #68, PR #71, PR #72)
When a Destination with a TargetNode is received it is mapped back to the relevant site.json file (PR #68, PR #71).
If it is a docking node, the path server will route a path to it using standard mapf techniques. The Plan.msg would have the TargetNode as its final waypoint and the mapf algorithm should route the robot to its pre-dock pose first.
To prevent replanning the PathServer also needs to maintain a PlanRegistry and the current state of the robot (this was already needed to be able to ad-hoc re-plan for robots). When a robot is performing a dock, the entire horizon between the pre-dock and the post-dock pose appears as a static obstacle to all other robots[^1] (PR #71). Traffic dependencies are calculated across multiple mapf sessions (PR #71).
Plan Executor (PR #64, PR #71, PR #72)
The plan executor also needs to maintain access to the PlanRegistry and rely on cross-MAPF session traffic dependencies (PR #71). It should be able to reconstruct the current relevant set of plans via a simple DFS (PR #71). For safe zones we need to use this cross-plan dependency to reserve space (PR #71, PR #72), while gating intermediate waypoints that carry TargetOrientation or TargetNode constraints (PR #64, PR #72).
Fleet Adapter (PR #67, PR #72, PR #73, PR #74, PR #77, PR #78)
The fleet adapter should match TargetNode to known docks (PR #68, PR #78). In the event that the currently released waypoints involve a dock/predock pair the adapter should hold its progress at the pre-dock waypoint and report Progress::MODE_ACTION until it reaches its final destination (PR #67, PR #69, PR #72, PR #78).
[^1]: This is something that may need to change. Ideally we would do two passes of MAPF. First with the docking robot's dock space as a static obstacle, and second with the docking robot at its final destination if dome robots cannot make it because theyre blocked.
Necessary Changes Across the NGP Stack
This section is llm generated changelog.
1. Site Configuration & DockRegistry (rmf_path_server, rmf_mock_robot_sim, & rmf_nav2_traffic)
- PRs: PR #68, PR #71, PR #74, PR #78
- Define docks in the RMF site file (
*.site.json) as guided navigation locations connected by lanes with"dock": {"dock_name": "...", "duration": ...}properties (PR #68). - Load
DockRegistryfrom thesite_fileROS parameter inrmf_mock_robot_sim(PR #68),rmf_path_server(PR #71), andrmf_nav2_traffic(PR #78) to resolve:- Dock location name / graph node key, world coordinates
(x, y), entry/staging coordinates(entry_x, entry_y), and approach headingentry_yaw.
- Dock location name / graph node key, world coordinates
2. Message Definitions (rmf_prototype_msgs)
- PRs: PR #64, PR #69, PR #78
Progress.msg(PR #69, PR #78):Waypoint.msg/DestinationConstraints.msg(PR #64):- Carry
arrival_constraints(TargetRegionwithTargetOrientation+TargetNode) onPlanwaypoints andSafeZone.incremental_targetso the graph node (TargetNode) is the single source of truth for docking targets.
- Carry
3. Path Server (rmf_path_server)
- PRs: PR #64, PR #71, PR #72
- Dock Waypoint & Orientation Annotation (
PlanRegistry::build_session_plans) (PR #64, PR #71, PR #72): - Action-Aware Replan Protection (
PlanServer::take_snapshot&PlanRegistry::is_executing_action) (PR #71):- Check whether any robot is currently executing a dock/undock action via:
- Exclude committed robots from MAPF replanning, mark their occupied segment (
occupied_path_of) in the planningMap, and compute cross-planTrafficDependencyblockers against their in-progress plans via DFS (get_mapf_snapshot) (PR #71).
4. Plan Executor (rmf_plan_executor)
- PRs: PR #64, PR #71, PR #72
- Constraint Gating (
handle_progress) (PR #64, PR #72):- Stop advancing
released_wp_idxat any intermediate waypoint that carriesarrival_constraints.nodesor a constrainedTargetOrientationuntil the robot reaches that waypoint.
- Stop advancing
- Constraint Forwarding (
SafeZone) (PR #64, PR #72):- Forward the target waypoint's
TargetOrientation,tolerance, andTargetNodes inSafeZone.incremental_targetso the fleet adapter knows both the spatial target and the target graph node.
- Forward the target waypoint's
- Cross-Plan Blocker, Subdivision & Target Occupancy Holding (PR #71, PR #72):
5. Fleet Adapter (rmf_mock_robot_sim & rmf_nav2_traffic)
- PRs: PR #67, PR #68, PR #69, PR #72, PR #73, PR #74, PR #77, PR #78
- Mock Robot Simulator Progress & Docking (
rmf_mock_robot_sim) (PR #67, PR #68, PR #69): - Action Classification (
ProgressTracker::resolve_dock_transition) (PR #78):- When a
SafeZoneupdatesProgressTracker, inspect the targetTargetNodes (and fallbackPlanwaypoint nodes) againstDockRegistry:- Approaching a known dock ->
InnerNavigationAction::DockRobot { navigate_to_staging_pose } - Departing a known dock ->
InnerNavigationAction::UndockRobot - Standard waypoint ->
InnerNavigationAction::NavigateToPose
- Approaching a known dock ->
- When a
- Immediate
MODE_ACTION& Pre-Waypoint Progress Hold (ProgressTracker) (PR #72, PR #78):- For
DockRobotandUndockRobot, sethold_at_pre_waypoint = trueand immediately publishProgresswithmode = Progress::MODE_ACTIONandreached_waypoint = last_waypointas soon as theSafeZoneis received (or when a stationaryNavigateToPoseat the staging pose upgrades in-place toDockRobot) (PR #78). - For
NavigateToPosewith a constrainedTargetOrientation, holdreached_waypointatlast_waypoint(hold_final_waypoint_for_yaw = true) until the robot's heading satisfiestarget_yaw_tolerance(PR #72, PR #78).
- For
- Sequence-Numbered Costmap Handshake & Branching Crossflow Dispatch (
InnerNavigationServices) (PR #73, PR #74, PR #77, PR #78):- After the sequence-numbered costmap handshake (
CostmapUpdateState, PR #73) confirms the robot'sSafeZonecostmap is applied in Nav2, dispatchInnerNavigationTargetthrough the one-shot branching Crossflow workflow (PR #77, PR #78):preempt_and_prepare_goal-> forks intoexecute_dock_robot(/inner/dock_robot),execute_undock_robot(/inner/undock_robot), orexecute_navigate_to_pose(/inner/navigate_to_pose) ->reconcile_goal_outcome.
- When
reconcile_goal_outcomereceivesGoalOutcomeStatus::Succeeded, release the action hold (mark_action_completed/mark_target_reached) and publishProgresswithmode = Progress::MODE_IDLE(orMODE_NAVIGATING) andreached_waypoint = target_waypoint(PR #78). - Verified end-to-end in Gazebo + Nav2 with
opennav_dockingand corridor swap/docking scenarios (PR #74, PR #78).
- After the sequence-numbered costmap handshake (
- Dominant language
- Python
- Stars
- 10
- Forks
- 9
- Avg merge
- 3h 21m
- Merged PRs (30d)
- 1
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from open-rmf/next_gen_prototype
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
open-rmf/next_gen_prototype#80 ·
Maintainers usually reply within 15 days
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 35/100
open-rmf/next_gen_prototype#66 ·
Maintainers usually reply within 15 days
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 15/100
open-rmf/next_gen_prototype#65 · 2 comments ·
Maintainers usually reply within 15 days
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 42/100
open-rmf/next_gen_prototype#57 ·
Maintainers usually reply within 15 days
-
enhancement
Difficulty 3/5 1-2 days Newbie friendliness 68/100
open-rmf/next_gen_prototype#52 ·
Maintainers usually reply within 15 days
All issues in open-rmf/next_gen_prototype
Similar issues
-
documentation good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
JheysonJhordyHuarauyaRiquelme/sprocguard#18 ·
Maintainers usually reply within 1 day
-
enhancement good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
dlq/synthpopcan#59 ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
mdn/translated-content#40220 ·
Maintainers usually reply within 4 days
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
ETSInitiative/PETSIRD#243 ·
Maintainers usually reply within 1 day
-
deferred p2
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
cuadrao-ai/argus#2160 ·
Maintainers usually reply within 1 day