28 #include <Eigen/StdVector> 29 #include <Eigen/Geometry> 44 #include "EXTERNAL/ceres/autodiff.h" 46 #if defined G2O_HAVE_CHOLMOD 48 #elif defined G2O_HAVE_CSPARSE 54 using namespace Eigen;
73 virtual bool read(std::istream& )
79 virtual bool write(std::ostream& )
const 110 virtual bool read(std::istream& )
116 virtual bool write(std::ostream& )
const 129 Eigen::Vector3d::ConstMapType v(update);
163 virtual bool read(std::istream& )
168 virtual bool write(std::ostream& )
const 175 inline void cross(
const T x[3],
const T y[3], T result[3])
const 177 result[0] = x[1] * y[2] - x[2] * y[1];
178 result[1] = x[2] * y[0] - x[0] * y[2];
179 result[2] = x[0] * y[1] - x[1] * y[0];
183 inline T
dot(
const T x[3],
const T y[3])
const {
return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]);}
192 bool operator()(
const T* camera,
const T* point, T* error)
const 196 T theta = sqrt(squaredNorm(camera));
199 v[0] = camera[0] / theta;
200 v[1] = camera[1] / theta;
201 v[2] = camera[2] / theta;
206 cross(v, point, vXp);
207 T vDotp = dot(v, point);
208 T oneMinusCth = T(1) - cth;
210 for (
int i = 0; i < 3; ++i)
211 p[i] = point[i] * cth + vXp[i] * sth + v[i] * vDotp * oneMinusCth;
215 cross(camera, point, aux);
216 for (
int i = 0; i < 3; ++i)
217 p[i] = point[i] + aux[i];
227 projectedPoint[0] = - p[0] / p[2];
228 projectedPoint[1] = - p[1] / p[2];
231 T radiusSqr = projectedPoint[0]*projectedPoint[0] + projectedPoint[1]*projectedPoint[1];
235 T r_p = T(1) + k1 * radiusSqr + k2 * radiusSqr * radiusSqr;
237 prediction[0] = f * r_p * projectedPoint[0];
238 prediction[1] = f * r_p * projectedPoint[1];
240 error[0] = prediction[0] - T(measurement()(0));
241 error[1] = prediction[1] - T(measurement()(1));
262 typedef ceres::internal::AutoDiff<EdgeObservationBAL, double, VertexCameraBAL::Dimension, VertexPointBAL::Dimension> BalAutoDiff;
264 Matrix<double, Dimension, VertexCameraBAL::Dimension, Eigen::RowMajor> dError_dCamera;
265 Matrix<double, Dimension, VertexPointBAL::Dimension, Eigen::RowMajor> dError_dPoint;
266 double *parameters[] = {
const_cast<double*
>(cam->
estimate().data()), const_cast<double*>(point->
estimate().data()) };
267 double *jacobians[] = { dError_dCamera.data(), dError_dPoint.data() };
268 double value[Dimension];
269 bool diffState = BalAutoDiff::Differentiate(*
this, parameters, Dimension, value, jacobians);
273 _jacobianOplusXi = dError_dCamera;
274 _jacobianOplusXj = dError_dPoint;
276 assert(0 &&
"Error while differentiating");
277 _jacobianOplusXi.setZero();
278 _jacobianOplusXi.setZero();
283 int main(
int argc,
char** argv)
288 string outputFilename;
289 string inputFilename;
290 string statsFilename;
292 arg.
param(
"i", maxIterations, 5,
"perform n iterations");
293 arg.
param(
"o", outputFilename,
"",
"write points into a vrml file");
294 arg.
param(
"pcg", usePCG,
false,
"use PCG instead of the Cholesky");
295 arg.
param(
"v", verbose,
false,
"verbose output of the optimization process");
296 arg.
param(
"stats", statsFilename,
"",
"specify a file for the statistics");
297 arg.
paramLeftOver(
"graph-input", inputFilename,
"",
"file which will be processed");
302 #ifdef G2O_HAVE_CHOLMOD 303 string choleskySolverName =
"CHOLMOD";
305 #elif defined G2O_HAVE_CSPARSE 306 string choleskySolverName =
"CSparse";
309 #error neither CSparse nor CHOLMOD are available 316 cout <<
"Using PCG" << endl;
317 linearSolver =
new BalLinearSolverPCG();
319 cout <<
"Using Cholesky: " << choleskySolverName << endl;
320 BalLinearSolver* cholesky =
new BalLinearSolver();
321 cholesky->setBlockOrdering(
true);
322 linearSolver = cholesky;
324 BalBlockSolver* solver_ptr =
new BalBlockSolver(linearSolver);
328 if (statsFilename.size() > 0){
332 vector<VertexPointBAL*> points;
333 vector<VertexCameraBAL*> cameras;
336 cout <<
"Loading BAL dataset " << inputFilename << endl;
338 ifstream ifs(inputFilename.c_str());
339 int numCameras, numPoints, numObservations;
340 ifs >> numCameras >> numPoints >> numObservations;
342 cerr << PVAR(numCameras) <<
" " << PVAR(numPoints) <<
" " << PVAR(numObservations) << endl;
345 cameras.reserve(numCameras);
346 for (
int i = 0; i < numCameras; ++i, ++id) {
350 cameras.push_back(cam);
353 points.reserve(numPoints);
354 for (
int i = 0; i < numPoints; ++i, ++id) {
358 bool addedVertex = optimizer.
addVertex(p);
360 cerr <<
"failing adding vertex" << endl;
366 for (
int i = 0; i < numObservations; ++i) {
367 int camIndex, pointIndex;
369 ifs >> camIndex >> pointIndex >> obsX >> obsY;
371 assert(camIndex >= 0 && (
size_t)camIndex < cameras.size() &&
"Index out of bounds");
373 assert(pointIndex >= 0 && (
size_t)pointIndex < points.size() &&
"Index out of bounds");
381 bool addedEdge = optimizer.
addEdge(e);
383 cerr <<
"error adding edge" << endl;
388 Eigen::VectorXd cameraParameter(9);
389 for (
int i = 0; i < numCameras; ++i) {
390 for (
int j = 0; j < 9; ++j)
391 ifs >> cameraParameter(j);
398 for (
int i = 0; i < numPoints; ++i) {
399 ifs >> p(0) >> p(1) >> p(2);
406 cout <<
"done." << endl;
408 cout <<
"Initializing ... " << flush;
410 cout <<
"done." << endl;
412 cout <<
"Start to optimize" << endl;
415 if (statsFilename!=
""){
416 cerr <<
"writing stats to file \"" << statsFilename <<
"\" ... ";
417 ofstream fout(statsFilename.c_str());
419 for (
size_t i=0; i<bsc.size(); i++)
420 fout << bsc[i] << endl;
421 cerr <<
"done." << endl;
425 if (outputFilename.size() > 0) {
426 ofstream fout(outputFilename.c_str());
428 <<
"#VRML V2.0 utf8\n" 430 <<
" appearance Appearance {\n" 431 <<
" material Material {\n" 432 <<
" diffuseColor " << 1 <<
" " << 0 <<
" " << 0 <<
"\n" 433 <<
" ambientIntensity 0.2\n" 434 <<
" emissiveColor 0.0 0.0 0.0\n" 435 <<
" specularColor 0.0 0.0 0.0\n" 436 <<
" shininess 0.2\n" 437 <<
" transparency 0.0\n" 440 <<
" geometry PointSet {\n" 441 <<
" coord Coordinate {\n" 443 for (vector<VertexPointBAL*>::const_iterator it = points.begin(); it != points.end(); ++it) {
444 fout << (*it)->estimate().transpose() << endl;
446 fout <<
" ]\n" <<
" }\n" <<
"}\n" <<
" }\n";
virtual void oplusImpl(const double *update)
const BatchStatisticsContainer & batchStatistics() const
virtual bool read(std::istream &)
read the vertex from a stream, i.e., the internal state of the vertex
#define __PRETTY_FUNCTION__
Command line parsing of argc and argv.
void setComputeBatchStatistics(bool computeBatchStatistics)
Implementation of the Levenberg Algorithm.
int optimize(int iterations, bool online=false)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
virtual void setMeasurement(const Measurement &m)
virtual bool read(std::istream &)
read the vertex from a stream, i.e., the internal state of the vertex
linear solver using PCG, pre-conditioner is block Jacobi
void setVertex(size_t i, Vertex *v)
void cross(const T x[3], const T y[3], T result[3]) const
virtual void oplusImpl(const double *update)
virtual void setId(int id)
sets the id of the node in the graph be sure that the graph keeps consistent after changing the id ...
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
bool parseArgs(int argc, char **argv, bool exitOnError=true)
void setVerbose(bool verbose)
linear solver which uses CSparse
void paramLeftOver(const std::string &name, std::string &p, const std::string &defValue, const std::string &desc, bool optional=false)
void setAlgorithm(OptimizationAlgorithm *algorithm)
EIGEN_STRONG_INLINE void setInformation(const InformationType &information)
virtual bool read(std::istream &)
read the vertex from a stream, i.e., the internal state of the vertex
void param(const std::string &name, bool &p, bool defValue, const std::string &desc)
basic solver for Ax = b which has to reimplemented for different linear algebra libraries ...
void setEstimate(const EstimateType &et)
set the estimate for the vertex also calls updateCache()
virtual bool write(std::ostream &) const
write the vertex to a stream
void setMarginalized(bool marginalized)
true => this node should be marginalized out during the optimization
edge representing the observation of a world feature by a camera
bool operator()(const T *camera, const T *point, T *error) const
virtual bool write(std::ostream &) const
write the vertex to a stream
const EstimateType & estimate() const
return the current estimate of the vertex
Implementation of a solver operating on the blocks of the Hessian.
T dot(const T x[3], const T y[3]) const
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)
int main(int argc, char **argv)
virtual void setToOriginImpl()
sets the node to the origin (used in the multilevel stuff)
std::vector< G2OBatchStatistics > BatchStatisticsContainer
static const int Dimension
dimension of the estimate (minimal) in the manifold space
virtual bool write(std::ostream &) const
write the vertex to a stream
virtual void setToOriginImpl()
sets the node to the origin (used in the multilevel stuff)
T squaredNorm(const T x[3]) const
camera vertex which stores the parameters for a pinhole camera