ros实验笔记之——基于cartographer的多机器人slam地图融合(代码片段)

gwpscut gwpscut     2023-01-31     691

关键词:

之前博客《 ROS仿真笔记之——多移动机器人SLAM地图融合 》已经实现了基于gmapping的多机器人地图融合。实验和仿真都验证过了。本博文通过cartographer来实现SLAM,再做map merge

先看视频效果

two

启动的文件

#! /bin/bash
gnome-terminal --tab -e 'bash -c "roscore;exec bash"'

sleep 3s
gnome-terminal --tab -e 'bash -c "expect robot1_run_kobuki.sh;exec bash"'
gnome-terminal --tab -e 'bash -c "expect robot2_run_kobuki.sh;exec bash"'

sleep 3s
gnome-terminal --tab -e 'bash -c "expect robot1_run_rplidar.sh;exec bash"'
gnome-terminal --tab -e 'bash -c "expect robot2_run_rplidar.sh;exec bash"'

sleep 3s
gnome-terminal --tab -e 'bash -c "ROS_NAMESPACE=tb2_0 roslaunch turtlebot_navigation multi_rplidar_cartographer.launch ns:=tb2_0_;exec bash"'
gnome-terminal --tab -e 'bash -c "ROS_NAMESPACE=tb2_1 roslaunch turtlebot_navigation multi_rplidar_cartographer.launch ns:=tb2_1_;exec bash"'

sleep 3s
gnome-terminal --tab -e 'bash -c "roslaunch turtlebot_bringup multi_cartographer_map_merge.launch;exec bash"'


sleep 3s
# gnome-terminal --window -e 'bash -c "ROS_NAMESPACE=tb2_0 roslaunch turtlebot_teleop keyboard_teleop.launch;exec bash"'
# gnome-terminal  --window -e 'bash -c "ROS_NAMESPACE=tb2_1 roslaunch turtlebot_teleop keyboard_teleop.launch;exec bash"'

multi_rplidar_cartographer.launch

<!--
  Copyright 2016 The Cartographer Authors

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<launch>
  <param name="/use_sim_time" value="false" />
  <!-- 必须改为false(实验时) -->

  <arg name="ns" default=""/>

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename $(arg ns)multi_slam.lua"
      output="screen">
    <remap from="scan" to="scan" />
  </node>

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05" />


 <!-- <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/multi_robot_mapmerge.rviz" /> -->

</launch>

multi_cartographer_map_merge.launch

<launch>
  <arg name="first_tb2"  default="tb2_0"/>
  <arg name="second_tb2" default="tb2_1"/>

  <arg name="first_tb2_x_pos" default="0.0"/>
  <arg name="first_tb2_y_pos" default="0.5"/>
  <arg name="first_tb2_z_pos" default=" 0.0"/>
  <arg name="first_tb2_yaw"   default=" 0.0"/>

  <arg name="second_tb2_x_pos" default="0.0"/>
  <arg name="second_tb2_y_pos" default="-0.5"/>
  <arg name="second_tb2_z_pos" default=" 0.0"/>
  <arg name="second_tb2_yaw"   default=" 0.0"/>


  <group ns="$(arg first_tb2)/map_merge">
    <param name="init_pose_x"   value="$(arg first_tb2_x_pos)"/>
    <param name="init_pose_y"   value="$(arg first_tb2_y_pos)"/>
    <param name="init_pose_z"   value="$(arg first_tb2_z_pos)"/>
    <param name="init_pose_yaw" value="$(arg first_tb2_yaw)"  />
  </group>

  <group ns="$(arg second_tb2)/map_merge">
    <param name="init_pose_x"   value="$(arg second_tb2_x_pos)"/>
    <param name="init_pose_y"   value="$(arg second_tb2_y_pos)"/>
    <param name="init_pose_z"   value="$(arg second_tb2_z_pos)"/>
    <param name="init_pose_yaw" value="$(arg second_tb2_yaw)"  />
