Wavefront grid planner computes collision-free, deterministic paths from start to goal using known occupancy maps for indoor robots.
How to add the Wavefront robot skill
- Load the most recent release of ARC (Get ARC).
- Press the Project tab from the top menu bar in ARC.
- Press Add Robot Skill from the button ribbon bar in ARC.
- Choose the Navigation category tab.
- Press the Wavefront icon to add the robot skill to your project.
Don't have a robot yet?
Follow the Getting Started Guide to build a robot and use the Wavefront robot skill.
How to use the Wavefront robot skill
The Wavefront Path Planning robot skill is very expiremental and provides an interesting way of calculating paths through two-dimensional grid environments. Using a classic wavefront (flood-fill) algorithm, the skill scans through a user-supplied map as a global variable identifying:
- A starting point
- A destination
- The arrangement of free space and obstacles
It then computes a shortest path from start to destination and outputs this route for visualization or robot movement logic.
This skill is useful when you have a map (either pre-built or dynamically sensed) and want ARC to determine how a robot might reach a waypoint.
How It Works
1. You provide a map
You must generate a map into an ARC global variable. The skill reads the grid map from the ARC global variable:
$MyMap
This variable must contain an 80×80 integer array where each cell represents a tile:
| Cell Value | Meaning |
|---|---|
255 |
Wall / Obstacle (not traversable) |
0 |
Empty Space (free to move) |
1 |
Source / Starting point |
254 |
Destination / Goal |
You may populate this map from a script, another skill, or a scanning process.
2. Your script robot skill triggers the Wave Front skill
Send the control command:
ControlCommand("WaveFront", "StartWavefront", "Start")
Once this command is received, the skill begins generating a path by reading the global variable $MyMap
3. Wavefront Flood-Fill Expansion
The planner performs a distance flood starting from the source:
- It scans outward through free cells
- Each cell is assigned a value that represents how many steps away it is from the source
- The wave continues until the destination is reached or no expansion is possible
This produces a gradient map, where smaller values are closer to the start and larger values are further away.
4. Path Extraction
Once the destination is reached, the skill:
- Starts at the destination cell
- Follows the lowest neighboring value repeatedly
- Continues tracing back through the grid until it reaches the source
This creates a step-by-step path representing the shortest route.
5. Route Output
After computing the path:
- Each cell that forms part of the final route is marked with
-1in$MyMap.
The skill then builds a display-friendly route representation into the global variable:
$MyRoute
This is a 1D ARC array that symbolizes the grid using readable characters:
| Character | Meaning |
|---|---|
S |
Start |
D |
Destination |
X |
Wall |
- |
Computed route path |
| Numbers | Internal wave values useful for debugging |
This array can be displayed in user interfaces, visualizers, logs, or used to convert into robot movement actions.
Example Map Workflow
Create or populate
$MyMapExample cell meanings:- Drop a
1where the robot is starting - Drop a
254where it needs to go - Fill walls as
255 - Leave traversable space as
0
- Drop a
Trigger the planner
ControlCommand("Wavefront", "StartWavefront" , "Start")Inspect the output
$MyMapnow contains the path marked as-1$MyRoutecontains a human-readable version
Integration Ideas
You can use the result for:
- Visual display of a planned path
- Robot movement scripting, stepping through locations
- Debugging map layouts
- Feeding into higher-level navigation behaviors
Notes and Tips
The algorithm finds the shortest path through axis-aligned (4-directional) movement. If no viable route exists, the destination will not be hit and no valid path is returned. Maps are assumed to be 80×80 - ensure your data matches this dimension.
Troubleshooting / FAQ
Nothing happens when I start the skill
Ensure you are sending the ControlCommand exactly as:
StartWavefront Start
My route doesn't appear
Make sure $MyMap exists and includes:
- A
1(source) - A
254(destination)
Can I print or visualize the route?
Yes - $MyRoute contains map characters that are easy to display in text windows, UIs, or scripts.
Technical Breakdown
Internally, the skill:
- Reads
$MyMapinto an array - Performs wave propagation until destination is detected
- Uses adjacency checks to locate the next nearest step
- Writes
-1along the final path - Converts the completed grid into symbolic characters stored in
$MyRoute
The process is efficient, simple, and suitable for educational examples or lightweight grid navigation.
Summary
The Wavefront Path Planning Skill turns a simple occupancy grid into a fully calculated movement route.
It gives ARC developers a way to:
- Represent space and obstacles,
- Automatically compute a path,
- Inspect or consume the output for robot behavior.
Example
This example is provided for expiremental use of this robot skill. This robot skill is not recommended to be used other than expirementing.
// Example: Using the Wavefront Path Planning robot skill from ARC JavaScript
// -------------------------------------------------------------------------
// Requirements:
// 1) $MyMap must already exist as the 80x80 map the Wavefront skill uses.
// - 255 = wall
// - 0 = empty
// - 1 = source
// - 254 = destination
// 2) The Wavefront skill must be added to the project.
// 3) Replace "Wavefront" in ControlCommand() with the actual name of your
// Wavefront skill window if it is different.
//
// This script:
// - Verifies $MyMap exists
// - Triggers the Wavefront planner
// - Reads $MyRoute
// - Prints a text visualization of the route to the console
// --- configuration -------------------------------------------------------
var width = 80; // map width used by the Wavefront skill
var height = 80; // map height used by the Wavefront skill
var wavefrontSkillName = "Wavefront"; // adjust to match your skill window name
// --- helper: get a safe global variable ---------------------------------
function getVarSafe(name, defaultValue) {
if (!varExists(name)) {
return defaultValue;
}
return getVar(name, defaultValue);
}
// --- step 1: verify that $MyMap exists ----------------------------------
if (!varExists("$MyMap")) {
print("Wavefront JS: ERROR - $MyMap does not exist. Create the map before running this script.");
print("Expected: 80x80 grid with values 0, 1, 254, 255.");
return;
}
print("Wavefront JS: $MyMap exists. Starting Wavefront path planning...");
// --- step 2: trigger the Wavefront skill --------------------------------
// This sends the same command the C# code expects: "StartWavefront Start"
ControlCommand(:wavefront:, "StartWavefront", Start");
// Note: Depending on how heavy your map is, you might want a small delay
// to ensure the skill has finished processing before reading $MyRoute.
// In many cases it's fine to read immediately, but here's a simple pause:
Sleep(500);
// --- step 3: read the generated $MyRoute --------------------------------
var route = getVarSafe("$MyRoute", null);
if (route == null) {
print("Wavefront JS: ERROR - $MyRoute does not exist. Did the Wavefront skill run?");
return;
}
if (!route.length || route.length === 0) {
print("Wavefront JS: $MyRoute is empty. No path may have been found.");
return;
}
print("Wavefront JS: $MyRoute length = " + route.length);
print("Wavefront JS: Rendering route map...");
// --- step 4: visualize the route as ASCII in the console ----------------
//
// The C# skill builds $MyRoute in this order:
//
// for (x = 0 .. width-1)
// for (y = 0 .. height-1)
// AppendToVariableArray("$MyRoute", disp);
//
// So the index is: index = x * height + y
//
// Each element of $MyRoute is a string:
// "S" = Source
// "D" = Destination
// "X" = Wall
// "-" = Path cell
// "0", "2", "3", ... = internal wave counts (for debugging)
for (var y = 0; y < height; y++) {
var line = "";
for (var x = 0; x < width; x++) {
var index = (x * height) + y;
if (index >= route.length) {
continue;
}
var cell = route[index];
// Compact display: single character per cell
// You can swap this to something else (e.g., ".", "#", etc.)
line += cell;
}
print(line);
}
// --- step 5: optional - extract just the path cells for movement --------
//
// Here we build an array of coordinates of all cells that are on the path ("-").
// You could then convert this into robot movement commands if desired.
var pathCells = [];
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x * height) + y;
if (index >= route.length) {
continue;
}
var cell = route[index];
if (cell === "-") {
pathCells.push({ x: x, y: y });
}
}
}
print("Wavefront JS: Path has " + pathCells.length + " cells.");
// Example: print first 10 path cells
var maxPreview = 10;
for (var i = 0; i < pathCells.length && i < maxPreview; i++) {
var p = pathCells[i];
print("Path[" + i + "]: x=" + p.x + ", y=" + p.y);
}
print("Wavefront JS: Done.");
