Cartographer Modular Resource

The Cartographer Project contains a C++ library that performs dense Simultaneous Localization And Mapping (SLAM).

To use Cartographer with the Viam SLAM service, you can use the cartographer modular resource.

The source code for this module is available on the viam-cartographer GitHub repository.

Using Cartographer

The cartographer module supports three modes of operation:

Hardware requirements

RPLidar

  • You must have an RPlidar, such as the RPlidar A1 or RPlidar A3, physically connected to your machine.

    Be sure to position the RPlidar so that it faces forward in the direction of travel. For example, if you are using a Viam Rover and the RPlidar A1 model, mount it to the Rover so that the pointed end of the RPlidar mount housing is facing in the same direction as the webcam.

    Furthermore, ensure that the center of the RPlidar is mounted at the center of your machine’s base. In the case of the Viam Rover the center is in the middle between the wheels.

    If you need a mount plate for your RPlidar A1 or A3 model, you can 3D print an adapter plate using the following:

  • In addition, you must add the rplidar module to your machine to support the RPlidar hardware, if you have not done so already.

Movement sensors (optional)

You can use data from one or more movement sensors on your machine to supplement the required LiDAR data. If you choose to use movement sensor data for SLAM, you can:

  • Add only inertial measurement unit (IMU) data
  • Add only odometry data
  • Add both IMU and odometry data
    • Requires all four of the above kinds of data, merged together using the merged movement sensor model
    • If you choose this option, be sure to configure data capture on the merged sensor and not on the individual movement sensors when following the steps below.

Create a new map

To create a new map, follow the instructions below.

  1. Ensure any sensors you wish to use are configured on the machine. See the Hardware Requirements above.

  2. Set up the cartographer module on your machine:

    Navigate to the CONFIGURE tab of your machine’s page in the Viam app.

    Click the + icon next to your machine part in the left-hand menu and select Service. Select SLAM, then select cartographer. You can also search for “cartographer”.

    Click Add module, give your service a name of your choice, then click Create.

    In the resulting SLAM service configuration pane, choose Create new map as the Mapping mode, then configure the rest of the Attributes for that mapping mode:

    • Camera: Select the name of the camera component that you created when you added the rplidar module to your machine. Example: “my-rplidar”. Then set the Data polling rate (Hz) for retrieving pointclouds from the camera. For RPLidar A1 and A3 we recommend a frequency of 5 Hz.
    • Movement Sensor (Optional): Select the name of the movement sensor component that you want to use for SLAM. If you are using both an IMU and an odometer, select the name of the merged movement sensor, not the name of either of the individual movement sensors. Examples: “my-imu”, “MyOdometer,” or “merged-ms”. Then set the Data polling rate (Hz) for retrieving readings from the movement sensor. We recommend a frequency of 20 Hz.
    • Minimum range (meters): Set the minimum range of your rplidar. See config params for suggested values for RPLidar A1 and A3.
    • Maximum range (meters): Set the maximum range of your rplidar. See config params for suggested values for RPLidar A1 and A3.

    If you would like to tune additional Cartographer parameters, you can the click {} button to switch to the advanced view, then edit the config_params from there. See the config_params section for more information on the other parameters.

    To save your changes, click the Save button in the top right corner of the page.

    Check the LOGS tab of your machine in the Viam app to make sure your RPlidar has connected and no errors are being raised.

  3. (Optional) Configure cartographer to use cloudSLAM:

    On the SLAM service configuration pane, click the {} button to switch to advanced views and set the use_cloud_slam field to true. This setting disables local mapping to limit cpu usage in favor of using cloudSLAM.

    In addition, your configured LiDAR camera and movement sensor must have data capture enabled. See the cloudSLAM documentation for more information on how to configure the feature on your machine and how to use cloudSLAM.

This example JSON configuration:

  • adds the viam:rplidar and the viam:cartographer modules
  • configures the viam:slam:cartographer service
{
  "modules": [
    {
      "type": "registry",
      "name": "viam_rplidar",
      "module_id": "viam:rplidar",
      "version": "0.1.16"
    },
    {
      "type": "registry",
      "name": "viam_cartographer",
      "module_id": "viam:cartographer",
      "version": "0.3.45"
    }
  ],
  "services": [
    {
      "attributes": {
        "config_params": {
          "max_range_meters": "25",
          "mode": "2d",
          "min_range_meters": "0.2"
        },
        "camera": {
          "name": "rplidar",
          "data_frequency_hz": "5"
        },
        "enable_mapping": true,
        "use_cloud_slam": false
      },
      "name": "slam",
      "type": "slam",
      "namespace": "rdk",
      "model": "viam:slam:cartographer"
    }
  ],
  "components": [
    {
      "namespace": "rdk",
      "attributes": {},
      "depends_on": [],
      "name": "rplidar",
      "model": "viam:lidar:rplidar",
      "type": "camera"
    }
  ]
}

For more information about the configuration attributes, see Attributes.

