Skip to content

feat: Core MAPF Path Server, Plan Executor, and Visual Tooling#13

Closed
arjo129 wants to merge 79 commits into
open-rmf:prototypefrom
arjo129:arjoc/feat/path_server_standalone
Closed

feat: Core MAPF Path Server, Plan Executor, and Visual Tooling#13
arjo129 wants to merge 79 commits into
open-rmf:prototypefrom
arjo129:arjoc/feat/path_server_standalone

Conversation

@arjo129

@arjo129 arjo129 commented Jun 8, 2026

Copy link
Copy Markdown
Member

Overview

Built on: ROS 2 Jazzy

This Pull Request introduces the foundational Multi-Agent Pathfinding (MAPF) trajectory generation, decoupled execution tracking, mock simulation scaffolding, and basic visual verification tools for the Next Generation RMF prototype.

By cleanly separating high-level conflict-free path planning from runtime trajectory execution, this architecture enables highly scalable fleet coordination, dynamic participant discovery, explicit progress signaling via safe zones, and rapid visualization.


Architectural Components & Packages

1. Planning & Execution (Decoupled Pipeline)

  • rmf_path_server: Core ROS 2 Rust planning node wrapping the MAPF backend (pibt). Implements asynchronous background planning. It also supports traffic dependency calculation which can then be used for dynamic safe zone grid allocation, traffic dependency visualization, footprint enforcement, and explicit waypoint release signaling by the rmf_plan_executor and dashboard.
  • rmf_plan_executor: Runtime execution coordinator. Subscribes to generated multi-agent trajectories, manages dynamic participant tracking, and synchronizes real-time waypoint progress via explicit PlanRelease signaling.

2. Interactive Demos & Visual Tooling

  • rmf_path_server_demo: An interactive web dashboard (HTML5/CSS3/VanillaJS) and scenario runner (demo.launch.py) allowing users to interactively spawn robots, click to assign goals, and observe dynamic conflict-free planning on a live HTML canvas. (More instructions Below)
  • rmf_path_server_test: Provides tests to check the validity of the path tracking (via PlanRelease.msg). We also provide a small web-based visualer to debug test trajectories.

3. Simulation & Supporting Infrastructure

  • rmf_mock_robot_sim: Lightweight Python simulation node modeling waypoint following behavior and publishing active robot state.
  • rmf_participant_discovery: Extended participant lifecycle messages (onboarding/offboarding) supporting fleet discovery.

Verification & Testing

Setup & Building

  1. Import Workspace Dependencies (via .repos file)
    Create a workspace and import the required ROS 2 Rust and navigation dependencies using this setup.repos:

    mkdir -p rmf_ws/src
    cd rmf_ws
    vcs import src < setup.repos
  2. Build the PR Packages
    Ensure you are at the workspace root inside the jazzy distrobox container, then build the relevant packages:

    colcon build --packages-select rmf_prototype_msgs rmf_participant_discovery rmf_path_server rmf_plan_executor rmf_mock_robot_sim rmf_path_server_demo rmf_path_server_test

Running Automated Integration Tests

Verify core scenario coordination and robust following behavior:

colcon test --packages-select rmf_path_server_test --event-handlers console_direct+

Running the Interactive Web Demonstration

path_server_smol.mp4

Launch the fully standalone path server dashboard:

ros2 launch rmf_path_server_demo demo.launch.py
  1. Open http://localhost:8080 in your web browser.
  2. Click Add Robot to drop active participants onto the canvas.
  3. Select a robot and click a cell to place its goal.
  4. Click Send Scenario to observe multi-agent trajectory generation and live execution progress.

Note: The visualizers are largely vibe-coded and meant to be used during development and debugging. I fully expect rmf-site to replace them in our first release. I would not personally bother with scrutinizing the quality of the code there.

Additional note: Currently mapf_post is pulled via git directly from the arjo/feat/more_efficient_checks branch.

We also don't introduce maps here as that is a whole other ticket of its own (See #12)

GenAI Use

