Define and partially specify Range and Bearing functors
parent
3bad6fea67
commit
03db69117a
20
gtsam.h
20
gtsam.h
|
@ -2272,20 +2272,16 @@ typedef gtsam::RangeFactor<gtsam::Pose2, gtsam::Point2> RangeFactorPosePoint2;
|
||||||
typedef gtsam::RangeFactor<gtsam::Pose3, gtsam::Point3> RangeFactorPosePoint3;
|
typedef gtsam::RangeFactor<gtsam::Pose3, gtsam::Point3> RangeFactorPosePoint3;
|
||||||
typedef gtsam::RangeFactor<gtsam::Pose2, gtsam::Pose2> RangeFactorPose2;
|
typedef gtsam::RangeFactor<gtsam::Pose2, gtsam::Pose2> RangeFactorPose2;
|
||||||
typedef gtsam::RangeFactor<gtsam::Pose3, gtsam::Pose3> RangeFactorPose3;
|
typedef gtsam::RangeFactor<gtsam::Pose3, gtsam::Pose3> RangeFactorPose3;
|
||||||
|
typedef gtsam::RangeFactor<gtsam::CalibratedCamera, gtsam::Point3> RangeFactorCalibratedCameraPoint;
|
||||||
// Commented out by Frank Dec 2014: not poses!
|
typedef gtsam::RangeFactor<gtsam::SimpleCamera, gtsam::Point3> RangeFactorSimpleCameraPoint;
|
||||||
// If needed, we need a RangeFactor that takes a camera, extracts the pose
|
typedef gtsam::RangeFactor<gtsam::CalibratedCamera, gtsam::CalibratedCamera> RangeFactorCalibratedCamera;
|
||||||
// Should be easy with Expressions
|
typedef gtsam::RangeFactor<gtsam::SimpleCamera, gtsam::SimpleCamera> RangeFactorSimpleCamera;
|
||||||
//typedef gtsam::RangeFactor<gtsam::CalibratedCamera, gtsam::Point3> RangeFactorCalibratedCameraPoint;
|
|
||||||
//typedef gtsam::RangeFactor<gtsam::SimpleCamera, gtsam::Point3> RangeFactorSimpleCameraPoint;
|
|
||||||
//typedef gtsam::RangeFactor<gtsam::CalibratedCamera, gtsam::CalibratedCamera> RangeFactorCalibratedCamera;
|
|
||||||
//typedef gtsam::RangeFactor<gtsam::SimpleCamera, gtsam::SimpleCamera> RangeFactorSimpleCamera;
|
|
||||||
|
|
||||||
|
|
||||||
#include <gtsam/sam/BearingFactor.h>
|
#include <gtsam/sam/BearingFactor.h>
|
||||||
template<POSE, POINT, MEASURED>
|
template<POSE, POINT, BEARING>
|
||||||
virtual class BearingFactor : gtsam::NoiseModelFactor {
|
virtual class BearingFactor : gtsam::NoiseModelFactor {
|
||||||
BearingFactor(size_t key1, size_t key2, const MEASURED& measured, const gtsam::noiseModel::Base* noiseModel);
|
BearingFactor(size_t key1, size_t key2, const BEARING& measured, const gtsam::noiseModel::Base* noiseModel);
|
||||||
|
|
||||||
// enabling serialization functionality
|
// enabling serialization functionality
|
||||||
void serialize() const;
|
void serialize() const;
|
||||||
|
@ -2295,9 +2291,9 @@ typedef gtsam::BearingFactor<gtsam::Pose2, gtsam::Point2, gtsam::Rot2> BearingFa
|
||||||
|
|
||||||
|
|
||||||
#include <gtsam/slam/BearingRangeFactor.h>
|
#include <gtsam/slam/BearingRangeFactor.h>
|
||||||
template<POSE, POINT, MEASURED>
|
template<POSE, POINT, BEARING>
|
||||||
virtual class BearingRangeFactor : gtsam::NoiseModelFactor {
|
virtual class BearingRangeFactor : gtsam::NoiseModelFactor {
|
||||||
BearingRangeFactor(size_t poseKey, size_t pointKey, const MEASURED& measuredBearing, double measuredRange, const gtsam::noiseModel::Base* noiseModel);
|
BearingRangeFactor(size_t poseKey, size_t pointKey, const BEARING& measuredBearing, double measuredRange, const gtsam::noiseModel::Base* noiseModel);
|
||||||
|
|
||||||
pair<MEASURED, double> measured() const;
|
pair<MEASURED, double> measured() const;
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Transformations and mesaurement functions
|
/// @name Transformations and measurement functions
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -393,5 +393,38 @@ struct traits<const CalibratedCamera> : public internal::Manifold<
|
||||||
CalibratedCamera> {
|
CalibratedCamera> {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Define Range functor specializations that are used in RangeFactor
|
||||||
|
template <typename A1, typename A2> struct Range;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<CalibratedCamera, Point3> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const CalibratedCamera& camera, const Point3& point,
|
||||||
|
OptionalJacobian<1, 6> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 3> H2 = boost::none) {
|
||||||
|
return camera.range(point, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<CalibratedCamera, Pose3> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const CalibratedCamera& camera, const Pose3& pose,
|
||||||
|
OptionalJacobian<1, 6> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 6> H2 = boost::none) {
|
||||||
|
return camera.range(pose, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<CalibratedCamera, CalibratedCamera> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const CalibratedCamera& camera1,
|
||||||
|
const CalibratedCamera& camera2,
|
||||||
|
OptionalJacobian<1, 6> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 6> H2 = boost::none) {
|
||||||
|
return camera1.range(camera2, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -263,24 +263,22 @@ public:
|
||||||
template<class CalibrationB>
|
template<class CalibrationB>
|
||||||
double range(const PinholeCamera<CalibrationB>& camera,
|
double range(const PinholeCamera<CalibrationB>& camera,
|
||||||
OptionalJacobian<1, dimension> Dcamera = boost::none,
|
OptionalJacobian<1, dimension> Dcamera = boost::none,
|
||||||
boost::optional<Matrix&> Dother = boost::none) const {
|
OptionalJacobian<1, 6 + CalibrationB::dimension> Dother = boost::none) const {
|
||||||
Matrix16 Dcamera_, Dother_;
|
Matrix16 Dcamera_, Dother_;
|
||||||
double result = this->pose().range(camera.pose(), Dcamera ? &Dcamera_ : 0,
|
double result = this->pose().range(camera.pose(), Dcamera ? &Dcamera_ : 0,
|
||||||
Dother ? &Dother_ : 0);
|
Dother ? &Dother_ : 0);
|
||||||
if (Dcamera) {
|
if (Dcamera) {
|
||||||
Dcamera->resize(1, 6 + DimK);
|
|
||||||
*Dcamera << Dcamera_, Eigen::Matrix<double, 1, DimK>::Zero();
|
*Dcamera << Dcamera_, Eigen::Matrix<double, 1, DimK>::Zero();
|
||||||
}
|
}
|
||||||
if (Dother) {
|
if (Dother) {
|
||||||
Dother->resize(1, 6 + CalibrationB::dimension);
|
|
||||||
Dother->setZero();
|
Dother->setZero();
|
||||||
Dother->block<1, 6>(0, 0) = Dother_;
|
Dother->template block<1, 6>(0, 0) = Dother_;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate range to another camera
|
* Calculate range to a calibrated camera
|
||||||
* @param camera Other camera
|
* @param camera Other camera
|
||||||
* @return range (double)
|
* @return range (double)
|
||||||
*/
|
*/
|
||||||
|
@ -314,4 +312,52 @@ struct traits<const PinholeCamera<Calibration> > : public internal::Manifold<
|
||||||
PinholeCamera<Calibration> > {
|
PinholeCamera<Calibration> > {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Define Range functor specializations that are used in RangeFactor
|
||||||
|
template <typename A1, typename A2> struct Range;
|
||||||
|
|
||||||
|
template <typename Calibration>
|
||||||
|
struct Range<PinholeCamera<Calibration>, Point3> {
|
||||||
|
typedef double result_type;
|
||||||
|
typedef PinholeCamera<Calibration> Camera;
|
||||||
|
double operator()(const Camera& camera, const Point3& point,
|
||||||
|
OptionalJacobian<1, Camera::dimension> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 3> H2 = boost::none) {
|
||||||
|
return camera.range(point, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Calibration>
|
||||||
|
struct Range<PinholeCamera<Calibration>, Pose3> {
|
||||||
|
typedef double result_type;
|
||||||
|
typedef PinholeCamera<Calibration> Camera;
|
||||||
|
double operator()(const Camera& camera, const Pose3& pose,
|
||||||
|
OptionalJacobian<1, Camera::dimension> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 6> H2 = boost::none) {
|
||||||
|
return camera.range(pose, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename CalibrationA, typename CalibrationB>
|
||||||
|
struct Range<PinholeCamera<CalibrationA>, PinholeCamera<CalibrationB> > {
|
||||||
|
typedef double result_type;
|
||||||
|
typedef PinholeCamera<CalibrationA> CameraA;
|
||||||
|
typedef PinholeCamera<CalibrationB> CameraB;
|
||||||
|
double operator()(const CameraA& camera1, const CameraB& camera2,
|
||||||
|
OptionalJacobian<1, CameraA::dimension> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, CameraB::dimension> H2 = boost::none) {
|
||||||
|
return camera1.range(camera2, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Calibration>
|
||||||
|
struct Range<PinholeCamera<Calibration>, CalibratedCamera> {
|
||||||
|
typedef double result_type;
|
||||||
|
typedef PinholeCamera<Calibration> Camera;
|
||||||
|
double operator()(const Camera& camera, const CalibratedCamera& cc,
|
||||||
|
OptionalJacobian<1, Camera::dimension> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 6> H2 = boost::none) {
|
||||||
|
return camera.range(cc, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // \ gtsam
|
} // \ gtsam
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtsam/base/VectorSpace.h>
|
#include <gtsam/base/VectorSpace.h>
|
||||||
|
#include <gtsam/dllexport.h>
|
||||||
#include <boost/serialization/nvp.hpp>
|
#include <boost/serialization/nvp.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -199,4 +200,19 @@ struct traits<Point3> : public internal::VectorSpace<Point3> {};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct traits<const Point3> : public internal::VectorSpace<Point3> {};
|
struct traits<const Point3> : public internal::VectorSpace<Point3> {};
|
||||||
|
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
struct Range;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<Point3, Point3> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const Point3& p, const Point3& q,
|
||||||
|
OptionalJacobian<1, 3> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 3> H2 = boost::none) {
|
||||||
|
return p.distance(q, H1, H2);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gtsam
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <gtsam/geometry/Point2.h>
|
#include <gtsam/geometry/Point2.h>
|
||||||
#include <gtsam/geometry/Rot2.h>
|
#include <gtsam/geometry/Rot2.h>
|
||||||
#include <gtsam/base/Lie.h>
|
#include <gtsam/base/Lie.h>
|
||||||
|
#include <gtsam/dllexport.h>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -295,5 +296,51 @@ struct traits<Pose2> : public internal::LieGroup<Pose2> {};
|
||||||
template<>
|
template<>
|
||||||
struct traits<const Pose2> : public internal::LieGroup<Pose2> {};
|
struct traits<const Pose2> : public internal::LieGroup<Pose2> {};
|
||||||
|
|
||||||
|
// Define Bearing functor specializations that are used in BearingFactor
|
||||||
|
template <typename A1, typename A2> struct Bearing;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Bearing<Pose2, Point2> {
|
||||||
|
typedef Rot2 result_type;
|
||||||
|
Rot2 operator()(const Pose2& pose, const Point2& point,
|
||||||
|
OptionalJacobian<1, 3> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 2> H2 = boost::none) {
|
||||||
|
return pose.bearing(point, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Bearing<Pose2, Pose2> {
|
||||||
|
typedef Rot2 result_type;
|
||||||
|
Rot2 operator()(const Pose2& pose1, const Pose2& pose2,
|
||||||
|
OptionalJacobian<1, 3> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 3> H2 = boost::none) {
|
||||||
|
return pose1.bearing(pose2, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define Range functor specializations that are used in RangeFactor
|
||||||
|
template <typename A1, typename A2> struct Range;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<Pose2, Point2> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const Pose2& pose, const Point2& point,
|
||||||
|
OptionalJacobian<1, 3> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 2> H2 = boost::none) {
|
||||||
|
return pose.range(point, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<Pose2, Pose2> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const Pose2& pose1, const Pose2& pose2,
|
||||||
|
OptionalJacobian<1, 3> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 3> H2 = boost::none) {
|
||||||
|
return pose1.range(pose2, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace gtsam
|
} // namespace gtsam
|
||||||
|
|
||||||
|
|
|
@ -337,5 +337,40 @@ struct traits<Pose3> : public internal::LieGroup<Pose3> {};
|
||||||
template <>
|
template <>
|
||||||
struct traits<const Pose3> : public internal::LieGroup<Pose3> {};
|
struct traits<const Pose3> : public internal::LieGroup<Pose3> {};
|
||||||
|
|
||||||
|
// Define Bearing functor specializations that are used in BearingFactor
|
||||||
|
template <typename A1, typename A2> struct Bearing;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Bearing<Pose3, Point3> {
|
||||||
|
typedef Unit3 result_type;
|
||||||
|
Unit3 operator()(const Pose3& pose, const Point3& point,
|
||||||
|
OptionalJacobian<2, 6> H1 = boost::none,
|
||||||
|
OptionalJacobian<2, 3> H2 = boost::none) {
|
||||||
|
return pose.bearing(point, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define Range functor specializations that are used in RangeFactor
|
||||||
|
template <typename A1, typename A2> struct Range;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<Pose3, Point3> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const Pose3& pose, const Point3& point,
|
||||||
|
OptionalJacobian<1, 6> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 3> H2 = boost::none) {
|
||||||
|
return pose.range(point, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<Pose3, Pose3> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const Pose3& pose1, const Pose3& pose2,
|
||||||
|
OptionalJacobian<1, 6> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 6> H2 = boost::none) {
|
||||||
|
return pose1.range(pose2, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace gtsam
|
} // namespace gtsam
|
||||||
|
|
|
@ -59,24 +59,6 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Range measurement concept
|
|
||||||
* Given a pair of Lie variables, there must exist a function to calculate
|
|
||||||
* range with derivatives.
|
|
||||||
*/
|
|
||||||
template<class V1, class V2>
|
|
||||||
class RangeMeasurementConcept {
|
|
||||||
private:
|
|
||||||
static double checkRangeMeasurement(const V1& x, const V2& p) {
|
|
||||||
return x.range(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double checkRangeMeasurementDerivatives(const V1& x, const V2& p) {
|
|
||||||
boost::optional<Matrix&> H1, H2;
|
|
||||||
return x.range(p, H1, H2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // \namespace gtsam
|
} // \namespace gtsam
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +74,3 @@ private:
|
||||||
#define GTSAM_CONCEPT_POSE_INST(T) template class gtsam::PoseConcept<T>;
|
#define GTSAM_CONCEPT_POSE_INST(T) template class gtsam::PoseConcept<T>;
|
||||||
#define GTSAM_CONCEPT_POSE_TYPE(T) typedef gtsam::PoseConcept<T> _gtsam_PoseConcept##T;
|
#define GTSAM_CONCEPT_POSE_TYPE(T) typedef gtsam::PoseConcept<T> _gtsam_PoseConcept##T;
|
||||||
|
|
||||||
/** Range Measurement macros */
|
|
||||||
#define GTSAM_CONCEPT_RANGE_MEASUREMENT_INST(V1,V2) template class gtsam::RangeMeasurementConcept<V1,V2>;
|
|
||||||
#define GTSAM_CONCEPT_RANGE_MEASUREMENT_TYPE(V1,V2) typedef gtsam::RangeMeasurementConcept<V1,V2> _gtsam_RangeMeasurementConcept##V1##V2;
|
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file BearingFactor.h
|
* @file BearingFactor.h
|
||||||
* @brief Serializable factor induced by a bearing measurement of a point from
|
* @brief Serializable factor induced by a bearing measurement
|
||||||
*a given pose
|
|
||||||
* @date July 2015
|
* @date July 2015
|
||||||
* @author Frank Dellaert
|
* @author Frank Dellaert
|
||||||
**/
|
**/
|
||||||
|
@ -20,17 +19,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtsam/nonlinear/SerializableExpressionFactor.h>
|
#include <gtsam/nonlinear/SerializableExpressionFactor.h>
|
||||||
#include <gtsam/geometry/concepts.h>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
// forward declaration of Bearing functor, assumed partially specified
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
struct Bearing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binary factor for a bearing measurement
|
* Binary factor for a bearing measurement
|
||||||
|
* Works for any two types A1,A2 for which the functor Bearing<A1,A2>() is
|
||||||
|
* defined
|
||||||
* @addtogroup SAM
|
* @addtogroup SAM
|
||||||
*/
|
*/
|
||||||
template <typename POSE, typename POINT, typename T>
|
template <typename A1, typename A2,
|
||||||
struct BearingFactor : public SerializableExpressionFactor2<T, POSE, POINT> {
|
typename T = typename Bearing<A1, A2>::result_type>
|
||||||
typedef SerializableExpressionFactor2<T, POSE, POINT> Base;
|
struct BearingFactor : public SerializableExpressionFactor2<T, A1, A2> {
|
||||||
|
typedef SerializableExpressionFactor2<T, A1, A2> Base;
|
||||||
|
|
||||||
/// default constructor
|
/// default constructor
|
||||||
BearingFactor() {}
|
BearingFactor() {}
|
||||||
|
@ -44,8 +49,9 @@ struct BearingFactor : public SerializableExpressionFactor2<T, POSE, POINT> {
|
||||||
|
|
||||||
// Return measurement expression
|
// Return measurement expression
|
||||||
virtual Expression<T> expression(Key key1, Key key2) const {
|
virtual Expression<T> expression(Key key1, Key key2) const {
|
||||||
return Expression<T>(Expression<POSE>(key1), &POSE::bearing,
|
Expression<A1> a1_(key1);
|
||||||
Expression<POINT>(key2));
|
Expression<A2> a2_(key2);
|
||||||
|
return Expression<T>(Bearing<A1, A2>(), a1_, a2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print
|
/// print
|
||||||
|
@ -57,8 +63,8 @@ struct BearingFactor : public SerializableExpressionFactor2<T, POSE, POINT> {
|
||||||
}; // BearingFactor
|
}; // BearingFactor
|
||||||
|
|
||||||
/// traits
|
/// traits
|
||||||
template <class POSE, class POINT, class T>
|
template <typename A1, typename A2, typename T>
|
||||||
struct traits<BearingFactor<POSE, POINT, T> >
|
struct traits<BearingFactor<A1, A2, T> >
|
||||||
: public Testable<BearingFactor<POSE, POINT, T> > {};
|
: public Testable<BearingFactor<A1, A2, T> > {};
|
||||||
|
|
||||||
} // namespace gtsam
|
} // namespace gtsam
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file RangeFactor.h
|
* @file RangeFactor.h
|
||||||
* @brief Serializable factor induced by a range measurement between two points
|
* @brief Serializable factor induced by a range measurement
|
||||||
*and/or poses
|
|
||||||
* @date July 2015
|
* @date July 2015
|
||||||
* @author Frank Dellaert
|
* @author Frank Dellaert
|
||||||
**/
|
**/
|
||||||
|
@ -20,30 +19,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtsam/nonlinear/SerializableExpressionFactor.h>
|
#include <gtsam/nonlinear/SerializableExpressionFactor.h>
|
||||||
#include <gtsam/geometry/concepts.h>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
// forward declaration of Range functor, assumed partially specified
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
struct Range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binary factor for a range measurement
|
* Binary factor for a range measurement
|
||||||
|
* Works for any two types A1,A2 for which the functor Range<A1,A2>() is defined
|
||||||
* @addtogroup SAM
|
* @addtogroup SAM
|
||||||
*/
|
*/
|
||||||
template <class A1, class A2 = A1>
|
template <typename A1, typename A2 = A1,
|
||||||
struct RangeFactor : public SerializableExpressionFactor2<double, A1, A2> {
|
typename T = typename Range<A1, A2>::result_type>
|
||||||
|
class RangeFactor : public SerializableExpressionFactor2<T, A1, A2> {
|
||||||
private:
|
private:
|
||||||
typedef RangeFactor<A1, A2> This;
|
typedef RangeFactor<A1, A2> This;
|
||||||
typedef SerializableExpressionFactor2<double, A1, A2> Base;
|
typedef SerializableExpressionFactor2<T, A1, A2> Base;
|
||||||
|
|
||||||
// Concept requirements for this factor
|
|
||||||
GTSAM_CONCEPT_RANGE_MEASUREMENT_TYPE(A1, A2)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// default constructor
|
/// default constructor
|
||||||
RangeFactor() {}
|
RangeFactor() {}
|
||||||
|
|
||||||
RangeFactor(Key key1, Key key2, double measured,
|
RangeFactor(Key key1, Key key2, T measured, const SharedNoiseModel& model)
|
||||||
const SharedNoiseModel& model)
|
|
||||||
: Base(key1, key2, model, measured) {
|
: Base(key1, key2, model, measured) {
|
||||||
this->initialize(expression(key1, key2));
|
this->initialize(expression(key1, key2));
|
||||||
}
|
}
|
||||||
|
@ -55,10 +54,10 @@ struct RangeFactor : public SerializableExpressionFactor2<double, A1, A2> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return measurement expression
|
// Return measurement expression
|
||||||
virtual Expression<double> expression(Key key1, Key key2) const {
|
virtual Expression<T> expression(Key key1, Key key2) const {
|
||||||
Expression<A1> t1_(key1);
|
Expression<A1> a1_(key1);
|
||||||
Expression<A2> t2_(key2);
|
Expression<A2> a2_(key2);
|
||||||
return Expression<double>(t1_, &A1::range, t2_);
|
return Expression<T>(Range<A1, A2>(), a1_, a2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print
|
/// print
|
||||||
|
@ -70,30 +69,29 @@ struct RangeFactor : public SerializableExpressionFactor2<double, A1, A2> {
|
||||||
}; // \ RangeFactor
|
}; // \ RangeFactor
|
||||||
|
|
||||||
/// traits
|
/// traits
|
||||||
template <class A1, class A2>
|
template <typename A1, typename A2, typename T>
|
||||||
struct traits<RangeFactor<A1, A2> > : public Testable<RangeFactor<A1, A2> > {};
|
struct traits<RangeFactor<A1, A2, T> >
|
||||||
|
: public Testable<RangeFactor<A1, A2, T> > {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binary factor for a range measurement, with a transform applied
|
* Binary factor for a range measurement, with a transform applied
|
||||||
* @addtogroup SAM
|
* @addtogroup SAM
|
||||||
*/
|
*/
|
||||||
template <class A1, class A2 = A1>
|
template <typename A1, typename A2 = A1,
|
||||||
|
typename T = typename Range<A1, A2>::result_type>
|
||||||
class RangeFactorWithTransform
|
class RangeFactorWithTransform
|
||||||
: public SerializableExpressionFactor2<double, A1, A2> {
|
: public SerializableExpressionFactor2<T, A1, A2> {
|
||||||
private:
|
private:
|
||||||
typedef RangeFactorWithTransform<A1, A2> This;
|
typedef RangeFactorWithTransform<A1, A2> This;
|
||||||
typedef SerializableExpressionFactor2<double, A1, A2> Base;
|
typedef SerializableExpressionFactor2<T, A1, A2> Base;
|
||||||
|
|
||||||
A1 body_T_sensor_; ///< The pose of the sensor in the body frame
|
A1 body_T_sensor_; ///< The pose of the sensor in the body frame
|
||||||
|
|
||||||
// Concept requirements for this factor
|
|
||||||
GTSAM_CONCEPT_RANGE_MEASUREMENT_TYPE(A1, A2)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//// Default constructor
|
//// Default constructor
|
||||||
RangeFactorWithTransform() {}
|
RangeFactorWithTransform() {}
|
||||||
|
|
||||||
RangeFactorWithTransform(Key key1, Key key2, double measured,
|
RangeFactorWithTransform(Key key1, Key key2, T measured,
|
||||||
const SharedNoiseModel& model,
|
const SharedNoiseModel& model,
|
||||||
const A1& body_T_sensor)
|
const A1& body_T_sensor)
|
||||||
: Base(key1, key2, model, measured), body_T_sensor_(body_T_sensor) {
|
: Base(key1, key2, model, measured), body_T_sensor_(body_T_sensor) {
|
||||||
|
@ -109,13 +107,13 @@ class RangeFactorWithTransform
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return measurement expression
|
// Return measurement expression
|
||||||
virtual Expression<double> expression(Key key1, Key key2) const {
|
virtual Expression<T> expression(Key key1, Key key2) const {
|
||||||
Expression<A1> body_T_sensor__(body_T_sensor_);
|
Expression<A1> body_T_sensor__(body_T_sensor_);
|
||||||
Expression<A1> nav_T_body_(key1);
|
Expression<A1> nav_T_body_(key1);
|
||||||
Expression<A1> nav_T_sensor_(traits<A1>::Compose, nav_T_body_,
|
Expression<A1> nav_T_sensor_(traits<A1>::Compose, nav_T_body_,
|
||||||
body_T_sensor__);
|
body_T_sensor__);
|
||||||
Expression<A2> t2_(key2);
|
Expression<A2> a2_(key2);
|
||||||
return Expression<double>(nav_T_sensor_, &A1::range, t2_);
|
return Expression<T>(Range<A1, A2>(), nav_T_sensor_, a2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** print contents */
|
/** print contents */
|
||||||
|
@ -128,8 +126,8 @@ class RangeFactorWithTransform
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Serialization function */
|
/** Serialization function */
|
||||||
friend class boost::serialization::access;
|
friend typename boost::serialization::access;
|
||||||
template <class ARCHIVE>
|
template <typename ARCHIVE>
|
||||||
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
|
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
|
||||||
ar& boost::serialization::make_nvp(
|
ar& boost::serialization::make_nvp(
|
||||||
"Base", boost::serialization::base_object<Base>(*this));
|
"Base", boost::serialization::base_object<Base>(*this));
|
||||||
|
@ -138,8 +136,8 @@ class RangeFactorWithTransform
|
||||||
}; // \ RangeFactorWithTransform
|
}; // \ RangeFactorWithTransform
|
||||||
|
|
||||||
/// traits
|
/// traits
|
||||||
template <class A1, class A2>
|
template <typename A1, typename A2, typename T>
|
||||||
struct traits<RangeFactorWithTransform<A1, A2> >
|
struct traits<RangeFactorWithTransform<A1, A2, T> >
|
||||||
: public Testable<RangeFactorWithTransform<A1, A2> > {};
|
: public Testable<RangeFactorWithTransform<A1, A2, T> > {};
|
||||||
|
|
||||||
} // \ namespace gtsam
|
} // \ namespace gtsam
|
||||||
|
|
|
@ -32,12 +32,12 @@ using namespace gtsam;
|
||||||
Key poseKey(1);
|
Key poseKey(1);
|
||||||
Key pointKey(2);
|
Key pointKey(2);
|
||||||
|
|
||||||
typedef BearingFactor<Pose2, Point2, Rot2> BearingFactor2D;
|
typedef BearingFactor<Pose2, Point2> BearingFactor2D;
|
||||||
double measurement2D(10.0);
|
double measurement2D(10.0);
|
||||||
static SharedNoiseModel model2D(noiseModel::Isotropic::Sigma(1, 0.5));
|
static SharedNoiseModel model2D(noiseModel::Isotropic::Sigma(1, 0.5));
|
||||||
BearingFactor2D factor2D(poseKey, pointKey, measurement2D, model2D);
|
BearingFactor2D factor2D(poseKey, pointKey, measurement2D, model2D);
|
||||||
|
|
||||||
typedef BearingFactor<Pose3, Point3, Unit3> BearingFactor3D;
|
typedef BearingFactor<Pose3, Point3> BearingFactor3D;
|
||||||
Unit3 measurement3D = Pose3().bearing(Point3(1, 0, 0)); // has to match values!
|
Unit3 measurement3D = Pose3().bearing(Point3(1, 0, 0)); // has to match values!
|
||||||
static SharedNoiseModel model3D(noiseModel::Isotropic::Sigma(2, 0.5));
|
static SharedNoiseModel model3D(noiseModel::Isotropic::Sigma(2, 0.5));
|
||||||
BearingFactor3D factor3D(poseKey, pointKey, measurement3D, model3D);
|
BearingFactor3D factor3D(poseKey, pointKey, measurement3D, model3D);
|
||||||
|
|
|
@ -344,6 +344,58 @@ TEST( RangeFactor, Jacobian3DWithTransform ) {
|
||||||
CHECK(assert_equal(H2Expected, H2Actual, 1e-9));
|
CHECK(assert_equal(H2Expected, H2Actual, 1e-9));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
// Do a test with Point3
|
||||||
|
TEST(RangeFactor, Point3) {
|
||||||
|
// Create a factor
|
||||||
|
Key poseKey(1);
|
||||||
|
Key pointKey(2);
|
||||||
|
double measurement(10.0);
|
||||||
|
RangeFactor<Point3> factor(poseKey, pointKey, measurement, model);
|
||||||
|
|
||||||
|
// Set the linearization point
|
||||||
|
Point3 pose(1.0, 2.0, 00);
|
||||||
|
Point3 point(-4.0, 11.0, 0);
|
||||||
|
|
||||||
|
// The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
|
||||||
|
Vector expectedError = (Vector(1) << 0.295630141).finished();
|
||||||
|
|
||||||
|
// Verify we get the expected error
|
||||||
|
CHECK(assert_equal(expectedError, factor.evaluateError(pose, point), 1e-9));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
// Do a test with non GTSAM types
|
||||||
|
|
||||||
|
namespace gtsam{
|
||||||
|
template <>
|
||||||
|
struct Range<Vector3, Vector3> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const Vector3& v1, const Vector3& v2,
|
||||||
|
OptionalJacobian<1, 3> H1, OptionalJacobian<1, 3> H2) {
|
||||||
|
return (v2 - v1).norm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RangeFactor, NonGTSAM) {
|
||||||
|
// Create a factor
|
||||||
|
Key poseKey(1);
|
||||||
|
Key pointKey(2);
|
||||||
|
double measurement(10.0);
|
||||||
|
RangeFactor<Vector3> factor(poseKey, pointKey, measurement, model);
|
||||||
|
|
||||||
|
// Set the linearization point
|
||||||
|
Vector3 pose(1.0, 2.0, 00);
|
||||||
|
Vector3 point(-4.0, 11.0, 0);
|
||||||
|
|
||||||
|
// The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
|
||||||
|
Vector expectedError = (Vector(1) << 0.295630141).finished();
|
||||||
|
|
||||||
|
// Verify we get the expected error
|
||||||
|
CHECK(assert_equal(expectedError, factor.evaluateError(pose, point), 1e-9));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() {
|
int main() {
|
||||||
TestResult tr;
|
TestResult tr;
|
||||||
|
|
|
@ -47,7 +47,6 @@ namespace gtsam {
|
||||||
|
|
||||||
/** concept check by type */
|
/** concept check by type */
|
||||||
GTSAM_CONCEPT_TESTABLE_TYPE(Rot)
|
GTSAM_CONCEPT_TESTABLE_TYPE(Rot)
|
||||||
GTSAM_CONCEPT_RANGE_MEASUREMENT_TYPE(Pose, Point)
|
|
||||||
GTSAM_CONCEPT_POSE_TYPE(Pose)
|
GTSAM_CONCEPT_POSE_TYPE(Pose)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -170,4 +170,17 @@ private:
|
||||||
template<>
|
template<>
|
||||||
struct traits<PoseRTV> : public internal::LieGroup<PoseRTV> {};
|
struct traits<PoseRTV> : public internal::LieGroup<PoseRTV> {};
|
||||||
|
|
||||||
|
// Define Range functor specializations that are used in RangeFactor
|
||||||
|
template <typename A1, typename A2> struct Range;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Range<PoseRTV, PoseRTV> {
|
||||||
|
typedef double result_type;
|
||||||
|
double operator()(const PoseRTV& pose1, const PoseRTV& pose2,
|
||||||
|
OptionalJacobian<1, 9> H1 = boost::none,
|
||||||
|
OptionalJacobian<1, 9> H2 = boost::none) {
|
||||||
|
return pose1.range(pose2, H1, H2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // \namespace gtsam
|
} // \namespace gtsam
|
||||||
|
|
Loading…
Reference in New Issue