Thumbnail

Wavefront

Wavefront grid planner computes collision-free, deterministic paths from start to goal using known occupancy maps for indoor robots.

Requires ARC v2 (Updated 12/4/2025)

How to add the Wavefront robot skill

  1. Load the most recent release of ARC (Get ARC).
  2. Press the Project tab from the top menu bar in ARC.
  3. Press Add Robot Skill from the button ribbon bar in ARC.
  4. Choose the Navigation category tab.
  5. 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 -1 in $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

  1. Create or populate $MyMap Example cell meanings:

    • Drop a 1 where the robot is starting
    • Drop a 254 where it needs to go
    • Fill walls as 255
    • Leave traversable space as 0
  2. Trigger the planner

    ControlCommand("Wavefront", "StartWavefront" , "Start")
    
  3. Inspect the output

    • $MyMap now contains the path marked as -1
    • $MyRoute contains 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 $MyMap into an array
  • Performs wave propagation until destination is detected
  • Uses adjacency checks to locate the next nearest step
  • Writes -1 along 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.");

ARC Pro

Upgrade to ARC Pro

With Synthiam ARC Pro, you're not just programming a robot; you're shaping the future of automation, one innovative idea at a time.