cartographer探秘第一章之安装编译与参数配置

第一步 安装与编译

具体的安装步骤参考官方文档即可,链接如下。值得注意的是,一定要确保每个步骤都安装成功,尤其是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
之后,再编译carographer_ros.
 
这步就和普通的ROS包的编译方式一样了,先新建工作空间,将cartographer_ros放进工作空间的src文件夹下,之后在工作空间中执行catkin_make即可完成cartographer_ros的编译.
 
 

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 的扫描匹配的最小二乘的公式推导。

由于本人正处于学习调研阶段,所以难免会有错误及疏漏,如果错误请指出,不胜感激!

 

 

  • 44
    点赞
  • 177
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
### 回答1: cartographer参数配置是指在进行地图绘制和制图过程中,根据具体需求对cartographer(地图绘制软件)进行设置和调整的过程。通过合理配置参数,可以达到更好的绘图效果和符合实际需求的地图制作。参数配置涉及到包括投影方式、坐标系统、地形高程、符号样式等多个方面。 首先,投影方式是参数配置中重要的一部分,可以选择不同的投影方式,比如等距圆柱投影、等面积投影、等角圆柱投影等,以适应实际应用需求。其次,坐标系统的选择也很关键,可以根据地图绘制的范围和精度选择合适的坐标系,如WGS84坐标系、Web墨卡托投影坐标系等。地形高程参数配置可以根据地理要素的高度信息进行设置,如山脉、高原、海洋等,可以使用等高线、渐变色等方式进行显示。符号样式的配置可以根据绘制目的和地图主题进行选择和调整,如图标、颜色、线型、填充样式等。 此外,还可以根据具体绘图需求进行更细致的参数配置。比如,地图比例尺、标注字体、注记位置、边框样式、图例等配置项。通过合理配置这些参数可以达到更好的地图效果和可视化效果。 总之,cartographer参数配置是地图绘制过程中的重要一环,通过合理设置各种参数可以制作出符合实际需求的地图,从而更好地展示和传达地理信息。 ### 回答2: Cartographer是谷歌开发的一种强大的SLAM算法,用于构建3D地图。在使用Cartographer进行参数配置时,可以根据具体的应用需求不同来进行相应的设置。 首先,可以调整Cartographer的传感器配置参数。这包括传感器的帧率、分辨率等参数。帧率设置越高,可以获得更多的数据,但也会增加处理数据的复杂度。分辨率可以根据需要进行调整,高分辨率可以获得更多细节,但也会占用更多的存储空间。 其次,需要对Cartograher的地面过滤器参数进行配置。地面过滤器可用于去除地面的杂乱数据,使地图更加准确。地面过滤器的参数设置包括地面点云高度阈值、地面点云最小点数等。这取决于实际地面的特征和要求。 另外,还可以配置Cartographer的回环检测参数。回环检测是指在建立地图过程中,检测到之前已经经过的地方,并将其与新观测的数据进行匹配,从而完善地图。回环检测参数的设置包括回环检测范围、回环关联的匹配阈值等。这些参数的设置直接影响到回环检测的准确性和效率。 最后,可以根据应用需求调整Cartograher的运行速度和精度之间的权衡参数。这些参数可以根据具体的情况进行调整,包括优化器迭代次数、点云配准的误差阈值等。通过调整这些参数,可以在满足实际应用需求的同时提高运行效率或提高地图的精度。 总之,Cartographer参数配置是一个根据具体应用需求进行调整的过程,通过合理配置参数,可以提高地图构建的准确性和效率,满足不同应用场景下的需求。 ### 回答3: cartographer是谷歌开发的一种用于构建实时二维或三维地图的SLAM(即时定位与地图构建)算法。该算法能够结合多个传感器的数据,如激光雷达和相机,来进行地图的构建和定位。 在使用cartographer时,有一些参数配置可以根据具体的应用场景进行调整,以达到更好的地图构建和定位效果。 其中一些重要的参数配置包括: 1. map_resolution(地图分辨率):该参数决定了地图中每个栅格的大小。较小的分辨率可以捕捉更多的细节,但会增加地图的大小和计算量。 2. num_submaps(子地图数量):cartographer将整个地图划分为多个子地图,该参数配置了子地图的数量。较大的值可以提高地图的准确性,但也会增加计算量。 3. submap_size(子地图大小):决定了每个子地图的尺寸。较大的尺寸可以包含更多的环境信息,但也会增加计算和存储开销。 4. scans_per_fog_update(每次迭代更新的扫描次数):用于控制每次迭代更新时使用的激光雷达扫描次数。较大的值可以提高地图的质量,但会增加计算开销。 5. matching_submaps_options(子地图匹配选项):用于配置子地图之间的匹配方式,如匹配窗口大小和难度。根据环境特点进行调整,可以提高地图匹配的准确性。 6. motion_filter_options(运动滤波器选项):用于筛选掉不符合运动规律的激光雷达数据点,以减少噪音和误差。根据传感器和环境特点进行调整,可以提高定位的准确性。 以上是一些常见的cartographer参数配置,根据具体的应用需求和环境特点,可以对这些参数进行调整,以达到更好的地图构建和定位效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值