Home » ROS2与SLAM入门教程 » ROS2与SLAM入门教程-整合cartographer建图

ROS2与SLAM入门教程-整合cartographer建图

ROS2与SLAM入门教程-整合cartographer建图

说明:

  • 介绍如何在ros2下使用cartographer

步骤:

apt安装(推荐)

  • 安装命令
sudo apt install cartographer
sudo apt install cartographer-ros

源码安装

  • foxy可以使用dashing的代码
  • 安装依赖
# wstool related
sudo apt-get install -y python-wstool python-rosdep ninja-build stow
 
# ceres related
sudo apt-get install cmake
sudo apt-get install libgoogle-glog-dev libgflags-dev
sudo apt-get install libatlas-base-dev
sudo apt-get install libeigen3-dev
sudo apt-get install libsuitesparse-dev
 
# cartographer related
sudo apt install lua5.2 liblua5.2-dev libluabind-dev
sudo apt install libprotobuf-dev protobuf-compiler
sudo apt install libcairo2-dev
  • 编译源码
# clone ros2 source
mkdir -p ~/cartographer_ws2/src
cd ~/cartographer_ws2/src
git clone -b dashing --single-branch https://github.com/ros2/cartographer_ros.git
cd ~/cartographer_ws2
wstool init src
wstool merge -t src src/cartographer_ros/cartographer_ros.rosinstall
wstool update -t src
colcon build
  • 新建luanch文件occupancy_grid.launch.py,参考turtlebot3
  • 位置/home/${YOUR_NAME}/${YOUR_WORKSPACE}/src/cartographer_ros/cartographer_ros/launch
  • 内容如下
# occupancy_grid.launch.py
 
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
 
 
def generate_launch_description():
    use_sim_time = LaunchConfiguration('use_sim_time', default='false')
    resolution = LaunchConfiguration('resolution', default='0.05')
    publish_period_sec = LaunchConfiguration('publish_period_sec', default='1.0')
 
    return LaunchDescription([
        DeclareLaunchArgument(
            'resolution',
            default_value=resolution,
            description='Resolution of a grid cell in the published occupancy grid'),
 
        DeclareLaunchArgument(
            'publish_period_sec',
            default_value=publish_period_sec,
            description='OccupancyGrid publishing period'),
 
        DeclareLaunchArgument(
            'use_sim_time',
            default_value='false',
            description='Use simulation (Gazebo) clock if true'),
 
        Node(
            package='cartographer_ros',
            node_executable='occupancy_grid_node',
            node_name='occupancy_grid_node',
            output='screen',
            parameters=[{'use_sim_time': use_sim_time}],
            arguments=['-resolution', resolution, '-publish_period_sec', publish_period_sec]),
    ])
  • 新建 cartographer.launch.py文件,参考turtlebot3文件
  • 位置/home/${YOUR_NAME}/${YOUR_WORKSPACE}/src/cartographer_ros/cartographer_ros/launch
  • 内容如下
# cartographer.launch.py
 
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import ThisLaunchFileDir
 
 
def generate_launch_description():
    use_sim_time = LaunchConfiguration('use_sim_time', default='true')
    cartographer_prefix = get_package_share_directory('cartographer_ros')
    cartographer_config_dir = LaunchConfiguration('cartographer_config_dir', default=os.path.join(
                                                  cartographer_prefix, 'configuration_files'))
    configuration_basename = LaunchConfiguration('configuration_basename',
                                                 default='turtlebot3_lds_2d.lua')
 
    resolution = LaunchConfiguration('resolution', default='0.05')
    publish_period_sec = LaunchConfiguration('publish_period_sec', default='1.0')
 
    return LaunchDescription([
        DeclareLaunchArgument(
            'cartographer_config_dir',
            default_value=cartographer_config_dir,
            description='Full path to config file to load'),
        DeclareLaunchArgument(
            'configuration_basename',
            default_value=configuration_basename,
            description='Name of lua file for cartographer'),
        DeclareLaunchArgument(
            'use_sim_time',
            default_value='false',
            description='Use simulation (Gazebo) clock if true'),
 
        Node(
            package='cartographer_ros',
            node_executable='cartographer_node',
            node_name='cartographer_node',
            output='screen',
            parameters=[{'use_sim_time': use_sim_time}],
            arguments=['-configuration_directory', cartographer_config_dir,
                       '-configuration_basename', configuration_basename]),
 
        DeclareLaunchArgument(
            'resolution',
            default_value=resolution,
            description='Resolution of a grid cell in the published occupancy grid'),
 
        DeclareLaunchArgument(
            'publish_period_sec',
            default_value=publish_period_sec,
            description='OccupancyGrid publishing period'),
 
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource([ThisLaunchFileDir(), '/occupancy_grid.launch.py']),
            launch_arguments={'use_sim_time': use_sim_time, 'resolution': resolution,
                              'publish_period_sec': publish_period_sec}.items(),
        ),
 
        Node(
            package='rviz2',
            node_executable='rviz2',
            node_name='rviz2',
            parameters=[{'use_sim_time': use_sim_time}],
            output='screen'),
    ])
  • 新建turtlebot3_lds_2d.lua,参考turtlebot3文件
  • 位置/home/${YOUR_NAME}/${YOUR_WORKSPACE}/src/cartographer_ros/configuration_files
    -内容如下
include "map_builder.lua"
include "trajectory_builder.lua"

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "imu_link",
  published_frame = "odom",
  odom_frame = "odom",
  provide_odom_frame = false,
  publish_frame_projected_to_2d = true,
  use_odometry = true,
  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.min_range = 0.12
TRAJECTORY_BUILDER_2D.max_range = 3.5
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 3.
TRAJECTORY_BUILDER_2D.use_imu_data = false
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true 
TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians = math.rad(0.1)

POSE_GRAPH.constraint_builder.min_score = 0.65
POSE_GRAPH.constraint_builder.global_localization_min_score = 0.7

-- POSE_GRAPH.optimize_every_n_nodes = 0

return options
  • 上面配置使用lds雷达,测距为max_range
  • 上面配置不使用imu
  • 更多配置可以参考cartographer官方文档
  • 增加了文件和配置需要重新编译一次源码
cd ~/cartographer_ws2
colcon build

测试

  • 启动自己的底盘,获取odom数据
  • 启动自己的雷达,获取scan数据
  • 启动自己的imu,获取imu数据
  • 启动建图
ros2 launch cartographer_ros cartographer.launch.py

保存地图1

  • 执行命令
# to build a map and save,
ros2 service call /finish_trajectory cartographer_ros_msgs/srv/FinishTrajectory "{trajectory_id: '0'}"
ros2 service call /write_state cartographer_ros_msgs/srv/WriteState "{filename: '~/cartorapher.pbstream'}"

保存地图2

  • 执行命令
ros2 run nav2_map_server map_saver_cli -f ~/cartorapher --ros-args -p save_map_timeout:=10000

纠错,疑问,交流: 请进入讨论区点击加入Q群

获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号


标签: ros2与slam入门教程