Skip to main content

GraphNav

Spot's GraphNav service controls its localization and navigation capabilities. Documentation from Boston Dynamics on how this works can be found here.

When you create an Autowalk on Spot, you are actually creating both a map and a mission. The map defines the area that Spot knows how to navigate through. The mission defines the sequence of actions you want Spot to perform within this map. GraphNav is in charge of how the map is built and how Spot can subsequently navigate through it.

The Rocos Agent allows access to GraphNav functions via service calls. It also allows exposes GraphNav data in the form of telemetry messages.

Note: the term graph refers to Spot's map of the environment. The term is used based on the graph structure of the map. In the subsequent documentation the terms graph and map will be used interchangeably. More information on the graph structure of Spot's maps can be found here.

Data Model

The live data viewer shows the GraphNav services and telemetry messages exposed by the Rocos Agent.

The processing, ros, and navigation services and telemetry are explained in their own sections below.

Services:

  • clearGraph: this clears the current map on Spot. This may be desired if you want to start recording a new map.

  • downloadGraph: this returns the JSON string containing Spot's full graph, including all waypoint and edge snapshots.

  • downloadGraphAndWriteToDisk: downloads the full graph from Spot and writes it to disk with a given graph name. It can then be reloaded onto Spot at a later date. This disk storage will persist across reboots of the computer running the Rocos Agent. In most cases this will be the Spot CORE.

  • getRecordingStatus: returns the recording status (e.g. whether or not Spot is currently recording a map).

  • localize: allows requesting that Spot localize itself within its map. You can ask Spot to localize to a given pose and/or fiducial. The inputs for the service call are anchorPose, ignoreFiducials, and fiducialId .

    • anchorPose : if unset (this is examined by confirming that the pose is empty or contains an all-zero quaternion for the rotation), then it will be ignored. Otherwise, a user can provide a suggestion as to where Spot should be in the map. The GraphNav service on Spot will then attempt to refine this based on its current sensor data compared to the data it stored when building the map.
    • ignoreFiducials : this can be set to true to tell GraphNav to ignore any fiducials it might see. This may be desired if you want the localization to only use the anchor pose you have provided for its localization attempt. If set to false, then Spot must be able to see a fiducial or else the localization attempt will fail.
    • fiducialId: If you want Spot to localize to a specific fiducial, then you can provide the fiducial ID here. If Spot cannot see this fiducial, an error will be returned.
  • localizeToNearestFiducial: Spot will attempt to localize using the nearest fiducial. If it can't see any fiducials, an error will be returned.

  • navigateToAnchorBlocking: explained in the Navigation documentation page.

  • navigateToAnchorNonBlocking: explained in the Navigation documentation page.

  • startRecordingMap: begin recording a new map. During recording, GraphNav navigation commands (such as navigateToAnchorBlocking) will be refused.

  • stopRecordingMap: complete the map recording.

  • createWaypoint: create a new waypoint at Spot's current position in its map. A prerequisite for calling this service is that map recording is in progress and Spot is localized to this map. The service takes as input the waypoint name you would like. It also takes an array of any fiducial IDs that you would like Spot to verify are currently visible before creating the waypoint. A Spot graph_nav.CreateWaypointResponse is returned in the service response. This includes information such as metadata for the waypoint created as well as the edge that links it to the existing map.

  • uploadGraph: upload a graph to Spot in a JSON string format. An example of this format is shown below. Note: this is not a valid graph and is simply shown to outline the JSON format expected.