After configuring cartographer the machine should begin mapping automatically. Navigate to the CONTROL tab on your machine’s page and click on the dropdown menu matching the name of the service you created. See our tips for making good maps. If you want to save your locally built map, you can use the GetInternalState API or use the local map uploading feature of the cloudslam wrapper module.

Update an existing map

To update an existing map with new pointcloud data from a new SLAM session, follow the instructions below.

  1. Configure your cartographer SLAM service using a map from your location:

    1. Select the Mapping mode dropdown and choose the Update existing map option.
    2. Configure Select map and Map version with the name and version of the map you would like to update. For the other attributes, review the information in Create a new map. You can see more details about the available maps from your machine’s Location page by clicking View SLAM library.

    This example JSON configuration:

    • adds the viam:rplidar and the viam:cartographer modules
    • configures the viam:slam:cartographer service
    • adds an viam:lidar:rplidar camera
    • specifies the slam_map to be updated in the packages

    {
      "modules": [
        {
          "type": "registry",
          "name": "viam_rplidar",
          "module_id": "viam:rplidar",
          "version": "0.1.16"
        },
        {
          "type": "registry",
          "name": "viam_cartographer",
          "module_id": "viam:cartographer",
          "version": "0.3.45"
        }
      ],
      "services": [
        {
          "attributes": {
            "config_params": {
              "max_range_meters": "25",
              "mode": "2d",
              "min_range_meters": "0.2"
            },
            "camera": {
              "name": "rplidar",
              "data_frequency_hz": "5"
            },
            "enable_mapping": true,
            "use_cloud_slam": false,
            "existing_map": "${packages.slam_map.test-map-1}/internalState.pbstream"
          },
          "name": "slam",
          "type": "slam",
          "namespace": "rdk",
          "model": "viam:slam:cartographer"
        }
      ],
      "components": [
        {
          "namespace": "rdk",
          "attributes": {},
          "depends_on": [],
          "name": "rplidar",
          "model": "viam:lidar:rplidar",
          "type": "camera"
        }
      ],
      "packages": [
        {
          "name": "test-map-1",
          "version": "1697208847",
          "package": "d1c224e8-483e-4cc7-980f-76b89d8fb507/test-map-1",
          "type": "slam_map"
        }
      ]
    }
    

    For more information about the configuration attributes, see Attributes.

    If you want to configure cartographer to use a locally saved map instead, see Using locally built maps.

  2. After configuring cartographer the machine should begin mapping automatically. Navigate to the CONTROL tab on your machine’s page and click on the dropdown menu matching the name of the service you created.

See our tips for making a good map! If you want to save your locally built map, you can use the GetInternalState API or use the local map uploading feature of the cloudslam wrapper module

Localize only

In this mode, the cartographer module on your machine executes the Cartographer algorithm to find its position on a map. This mode is better when using motion planning’s MoveOnMap because the map will not be modified.

  1. Configure your cartographer SLAM service:

    1. Select the Mapping mode dropdown and choose the Update existing map option.
    2. Configure Select map and Map version with the name and version of the map you would like to localize on. For the other attributes, review the information in Create a new map. You can see more details about the available maps from your machine’s Location page by clicking View SLAM library.

    This example JSON configuration:

    • adds the viam:rplidar and the viam:cartographer modules
    • configures the viam:slam:cartographer service
    • adds an viam:lidar:rplidar
    • specifies the slam_map for localization in the packages

    {
      "modules": [
        {
          "type": "registry",
          "name": "viam_rplidar",
          "module_id": "viam:rplidar",
          "version": "0.1.16"
        },
        {
          "type": "registry",
          "name": "viam_cartographer",
          "module_id": "viam:cartographer",
          "version": "0.3.45"
        }
      ],
      "services": [
        {
          "type": "slam",
          "namespace": "rdk",
          "model": "viam:slam:cartographer",
          "attributes": {
            "config_params": {
              "min_range_meters": "0.2",
              "max_range_meters": "25",
              "mode": "2d"
            },
            "camera": {
              "name": "rplidar",
              "data_frequency_hz": "5"
            },
            "enable_mapping": false,
            "use_cloud_slam": false,
            "existing_map": "${packages.slam_map.test-map-1}/internalState.pbstream"
          },
          "name": "slam"
        }
      ],
      "components": [
        {
          "model": "viam:lidar:rplidar",
          "type": "camera",
          "namespace": "rdk",
          "attributes": {},
          "depends_on": [],
          "name": "rplidar"
        }
      ],
      "packages": [
        {
          "type": "slam_map",
          "name": "test-map-1",
          "version": "1697208847",
          "package": "d1c224e8-483e-4cc7-980f-76b89d8fb507/test-map-1"
        }
      ]
    }
    

    For more information about the configuration attributes, see Attributes.

    If you want to configure cartographer to use a locally saved map instead, see Using locally built maps.

  2. After configuring cartographer on the machine, the map should appear automatically. Navigate to the CONTROL tab on your machine’s page and click on the dropdown menu matching the name of the service you created.

Attributes