</group>


  <node pkg="multirobot_map_merge" type="map_merge" respawn="false" name="map_merge" output="screen">
    <param name="robot_map_topic" value="map"/>
    <param name="robot_namespace" value="tb2"/>
    <param name="merged_map_topic" value="map"/>
    <param name="world_frame" value="map"/>
    <param name="known_init_poses" value="true"/>
    <param name="merging_rate" value="0.5"/>
    <param name="discovery_rate" value="0.05"/>
    <param name="estimation_rate" value="0.1"/>
    <param name="estimation_confidence" value="1.0"/>
  </node>

  <node pkg="tf" type="static_transform_publisher" name="world_to_$(arg first_tb2)_tf_broadcaster"  args="0 0 0 0 0 0 /map /$(arg first_tb2)/map 100"/>
  <node pkg="tf" type="static_transform_publisher" name="world_to_$(arg second_tb2)_tf_broadcaster" args="0 0 0 0 0 0 /map /$(arg second_tb2)/map 100"/>
  <!-- <node pkg="tf" type="static_transform_publisher" name="world_to_$(arg third_tb2)_tf_broadcaster" args="0 0 0 0 0 0 /map /$(arg second_tb2)/map 100"/> -->


 <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/multi_robot_mapmerge.rviz" />



</launch>


<!-- http://wiki.ros.org/multirobot_map_merge -->

(arg ns)multi_slam.lua

-- Copyright 2016 The Cartographer Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

include "map_builder.lua"
include "trajectory_builder.lua"

options = 
  map_builder = MAP_BUILDER,                -- map_builder.lua的配置信息
  trajectory_builder = TRAJECTORY_BUILDER,  -- trajectory_builder.lua的配置信息
  
  map_frame = "tb2_0/map",                        -- 地图坐标系的名字
  tracking_frame = "tb2_0/laser",              -- 将所有传感器数据转换到这个坐标系下
  published_frame = "tb2_0/laser",            -- tf: map -> footprint
  odom_frame = "tb2_0/odom",                      -- 里程计的坐标系名字
  provide_odom_frame = true,               -- 是否提供odom的tf, 如果为true,则tf树为map->odom->footprint
                                            -- 如果为false tf树为map->footprint
  publish_frame_projected_to_2d = false,    -- 是否将坐标系投影到平面上
  use_pose_extrapolator = true,            -- 发布tf时是使用pose_extrapolator的位姿还是前端计算出来的位姿

  use_odometry = false,                     -- 是否使用里程计,如果使用要求一定要有odom的tf
  use_nav_sat = false,                      -- 是否使用gps
  use_landmarks = false,                    -- 是否使用landmark
  num_laser_scans = 1,                      -- 是否使用单线激光数据
  num_multi_echo_laser_scans = 0,           -- 是否使用multi_echo_laser_scans数据
  num_subdivisions_per_laser_scan = 1,      -- 1帧数据被分成几次处理,一般为1
  num_point_clouds = 0,                     -- 是否使用点云数据
  
  lookup_transform_timeout_sec = 0.2,       -- 查找tf时的超时时间
  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.3
TRAJECTORY_BUILDER_2D.max_range = 8.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1.
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

-- MAP_BUILDER.use_trajectory_builder_2d = true

-- TRAJECTORY_BUILDER_2D.use_imu_data = true
-- TRAJECTORY_BUILDER_2D.min_range = 0.3
-- TRAJECTORY_BUILDER_2D.max_range = 100.
-- TRAJECTORY_BUILDER_2D.min_z = 0.2
-- --TRAJECTORY_BUILDER_2D.max_z = 1.4
-- --TRAJECTORY_BUILDER_2D.voxel_filter_size = 0.02

-- --TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_length = 0.5
-- --TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.min_num_points = 200.
-- --TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_range = 50.

-- --TRAJECTORY_BUILDER_2D.loop_closure_adaptive_voxel_filter.max_length = 0.9
-- --TRAJECTORY_BUILDER_2D.loop_closure_adaptive_voxel_filter.min_num_points = 100
-- --TRAJECTORY_BUILDER_2D.loop_closure_adaptive_voxel_filter.max_range = 50.

-- TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = false
-- TRAJECTORY_BUILDER_2D.ceres_scan_matcher.occupied_space_weight = 1.
-- TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight = 1.
-- TRAJECTORY_BUILDER_2D.ceres_scan_matcher.rotation_weight = 1.
-- --TRAJECTORY_BUILDER_2D.ceres_scan_matcher.ceres_solver_options.max_num_iterations = 12

-- --TRAJECTORY_BUILDER_2D.motion_filter.max_distance_meters = 0.1
-- --TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians = 0.004
-- --TRAJECTORY_BUILDER_2D.imu_gravity_time_constant = 1.

-- TRAJECTORY_BUILDER_2D.submaps.num_range_data = 80.
-- TRAJECTORY_BUILDER_2D.submaps.grid_options_2d.resolution = 0.1

-- POSE_GRAPH.optimize_every_n_nodes = 160.
-- POSE_GRAPH.constraint_builder.sampling_ratio = 0.3
-- POSE_GRAPH.constraint_builder.max_constraint_distance = 15.
-- POSE_GRAPH.constraint_builder.min_score = 0.48
-- POSE_GRAPH.constraint_builder.global_localization_min_score = 0.60

return options

总结

map merge这个包是基于特征点来做地图融合的。通过视频可以看到,一开始匹配的点可能不是很好,这样导致融合的地图很乱。但是慢慢的,随着机器人走动的路径越来越多(而cartographer的回环也让地图越来越好)最终融合的效果还是不错的。

初始的位置影响其实不是很大~~~

ros学习笔记之——3dmapmerge(代码片段)