We follow OSRA's policy on GenAI tools

  • I used a GenAI tool in this PR.
  • I did not use GenAI

Generated-by: Gemini-CLI

arjo129 and others added 26 commits June 8, 2026 02:21
- Implement CurrentlyOccupiedDestinations for occupancy management.
- Implement DestinationServer with request_destination logic.
- Set up robot goal subscribers and publishers in main.
- Add comprehensive unit tests for reservation logic.

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…or server to use Worker

- Created rmf_reservation_tests package with integration tests.
- Refactored rmf_simple_destination_server to use rclrs::Worker for state management.
- Verified functionality with integration tests.

Assisted-by: Gemini CLI
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
… boarding

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…lding

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…ith session-based task cancellation

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…th server

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…grid management in path server

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…signaling for waypoint progress synchronization

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…ent in plan executor

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…ces (#1)

Allows the user to define in a yaml file:

A list of backup parking spaces a robot can be diverted to while it waits
A list of safe sets that defines a region of the map that robots are allowed to enter
Adds a config module to parse and validate the yaml file.

Publishes an unreachable error code if requested regions are outside safe sets.

Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
arjo129 added 6 commits June 19, 2026 06:44
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
@arjo129 arjo129 requested a review from mxgrey June 19, 2026 08:02
@arjo129 arjo129 changed the base branch from main to prototype June 22, 2026 00:49

@SamuelFoo SamuelFoo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Just some minor comments.

}

