cartographer 代码思想解读(9)- 激光雷达畸变矫正

cartographer 代码思想解读(9)- 激光雷达畸变矫正


本节为cartographer前端匹配算法中最后一个核心算法实现内容,下节将会这9节内容串起来构成cartographer中2dslam的前端总体接口local_trajectory_builder_2d类。此节激光矫正具体实现就是在local_trajectory_builder_2d实现的,单独列出来进行分析。是因为至今我使用的SLAM从未进行过矫正考虑,是因为室内机器人速度较低,同时雷达采用性能较好雷达,则可做简单的假设,认为影响较少。但是机器人运行速度较快时,则必须考虑畸变问题。
激光雷达为什么会产生畸变,原因是激光雷达获取的360度或270度的激光光束距离,并非瞬间同步完成的。目前采用的激光雷达大多数是旋转雷达,通过一反光镜高速旋转,向四周进行测距,因此每一帧激光点云中相邻的光束点存在时间间隔measure time。如此一圈360度,若一圈共测量360个点(即一度一个点),则第一个光束测得距离和最后一个获取的时间差将会为 360×measure time。因此当机器人在运动时获得一帧激光点云,第一个点和最后一点实际对应的激光原点坐标将不一致,故导致激光点云畸变。若机器人运行速度越快,则畸变越为严重。

cartographer采用的校准方法是采用前面分析的位姿估计器,可以估计出每时刻的线速度和角速度,因此得出每时刻的位置变换,通过点云中每个点的时间戳,获取其原点位置进行转换校准。

 // 开辟一个新的vector存储所有当前雷达传感器点云每个点对应的位置信息,其位置信息由估计器预测而来
  std::vector<transform::Rigid3f> range_data_poses;
  range_data_poses.reserve(synchronized_data.ranges.size());
  bool warned = false;
  for (const auto& range : synchronized_data.ranges) {
    common::Time time_point = time + common::FromSeconds(range.point_time.time);
    // 遍历每一个点云点的时间戳,理论上应晚于估计器上刻位置时间戳,否则说明传感器采集时间错误
    if (time_point < extrapolator_->GetLastExtrapolatedTime()) {
      if (!warned) {
        LOG(ERROR)
            << "Timestamp of individual range data point jumps backwards from "
            << extrapolator_->GetLastExtrapolatedTime() << " to " << time_point;
        warned = true;
      }
      //
      time_point = extrapolator_->GetLastExtrapolatedTime();
    }
    // 根据每个点的时间戳估计点云点对应的位置并进行缓存
    range_data_poses.push_back(
        extrapolator_->ExtrapolatePose(time_point).cast<float>());
  }

上面代码则是获取点云中每个点的时间戳,并且估计其原点的位置并放入缓存中;

  for (size_t i = 0; i < synchronized_data.ranges.size(); ++i) {
    // 提取每一个点云点的pose(包含时间戳)
    const sensor::TimedRangefinderPoint& hit =
        synchronized_data.ranges[i].point_time;
    // 提取此点云对应的原点坐标pose,并进行畸变矫正
    const Eigen::Vector3f origin_in_local =
        range_data_poses[i] *
        synchronized_data.origins.at(synchronized_data.ranges[i].origin_index);
    // 对此点进行畸变矫正,并转换为pose,不包含时间戳
    sensor::RangefinderPoint hit_in_local =
        range_data_poses[i] * sensor::ToRangefinderPoint(hit);
    // 计算点到原点距离
    const Eigen::Vector3f delta = hit_in_local.position - origin_in_local;
    const float range = delta.norm();
    // 距离满足一定范围内保留,否则丢弃
    if (range >= options_.min_range()) {
      if (range <= options_.max_range()) {
        accumulated_range_data_.returns.push_back(hit_in_local);
      } else {
        // 超出设置最远距离,则放入miss队列中,并且距离全部调整为配置值
        hit_in_local.position =
            origin_in_local +
            options_.missing_data_ray_length() / range * delta;
        accumulated_range_data_.misses.push_back(hit_in_local);
      }
    }
  }

上面代码遍历每个点,计算校准后的点云;

简单总结:
畸变基本步骤:
1.获取每一帧点云每个点的时间戳;
2.代入估计器估计出每个原点时间戳的位置;
3.将每个点对应估计的原点坐标进行转换至世界坐标系;
注意:
在做畸变校准时,需要注意激光雷达旋转方向,考虑时间间隔递增的方向,否则结果会更加不准确;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值