# include <gtsam/slam/PriorFactor.h>
# include <gtsam/nonlinear/NonlinearFactorGraph.h>
# include <gtsam/nonlinear/Values.h>
# include <gtsam/nonlinear/GaussNewtonOptimizer.h>
# include <gtsam/geometry/OrientedPlane3.h>
# include <gtsam/geometry/Pose3.h>
# include <gtsam/inference/Symbol.h>
# include <boost/optional.hpp>
# include <iostream> using namespace gtsam;
class CustomOrientedPlane3Factor : public NoiseModelFactor1 < Pose3 > { OrientedPlane3 measured_; public : CustomOrientedPlane3Factor ( const OrientedPlane3& measured, const SharedNoiseModel& model, Key poseKey) : NoiseModelFactor1 < Pose3> ( model, poseKey) , measured_ ( measured) { } Vector evaluateError ( const Pose3& pose, boost:: optional< Matrix& > H = boost:: none) const override { OrientedPlane3 transformedPlane = measured_. transform ( pose, H) ; double zError = pose. translation ( ) . z ( ) - transformedPlane. planeCoefficients ( ) ( 3 ) ; Vector3 normalError = transformedPlane. planeCoefficients ( ) . head < 3 > ( ) - measured_. planeCoefficients ( ) . head < 3 > ( ) ; Vector error ( 4 ) ; error << normalError, zError; if ( H) { * H = Matrix :: Zero ( 4 , 6 ) ; ( * H) ( 3 , 5 ) = 1.0 ; } return error; }
} ; int main ( ) { NonlinearFactorGraph graph; Pose3 initialPose ( Rot3 :: Ypr ( 0.1 , 0.1 , 0.1 ) , Point3 ( 10.5 , 20.4 , 1.2 ) ) ; Vector6 poseConstraint; poseConstraint << 0.0 , 0.0 , 1.0 , 1.0 , 1.0 , 1.0 ; auto poseNoise = noiseModel:: Diagonal :: Sigmas ( poseConstraint * 0.1 ) ; graph. add ( PriorFactor < Pose3> ( Symbol ( 'x' , 0 ) , initialPose, poseNoise) ) ; std:: cout << "Initial Pose:\n" << initialPose << std:: endl; std:: vector< OrientedPlane3> observedPlanes = { OrientedPlane3 ( 0 , 0 , 1 , - 1.5 ) , OrientedPlane3 ( 0 , 0 , 1 , - 2.0 ) , OrientedPlane3 ( 0 , 0 , 1 , - 1.0 ) , OrientedPlane3 ( 0 , 0 , 1 , - 0.5 ) } ; auto planeNoise = noiseModel:: Isotropic :: Sigma ( 4 , 1e-3 ) ; for ( size_t i = 0 ; i < observedPlanes. size ( ) ; ++ i) { graph. add ( boost:: make_shared < CustomOrientedPlane3Factor> ( observedPlanes[ i] , planeNoise, Symbol ( 'x' , 0 ) ) ) ; } Values initialEstimate; initialEstimate. insert ( Symbol ( 'x' , 0 ) , initialPose) ; GaussNewtonParams params; params. setMaxIterations ( 10 ) ; params. setRelativeErrorTol ( 1e-5 ) ; GaussNewtonOptimizer optimizer ( graph, initialEstimate, params) ; Values result = optimizer. optimize ( ) ; std:: cout << "Optimized Pose:\n" << result. at < Pose3> ( Symbol ( 'x' , 0 ) ) << std:: endl; return 0 ;
}