lego-loam featureAssociation 源码注释(五)补充
继续来看位姿优化:
void updateTransformation(){
if (laserCloudCornerLastNum < 10 || laserCloudSurfLastNum < 100)
return;
for (int iterCount1 = 0; iterCount1 < 25; iterCount1++) {
laserCloudOri->clear();
coeffSel->clear();
findCorrespondingSurfFeatures(iterCount1);
if (laserCloudOri->points.size() < 10)
continue;
if (calculateTransformationSurf(iterCount1) == false)
break;
}
for (int iterCount2 = 0; iterCount2 < 25; iterCount2++) {
laserCloudOri->clear();
coeffSel->clear();
findCorrespondingCornerFeatures(iterCount2);
if (laserCloudOri->points.size() < 10)
continue;
if (calculateTransformationCorner(iterCount2) == false)
break;
}
}
上一节中我们看过了findCorrespondingSurfFeatures和calculateTransformationSurf函数。
findCorrespondingCornerFeatures中求点到直线法向量的代码和findCorrespondingSurfFeatures求平面法向量有很大区别,所以我们详细介绍一下。然后calculateTransformationCorner由点到线特征的距离求雅可比来优化位姿的代码和calculateTransformationSurf类似,我们不多关注了:
!!!但是不要忘了lego-loam的一个特点:
对于面特征点,待优化的参数是俯仰角,横滚角以及高度,在lego-loam中面点均是地面点,所以x,y的变化对于面点优化无意义,同理偏航角也是如此,绕z轴旋转,对于面点也是变化极小。而线特征优化时,现实中存在x,y轴的变动,以及偏航角变化。所以,在lego-loam中是两阶段优化,面特征优化得到的是横滚角,俯仰角以及z轴偏移;而线特征优化得到的x轴偏移,y轴偏移以及偏航角。
求解点到直线法向量,以及点到直线距离:
if (pointSearchCornerInd2[i] >= 0) {
tripod1 = laserCloudCornerLast->points[pointSearchCornerInd1[i]];
tripod2 = laserCloudCornerLast->points[pointSearchCornerInd2[i]];
float x0 = pointSel.x;
float y0 = pointSel.y;
float z0 = pointSel.z;
float x1 = tripod1.x;
float y1 = tripod1.y;
float z1 = tripod1.z;
float x2 = tripod2.x;
float y2 = tripod2.y;
float z2 = tripod2.z;
float m11 = ((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1));
float m22 = ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1));
float m33 = ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1));
float a012 = sqrt(m11 * m11 + m22 * m22 + m33 * m33);
float l12 = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));
float la = ((y1 - y2)*m11 + (z1 - z2)*m22) / a012 / l12;
float lb = -((x1 - x2)*m11 - (z1 - z2)*m33) / a012 / l12;
float lc = -((x1 - x2)*m22 + (y1 - y2)*m33) / a012 / l12;
float ld2 = a012 / l12;
float s = 1;
if (iterCount >= 5) {
s = 1 - 1.8 * fabs(ld2);
}
if (s > 0.1 && ld2 != 0) {
coeff.x = s * la;
coeff.y = s * lb;
coeff.z = s * lc;
coeff.intensity = s * ld2;
laserCloudOri->push_back(cornerPointsSharp->points[i]);
coeffSel->push_back(coeff);
}
}