35 template <
class CAMERA>
36 class CameraSet :
public std::vector<CAMERA, Eigen::aligned_allocator<CAMERA>> {
38 using Base = std::vector<CAMERA, typename Eigen::aligned_allocator<CAMERA>>;
44 typedef typename CAMERA::Measurement
Z;
45 typedef typename CAMERA::MeasurementVector ZVector;
51 static Vector
ErrorVector(
const ZVector& predicted,
const ZVector& measured) {
53 size_t m = predicted.size();
54 if (measured.size() != m)
55 throw std::runtime_error(
"CameraSet::errors: size mismatch");
59 for (
size_t i = 0,
row = 0; i < m; i++,
row +=
ZDim) {
61 if (ZDim == 3 && std::isnan(bi(1))) {
65 b.segment<ZDim>(
row) = bi;
77 using MatrixZD = Eigen::Matrix<double, ZDim, D>;
78 using FBlocks = std::vector<MatrixZD, Eigen::aligned_allocator<MatrixZD>>;
85 virtual void print(
const std::string& s =
"")
const {
86 std::cout << s <<
"CameraSet, cameras = \n";
87 for (
size_t k = 0; k < this->size(); ++k) this->at(k).print(s);
92 if (this->size() != p.size())
return false;
93 bool camerasAreEqual =
true;
94 for (
size_t i = 0; i < this->size(); i++) {
95 if (this->at(i).equals(p.at(i), tol) ==
false) camerasAreEqual =
false;
98 return camerasAreEqual;
107 template <
class POINT>
109 FBlocks* Fs =
nullptr,
110 Matrix* E =
nullptr)
const {
114 size_t m = this->size();
119 if (E) E->resize(ZDim * m, N);
120 if (Fs) Fs->resize(m);
123 for (
size_t i = 0; i < m; i++) {
125 Eigen::Matrix<double, ZDim, N> Ei;
126 z.emplace_back(this->at(i).
project2(point, Fs ? &Fi : 0, E ? &Ei : 0));
127 if (Fs) (*Fs)[i] = Fi;
128 if (E) E->block<
ZDim, N>(ZDim * i, 0) = Ei;
138 template <
class POINT,
class... OptArgs>
139 ZVector
project2(
const POINT& point, OptArgs&... args)
const {
145 template <
class POINT>
147 FBlocks* Fs =
nullptr,
148 Matrix* E =
nullptr)
const {
156 template <
class POINT,
class... OptArgs,
typename =
std::enable_if_t<
sizeof...(OptArgs)!=0>>
158 OptArgs&... args)
const {
173 Eigen::Matrix<double, ZDim, ND>,
174 Eigen::aligned_allocator<Eigen::Matrix<double, ZDim, ND>>>& Fs,
175 const Matrix& E,
const Eigen::Matrix<double, N, N>& P,
const Vector& b) {
177 size_t m = Fs.size();
181 size_t M1 = ND * m + 1;
182 std::vector<DenseIndex> dims(m + 1);
183 std::fill(dims.begin(), dims.end() - 1, ND);
188 for (
size_t i = 0; i < m; i++) {
190 const Eigen::Matrix<double, ZDim, ND>& Fi = Fs[i];
191 const auto FiT = Fi.transpose();
192 const Eigen::Matrix<double, ZDim, N> Ei_P =
193 E.block(ZDim * i, 0, ZDim, N) * P;
198 FiT * b.segment<ZDim>(ZDim * i)
208 FiT * (Fi - Ei_P * E.block(ZDim * i, 0, ZDim, N).transpose() * Fi));
211 for (
size_t j = i + 1; j < m; j++) {
212 const Eigen::Matrix<double, ZDim, ND>& Fj = Fs[j];
217 -FiT * (Ei_P * E.block(ZDim * j, 0, ZDim, N).transpose() * Fj));
222 return augmentedHessian;
238 template <
int N,
int ND,
int NDD>
241 Eigen::Matrix<double, ZDim, ND>,
242 Eigen::aligned_allocator<Eigen::Matrix<double, ZDim, ND>>>& Fs,
243 const Matrix& E,
const Eigen::Matrix<double, N, N>& P,
const Vector& b,
245 size_t nrNonuniqueKeys = jacobianKeys.size();
246 size_t nrUniqueKeys = hessianKeys.size();
252 std::vector<DenseIndex> dims(nrUniqueKeys + 1);
253 std::fill(dims.begin(), dims.end() - 1, NDD);
258 if (nrUniqueKeys == nrNonuniqueKeys) {
265 std::vector<DenseIndex> nonuniqueDims(nrNonuniqueKeys + 1);
266 std::fill(nonuniqueDims.begin(), nonuniqueDims.end() - 1, NDD);
267 nonuniqueDims.back() = 1;
273 std::map<Key, size_t> keyToSlotMap;
274 for (
size_t k = 0; k < nrUniqueKeys; k++) {
275 keyToSlotMap[hessianKeys[k]] = k;
280 dims, Matrix::Zero(NDD * nrUniqueKeys + 1, NDD * nrUniqueKeys + 1));
285 for (
size_t i = 0; i < nrNonuniqueKeys; i++) {
286 Key key_i = jacobianKeys.at(i);
290 keyToSlotMap[key_i], nrUniqueKeys,
294 for (
size_t j = i; j < nrNonuniqueKeys; j++) {
295 Key key_j = jacobianKeys.at(j);
300 if (keyToSlotMap[key_i] != keyToSlotMap[key_j]) {
302 keyToSlotMap[key_i], keyToSlotMap[key_j],
316 nrUniqueKeys, augmentedHessian.
diagonalBlock(nrNonuniqueKeys));
318 return augmentedHessianUniqueKeys;
329 const FBlocks& Fs,
const Matrix& E,
const Eigen::Matrix<double, N, N>& P,
331 return SchurComplement<N, D>(Fs, E, P, b);
337 const Matrix& E,
double lambda,
338 bool diagonalDamping =
false) {
339 Matrix EtE = E.transpose() * E;
341 if (diagonalDamping) {
342 EtE.diagonal() += lambda * EtE.diagonal();
345 EtE += lambda * Eigen::MatrixXd::Identity(n, n);
352 static Matrix
PointCov(
const Matrix& E,
const double lambda = 0.0,
353 bool diagonalDamping =
false) {
356 ComputePointCovariance<2>(P2, E, lambda, diagonalDamping);
360 ComputePointCovariance<3>(P3, E, lambda, diagonalDamping);
370 const Matrix& E,
const Vector& b,
371 const double lambda = 0.0,
372 bool diagonalDamping =
false) {
375 ComputePointCovariance<2>(P, E, lambda, diagonalDamping);
376 return SchurComplement<2>(Fblocks, E, P, b);
379 ComputePointCovariance<3>(P, E, lambda, diagonalDamping);
380 return SchurComplement<3>(Fblocks, E, P, b);
391 const FBlocks& Fs,
const Matrix& E,
const Eigen::Matrix<double, N, N>& P,
394 assert(keys.size() == Fs.size());
395 assert(keys.size() <= allKeys.size());
398 for (
size_t slot = 0; slot < allKeys.size(); slot++)
399 KeySlotMap.emplace(allKeys[slot], slot);
406 size_t m = Fs.size();
407 size_t M = (augmentedHessian.
rows() - 1) / D;
408 assert(allKeys.size() == M);
411 for (
size_t i = 0; i < m; i++) {
414 const auto FiT = Fi.transpose();
415 const Eigen::Matrix<double, 2, N> Ei_P =
416 E.template block<ZDim, N>(ZDim * i, 0) * P;
429 FiT * b.segment<ZDim>(ZDim * i)
444 Ei_P * E.template block<ZDim, N>(ZDim * i, 0).transpose() * Fi)))
448 for (
size_t j = i + 1; j < m; j++) {
459 -FiT * (Ei_P * E.template block<ZDim, N>(ZDim * j, 0).transpose() *
468 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION 469 friend class boost::serialization::access; 471 template <
class ARCHIVE>
472 void serialize(ARCHIVE& ar,
const unsigned int ) {
481 template <
class CAMERA>
484 template <
class CAMERA>
487 template <
class CAMERA>
490 template <
class CAMERA>
typename std::enable_if< B, T >::type enable_if_t
An shorthand alias for accessing the ::type inside std::enable_if that can be used in a template dire...
Definition: make_shared.h:30
static Matrix PointCov(const Matrix &E, const double lambda=0.0, bool diagonalDamping=false)
Computes Point Covariance P, with lambda parameter, dynamic version.
Definition: CameraSet.h:352
const MATRIX::ConstRowXpr row(const MATRIX &A, size_t j)
Definition: Matrix.h:221
static SymmetricBlockMatrix SchurComplementAndRearrangeBlocks(const std::vector< Eigen::Matrix< double, ZDim, ND >, Eigen::aligned_allocator< Eigen::Matrix< double, ZDim, ND >>> &Fs, const Matrix &E, const Eigen::Matrix< double, N, N > &P, const Vector &b, const KeyVector &jacobianKeys, const KeyVector &hessianKeys)
Definition: CameraSet.h:239
bool equals(const CameraSet &p, double tol=1e-9) const
equals
Definition: CameraSet.h:91
Concept check for values that can be used in unit tests.
Access to matrices via blocks of pre-defined sizes. Used in GaussianFactor and GaussianConditional.
void setOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType &xpr)
Set an off-diagonal block. Only the upper triangular portion of xpr is evaluated. ...
Definition: SymmetricBlockMatrix.h:203
std::string serialize(const T &input)
serializes to a string
Definition: serialization.h:113
Definition: Testable.h:152
Vector reprojectionError(const POINT &point, const ZVector &measured, OptArgs &... args) const
Definition: CameraSet.h:157
Give fixed size dimension of a type, fails at compile time if dynamic.
Definition: Manifold.h:161
Vector reprojectionError(const POINT &point, const ZVector &measured, FBlocks *Fs=nullptr, Matrix *E=nullptr) const
Calculate vector [project2(point)-z] of re-projection errors.
Definition: CameraSet.h:146
virtual ~CameraSet()=default
Destructor.
static Vector ErrorVector(const ZVector &predicted, const ZVector &measured)
Make a vector of re-projection errors.
Definition: CameraSet.h:51
A set of cameras, all with their own calibration.
Definition: CameraSet.h:36
static SymmetricBlockMatrix SchurComplement(const std::vector< Eigen::Matrix< double, ZDim, ND >, Eigen::aligned_allocator< Eigen::Matrix< double, ZDim, ND >>> &Fs, const Matrix &E, const Eigen::Matrix< double, N, N > &P, const Vector &b)
Definition: CameraSet.h:171
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:108
Definition: SymmetricBlockMatrix.h:53
static const int D
Camera dimension.
Definition: CameraSet.h:47
ZVector project2(const POINT &point, FBlocks *Fs=nullptr, Matrix *E=nullptr) const
Definition: CameraSet.h:108
Eigen::SelfAdjointView< constBlock, Eigen::Upper > selfadjointView(DenseIndex I, DenseIndex J) const
Return the square sub-matrix that contains blocks(i:j, i:j).
Definition: SymmetricBlockMatrix.h:158
DenseIndex rows() const
Row size.
Definition: SymmetricBlockMatrix.h:116
void setDiagonalBlock(DenseIndex I, const XprType &xpr)
Set a diagonal block. Only the upper triangular portion of xpr is evaluated.
Definition: SymmetricBlockMatrix.h:197
virtual void print(const std::string &s="") const
Definition: CameraSet.h:85
static SymmetricBlockMatrix SchurComplement(const FBlocks &Fblocks, const Matrix &E, const Vector &b, const double lambda=0.0, bool diagonalDamping=false)
Definition: CameraSet.h:369
CAMERA::Measurement Z
Definition: CameraSet.h:44
void updateDiagonalBlock(DenseIndex I, const XprType &xpr)
Increment the diagonal block by the values in xpr. Only reads the upper triangular part of xpr...
Definition: SymmetricBlockMatrix.h:214
static const int ZDim
Measurement dimension.
Definition: CameraSet.h:48
Calibrated camera for which only pose is unknown.
Definition: chartTesting.h:28
A thin wrapper around std::map that uses boost's fast_pool_allocator.
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:86
static void ComputePointCovariance(Eigen::Matrix< double, N, N > &P, const Matrix &E, double lambda, bool diagonalDamping=false)
Computes Point Covariance P, with lambda parameter.
Definition: CameraSet.h:336
Eigen::Matrix< double, ZDim, D > MatrixZD
Definitions for blocks of F.
Definition: CameraSet.h:77
#define GTSAM_MAKE_ALIGNED_OPERATOR_NEW
Definition: types.h:284
void updateOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType &xpr)
Definition: SymmetricBlockMatrix.h:230
Eigen::SelfAdjointView< Block, Eigen::Upper > diagonalBlock(DenseIndex J)
Return the J'th diagonal block as a self adjoint view.
Definition: SymmetricBlockMatrix.h:137
static void UpdateSchurComplement(const FBlocks &Fs, const Matrix &E, const Eigen::Matrix< double, N, N > &P, const Vector &b, const KeyVector &allKeys, const KeyVector &keys, SymmetricBlockMatrix &augmentedHessian)
Definition: CameraSet.h:390
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
constBlock aboveDiagonalBlock(DenseIndex I, DenseIndex J) const
Get block above the diagonal (I, J).
Definition: SymmetricBlockMatrix.h:152
ZVector project2(const POINT &point, OptArgs &... args) const
Definition: CameraSet.h:139
static SymmetricBlockMatrix SchurComplement(const FBlocks &Fs, const Matrix &E, const Eigen::Matrix< double, N, N > &P, const Vector &b)
Definition: CameraSet.h:328