之前博客《ROS实验笔记之——基于cartographer的多机器人SLAM地图融合》已经实现了2Dmapmerge,也做了大量这方面的demotwo基于两个turtlebot2的多机器人SLAM地图融合本博文看看3dmapmerge方面的资料首先呢有CCM-SLAM(https://github.com/VI... 查看详情

ros实验笔记之——基于prometheus的无人机运动规划(代码片段)

...学习无人机的运动规划。关于该项目的配置可以参考《ROS实验笔记之——基于Prometheus自主无人机开源项目的学习与仿真》Demo演示基于2D-LiDAR的APF路径规划基于rgbdcamera的APF路径规划基于3D-LiDAR的Astar路径规划ego-planner对于ego-planner&#... 查看详情

ros实验笔记之——基于l515激光相机的flvis与mlmapping(代码片段)

之前博客《ROS实验笔记之——VINS-Mono在l515上的实现》在l515上实现了vins,博客《ROS实验笔记之——SLAM无人驾驶初入门》配置flvis并跑了对应的kitti数据集本博文在l515上先实现flvis然后再用mlmapping来建图。camera.launch<launch>&l... 查看详情

ros实验笔记之——evo(代码片段)

Errorwhileprocessing"dvs_trackingflyingroom"·Issue#4·uzh-rpg/rpg_dvs_evo_open·GitHub之前博客《ROS仿真笔记之——基于gazebo的eventcamera仿真(dvsgazebo)》介绍了DVS的gazebo仿真。博客《ROS学习笔记之——ESVO复现及DAVIS346测试》介绍了ESVO以及事件... 查看详情

ros实验笔记之——基于eventcamera的asc*特征(代码片段)

目录原理测试参考资料:原理详细的理论部分就不阐述了,可以参考原文以及这个博客~【事件相机整理】角点检测与跟踪总结_larrydong的博客-CSDN博客测试先进入工程编译源码。注意用ros版本的~运行的节点图如下然... 查看详情

ros实验笔记之——px4仿真

...些基本的仿真学习~之前在做无人机仿真开发时《ROS实验笔记之——基于Prometheus自主无人机开源项目的学习与仿真》,已经安装了px4了~为此不需要 查看详情

ros实验笔记之——基于vscode的ros开发(代码片段)

在VSCODE中添加ROS的插件,可以使得其开发比较简单,但是有时候还是无法显示出一些ROS函数或者变量,修改.vscode文件夹下的c_cpp_properties.json文件如下:"configurations":["browse":"databaseFilename":"","li... 查看详情

ros实验笔记之——基于dv-gui的camera与imu校正(davis346与dvxplorer)

参考资料Tutorials|iniVation 查看详情

ros实验笔记之——基于kalibr来标定davis346(代码片段)

之前博客《ROS学习笔记之——DAVIS346calibration》已经实现了用dv-gui(Calibration[Tutorial]·DV)来标定eventcamera了。但是缺少了跟IMU的外参标定等等。本博文利用Kalibr库来对其进行标定。Kalibr安装先创建一个工作空间mkdir-p~/kalibr_... 查看详情

ros实验笔记之——基于kalibr标定event与imu(代码片段)

之前博客《ROS实验笔记之——基于kalibr来标定DAVIS346》实现了基于colorframe用kalibr矫正camera与imu。但是由于dvxplorer没有image,所以后面又在博客《ROS实验笔记之——基于dv-gui的camera与IMU校正(DAVIS346与DVXplorer)》直接利... 查看详情

ros实验笔记之——基于dv-gui多次标定event与imu的实验记录

之前博客《ROS实验笔记之——基于dv-gui的camera与IMU校正(DAVIS346与DVXplorer)》已经实现了event与imu的标定,但是几次标定下来发现误差还挺大的。。。。本来打算用dvsrender获取图像,然后用原始版本的kalibr来标定&#x... 查看详情

ros学习笔记之——基于qgc的px4仿真

之前博客《ROS实验笔记之——PX4仿真》已经介绍了PX4编译及QGC的安装,本博文进一步的基于QGC进行仿真控制QGC里有很多的参数控制首先打开虚拟的遥控器是实现遥控控制就可以在QGC用模拟手柄控制无人机(左边的遥感是... 查看详情

ros实验笔记之——slam无人驾驶初入门(代码片段)

最近想学习一下无人驾驶SLAM方面的内容代码测试这里先基于kitti数据集,进行测试。之前博客中已经介绍过kitti数据集了。本博文就用这个数据集来进行各种经典方法的复现TheKITTIVisionBenchmarkSuitehttp://www.cvlibs.net/datasets/kitti/eva... 查看详情

ros实验笔记之——基于allan_variance_ros标定imu(代码片段)

之前标定IMU都是采用imu_utils的,但是今天发现,在kalibr里面作者推荐用的是allan_variance_ros本博文就试试用此算法的标定结果,同时也可以跟之前imu_utils标定的结果对比一下~下载文件后,编译catkinbuildallan_variance_rosR... 查看详情

ros实验笔记之——ceres跟eigen不匹配(代码片段)

slam中经常需要用到基于ceres的优化,但是有时eigen库更新了或者对应的gcc版本影响编译之类的,会出现eigen的版本根ceres版本不匹配。实际上只需要进入对应的文件更改依赖即可。当然提前需要自己的eigen版本号。可参考查... 查看详情

ros仿真笔记之——基于gazebo的多机器人探索环境仿真(代码片段)

...plore_lite的机器人的包本博文对其进行gazebo仿真分析 目录实验修改地方的说明参考资料 实验首先在包clone下来(这个包设置为私密了,想下载的读者可以直接下载源包https://github.com/hrnr/m-explore然后再做相应的改动)cd... 查看详情

ros实验笔记之——无人机在vicion下试飞(代码片段)

之前博《ROS实验笔记之——自主搭建四旋翼无人机》、《ROS实验笔记之——JCV-450无人机初入门》、《ROS实验笔记之——基于Prometheus自主无人机开源项目的学习与仿真》已经介绍过一些无人机的仿真,试飞。本博文基于vicion... 查看详情

ros实验笔记之——davis346测试(代码片段)

之前博客《ROS学习笔记之——ESVO复现及DAVIS346测试》介绍了dvs驱动的安装。本博文对到手的时间相机进行测试。运行命令roslaunchdvs_rendererdavis_mono.launch但是运行的时候出现报错[WARN][1632472696.858249337]:Cameracalibrationfile/home/kwanwaipang/.r... 查看详情