A practical introduction to pose-graph SLAM with ROS

Note: This is a live article and as I get time I will update it…
In this post,  we are going to understand the pose-graph SLAM approach with ROS where we can run the robot around some environment, gather the data, solve a non-linear optimization and generate a map which can then be used by the robot for localization. There are 4 major components to this problem; (i) how to generate the pose to pose odometry ?(relatively easy these days in ROS), (ii) how to generate loop closure constraints between various poses? (iii) how to solve the graph optimization problem? (iv) how to take an optimized graph and construct a usable map? Finally once we have a map, we should technically be able to use it to localize.
Before we dive into the details, here a few resources that deal with SLAM in ROS:
  1. This paper provides a comparison of SLAM techniques in ROS.
  2. In this ros answers question, I raised a discussion about doing pose-graph SLAM with ROS.
  3. open_karto is an open source library that is used by nav2d and slam_karto to do pose-graph SLAM in ROS. It provides loop closure and other capabilities required for autonomous mapping and navigation. It does not provide a backend.
  4. I have developed a ROS package called slam_karto_g2o for pose-graph SLAM using g2o as backend and open_karto as front-end.
  5. I have developed a ROS package called slam_karto_gtsam for pose-graph SLAM using GTSAM as backend and open_karto as front-end.
  6. I have developed a package called slam_karto_sesync for pose-graph SLAM using SE-Sync as backend and open karto as front-end. SE-Sync is an awesome work on globally optimal SLAM solutions from relative measurements.
  7. Luca Carlone’s website has an excellent description of the file formats that are used by pose-graph SLAM solvers.
  8. A Udacity video by Sebastian Thrun.
  9. A tutorial style video by Cyril Stachniss.
  10. g2o, GTSAM and LAGO are good options for the backend. LAGO solver by Luca Carlone @ MIT is quite robust when the odometry is bad as it separates orientation and position estimation.
  11. Google Cartographer is another option for a pose-graph SLAM solver, I have never tested or tried it before.
  12. amcl is a popular particle-filter based approach to robot localization with LiDAR.
Here are some key terms:
  1. Pose-graph: a network of nodes and edges where the nodes are robot poses and edges are constraints between poses.
  2. Loop closure: a constraint between the a recent robot pose and a past pose when the robot revisits a previously visited location. Loop closure is highly sensitive to the current estimate of where the robot is. If your current estimate is bad you may not realize you are visiting a previously visited location! There are global loop closure approaches which try to match what the robot sees to everything seen in the past in order to find a closure, such approaches may be computationally expensive.
  3. Back-end: a non-linear optimizer that solves a given graph structure and computes the history of robot poses.
  4. Front-end: detects when a loop closure occurs. This is usually the perception side of SLAM.
Now lets look at each piece of the puzzle that is pose-graph SLAM:
  1. Pose to pose odometry: First, I tried using laser_scan_matcher to compute the transformation between poses (or keyframes) but soon realized that laser_scan_matcher (which uses CSM – Canonical Scan Matcher) doesn’t work very well in cluttered environments. We have switched to using the scan matching from Hector SLAM which appeared to be doing better than laser scan matcher. But now I have switched to using open karto. It come with a very robust scan matcher.
  2. Loop closure detection (a.k.a Front-end): The front-end relies heavily on the current estimate of where the robot. This is quite sensitive to the odometry. If the odometry is bad then the front-end may never detect a loop closure. This is one of the main reasons for SLAM failure. FLIRT features are one good way to detect loop closure, however currently I rely on the open karto implementation. You can download the FLIRT library from openslam.
Let’s start talking about open karto as that seems to be the most user friendly library for pose-graph SLAM to my knowledge.

open_karto is an open source BSD licensed version of Karto SLAM SDK that is marketed by Karto Robotics from SRI International. Open karto is quite popularly used in ROS, I have seen nav2d and slam_karto both use this package. Open karto does does not inherently provide a bundle adjustment or optimization solver. Rather you are supposed to provide an external solver. A commonly used library to solve the pose-graph with open karto is sparse bundle adjustment (sba package). Now lets elaborate more on what we know so far about these packages.

