├── .DS_Store
├── example.png
├── src
├── .DS_Store
├── path_planner_node_main.cc
├── common.h
├── common.cc
├── kd_tree.h
├── CMakeLists.txt
├── path_planner_node.h
├── kd_tree.cc
└── path_planner_node.cc
├── srv
├── RoadmapQuery.srv
├── PathPlan.srv
├── ReconnectSubmaps.srv
├── ConnectionQuery.srv
└── CMakeLists.txt
├── launch
├── .DS_Store
└── path_planner.launch
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xumzsy/cartographer_ros_path_planner/HEAD/.DS_Store
--------------------------------------------------------------------------------
/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xumzsy/cartographer_ros_path_planner/HEAD/example.png
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xumzsy/cartographer_ros_path_planner/HEAD/src/.DS_Store
--------------------------------------------------------------------------------
/srv/RoadmapQuery.srv:
--------------------------------------------------------------------------------
1 | int32 trajectory_id
2 | int32 submap_index
3 | ---
4 | int32[] connections
5 |
--------------------------------------------------------------------------------
/launch/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xumzsy/cartographer_ros_path_planner/HEAD/launch/.DS_Store
--------------------------------------------------------------------------------
/srv/PathPlan.srv:
--------------------------------------------------------------------------------
1 | geometry_msgs/Point start_point
2 | geometry_msgs/Point end_point
3 | ---
4 | geometry_msgs/Point[] path
--------------------------------------------------------------------------------
/srv/ReconnectSubmaps.srv:
--------------------------------------------------------------------------------
1 | int32 start_trajectory_id
2 | int32 start_submap_index
3 | int32 end_trajectory_id
4 | int32 end_submap_index
5 | ---
6 |
--------------------------------------------------------------------------------
/srv/ConnectionQuery.srv:
--------------------------------------------------------------------------------
1 | int32 start_trajectory_id
2 | int32 start_submap_index
3 | int32 end_trajectory_id
4 | int32 end_submap_index
5 | ---
6 | geometry_msgs/Point[] path
7 |
--------------------------------------------------------------------------------
/src/path_planner_node_main.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Author: Mengze Xu
3 | */
4 |
5 | #include "ros/ros.h"
6 | #include "path_planner_node.h"
7 |
8 | int main(int argc, char** argv){
9 | ::ros::init(argc, argv, "cartographer_navigation_node");
10 | ::ros::start();
11 | cartographer_ros::cartographer_ros_path_planner::PathPlannerNode node;
12 | ::ros::spin();
13 | ::ros::shutdown();
14 | return 0;
15 | }
16 |
--------------------------------------------------------------------------------
/src/common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Author: Mengze Xu
3 | * Define some common basic functions
4 | */
5 |
6 |
7 | #ifndef common_h
8 | #define common_h
9 |
10 | #include "geometry_msgs/Point.h"
11 | #include "geometry_msgs/Pose.h"
12 |
13 | namespace cartographer_ros {
14 | namespace cartographer_ros_path_planner{
15 |
16 | // Return distance2 in XY plane
17 | double Distance2BetweenPoint(const geometry_msgs::Point& point1, const geometry_msgs::Point& point2);
18 |
19 | double Distance2BetweenPose(const geometry_msgs::Pose& pose1, const geometry_msgs::Pose& pose2);
20 |
21 | } // namespace cartographer_ros_path_planner
22 | } // namespace cartographer_ros
23 |
24 | #endif /* common_h */
25 |
--------------------------------------------------------------------------------
/launch/path_planner.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/common.cc:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | *
5 | */
6 |
7 |
8 | #include "common.h"
9 |
10 | namespace cartographer_ros {
11 | namespace cartographer_ros_path_planner{
12 |
13 | // Return distance2 in XY plane
14 | double Distance2BetweenPoint(const geometry_msgs::Point& point1, const geometry_msgs::Point& point2){
15 | return (point1.x-point2.x)*(point1.x-point2.x) + (point1.y-point2.y)*(point1.y-point2.y);
16 | }
17 |
18 | double Distance2BetweenPose(const geometry_msgs::Pose& pose1, const geometry_msgs::Pose& pose2){
19 | return (pose1.position.x-pose2.position.x)*(pose1.position.x-pose2.position.x)+
20 | (pose1.position.y-pose2.position.y)*(pose1.position.y-pose2.position.y)
21 | +(pose1.position.z-pose2.position.z)*(pose1.position.z-pose2.position.z);
22 | }
23 |
24 | } // namespace cartographer_ros_path_planner
25 | } // namespace cartographer_ros
26 |
--------------------------------------------------------------------------------
/srv/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2016 The Cartographer Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | cmake_minimum_required(VERSION 2.8.3)
16 |
17 | project(cartographer_ros_msgs)
18 |
19 | set(PACKAGE_DEPENDENCIES
20 | geometry_msgs
21 | )
22 |
23 | find_package(catkin REQUIRED COMPONENTS message_generation ${PACKAGE_DEPENDENCIES})
24 |
25 | add_message_files(
26 | FILES
27 | StatusCode.msg
28 | StatusResponse.msg
29 | SubmapList.msg
30 | SubmapEntry.msg
31 | SubmapTexture.msg
32 | SensorTopics.msg
33 | TrajectoryOptions.msg
34 | )
35 |
36 | add_service_files(
37 | FILES
38 | SubmapQuery.srv
39 | FinishTrajectory.srv
40 | StartTrajectory.srv
41 | WriteState.srv
42 | ConnectionQuery.srv
43 | PathPlan.srv
44 | ReconnectSubmaps.srv
45 | RoadmapQuery.srv
46 | )
47 |
48 | generate_messages(
49 | DEPENDENCIES
50 | geometry_msgs
51 | )
52 |
53 | catkin_package(
54 | CATKIN_DEPENDS
55 | ${PACKAGE_DEPENDENCIES}
56 | )
57 |
--------------------------------------------------------------------------------
/src/kd_tree.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Author: Mengze Xu
3 | * Implement 2d kd tree for quick near neighbor search in RRT and submaps.
4 | *
5 | * TODO: Add rebalance method and make the clss more unisersal
6 | */
7 |
8 | #ifndef kd_tree_h
9 | #define kd_tree_h
10 |
11 | #include
12 | #include "geometry_msgs/Point.h"
13 |
14 | namespace cartographer_ros {
15 | namespace cartographer_ros_path_planner{
16 |
17 | struct KdTreeNode{
18 | geometry_msgs::Point point;
19 | KdTreeNode* parent_node; // Used for plan planning
20 | double distance; // Used for plan planning
21 | KdTreeNode* left_node; // Used for kd tree
22 | KdTreeNode* right_node; // used for kd tree
23 | int trajectory_id; // used for submaps
24 | int submap_index; // used for submaps
25 |
26 | KdTreeNode();
27 | KdTreeNode(geometry_msgs::Point p);
28 | KdTreeNode(geometry_msgs::Point p, int trajectory_idx, int submap_idx);
29 | };
30 |
31 |
32 | class KdTree{
33 | public:
34 | // Return nearest node to target point
35 | KdTreeNode* NearestKdTreeNode(const geometry_msgs::Point& target) const;
36 |
37 | // Return near nodes around target within radius
38 | std::vector NearKdTreeNode(const geometry_msgs::Point& target,
39 | double radius) const;
40 |
41 | // Add a new point into RRT tree
42 | KdTreeNode* AddPointToKdTree(geometry_msgs::Point point);
43 | KdTreeNode* AddPointToKdTree(geometry_msgs::Point point, KdTreeNode* parent, int depth);
44 | KdTreeNode* AddPointToKdTree(geometry_msgs::Point point, int trajectory_idx, int submap_idx);
45 |
46 | // Constructor
47 | KdTree();
48 | KdTree(geometry_msgs::Point start_point);
49 | ~KdTree(){DestroyRRT(root_);}
50 |
51 | // For test
52 | KdTreeNode* BruceNearestKdTreeNode(const geometry_msgs::Point& point);
53 | std::vector BruceNearKdTreeNode(const geometry_msgs::Point& target, double radius);
54 |
55 | private:
56 |
57 | // Help function to go through kd tree
58 | void SearchKdTreeNode(const geometry_msgs::Point& target,
59 | KdTreeNode* current_node,
60 | KdTreeNode*& current_nearest_node,
61 | double& current_cloest_distance2,
62 | int depth) const;
63 | void SearchKdTreeNode(const geometry_msgs::Point& target,
64 | KdTreeNode* current_node,
65 | std::vector& near_nodes,
66 | double radius,
67 | int depth) const;
68 | // Destroy RRT
69 | void DestroyRRT(KdTreeNode* root);
70 |
71 | KdTreeNode* const root_;
72 | };
73 |
74 | } // namespace cartographer_ros_path_planner
75 | } // namespace cartographer_ros
76 |
77 | #endif /* kd_tree_h */
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cartographer ROS Path Planner
2 | This package provides online 2D path planning based on cartographer submaps and does not rely on the global occupied grid. Main idea is to build up a global road map for submaps and use RRT* as local planner.
3 |
4 | 
5 | ## Getting Started
6 | ### Prerequisites
7 | The package runs on Ubuntu 16.04 and ROS Kinetic.
8 | ### Installing
9 | * Follow [cartographer_ros](https://github.com/googlecartographer/cartographer_ros) to download cartographer, cacartographer_ros and 2d demo.
10 | * Move files in "src" to cartographer_ros/cartographer_ros/cartographer_ros
11 | * Move files in "srv" to cartographer_ros/cartographer_ros_msgs/srv
12 | * Move files in "launch" to cartographer_ros/cartographer_ros/launch
13 | * Substitute cartographer_ros/cartographer_ros_msgs/CmakeLists.txt with the cmake file in srv
14 | * Remake cartographer_ros
15 |
16 | ### Running the tests
17 | * After launching 2d demo, open another terminal and launch the planner
18 | ```
19 | roslaunch cartographer_ros cartographer_path_planner.launch
20 | ```
21 | * Use the "clicked point" to play with it. The planner will plan a path between map origin to clicked point.
22 | * In a few case, the path may go through the wall. This is mainly due to incorrect submaps created by cartographer.
23 |
24 | ## Methods
25 | ### Submap Road Map
26 | Kd tree is used to store each submap's origin. For each submap, I try to connect it to nearby submaps in map, last submap and the next submap in time series. RRT* is used to do local planning and the result path is stored in a map with submap id as key.
27 |
28 | ### Global Path Plan
29 | I decompose the global path plan into three parts: locally plan paths to connect start point and end point to nearest submaps. Use BFS to find the shortest path between these two submaps in road map. Finally combine the three paths.
30 |
31 | ## Parameters
32 | ### Hard Coded Parameters (const)
33 | * kFinishVersion = 180. This is given by cartographer.
34 | * kOccupyThreshold = 64. 0 is definitely free and 100 is definitely occupied.
35 | * kOccupyGridResolution = 0.05 [m] Decided by cartographer configuration but hard coded here.
36 | * kCloseSubmapRadius = 5.0 [m] Radius to find nearby submaps to given point
37 | ### ROS parameters in launch file
38 | * max_rrt_node_num. Max num of node RRT will contain.
39 | * step_to_check_reach_endpoint. Decide how often try to connect end point to RRT
40 | * distance_threshold_for_adding. Distance threshold to decide whether try to connect two submaps
41 | * distance_threshold_for_updating. If the position of the submap changes over this threshold, it will recalculate its road map
42 | * rotation_threshold_for_updating. If the oretation (q.z) of the submap changes over this threshold, it will recalculate its road map
43 | * probability_of_choose_endpoint. Probability to choose end point instead of random point as new point in RRT.
44 | * rrt_grow_step and rrt_trim_radius. Parameters in RRT* algorithm.
45 |
46 | ## ROS API
47 | * "/roadmap_query": Receive the SubmapId and return corresponding submaps connections
48 | * "/connection_query": Receive two SubmapId and return the path in road map between them
49 | * "/reconnect_submaps": Receive two SubmapId, discard existing path and try to reconnect them
50 | * "/plan_path": Receive two geometry_msgs::Point and return a path connecting them
51 | ## C++ API
52 | path_planner_node.h is well documented and provides useful information
53 |
54 | ## Future Work
55 | ### Improvement
56 | * Add functions to smooth the path
57 | * Add more RRT* tricks to accelerate convergence of RRT*
58 |
59 | ### Navigation
60 | To work as navigation stack, continues real time localization and velocity controller are needed. Now cartographer supports pure localization as a new trajectory in map builder but has not provided ROS API.
61 |
62 | Velocity controller transforms trajectory of way points to smooth velocity command which can be directly sent to robot's motion controller.
63 |
64 | Since the submap are not perfect, dynamic navigation is desired. This however needs changes in cartographer and can not be implemented just in ROS.
65 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2016 The Cartographer Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | google_binary(cartographer_assets_writer
16 | SRCS
17 | assets_writer_main.cc
18 | ros_map_writing_points_processor.h
19 | ros_map_writing_points_processor.cc
20 | )
21 |
22 | install(TARGETS cartographer_assets_writer
23 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
24 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
25 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
26 | )
27 |
28 | google_binary(cartographer_node
29 | SRCS
30 | node_main.cc
31 | )
32 |
33 | install(TARGETS cartographer_node
34 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
35 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
36 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
37 | )
38 |
39 | google_binary(cartographer_offline_node
40 | SRCS
41 | offline_node_main.cc
42 | )
43 |
44 | install(TARGETS cartographer_offline_node
45 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
46 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
47 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
48 | )
49 |
50 | google_binary(cartographer_start_trajectory
51 | SRCS
52 | start_trajectory_main.cc
53 | )
54 |
55 | install(TARGETS cartographer_start_trajectory
56 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
57 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
58 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
59 | )
60 |
61 | google_binary(cartographer_occupancy_grid_node
62 | SRCS
63 | occupancy_grid_node_main.cc
64 | )
65 |
66 | install(TARGETS cartographer_occupancy_grid_node
67 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
68 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
69 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
70 | )
71 |
72 | google_binary(cartographer_path_planner_node
73 | SRCS
74 | path_planner_node_main.cc
75 | )
76 |
77 | install(TARGETS cartographer_path_planner_node
78 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
79 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
80 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
81 | )
82 |
83 |
84 | google_binary(cartographer_rosbag_validate
85 | SRCS
86 | rosbag_validate_main.cc
87 | )
88 |
89 | install(TARGETS cartographer_rosbag_validate
90 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
91 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
92 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
93 | )
94 |
95 | google_binary(cartographer_pbstream_to_ros_map
96 | SRCS
97 | pbstream_to_ros_map_main.cc
98 | )
99 |
100 | install(TARGETS cartographer_pbstream_to_ros_map
101 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
102 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
103 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
104 | )
105 |
106 | google_binary(cartographer_pbstream_map_publisher
107 | SRCS
108 | pbstream_map_publisher_main.cc
109 | )
110 |
111 | install(TARGETS cartographer_pbstream_map_publisher
112 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
113 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
114 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
115 | )
116 |
117 | # TODO(cschuet): Add support for shared library case.
118 | if (${BUILD_GRPC})
119 | google_binary(cartographer_grpc_node
120 | SRCS
121 | cartographer_grpc/node_grpc_main.cc
122 | )
123 |
124 | install(TARGETS cartographer_grpc_node
125 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
126 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
127 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
128 | )
129 |
130 | google_binary(cartographer_grpc_offline_node
131 | SRCS
132 | cartographer_grpc/offline_node_grpc_main.cc
133 | )
134 |
135 | install(TARGETS cartographer_grpc_offline_node
136 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
137 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
138 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
139 | )
140 |
141 | install(PROGRAMS
142 | ../scripts/cartographer_grpc_server.sh
143 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
144 | )
145 | endif()
146 |
--------------------------------------------------------------------------------
/src/path_planner_node.h:
--------------------------------------------------------------------------------
1 | /*
2 | */
3 |
4 | #ifndef PATH_PLANNER_NODE_H
5 | #define PATH_PLANNER_NODE_H
6 |
7 | #include