{
"edge_snapshots": {
"edge_snapshot_id_arced-coati-k55Nltmtfb1T+WDyHrU56Q==": "{\"header\":{\"requestHeader\":{\"requestTimestamp\":\"2022-08-31T01:41:06.565402809Z\", \"clientName\":\"rocos-agent\"}, \"requestReceivedTimestamp\":\"2022-08-31T01:40:29.767634267Z\", \"responseTimestamp\":\"2022-08-31T01:40:29.767651442Z\", \"error\":{\"code\":\"CODE_OK\"}, \"request\":{\"@type\":\"type.googleapis.com/bosdyn.api.graph_nav.DownloadEdgeSnapshotRequest\", \"header\":{\"requestTimestamp\":\"2022-08-31T01:41:06.565402809Z\", \"clientName\":\"rocos-agent\"}, \"edgeSnapshotId\":\"edge_snapshot_id_arced-coati-k55Nltmtfb1T+WDyHrU56Q==\"}}, \"status\":\"STATUS_OK\", \"edgeSnapshotId\":\"edge_snapshot_id_arced-coati-k55Nltmtfb1T+WDyHrU56Q==\", \"chunk\":{\"totalSize\":\"633\", \"data\":\"CjVlZGdlX3NuYXBzaG90X\"}}"
},
"waypoint_snapshots": {
"snapshot_both-medusa-PjsPDTKhnX.zjIz92Q5rLw==": "{\"header\":{\"requestHeader\":{\"requestTimestamp\":\"2022-08-31T01:41:06.548500071Z\", \"clientName\":\"rocos-agent\"}, \"requestReceivedTimestamp\":\"2022-08-31T01:40:29.750843096Z\", \"responseTimestamp\":\"2022-08-31T01:40:29.751582905Z\", \"error\":{\"code\":\"CODE_OK\"}, \"request\":{\"@type\":\"type.googleapis.com/bosdyn.api.graph_nav.DownloadWaypointSnapshotRequest\", \"header\":{\"requestTimestamp\":\"2022-08-31T01:41:06.548500071Z\", \"clientName\":\"rocos-agent\"}, \"waypointSnapshotId\":\"snapshot_both-medusa-PjsPDTKhnX.zjIz92Q5rLw==\"}}, \"status\":\"STATUS_OK\", \"waypointSnapshotId\":\"snapshot_both-medusa-PjsPDTKhnX.zjIz92Q5rLw==\", \"chunk\":{\"totalSize\":\"163326\", \"data\":\"Ci1zbmFwc2hvdF9\"}"
},
"graph": "{\"waypoints\":[{\"id\":\"batty-hyla-+QxhCAUzvzku3EtyWtl1bQ==\", \"snapshotId\":\"snapshot_eight-chunga-t15BAbj7V91PSnzoq.oR+A==\", \"waypointTformKo\":{\"position\":{\"x\":-2.635694923530833, \"y\":0.036716884261488246, \"z\":8.104246476490928}, \"rotation\":{\"x\":0.003348377998918295, \"y\":-0.0037537238094955683, \"z\":-0.18755276501178741, \"w\":0.982241690158844}}, \"annotations\":{\"name\":\"Go Here - 1\", \"creationTime\":\"2022-08-31T00:51:54.129059305Z\"}}, {\"id\":\"dressy-scarab-0CXghvdyEQKTGpIZLiLhKg==\", \"snapshotId\":\"snapshot_peanut-civet-4s0LCuFT2tVr2ib9yENw0Q==\", \"waypointTformKo\":{\"position\":{\"x\":-2.621692068110653, \"y\":0.12672358207400033, \"z\":8.530503860555772}, \"rotation\":{\"x\":0.0000710085078026168, \"y\":-0.0018362380797043443, \"z\":-0.19325873255729675, \"w\":0.9811460971832275}}, \"annotations\":{\"name\":\"Test123 - Test123 - 1\", \"creationTime\":\"2022-08-31T00:52:34.063716029Z\", \"scanMatchRegion\":{\"empty\":{}}}}, {\"id\":\"ended-insect-DxDSztlHTDj+UPommQsHYQ==\", \"snapshotId\":\"snapshot_permed-impala-sYQ6r2r7VIlk+4LRvNVd5Q==\", \"waypointTformKo\":{\"position\":{\"x\":0.06915909969187833, \"y\":0.05662527076359212, \"z\":8.07674714175705}, \"rotation\":{\"x\":0.0036410747561603785, \"y\":-0.002288072369992733, \"z\":-0.19270142912864685, \"w\":0.9812480211257935}}, \"annotations\":{\"name\":\"Go Here - 2\", \"creationTime\":\"2022-08-31T00:52:56.710367801Z\"}}], \"edges\":[{\"id\":{\"fromWaypoint\":\"batty-hyla-+QxhCAUzvzku3EtyWtl1bQ==\", \"toWaypoint\":\"dressy-scarab-0CXghvdyEQKTGpIZLiLhKg==\"}, \"snapshotId\":\"edge_snapshot_id_arced-coati-k55Nltmtfb1T+WDyHrU56Q==\", \"fromTformTo\":{\"position\":{\"x\":0.029856496528475773, \"y\":-0.010931830402090323, \"z\":-0.41346441172910353}, \"rotation\":{\"x\":0.002834452112088394, \"y\":-0.002513107316863454, \"z\":0.005816002570657397, \"w\":0.9999759409377263}}, \"annotations\":{\"velLimit\":{}, \"stairs\":{\"state\":\"ANNOTATION_STATE_NONE\"}, \"directionConstraint\":\"DIRECTION_CONSTRAINT_NONE\", \"flatGround\":false, \"overrideMobilityParams\":\"terrainParams.gratedSurfacesMode,terrainParams.groundMuHint,bodyControl,obstacleParams.obstacleAvoidancePadding,obstacleParams.disableVisionFootObstacleAvoidance,obstacleParams.disableVisionBodyObstacleAvoidance,obstacleParams.disableVisionNegativeObstacles,disallowStairTracker,disableStairErrorAutoDescent,disallowNonStairsPitchLimiting,disableNearmapCliffAvoidance,swingHeight,locomotionHint\", \"mobilityParams\":{\"obstacleParams\":{}, \"terrainParams\":{}}, \"cost\":0.41468510350311427, \"edgeSource\":\"EDGE_SOURCE_ODOMETRY\"}}"
}

