自动驾驶(七十三)---------离散点计算曲率

       在自动驾驶中,很常见的一个问题是通过离散点计算曲率,奇怪的是网上居然找不到我需要的资料,也许是我描述的不对,总之找了很久都不是很满意,所以干脆自己来总结一下吧。

        网上也不是找不到资料,但是大部分都是这样:

         (1)通过曲率公式,首先你要知道曲线的表达式,然后代入公式计算。

         (2)离散点也需要先polyfit拟合成多项式,再利用上面的公式计算曲率。

         (3)在matlab中,用csape()对离散点进行Spline插值,然后用fnder()对得到曲线求导,最后用fnval()对导数求值即可。

         (4)通过标量公式,计算曲率。

         (5)三个点外接圆:自动驾驶(七十三)---------离散点计算曲率_第1张图片但是三个点计算,不好推广。

          总之以上的一些方法都不直接,拐弯抹角计算曲率,曲率直接理解就是角度变化率,近似对应于曲率半径的倒数,利用一串点鲁棒的计算对应的曲率就应该很简单才对,不要什么拟合多项式再代公式求曲率,简直是隔靴搔痒、舍本逐末。这里我总结一种直观的方法,抛砖引玉:

1. 离散点拟合圆

         曲率的倒数就是半径,那我先拟合圆,知道半径也就知道曲率了,圆的拟合可以使多个点,拟合也有足够的鲁棒性。

         用圆的展开公式:。圆心为,圆的半径就是 。

         误差方程为:        对于自变量a、b、c求偏导为0:

         得到: 为了直观和看代码方便,我们假设 

                   上式可以描述为:

          通过矩阵知识可以解出:


void FitCenterByLeastSquares(std::vector mapPoint, Point3D ¢erP, double &radius) {
    double sumX = 0, sumY = 0;
    double sumXX = 0, sumYY = 0, sumXY = 0;
    double sumXXX = 0, sumXXY = 0, sumXYY = 0, sumYYY = 0;

    int pCount = mapPoint.size();
    for (int i = 0; i

2. 计算正负号

        通过上面我们计算出圆的半径,倒数就是曲率,那么曲率的正负号呢?这里我们也需要一种方法优雅的计算它的正负号,不然有失风度,目前我能给出的方法是直线与圆心的关系:

        计算起始点与终点的直线,判断该直线与圆心的关系从而判断曲率的正负号,又因为前面已经计算了很多最小二乘法的中间变量,要是不用也可惜了,干脆拟合直线算了:

       类似的误差方程:    偏导为0得到:和   

       联立解方程得到:自动驾驶(七十三)---------离散点计算曲率_第2张图片      最后把圆心代入方程判断正负即可。

       这里给出新加的代码,只需要在原来的基础上只要加3行代码即可,基本上还算优雅吧:

    //计算曲率正负号
	a = (sumXY-((sumX*sumY)/pCount))/(sumXX-(sumX*sumX/pCount));
	b = (sumY-a*sumX)/pCount;
	centerP.z = (xCenter*a+b

        

你可能感兴趣的:(自动驾驶)