今天打算用b样条曲线来对一些点云数据做平滑操作。使用的是egien库中的SplineFitting类和Spline类。

这两个类的文档见:http://eigen.tuxfamily.org/dox-devel/unsupported/structEigen_1_1SplineFitting.html

void do_spline_smooth(vector<PointXYZ>& data)
{
	Eigen::Matrix3Xf m;
	m.resize(3, data.size());
	for (int i = 0; i < data.size(); i++)
	{
		m(0, i) = data[i].x;
		m(1, i) = data[i].y;
		m(2, i) = data[i].z;
	}
	Eigen::Spline3f s = Eigen::SplineFitting<Eigen::Spline3f>::Interpolate(m, 7);
	data.clear();
	for (float i = 0; i <= 1; i += 1. / 200)
	{
		auto d = s(i);
		data.emplace_back(d[0], d[1], d[2]);
	}
}

代码如上,就是把一组点通过b样条拟合再重采样。但是第一次用的时候遇到了个问题,就是得到的数据都是float类型的nan(not a number)。这里我的输入的点云数值范围大概在(950,500,500)左右

经过一下午加上晚上的调试,我终于明白是因为eigen在 Eigen::SplineFitting<Eigen::Spline3f>::Interpolate 这个函数中,由如下一段代码

    HouseholderQR<MatrixType> qr(A);

    // Here, we are creating a temporary due to an Eigen issue.
    ControlPointVectorType ctrls = qr.solve(MatrixType(pts.transpose())).transpose();

问题就出在这个 HouseholderQR 类中。根据我的调试, qr.solve 返回的结果中就出现了很多nan。

查找这个类的文档,http://eigen.tuxfamily.org/dox/classEigen_1_1HouseholderQR.html,发现,有如下这样一段话:

This Householder QR decomposition is faster, but less numerically stable and less feature-full than FullPivHouseholderQR or ColPivHouseholderQR.

所以我怀疑是不是因为这个方法的数值稳定性不够,导致出现大量nan。我改用了FullPibHouseholderQR,果然可以了。看来就是数值稳定性的问题。

根据官网的介绍,这三种QR的方法,速度上 HouseholderQR >ColPivHouseholderQR>FullPivHouseholderQR,数值稳定性则反之。

考虑到数值稳定性也和数值范围有关,我将输入数据都除以了1000,再使用HouseholderQR,果然也没出现nan的状况了。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注