if released_wp_idx >= plan.waypoints.len() {
released_wp_idx = plan.waypoints.len() - 1;

@SamuelFoo SamuelFoo Jun 22, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any danger of this underflowing if the plan is empty?

This is probably a minor issue if the current plans seem to always produce one waypoint.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch we should absolutely check this! Ive fixed it in 70e281e

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a more serious note we should probably do more input validation, but that should ideally be a seperate PR.

arjo129 added 3 commits June 22, 2026 02:18
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a foundational ROS 2 Jazzy “path planning → execution” pipeline for the next-gen RMF prototype, including participant discovery utilities, a Rust MAPF path server + executor, a Python mock robot simulator, launch-test integration coverage, and web-based visualization/demo tooling.

Changes:

  • Added rmf_path_server (Rust) with a decoupled worker model (discovery vs destinations) and a PIBT-based planner backend.
  • Added rmf_plan_executor (Rust) to track execution progress, publish PlanRelease, and generate SafeZone costmaps.
  • Added rmf_participant_discovery (Rust lib), rmf_mock_robot_sim (Python), rmf_path_server_test (launch tests + trajectory visualizer), and rmf_path_server_demo (web dashboard + HTTP/SSE spawner).

Reviewed changes

Copilot reviewed 54 out of 56 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
.gitignore Adds ignore patterns (currently includes source-file entries that should be removed).
README.md Documents workspace setup, build, tests, and demo usage.
discourse/1-topics-interfaces.md Adds design document for topic/interface taxonomy.
discourse/2-traffic-management-interfaces.md Adds Discourse link header to traffic management interfaces document.
path_server/README.md Documents path server folder and demo launch.
path_server/rmf_path_server/.gitignore Ignores Rust target/ output.
path_server/rmf_path_server/Cargo.toml Declares Rust deps for path server (currently unpinned / git branch-based).
path_server/rmf_path_server/package.xml ROS package manifest for the Rust path server node.
path_server/rmf_path_server/src/lib.rs Implements path server workers, background planning, plan publication, and discovery wiring.
path_server/rmf_path_server/src/main.rs Starts the path server node and spins executor.
path_server/rmf_path_server/src/planner.rs Defines MapfPlanner trait plus PIBT-based planner implementation.
path_server/rmf_plan_executor/.gitignore Ignores Rust target/ output.
path_server/rmf_plan_executor/Cargo.toml Declares Rust deps for plan executor (currently unpinned / git branch-based).
path_server/rmf_plan_executor/package.xml ROS package manifest for plan executor.
path_server/rmf_plan_executor/src/lib.rs Implements execution tracking, PlanRelease, and safe-zone allocation/costmap publication.
path_server/rmf_plan_executor/src/main.rs Runs executor + discovery wiring for per-robot subscriptions.
path_server/rmf_path_server_demo/README.md Documents demo dashboard usage.
path_server/rmf_path_server_demo/launch/demo.launch.py Launches path server + spawner + executor for demo.
path_server/rmf_path_server_demo/package.xml ROS package manifest for demo tooling.
path_server/rmf_path_server_demo/resource/rmf_path_server_demo Ament resource index marker.
path_server/rmf_path_server_demo/setup.cfg Python package install script dirs.
path_server/rmf_path_server_demo/setup.py Installs demo Python package and web assets.
path_server/rmf_path_server_demo/rmf_path_server_demo/__init__.py Python package init.
path_server/rmf_path_server_demo/rmf_path_server_demo/robot_spawner.py HTTP/SSE bridge that spawns mock robots and publishes discovery/destinations.
path_server/rmf_path_server_demo/www/app.js Dashboard logic (SSE stream, robot interactions, rendering).
path_server/rmf_path_server_demo/www/index.html Dashboard HTML layout and dependencies.
path_server/rmf_path_server_demo/www/style.css Dashboard styling.
path_server/rmf_path_server_test/.gitignore Ignores pytest cache and bytecode in tests.
path_server/rmf_path_server_test/README.md Documents launch tests and the trajectory visualizer usage.
path_server/rmf_path_server_test/package.xml ROS package manifest for tests (missing some test dependencies).
path_server/rmf_path_server_test/resource/rmf_path_server_test Ament resource index marker.
path_server/rmf_path_server_test/setup.cfg Python package install script dirs.
path_server/rmf_path_server_test/setup.py Installs test package and visualizer CLI entry point.
path_server/rmf_path_server_test/rmf_path_server_test/__init__.py Python package init.
path_server/rmf_path_server_test/rmf_path_server_test/visualize.py Standalone trajectory CSV web visualizer.
path_server/rmf_path_server_test/test/test_copyright.py Ament copyright lint test.
path_server/rmf_path_server_test/test/test_flake8.py Ament flake8 lint test.
path_server/rmf_path_server_test/test/test_pep257.py Ament pep257 lint test.
path_server/rmf_path_server_test/test/test_path_server_follow.py Integration test for following/collision avoidance behavior.
path_server/rmf_path_server_test/test/test_path_server_scenario.py Integration test for dynamic redirection + scenario behavior.
rmf_participant_discovery/.gitignore Ignores Rust target/ output.
rmf_participant_discovery/Cargo.toml Rust crate manifest for participant discovery helper.
rmf_participant_discovery/package.xml ROS package manifest for participant discovery crate.
rmf_participant_discovery/src/lib.rs Provides ParticipantTracker + generic discovery subscription helper and tests.
rmf_mock_robot_sim/README.md Documents mock robot simulator behavior (needs topic corrections).
rmf_mock_robot_sim/package.xml ROS package manifest (currently contains TODO placeholders).
rmf_mock_robot_sim/resource/rmf_mock_robot_sim Ament resource index marker.
rmf_mock_robot_sim/setup.cfg Python package install script dirs.
rmf_mock_robot_sim/setup.py Python package manifest (currently contains TODO placeholders).
rmf_mock_robot_sim/rmf_mock_robot_sim/__init__.py Python package init.
rmf_mock_robot_sim/rmf_mock_robot_sim/mock_robot_sim_node.py Mock robot simulation node publishing odom/progress and following plans/releases.
rmf_mock_robot_sim/test/test_copyright.py Ament copyright lint test.
rmf_mock_robot_sim/test/test_flake8.py Ament flake8 lint test.
rmf_mock_robot_sim/test/test_mock_robot_sim.py Launch test validating mock robot behavior with plan/release/progress.
rmf_mock_robot_sim/test/test_pep257.py Ament pep257 lint test.
rmf_prototype_msgs/msg/Participant.msg Minor formatting change (trailing blank line).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread path_server/rmf_path_server_test/package.xml Outdated
Comment thread rmf_mock_robot_sim/package.xml
Comment thread rmf_mock_robot_sim/setup.py
Comment on lines +1 to +3
This package contains a simple node that publishes the odom for an individual robot. When robots receive a ~/path on the topic the odom will be updated accordingly.

At startup the robot should also publish itself in the participant_discovery topic (read the details of the spec [here](../../discourse/2-traffic-management-interfaces.md)). No newline at end of file
Comment on lines +599 to +603
|server: &mut DiscoveryServer<P>, robot_id: &str| {
if server.active_robots.remove(robot_id).is_some() {
rclrs::log!(server.node.logger(), "Participant left: {}", robot_id);
}
},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets open an issue to handle this in the future.

Comment thread path_server/rmf_path_server_demo/rmf_path_server_demo/robot_spawner.py Outdated
Comment on lines +68 to +72
for p in msg.participants {
if added.contains(&p.name) {
executor.handle_robot_added(&p.name, 0.49);
}
}
Comment thread path_server/rmf_path_server/Cargo.toml
Comment thread path_server/rmf_plan_executor/Cargo.toml
Comment on lines +1 to +4
[package]
name = "rmf_participant_discovery"
version = "0.1.0"
edition = "2021"
arjo129 added 4 commits June 22, 2026 05:24
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>

@mxgrey mxgrey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just have a few small follow-up remarks on the build instructions. Other than that, I'll be happy to merge this soon.

Comment thread README.md Outdated
Comment thread README.md Outdated
2. **Build the PR Packages**
Ensure you are at the workspace root inside the `jazzy` distrobox container, then build the relevant packages:
```bash
colcon build --packages-select rmf_prototype_msgs rmf_participant_discovery rmf_path_server rmf_plan_executor rmf_mock_robot_sim rmf_path_server_demo rmf_path_server_test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When and how do the message packages get built under these build instructions?

I think we need the user to install colcon-cargo and colcon-ros-cargo to generate the config file with the patches, don't we? As of Noble, I believe this still requires users to do pip install --break-system-packages ... which feels icky, but currently there doesn't seem to be a good way around it.

Another option might be to provide the user with a premade .cargo/config.toml containing the patches and give them a curl command to put it in their workspace. That would spare them from needing --break-system-packages.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +288 to +292
rclrs::log!(
self.node.logger(),
"Odometry for robot {} is missing or stale. Skipping plan.",
robot_id
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CPU throttle is a very good point for why we should just stick with a 10Hz idle loop. Like you said, we could still do debouncing with a reactive system, but the added complexity isn't worth the extremely minor performance benefits (if there would even be any performance benefits at all).

from launch_ros.actions import Node


def generate_launch_description():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I could change this to xml/yaml if those are preferred.

I don't have a strong personal opinion, I was mostly curious. I think .launch.xml is more broadly familiar, easier to understand, and easier to write in most cases. Even though I don't generally care for .xml, I think people get easily confused by .launch.py's declarative structure.

Does <include> work across .launch.xml and .launch.py? I think most of our user-base will prefer .launch.xml, so if we make anything that we want to be includable by downstream launch files, we should make sure .launch.xml files can include them.

arjo129 and others added 5 commits June 22, 2026 13:55
Co-authored-by: Grey <greyxmike@gmail.com>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
…ver_standalone' into arjoc/feat/path_server_standalone
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
Signed-off-by: Arjo Chakravarty <arjoc@intrinsic.ai>
@arjo129 arjo129 deleted the branch open-rmf:prototype June 22, 2026 06:19
@arjo129 arjo129 closed this Jun 22, 2026
@arjo129

arjo129 commented Jun 22, 2026

Copy link
Copy Markdown
Member Author

For whatever reason I cant re-open this pull request to target the correct branch when I deleted the base branch. Ive opened #17 to continue development.

@mxgrey mxgrey removed this from PMC Board Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants