Turtlebot2上的cartographer部署与测试

任务动机:在openEuler下部署和测试cartographer,为cartographer优化创建环境。

任务描述:Turtlebot2上安装cartographer,添加雷达和底盘驱动后,对软件所5号楼12层2000平方米办公场所进行制图,对比Lidar、Lidar+IMU和Lidar+odom解决方案制图效果。

1. 安装

1.1 cartographer安装

我这边直接安装的是turtlebot版本,本质上与单纯的cartographer版本的区别就是多了一个turtlebot的依赖包。前面编译步骤没有区别。

第一步:安装相关依赖包
sudo apt-get update
sudo apt-get install -y python-wstool python-rosdep ninja-build
第二步:创建并初始化 名为 catkin_ws 的工作空间
mkdir catkin_ws
cd catkin_ws
wstool init src
第三步:生成编译所需依赖包
wstool merge -t src https://raw.githubusercontent.com/googlecartographer/cartographer_turtlebot/master/cartographer_turtlebot.rosinstall
wstool update -t src
第四步:安装第三步中的包文件中的所需ros依赖

src/cartographer/scripts/install_proto3.sh
sudo rosdep init
rosdep update
rosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} -y
第五步:编译安装
catkin_make_isolated --install --use-ninja -j1
source install_isolated/setup.bash

注意事项

1. 如果没有科学上网,在执行wstool update -t src之前,需要将src/.rosinstall文件修改成以下内容,以解决ceres-solver下载不了的问题

vim src/.rosinstall
# 更改ceres-solver中地址改为下面的地址:
#>>uri: https://github.com/ceres-solver/ceres-solver.git

2. 网络要保持连同,因为在执行过程中还会从github下载软件包

3. 如果编译失败,就删掉工作空间目录下除了src目录之外其他所有的文件夹,重新编译

4. 扩展2Gswap:apt-get install dphys-swapfile

5. 使用单核编译,对应上述流程的第五步:catkin_make_isolated --install --use-ninja -j1

测试

source ~/catkin_ws/install_isolated/setup.bash
  • 使用博物馆数据集:

    https://storage.googleapis.com/cartographer-public-data/bags/backpack_2d/cartographer_paper_deutsches_museum.bag

  • 启动cartographer:
roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag
  • 测试结果:

1.2 激光雷达驱动

  1. 下载驱动:

    git clone https://github.com/leishen-lidar/LS01B

  2. 构建对应工作空间

  3. 直接roslaunch 驱动即可。

roslaunch ls01b_v2 ls01b_v2.launch

如果需要可视化的话: 在rviz中将固定的frame设置为laser_link,添加对应的laserScan模块即可,其中lidar的topic_name: /scan

1.3 底盘驱动

首先打开kobuki底盘电源,USB线连接cp机,确认绿灯亮起后输入命令。

roscore

roslaunch turtlebot_bringup minimal.launch

roslaunch turtlebot_teleop keyboard_teleop.launch

通过键盘控制机器人移动。

1.4 两种雷达型号的性能测试

分别在kobuki底盘上使用两种不同的雷达型号进行cpu和mem的占用测试。

1> cartographer运行中资源占用情况

Turtlebot2上的cartographer部署与测试_第1张图片

cartographer这部分很正常,不存在什么问题。跟turtlebot的cpu占用差不多,排除cartographer的问题。

2> Ydlidar雷达的资源占用和镭神雷达对比

  • Ydlidar情况:

Turtlebot2上的cartographer部署与测试_第2张图片

  • 镭神的情况:

Turtlebot2上的cartographer部署与测试_第3张图片

通过上述可以看出:

  • yd雷达cpu占有平均在50%,跟cartographer一个数量级。不太合理。
  • 正常雷达使用cpu情况应该是镭神这样,大约在5%左右的cpu占用量。这样才是一个合理的范围。

3> test method

pip install psrecord
alias psrecord='/home/《your_name》/.local/bin/psrecord'
psrecord  --interval 1 --plot .png

4> 更换ydlidar的SDK之后的两个雷达测试对比

yd_lidar

Turtlebot2上的cartographer部署与测试_第4张图片

  • nums of each scan: 909

    frequency : 10hz

leishen_lidar

Turtlebot2上的cartographer部署与测试_第5张图片

  • nums of each scan: 1440

  • frequency: 10hz

2. lidar + IMU + odom配置

2.1 相关参数

1. **.lua 文件关键参数说明(基于博物馆lua文件)

tracking_frame = "base_link",
published_frame = "base_link",
odom_frame = "odom",
provide_odom_frame = true,

---

use_odometry = false,

通常情况下,tracking_frame应该等于imu_link, 但是在博物馆lua文件中,写的是base_link,究其原因是博物馆的base_link == imu_link:

Turtlebot2上的cartographer部署与测试_第6张图片

上图中,我们可以看到由节点/robot_state_publisher维护的tf变换中,transform一直都是0;

odom_frame 只有当参数provide_odom_frame is true的时候,该参数才有意义。该frame连接 published_frame 和map_frame,表示机器人没有遇到回环的时候局部SLAM的定位结果。

他只是这个frame的名字,为了防止和真正机器人提供的odom混淆,建议改名字为"odom_by_cartographer":

Turtlebot2上的cartographer部署与测试_第7张图片

provide_odom_frame

