接口具体为:
std::unique_ptr<LocalTrajectoryBuilder3D::MatchingResult> LocalTrajectoryBuilder3D::AddRangeData( const std::string& sensor_id, const sensor::TimedPointCloudData& unsynchronized_data) { ... }输入:激光雷达的传感器ID,未时间同步的激光点云原始数据; 输出:submap坐标系下的匹配定位结果。 此处为local(局部坐标系)下对激光原始数据进行处理和前端匹配定位的入口。主要分为以下6个部分内容:
how ?待完善:
auto synchronized_data = range_data_collator_.AddRangeData(sensor_id, unsynchronized_data); if (synchronized_data.ranges.empty()) { LOG(INFO) << "Range data collator filling buffer."; return nullptr; }此处得到每个点云的pos是为了补偿在激光扫描360度(20Hz的话一圈就是50ms)的过程中机器人会产生运动,这会对激光点云产生影响,基于此pos可以消除扫描过程中运动对激光扫描的影响。
std::vector<transform::Rigid3f> hits_poses; hits_poses.reserve(hits.size()); bool warned = false; for (const auto& hit : hits) { common::Time time_point = time + common::FromSeconds(hit.point_time[3]); 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(); } hits_poses.push_back( extrapolator_->ExtrapolatePose(time_point).cast<float>()); }点云距离的计算根据local系下的当前点云坐标与origin点云坐标求模得到。
if (num_accumulated_ == 0) { // 'accumulated_range_data_.origin' is not used. accumulated_range_data_ = sensor::RangeData{{}, {}, {}}; } for (size_t i = 0; i < hits.size(); ++i) { const Eigen::Vector3f hit_in_local = hits_poses[i] * hits[i].point_time.head<3>(); const Eigen::Vector3f origin_in_local = hits_poses[i] * synchronized_data.origins.at(hits[i].origin_index); const Eigen::Vector3f delta = hit_in_local - 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 { // We insert a ray cropped to 'max_range' as a miss for hits beyond the // maximum range. This way the free space up to the maximum range will // be updated. accumulated_range_data_.misses.push_back( origin_in_local + options_.max_range() / range * delta); } } } ++num_accumulated_;这里的当前pos指的是时间为time时的机器人位姿,也就是激光雷达帧初始和IMU数据对齐时刻的位姿,后面扫描的点云时间以此为基准。基于第4)步得到的位姿可以将扫描过程中的运动引起的激光点云坐标变化补偿掉。将所有的激光点云转换为初始origin点下无运动影响的local系下的点云坐标accumulated_range_data_(但是还没有转换到激光时间对齐时刻time下的local系)。
transform::Rigid3f current_pose = extrapolator_->ExtrapolatePose(time).cast<float>(); const sensor::RangeData filtered_range_data = { current_pose.translation(), sensor::VoxelFilter(options_.voxel_filter_size()) .Filter(accumulated_range_data_.returns), sensor::VoxelFilter(options_.voxel_filter_size()) .Filter(accumulated_range_data_.misses)};传入的时候同时基于同步时刻time的pos位姿矩阵将激光点云的数据变换到Time时刻local坐标系下。
return AddAccumulatedRangeData( time, sensor::TransformRangeData(filtered_range_data, current_pose.inverse()));