BIG change: SmartFactorBase and SmartProjectionFactor now templated on CAMERA
parent
d5261e2e8d
commit
d6f54475c3
|
@ -45,6 +45,9 @@ template<class CAMERA>
|
|||
class SmartFactorBase: public NonlinearFactor {
|
||||
|
||||
private:
|
||||
typedef NonlinearFactor Base;
|
||||
typedef SmartFactorBase<CAMERA> This;
|
||||
typedef typename CAMERA::Measurement Z;
|
||||
|
||||
/**
|
||||
* As of Feb 22, 2015, the noise model is the same for all measurements and
|
||||
|
@ -56,9 +59,6 @@ private:
|
|||
|
||||
protected:
|
||||
|
||||
// Figure out the measurement type
|
||||
typedef typename CAMERA::Measurement Z;
|
||||
|
||||
/**
|
||||
* 2D measurement and noise model for each of the m views
|
||||
* We keep a copy of measurements for I/O and computing the error.
|
||||
|
@ -66,19 +66,11 @@ protected:
|
|||
*/
|
||||
std::vector<Z> measured_;
|
||||
|
||||
/// shorthand for base class type
|
||||
typedef NonlinearFactor Base;
|
||||
|
||||
/// shorthand for this class
|
||||
typedef SmartFactorBase<CAMERA> This;
|
||||
|
||||
static const int ZDim = traits<Z>::dimension; ///< Measurement dimension
|
||||
static const int Dim = traits<CAMERA>::dimension; ///< Camera dimension
|
||||
|
||||
// Definitions for blocks of F
|
||||
typedef Eigen::Matrix<double, ZDim, Dim> Matrix2D; // F
|
||||
// Definitions for block matrices used internally
|
||||
typedef Eigen::Matrix<double, Dim, ZDim> MatrixD2; // F'
|
||||
typedef std::pair<Key, Matrix2D> KeyMatrix2D; // Fblocks
|
||||
typedef Eigen::Matrix<double, Dim, Dim> MatrixDD; // camera hessian block
|
||||
typedef Eigen::Matrix<double, ZDim, 3> Matrix23;
|
||||
typedef Eigen::Matrix<double, Dim, 1> VectorD;
|
||||
|
@ -105,6 +97,10 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
// Definitions for blocks of F, externally visible
|
||||
typedef Eigen::Matrix<double, ZDim, Dim> Matrix2D; // F
|
||||
typedef std::pair<Key, Matrix2D> KeyMatrix2D; // Fblocks
|
||||
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
|
||||
/// shorthand for a smart pointer to a factor
|
||||
|
@ -256,57 +252,19 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Compute whitenedError, returning only the derivative E, i.e.,
|
||||
* the stacked ZDim*3 derivatives of project with respect to the point.
|
||||
* Assumes non-degenerate ! TODO explain this
|
||||
*/
|
||||
Vector reprojectionErrors(const Cameras& cameras, const Point3& point,
|
||||
Matrix& E) const {
|
||||
|
||||
// Project into CameraSet, calculating derivatives
|
||||
std::vector<Z> predicted;
|
||||
predicted = cameras.project2(point, boost::none, E);
|
||||
|
||||
// if needed, whiten
|
||||
size_t m = keys_.size();
|
||||
Vector b(ZDim * m);
|
||||
for (size_t i = 0, row = 0; i < m; i++, row += ZDim) {
|
||||
|
||||
// Calculate error
|
||||
const Z& zi = measured_.at(i);
|
||||
Vector bi = (zi - predicted[i]).vector();
|
||||
b.segment<ZDim>(row) = bi;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute F, E, and optionally H, where F and E are the stacked derivatives
|
||||
* with respect to the cameras, point, and calibration, respectively.
|
||||
* The value of cameras/point are passed as parameters.
|
||||
* Returns error vector b
|
||||
* Compute reprojection errors and derivatives
|
||||
* TODO: the treatment of body_P_sensor_ is weird: the transformation
|
||||
* is applied in the caller, but the derivatives are computed here.
|
||||
*/
|
||||
Vector reprojectionErrors(const Cameras& cameras, const Point3& point,
|
||||
typename Cameras::FBlocks& F, Matrix& E) const {
|
||||
|
||||
// Project into CameraSet, calculating derivatives
|
||||
std::vector<Z> predicted;
|
||||
predicted = cameras.project2(point, F, E);
|
||||
Vector b = cameras.reprojectionErrors(point, measured_, F, E);
|
||||
|
||||
// Calculate error and whiten derivatives if needed
|
||||
size_t m = keys_.size();
|
||||
Vector b(ZDim * m);
|
||||
for (size_t i = 0; i < m; i++) {
|
||||
|
||||
// Calculate error
|
||||
const Z& zi = measured_.at(i);
|
||||
Vector bi = (zi - predicted[i]).vector();
|
||||
|
||||
// if we have a sensor offset, correct camera derivatives
|
||||
if (body_P_sensor_) {
|
||||
// TODO: no simpler way ??
|
||||
// Apply sensor chain rule if needed TODO: no simpler way ??
|
||||
if (body_P_sensor_) {
|
||||
size_t m = keys_.size();
|
||||
for (size_t i = 0; i < m; i++) {
|
||||
const Pose3& pose_i = cameras[i].pose();
|
||||
Pose3 w_Pose_body = pose_i.compose(body_P_sensor_->inverse());
|
||||
Matrix66 J;
|
||||
|
@ -314,6 +272,7 @@ public:
|
|||
F[i].leftCols(6) *= J;
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -344,7 +303,7 @@ public:
|
|||
/// Assumes non-degenerate !
|
||||
void computeEP(Matrix& E, Matrix& P, const Cameras& cameras,
|
||||
const Point3& point) const {
|
||||
reprojectionErrors(cameras, point, E);
|
||||
cameras.reprojectionErrors(point, measured_, boost::none, E);
|
||||
P = PointCov(E);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,23 +25,29 @@ namespace gtsam {
|
|||
/**
|
||||
* @addtogroup SLAM
|
||||
*/
|
||||
template<class CALIBRATION, size_t D>
|
||||
class SmartProjectionCameraFactor: public SmartProjectionFactor<CALIBRATION, D> {
|
||||
template<class CALIBRATION>
|
||||
class SmartProjectionCameraFactor: public SmartProjectionFactor<
|
||||
PinholeCamera<CALIBRATION> > {
|
||||
|
||||
private:
|
||||
typedef PinholeCamera<CALIBRATION> Camera;
|
||||
typedef SmartProjectionFactor<Camera> Base;
|
||||
typedef SmartProjectionCameraFactor<CALIBRATION> This;
|
||||
|
||||
protected:
|
||||
|
||||
static const int Dim = traits<Camera>::dimension; ///< CAMERA dimension
|
||||
|
||||
bool isImplicit_;
|
||||
|
||||
public:
|
||||
|
||||
/// shorthand for base class type
|
||||
typedef SmartProjectionFactor<CALIBRATION, D> Base;
|
||||
|
||||
/// shorthand for this class
|
||||
typedef SmartProjectionCameraFactor<CALIBRATION, D> This;
|
||||
|
||||
/// shorthand for a smart pointer to a factor
|
||||
typedef boost::shared_ptr<This> shared_ptr;
|
||||
|
||||
// A set of cameras
|
||||
typedef CameraSet<Camera> Cameras;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param rankTol tolerance used to check if point triangulation is degenerate
|
||||
|
@ -88,14 +94,14 @@ public:
|
|||
|
||||
/// get the dimension of the factor (number of rows on linearization)
|
||||
virtual size_t dim() const {
|
||||
return D * this->keys_.size(); // 6 for the pose and 3 for the calibration
|
||||
return Dim * this->keys_.size(); // 6 for the pose and 3 for the calibration
|
||||
}
|
||||
|
||||
/// Collect all cameras: important that in key order
|
||||
typename Base::Cameras cameras(const Values& values) const {
|
||||
typename Base::Cameras cameras;
|
||||
Cameras cameras(const Values& values) const {
|
||||
Cameras cameras;
|
||||
BOOST_FOREACH(const Key& k, this->keys_)
|
||||
cameras.push_back(values.at<typename Base::Camera>(k));
|
||||
cameras.push_back(values.at<Camera>(k));
|
||||
return cameras;
|
||||
}
|
||||
|
||||
|
@ -109,19 +115,19 @@ public:
|
|||
}
|
||||
|
||||
/// linearize returns a Hessianfactor that is an approximation of error(p)
|
||||
virtual boost::shared_ptr<RegularHessianFactor<D> > linearizeToHessian(
|
||||
virtual boost::shared_ptr<RegularHessianFactor<Dim> > linearizeToHessian(
|
||||
const Values& values, double lambda=0.0) const {
|
||||
return Base::createHessianFactor(cameras(values),lambda);
|
||||
}
|
||||
|
||||
/// linearize returns a Hessianfactor that is an approximation of error(p)
|
||||
virtual boost::shared_ptr<RegularImplicitSchurFactor<D> > linearizeToImplicit(
|
||||
virtual boost::shared_ptr<RegularImplicitSchurFactor<Dim> > linearizeToImplicit(
|
||||
const Values& values, double lambda=0.0) const {
|
||||
return Base::createRegularImplicitSchurFactor(cameras(values),lambda);
|
||||
}
|
||||
|
||||
/// linearize returns a Jacobianfactor that is an approximation of error(p)
|
||||
virtual boost::shared_ptr<JacobianFactorQ<D, 2> > linearizeToJacobian(
|
||||
virtual boost::shared_ptr<JacobianFactorQ<Dim, 2> > linearizeToJacobian(
|
||||
const Values& values, double lambda=0.0) const {
|
||||
return Base::createJacobianQFactor(cameras(values),lambda);
|
||||
}
|
||||
|
|
|
@ -60,11 +60,17 @@ enum LinearizationMode {
|
|||
/**
|
||||
* SmartProjectionFactor: triangulates point and keeps an estimate of it around.
|
||||
*/
|
||||
template<class CALIBRATION, size_t D>
|
||||
class SmartProjectionFactor: public SmartFactorBase<PinholeCamera<CALIBRATION>,
|
||||
D> {
|
||||
template<class CAMERA>
|
||||
class SmartProjectionFactor: public SmartFactorBase<CAMERA> {
|
||||
|
||||
private:
|
||||
typedef SmartFactorBase<CAMERA> Base;
|
||||
typedef SmartProjectionFactor<CAMERA> This;
|
||||
|
||||
protected:
|
||||
|
||||
static const int Dim = traits<CAMERA>::dimension; ///< CAMERA dimension
|
||||
|
||||
// Some triangulation parameters
|
||||
const double rankTolerance_; ///< threshold to decide whether triangulation is degenerate_
|
||||
const double retriangulationThreshold_; ///< threshold to decide whether to re-triangulate
|
||||
|
@ -91,9 +97,6 @@ protected:
|
|||
/// shorthand for smart projection factor state variable
|
||||
typedef boost::shared_ptr<SmartProjectionFactorState> SmartFactorStatePtr;
|
||||
|
||||
/// shorthand for base class type
|
||||
typedef SmartFactorBase<PinholeCamera<CALIBRATION>, D> Base;
|
||||
|
||||
double landmarkDistanceThreshold_; // if the landmark is triangulated at a
|
||||
// distance larger than that the factor is considered degenerate
|
||||
|
||||
|
@ -101,17 +104,13 @@ protected:
|
|||
// average reprojection error is smaller than this threshold after triangulation,
|
||||
// and the factor is disregarded if the error is large
|
||||
|
||||
/// shorthand for this class
|
||||
typedef SmartProjectionFactor<CALIBRATION, D> This;
|
||||
|
||||
public:
|
||||
|
||||
/// shorthand for a smart pointer to a factor
|
||||
typedef boost::shared_ptr<This> shared_ptr;
|
||||
|
||||
/// shorthand for a pinhole camera
|
||||
typedef PinholeCamera<CALIBRATION> Camera;
|
||||
typedef CameraSet<Camera> Cameras;
|
||||
/// shorthand for a set of cameras
|
||||
typedef CameraSet<CAMERA> Cameras;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -243,7 +242,7 @@ public:
|
|||
// We triangulate the 3D position of the landmark
|
||||
try {
|
||||
// std::cout << "triangulatePoint3 i \n" << rankTolerance << std::endl;
|
||||
point_ = triangulatePoint3<CALIBRATION>(cameras, this->measured_,
|
||||
point_ = triangulatePoint3<CAMERA>(cameras, this->measured_,
|
||||
rankTolerance_, enableEPI_);
|
||||
degenerate_ = false;
|
||||
cheiralityException_ = false;
|
||||
|
@ -251,7 +250,7 @@ public:
|
|||
// Check landmark distance and reprojection errors to avoid outliers
|
||||
double totalReprojError = 0.0;
|
||||
size_t i = 0;
|
||||
BOOST_FOREACH(const Camera& camera, cameras) {
|
||||
BOOST_FOREACH(const CAMERA& camera, cameras) {
|
||||
Point3 cameraTranslation = camera.pose().translation();
|
||||
// we discard smart factors corresponding to points that are far away
|
||||
if (cameraTranslation.distance(point_) > landmarkDistanceThreshold_) {
|
||||
|
@ -314,7 +313,7 @@ public:
|
|||
}
|
||||
|
||||
/// linearize returns a Hessianfactor that is an approximation of error(p)
|
||||
boost::shared_ptr<RegularHessianFactor<D> > createHessianFactor(
|
||||
boost::shared_ptr<RegularHessianFactor<Dim> > createHessianFactor(
|
||||
const Cameras& cameras, const double lambda = 0.0) const {
|
||||
|
||||
bool isDebug = false;
|
||||
|
@ -338,10 +337,10 @@ public:
|
|||
&& (this->cheiralityException_ || this->degenerate_))) {
|
||||
// std::cout << "In linearize: exception" << std::endl;
|
||||
BOOST_FOREACH(Matrix& m, Gs)
|
||||
m = zeros(D, D);
|
||||
m = zeros(Dim, Dim);
|
||||
BOOST_FOREACH(Vector& v, gs)
|
||||
v = zero(D);
|
||||
return boost::make_shared<RegularHessianFactor<D> >(this->keys_, Gs, gs,
|
||||
v = zero(Dim);
|
||||
return boost::make_shared<RegularHessianFactor<Dim> >(this->keys_, Gs, gs,
|
||||
0.0);
|
||||
}
|
||||
|
||||
|
@ -366,7 +365,7 @@ public:
|
|||
<< "something wrong in SmartProjectionHessianFactor: selective relinearization should be disabled"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
return boost::make_shared<RegularHessianFactor<D> >(this->keys_,
|
||||
return boost::make_shared<RegularHessianFactor<Dim> >(this->keys_,
|
||||
this->state_->Gs, this->state_->gs, this->state_->f);
|
||||
}
|
||||
|
||||
|
@ -378,7 +377,7 @@ public:
|
|||
// Schur complement trick
|
||||
// Frank says: should be possible to do this more efficiently?
|
||||
// And we care, as in grouped factors this is called repeatedly
|
||||
Matrix H(D * numKeys, D * numKeys);
|
||||
Matrix H(Dim * numKeys, Dim * numKeys);
|
||||
Vector gs_vector;
|
||||
|
||||
Matrix3 P = Base::PointCov(E, lambda);
|
||||
|
@ -390,11 +389,11 @@ public:
|
|||
// Populate Gs and gs
|
||||
int GsCount2 = 0;
|
||||
for (DenseIndex i1 = 0; i1 < (DenseIndex) numKeys; i1++) { // for each camera
|
||||
DenseIndex i1D = i1 * D;
|
||||
gs.at(i1) = gs_vector.segment<D>(i1D);
|
||||
DenseIndex i1D = i1 * Dim;
|
||||
gs.at(i1) = gs_vector.segment<Dim>(i1D);
|
||||
for (DenseIndex i2 = 0; i2 < (DenseIndex) numKeys; i2++) {
|
||||
if (i2 >= i1) {
|
||||
Gs.at(GsCount2) = H.block<D, D>(i1D, i2 * D);
|
||||
Gs.at(GsCount2) = H.block<Dim, Dim>(i1D, i2 * Dim);
|
||||
GsCount2++;
|
||||
}
|
||||
}
|
||||
|
@ -405,37 +404,37 @@ public:
|
|||
this->state_->gs = gs;
|
||||
this->state_->f = f;
|
||||
}
|
||||
return boost::make_shared<RegularHessianFactor<D> >(this->keys_, Gs, gs, f);
|
||||
return boost::make_shared<RegularHessianFactor<Dim> >(this->keys_, Gs, gs, f);
|
||||
}
|
||||
|
||||
// create factor
|
||||
boost::shared_ptr<RegularImplicitSchurFactor<D> > createRegularImplicitSchurFactor(
|
||||
boost::shared_ptr<RegularImplicitSchurFactor<Dim> > createRegularImplicitSchurFactor(
|
||||
const Cameras& cameras, double lambda) const {
|
||||
if (triangulateForLinearize(cameras))
|
||||
return Base::createRegularImplicitSchurFactor(cameras, point_, lambda);
|
||||
else
|
||||
return boost::shared_ptr<RegularImplicitSchurFactor<D> >();
|
||||
return boost::shared_ptr<RegularImplicitSchurFactor<Dim> >();
|
||||
}
|
||||
|
||||
/// create factor
|
||||
boost::shared_ptr<JacobianFactorQ<D, 2> > createJacobianQFactor(
|
||||
boost::shared_ptr<JacobianFactorQ<Dim, 2> > createJacobianQFactor(
|
||||
const Cameras& cameras, double lambda) const {
|
||||
if (triangulateForLinearize(cameras))
|
||||
return Base::createJacobianQFactor(cameras, point_, lambda);
|
||||
else
|
||||
return boost::make_shared<JacobianFactorQ<D, 2> >(this->keys_);
|
||||
return boost::make_shared<JacobianFactorQ<Dim, 2> >(this->keys_);
|
||||
}
|
||||
|
||||
/// Create a factor, takes values
|
||||
boost::shared_ptr<JacobianFactorQ<D, 2> > createJacobianQFactor(
|
||||
boost::shared_ptr<JacobianFactorQ<Dim, 2> > createJacobianQFactor(
|
||||
const Values& values, double lambda) const {
|
||||
Cameras myCameras;
|
||||
Cameras cameras;
|
||||
// TODO triangulate twice ??
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
return createJacobianQFactor(myCameras, lambda);
|
||||
return createJacobianQFactor(cameras, lambda);
|
||||
else
|
||||
return boost::make_shared<JacobianFactorQ<D, 2> >(this->keys_);
|
||||
return boost::make_shared<JacobianFactorQ<Dim, 2> >(this->keys_);
|
||||
}
|
||||
|
||||
/// different (faster) way to compute Jacobian factor
|
||||
|
@ -444,20 +443,20 @@ public:
|
|||
if (triangulateForLinearize(cameras))
|
||||
return Base::createJacobianSVDFactor(cameras, point_, lambda);
|
||||
else
|
||||
return boost::make_shared<JacobianFactorSVD<D, 2> >(this->keys_);
|
||||
return boost::make_shared<JacobianFactorSVD<Dim, 2> >(this->keys_);
|
||||
}
|
||||
|
||||
/// Returns true if nonDegenerate
|
||||
bool computeCamerasAndTriangulate(const Values& values,
|
||||
Cameras& myCameras) const {
|
||||
Cameras& cameras) const {
|
||||
Values valuesFactor;
|
||||
|
||||
// Select only the cameras
|
||||
BOOST_FOREACH(const Key key, this->keys_)
|
||||
valuesFactor.insert(key, values.at(key));
|
||||
|
||||
myCameras = this->cameras(valuesFactor);
|
||||
size_t nrCameras = this->triangulateSafe(myCameras);
|
||||
cameras = this->cameras(valuesFactor);
|
||||
size_t nrCameras = this->triangulateSafe(cameras);
|
||||
|
||||
if (nrCameras < 2
|
||||
|| (!this->manageDegeneracy_
|
||||
|
@ -477,27 +476,22 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Assumes non-degenerate !
|
||||
void computeEP(Matrix& E, Matrix& P, const Cameras& cameras) const {
|
||||
return Base::computeEP(E, P, cameras, point_);
|
||||
}
|
||||
|
||||
/// Takes values
|
||||
bool computeEP(Matrix& E, Matrix& P, const Values& values) const {
|
||||
Cameras myCameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
Cameras cameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
computeEP(E, P, myCameras);
|
||||
Base::computeEP(E, P, cameras, point_);
|
||||
return nonDegenerate;
|
||||
}
|
||||
|
||||
/// Version that takes values, and creates the point
|
||||
bool computeJacobians(std::vector<typename Base::KeyMatrix2D>& Fblocks,
|
||||
Matrix& E, Vector& b, const Values& values) const {
|
||||
Cameras myCameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
Cameras cameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
computeJacobians(Fblocks, E, b, myCameras);
|
||||
computeJacobians(Fblocks, E, b, cameras);
|
||||
return nonDegenerate;
|
||||
}
|
||||
|
||||
|
@ -513,12 +507,13 @@ public:
|
|||
std::cout
|
||||
<< "SmartProjectionFactor: Management of degeneracy is disabled - not ready to be used"
|
||||
<< std::endl;
|
||||
if (D > 6) {
|
||||
if (Dim > 6) {
|
||||
std::cout
|
||||
<< "Management of degeneracy is not yet ready when one also optimizes for the calibration "
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// TODO replace all this by Call to CameraSet
|
||||
int numKeys = this->keys_.size();
|
||||
E = zeros(2 * numKeys, 2);
|
||||
b = zero(2 * numKeys);
|
||||
|
@ -533,7 +528,6 @@ public:
|
|||
Vector bi = -(cameras[i].projectPointAtInfinity(this->point_, Fi, Ei)
|
||||
- this->measured_.at(i)).vector();
|
||||
|
||||
this->noiseModel_->WhitenSystem(Fi, Ei, bi);
|
||||
f += bi.squaredNorm();
|
||||
Fblocks.push_back(typename Base::KeyMatrix2D(this->keys_[i], Fi));
|
||||
E.block<2, 2>(2 * i, 0) = Ei;
|
||||
|
@ -549,10 +543,10 @@ public:
|
|||
/// takes values
|
||||
bool computeJacobiansSVD(std::vector<typename Base::KeyMatrix2D>& Fblocks,
|
||||
Matrix& Enull, Vector& b, const Values& values) const {
|
||||
typename Base::Cameras myCameras;
|
||||
double good = computeCamerasAndTriangulate(values, myCameras);
|
||||
typename Base::Cameras cameras;
|
||||
double good = computeCamerasAndTriangulate(values, cameras);
|
||||
if (good)
|
||||
computeJacobiansSVD(Fblocks, Enull, b, myCameras);
|
||||
computeJacobiansSVD(Fblocks, Enull, b, cameras);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -583,12 +577,12 @@ public:
|
|||
|
||||
/// Calculate vector of re-projection errors, before applying noise model
|
||||
Vector reprojectionError(const Values& values) const {
|
||||
Cameras myCameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
Cameras cameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
return reprojectionError(myCameras);
|
||||
return reprojectionError(cameras);
|
||||
else
|
||||
return zero(myCameras.size() * 2);
|
||||
return zero(cameras.size() * 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,21 +38,22 @@ namespace gtsam {
|
|||
* @addtogroup SLAM
|
||||
*/
|
||||
template<class CALIBRATION>
|
||||
class SmartProjectionPoseFactor: public SmartProjectionFactor<CALIBRATION, 6> {
|
||||
class SmartProjectionPoseFactor: public SmartProjectionFactor<
|
||||
PinholePose<CALIBRATION> > {
|
||||
|
||||
private:
|
||||
typedef PinholePose<CALIBRATION> Camera;
|
||||
typedef SmartProjectionFactor<Camera> Base;
|
||||
typedef SmartProjectionPoseFactor<CALIBRATION> This;
|
||||
|
||||
protected:
|
||||
|
||||
LinearizationMode linearizeTo_; ///< How to linearize the factor (HESSIAN, JACOBIAN_SVD, JACOBIAN_Q)
|
||||
|
||||
std::vector<boost::shared_ptr<CALIBRATION> > K_all_; ///< shared pointer to calibration object (one for each camera)
|
||||
std::vector<boost::shared_ptr<CALIBRATION> > sharedKs_; ///< shared pointer to calibration object (one for each camera)
|
||||
|
||||
public:
|
||||
|
||||
/// shorthand for base class type
|
||||
typedef SmartProjectionFactor<CALIBRATION, 6> Base;
|
||||
|
||||
/// shorthand for this class
|
||||
typedef SmartProjectionPoseFactor<CALIBRATION> This;
|
||||
|
||||
/// shorthand for a smart pointer to a factor
|
||||
typedef boost::shared_ptr<This> shared_ptr;
|
||||
|
||||
|
@ -87,7 +88,7 @@ public:
|
|||
const SharedNoiseModel noise_i,
|
||||
const boost::shared_ptr<CALIBRATION> K_i) {
|
||||
Base::add(measured_i, poseKey_i, noise_i);
|
||||
K_all_.push_back(K_i);
|
||||
sharedKs_.push_back(K_i);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,7 +103,7 @@ public:
|
|||
std::vector<boost::shared_ptr<CALIBRATION> > Ks) {
|
||||
Base::add(measurements, poseKeys, noises);
|
||||
for (size_t i = 0; i < measurements.size(); i++) {
|
||||
K_all_.push_back(Ks.at(i));
|
||||
sharedKs_.push_back(Ks.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +118,7 @@ public:
|
|||
const SharedNoiseModel noise, const boost::shared_ptr<CALIBRATION> K) {
|
||||
for (size_t i = 0; i < measurements.size(); i++) {
|
||||
Base::add(measurements.at(i), poseKeys.at(i), noise);
|
||||
K_all_.push_back(K);
|
||||
sharedKs_.push_back(K);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +130,7 @@ public:
|
|||
void print(const std::string& s = "", const KeyFormatter& keyFormatter =
|
||||
DefaultKeyFormatter) const {
|
||||
std::cout << s << "SmartProjectionPoseFactor, z = \n ";
|
||||
BOOST_FOREACH(const boost::shared_ptr<CALIBRATION>& K, K_all_)
|
||||
BOOST_FOREACH(const boost::shared_ptr<CALIBRATION>& K, sharedKs_)
|
||||
K->print("calibration = ");
|
||||
Base::print("", keyFormatter);
|
||||
}
|
||||
|
@ -155,7 +156,7 @@ public:
|
|||
if(Base::body_P_sensor_)
|
||||
pose = pose.compose(*(Base::body_P_sensor_));
|
||||
|
||||
typename Base::Camera camera(pose, *K_all_[i++]);
|
||||
Camera camera(pose, sharedKs_[i++]);
|
||||
cameras.push_back(camera);
|
||||
}
|
||||
return cameras;
|
||||
|
@ -193,9 +194,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/** return the calibration object */
|
||||
/** return calibration shared pointers */
|
||||
inline const std::vector<boost::shared_ptr<CALIBRATION> > calibration() const {
|
||||
return K_all_;
|
||||
return sharedKs_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -205,7 +206,7 @@ private:
|
|||
template<class ARCHIVE>
|
||||
void serialize(ARCHIVE & ar, const unsigned int version) {
|
||||
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
|
||||
ar & BOOST_SERIALIZATION_NVP(K_all_);
|
||||
ar & BOOST_SERIALIZATION_NVP(sharedKs_);
|
||||
}
|
||||
|
||||
}; // end of class declaration
|
||||
|
|
|
@ -72,8 +72,8 @@ static Point2 measurement1(323.0, 240.0);
|
|||
static Pose3 body_P_sensor1(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2), Point3(0.25, -0.10, 1.0));
|
||||
|
||||
typedef PinholeCamera<Cal3_S2> CameraCal3_S2;
|
||||
typedef SmartProjectionCameraFactor<Cal3_S2, 11> SmartFactor;
|
||||
typedef SmartProjectionCameraFactor<Cal3Bundler, 9> SmartFactorBundler;
|
||||
typedef SmartProjectionCameraFactor<Cal3_S2> SmartFactor;
|
||||
typedef SmartProjectionCameraFactor<Cal3Bundler> SmartFactorBundler;
|
||||
typedef GeneralSFMFactor<Camera, Point3> SFMFactor;
|
||||
|
||||
template<class CALIBRATION>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -64,7 +64,7 @@ enum LinearizationMode {
|
|||
* SmartStereoProjectionFactor: triangulates point
|
||||
*/
|
||||
template<class CALIBRATION, size_t D>
|
||||
class SmartStereoProjectionFactor: public SmartFactorBase<StereoCamera, D> {
|
||||
class SmartStereoProjectionFactor: public SmartFactorBase<StereoCamera> {
|
||||
protected:
|
||||
|
||||
// Some triangulation parameters
|
||||
|
@ -94,7 +94,7 @@ protected:
|
|||
typedef boost::shared_ptr<SmartStereoProjectionFactorState> SmartFactorStatePtr;
|
||||
|
||||
/// shorthand for base class type
|
||||
typedef SmartFactorBase<StereoCamera, D> Base;
|
||||
typedef SmartFactorBase<StereoCamera> Base;
|
||||
|
||||
double landmarkDistanceThreshold_; // if the landmark is triangulated at a
|
||||
// distance larger than that the factor is considered degenerate
|
||||
|
@ -465,11 +465,11 @@ public:
|
|||
// /// Create a factor, takes values
|
||||
// boost::shared_ptr<JacobianFactorQ<D> > createJacobianQFactor(
|
||||
// const Values& values, double lambda) const {
|
||||
// Cameras myCameras;
|
||||
// Cameras cameras;
|
||||
// // TODO triangulate twice ??
|
||||
// bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
// bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
// if (nonDegenerate)
|
||||
// return createJacobianQFactor(myCameras, lambda);
|
||||
// return createJacobianQFactor(cameras, lambda);
|
||||
// else
|
||||
// return boost::make_shared< JacobianFactorQ<D> >(this->keys_);
|
||||
// }
|
||||
|
@ -485,15 +485,15 @@ public:
|
|||
|
||||
/// Returns true if nonDegenerate
|
||||
bool computeCamerasAndTriangulate(const Values& values,
|
||||
Cameras& myCameras) const {
|
||||
Cameras& cameras) const {
|
||||
Values valuesFactor;
|
||||
|
||||
// Select only the cameras
|
||||
BOOST_FOREACH(const Key key, this->keys_)
|
||||
valuesFactor.insert(key, values.at(key));
|
||||
|
||||
myCameras = this->cameras(valuesFactor);
|
||||
size_t nrCameras = this->triangulateSafe(myCameras);
|
||||
cameras = this->cameras(valuesFactor);
|
||||
size_t nrCameras = this->triangulateSafe(cameras);
|
||||
|
||||
if (nrCameras < 2
|
||||
|| (!this->manageDegeneracy_
|
||||
|
@ -520,20 +520,20 @@ public:
|
|||
|
||||
/// Takes values
|
||||
bool computeEP(Matrix& E, Matrix& PointCov, const Values& values) const {
|
||||
Cameras myCameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
Cameras cameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
computeEP(E, PointCov, myCameras);
|
||||
computeEP(E, PointCov, cameras);
|
||||
return nonDegenerate;
|
||||
}
|
||||
|
||||
/// Version that takes values, and creates the point
|
||||
bool computeJacobians(std::vector<typename Base::KeyMatrix2D>& Fblocks,
|
||||
Matrix& E, Vector& b, const Values& values) const {
|
||||
Cameras myCameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
Cameras cameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
computeJacobians(Fblocks, E, b, myCameras, 0.0);
|
||||
computeJacobians(Fblocks, E, b, cameras, 0.0);
|
||||
return nonDegenerate;
|
||||
}
|
||||
|
||||
|
@ -598,10 +598,10 @@ public:
|
|||
// /// takes values
|
||||
// bool computeJacobiansSVD(std::vector<typename Base::KeyMatrix2D>& Fblocks,
|
||||
// Matrix& Enull, Vector& b, const Values& values) const {
|
||||
// typename Base::Cameras myCameras;
|
||||
// double good = computeCamerasAndTriangulate(values, myCameras);
|
||||
// typename Base::Cameras cameras;
|
||||
// double good = computeCamerasAndTriangulate(values, cameras);
|
||||
// if (good)
|
||||
// computeJacobiansSVD(Fblocks, Enull, b, myCameras);
|
||||
// computeJacobiansSVD(Fblocks, Enull, b, cameras);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
|
@ -624,20 +624,14 @@ public:
|
|||
return Base::computeJacobians(F, E, b, cameras, point_);
|
||||
}
|
||||
|
||||
/// Calculate vector of re-projection errors, before applying noise model
|
||||
/// Assumes triangulation was done and degeneracy handled
|
||||
Vector reprojectionError(const Cameras& cameras) const {
|
||||
return Base::reprojectionError(cameras, point_);
|
||||
}
|
||||
|
||||
/// Calculate vector of re-projection errors, before applying noise model
|
||||
Vector reprojectionError(const Values& values) const {
|
||||
Cameras myCameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, myCameras);
|
||||
Cameras cameras;
|
||||
bool nonDegenerate = computeCamerasAndTriangulate(values, cameras);
|
||||
if (nonDegenerate)
|
||||
return reprojectionError(myCameras);
|
||||
return cameras.reprojectionErrors(point_);
|
||||
else
|
||||
return zero(myCameras.size() * 3);
|
||||
return zero(cameras.size() * 3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue