当前位姿与上一次位姿做差,计算做累计角度偏差和位移偏差。利用激光雷达测得距离做得分处理。非首帧调用scanMatch,upDateTreeWeight,resample。首帧则调用invalidActiveArea,computeActiveArea,registerScan。
第1部分
1 | bool GridSlamProcessor::processScan(const RangeReading & reading, int adaptParticles) |
ScanMatcher 构造函数
1 | ScanMatcher::ScanMatcher(): m_laserPose(0,0,0) |
全是参数赋值,但是全写死,不能通过ROS修改
drawFromMotion 里程计运动模型
- p 表示粒子估计的最优位置(机器人上一个时刻的最优位置)
- pnew 表示里程计算出来的新的位置
- pold 表示建图引擎记录的上一时刻的位姿(即上一个里程计的位置)
不是执行圆加运算,pnew和pold只是用于产生噪声控制量,然后加到p上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24OrientedPoint
MotionModel::drawFromMotion(const OrientedPoint& p, const OrientedPoint& pnew, const OrientedPoint& pold) const
{
double sxy=0.3*srr;
// 计算出pnew 相对于 pold走了多少距离,得到控制量
// 这里的距离表达是相对于车身坐标系来说的
OrientedPoint delta=absoluteDifference(pnew, pold);
/*初始化一个点*/
OrientedPoint noisypoint(delta);
/*走过的三个方向的距离,为控制量添加上噪声项*/
noisypoint.x+=sampleGaussian(srr*fabs(delta.x)+str*fabs(delta.theta)+sxy*fabs(delta.y));
noisypoint.y+=sampleGaussian(srr*fabs(delta.y)+str*fabs(delta.theta)+sxy*fabs(delta.x));
noisypoint.theta+=sampleGaussian(stt*fabs(delta.theta)+srt*sqrt(delta.x*delta.x+delta.y*delta.y));
/*限制角度的范围为 -π~π */
noisypoint.theta=fmod(noisypoint.theta, 2*M_PI);
if (noisypoint.theta>M_PI)
noisypoint.theta-=2*M_PI;
/*把加入了噪声的控制量 加到粒子估计的最优的位置上,得到新的粒子位姿的预估(根据运动模型推算)*/
return absoluteSum(p,noisypoint);
}
这里的MotionModel是一个十分粗糙的运动模型,只是简单的矢量加减运算。 相比于《Probabilistic Robotics》
中提到的速度模型和里程计模型而言,有很多方面都没有考虑,精度上可能有折扣。
第2部分 if中的处理激光数据
1 | last_update_time_ = reading.getTime(); |