在激光SLAM中使用gtsam加入地平面约束作为新的因子,用C++实现
时间: 2024-03-17 19:41:57 浏览: 277
在激光SLAM中使用gtsam加入地平面约束作为新的因子时,我们需要定义一个地平面约束因子类,并实现其evaluateError()和linearize()方法。
假设我们有一个地平面约束因子 $f$,它的观测值为 $z$,地平面法向量的估计值为 $n$,噪声模型为高斯分布 $\mathcal{N}(0, \Sigma)$。那么,地平面约束的残差函数 $e(z, n)$ 可以定义为:
$$
e(z, n) = z - n^T p
$$
其中,$p$ 是激光雷达扫描点的坐标,$n$ 是地平面法向量的估计值。
在C++中实现地平面约束因子类的代码如下:
```C++
#include <gtsam/geometry/Point3.h>
#include <gtsam/nonlinear/NonlinearFactor.h>
#include <gtsam/base/Vector.h>
#include <gtsam/base/Matrix.h>
#include <gtsam/base/Matrix.h>
#include <boost/make_shared.hpp>
class GroundPlaneFactor : public gtsam::NoiseModelFactor1<gtsam::Point3> {
public:
GroundPlaneFactor(const gtsam::Key& key, const gtsam::Point3& point, const gtsam::SharedNoiseModel& model)
: NoiseModelFactor1<gtsam::Point3>(model, key), point_(point) {}
virtual ~GroundPlaneFactor() {}
virtual gtsam::Vector evaluateError(const gtsam::Point3& n, boost::optional<gtsam::Matrix&> H = boost::none) const {
gtsam::Vector3 error;
double d = point_.dot(n);
error[0] = d - point_.x() * n.x() - point_.y() * n.y() - point_.z() * n.z();
if (H) {
*H = (gtsam::Matrix3() << -point_.x(), -point_.y(), -point_.z()).finished();
}
return error;
}
static boost::shared_ptr<GroundPlaneFactor> Create(const gtsam::Key& key, const gtsam::Point3& point, double sigma) {
gtsam::Matrix3 covariance = gtsam::Matrix3::Identity() * pow(sigma, 2);
gtsam::noiseModel::Gaussian::shared_ptr noise_model = gtsam::noiseModel::Gaussian::Covariance(covariance);
return boost::make_shared<GroundPlaneFactor>(key, point, noise_model);
}
private:
gtsam::Point3 point_;
};
```
上面的代码中,我们继承了gtsam::NoiseModelFactor1类,并重载了evaluateError()方法。在evaluateError()方法中,我们计算出当前地平面法向量的估计值 $n$ 对应的残差,并计算残差函数的一阶导数,返回一个Jacobian矩阵。在Create()方法中,我们定义了一个静态的工厂函数,用于创建GroundPlaneFactor类的对象,并设置噪声模型。
阅读全文