Fix OrientedPlane3Factor jacobian using numericalDerivative
parent
df5ecac604
commit
75eb859ee7
|
|
@ -114,6 +114,10 @@ public:
|
||||||
*/
|
*/
|
||||||
Vector3 error(const OrientedPlane3& plane) const;
|
Vector3 error(const OrientedPlane3& plane) const;
|
||||||
|
|
||||||
|
static Vector3 Error(const OrientedPlane3& plane1, const OrientedPlane3& plane2) {
|
||||||
|
return plane1.error(plane2);
|
||||||
|
}
|
||||||
|
|
||||||
/** Computes the error between the two planes, with derivatives.
|
/** Computes the error between the two planes, with derivatives.
|
||||||
* This uses Unit3::errorVector, as opposed to the other .error() in this class, which uses
|
* This uses Unit3::errorVector, as opposed to the other .error() in this class, which uses
|
||||||
* Unit3::localCoordinates. This one has correct derivatives.
|
* Unit3::localCoordinates. This one has correct derivatives.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtsam/base/numericalDerivative.h>
|
||||||
#include <gtsam/geometry/OrientedPlane3.h>
|
#include <gtsam/geometry/OrientedPlane3.h>
|
||||||
#include <gtsam/nonlinear/NonlinearFactor.h>
|
#include <gtsam/nonlinear/NonlinearFactor.h>
|
||||||
|
|
||||||
|
|
@ -48,10 +49,27 @@ public:
|
||||||
virtual Vector evaluateError(const Pose3& pose, const OrientedPlane3& plane,
|
virtual Vector evaluateError(const Pose3& pose, const OrientedPlane3& plane,
|
||||||
boost::optional<Matrix&> H1 = boost::none, boost::optional<Matrix&> H2 =
|
boost::optional<Matrix&> H1 = boost::none, boost::optional<Matrix&> H2 =
|
||||||
boost::none) const {
|
boost::none) const {
|
||||||
OrientedPlane3 predicted_plane = OrientedPlane3::Transform(plane, pose, H1,
|
|
||||||
H2);
|
|
||||||
Vector err(3);
|
Vector err(3);
|
||||||
err << predicted_plane.error(measured_p_);
|
|
||||||
|
if (H1 || H2) {
|
||||||
|
Matrix H1_1, H2_1;
|
||||||
|
OrientedPlane3 predicted_plane = OrientedPlane3::Transform(plane, pose, H1_1, H2_1);
|
||||||
|
err << predicted_plane.error(measured_p_);
|
||||||
|
// Numerically calculate the derivative since this function doesn't provide one.
|
||||||
|
auto f = boost::bind(&OrientedPlane3::Error, _1, _2);
|
||||||
|
Matrix H1_2 = numericalDerivative21<Vector3, OrientedPlane3, OrientedPlane3>(f, predicted_plane, measured_p_);
|
||||||
|
|
||||||
|
// Apply the chain rule to calculate the derivatives.
|
||||||
|
if (H1) {
|
||||||
|
*H1 = H1_2 * H1_1;
|
||||||
|
}
|
||||||
|
if (H2) {
|
||||||
|
*H2 = H1_2 * H2_1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OrientedPlane3 predicted_plane = OrientedPlane3::Transform(plane, pose, H1, H2);
|
||||||
|
err << predicted_plane.error(measured_p_);
|
||||||
|
}
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ TEST (OrientedPlane3Factor, lm_rotation_error) {
|
||||||
// Tests one pose, two measurements of the landmark that differ in angle only.
|
// Tests one pose, two measurements of the landmark that differ in angle only.
|
||||||
// Normal along -x, 3m away
|
// Normal along -x, 3m away
|
||||||
Symbol lm_sym('p', 0);
|
Symbol lm_sym('p', 0);
|
||||||
OrientedPlane3 test_lm0(-1.0, 0.0, 0.0, 3.0);
|
OrientedPlane3 test_lm0(-1.0/sqrt(1.01), 0.1/sqrt(1.01), 0.0, 3.0);
|
||||||
|
|
||||||
ISAM2 isam2;
|
ISAM2 isam2;
|
||||||
Values new_values;
|
Values new_values;
|
||||||
|
|
@ -153,8 +153,8 @@ TEST( OrientedPlane3Factor, Derivatives ) {
|
||||||
factor.evaluateError(poseLin, pLin, actualH1, actualH2);
|
factor.evaluateError(poseLin, pLin, actualH1, actualH2);
|
||||||
|
|
||||||
// Verify we get the expected error
|
// Verify we get the expected error
|
||||||
EXPECT(assert_equal(numericalH1, actualH1, 1e-8));
|
EXPECT(assert_equal(numericalH1, actualH1, 1e-7));
|
||||||
EXPECT(assert_equal(numericalH2, actualH2, 1e-8));
|
EXPECT(assert_equal(numericalH2, actualH2, 1e-7));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue