Cartographer前端之real_time_correlative_scan_matcher_2d

cartographer的几个scanmatcher这里说的蛮好的,但是real_time_correlative_scan_matcher这是没有用到高/低分辨率地图以及分支定界算法的。(也可能是我没看明白)

先看一下这个文档!!!!!!!!

Real-Time Correlative Scan Matching完全解析(CSM帧匹配算法)

总的来说 real_time_correlative_scan_matcher 就是给定先验位置、点云、概率地图、搜索边界然后打散点通过概率地图的得分和再获取最大和然后输出得分最大的位姿。

1、准备知识介绍

  • 概率栅格图
    占据栅格图(occupancy grid map),就是利用了栅格化的思路,将障碍物在地图中以占据栅格进行表示。概率越高,说明该位置很有可能有障碍物;相反概率越低,也就意味着该位置很可能是空的。下面两图分别表示占据栅格图局部示意、以及整张地图。

 

 

2、Real Time 匹配算法综述

  • 激光打到障碍物才返回,也就是说当前激光数据可以很好的反应出当前车辆附近障碍物的轮廓。
  • 在这里插入图片描述
  • 通过激光扫描到的轮廓,和上面栅格图进行对比,通过最佳匹配位置找到机器人的位姿。
  • 如何找到最佳匹配位置了。
    1、在设定的初始位置,在窗口范围内搜索,提取出每个候选位姿。
    2、计算出每个候选位姿下,点云打在栅格图上面的概率,计算其和。
    3、概率和最大的候选位姿,就为所要寻找的最佳位姿。

 3、代码详解

具体的部分只贴下面一段 Match的代码

double RealTimeCorrelativeScanMatcher2D::Match(
  const transform::Rigid2d& initial_pose_estimate, const sensor::PointCloud& point_cloud, const Grid2D& grid, transform::Rigid2d* pose_estimate) const
{
  CHECK(pose_estimate != nullptr);

  const Eigen::Rotation2Dd initial_rotation    = initial_pose_estimate.rotation();  // 获取机器人初始位姿
  const sensor::PointCloud rotated_point_cloud = sensor::TransformPointCloud(
    point_cloud,
    transform::Rigid3f::Rotation(Eigen::AngleAxisf(
                                   initial_rotation.cast<float>().angle(), Eigen::Vector3f::UnitZ())));
  const SearchParameters search_parameters(
    options_.linear_search_window(), options_.angular_search_window(),
    rotated_point_cloud, grid.limits().resolution());

  const std::vector<sensor::PointCloud> rotated_scans =
    GenerateRotatedScans(rotated_point_cloud, search_parameters);
  const std::vector<DiscreteScan2D> discrete_scans = DiscretizeScans(
    grid.limits(), rotated_scans,
    Eigen::Translation2f(initial_pose_estimate.translation().x(),
                         initial_pose_estimate.translation().y()));
  // 初始化在xy平移空间内偏移量,即窗口大小和偏移量
  // 获取整个搜索空间的候选解
  std::vector<Candidate2D> candidates =
    GenerateExhaustiveSearchCandidates(search_parameters);
  // 对所有候选解打分
  ScoreCandidates(grid, discrete_scans, search_parameters, &candidates);
  // 找到得分最大的候选解
  const Candidate2D& best_candidate =
    *std::max_element(candidates.begin(), candidates.end());
  // 输出优化得到的位姿
  *pose_estimate = transform::Rigid2d(
    {initial_pose_estimate.translation().x() + best_candidate.x,
     initial_pose_estimate.translation().y() + best_candidate.y},
    initial_rotation * Eigen::Rotation2Dd(best_candidate.orientation));
  return best_candidate.score;
}

上面函数的有一下两个主要逻辑:
1、GenerateExhaustiveSearchTransforms:创建搜索空间,也就是说在一定范围内,等间隔划分搜索位置,这所有搜索位置的集合为搜索空间。
2、ScoreCandidate:最佳位置,应该出现在上面搜索空间中的某一个搜索位置。该函数的目的就是,对搜索空间中的所有搜索位置进行打分,找出打分最高的,就认为是最佳位置。

下面详细看这两个函数的代码,了解其细节

