170 lines
5.0 KiB
C++
170 lines
5.0 KiB
C++
/* ----------------------------------------------------------------------------
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
* Atlanta, Georgia 30332-0415
|
|
* All Rights Reserved
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
* See LICENSE for the license information
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
* @file TSAMFactors.h
|
|
* @brief TSAM 1 Factors, simpler than the hierarchical TSAM 2
|
|
* @author Frank Dellaert
|
|
* @date May 2014
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <gtsam/geometry/Pose2.h>
|
|
#include <gtsam/nonlinear/NonlinearFactor.h>
|
|
|
|
namespace gtsam {
|
|
|
|
/**
|
|
* DeltaFactor: relative 2D measurement between Pose2 and Point2
|
|
*/
|
|
class DeltaFactor: public NoiseModelFactorN<Pose2, Point2> {
|
|
|
|
public:
|
|
typedef DeltaFactor This;
|
|
typedef NoiseModelFactorN<Pose2, Point2> Base;
|
|
typedef std::shared_ptr<This> shared_ptr;
|
|
|
|
private:
|
|
Point2 measured_; ///< the measurement
|
|
|
|
public:
|
|
|
|
// Provide access to the Matrix& version of evaluateError:
|
|
using Base::evaluateError;
|
|
|
|
/// Constructor
|
|
DeltaFactor(Key i, Key j, const Point2& measured,
|
|
const SharedNoiseModel& model) :
|
|
Base(model, i, j), measured_(measured) {
|
|
}
|
|
|
|
/// Evaluate measurement error h(x)-z
|
|
Vector evaluateError(const Pose2& pose, const Point2& point,
|
|
OptionalMatrixType H1, OptionalMatrixType H2) const override {
|
|
return pose.transformTo(point, H1, H2) - measured_;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* DeltaFactorBase: relative 2D measurement between Pose2 and Point2, with Basenodes
|
|
*/
|
|
class DeltaFactorBase: public NoiseModelFactorN<Pose2, Pose2, Pose2, Point2> {
|
|
|
|
public:
|
|
typedef DeltaFactorBase This;
|
|
typedef NoiseModelFactorN<Pose2, Pose2, Pose2, Point2> Base;
|
|
typedef std::shared_ptr<This> shared_ptr;
|
|
|
|
private:
|
|
Point2 measured_; ///< the measurement
|
|
|
|
public:
|
|
|
|
// Provide access to the Matrix& version of evaluateError:
|
|
using Base::evaluateError;
|
|
|
|
/// Constructor
|
|
DeltaFactorBase(Key b1, Key i, Key b2, Key j, const Point2& measured,
|
|
const SharedNoiseModel& model) :
|
|
Base(model, b1, i, b2, j), measured_(measured) {
|
|
}
|
|
|
|
/// Evaluate measurement error h(x)-z
|
|
Vector evaluateError(const Pose2& base1, const Pose2& pose,
|
|
const Pose2& base2, const Point2& point, //
|
|
OptionalMatrixType H1, OptionalMatrixType H2, //
|
|
OptionalMatrixType H3, OptionalMatrixType H4) const override {
|
|
if (H1 || H2 || H3 || H4) {
|
|
// TODO use fixed-size matrices
|
|
Matrix D_pose_g_base1, D_pose_g_pose;
|
|
Pose2 pose_g = base1.compose(pose, D_pose_g_base1, D_pose_g_pose);
|
|
Matrix D_point_g_base2, D_point_g_point;
|
|
Point2 point_g = base2.transformFrom(point, D_point_g_base2,
|
|
D_point_g_point);
|
|
Matrix D_e_pose_g, D_e_point_g;
|
|
Point2 d = pose_g.transformTo(point_g, D_e_pose_g, D_e_point_g);
|
|
if (H1)
|
|
*H1 = D_e_pose_g * D_pose_g_base1;
|
|
if (H2)
|
|
*H2 = D_e_pose_g * D_pose_g_pose;
|
|
if (H3)
|
|
*H3 = D_e_point_g * D_point_g_base2;
|
|
if (H4)
|
|
*H4 = D_e_point_g * D_point_g_point;
|
|
return d - measured_;
|
|
} else {
|
|
Pose2 pose_g = base1.compose(pose);
|
|
Point2 point_g = base2.transformFrom(point);
|
|
Point2 d = pose_g.transformTo(point_g);
|
|
return d - measured_;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* OdometryFactorBase: Pose2 odometry, with Basenodes
|
|
*/
|
|
class OdometryFactorBase: public NoiseModelFactorN<Pose2, Pose2, Pose2, Pose2> {
|
|
|
|
public:
|
|
typedef OdometryFactorBase This;
|
|
typedef NoiseModelFactorN<Pose2, Pose2, Pose2, Pose2> Base;
|
|
typedef std::shared_ptr<This> shared_ptr;
|
|
|
|
private:
|
|
Pose2 measured_; ///< the measurement
|
|
|
|
public:
|
|
|
|
// Provide access to the Matrix& version of evaluateError:
|
|
using Base::evaluateError;
|
|
|
|
/// Constructor
|
|
OdometryFactorBase(Key b1, Key i, Key b2, Key j, const Pose2& measured,
|
|
const SharedNoiseModel& model) :
|
|
Base(model, b1, i, b2, j), measured_(measured) {
|
|
}
|
|
|
|
/// Evaluate measurement error h(x)-z
|
|
Vector evaluateError(const Pose2& base1, const Pose2& pose1,
|
|
const Pose2& base2, const Pose2& pose2,
|
|
OptionalMatrixType H1, OptionalMatrixType H2,
|
|
OptionalMatrixType H3, OptionalMatrixType H4) const override {
|
|
if (H1 || H2 || H3 || H4) {
|
|
// TODO use fixed-size matrices
|
|
Matrix D_pose1_g_base1, D_pose1_g_pose1;
|
|
Pose2 pose1_g = base1.compose(pose1, D_pose1_g_base1, D_pose1_g_pose1);
|
|
Matrix D_pose2_g_base2, D_pose2_g_pose2;
|
|
Pose2 pose2_g = base2.compose(pose2, D_pose2_g_base2, D_pose2_g_pose2);
|
|
Matrix D_e_pose1_g, D_e_pose2_g;
|
|
Pose2 d = pose1_g.between(pose2_g, D_e_pose1_g, D_e_pose2_g);
|
|
if (H1)
|
|
*H1 = D_e_pose1_g * D_pose1_g_base1;
|
|
if (H2)
|
|
*H2 = D_e_pose1_g * D_pose1_g_pose1;
|
|
if (H3)
|
|
*H3 = D_e_pose2_g * D_pose2_g_base2;
|
|
if (H4)
|
|
*H4 = D_e_pose2_g * D_pose2_g_pose2;
|
|
return measured_.localCoordinates(d);
|
|
} else {
|
|
Pose2 pose1_g = base1.compose(pose1);
|
|
Pose2 pose2_g = base2.compose(pose2);
|
|
Pose2 d = pose1_g.between(pose2_g);
|
|
return measured_.localCoordinates(d);
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|
|
|