第一步 安装与编译
具体的安装步骤参考官方文档即可,链接如下。值得注意的是,一定要确保每个步骤都安装成功,尤其是Ninja。
https://google-cartographer-ros.readthedocs.io/en/latest/compilation.html
1.1 下载代码
其中ceres1.13.0是需要翻墙才能下载的,可以直接下载我上传的代码,cartographer的2019年5月28日的安装代码(release-1.0),包含了proto,cartographer,cartographer_ros以及ceres1.13.0版本。
---
后来有同学反应 abseil-cpp 这个包也下载不下来,所以我又上传了一份新的代码,是2021年04月20日在github上下载的最新的代码,包含了如下内容.
https://download.csdn.net/download/tiancailx/17061391
cartographer_install_2021-04-20:
abseil-cpp
protobuf
ceres-solver
cartographer
cartographer_ros
auto-carto-build.sh
通过如下命令执行编译与安装脚本
chmod +x auto-carto-build.sh
./auto-carto-build.sh
通过执行脚本自动安装abseil-cpp,protobuf,ceres-solver,以及cartographer,会直接安装在系统里,以后如果不更改的话就不需要重新编译了.
所以之后只需要在ROS的工作空间中使用catkin_make编译cartographer_ros就可以了,就像 1.3.4.1 说的那样.
1.2 安装依赖
sudo apt-get install -y python-wstool python-rosdep ninja-build \
libgflags-dev python-sphinx libgoogle-glog-dev libsuitesparse-dev liblua5.2-dev \
libatlas-base-dev stow
1.3 编译
其中1-4步为分步执行各个依赖包.
其中,1.3.5是通过脚本来安装cartographer与各个依赖包.
1.3.1 第一步 编译abseil-cpp
最新的cartographer还依赖 abseil-cpp 这个包,所以首先单独安装一下这个包.
这个包的安装方式在cartographer/scripts文件夹中的 install_abseil.sh 文件中.可以直接运行这个文件,运行方式如下所示:
cd cartographer/scripts
chmod +x install_abseil.sh
./install_abseil.sh
也可以直接将命令复制到终端中逐行运行,这个文件的内容如下所示.可以看到,首先通过git clone的方式下载了abseil-cpp 包,之后将这个包的版本切换到了 d902 版本,然后才进行编译与安装.
set -o errexit
set -o verbose
git clone https://github.com/abseil/abseil-cpp.git
cd abseil-cpp
git checkout d902eb869bcfacc1bad14933ed9af4bed006d481
mkdir build
cd build
cmake -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_INSTALL_PREFIX=/usr/local/stow/absl \
..
ninja
sudo ninja install
cd /usr/local/stow
sudo stow absl
注意:install之后这个包就不需要管了,可以删除掉了,因为已经install到系统里了。
1.3.2 第二步 编译protobuf
protobuf 的安装方式在cartographer/scripts文件夹中的 install_proto3.sh 文件中.可以直接运行这个文件,运行方式如下所示:
cd cartographer/scripts/
chmod +x install_proto3.sh
./install_proto3.sh
也可以直接将命令复制到终端中逐行运行,这个文件的内容如下所示.
可以看到,首先通过git clone的方式下载了protobuf 包,之后将这个包的版本切换到了 3.4.2 版本,然后才进行编译与安装.
set -o errexit
set -o verbose
VERSION="v3.4.1"
# Build and install proto3.
git clone https://github.com/google/protobuf.git
cd protobuf
git checkout tags/${VERSION}
mkdir build
cd build
cmake -G Ninja \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_BUILD_TYPE=Release \
-Dprotobuf_BUILD_TESTS=OFF \
../cmake
ninja
sudo ninja install
注意:install之后这个包就不需要管了,可以删除掉了,因为已经install到系统里了。
1.3.3 第三步 编译ceres
ceres 的安装方式在cartographer/scripts文件夹中的 install_ceres.sh文件中.可以直接运行这个文件,运行方式如下所示:
cd cartographer/scripts/
chmod +x install_ceres.sh
./install_ceres.sh
也可以直接将命令复制到终端中逐行运行,这个文件的内容如下所示.
可以看到,首先通过git clone的方式下载了protobuf 包,之后将这个包的版本切换到了1.13.0 版本,然后才进行编译与安装.
set -o errexit
set -o verbose
VERSION="1.13.0"
# Build and install Ceres.
git clone https://ceres-solver.googlesource.com/ceres-solver
cd ceres-solver
git checkout tags/${VERSION}
mkdir build
cd build
cmake .. -G Ninja -DCXX11=ON
ninja
CTEST_OUTPUT_ON_FAILURE=1 ninja test
sudo ninja install
注意:ceres的下载需要科学上网才可以下载.如果不知道从哪里下载ceres的同学,可以去我的资源中免费下载.
1.3.4 第四步 编译cartographer与cartographer_ros
如果你跟着我成功走到了这步的话,那么恭喜你,你的安装没有遇到各种意外.
前三步已经将cartographer与cartographer_ros的各个依赖包都装好了,这步就是要开始编译主角,cartographer与cartographer_ros了.
这一步根据是否需要修改cartographer的代码,可以分成两种编译方式.
1.3.4.1 不需要修改cartographer源码
如果不需要修改cartographer源码的话,可以先编译cartographer,然后install到系统中,接下来就只需要将cartographer_ros看做是一个普通的ROS包进行编译就好了.
首先,安装cartographer,通过在终端中逐行执行如下命令即可完成cartographer的编译与安装,最后一步会将cartographer安装到系统中,可以被其他的包找到.
# Build and install Cartographer.
cd cartographer
mkdir build
cd build
cmake .. -G Ninja
ninja
sudo ninja install
1.3.4.2 需要修改cartographer源码
需要修改cartographer的源码的话,就需要将cartographer与cartographer_ros放在一起进行编译.
由于carographer不是ROS的包,所以不能通过catkin_make进行编译.需要通过cartographer官方教程中的ninja来进行编译.
cartographer_ws:
src:
cartographer
cartographer_ros:
cartographer_ros
cartographer_ros_msgs
cartographer_ros_rviz
之后,通过cartographer官方文档中的编译指令进行编译
# 处于cartographer_ws文件夹内
catkin_make_isolated --install --use-ninja
1.3.5 通过脚本编译cartographer与依赖
如果觉得上述步骤很麻烦,可以将所有的命令设置成一个脚本文件一起执行.
首先将各个包的位置设置为如下所示,将protobuf与ceres-solver,cartographer,放在同一个文件夹下.并新建一个auto-carto-build.sh文件.
cartographer_ws:
protobuf
cartographer
ceres-solver
auto-carto-build.sh
auto-carto-build.sh的内容如下所示,这个脚本首先会下载 abseil-cpp,然后进行 abseil-cpp的编译与安装,之后进行ceres-solver的编译与安装,之后进行protobuf的编译与安装,之后进行cartographer的编译与安装.
#! /bin/bash
# Build and install abseil-cpp
set -o errexit
set -o verbose
git clone https://github.com/abseil/abseil-cpp.git
cd abseil-cpp
git checkout d902eb869bcfacc1bad14933ed9af4bed006d481
mkdir build
cd build
cmake -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_INSTALL_PREFIX=/usr/local/stow/absl \
..
ninja
sudo ninja install
cd /usr/local/stow
sudo stow absl
# Build and install Ceres.
cd -
cd ../../ceres-solver
mkdir build
cd build
cmake .. -G Ninja -DCXX11=ON
ninja
#CTEST_OUTPUT_ON_FAILURE=1 ninja test
sudo ninja install
# Build and install proto3.
cd ../../protobuf
mkdir build
cd build
cmake -G Ninja \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_BUILD_TYPE=Release \
-Dprotobuf_BUILD_TESTS=OFF \
../cmake
ninja
sudo ninja install
# Build and install Cartographer.
cd ../../cartographer
mkdir build
cd build
cmake .. -G Ninja
ninja
#CTEST_OUTPUT_ON_FAILURE=1 ninja test
sudo ninja install
上边的脚步是将test注释掉了,如果想要启用test就把注释打开。
通过如下命令执行脚本
chmod +x auto-carto-build.sh
./auto-carto-build.sh
通过这个脚本安装之后,abseil-cpp, protobuf, ceres, cartographe, 都会被install进系统中。
也就是说如果不改cartographer源码的话,以后都不需要编译这四个包了,只需要用catkin_make编译cartographer_ros即可.这种情况下,修改lua文件也会即时生效。
如果使用 catkin_make_isolated --install --use-ninja 编译这几个包的话每次改完Lua文件还需要使用这条指令编译之后才可以使得修改后的lua文件生效。
第二步 参数配置
安装好了之后试着跑一下demo,官方文档中的那几个demo包的下载需要翻墙,下好了直接就能跑,只要把bag包放在Download文件夹下即可。
如果想要使用自己的机器人跑carto该怎么去修改参数配置文档呢,也就是lua文件。
carto的默认参数配置在cartographer/configuration_files文件夹下,其中有2个起总领作用,分别是map_builder.lua以及trajectory_builder.lua。两个文件的内容如下:
# map_builder.lua
include "pose_graph.lua"
MAP_BUILDER = {
use_trajectory_builder_2d = false,
use_trajectory_builder_3d = false,
num_background_threads = 4,
pose_graph = POSE_GRAPH,
collate_by_trajectory = false,
}
# trajectory_builder.lua
include "trajectory_builder_2d.lua"
include "trajectory_builder_3d.lua"
TRAJECTORY_BUILDER = {
trajectory_builder_2d = TRAJECTORY_BUILDER_2D,
trajectory_builder_3d = TRAJECTORY_BUILDER_3D,
-- pure_localization_trimmer = {
-- max_submaps_to_keep = 3,
-- },
collate_fixed_frame = true,
collate_landmarks = false,
}
可以看到,map_build.lua配置了是使用trajectory_build_2d还是trajectory_build_3d,以及后端使用的线程数。trajectory_build就是前端具体的参数配置,分为2d和3d两个文件,而pose_graph.lua为后端优化的具体参数配置。那想要配置自己的硬件实现carto该怎么做呢,接下来我照着carto的demo的配置文件backpack_2d.lua进行讲解一下。
include "map_builder.lua"
include "trajectory_builder.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER,
map_frame = "map",
tracking_frame = "base_link", # 进行slam的坐标系,如果有imu的话为imu的坐标系,没有的话就是base_link 或者 base_footprint
published_frame = "base_link", # carto发布的坐标系
odom_frame = "odom", # 里程计数据的坐标系名称
provide_odom_frame = true, # 是否发布里程计坐标系,适用于机器人本身没有odom坐标系的情况
publish_frame_projected_to_2d = false,
use_pose_extrapolator = true,
use_odometry = false, # 是否使用odom数据
use_nav_sat = false, # 是否使用gps数据
use_landmarks = false, # 是否使用landmarks
num_laser_scans = 0, # 如果用的是单线雷达,此处为雷达的数量
num_multi_echo_laser_scans = 1,
num_subdivisions_per_laser_scan = 10, # 将雷达一帧的数据拆分成几次发出来,对于普通雷达的驱动包来说,此处应为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., # 接下来的5个参数为5种观测的权重比
odometry_sampling_ratio = 1., # 如odom的数据非常不准,可以设置为0.3以减小odom对整体优化的影响
fixed_frame_pose_sampling_ratio = 1.,
imu_sampling_ratio = 1.,
landmarks_sampling_ratio = 1.,
}
MAP_BUILDER.use_trajectory_builder_2d = true # 具体是使用2d 还是 3d 的slam
TRAJECTORY_BUILDER_2D.num_accumulated_range_data = 10 # 几个雷达,以及一帧数据被拆成几次发出来,对于1个激光雷达,普通的雷达驱动包来说,此处应为1
return options
这是对默认的配置文件进行了简单的分析,但是该怎样配置自己的硬件的lua呢?
# myrobot_2d.lua
include "map_builder.lua"
include "trajectory_builder.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER,
map_frame = "map",
tracking_frame = "base_link",
published_frame = "base_link",
odom_frame = "odom",
provide_odom_frame = true,
publish_frame_projected_to_2d = false,
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.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.use_imu_data = false
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.min_range = 0.
TRAJECTORY_BUILDER_2D.max_range = 30.
return options
以上配置了使用1个单线激光雷达进行2d slam 的lua文件,并且是在机器人本身没有提供odom坐标系的情况下。以上配置出来的tf为 map->odom->base_link。
这几个坐标系的名字都是干嘛的呢?
map_frame始终为map,这个不用动。tracking_frame也可以始终为base_link不用动。provide_odom_frame 为 false时,carto发布的坐标变化为 map_frame -> published_frame ,也就是map到base_link,如果provide_odom_frame为 true时,carto就会发布map -> odom -> base_link 的坐标变化。
所以,如果机器人本身存在odom坐标系,而你又想让carto 使用 odom数据 ,就需要将published_frame 设置为odom,provide_odom_frame = false 而use_odometry = true。
之后MAP_BUILDER.use_trajectory_builder_2d为使用2d slam 。在进行2d slam 时,carto的默认配置是使用imu的,所以如果没有imu就要TRAJECTORY_BUILDER_2D.use_imu_data = false,否则会一直等待imu的数据而进行不下去。而3d 的 slam 必须使用imu,所以就没有这个参数配置。
再之后 TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true,这一项配置很重要,对于我自己使用的雷达或者在 gazebo 中仿真时,如果不配置这项得到的建图效果将非常差。但是carto得demo没有进行这一项的配置也跑的很好,这让我很费解,难道是因为我没使用imu的问题???
那这个参数是干嘛的呢?
这个参数配置的是否使用 实时的闭环检测方法 来进行前端的扫描匹配。如果这项为false,则扫描匹配使用的是通过前一帧位置的先验,将当前scan与之前做对比,使用 高斯牛顿法 迭代 求解最小二乘问题 求得当前scan的坐标变换。如果这项为true,则使用闭环检测的方法,将当前scan在一定的搜索范围内搜索,范围为设定的平移距离及角度大小,然后在将scan插入到匹配的最优位置处。这种方式建图的效果非常好,即使建图有漂移也能够修正回去,但是这个方法的计算复杂度非常高,非常耗cpu。
到这里2d 的 slam 应该能够使用了。在carto demo 的 launch 中配置了 urdf 模型,如果机器人的urdf 模型已经单独启动了,那么就不需要在carto的launch中配置urdf了。carto的launch 和 lua 配置文件都是在install_isolated/share/cartographer_ros/launch/ 和
install_isolated/share/cartographer_ros/configuration_files/ 下,所以如果只修改了cartographer_ros软件包中的launch 和 lua 文件之后是需要重新编译的,编译之后才能将修改的文件安装到install_isolated文件中。编译的命令为:
source install_isolated/setup.bash
catkin_make_isolated --install --use-ninja
第三步 参数说明
3.1 trajectory_builder_2d.lua
TRAJECTORY_BUILDER_2D = { # 距离的单位: 米, 角度的单位: 度,时间的单位: 秒
use_imu_data = true,
min_range = 0., # 雷达数据的最远最近滤波
max_range = 30.,
min_z = -0.8, # 还可以设置雷达数据在z轴上的滤波将3d数据转成2d的
max_z = 2.,
missing_data_ray_length = 5., # 超出'max_range'的点将以此长度作为free空间插入
num_accumulated_range_data = 1, # carto建议将一帧雷达数据分成几个ros的消息发,以减少运动带来的雷达数据的畸变
voxel_filter_size = 0.025, # 使用voxel滤波时立方体边长的大小,这个值是固定的
# 使用固定的voxel滤波之后,再尝试使用自适应的voxel滤波,体素滤波器 用于生成稀疏点云 以进行 扫描匹配
adaptive_voxel_filter = {
max_length = 0.5, # 尝试确定最佳的立方体边长,边长最大为0.5
min_num_points = 200, # 如果存在 较多点 并且大于'min_num_points',则减小体素长度以尝试获得该最小点数
max_range = 50., # 距远离原点超过max_range 的点被移除
},
loop_closure_adaptive_voxel_filter = {
max_length = 0.9,
min_num_points = 100, # 体素滤波器 用于生成稀疏点云 以进行 闭环检测
max_range = 50.,
},
# 是否使用 real_time_correlative_scan_matcher 解决 在线的扫描匹配 问题,从而为ceres提供先验信息
use_online_correlative_scan_matching = false,
# 有2种解决 扫描匹配 问题 的方法
# 通过 类似闭环检测 的方式找到最优匹配,然后作为 先验,再使用ceres_scan_matcher 进行求解
# 计算复杂度高,但是很鲁棒,在odom或者imu不准时依然能达到很好的效果
# 如果一个平台的瞬间平移很少,则可以降低平移的权重,旋转也是一样
real_time_correlative_scan_matcher = {
linear_search_window = 0.1, # 找到最佳扫描匹配的最小线性搜索窗口
angular_search_window = math.rad(20.), # 找到最佳扫描匹配的最小角度搜索窗口
translation_delta_cost_weight = 1e-1, # 用于计算各部分score的权重
rotation_delta_cost_weight = 1e-1,
},
# 将前一时刻的位姿作为先验,使用odom或者imu的数据进行预测,以确定scan的最优位姿
ceres_scan_matcher = {
occupied_space_weight = 1., # 每个Cost因素的 尺度因子
translation_weight = 10.,
rotation_weight = 40.,
ceres_solver_options = { # see https://code.google.com/p/ceres-solver/
use_nonmonotonic_steps = false,
max_num_iterations = 20,
num_threads = 1,
},
},
# 只有当scan的 平移、旋转或者时间 超过阈值时 才会被加入到 submap 中,不超过则舍弃
motion_filter = {
max_time_seconds = 5.,
max_distance_meters = 0.2,
max_angle_radians = math.rad(1.),
},
imu_gravity_time_constant = 10., # 移动时通过imu观测10s以确定重力的平均方向
submaps = {
num_range_data = 90, # 每个submap的scan总数为num_range_data 的2倍,前一半进行初始化而不进行匹配,后一半进行匹配
grid_options_2d = {
grid_type = "PROBABILITY_GRID", # submap 存储雷达数据的格式,还可以为Truncated Signed Distance Fields (TSDF)
resolution = 0.05, # 0.05米 栅格的尺寸
},
range_data_inserter = {
range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D",
probability_grid_range_data_inserter = {
insert_free_space = true, # 如果为 false,则free的栅格不会改变 占用网格 中的概率。
hit_probability = 0.55, # hit(占用) 时的概率
miss_probability = 0.49, # miss(空闲) 时的概率
},
tsdf_range_data_inserter = {
truncation_distance = 0.3,
maximum_weight = 10.,
update_free_space = false,
normal_estimation_options = {
num_normal_samples = 4,
sample_radius = 0.5,
},
project_sdf_distance_to_scan_normal = true,
update_weight_range_exponent = 0,
update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.5,
update_weight_distance_cell_to_hit_kernel_bandwidth = 0.5,
},
},
},
}
3.2 trajectory_builder_3d.lua
MAX_3D_RANGE = 60.
TRAJECTORY_BUILDER_3D = {
min_range = 1.,
max_range = MAX_3D_RANGE,
num_accumulated_range_data = 1,
voxel_filter_size = 0.15,
# 在3d slam 时会有2个自适应滤波,一个生成高分辨率点云,一个生成低分辨率点云
high_resolution_adaptive_voxel_filter = {
max_length = 2.,
min_num_points = 150,
max_range = 15.,
},
low_resolution_adaptive_voxel_filter = {
max_length = 4.,
min_num_points = 200,
max_range = MAX_3D_RANGE,
},
use_online_correlative_scan_matching = false,
real_time_correlative_scan_matcher = {
linear_search_window = 0.15,
angular_search_window = math.rad(1.),
translation_delta_cost_weight = 1e-1,
rotation_delta_cost_weight = 1e-1,
},
# 在3D中,occupied_space_weight_0和occupied_space_weight_1参数分别与高分辨率和低分辨率滤波点云相关
ceres_scan_matcher = {
occupied_space_weight_0 = 1.,
occupied_space_weight_1 = 6.,
translation_weight = 5.,
rotation_weight = 4e2,
only_optimize_yaw = false,
ceres_solver_options = {
use_nonmonotonic_steps = false,
max_num_iterations = 12,
num_threads = 1,
},
},
motion_filter = {
max_time_seconds = 0.5,
max_distance_meters = 0.1,
max_angle_radians = 0.004,
},
imu_gravity_time_constant = 10.,
rotational_histogram_size = 120, # rotational scan matcher 的 histogram buckets
# 在3D中,出于扫描匹配性能的原因,使用两个混合概率网格。 (术语“hybrid”仅指内部树状数据表示并被抽象给用户)
submaps = {
high_resolution = 0.10, # 用于近距离测量的高分辨率hybrid网格 for local SLAM and loop closure,用来与小尺寸voxel进行精匹配
high_resolution_max_range = 20., # 在插入 high_resolution map 之前过滤点云的最大范围
low_resolution = 0.45, # 用于远距离测量的低分辨率hybrid网格 for local SLAM only,用来与大尺寸voxel进行粗匹配
num_range_data = 160,
range_data_inserter = {
hit_probability = 0.55,
miss_probability = 0.49,
num_free_space_voxels = 2, # 最多可更新多少个free space voxels以进行扫描匹配,0禁用free space
},
},
}
3.3 pose_graph.lua
POSE_GRAPH = {
optimize_every_n_nodes = 90, # 每几个节点(节点是什么?scan?)执行一次优化,设为0即关闭后端优化
constraint_builder = {
sampling_ratio = 0.3, # 如果添加的约束与潜在约束的比例低于 此比例,则将添加约束。
max_constraint_distance = 15., # 在子图附近考虑姿势的阈值
min_score = 0.55, # 扫描匹配分数的阈值,低于该阈值时不考虑匹配。 低分表示扫描和地图看起来不相似
global_localization_min_score = 0.6, # 阈值,低于该阈值的全局定位不受信任
loop_closure_translation_weight = 1.1e4, # 优化问题中的 闭环约束 的 平移 的权重
loop_closure_rotation_weight = 1e5, # 优化问题中的 闭环约束 的 旋转 的权重
log_matches = true, # 闭环约束的直方图统计报告
fast_correlative_scan_matcher = { # 闭环检测的第一步
linear_search_window = 7., # 依靠“分支定界”机制在不同的网格分辨率下工作,并有效地消除不正确的匹配
angular_search_window = math.rad(30.), # 一旦找到足够好的分数(高于最低匹配分数),它(scan)就会被送入Ceres扫描匹配器以优化姿势。
branch_and_bound_depth = 7,
},
ceres_scan_matcher = { # 闭环检测的第二步 优化位姿图
occupied_space_weight = 20.,
translation_weight = 10.,
rotation_weight = 1.,
ceres_solver_options = {
use_nonmonotonic_steps = true,
max_num_iterations = 10,
num_threads = 1,
},
},
fast_correlative_scan_matcher_3d = {
branch_and_bound_depth = 8,
full_resolution_depth = 3,
min_rotational_score = 0.77,
min_low_resolution_score = 0.55,
linear_xy_search_window = 5.,
linear_z_search_window = 1.,
angular_search_window = math.rad(15.),
},
ceres_scan_matcher_3d = {
occupied_space_weight_0 = 5.,
occupied_space_weight_1 = 30.,
translation_weight = 10.,
rotation_weight = 1.,
only_optimize_yaw = false,
ceres_solver_options = {
use_nonmonotonic_steps = false,
max_num_iterations = 10,
num_threads = 1,
},
},
},
matcher_translation_weight = 5e2,
matcher_rotation_weight = 1.6e3,
optimization_problem = { # 残差方程的参数配置
huber_scale = 1e1, # Huber损失函数的尺度因子,该值越大,(potential) outliers(潜在)异常值 的影响越大。
acceleration_weight = 1e3, # IMU加速度的权重
rotation_weight = 3e5, # IMU旋转项的权重
local_slam_pose_translation_weight = 1e5, # 基于local SLAM的姿势在连续节点之间进行平移的权重
local_slam_pose_rotation_weight = 1e5, # 基于里程计的姿势在连续节点之间进行平移的权重
odometry_translation_weight = 1e5,
odometry_rotation_weight = 1e5,
fixed_frame_pose_translation_weight = 1e1, # FixedFramePose?应该是gps的
fixed_frame_pose_rotation_weight = 1e2,
log_solver_summary = false, # 可以记录Ceres全局优化的结果并用于改进您的外部校准
use_online_imu_extrinsics_in_3d = true, # 作为IMU残差的一部分
fix_z_in_3d = false,
ceres_solver_options = {
use_nonmonotonic_steps = false,
max_num_iterations = 50,
num_threads = 7,
},
},
max_num_final_iterations = 200, # 在建图结束之后会运行一个新的全局优化,不要求实时性,迭代次数多
global_sampling_ratio = 0.003,
log_residual_histograms = true,
global_constraint_search_after_n_seconds = 10.,
-- overlapping_submaps_trimmer_2d = {
-- fresh_submaps_count = 1,
-- min_covered_area = 2,
-- min_added_submaps_count = 5,
-- },
}
注: 目标计划
在3个月的时间中,我要完成carto的参数配置,最优参数的选择,carto的算法原理以及代码过程。并且将hokuyo, sick, 倍加福 3种单线激光雷达的建图效果对比出来,并分别配置出参数。以及 vlp-16 多线雷达的建图效果及参数。
所以这一章讲的是参数的意义,之后会将carto的论文及代码分析写出来。最后给出4种雷达的建图效果对比。接下来的第二章是对carto的论文进行分析,由于carto的前端使用的hector slam 的方法,所以还会顺带讲一下hector slam 的扫描匹配的最小二乘的公式推导。
由于本人正处于学习调研阶段,所以难免会有错误及疏漏,如果错误请指出,不胜感激!