true的话:提供纯粹的由cartographer生成的里程计frame

false的话, the tf_tree like this:

Turtlebot2上的cartographer部署与测试_第8张图片

use_odometry 启用的话,cartographer的节点在话题"/odom"上订阅消息类型为nav_msgs/Odometry的消息类型。 注意: 这里的odom是topic,而不是 frame

2. 在cartographer中使用更多的传感器、信息

     1. wheel encoder it can be used to improve cartographer's localization. just modify the .luafiles:

use_odometry

     2. gps

     this topic can improve the global SLAM.

     3. landmark For landmarks publishing on a cartographer_ros_msgs/LandmarkList topic named landmarks.

     the msg info:

std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
cartographer_ros_msgs/LandmarkEntry[] landmark
  string id
  geometry_msgs/Pose tracking_from_landmark_transform
 geometry_msgs/Point position
   float64 x
   float64 y
   float64 z
 geometry_msgs/Quaternion orientation
   float64 x
   float64 y
   float64 z
   float64 w
  float64 translation_weight
  float64 rotation_weight

3. 相关知识

  1. Cartographer需要三轴的加速度来估计重力方向。

  2. 如果已经建好地图, 可以使用cartographer进行纯定位.在cartographer_node的参数中配置 -load_state_filename ,然后再lua文件中做如下定义:

TRAJECTORY_BUILDER.pure_localization_trimmer = {
    max_submaps_to_keep = 3,
}

    3. IMU-lidar的外参标定

ceres优化器可以帮助提高外参标定的准确度。使用过程中,多走一些回环,有助于提高外参标定的结果精度。

如果需要我们自己维护tf_tree的时候,有如下两种方法

  • urdf
  • robot_state_publisher

小结:想要在turtlebot上正确运行cartographer,需要对lua文件和launch文件进行更改。

2.2 真实机器人上的lua文件

使用odom+lidar的配置:

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

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "odom",
  published_frame = "odom",
  odom_frame = "odom",
  provide_odom_frame = false,
  publish_frame_projected_to_2d = true,
  use_pose_extrapolator = 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.5,
  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
MAP_BUILDER.num_background_threads = 5

TRAJECTORY_BUILDER_2D.min_range = 0.1
TRAJECTORY_BUILDER_2D.max_range = 12

TRAJECTORY_BUILDER_2D.voxel_filter_size = 0.05
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_length = 1.0 
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.min_num_points = 200
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_range = 50

TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1.

TRAJECTORY_BUILDER_2D.submaps.num_range_data = 50

TRAJECTORY_BUILDER_2D.use_imu_data = false 
--POSE_GRAPH.optimization_problem.local_slam_pose_translation_weight
--POSE_GRAPH.optimization_problem.local_slam_pose_rotation_weight
--POSE_GRAPH.optimization_problem.odometry_translation_weight
--POSE_GRAPH.optimization_problem.odometry_rotation_weight

-- TRAJECTORY_BUILDER_2D.ceres_scan_matcher.tranlation_weight = 2e2
-- TRAJECTORY_BUILDER_2D.ceres_scan_matcher.rotation_weight = 4e2

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 = 6e-1


POSE_GRAPH.optimize_every_n_nodes = 70
POSE_GRAPH.global_sampling_ratio = 0.001
POSE_GRAPH.global_constraint_search_after_n_seconds = 10

POSE_GRAPH.constraint_builder.sampling_ratio = 0.3
POSE_GRAPH.constraint_builder.min_score= 0.65

POSE_GRAPH.optimization_problem.ceres_solver_options.max_num_iterations = 50
POSE_GRAPH.optimization_problem.huber_scale = 1e2


return options

使用lidar + imu的lua配置:

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

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "imu",
  published_frame = "odom",
  odom_frame = "odom",
  provide_odom_frame = false,
  publish_frame_projected_to_2d = true,
  use_pose_extrapolator = true,
  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.5,
  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
MAP_BUILDER.num_background_threads = 8

TRAJECTORY_BUILDER_2D.min_range = 0.1
TRAJECTORY_BUILDER_2D.max_range = 12

TRAJECTORY_BUILDER_2D.voxel_filter_size = 0.05
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_length = 1.0 
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.min_num_points = 200
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_range = 50

TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1.

TRAJECTORY_BUILDER_2D.submaps.num_range_data = 50

TRAJECTORY_BUILDER_2D.use_imu_data = true 

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 = 6e-1


POSE_GRAPH.optimize_every_n_nodes = 70
POSE_GRAPH.global_sampling_ratio = 0.001
POSE_GRAPH.global_constraint_search_after_n_seconds = 10

POSE_GRAPH.constraint_builder.sampling_ratio = 0.3
POSE_GRAPH.constraint_builder.min_score= 0.65

POSE_GRAPH.optimization_problem.ceres_solver_options.max_num_iterations = 50
POSE_GRAPH.optimization_problem.huber_scale = 1e2


return options

2.3 真实机器人上的launch文件



  
	
    	
    	
    	
    	
	 
  

  

3. 真实环境测试

在整个软件所5号楼12层构建地图,全部面积达到2000+平方米。

分离试验结果:

Turtlebot2上的cartographer部署与测试_第9张图片

从上图可以看到,ODOM + LIDAR在局部存在纠偏没纠回来的可能。

你可能感兴趣的:(算法)