cartographer常用的lua配置文件包括:map_builder.lua、trajectory_builder.lua、pose_graph.lua、trajectory_builder_2d.lua、trajectory_builder_3d.lua。这些文件的位置在
工作空间/src/cartographer/configuration_files
trajectory_builder.lua、trajectory_builder_2d.lua、trajectory_builder_3d.lua负责前端扫描匹配,map_builder.lua和pose_graph.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 "trajectory_builder_2d.lua"
include "trajectory_builder_3d.lua"
TRAJECTORY_BUILDER = {
trajectory_builder_2d = TRAJECTORY_BUILDER_2D, -- 表示引用了trajectory_builder_2d.lua文件
trajectory_builder_3d = TRAJECTORY_BUILDER_3D,
-- pure_localization_trimmer = {
-- max_submaps_to_keep = 3,
-- },
collate_fixed_frame = true, -- 是否将数据放入阻塞队列中
collate_landmarks = false, -- 是否将数据放入阻塞队列中
}
trajectory_builder.lua文件比较简单,主要参数在trajectory_builder_2d.lua和trajectory_builder_3d.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.
TRAJECTORY_BUILDER_2D = {
use_imu_data = true, -- 是否使用imu数据,默认为true
min_range = 0., -- 雷达数据的最远最近滤波, 保存中间值
max_range = 30., -- 雷达数据不在min_range和max_range之间的会被扔掉
min_z = -0.8, -- 雷达数据的最高与最低的过滤, 保存中间值
max_z = 2., -- 点云数据在z轴的分布在min_z和max_z之间才会被采用,可以通过这两个参数减少地面反射的雷达数据对cartographer的干扰
missing_data_ray_length = 5., -- 超过最大距离范围的数据点用这个距离代替,对于雷达数据中的NAN或NAF数据,用这个参数的值代替
num_accumulated_range_data = 1, -- 几帧有效的点云数据进行一次扫描匹配
voxel_filter_size = 0.025, -- 体素滤波的立方体的边长
-- 使用固定的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提供先验信息
-- 计算复杂度高 , 但是很鲁棒 , 在odom或者imu不准时依然能达到很好的效果
-- 设置为true会提高计算量,当使用频率较低的单线雷达、建图出现叠图的情况时,可以设置为true,辅助建图
use_online_correlative_scan_matching = false,
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,
},
-- ceres匹配的一些配置参数
ceres_scan_matcher = {
occupied_space_weight = 1., -- 地图匹配权重
translation_weight = 10., -- 平移权重,匹配位置和先验位置偏差量的权重
rotation_weight = 40., -- 旋转权重,匹配的姿态和先验的姿态偏差量的权重
-- 以上三者求參差最小,作为ceres的优化依据
-- 下面是ceres求解的参数设置
ceres_solver_options = {
use_nonmonotonic_steps = false,
max_num_iterations = 20, -- 最大迭代次数
num_threads = 1, -- 线程数
},
},
-- 为了防止子图里插入太多数据, 在插入子图之前之前对点云数据进行过滤
motion_filter = {
max_time_seconds = 5.,
max_distance_meters = 0.2,
max_angle_radians = math.rad(1.),
},
-- TODO(schwoere,wohe): Remove this constant. This is only kept for ROS.
imu_gravity_time_constant = 10.,
-- 位姿预测器,一般不用
pose_extrapolator = {
use_imu_based = false,
constant_velocity = {
imu_gravity_time_constant = 10.,
pose_queue_duration = 0.001,
},
imu_based = {
pose_queue_duration = 5.,
gravity_constant = 9.806,
pose_translation_weight = 1.,
pose_rotation_weight = 1.,
imu_acceleration_weight = 1.,
imu_rotation_weight = 1.,
odometry_translation_weight = 1.,
odometry_rotation_weight = 1.,
solver_options = {
use_nonmonotonic_steps = false;
max_num_iterations = 10;
num_threads = 1;
},
},
},
-- 子图相关的一些配置
submaps = {
num_range_data = 90, -- 一个子图里插入雷达数据为180个,这个参数在代码里会乘2
grid_options_2d = {
grid_type = "PROBABILITY_GRID", -- 地图的种类, PROBABILITY_GRID是概率栅格地图,还可以是tsdf格式
resolution = 0.05, -- 地图分辨率
},
range_data_inserter = {
range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D",
-- 概率占用栅格地图的一些配置
probability_grid_range_data_inserter = {
insert_free_space = true,
hit_probability = 0.55, -- 大于该值表示栅格被占用
miss_probability = 0.49, -- 小于该值表明栅格为空
},
-- tsdf地图的一些配置
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,
},
},
},
}
trajectory_builder_3d.lua和trajectory_builder_2d.lua的内容基本相同,下面来解析不同的参数。
-- 在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,
},
ceres_scan_matcher = {
-- 在3D中,occupied_space_weight_0和occupied_space_weight_1参数分别与高分辨率和低分辨率滤波点云相关
occupied_space_weight_0 = 1.,
occupied_space_weight_1 = 6.,
intensity_cost_function_options_0 = {
weight = 0.5,
huber_scale = 0.3,
intensity_threshold = INTENSITY_THRESHOLD,
},
translation_weight = 5.,
rotation_weight = 4e2,
only_optimize_yaw = false,
ceres_solver_options = {
use_nonmonotonic_steps = false,
max_num_iterations = 12,
num_threads = 1,
},
submaps = {
-- 2种分辨率的地图
high_resolution = 0.10, -- 用于近距离测量的高分辨率hybrid网格 for local SLAM and loop closure, 用来与小尺寸voxel进行精匹配
high_resolution_max_range = 20., -- 在插入 high_resolution map 之前过滤点云的最大范围
low_resolution = 0.45,
num_range_data = 160, -- 用于远距离测量的低分辨率hybrid网格 for local SLAM only, 用来与大尺寸voxel进行粗匹配
range_data_inserter = {
hit_probability = 0.55,
miss_probability = 0.49,
num_free_space_voxels = 2,
intensity_threshold = INTENSITY_THRESHOLD,
},
-- 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 "pose_graph.lua"
MAP_BUILDER = {
use_trajectory_builder_2d = false,--use_trajectory_builder_2d和use_trajectory_builder_3d要有一个为true
use_trajectory_builder_3d = false,
num_background_threads = 4, -- 后台线程数
pose_graph = POSE_GRAPH, -- 加载pose_graph.lua的参数
collate_by_trajectory = false,
}
-- 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.
POSE_GRAPH = {
-- 每隔多少个节点执行一次后端优化,可以设置为num_range_data的2倍,每插入2*num_range_data的雷达数据,子图会更新一次,optimize_every_n_nodes设置的太小会导致在子图无变化时多次优化。
optimize_every_n_nodes = 90,
-- 约束构建的相关参数
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, -- 打印约束计算的log
-- 基于分支定界算法的2d粗匹配器
fast_correlative_scan_matcher = {
linear_search_window = 7.,
angular_search_window = math.rad(30.),
branch_and_bound_depth = 7,
},
-- 基于ceres的2d精匹配器
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,
},
},
-- 基于分支定界算法的3d粗匹配器
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的3d精匹配器
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, -- 值越大,(潜在)异常值的影响就越大
acceleration_weight = 1.1e2, -- 3d里imu的线加速度的权重
rotation_weight = 1.6e4, -- 3d里imu的旋转的权重
-- 前端结果残差的权重
local_slam_pose_translation_weight = 1e5,
local_slam_pose_rotation_weight = 1e5,
-- 里程计残差的权重
odometry_translation_weight = 1e5,
odometry_rotation_weight = 1e5,
-- gps残差的权重
fixed_frame_pose_translation_weight = 1e1,
fixed_frame_pose_rotation_weight = 1e2,
fixed_frame_pose_use_tolerant_loss = false,
fixed_frame_pose_tolerant_loss_param_a = 1,
fixed_frame_pose_tolerant_loss_param_b = 1,
log_solver_summary = false, --是否保存优化后的结果
use_online_imu_extrinsics_in_3d = true,
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,
-- },
}
以backpack_2d.lua为例,讲解自己的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,
map_frame = "map", --地图坐标系的名字
tracking_frame = "base_link", -- 将所有传感器数据转换到这个坐标系下,如果有imu,一般设置为imu_link,因为imu的频率非常高(上百hz),而雷达数据的频率相对低(几十hz),如果把imu数据转换到其他坐标系则每秒钟需要转换几百次,比较耗费资源
published_frame = "base_link", -- 设置为tf树最顶端的坐标系名称,设置完成后cartographer会发布map->published_frame的坐标系
odom_frame = "odom", -- 里程计的坐标系名字
provide_odom_frame = true, -- 是否提供odom的tf, 如果为true,则tf树为map->odom->footprint,如果为false,则tf树为map->published_frame
publish_frame_projected_to_2d = false,-- 是否将坐标系投影到平面上,一般为false
use_pose_extrapolator = true, --是否使用位姿推测器,一般为false
-- 通过话题订阅的方式使用里程计、gps、landmark,三者可以同时订阅,但每个只能订阅1个话题
use_odometry = false, -- 是否使用里程计,如果使用要求一定要有odom的tf
use_nav_sat = false,-- 是否使用gps
use_landmarks = false,-- 是否使用landmark
--num_laser_scans、num_multi_echo_laser_scans、num_point_clouds三者不能同时为0
num_laser_scans = 0, -- 是否使用单线激光数据并设置订阅topic的数量
num_multi_echo_laser_scans = 1,-- 是否使用multi_echo_laser_scans数据
num_subdivisions_per_laser_scan = 10,-- 1帧数据被分成几次处理,一般为1
num_point_clouds = 0,-- 是否使用16线点云数据
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., --设置为0.1则表示每10帧数据使用1帧数据
odometry_sampling_ratio = 1.,
fixed_frame_pose_sampling_ratio = 1.,
imu_sampling_ratio = 1.,
landmarks_sampling_ratio = 1.,
}
--修改之前5个lua文件参数可以使用这种方式
MAP_BUILDER.use_trajectory_builder_2d = true
TRAJECTORY_BUILDER_2D.num_accumulated_range_data = 10
return options