LeGO-LOAM_NOTED
LeGO-LOAM_NOTED copied to clipboard
TransformToStart
楼主,好多人都说TransformToStart这个函数是将当前点转换到上一帧坐标下,可是和强度有什么关系呢?为什么TransformToStart里面要先用intensity信息? 我用自己的包不用imu跑的过程中,由于有一个点的强度信息是nan,导致转换过之后点的xyz坐标都是nan,结果程序崩溃了。所以想问下TransformToStart具体是什么作用?
void TransformToStart(PointType const * const pi, PointType * const po)
{
float s = 10 * (pi->intensity - int(pi->intensity));
float rx = s * transformCur[0];
float ry = s * transformCur[1];
float rz = s * transformCur[2];
float tx = s * transformCur[3];
float ty = s * transformCur[4];
float tz = s * transformCur[5];
float x1 = cos(rz) * (pi->x - tx) + sin(rz) * (pi->y - ty);
float y1 = -sin(rz) * (pi->x - tx) + cos(rz) * (pi->y - ty);
float z1 = (pi->z - tz);
float x2 = x1;
float y2 = cos(rx) * y1 + sin(rx) * z1;
float z2 = -sin(rx) * y1 + cos(rx) * z1;
po->x = cos(ry) * x2 - sin(ry) * z2;
po->y = y2;
po->z = sin(ry) * x2 + cos(ry) * z2;
po->intensity = pi->intensity;
}
intensity中的整数部分存储的是点云所在的扫描线,小数部分存储的是该扫描线中一点相对于该扫描线起点的时间。具体在featureAssociation.cpp的adjustDistortion()函数中
float relTime = (ori - segInfo.startOrientation) / segInfo.orientationDiff;
point.intensity = int(segmentedCloud->points[i].intensity) + scanPeriod * relTime;
由于激光扫描一圈不是瞬时完成,所以采集到的数据相当于在不同坐标系下采集到的,也就是运动失真,而我们想要的是扫描一圈的点都是在同一坐标系下,消除运动失真前后的点云如下图,该图是LOAM论文中的。
TransformToStart就是采用线性插值的方法来消除这个运动失真,具体地,就是根据每个点相对该帧扫描的起始点的时间,得到它对应的旋转平移,从而将该点转换到该帧起始时刻的坐标系下。
intensity中的整数部分存储的是点云所在的扫描线,小数部分存储的是该扫描线中一点相对于该扫描线起点的时间。具体在featureAssociation.cpp的adjustDistortion()函数中
float relTime = (ori - segInfo.startOrientation) / segInfo.orientationDiff;
point.intensity = int(segmentedCloud->points[i].intensity) + scanPeriod * relTime;
由于激光扫描一圈不是瞬时完成,所以采集到的数据相当于在不同坐标系下采集到的,也就是运动失真,而我们想要的是扫描一圈的点都是在同一坐标系下,消除运动失真前后的点云如下图,该图是LOAM论文中的。TransformToStart就是采用线性插值的方法来消除这个运动失真,具体地,就是根据每个点相对该帧扫描的起始点的时间,得到它对应的旋转平移,从而将该点转换到该帧起始时刻的坐标系下。
我感觉你说的有点不对。 TransformToStart 应该是将当前scan转换到上一scan的坐标系下,然后在同一坐标系下,调用搜索查找最近点。