Open karto appears to handle scan matching, loop closure detection and maintaining the underlying pose-graph structure for the SLAM problem. It requires an external solver to solve the non-linear optimization or bundle adjustment. In Mapper.cpp, Mapper class has a Process function which processes a new incoming laser scan. If scan matching is set to true, it will do scan matching to compute local corrections, if loop closure is set to true it will also check for loop closure. In OpenMapper.cpp, MapperGraph class has a TryCloseLoop function that uses the internal MatchScan function to find transforms for loop closure. To add our bundle adjustment solver, all we need to do is to write a wrapper class around GTSAM, g2o etc. which provides the same interface as the SpaSolver class in slam_karto.
The slam karto package basically uses open karto to create and maintain the pose-graph and sba package to solve the pose-graph SLAM problem. The sba package provides for a way to add a vertex and a constraint to the pose-graph. The slam_karto.cpp file handles incoming laser scans using laserCallback function, this function internally calls addScan. In addScan, first the odometry pose is retrieved using getOdomPose function, getOdomPose looks for the transform from odom frame to base_link by default. If no odometry pose transform is found, the addScan function returns false. If an odometry transform is found, addScan proceeds and converts the ros laser scan message into a karto localized range scan and places it at the odometric pose. The range scan is then processed by the Karto Mapper class, and the corrected pose of the newly added vertex is retrieved, these corrections usually happen when loop closure is detected. The SpaSolver class in spa_solver.h is basically a wrapper that connects karto’s mapper to sba library.
sparse bundle adjustment (sba)
The sba package is based on work by Kurt Konolige (pdf). The sba package provides in spa2d.h a class called SysSPA2d. This class allows adding nodes and constraints for the bundle adjustment problem. It uses Levenberg-Marquadt approach to non-linear optimization and uses CHOLMOD internally to solve the linear sub-problems. Ideally, it should not be difficult to use any other solver like g2o or GTSAM instead of sba to do slam with open karto.


  1. leon yanoff said:

    when i use the package of slam_karto_g2o ,i find that the open_karto version is not the same as mine. will you provide the correct version?

    August 19, 2017
        • sauravagarwal said:

          That was a little change I made to open karto myself and forgot to remove earlier. Now, I have removed that particular parameter loading. Please pull the latest version and try using it.

          August 21, 2017
          • Aswin said:

            Was this parameter loading removed?

            I get slam_karto_gtsam.cpp:170:14: error: ‘class karto::Mapper’ has no member named ‘setParamDoLoopClosingWithoutScanMatching’

            May 29, 2018
          • sauravagarwal said:

            Hi Aswin, thanks for bringing this to my attention. Yes this parameter was removed.

            July 1, 2018
  2. Lv Chaoshun said:

    Why cannot loop close use your slam_karto_g2o?

    December 19, 2017
    • sauravagarwal said:

      Can you provide more details?

      December 24, 2017
      • Lv Chaoshun said:

        Hi sauravagarwal :
        I am so glad that you can reply me, I have found the problem, the parameter need to adjust, thank you!

        and I found the G2O was no better than SPA. sometimes the G2O cannot loop closure.

        January 2, 2018
  3. Lv Chaoshun said:

    Hi sauravagarwal:
    Did you know how to save my pose graph, and reload it to continue mapping when next time?

    January 3, 2018
    • sauravagarwal said:

      That’s a great question! for SRI Karto you may have to write your own function to write out the pose-graph in the form of an xml or something else. It’s not too hard but something that doesn’t exist. On the other hand you can try google cartographer which does allow you to write out the map.

      April 1, 2018
  4. Jad said:

    Do you know any front ends for pose-graph slam that use landmark measurements (range and bearing), instead of laser scans?

    August 3, 2018
    • sauravagarwal said:

      You can use fiducial marker libraries like Aruco which will give you data association and range/bearing measurements to unique landmarks. If you’re looking for a more generic landmark based system, then I’m not too aware.

      August 3, 2018
  5. Dandan said:


    Thanks for your sharing. I just have a few questions about using open karto for pose-to-pose odometry. Since open-karto also needs an odometric pose as input, what odometric source do you provide with open-karto? And in this case, odometric source publishes to odom frame, open-karto corrects it and publishes the result to map frame? Is it?

    Thanks a lot for your help.

    October 30, 2018
    • sauravagarwal said:

      Usually wheel odometry is a good odometry source. Yes odometric source publishes to odom frame, open-karto corrects it and publishes the result to map frame

      November 3, 2018
      • Danx said:

        Thanks. And I tried to use “wheel odom -> karto map” to generate the closed map from the first tour. And it works pretty good. And then for the later-on tours, I don’t need a new map anymore. I just need to localize the robot with the map (from first tour) and navigation.

        For this need, can I also use open-karto for localization only, since I feel its scan match is pretty powerful? I tried to set the tf tree as “wheel odom -> open karto frame -. amcl map frame”. And of course, amcl is provided with the generated map from the first tour. Do you think it is a good choice? Or do you have other suggestions? And in my environment, wheel-odom is not accurate enough to provide odometry for amcl.

        November 7, 2018
        • sauravagarwal said:

          What you’re trying to do is better achieved by cartographer. Cartographer doesn’t need external odometry sources. If you have any IMU and a Lidar you can get away with pretty good results.

          November 8, 2018
  6. Milad said:


    I am quite new in ROS. When I catkin build the pkg there is no launch folder. Would you please help with my concern.


    November 1, 2018
    • sauravagarwal said:

      Looks like you need to go through basic ROS tutorials of which there are plenty on the web

      November 3, 2018
      • Milad said:

        Hi Saurava,

        Can you link me to a data which is directly used in slam_karto?

        Kind regards

        January 28, 2019
  7. Jack Lee said:

    Hi sauravagarwal:
    I’m not very familiar with ROS and I am learning karto. I have downloaded the slam_karto and roslaunch the build_map_w_params.launch, what bag I paly is intel.bag ,I can see the laser points, but I can’t see the map from rviz . I can see /map in topiclist while i can’t see the map in rqt_graph. At first I thought the pack of slam_karto did not work, so I downloaded slam_karto_g2o but the results were the same.It’s been bothering me for a long time, and I can’t figure it out.Could you help me?

    November 10, 2018
    • sauravagarwal said:

      make sure the odometry is available and sent on the right topic at which the slam system wants it. Top culprits can be missing odometry or mismatched topic names. I have never tried it on the intel bag so i am not sure what data sources it contains.

      November 10, 2018
      • Jack Lee said:

        Thank you for taking the time to reply to me, you helped me a lot.

        November 11, 2018
        • sauravagarwal said:


          November 18, 2018
  8. Seon said:


    Can I run this without tf messages?
    I only have LaserScan Data.
    And I don’t want to use Google Cartographer


    December 4, 2020
  9. Polychronis Kondaxakis said:


    In your slam_karto_sesync implementation, there is a problem aligning the maps correctly every time the sesync algorithm is trying to optimize the graph. Have you managed to produce any correct map alignments at any available datasets?

    Best regards,


    April 30, 2022
  10. Polychronis Kondaxakis said:

    Hi again,

    I noticed that in the slam_karto_gtsam implementation, the map frame jumps dramatically with respect to odometry frame from times to times. Are you aware of this behavior? If yes can you explain it?

    Please let me know.

    Best regards,


    April 30, 2022

Comments are closed.