ROS2利用cartographer算法进行激光建图
环境:
Ubuntu22.04
ROS2 humble
激光雷达:轮趣的镭神N10
1.安装cartographer
sudo apt install ros-humble-cartographer
sudo apt install ros-humble-cartographer-ros
有的人安装第一个命令就可以全部下载,有的需要运行第二行命令!
2.检测是否安装完成
ros2 pkg list | grep cartographer
返回以下信息说明安装好了
cartographer_ros
cartographer_ros_msgs
3.配置cartographer的launch文件
ros2humble cartographer会下载到电脑的路径为/opt/ros/humble/share/cartographer_ros/configuration_files/
学习理解cartographer的.lua和.launch.py文件的配置
以backpack2d.lua为例(文件在configuration_files这个文件夹),基于官方的backpack2d.lua改成自己需要的配置文件,我的激光雷达的frame_ID是laser
(1).lua
backpack2d.lua
include "map_builder.lua"
include "trajectory_builder.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER,
map_frame = "map", //构建地图所使用的坐标系,一般就使用我们前面提到的map即可
tracking_frame = "base_link", //这里改为雷达的frame_ID 作者的雷达是laser,改为laser即可
published_frame = "base_link",
odom_frame = "odom",
provide_odom_frame = false,
publish_frame_projected_to_2d = false,
use_pose_extrapolator = false,
use_odometry = false,
use_nav_sat = false,
use_landmarks = false,
num_laser_scans = 1, //订阅的雷达数量
num_multi_echo_laser_scans = 0,
num_subdivisions_per_laser_scan = 1,
num_point_clouds = 0,
lookup_transform_timeout_sec = 0.2,
submap_publish_period_sec = 0.3,
pose_publish_period_sec = 5e-3,
trajectory_publish_period_sec = 30e-3,
rangefinder_sampling_ratio = 1.,
odometry_sampling_ratio = 1.,
fixed_frame_pose_sampling_ratio = 1.,
imu_sampling_ratio = 1.,
landmarks_sampling_ratio = 1.,
}
MAP_BUILDER.use_trajectory_builder_2d = true
TRAJECTORY_BUILDER_2D.submaps.num_range_data = 35
TRAJECTORY_BUILDER_2D.min_range = 0.
TRAJECTORY_BUILDER_2D.max_range = 200.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 5.
TRAJECTORY_BUILDER_2D.use_imu_data = false
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.1
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.translation_delta_cost_weight = 10.
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.rotation_delta_cost_weight = 1e-1
POSE_GRAPH.optimization_problem.huber_scale = 1e2
POSE_GRAPH.optimize_every_n_nodes = 35
POSE_GRAPH.constraint_builder.min_score = 0.65
return options
注意的是将该文件更改过后可能会出现权限无法保存的问题,我们可以sudo chmod 777 (该文件夹的路径),然后就可以另存为一个新文件,注意新文件名字在launch.py文件中会映射到此处,作者此处文件名字改为了mylaser.lua 其他参数意思自行查资料,上述代码博主经过实验只需要改tracking_frame为雷达即可。
(2).launch.py文件
在launch文件夹中
同理我们以backpack_2d.launch.py这个文件为例
backpack_2d.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.conditions import IfCondition, UnlessCondition
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node, SetRemap
from launch_ros.substitutions import FindPackageShare
from launch.launch_description_sources import PythonLaunchDescriptionSource
import os
def generate_launch_description():
## ***** Launch arguments *****
# 是否使用仿真时间,真实的机器人我们不需要,设置为False
use_sim_time_arg = DeclareLaunchArgument('use_sim_time', default_value = 'False')
## ***** File paths ******
# 找到cartographer功能包的地址
pkg_share = FindPackageShare('cartographer_ros').find('cartographer_ros')
## ***** Nodes *****
#=====================声明三个节点,cartographer/occupancy_grid_node/rviz_node=================================
cartographer_node = Node(
package = 'cartographer_ros',
executable = 'cartographer_node',
parameters = [{'use_sim_time': LaunchConfiguration('use_sim_time')}],
arguments = [
'-configuration_directory', FindPackageShare('cartographer_ros').find('cartographer_ros') + '/configuration_files',
'-configuration_basename', 'backpack_2d.lua'], //注意这里有一个.lua文件的映射,改为自己配置的.lua文件,我这里是mylase.lua
remappings = [
('echoes', 'horizontal_laser_2d')],
output = 'screen'
)
# 可视化节点
rviz_node = Node(
package='rviz2',
namespace='rviz2',
executable='rviz2',
name='rviz2',
output='screen')
cartographer_occupancy_grid_node = Node(
package = 'cartographer_ros',
executable = 'cartographer_occupancy_grid_node',
parameters = [
{'use_sim_time': True},
{'resolution': 0.05}],
)
return LaunchDescription([
use_sim_time_arg,
# Nodes
rviz_node ,
cartographer_node,
cartographer_occupancy_grid_node,
])
同理,这里会出现一个权限的问题,自行解决
附上博主自己配置的建图文件
mylaser.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.conditions import IfCondition, UnlessCondition
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node, SetRemap
from launch_ros.substitutions import FindPackageShare
from launch.launch_description_sources import PythonLaunchDescriptionSource
import os
def generate_launch_description():
## ***** Launch arguments *****
use_sim_time_arg = DeclareLaunchArgument('use_sim_time', default_value = 'False')
## ***** File paths ******
pkg_share = FindPackageShare('cartographer_ros').find('cartographer_ros')
# urdf_dir = os.path.join(pkg_share, 'urdf')
# urdf_file = os.path.join(urdf_dir, 'backpack_2d.urdf')
# with open(urdf_file, 'r') as infp:
# robot_desc = infp.read()
## ***** Nodes *****
# robot_state_publisher_node = Node(
# package = 'robot_state_publisher',
# executable = 'robot_state_publisher',
# parameters=[
# {'robot_description': robot_desc},
# {'use_sim_time': LaunchConfiguration('use_sim_time')}],
# output = 'screen'
# )
cartographer_node = Node(
package = 'cartographer_ros',
executable = 'cartographer_node',
arguments = [
'-configuration_directory', FindPackageShare('cartographer_ros').find('cartographer_ros') + '/configuration_files',
'-configuration_basename', 'mylaser.lua'],
remappings = [
('scan', 'scan')],
output = 'screen'
)
cartographer_occupancy_grid_node = Node(
package = 'cartographer_ros',
executable = 'cartographer_occupancy_grid_node',
parameters = [
{'use_sim_time': False},
{'resolution': 0.05}],
)
rviz_node = Node(
package='rviz2',
namespace='rviz2',
executable='rviz2',
name='rviz2',
output='screen')
return LaunchDescription([
use_sim_time_arg,
# Nodes
# robot_state_publisher_node,
rviz_node,
cartographer_node,
cartographer_occupancy_grid_node,
])
4.启动雷达驱动和自己配置的launch文件就可以开始建图了
ros2 launch lsidar_driver lsn_10.launch.py
ros2 launch cartographer_ros mylaser.launch.py

如果运行自己配置的文件后没有出现地图信息说明配置文件细节有问题,可根据报错的信息去排查
以博主自己的错误为例

这里的Error是因为我的.lua文件为没有与launch文件中的映射名字一致才会报错,如果你也遇到这样的问题请仔细看第三点的(1)和(2)
5.地图保存
ros2 run nva_map_server map_saver_cli -f map
注意:在调用map_saver节点之前不要关闭建图算法的节点不然后丢失地图,以上代码为博主手敲,如果出现错误请自行table补全