Telemetry:

  • graph: the graph currently on Spot. This includes the edges, waypoints, and anchoring. It does not include the edge and waypoint snapshots..
  • graphGeojson: the graph waypoints and edges represented as a GeoJSON Feature Collection of Point and LineString features, respectively. If the graph has valid anchoring, this GeoJSON will be in the anchor frame. Otherwise it will use the waypoint position in the odom frame.
  • graphsSavedToDisk: the list of graph names saved to disk.
  • isRecordingMap: a boolean showing true/false as to whether or not Spot is currently recording a map.
  • isSpotLost: a boolean indicating if Spot's localization within a map is no longer valid. This can happen if the map has changed too much since the time it was recorded.
  • localizationStatus: the full localization status received from Spot.
  • navigationFeedback: feedback on any navigation commands that are currently being executed.
  • navigationInProgress: boolean representing whether a navigation command is currently being executed.
  • navigationStatus: the human readable string status extracted from navigation feedback.
  • remainingRouteGeojson: the GeoJSON Feature Collection showing route Spot is currently taking to reach a navigation goal.
  • waypoints: the number of waypoints in the graph currently on Spot.
  • worldObjectAnchoringsGeoJSON: the GeoJSON Feature Collection representation of the anchor positions of world objects in Spot's map. A common example of a world object is a fiducial.

Map Processing:

Spot's map processing allows a user to request that Spot automatically find any additional edges between waypoints that may not have been made during the map recording. This is known as topology processing.

Map anchoring functionality also allows transforming Spot's anchor frame into a frame of your choosing.

More information on map topology processing and anchor processing can be found in the relevant Boston Dynamics documentation here.

Services:

  • clearMapAnchoringCache: removes the known anchoring stored in the Agent.
  • processFullMapAnchoring: processes the input array of waypoint and world object anchors. These specify how each waypoint and world object should be represented in the anchor frame.
  • processMapTopology: request that Spot automatically find any additional edges between waypoints that may not have been made during the map recording.
  • processWaypointAnchoring: add a single waypoint anchoring. This can be done one waypoint at a time. The Rocos Agent will store each anchoring in memory and append it to each subsequent request.
  • processWorldObjectAnchoring: add a single world object anchoring. This can be done one world object at a time. The Rocos Agent will store each anchoring in memory and append it to each subsequent request.

Telemetry:

  • currentAnchoring: telemetry message showing all of the waypoint and world object anchorings currently saved in memory by the Rocos Agent.

ROS Anchor Pose:

