212 {
213 int maxIterations;
214 bool verbose;
215 bool usePCG;
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");
227
229
231 using BalLinearSolverPCG =
233
235 std::unique_ptr<g2o::LinearSolver<BalBlockSolver::PoseMatrixType>>
236 linearSolver;
237 if (usePCG) {
238 cout << "Using PCG" << endl;
239 linearSolver = std::make_unique<BalLinearSolverPCG>();
240 } else {
241#ifdef G2O_HAVE_CHOLMOD
242 string_view choleskySolverName = "CHOLMOD";
243 using BalLinearSolver =
245#else
246 string_view choleskySolverName = "Eigen";
247 using BalLinearSolver =
249#endif
250 cout << "Using Cholesky: " << choleskySolverName << endl;
251 auto cholesky = std::make_unique<BalLinearSolver>();
252 cholesky->setBlockOrdering(true);
253 linearSolver = std::move(cholesky);
254 }
257 std::make_unique<BalBlockSolver>(std::move(linearSolver)));
258
259
261 if (statsFilename.size() > 0) {
263 }
264
265 vector<VertexPointBAL*> points;
266 vector<VertexCameraBAL*> cameras;
267
268
269 cout << "Loading BAL dataset " << inputFilename << endl;
270 {
271 ifstream ifs(inputFilename.c_str());
272 int numCameras, numPoints, numObservations;
273 ifs >> numCameras >> numPoints >> numObservations;
274
275 cerr << PVAR(numCameras) << " " << PVAR(numPoints) << " "
276 << PVAR(numObservations) << endl;
277
278 int id = 0;
279 cameras.reserve(numCameras);
280 for (int i = 0; i < numCameras; ++i, ++id) {
284 cameras.push_back(cam);
285 }
286
287 points.reserve(numPoints);
288 for (int i = 0; i < numPoints; ++i, ++id) {
292 bool addedVertex = optimizer.
addVertex(p);
293 if (!addedVertex) {
294 cerr << "failing adding vertex" << endl;
295 }
296 points.push_back(p);
297 }
298
299
300 for (int i = 0; i < numObservations; ++i) {
301 int camIndex, pointIndex;
302 double obsX, obsY;
303 ifs >> camIndex >> pointIndex >> obsX >> obsY;
304
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");
311
317 bool addedEdge = optimizer.
addEdge(e);
318 if (!addedEdge) {
319 cerr << "error adding edge" << endl;
320 }
321 }
322
323
324 for (int i = 0; i < numCameras; ++i) {
326 for (int j = 0; j < 9; ++j) ifs >> cameraParameter(j);
329 }
330
331
332 for (int i = 0; i < numPoints; ++i) {
334 ifs >> p(0) >> p(1) >> p(2);
337 }
338 }
339 cout << "done." << endl;
340
341 cout << "Initializing ... " << flush;
343 cout << "done." << endl;
345 cout << "Start to optimize" << endl;
347
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;
354 }
355
356
357 if (outputFilename.size() > 0) {
358 ofstream fout(outputFilename.c_str());
359 fout << "#VRML V2.0 utf8\n"
360 << "Shape {\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"
369 << " }\n"
370 << " }\n"
371 << " geometry PointSet {\n"
372 << " coord Coordinate {\n"
373 << " point [\n";
374 for (vector<VertexPointBAL*>::const_iterator it = points.begin();
375 it != points.end(); ++it) {
376 fout << (*it)->estimate().transpose() << endl;
377 }
378 fout << " ]\n"
379 << " }\n"
380 << "}\n"
381 << " }\n";
382 }
383
384 return 0;
385}
edge representing the observation of a world feature by a camera
camera vertex which stores the parameters for a pinhole camera
virtual void setMeasurement(const Measurement &m)
void setInformation(const InformationType &information)
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)
std::vector< G2OBatchStatistics > BatchStatisticsContainer
virtual bool addEdge(HyperGraph::Edge *e)
virtual bool addVertex(HyperGraph::Vertex *v, Data *userData)