eigen中SplineFitting得到的都是nan
今天打算用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,发现,有如下这样一段话:
所以我怀疑是不是因为这个方法的数值稳定性不够,导致出现大量nan。我改用了FullPibHouseholderQR,果然可以了。看来就是数值稳定性的问题。
根据官网的介绍,这三种QR的方法,速度上 HouseholderQR >ColPivHouseholderQR>FullPivHouseholderQR,数值稳定性则反之。
考虑到数值稳定性也和数值范围有关,我将输入数据都除以了1000,再使用HouseholderQR,果然也没出现nan的状况了。