PCL:激光点云车道线检测及最小二乘法拟合

PCL:激光点云车道线检测及最小二乘法拟合


目前已经将车道线的最小二乘拟合及配合rviz可视化实现了。

数学部分

补充:拟合的数学模型是直线一般式

当x1≠x2,y1≠y2时,直线的斜率k=(y2-y1)/(x2-x1)
故直线方程为y-y1=(y2-y1)/(x2-x1)×(x-x1)
即x2y-x1y-x2y1+x1y1=(y2-y1)x-x1(y2-y1)(y2-y1)x-(x2-x1)y-x1(y2-y1)+(x2-x1)y1=0(y2-y1)x+(x1-x2)y+x2y1-x1y2=0 ①
可以发现,当x1=x2或y1=y2时,①式仍然成立。所以直线AX+BY+C=0的一般式方程就是:
A = Y2 - Y1
B = X1 - X2
C = X2*Y1 - X1*Y2

对于一元二次多项式,可以转换为线性方程组求解,我们一般写成矩阵形式 Ax = y。
在这里插入图片描述

Ax = y非一致方程和一致方程的求解
一致与非一致方程

    一致方程是指Ax = y有至少一个解
    非一致方程指Ax = y没有解

Ax = y求解

    如果A是满秩的方阵,则x = inv(A)*y

    如果A不是方阵,但是是行满秩或者列满秩,那么解为A的伪逆乘以y

    如果A是秩亏的,那么A的解为A的广义逆乘以y

实际上广义逆包括逆、伪逆,广义逆又称为:Moore-Penrose逆矩阵,所以Ax = y的解可以统一为A 的Moore-Penrose逆矩阵乘以y,特别的是,对于一致性方程,该解为最小范数解,对于非一致方程,该解为最小范数最小二乘解

Moore-Penrose逆矩阵
在这里插入图片描述

代码实现

// 拟合求系数
void line_fitting(pcl::PointCloud<pcl::PointXYZ>::Ptr &in_cloud, double &a, double&b, double&c)
{
	vector<double>x, y;
	int num = in_cloud->size();
	for (int i = 0; i < num; i++)
	{
		pcl::PointXYZ p = in_cloud->at(i);
		x.push_back(p.x);
		y.push_back(p.y);
	}
	MatrixXd A(3, 3), B(3, 1), Y(3, 1);
	double A01(0), A02(0), A12(0), A22(0), B00(0), B10(0), B12(0);
	for (int i=0; i<num; i++)
	{
		A01 += x[i];
		A02 += x[i] * x[i];
		A12 += x[i] * x[i] * x[i];
		A22 += x[i] * x[i] * x[i] * x[i];
		B00 += y[i];
		B10 += x[i] * y[i];
		B12 += x[i] * x[i] * y[i];
	}
	A << num, A01, A02;
		 A01, A02, A12;
		 A02, A12, A22;
	B << B00,
		 B10,
		 B12;
	Y = A.inverse() * B;
	a = Y(2, 0);
	b = Y(1, 0);
	c = Y(0, 0);
}
// rviz
void line_fitting_show(pcl::PointCloud<pcl::PointXYZ>::Ptr &in_cloud, visualization_msgs::Marker &line, double a0, double a1, double a2;
{
	pcl::PointXYZ min, max;
	line.lifetime = ros::Buration(0.3);
	line.type = visualization_msgs::Marker::LINE_STRIP;
	line.action = visualization_msgs::Marker::ADD;
	line.ns = "lane";
	line.id = 0;
	line.scale.x = 0.2;
	line.color.g = 1;
	line.color.a = 1;
	line.pose.orientation.w = 1;
	pcl::getMinMax3D(*in_cloud, min, max);
	float x_min = min.x;
	float x_max = max.x;
	vector<double> xx, yy;
	double step = 0.5;
	int step_num = std::ceil((x_max - x_min) /step);
	forint i = 0; i < step_num + 2; i++)
	{
		double tmp_value = x_min + i * step;
		if (tmp_value > x_max)
		{
			tmp_value = x_max;
		}
		xx.push_back(tmp_value);
		geometry_msgs::Point p;
		p.x = tmp_value;
		p.y = a0 + a1*xx[i] + a2*xx[i]*xx[i];
		p.z = min.z;
		line.points.push_back(p);
	}
}
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ywfwyht

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值