28#include <Eigen/Geometry>
45#if defined G2O_HAVE_CHOLMOD
74 bool read(std::istream& )
override {
79 bool write(std::ostream& )
const override {
104 bool read(std::istream& )
override {
109 bool write(std::ostream& )
const override {
119 g2o::Vector3::ConstMapType v(update);
152 bool read(std::istream& )
override {
156 bool write(std::ostream& )
const override {
164 template <
typename T>
165 bool operator()(
const T* p_camera,
const T* p_point, T* p_error)
const {
172 T theta = camera.template head<3>().norm();
179 T vDotp = v.dot(point);
180 T oneMinusCth = T(1) - cth;
182 p = point * cth + vXp * sth + v * vDotp * oneMinusCth;
185 p = point + camera.template head<3>().cross(point);
189 p += camera.template segment<3>(3);
195 T radiusSqr = projectedPoint.squaredNorm();
196 const T& f = camera(6);
197 const T& k1 = camera(7);
198 const T& k2 = camera(8);
199 T r_p = T(1) + k1 * radiusSqr + k2 * radiusSqr * radiusSqr;
212int main(
int argc,
char** argv) {
216 string outputFilename;
217 string inputFilename;
218 string statsFilename;
220 arg.
param(
"i", maxIterations, 5,
"perform n iterations");
221 arg.
param(
"o", outputFilename,
"",
"write points into a vrml file");
222 arg.
param(
"pcg", usePCG,
false,
"use PCG instead of the Cholesky");
223 arg.
param(
"v", verbose,
false,
"verbose output of the optimization process");
224 arg.
param(
"stats", statsFilename,
"",
"specify a file for the statistics");
226 "file which will be processed");
231 using BalLinearSolverPCG =
235 std::unique_ptr<g2o::LinearSolver<BalBlockSolver::PoseMatrixType>>
238 cout <<
"Using PCG" << endl;
239 linearSolver = std::make_unique<BalLinearSolverPCG>();
241#ifdef G2O_HAVE_CHOLMOD
242 string_view choleskySolverName =
"CHOLMOD";
243 using BalLinearSolver =
246 string_view choleskySolverName =
"Eigen";
247 using BalLinearSolver =
250 cout <<
"Using Cholesky: " << choleskySolverName << endl;
251 auto cholesky = std::make_unique<BalLinearSolver>();
252 cholesky->setBlockOrdering(
true);
253 linearSolver = std::move(cholesky);
257 std::make_unique<BalBlockSolver>(std::move(linearSolver)));
261 if (statsFilename.size() > 0) {
265 vector<VertexPointBAL*> points;
266 vector<VertexCameraBAL*> cameras;
269 cout <<
"Loading BAL dataset " << inputFilename << endl;
271 ifstream ifs(inputFilename.c_str());
272 int numCameras, numPoints, numObservations;
273 ifs >> numCameras >> numPoints >> numObservations;
275 cerr << PVAR(numCameras) <<
" " << PVAR(numPoints) <<
" "
276 << PVAR(numObservations) << endl;
279 cameras.reserve(numCameras);
280 for (
int i = 0; i < numCameras; ++i, ++id) {
284 cameras.push_back(cam);
287 points.reserve(numPoints);
288 for (
int i = 0; i < numPoints; ++i, ++id) {
292 bool addedVertex = optimizer.
addVertex(p);
294 cerr <<
"failing adding vertex" << endl;
300 for (
int i = 0; i < numObservations; ++i) {
301 int camIndex, pointIndex;
303 ifs >> camIndex >> pointIndex >> obsX >> obsY;
305 assert(camIndex >= 0 && (
size_t)camIndex < cameras.size() &&
306 "Index out of bounds");
308 assert(pointIndex >= 0 && (
size_t)pointIndex < points.size() &&
309 "Index out of bounds");
317 bool addedEdge = optimizer.
addEdge(e);
319 cerr <<
"error adding edge" << endl;
324 for (
int i = 0; i < numCameras; ++i) {
326 for (
int j = 0; j < 9; ++j) ifs >> cameraParameter(j);
332 for (
int i = 0; i < numPoints; ++i) {
334 ifs >> p(0) >> p(1) >> p(2);
339 cout <<
"done." << endl;
341 cout <<
"Initializing ... " << flush;
343 cout <<
"done." << endl;
345 cout <<
"Start to optimize" << endl;
348 if (statsFilename !=
"") {
349 cerr <<
"writing stats to file \"" << statsFilename <<
"\" ... ";
350 ofstream fout(statsFilename.c_str());
352 for (
size_t i = 0; i < bsc.size(); i++) fout << bsc[i] << endl;
353 cerr <<
"done." << endl;
357 if (outputFilename.size() > 0) {
358 ofstream fout(outputFilename.c_str());
359 fout <<
"#VRML V2.0 utf8\n"
361 <<
" appearance Appearance {\n"
362 <<
" material Material {\n"
363 <<
" diffuseColor " << 1 <<
" " << 0 <<
" " << 0 <<
"\n"
364 <<
" ambientIntensity 0.2\n"
365 <<
" emissiveColor 0.0 0.0 0.0\n"
366 <<
" specularColor 0.0 0.0 0.0\n"
367 <<
" shininess 0.2\n"
368 <<
" transparency 0.0\n"
371 <<
" geometry PointSet {\n"
372 <<
" coord Coordinate {\n"
374 for (vector<VertexPointBAL*>::const_iterator it = points.begin();
375 it != points.end(); ++it) {
376 fout << (*it)->estimate().transpose() << endl;
#define G2O_MAKE_AUTO_AD_FUNCTIONS
edge representing the observation of a world feature by a camera
bool write(std::ostream &) const override
write the vertex to a stream
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
bool operator()(const T *p_camera, const T *p_point, T *p_error) const
bool read(std::istream &) override
read the vertex from a stream, i.e., the internal state of the vertex
camera vertex which stores the parameters for a pinhole camera
bool read(std::istream &) override
read the vertex from a stream, i.e., the internal state of the vertex
bool write(std::ostream &) const override
write the vertex to a stream
void oplusImpl(const double *update) override
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
void setToOriginImpl() override
sets the node to the origin (used in the multilevel stuff)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
void setToOriginImpl() override
sets the node to the origin (used in the multilevel stuff)
bool write(std::ostream &) const override
write the vertex to a stream
void oplusImpl(const double *update) override
bool read(std::istream &) override
read the vertex from a stream, i.e., the internal state of the vertex
EIGEN_STRONG_INLINE const Measurement & measurement() const
accessor functions for the measurement represented by the edge
virtual void setMeasurement(const Measurement &m)
void setInformation(const InformationType &information)
const ErrorVector & error() const
static const int Dimension
dimension of the estimate (minimal) in the manifold space
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
Implementation of a solver operating on the blocks of the Hessian.
Command line parsing of argc and argv.
bool parseArgs(int argc, char **argv, bool exitOnError=true)
void paramLeftOver(const std::string &name, std::string &p, const std::string &defValue, const std::string &desc, bool optional=false)
void param(const std::string &name, bool &p, bool defValue, const std::string &desc)
void setVertex(size_t i, Vertex *v)
basic solver for Ax = b which has to reimplemented for different linear algebra libraries
linear solver which uses the sparse Cholesky solver from Eigen
linear solver using PCG, pre-conditioner is block Jacobi
virtual void setId(int id)
void setMarginalized(bool marginalized)
true => this node should be marginalized out during the optimization
Implementation of the Levenberg Algorithm.
int optimize(int iterations, bool online=false)
void setVerbose(bool verbose)
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
void setAlgorithm(OptimizationAlgorithm *algorithm)
const BatchStatisticsContainer & batchStatistics() const
void setComputeBatchStatistics(bool computeBatchStatistics)
#define __PRETTY_FUNCTION__
Eigen::Matrix< T, N, 1, Eigen::ColMajor > VectorN
std::vector< G2OBatchStatistics > BatchStatisticsContainer
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)