std::vector<transform::Rigid3f>
RealTimeCorrelativeScanMatcher::GenerateExhaustiveSearchTransforms(
    const float resolution, const sensor::PointCloud& point_cloud) const {
  std::vector<transform::Rigid3f> result;
  //线性搜索步长=线性搜索距离(x,y,z方向)÷ 分辨率(每个格子的长度)
  const int linear_window_size =  
      common::RoundToInt(options_.linear_search_window() / resolution);
  // We set this value to something on the order of resolution to make sure that
  // the std::acos() below is defined.
  float max_scan_range = 3.f * resolution;
  for (const Eigen::Vector3f& point : point_cloud) {
    const float range = point.norm();
    max_scan_range = std::max(range, max_scan_range);
  }
  const float kSafetyMargin = 1.f - 1e-3f;
  const float angular_step_size =  //采用余弦定理计算角度步长,具体理解见下面图片。
      kSafetyMargin * std::acos(1.f - common::Pow2(resolution) /
                                          (2.f * common::Pow2(max_scan_range)));
  const int angular_window_size =
      common::RoundToInt(options_.angular_search_window() / angular_step_size);
  for (int z = -linear_window_size; z <= linear_window_size; ++z) {
    for (int y = -linear_window_size; y <= linear_window_size; ++y) {
      for (int x = -linear_window_size; x <= linear_window_size; ++x) {
        for (int rz = -angular_window_size; rz <= angular_window_size; ++rz) {
          for (int ry = -angular_window_size; ry <= angular_window_size; ++ry) {
            for (int rx = -angular_window_size; rx <= angular_window_size;
                 ++rx) {
              const Eigen::Vector3f angle_axis(rx * angular_step_size,
                                               ry * angular_step_size,
                                               rz * angular_step_size);
              result.emplace_back(
                  Eigen::Vector3f(x * resolution, y * resolution,
                                  z * resolution),
                  transform::AngleAxisVectorToRotationQuaternion(angle_axis));
            }
          }
        }
      }
    }
  }
  return result;
}

角度步长angular_step_size的计算如下:

 \cos \theta =1-\frac{r^{2}}{2dmax^{2}}

  • 对候选位置进行打分:ScoreCandidate
float RealTimeCorrelativeScanMatcher::ScoreCandidate(
    const HybridGrid& hybrid_grid,
    const sensor::PointCloud& transformed_point_cloud,
    const transform::Rigid3f& transform) const {
  float score = 0.f;
  //获得每个point,在概率栅格图hybrid_grid上面的概率score, 求和,然后求平均。
  for (const Eigen::Vector3f& point : transformed_point_cloud) {
    score += hybrid_grid.GetProbability(hybrid_grid.GetCellIndex(point));
  }
  score /= static_cast<float>(transformed_point_cloud.size());
  const float angle = transform::GetAngle(transform);
  //求得的分值score,要乘以对应的权重。候选位置的平移量translation,旋转量angle越大,
  //说明越偏离初始值,可靠性越差,对应的权重就越小。
  score *=
      std::exp(-common::Pow2(transform.translation().norm() *
                                 options_.translation_delta_cost_weight() +
                             angle * options_.rotation_delta_cost_weight()));
  CHECK_GT(score, 0.f);
  return score;
}

从这段看目前没看到高/低分辨率地图、分支定界这块(应该是在ceres_scan_matcher这里,也就是说第一个超链接讲的范围不太对),实际是暴力匹配。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是使用Cartographer定位和Move_base导航的参数配置: 1. Cartographer参数配置: 在使用Cartographer进行定位时,需要进行以下参数配置: - 地图加载:在Cartographer的配置文件中,需要指定地图文件的路径和名称。可以使用以下命令加载地图文件: ``` roslaunch cartographer_ros my_robot.launch bag_filename:=/home/user/bag_file.bag ``` - 传感器配置:需要根据机器人使用的传感器类型进行相应的配置。例如,配置激光雷达的角度分辨率、最大扫描距离等参数。 - 坐标系配置:需要设置Cartographer使用的坐标系,以及与机器人的坐标系之间的转换关系。 - 位姿估计配置:需要设置Cartographer使用的位姿估计算法,以及相应的参数。 2. Move_base参数配置: 在使用Move_base进行导航时,需要进行以下参数配置: - 全局规划器参数:需要设置全局规划器使用的算法类型、地图分辨率、规划器在地图中搜索的范围等参数。 - 局部规划器参数:需要设置局部规划器使用的算法类型、机器人的最大速度、最大加速度等参数。 - 路径跟踪控制器参数:需要设置路径跟踪控制器使用的算法类型、机器人的最大速度、最大加速度等参数。 - costmap参数:需要设置costmap使用的参数,如地图分辨率、障碍物半径、机器人轮廓等。 以上是参数配置的一些基本内容,具体参数配置可能会因机器人类型、环境等因素而有所不同。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值