Telemetry:

  • anchor: Spot's pose in the anchor frame, formatted as a ROS odometry message.

Spot's GraphNav service allows a user to request that Spot navigate to a specified position in Spot's anchor frame. Spot can achieve this by traversing the known waypoints and edges in its map to find the best route.

The Rocos Agent exposes this functionality with two service calls:

  • navigateToAnchorBlocking
  • navigateToAnchorNonBlocking

The non-blocking variation will immediately return success if the inputs are correct and Spot is in a valid state for navigation.

The service payload required for these services is explained below:

{
"anchorGoal": {
"position": {
"x": 0,
"y": 0,
"z": 0
},
"rotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 0
}
},
"tolerance": {
"x": 0,
"y": 0,
"z": 0
},
"travelParams": {
"max_distance": 0,
"max_yaw": 0,
"velocity_limit": {
"max_vel": {
"angular": 0,
"linear": {
"x": 0,
"y": 0
}
},
"min_vel": {
"angular": 0,
"linear": {
"x": 0,
"y": 0
}
}
},
"ignore_final_yaw": false,
"feature_quality_tolerance": 0,
"disable_directed_exploration": false,
"disable_alternate_route_finding": false,
"path_following_mode": 1,
"blocked_path_wait_time": {
"seconds": 20
},
"ground_clutter_mode": 2
},
"ttl": "",
"disableTimeout": false
}
  • anchorGoal: the pose in the anchor frame Spot should navigate to.

  • tolerance: the x,y,z parameters control the selection of the goal waypoint. In the anchor frame, they are the with respect to the goal pose within which waypoints will be considered.

  • travelParams:

    • max_distance: the threshold in metres within which Spot will consider itself to have reached the anchor goal.

    • max_yaw: the maximum difference in yaw angle in radians compared to the anchor goal angle below which Spot will consider itself to have reached the anchor goal.

    • velocity_limit: the minimum and maximum velocities you would like Spot to use while navigating to the anchor goal.

    • ignore_final_yaw: if true, Spot will attempt to reach the anchor goal position without attempting to achieve the anchor goal yaw angle.

    • feature_quality_tolerance: controls the number of waypoints Spot will tolerate that have poor feature quality. The values accepted are:

      • 1: Spot's default number of waypoints with poor feature quality will be allowed.
      • 2: Unlimited number of waypoints with poor feature quality will be allowed.
    • disable_directed_exploration: if true. directed exploration for the navigation will be disabled. Boston Dynamics' documentation on this can be found here.

    • disable_alternate_route_finding: if true, Spot will not attempt to find an alternative route to an anchor goal if it decides that the first route chosen is not traversable.

    • path_following_mode: (As of Spot Release 3.2.0) options for this are default and strict.

      • 1: Default path following mode will be used as determined during map recording.
      • 2: Strict path following mode. Any obstacles that Spot would otherwise attempt to walk around will not be allowed. Spot will expect to walk in exactly the same path as it did during map recording. This may be useful for scenarios where following a highly determinant path is required.
    • blocked_path_wait_time : (As of Spot Release 3.2.0) allows specifying the number of seconds Spot should wait if an unexpected obstacle is encountered. This provides a convenient way for Spot to allow dynamic obstacles such as humans to move themselves out of Spot's path before Spot will continue navigating.

    • ground_clutter_mode: (As of Spot Release 3.2.0) options are:

      • 1: Off. Spot will attempt to walk on any small obstacles in its path that are below the height threshold for a non-traversable object even if they were not present during map recording.
      • 2: Objects that were not stepped on during map recording are considered to obstacles which Spot will avoid.
  • ttl: the string time-to-live input determining how long Spot is allowed to attempt navigating to the goal before the robot should stop. If a user, for example, enters "30s" for this, then Spot will have 30 seconds to reach the goal. If navigation is still in progress after this time, Spot will give up.

  • disableTimeout: for long running navigation commands a user may wish that there is no timeout. If this parameter is set to true, then the ttl input explained above will be ignored. Spot will therefore continue navigating as long is required before it either reaches the goal or encounters an error. The disableTimeout parameter is only available for the navigateToAnchorBlocking call, not the non-blocking variant.