/* ---------------------------------------------------------------------------- * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) * See LICENSE for the license information * -------------------------------------------------------------------------- */ /** * @file InitializePose.h * @author Frank Dellaert * @date August, 2020 * @brief common code between lago.* (2D) and InitializePose3.* (3D) */ #pragma once #include #include #include #include #include namespace gtsam { namespace initialize { static constexpr Key kAnchorKey = 99999999; /** * Select the subgraph of betweenFactors and transforms priors into between * wrt a fictitious node */ template static NonlinearFactorGraph buildPoseGraph(const NonlinearFactorGraph& graph) { NonlinearFactorGraph poseGraph; for (const auto& factor : graph) { // recast to a between on Pose if (auto between = boost::dynamic_pointer_cast >(factor)) poseGraph.add(between); // recast PriorFactor to BetweenFactor if (auto prior = boost::dynamic_pointer_cast >(factor)) poseGraph.emplace_shared >( kAnchorKey, prior->keys()[0], prior->prior(), prior->noiseModel()); } return poseGraph; } /** * Use Gauss-Newton optimizer to optimize for poses given rotation estimates */ template static Values computePoses(const Values& initialRot, NonlinearFactorGraph* posegraph, bool singleIter = true) { const auto origin = Pose().translation(); // Upgrade rotations to full poses Values initialPose; for (const auto key_value : initialRot) { Key key = key_value.key; const auto& rot = initialRot.at(key); Pose initializedPose = Pose(rot, origin); initialPose.insert(key, initializedPose); } // add prior on dummy node auto priorModel = noiseModel::Unit::Create(Pose::dimension); initialPose.insert(kAnchorKey, Pose()); posegraph->emplace_shared >(kAnchorKey, Pose(), priorModel); // Create optimizer GaussNewtonParams params; if (singleIter) { params.maxIterations = 1; } else { params.setVerbosity("TERMINATION"); } GaussNewtonOptimizer optimizer(*posegraph, initialPose, params); Values GNresult = optimizer.optimize(); // put into Values structure Values estimate; for (const auto key_value : GNresult) { Key key = key_value.key; if (key != kAnchorKey) { const Pose& pose = GNresult.at(key); estimate.insert(key, pose); } } return estimate; } } // namespace initialize } // namespace gtsam