GPS-driven outdoor robot navigation with satellite maps, saved waypoints, zones, no-go areas, obstacle avoidance, and coverage mowing patterns
How to add the Outdoor Navigator robot skill
- Load the most recent release of ARCx on a compatible operating system (Get ARCx).
- Press the + Skills menu from the top menu bar in ARCx.
- Choose any of these category tabs, the robot skill appears in each of them: GPS, Navigation.
- Press the Outdoor Navigator 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 Outdoor Navigator robot skill.
How to use the Outdoor Navigator robot skill
The Outdoor Navigator drives a robot around outdoors by GPS, on a satellite map. Save places, draw the areas it works in and the areas it must never enter, and send it anywhere on the map. It plans its way round no-go areas and whatever its lidar sees, and it can cover a whole area in rows, the way a robot mower does.
What it needs in your project
| You need | What it does | Examples |
|---|---|---|
| A GPS robot skill | Says where the robot is on the earth and which way it faces, through the Navigation Messaging System (NMS) | BN-880 GPS Compass, an RTK GPS, a MAVLink autopilot |
| A movement panel | Turns "go forward" into motor power | Any movement panel: H-bridge, Sabertooth, a custom one |
| A distance sensor (optional) | Sees obstacles, so routes go round them | A lidar, a depth camera, ultrasonic sensors reporting to the NMS |
The Outdoor Navigator does not talk to a GPS itself. Whichever GPS robot skill the project has reports the robot's pose to the NMS and ties the NMS map to the earth, and this skill reads both. Change GPS and nothing here needs to change. Everything it saves (waypoints, zones, no-go areas) is a latitude and longitude, so it stays put on the map whichever GPS reports the position.
How accurate it can be is down to the GPS. A plain GPS such as the BN-880 is good to a metre or two, which is fine for driving to the shed and back. Mowing a lawn in neat rows needs an RTK GPS, good to a few centimetres.
The map
The background is a satellite photograph (Esri World Imagery), or OpenStreetMap streets, or your own tile server. Your browser fetches the pictures, so it needs the internet. North is up.
| On the map | Means |
|---|---|
| White triangle | The robot, pointing the way it faces. It turns blue while the coverage tool is on |
| Blue circle round the robot | The GPS's own error estimate, when it is bigger than the robot |
| Green outline | A zone. The active zone is brighter |
| Red outline | A no-go area |
| Yellow dots | Waypoints |
| Cyan line | The route being driven. Orange when only part of the way could be found |
| Thin yellow line | The rest of a route's stops |
| Blue lines | A coverage pattern: the passes that use the tool, brighter once done. Grey legs are travel |
| Orange squares | Obstacles the distance sensors have mapped |
| Red dots | The newest lidar sweep |
| Purple line | The trail behind the robot |
Drag to pan and use the wheel to zoom. Center finds the robot and follows it again. The latitude and longitude under the pointer are shown in the corner.
The tools above the map decide what a click does:
| Tool | A click |
|---|---|
| Pan | Nothing. Safe to leave on |
| Drive to | Sends the robot there |
| Waypoint | Saves a waypoint there |
| Boundary | Adds a corner to the active zone's boundary, into the nearest edge. Drag a corner to move it; right click a corner to remove it |
| No-go | Adds a corner to a new no-go area. Finish saves it (give it a name first if you like); right click removes the last corner |
Driving
Pick a waypoint and press Go, pick a saved route and press Drive, or click the map with Drive to. Scripts and AI assistants can do the same.
The route is worked out on squares across the ground. Obstacles and no-go areas are grown by half the robot's width, so a route the planner accepts is one the robot fits along. Beyond that it prefers to keep some distance where there is room, and the staircase of squares is pulled straight into a few long runs. The route is worked out again every second, so it bends round obstacles as the lidar sees them. Something suddenly close in front stops the robot at once; it then turns towards the new way round and carries on.
The robot steers along the route, aiming a little way ahead of itself. It turns on the spot for big corrections and slows one wheel for small ones, and eases off near the destination. It counts as arrived within the Arrived within distance.
It pauses by itself, and carries on by itself, when:
- the GPS's error estimate goes over Pause when GPS error is over (under trees, beside a building);
- the GPS skill stops reporting a position;
- another robot skill pauses navigation through the NMS (an obstacle zone, a bumper script).
It gives up when it gets no closer for Give up after no progress for, and with a Geofence margin set it stops if it ever leaves the active zone by more than that.
A route can loop: a patrol of the yard that carries on until it is stopped.
Zones and coverage
A zone is a working area: the back lawn, a field, a car park. Make one on the Places tab, then draw its boundary on the map with Boundary, or record it by driving round it: ** > Record the zone's boundary by driving round it**, drive or push the robot round the edge, then stop recording. The recording is simplified into straight runs.
No-go areas are drawn with No-go. Every route avoids every no-go area, whichever zone is active. Stay inside the active zone keeps routes inside the active zone's boundary too, for a robot that must stay on the lawn.
Cover drives over the whole active zone. It does laps round the edge, then rows across the zone at the angle with the fewest turns, round its no-go areas, and finishes at the edge nearest where it started. Preview draws the pattern first without moving. The Tool on and Tool off scripts run as each pass that covers ground starts and ends, and whenever the robot pauses or stops, so a mower's blade only turns while it is mowing. If the lidar finds something in the way of a pass, the robot goes round it and rejoins the pattern.
Places
The waypoints with their distance from the robot, the zones with their area and no-go areas, and the routes. Each has a button to go, drive or make active, and to delete; every delete asks first. Add a route by giving it a name and its waypoints separated by commas.
Configuration
Robot and route
| Setting | Meaning | Default |
|---|---|---|
| Robot width | Including anything that sticks out. The most important setting: too small and it clips things, too big and it refuses gaps it fits through | 0.6 m |
| Preferred clearance | Extra room the route would rather leave | 0.5 m |
| Clearance preference | How strongly. 0 takes the shortest route | 2 |
| Route square size | Smaller fits narrower gaps and costs more. Long trips use bigger squares by themselves | 0.3 m |
| Work the route out every | 1000 ms | |
| Detour up to | How far beyond the start and destination a route may go to get round something | 25 m |
| Stay inside the active zone | When the robot and its destination are both inside the active zone | off |
Sensors
| Setting | Meaning | Default |
|---|---|---|
| Map obstacles | Plan round what the distance sensors see. Every beam clears what it passes through and marks where it stops, so things that move away are forgotten | on |
| Obstacle square size | Changing it clears the obstacle map | 0.2 m |
| Ignore readings closer than | The robot's own body, grass in front of a low sensor | 0.25 m |
| Ignore readings further than | A robot that is not level sees the ground in the distance | 12 m |
| Minimum reading confidence | 0 accepts everything | 0 |
| Keep the obstacle map in the project | So it is there next time. Off keeps project files small | off |
Driving
| Setting | Meaning | Default |
|---|---|---|
| Drive / turn speed | 0 to 255, handed to the movement panel | 160 / 110 |
| Turn on the spot beyond | Larger heading errors stop and turn; smaller ones steer | 35 |
| Steer while driving | Slow the inside wheel. Needs a Movement Panel with separate left and right speeds | on |
| Look ahead | How far along the route the robot aims. Longer is smoother and cuts corners more | 1.5 m |
| Arrived within | Not smaller than the GPS's error, or the robot circles | 1.5 m |
| Slow down within / to | 3 m / 70 | |
| Stop for obstacles within | Stop at once for something this close ahead | 0.5 m |
| Watch an ARC of | Centred straight ahead | 60 |
| Give up after no progress for | 0 never gives up | 45 s |
| Pause when GPS error is over | 0 never pauses | 6 m |
| Geofence margin | 0 turns the geofence off | 0 |
Coverage
| Setting | Meaning | Default |
|---|---|---|
| Tool width | The width covered in one pass | 0.5 m |
| Overlap | The fraction of each pass that overlaps the last | 0.1 |
| Laps round the edge | For a clean edge and room to turn | 1 |
| Row direction | Degrees clockwise from north, or -1 for the fewest turns | -1 |
| Edge margin | Extra distance from the boundary and no-go areas. A robot wider than its tool keeps its body inside by itself | 0 |
| Tool on / Tool off | Scripts that start and stop the tool |
Map
| Setting | Meaning | Default |
|---|---|---|
| Background | Satellite (Esri World Imagery), Streets (OpenStreetMap, light use only under its tile policy), your own tile server, or none | Satellite |
| Tile address, Deepest zoom | For your own server: an address with {z}, {x} and {y} |
|
| Background strength | Less makes the drawing over it easier to read | 0.85 |
| Show obstacles, Show the lidar | on | |
| Trail length | Positions. 0 draws none | 1500 |
| Record a corner every | When recording a boundary | 0.5 m |
Scripts
| Script | When it runs |
|---|---|
| Set off | Each time the robot sets off |
| Arrived | On reaching each waypoint or destination. $ONavDestination holds which |
| Completed | When a route or a coverage finishes |
| Paused | When the robot pauses. $ONavPauseReason says why |
| Failed | When a drive ends without arriving. $ONavResult says why: Cancelled, Stuck, NoPosition, OutsideGeofence or Error |
The Window tab sets the robot skill's window title, its size on the workspace and notes about it.
Global variables
With the default prefix ONav.
| Variable | What it holds |
|---|---|
ONavLatitude, ONavLongitude, ONavHeading |
Where the robot is, and which way it faces in degrees clockwise from true north |
ONavIsNavigating, ONavStatus, ONavMission |
Whether it is driving, Navigating / Paused / Idle, and GoTo / Route / Coverage |
ONavDestination, ONavDistanceToDestination, ONavRouteLength |
Where it is going, how far in a straight line, and how long the planned route is, in metres |
ONavDoing, ONavPauseReason, ONavResult |
What it is doing now, why it paused, how the last drive ended |
ONavCoverageProgress, ONavToolOn |
Coverage done, 0 to 100, and whether the tool should be working |
ONavObstacleAhead |
The nearest thing in the ARC ahead in metres, 0 for nothing |
ONavWaypoints, ONavZones |
The saved names |
Custom UI widgets
Outdoor map is the satellite map following the robot. Send robot to is a destination, one big button and what the robot is doing. Its Target setting locks it to a waypoint name, route:Name for a saved route, or cover:Zone to cover a zone. A few of them on one screen make a remote control for the yard.
When it does not work
| What you see | Usually means |
|---|---|
| "No GPS skill has tied the map to the earth yet" | There is no GPS robot skill, or it has no fix yet |
| No satellite picture | The browser has no internet, or the area is zoomed out too far |
| The route is orange and stops short | The destination is walled off by no-go areas or obstacles, or Detour up to is too small |
| It refuses a gap it fits through | Robot width plus Preferred clearance is wider than the gap |
| It circles the destination | Arrived within is smaller than the GPS's error |
| It keeps pausing for the GPS | Trees or buildings. Raise Pause when GPS error is over, or drive somewhere more open |
| Obstacles appear where there are none | The lidar sees the ground: lower Ignore readings further than, or mount it level |
| Coverage leaves stripes | The GPS is not accurate enough for the tool. Use RTK, or more Overlap |
Control Commands for the Outdoor Navigator robot skill
There are Control Commands available for this robot skill which allows the skill to be controlled programmatically from scripts or other robot skills. These commands enable you to automate actions, respond to sensor inputs, and integrate the robot skill with other systems or custom interfaces. If you're new to the concept of Control Commands, we have a comprehensive manual available here that explains how to use them, provides examples to get you started and make the most of this powerful feature.
Control Command ManualThis robot skill has 19 control commands, listed below. Send them from a JavaScript or Python script, from Blockly, or from another robot skill.
The first value is always the window title, which is the name in the title bar of the robot skill on your workspace. It starts out as Outdoor Navigator, which is what every example below uses. If you rename the robot skill, or add a second copy of it to the project, use the title as it appears on that window instead.
ControlCommand() can be shortened to CC(), and both spellings work in JavaScript and in Python. The examples are JavaScript; Python is the same call, except that true and false are written True and False.
AddWaypoint
Save a latitude and longitude (degrees) as a waypoint. Replaces a waypoint of the same name.
Syntax
ControlCommand("Outdoor Navigator", "AddWaypoint", (String)waypointName, (Number)latitude, (Number)longitude)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | waypointName | Text | Your text, in quotes |
| 2 | latitude | Number | A number, without quotes |
| 3 | longitude | Number | A number, without quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "AddWaypoint", "waypointName", 0, 0);
AddWaypointHere
Save where the robot is as a waypoint. Replaces a waypoint of the same name.
Syntax
ControlCommand("Outdoor Navigator", "AddWaypointHere", (String)waypointName)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | waypointName | Text | Your text, in quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "AddWaypointHere", "waypointName");
ClearObstacles
Forget the obstacles the distance sensors have mapped.
Syntax
ControlCommand("Outdoor Navigator", "ClearObstacles")
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "ClearObstacles");
CoverZone
Cover a zone in rows (mow it, sweep it, spray it), avoiding its no-go areas, running the tool on and off scripts. Pass an empty name for the active zone. Returns the metres to drive.
Syntax
ControlCommand("Outdoor Navigator", "CoverZone", (String)zoneName)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | zoneName | Text | Your text, in quotes |
Returns: Double [5.0e324 to 1.7e308]
Example
var result = ControlCommand("Outdoor Navigator", "CoverZone", "zoneName");
DeleteWaypoint
Delete a saved waypoint.
Syntax
ControlCommand("Outdoor Navigator", "DeleteWaypoint", (String)waypointName)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | waypointName | Text | Your text, in quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "DeleteWaypoint", "waypointName");
GetCoverageProgress
How much of the current or last coverage is done, 0 to 100.
Syntax
ControlCommand("Outdoor Navigator", "GetCoverageProgress")
Returns: Double [5.0e324 to 1.7e308]
Example
var result = ControlCommand("Outdoor Navigator", "GetCoverageProgress");
GetDistanceToDestination
Metres to the current destination in a straight line. 0 when not driving.
Syntax
ControlCommand("Outdoor Navigator", "GetDistanceToDestination")
Returns: Double [5.0e324 to 1.7e308]
Example
var result = ControlCommand("Outdoor Navigator", "GetDistanceToDestination");
GetPosition
Where the robot is: an array of latitude, longitude (degrees) and heading (degrees clockwise from true north).
Syntax
ControlCommand("Outdoor Navigator", "GetPosition")
Returns: Array of Double
Example
var result = ControlCommand("Outdoor Navigator", "GetPosition");
GetWaypoints
The names of every saved waypoint.
Syntax
ControlCommand("Outdoor Navigator", "GetWaypoints")
Returns: Array of String
Example
var result = ControlCommand("Outdoor Navigator", "GetWaypoints");
GoToLatLon
Drive to a latitude and longitude in degrees.
Syntax
ControlCommand("Outdoor Navigator", "GoToLatLon", (Number)latitude, (Number)longitude)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | latitude | Number | A number, without quotes |
| 2 | longitude | Number | A number, without quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "GoToLatLon", 0, 0);
GoToWaypoint
Drive to a saved waypoint, planning round no-go areas and obstacles. Returns once the robot has set off; the IsNavigating variable and the arrival script say when it gets there.
Syntax
ControlCommand("Outdoor Navigator", "GoToWaypoint", (String)waypointName)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | waypointName | Text | Your text, in quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "GoToWaypoint", "waypointName");
IsNavigating
Is the robot driving (or paused on the way)?
Syntax
ControlCommand("Outdoor Navigator", "IsNavigating")
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "IsNavigating");
PauseNavigating
Hold still without abandoning the drive. ResumeNavigating carries on.
Syntax
ControlCommand("Outdoor Navigator", "PauseNavigating")
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "PauseNavigating");
ResumeNavigating
Carry on after PauseNavigating.
Syntax
ControlCommand("Outdoor Navigator", "ResumeNavigating")
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "ResumeNavigating");
SetActiveZone
Make a zone the active one (for coverage, the geofence and staying inside).
Syntax
ControlCommand("Outdoor Navigator", "SetActiveZone", (String)zoneName)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | zoneName | Text | Your text, in quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "SetActiveZone", "zoneName");
StartRecordingBoundary
Record a zone's boundary by driving round it: start here, drive the robot round the edge, then StopRecording. The zone is created if it does not exist.
Syntax
ControlCommand("Outdoor Navigator", "StartRecordingBoundary", (String)zoneName)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | zoneName | Text | Your text, in quotes |
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "StartRecordingBoundary", "zoneName");
StartRoute
Drive a saved route by name, or several waypoints in turn given as one comma separated list. Pass true or false as the second value to loop or not (a saved route uses its own setting when it is left out). Returns how many stops it has.
Syntax
ControlCommand("Outdoor Navigator", "StartRoute", (String)routeNameOrWaypointNames, (Bool)loop)
Parameters
| # | Name | Type | What to pass |
|---|---|---|---|
| 1 | routeNameOrWaypointNames | Text | Your text, in quotes |
| 2 | loop | True or false | true or false, without quotes |
Returns: Integer [-2,147,483,648 to 2,147,483,647]
Example
var result = ControlCommand("Outdoor Navigator", "StartRoute", "routeNameOrWaypointNames", true);
StopNavigating
Stop driving and abandon the destination, route or coverage.
Syntax
ControlCommand("Outdoor Navigator", "StopNavigating")
Returns: Boolean [true or false]
Example
var result = ControlCommand("Outdoor Navigator", "StopNavigating");
StopRecording
Finish recording a boundary. Returns how many corners it has after straight runs are simplified.
Syntax
ControlCommand("Outdoor Navigator", "StopRecording")
Returns: Integer [-2,147,483,648 to 2,147,483,647]
Example
var result = ControlCommand("Outdoor Navigator", "StopRecording");
This list is read out of the robot skill itself each time its package is uploaded, so it matches the published version (v1).











This robot skill has been updated to v1.
What has changed
iniitial release