├── .gitignore
├── .gitmodules
├── README.md
├── sample_code_cpp
├── README.md
├── data
│ ├── corridor.lsc
│ └── hall.lsc
├── framework.cfg
├── images
│ ├── dependency_graph.png
│ ├── odom.png
│ └── slam.png
└── src
│ ├── CMakeLists.txt
│ ├── cxxopts
│ └── cxxopts.hpp
│ ├── launcher
│ ├── CMakeLists.txt
│ ├── FrameworkFactory
│ │ ├── CostFunctionFactory
│ │ │ └── CostFunctionFactory.h
│ │ ├── DataAssociatorFactory
│ │ │ └── DataAssociatorFactory.h
│ │ ├── FrameworkFactory.cpp
│ │ ├── FrameworkFactory.h
│ │ ├── PointCloudMapFactory
│ │ │ └── PointCloudMapFactory.h
│ │ ├── PoseEstimatorFactory
│ │ │ └── PoseEstimatorFactory.h
│ │ ├── PoseOptimizerFactory
│ │ │ └── PoseOptimizerFactory.h
│ │ └── ReferenceScanMakerFactory
│ │ │ └── ReferenceScanMakerFactory.h
│ ├── MapDrawer
│ │ ├── MapDrawer.cpp
│ │ └── MapDrawer.h
│ ├── SensorDataReader
│ │ ├── SensorDataReader.cpp
│ │ └── SensorDataReader.h
│ └── SlamLauncher
│ │ ├── SlamLauncher.cpp
│ │ └── SlamLauncher.h
│ ├── main.cpp
│ ├── slam
│ ├── CMakeLists.txt
│ ├── CostFunction
│ │ ├── CostFunction.h
│ │ ├── CostFunction_EuclideanDistance.cpp
│ │ ├── CostFunction_EuclideanDistance.h
│ │ ├── CostFunction_PerpendicularDistance.cpp
│ │ └── CostFunction_PerpendicularDistance.h
│ ├── CovarianceCalculator
│ │ ├── CovarianceCalculator.cpp
│ │ └── CovarianceCalculator.h
│ ├── DataAssociator
│ │ ├── DataAssociator.h
│ │ ├── DataAssociator_GridTable.cpp
│ │ ├── DataAssociator_GridTable.h
│ │ ├── DataAssociator_LinearSearch.cpp
│ │ └── DataAssociator_LinearSearch.h
│ ├── LoopDetector
│ │ ├── LoopDetector.cpp
│ │ └── LoopDetector.h
│ ├── PointCloudMap
│ │ ├── PointCloudMap.h
│ │ ├── PointCloudMap_EntirePoint.cpp
│ │ ├── PointCloudMap_EntirePoint.h
│ │ ├── PointCloudMap_GridTable.cpp
│ │ ├── PointCloudMap_GridTable.h
│ │ ├── PointCloudMap_SubMap.cpp
│ │ └── PointCloudMap_SubMap.h
│ ├── PoseEstimator
│ │ ├── PoseEstimator.h
│ │ ├── PoseEstimator_ICP.cpp
│ │ ├── PoseEstimator_ICP.h
│ │ ├── PoseEstimator_NDT.cpp
│ │ └── PoseEstimator_NDT.h
│ ├── PoseGraph
│ │ ├── PoseGraph.cpp
│ │ └── PoseGraph.h
│ ├── PoseOptimizer
│ │ ├── PoseOptimizer.h
│ │ ├── PoseOptimizer_GradientDescent.cpp
│ │ ├── PoseOptimizer_GradientDescent.h
│ │ ├── PoseOptimizer_LineSearch.cpp
│ │ └── PoseOptimizer_LineSearch.h
│ ├── ReferenceScanMaker
│ │ ├── ReferenceScanMaker.h
│ │ ├── ReferenceScanMaker_LastScan.cpp
│ │ ├── ReferenceScanMaker_LastScan.h
│ │ ├── ReferenceScanMaker_LocalMap.cpp
│ │ └── ReferenceScanMaker_LocalMap.h
│ ├── ScanMatcher
│ │ ├── ScanMatcher.cpp
│ │ └── ScanMatcher.h
│ ├── ScanPreprocessor
│ │ ├── ScanPreprocessor.cpp
│ │ └── ScanPreprocessor.h
│ ├── SlamBackend
│ │ ├── SlamBackend.cpp
│ │ └── SlamBackend.h
│ └── SlamFrontend
│ │ ├── SlamFrontend.cpp
│ │ └── SlamFrontend.h
│ ├── solver
│ └── p2o
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── p2o.h
│ │ └── samples
│ │ ├── CMakeLists.txt
│ │ ├── build_and_run_p2o.sh
│ │ ├── plot_data.plt
│ │ └── test_p2o.cpp
│ ├── test
│ ├── launcher
│ │ └── CMakeLists.txt
│ ├── slam
│ │ └── CMakeLists.txt
│ └── utility
│ │ ├── CMakeLists.txt
│ │ ├── LaserPoint2D_test.cpp
│ │ ├── MyUtility_test.cpp
│ │ └── Pose2D_test.cpp
│ └── utility
│ ├── CMakeLists.txt
│ ├── GridTable2D.h
│ ├── LaserPoint2D.h
│ ├── MyUtility
│ ├── MyUtility.cpp
│ └── MyUtility.h
│ ├── Pose2D.h
│ └── Scan2D.h
├── sample_code_python
├── data
│ ├── killian-e.dat
│ ├── killian-small-rot-inf-e.dat
│ ├── killian-v.dat
│ └── mit-e.dat
├── graph_based_slam.ipynb
└── images
│ ├── graph_based_slam1.png
│ ├── graph_based_slam2.png
│ └── graph_based_slam3.png
└── tex
├── Graph-Based-SLAM_english.pdf
├── Graph-Based-SLAM_english.tex
├── Graph-Based-SLAM_japanese.pdf
├── Graph-Based-SLAM_japanese.tex
└── images
├── 1-1_error_between_edges.png
├── 1-1_error_between_edges.xbb
├── 2-1_coordinate.png
├── 2-1_coordinate.xbb
├── 2-2_rotation_matrix.png
├── 2-2_rotation_matrix.xbb
├── 2-3_pose_representation_matrix.png
├── 2-3_pose_representation_matrix.xbb
├── 2-4_pose_representation_matrix_inverse.png
├── 2-4_pose_representation_matrix_inverse.xbb
├── 2-5_observation_representation_matrix.png
├── 2-5_observation_representation_matrix.xbb
├── 2-6_rotation_matrix.png
├── 2-6_rotation_matrix.xbb
├── 2-7_sensor_model.png
├── 2-7_sensor_model.xbb
├── 3-1_difference_between_nodes.png
├── 3-1_difference_between_nodes.xbb
├── 3-2_error_between_edges.png
├── 3-2_error_between_edges.xbb
├── 4-1_by_deleji_1.png
├── 4-1_by_deleji_1.xbb
├── 4-2_by_deleji_2.png
├── 4-2_by_deleji_2.xbb
├── 4-3_by_deleji_3.png
├── 4-3_by_deleji_3.xbb
├── Graph-Based-SLAM_english-page-001.jpg
├── Graph-Based-SLAM_english-page-003.jpg
├── Graph-Based-SLAM_english-page-005.jpg
└── Graph-Based-SLAM_english-page-007.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | sample_code_cpp/src/build/
2 | sample_code_cpp/.vscode/
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "sample_code_cpp/src/cmake/DownloadProject"]
2 | path = sample_code_cpp/src/cmake/DownloadProject
3 | url = https://github.com/Crascit/DownloadProject.git
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Graph Based SLAM
2 |
3 | Explanation of Graph based SLAM with C++ and Python sample code
4 |
5 |
6 | ## Explanation
7 |
8 | [tex/Graph-Based-SLAM_english.pdf](./tex/Graph-Based-SLAM_english.pdf)
9 |
10 | | | | |
11 | | :---: | :---: | :---: |
12 | |  |  |  |
13 |
14 |
15 | ## Sample code [C++]
16 |
17 | [sample_code_cpp](./sample_code_cpp/)
18 |
19 | | Odometry only | Sample SLAM |
20 | | :---: | :---: |
21 | |  |  |
22 |
23 |
24 | ## Sample code [Python]
25 |
26 | [sample_code_python](./sample_code_python/)
27 |
28 | | | | |
29 | | :---: | :---: | :---: |
30 | |  |  |  |
--------------------------------------------------------------------------------
/sample_code_cpp/README.md:
--------------------------------------------------------------------------------
1 | # Sample SLAM
2 |
3 | Scan matching as a front-end, Graph based SLAM as a back-end.
4 | Inspired by [furo-org/LittleSLAM](https://github.com/furo-org/LittleSLAM).
5 |
6 | | Odometry only | Sample SLAM |
7 | | :---: | :---: |
8 | |  |  |
9 |
10 | The framework can be customized in `framework.cfg` by Factory Method as shown below:
11 |
12 | | Module | Type | Description |
13 | | --- | --- | --- |
14 | | PointCloudMap | _EntirePoint | Stores entire laser point |
15 | | | _GridTable | Stores laser points in a grid based manner |
16 | | | _SubMap | Stores laser points in a grid based manner with sub maps |
17 | | ReferenceScanMaker | _LastScan | Last scan as a reference scan for scan matching |
18 | | | _LocalMap | Local map as a reference scan for scan matching |
19 | | PoseEstimator | _ICP | Iterative Closest Point |
20 | | | _NDT | Normal Distribution Transform (WIP) |
21 | | DataAssociator | _LinearSearch | Linear search to find corresponding laser points |
22 | | | _GridTabel | Grid based search to find corresponding laser points |
23 | | PoseOptimizer | _GradientDescent | Gradient descent with a fixed step rate |
24 | | | _LineSearch | Gradient descent with a dynamic step rate determined by line search |
25 | | CostFunction | _EuclideanDistance | Euclidean distance as an error distance |
26 | | | _PerpendicularDistance | Perpendicular distance as an error distance |
27 |
28 |
29 |
30 | 
31 |
32 | # Pre-requirements
33 |
34 | * Boost
35 | * CMake
36 | * Eigen
37 | * gnuplot
38 |
39 | ## Install on Ubuntu
40 |
41 | ```
42 | $ sudo apt-get install build-essential libboost-all-dev cmake libeigen3-dev gnuplot gnuplot-x11
43 | ```
44 |
45 | ## Install on Mac
46 |
47 | ```
48 | $ brew install boost cmake eigen gnuplot
49 | ```
50 |
51 |
52 |
53 | # How to build
54 |
55 | ```
56 | $ git clone --recursive https://github.com/hotsuyuki/Graph-Based-SLAM.git
57 | $ cd Graph-Based-SLAM/
58 | $ cd sample_code_cpp/src/
59 | $ mkdir build
60 | $ cd build/
61 | $ cmake ..
62 | $ cmake --build .
63 | ```
64 |
65 | This command downloads [google/googletest](https://github.com/google/googletest) using [Crascit/DownloadProject](https://github.com/Crascit/DownloadProject) and produces an executable file named `main` in the `build` directory.
66 |
67 |
68 |
69 | # How to run
70 |
71 | The executable file `main` requires at least two arguments:
72 |
73 | * `data-file` ... path to the input scan data
74 | * `viz-mode` ... visualization mode: *scan* | *odom* | *slam*
75 |
76 | ## (a) Launch SLAM
77 |
78 | ```
79 | $ ./main --data-file ../../data/corridor.lsc --viz-mode slam
80 | ```
81 | or
82 | ```
83 | $ ./main ../../data/corridor.lsc slam
84 | ```
85 |
86 | ## (b) Odometry only
87 |
88 | ```
89 | $ ./main --data-file ../../data/corridor.lsc --viz-mode odom
90 | ```
91 | or
92 | ```
93 | $ ./main ../../data/corridor.lsc odom
94 | ```
95 |
96 | ## (c) Check scan data
97 |
98 | ```
99 | $ ./main --data-file ../../data/corridor.lsc --viz-mode scan
100 | ```
101 | or
102 | ```
103 | $ ./main ../../data/corridor.lsc scan
104 | ```
105 |
106 | The full arguments and options are shown below:
107 |
108 | ```
109 | usage:
110 | main [OPTION...] data-file viz-mode
111 |
112 | positional arguments:
113 | data-file String: Path to sensor data file (.lsc)
114 | viz-mode String: Visualization mode ... scan | odom | slam
115 |
116 | options:
117 | -h, --help Print usage
118 | ```
119 |
120 |
121 |
122 | # How to test
123 |
124 | The program can be tested with Google C++ Testing Framework.
125 |
126 | ```
127 | $ cd Graph-Based-SLAM/
128 | $ cd sample_code_cpp/src/build/
129 | $ ./test/utility/utility_test
130 | ```
131 |
132 |
133 |
134 | # References
135 |
136 | * [furo-org/LittleSLAM](https://github.com/furo-org/LittleSLAM)
137 | * [furo-org/p2o](https://github.com/furo-org/p2o/tree/768dee340de702a6eee61f7b0172a836d1e021ea)
138 | * [TadaoYamaoka/cxxopts/include/cxxopts.hpp](https://github.com/TadaoYamaoka/cxxopts/blob/master/include/cxxopts.hpp)
--------------------------------------------------------------------------------
/sample_code_cpp/framework.cfg:
--------------------------------------------------------------------------------
1 | # Framework Config
2 | # Comment starts from '#' or ';'
3 |
4 |
5 | ## [point_cloud_map_type] : entire_point | grid_tabel | sub_map
6 | ### entire_point ... Stores entire laser point
7 | ### grid_tabel ... Stores laser points in a grid based manner
8 | ### sub_map ... Stores laser points in a grid based manner with sub maps
9 | ; point_cloud_map_type = entire_point
10 | ; point_cloud_map_type = grid_table
11 | point_cloud_map_type = sub_map
12 |
13 |
14 | ## [reference_scan_maker_type] : last_scan | local_map
15 | ### last_scan ... Last scan as a reference scan for scan matching
16 | ### local_map ... Local map as a reference scan for scan matching
17 | ; reference_scan_maker_type = last_scan
18 | reference_scan_maker_type = local_map
19 |
20 |
21 | ## [pose_estimator_type] : icp | ndt
22 | ### icp ... Iterative Closest Point
23 | ### ndt ... Normal Distribution Transform
24 | pose_estimator_type = icp
25 | ; pose_estimator_type = ndt
26 |
27 |
28 | ## [data_associator_type] : linear_search | grid_table
29 | ### linear_search ... Linear search to find corresponding laser points
30 | ### grid_tabel ... Grid based search to find corresponding laser points
31 | ; data_associator_type = linear_search
32 | data_associator_type = grid_table
33 |
34 |
35 | ## [pose_optimizer_type] : gradient_descent | line_search
36 | ### gradient_descent ... Gradient descent with a fixed step rate
37 | ### line_search ... Gradient descent with a dynamic step rate determined by line search
38 | pose_optimizer_type = gradient_descent
39 | ; pose_optimizer_type = line_search
40 |
41 |
42 | ## [cost_function_type] : euclidean_distance | euclidean_distance
43 | ### euclidean_distance ... Euclidean distance as an error distance
44 | ### perpendicular_distance ... Perpendicular distance as an error distance
45 | ; cost_function_type = euclidean_distance
46 | cost_function_type = perpendicular_distance
47 |
48 |
49 | ## [is_scan_preprocess] : 0 | 1
50 | ### 0 ... false
51 | ### 1 ... true
52 | ; is_scan_preprocess = 0
53 | is_scan_preprocess = 1
54 |
55 |
56 | ## [is_odometry_fusion] : 0 | 1
57 | ### 0 ... false
58 | ### 1 ... true
59 | ; is_odometry_fusion = 0
60 | is_odometry_fusion = 1
61 |
62 |
63 | ## [is_loop_closure] : 0 | 1
64 | ### 0 ... false
65 | ### 1 ... true
66 | ; is_loop_closure = 0
67 | is_loop_closure = 1
68 |
69 | ### NOTE: If is_loop_closure == 1, then some types are set as shown below.
70 | ### NOTE: point_cloud_map_type == sub_map
71 | ### NOTE: data_associator_type == grid_table
72 | ### NOTE: cost_function_type == perpendicular_distance
--------------------------------------------------------------------------------
/sample_code_cpp/images/dependency_graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hotsuyuki/Graph-Based-SLAM/bd5d659095d15de2812078f7853c00425aefa7a8/sample_code_cpp/images/dependency_graph.png
--------------------------------------------------------------------------------
/sample_code_cpp/images/odom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hotsuyuki/Graph-Based-SLAM/bd5d659095d15de2812078f7853c00425aefa7a8/sample_code_cpp/images/odom.png
--------------------------------------------------------------------------------
/sample_code_cpp/images/slam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hotsuyuki/Graph-Based-SLAM/bd5d659095d15de2812078f7853c00425aefa7a8/sample_code_cpp/images/slam.png
--------------------------------------------------------------------------------
/sample_code_cpp/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.12)
2 |
3 | project(sample_slam
4 | VERSION 1.0.0
5 | DESCRIPTION "Sample SLAM: Scan matching as a front-end, Graph based SLAM as a back-end"
6 | LANGUAGES CXX
7 | )
8 |
9 | add_subdirectory(${CMAKE_SOURCE_DIR}/launcher/)
10 | add_subdirectory(${CMAKE_SOURCE_DIR}/slam/)
11 | add_subdirectory(${CMAKE_SOURCE_DIR}/utility/)
12 |
13 | enable_testing()
14 | # add_subdirectory(${CMAKE_SOURCE_DIR}/test/launcher/)
15 | # add_subdirectory(${CMAKE_SOURCE_DIR}/test/slam/)
16 | add_subdirectory(${CMAKE_SOURCE_DIR}/test/utility/)
17 |
18 | add_executable(main ${CMAKE_SOURCE_DIR}/main.cpp)
19 | target_compile_features(main PRIVATE cxx_std_11)
20 |
21 | target_include_directories(main PRIVATE
22 | ${CMAKE_SOURCE_DIR}/cxxopts/
23 | )
24 |
25 | target_link_libraries(main
26 | launcher
27 | )
--------------------------------------------------------------------------------
/sample_code_cpp/src/launcher/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.12)
2 |
3 | project(launcher_lib
4 | VERSION 1.0.0
5 | DESCRIPTION "Launcher library"
6 | LANGUAGES CXX
7 | )
8 |
9 | add_library(launcher STATIC
10 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/FrameworkFactory.cpp
11 | ################
12 | ${PROJECT_SOURCE_DIR}/MapDrawer/MapDrawer.cpp
13 | ${PROJECT_SOURCE_DIR}/SensorDataReader/SensorDataReader.cpp
14 | ${PROJECT_SOURCE_DIR}/SlamLauncher/SlamLauncher.cpp
15 | )
16 | target_compile_features(launcher PRIVATE cxx_std_11)
17 |
18 | target_include_directories(launcher PUBLIC
19 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/
20 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/CostFunctionFactory/
21 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/DataAssociatorFactory/
22 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/PointCloudMapFactory/
23 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/PoseEstimatorFactory/
24 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/PoseOptimizerFactory/
25 | ${PROJECT_SOURCE_DIR}/FrameworkFactory/ReferenceScanMakerFactory/
26 | ################
27 | ${PROJECT_SOURCE_DIR}/MapDrawer/
28 | ${PROJECT_SOURCE_DIR}/SensorDataReader/
29 | ${PROJECT_SOURCE_DIR}/SlamLauncher/
30 | )
31 |
32 | target_link_libraries(launcher
33 | slam
34 | utility
35 | )
--------------------------------------------------------------------------------
/sample_code_cpp/src/launcher/FrameworkFactory/CostFunctionFactory/CostFunctionFactory.h:
--------------------------------------------------------------------------------
1 | #ifndef LAUNCHER_COSTFUNCTIONFACTORY_H_
2 | #define LAUNCHER_COSTFUNCTIONFACTORY_H_
3 |
4 |
5 | #include
6 | #include