NameData TypeRequired?Description
use_cloud_slambooleanRequiredIf true, the Cartographer algorithm will disable mapping on the machine. This feature should only be used when trying to use cloudslam.
cameraobjRequiredAn object of the form { "name": <string>, "data_frequency_hz": <int> } where name is the name of the LiDAR camera component to use as input and data_frequency_hz is the rate at which to capture (in “Create new map” or “Update existing map” modes) or poll (in “Localize only” mode) data from that camera component.
movement_sensorobjOptionalAn object of the form { "name": <string>, "data_frequency_hz": <int> } where name is the name of the IMU movement sensor (that is, a movement sensor that supports the GetAngularVelocity and GetLinearAcceleration API methods) to use as additional input and data_frequency_hz is the rate at which to capture (in “Create new map” or “Update existing map” modes) or poll (in “Localize only” mode) data from that movement sensor component.
enable_mappingbooleanOptionalIf true, Cartographer will build the map in addition to doing localization.
    Default: true
existing_mapstringOptionalThe alias of the package containing the existing map to build on (in “Update existing map” mode) or localize on (in “Localize only” mode). Can also point to a locally saved .pbstream file.
config_paramsobjOptionalParameters available to fine-tune the cartographer algorithm: read more below.

config_params

Parameter ModeDescriptionRequired?Default ValueNotes
mode2dRequiredNone
optimize_every_n_nodesHow many trajectory nodes are inserted before the global optimization is run.Optional3To disable global SLAM and use only local SLAM, set this to 0.
num_range_dataNumber of measurements in each submap.Optional30
missing_data_ray_length_metersReplaces the length of ranges that are further than max_range with this value.Optional25Typically the same as max_range.
max_range_metersMaximum range of valid measurements.Optional25For an RPlidar A3, set this value to 25. For an RPlidar A1, use 12.
min_range_metersMinimum range of valid measurements.Optional0.2For an RPlidar A3, set this value to 0.2. For RPlidar A1, use 0.15.
max_submaps_to_keepNumber of submaps to use and track for localization.Optional3Only for LOCALIZING mode.
fresh_submaps_countLength of submap history considered when running SLAM in updating mode.Optional3Only for UPDATING mode.
min_covered_area_meters_squaredThe minimum overlapping area, in square meters, for an old submap to be considered for deletion.Optional1.0Only for UPDATING mode.
min_added_submaps_countThe minimum number of added submaps before deletion of the old submap is considered.Optional1Only for UPDATING mode.
occupied_space_weightEmphasis to put on scanned data points between measurements.Optional20.0Higher values make it harder to overwrite prior scanned points. Relative to translation weight and rotation weight.
translation_weightEmphasis to put on expected translational change from pose extrapolator data between measurements.Optional10.0Higher values make it harder for scan matching to translate prior scans. Relative to occupied space weight and rotation weight.
rotation_weightEmphasis to put on expected rotational change from pose extrapolator data between measurements.Optional1.0Higher values make it harder for scan matching to rotate prior scans. Relative to occupied space weight and translation weight.

For more information, see the Cartographer algorithm walkthrough, tuning overview, and config parameter list.

Using locally built maps

You can see details about the available maps from your machine’s Location page by clicking View SLAM library. If you do not have any maps, and you do not wish to use cloudslam, but you still want to use localizing and updating modes with cartographer, you can take the following steps.

  1. Save a .pbstream file by using the GetInternalState or InternalStateFull APIs by using one of the SDKs. Note, InternalStateFull is currently only implemented in Go.
  2. Ensure the .pbstream file is located somewhere on the machine, and note the directory path to that file.
  3. In your cartographer’s config, update the existing_map field with the path to the file that was noted in #2.

your config should look something like the following:

{
  "modules": [
    {
      "type": "registry",
      "name": "viam_rplidar",
      "module_id": "viam:rplidar",
      "version": "0.1.16"
    },
    {
      "type": "registry",
      "name": "viam_cartographer",
      "module_id": "viam:cartographer",
      "version": "0.3.45"
    }
  ],
  "services": [
    {
      "attributes": {
        "config_params": {
          "max_range_meters": "25",
          "mode": "2d",
          "min_range_meters": "0.2"
        },
        "camera": {
          "name": "rplidar",
          "data_frequency_hz": "5"
        },
        "enable_mapping": true,
        "use_cloud_slam": false,
        "existing_map": "/PATH/TO/FILE/<INTERNAL-STATE-NAME>.pbstream"
      },
      "name": "slam",
      "type": "slam",
      "namespace": "rdk",
      "model": "viam:slam:cartographer"
    }
  ],
  "components": [
    {
      "namespace": "rdk",
      "attributes": {},
      "depends_on": [],
      "name": "rplidar",
      "model": "viam:lidar:rplidar",
      "type": "camera"
    }
  ],
  "packages": []
}

Now your cartographer service should be running using your locally saved map.

Have questions, or want to meet other people working on robots? Join our Community Discord.

If you notice any issues with the documentation, feel free to file an issue or edit this file.