0.引言
校正由于运动引起的激光点云畸变。
点云去畸变的方法包括:
- 纯估计方法(ICP/VICP)
- 传感器辅助方法(IMU/ODOM)
- 融合的方法
这里学习的也是传感器辅助方法。多余的也不再赘述,自己理一下几个坐标关系并做记录。
1.理解几个坐标系的关系
畸变产生的原因如图所示,自己理解也是基于这张图进行理解。
图片来源
这个坐标系关系和后续的代码相对应。
通过线性插值,计算补偿矩阵的原理:
雷达扫描一帧的时间是固定的,通过计算得到每个点的采集时刻,将所有点都统一到同一时刻,**假设选择每完成一帧扫描的结束时刻,**如图所示,直观的理解就是:
- 1.时间越靠近
t
k
t_k
tk? ,补偿矩阵越近似于
T
k
+
1
,
k
T_{k+1,k}
Tk+1,k?
- 2.时间越靠近
t
k
+
1
t_{k+1}
tk+1? ,补偿矩阵越接近于单位阵,就是不需要补偿
T
i
=
t
k
+
1
?
t
i
t
k
+
1
?
t
k
T
k
+
1
,
k
T^{i}=\frac{t_{k+1}-t_{i}}{t_{k+1}-t_{k}} T_{k+1, k}
Ti=tk+1??tk?tk+1??ti??Tk+1,k?
最后将相应的点云乘上补偿矩阵即可。
2.代码阅读
void LidarMotionCompensation(Transform &extr, LoaderPointcloudPtr org_pc,
PointCloudXYZNPtr comp_pc, double min_time,
double max_time, Transform &start_pose,
Transform &end_pose) {
Transform start_lidar_pose = start_pose * extr;
Transform end_lidar_pose = end_pose * extr;
Transform relative_pose = end_lidar_pose.inverse() * start_lidar_pose;
Eigen::Vector3f relative_tran = relative_pose.translation_;
Eigen::Quaternionf relative_quat = relative_pose.rotation_;
pcl::PointCloud<pcl::PointXYZ>::Ptr temp_pc(
new pcl::PointCloud<pcl::PointXYZ>());
double time_range = max_time - min_time;
for (int i = 0; i < org_pc->size(); i++) {
auto point = org_pc->points[i];
double ratio = (max_time - point.timestamp) / time_range;
Eigen::Quaternionf identity_;
identity_.setIdentity();
Eigen::Affine3f trans(identity_.slerp(ratio, relative_quat));
trans.translation() = ratio * relative_tran;
Eigen::Vector3f pt(point.x, point.y, point.z);
Eigen::Vector3f comp_pt = pt;
if (max_time - min_time > 1e-3) {
comp_pt = trans * pt;
std::cout << "trans the point" << std::endl;
}
if (std::isnan(comp_pt[0]) || std::isnan(comp_pt[1]) ||
std::isnan(comp_pt[2]))
continue;
pcl::PointXYZ pc;
pc.x = comp_pt[0];
pc.y = comp_pt[1];
pc.z = comp_pt[2];
temp_pc->points.push_back(pc);
}
pcl::NormalEstimationOMP<pcl::PointXYZ, PointXYZN> norm_est;
pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(
new pcl::search::KdTree<pcl::PointXYZ>());
norm_est.setNumberOfThreads(8);
norm_est.setInputCloud(temp_pc);
norm_est.setSearchMethod(kdtree);
norm_est.setKSearch(20);
norm_est.compute(*comp_pc);
}
|