diff --git a/gtsam/slam/InitializePose3.cpp b/gtsam/slam/InitializePose3.cpp index 38bfcf82f..5779a109c 100644 --- a/gtsam/slam/InitializePose3.cpp +++ b/gtsam/slam/InitializePose3.cpp @@ -38,6 +38,8 @@ static const Matrix zero33= Matrix::Zero(3,3); static const Key keyAnchor = symbol('Z', 9999999); +typedef std::map > KeyVectorMap; + /* ************************************************************************* */ GaussianFactorGraph buildLinearOrientationGraph(const NonlinearFactorGraph& g) { @@ -150,16 +152,31 @@ Values computeOrientationsChordal(const NonlinearFactorGraph& pose3Graph) { Values computeOrientationsGradient(const NonlinearFactorGraph& pose3Graph, const Values& givenGuess) { gttic(InitializePose3_computeOrientationsGradient); + // this works on the inverse rotations, according to Tron&Vidal,2011 + Values inverseRot; + BOOST_FOREACH(const Values::ConstKeyValuePair& key_value, givenGuess) { + Key key = key_value.key; + const Pose3& pose = givenGuess.at(key); + inverseRot.insert(key, pose.rotation().inverse()); + } + // Create the map of edges incident on each node + KeyVectorMap adjEdgesMap; +// +// // regularize measurements and plug everything in a factor graph +// GaussianFactorGraph relaxedGraph = buildLinearOrientationGraph(pose3Graph); +// +// // Solve the LFG +// VectorValues relaxedRot3 = relaxedGraph.optimize(); - // regularize measurements and plug everything in a factor graph - GaussianFactorGraph relaxedGraph = buildLinearOrientationGraph(pose3Graph); - - // Solve the LFG - VectorValues relaxedRot3 = relaxedGraph.optimize(); - - // normalize and compute Rot3 - return normalizeRelaxedRotations(relaxedRot3); + // Return correct rotations + Values estimateRot; + BOOST_FOREACH(const Values::ConstKeyValuePair& key_value, inverseRot) { + Key key = key_value.key; + const Rot3& R = inverseRot.at(key); + estimateRot.insert(key, R.inverse()); + } + return estimateRot; } /* ************************************************************************* */ diff --git a/gtsam/slam/InitializePose3.h b/gtsam/slam/InitializePose3.h index 7b5489353..b6632212c 100644 --- a/gtsam/slam/InitializePose3.h +++ b/gtsam/slam/InitializePose3.h @@ -34,6 +34,8 @@ GTSAM_EXPORT Values normalizeRelaxedRotations(const VectorValues& relaxedRot3); GTSAM_EXPORT Values computeOrientationsChordal(const NonlinearFactorGraph& pose3Graph); +GTSAM_EXPORT Values computeOrientationsGradient(const NonlinearFactorGraph& pose3Graph, const Values& givenGuess); + GTSAM_EXPORT NonlinearFactorGraph buildPose3graph(const NonlinearFactorGraph& graph); GTSAM_EXPORT Values computePoses(NonlinearFactorGraph& pose3graph, Values& initialRot); diff --git a/gtsam/slam/tests/testInitializePose3.cpp b/gtsam/slam/tests/testInitializePose3.cpp index 5387af7ef..57715deca 100644 --- a/gtsam/slam/tests/testInitializePose3.cpp +++ b/gtsam/slam/tests/testInitializePose3.cpp @@ -91,6 +91,25 @@ TEST( InitializePose3, orientations ) { EXPECT(assert_equal(simple::R3, initial.at(x3), 1e-6)); } +/* *************************************************************************** */ +TEST( InitializePose3, orientationsGradient ) { + NonlinearFactorGraph pose3Graph = InitializePose3::buildPose3graph(simple::graph()); + + // Wrong initial guess - initialization should fix the rotations + Values givenPoses; + givenPoses.insert(x0,simple::pose0); + givenPoses.insert(x1,simple::pose0); + givenPoses.insert(x2,simple::pose0); + givenPoses.insert(x3,simple::pose0); + Values initial = InitializePose3::computeOrientationsGradient(pose3Graph, givenPoses); + + // comparison is up to M_PI, that's why we add some multiples of 2*M_PI + EXPECT(assert_equal(simple::R0, initial.at(x0), 1e-6)); + EXPECT(assert_equal(simple::R1, initial.at(x1), 1e-6)); + EXPECT(assert_equal(simple::R2, initial.at(x2), 1e-6)); + EXPECT(assert_equal(simple::R3, initial.at(x3), 1e-6)); +} + /* *************************************************************************** */ TEST( InitializePose3, posesWithGivenGuess ) { Values givenPoses;