Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/plane factor #564

Merged
merged 36 commits into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
df5ecac
Add unit test for oriented plane 3 factor jacobian
dwisth Jun 16, 2020
75eb859
Fix OrientedPlane3Factor jacobian using numericalDerivative
dwisth Jun 22, 2020
58a0f82
Address Frank's comments and clean up changes
dwisth Jun 23, 2020
795380d
Update style and switch to errorVector()
dwisth Jun 23, 2020
a897ee7
Fix all unit tests. Only remaining item is the analytical Jacobian fo…
dwisth Jul 15, 2020
1708162
Fixed some warnings
dellaert Oct 12, 2020
5df3eeb
Printing now transpose
dellaert Oct 12, 2020
4adca52
Simplified evaluateError
dellaert Oct 12, 2020
6909c2b
Use keyFormatter
dellaert Oct 12, 2020
adbd9a6
Added unit test for issue 561
dellaert Oct 12, 2020
af4005a
pass in params to optimizer
varunagrawal Nov 15, 2020
d4aec50
Merge branch 'develop' into fix/planeFactor
varunagrawal Nov 16, 2020
edb3aea
Merge branch 'develop' into fix/oriented-plane3-factor-jacobian
varunagrawal Dec 6, 2020
534fa6b
formatting and small fixes
varunagrawal Dec 6, 2020
5076837
Add a simplifed version of the minimal failing example
dwisth Jan 19, 2021
62119d8
Add hessian calculation
dwisth Jan 19, 2021
b9a8101
Merge pull request #680 from dwisth/fix/planeFactor-dwisth
dellaert Jan 21, 2021
b5789f6
Merge branch 'develop' into fix/planeFactor
dellaert Jan 21, 2021
6b11c9f
use transform rather than deprecated static function
dellaert Jan 21, 2021
fd8575b
Merge branch 'fix/planeFactor' into fix/oriented-plane3-factor-jacobian
dellaert Jan 21, 2021
564c8bf
Merge pull request #362 from dwisth/fix/oriented-plane3-factor-jacobian
dellaert Jan 21, 2021
68887f2
Got rid of extra keys
dellaert Jan 21, 2021
6c39730
Got rid of static versions of methods
dellaert Jan 21, 2021
1b36c74
Cleaned up derivative code
dellaert Jan 21, 2021
79d4247
Cleanup
dellaert Jan 21, 2021
46464aa
cleanup
dellaert Jan 29, 2021
9eb6267
Comments
dellaert Feb 3, 2021
a62bdd4
Add new oriented plane 3 factors with local linearisation point
dwisth Feb 15, 2021
0ad488c
Update print method of OrientedPlane3Factor
dwisth Feb 15, 2021
5087d36
remove deprecated Unit3::error() which is replaced by Unit3::errorVec…
dwisth Feb 15, 2021
7480d14
Update documentation on new factor
dwisth Feb 15, 2021
1771a56
Revert "remove deprecated Unit3::error() which is replaced by Unit3::…
dwisth Feb 16, 2021
71f39ab
remove the error() function from OrientedPlane3 (it had incorrect der…
dwisth Feb 16, 2021
960a3e1
Tidy up comments and use cpplint
dwisth Feb 16, 2021
5b0bd08
small tidy and fix unit tests
dwisth Feb 16, 2021
8f18ce9
Add inline comments on commented-out unit tests
dwisth Feb 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 17 additions & 22 deletions gtsam/geometry/OrientedPlane3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

#include <gtsam/geometry/OrientedPlane3.h>
#include <gtsam/geometry/Point2.h>

#include <iostream>

using namespace std;
Expand All @@ -28,12 +28,13 @@ namespace gtsam {
/* ************************************************************************* */
void OrientedPlane3::print(const string& s) const {
Vector4 coeffs = planeCoefficients();
cout << s << " : " << coeffs << endl;
cout << s << " : " << coeffs.transpose() << endl;
}

/* ************************************************************************* */
OrientedPlane3 OrientedPlane3::transform(const Pose3& xr, OptionalJacobian<3, 3> Hp,
OptionalJacobian<3, 6> Hr) const {
OrientedPlane3 OrientedPlane3::transform(const Pose3& xr,
OptionalJacobian<3, 3> Hp,
OptionalJacobian<3, 6> Hr) const {
Matrix23 D_rotated_plane;
Matrix22 D_rotated_pose;
Unit3 n_rotated = xr.rotation().unrotate(n_, D_rotated_plane, D_rotated_pose);
Expand All @@ -42,53 +43,47 @@ OrientedPlane3 OrientedPlane3::transform(const Pose3& xr, OptionalJacobian<3, 3>
double pred_d = n_.unitVector().dot(xr.translation()) + d_;

if (Hr) {
*Hr = Matrix::Zero(3,6);
Hr->setZero();
Hr->block<2, 3>(0, 0) = D_rotated_plane;
Hr->block<1, 3>(2, 3) = unit_vec;
}
if (Hp) {
Vector2 hpp = n_.basis().transpose() * xr.translation();
*Hp = Z_3x3;
Hp->setZero();
Hp->block<2, 2>(0, 0) = D_rotated_pose;
Hp->block<1, 2>(2, 0) = hpp;
Hp->block<1, 2>(2, 0) = n_.basis().transpose() * xr.translation();
(*Hp)(2, 2) = 1;
}

return OrientedPlane3(unit_vec(0), unit_vec(1), unit_vec(2), pred_d);
}

/* ************************************************************************* */
Vector3 OrientedPlane3::error(const OrientedPlane3& plane) const {
Vector2 n_error = -n_.localCoordinates(plane.n_);
return Vector3(n_error(0), n_error(1), d_ - plane.d_);
}

/* ************************************************************************* */
Vector3 OrientedPlane3::errorVector(const OrientedPlane3& other, OptionalJacobian<3, 3> H1,
Vector3 OrientedPlane3::errorVector(const OrientedPlane3& other,
OptionalJacobian<3, 3> H1,
OptionalJacobian<3, 3> H2) const {
Matrix22 H_n_error_this, H_n_error_other;
Vector2 n_error = n_.errorVector(other.normal(), H1 ? &H_n_error_this : 0,
Vector2 n_error = n_.errorVector(other.n_, H1 ? &H_n_error_this : 0,
dellaert marked this conversation as resolved.
Show resolved Hide resolved
H2 ? &H_n_error_other : 0);

double d_error = d_ - other.d_;

if (H1) {
*H1 << H_n_error_this, Vector2::Zero(), 0, 0, 1;
*H1 << H_n_error_this, Z_2x1, 0, 0, 1;
}
if (H2) {
*H2 << H_n_error_other, Vector2::Zero(), 0, 0, -1;
*H2 << H_n_error_other, Z_2x1, 0, 0, -1;
}

return Vector3(n_error(0), n_error(1), d_error);
}

/* ************************************************************************* */
OrientedPlane3 OrientedPlane3::retract(const Vector3& v,
OptionalJacobian<3,3> H) const {
OptionalJacobian<3, 3> H) const {
Matrix22 H_n;
Unit3 n_retract (n_.retract(Vector2(v(0), v(1)), H? &H_n : nullptr));
Unit3 n_retract(n_.retract(Vector2(v(0), v(1)), H? &H_n : nullptr));
if (H) {
*H << H_n, Vector2::Zero(), 0, 0, 1;
*H << H_n, Z_2x1, 0, 0, 1;
}
return OrientedPlane3(n_retract, d_ + v(2));
}
Expand All @@ -100,4 +95,4 @@ Vector3 OrientedPlane3::localCoordinates(const OrientedPlane3& y) const {
return Vector3(n_local(0), n_local(1), -d_local);
}

}
} // namespace gtsam
63 changes: 21 additions & 42 deletions gtsam/geometry/OrientedPlane3.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,21 @@

#pragma once

#include <gtsam/geometry/Rot3.h>
#include <gtsam/geometry/Unit3.h>
#include <gtsam/geometry/Pose3.h>
#include <string>

namespace gtsam {

/**
* @brief Represents an infinite plane in 3D, which is composed of a planar normal and its
* perpendicular distance to the origin.
* Currently it provides a transform of the plane, and a norm 1 differencing of two planes.
* @brief Represents an infinite plane in 3D, which is composed of a planar
* normal and its perpendicular distance to the origin.
* Currently it provides a transform of the plane, and a norm 1 differencing of
* two planes.
* Refer to Trevor12iros for more math details.
*/
class GTSAM_EXPORT OrientedPlane3 {

private:

Unit3 n_; ///< The direction of the planar normal
double d_; ///< The perpendicular distance to this plane

Expand All @@ -53,19 +52,17 @@ class GTSAM_EXPORT OrientedPlane3 {
}

/// Construct from a Unit3 and a distance
OrientedPlane3(const Unit3& s, double d) :
n_(s), d_(d) {
OrientedPlane3(const Unit3& n, double d) :
n_(n), d_(d) {
}

/// Construct from a vector of plane coefficients
OrientedPlane3(const Vector4& vec) :
n_(vec(0), vec(1), vec(2)), d_(vec(3)) {
}
explicit OrientedPlane3(const Vector4& vec)
: n_(vec(0), vec(1), vec(2)), d_(vec(3)) {}

/// Construct from four numbers of plane coeffcients (a, b, c, d)
OrientedPlane3(double a, double b, double c, double d) {
Point3 p(a, b, c);
n_ = Unit3(p);
n_ = Unit3(a, b, c);
d_ = d;
}

Expand All @@ -90,37 +87,18 @@ class GTSAM_EXPORT OrientedPlane3 {
* @return the transformed plane
*/
OrientedPlane3 transform(const Pose3& xr,
OptionalJacobian<3, 3> Hp = boost::none,
OptionalJacobian<3, 6> Hr = boost::none) const;

/**
* @deprecated the static method has wrong Jacobian order,
* please use the member method transform()
* @param The raw plane
* @param xr a transformation in current coordiante
* @param Hr optional jacobian wrpt the pose transformation
* @param Hp optional Jacobian wrpt the destination plane
* @return the transformed plane
*/
static OrientedPlane3 Transform(const OrientedPlane3& plane,
const Pose3& xr, OptionalJacobian<3, 6> Hr = boost::none,
OptionalJacobian<3, 3> Hp = boost::none) {
return plane.transform(xr, Hp, Hr);
}

/** Computes the error between two planes.
* The error is a norm 1 difference in tangent space.
* @param the other plane
*/
Vector3 error(const OrientedPlane3& plane) const;
OptionalJacobian<3, 3> Hp = boost::none,
OptionalJacobian<3, 6> Hr = boost::none) const;

/** Computes the error between the two planes, with derivatives.
* This uses Unit3::errorVector, as opposed to the other .error() in this class, which uses
* Unit3::localCoordinates. This one has correct derivatives.
* This uses Unit3::errorVector, as opposed to the other .error() in this
* class, which uses Unit3::localCoordinates. This one has correct
* derivatives.
* NOTE(hayk): The derivatives are zero when normals are exactly orthogonal.
* @param the other plane
* @param other the other plane
*/
Vector3 errorVector(const OrientedPlane3& other, OptionalJacobian<3, 3> H1 = boost::none, //
Vector3 errorVector(const OrientedPlane3& other,
OptionalJacobian<3, 3> H1 = boost::none,
OptionalJacobian<3, 3> H2 = boost::none) const;

/// Dimensionality of tangent space = 3 DOF
Expand All @@ -134,7 +112,8 @@ class GTSAM_EXPORT OrientedPlane3 {
}

/// The retract function
OrientedPlane3 retract(const Vector3& v, OptionalJacobian<3,3> H = boost::none) const;
OrientedPlane3 retract(const Vector3& v,
OptionalJacobian<3, 3> H = boost::none) const;

/// The local coordinates function
Vector3 localCoordinates(const OrientedPlane3& s) const;
Expand Down Expand Up @@ -166,5 +145,5 @@ template<> struct traits<const OrientedPlane3> : public internal::Manifold<
OrientedPlane3> {
};

} // namespace gtsam
} // namespace gtsam

59 changes: 21 additions & 38 deletions gtsam/geometry/tests/testOrientedPlane3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ GTSAM_CONCEPT_TESTABLE_INST(OrientedPlane3)
GTSAM_CONCEPT_MANIFOLD_INST(OrientedPlane3)

//*******************************************************************************
TEST (OrientedPlane3, getMethods) {
TEST(OrientedPlane3, getMethods) {
Vector4 c;
c << -1, 0, 0, 5;
OrientedPlane3 plane1(c);
Expand All @@ -50,44 +50,27 @@ TEST (OrientedPlane3, getMethods) {


//*******************************************************************************
OrientedPlane3 Transform_(const OrientedPlane3& plane, const Pose3& xr) {
return OrientedPlane3::Transform(plane, xr);
}

OrientedPlane3 transform_(const OrientedPlane3& plane, const Pose3& xr) {
return plane.transform(xr);
}

TEST (OrientedPlane3, transform) {
TEST(OrientedPlane3, transform) {
gtsam::Pose3 pose(gtsam::Rot3::Ypr(-M_PI / 4.0, 0.0, 0.0),
gtsam::Point3(2.0, 3.0, 4.0));
gtsam::Point3(2.0, 3.0, 4.0));
OrientedPlane3 plane(-1, 0, 0, 5);
OrientedPlane3 expectedPlane(-sqrt(2.0) / 2.0, -sqrt(2.0) / 2.0, 0.0, 3);
OrientedPlane3 transformedPlane1 = OrientedPlane3::Transform(plane, pose,
none, none);
OrientedPlane3 transformedPlane2 = plane.transform(pose, none, none);
EXPECT(assert_equal(expectedPlane, transformedPlane1, 1e-5));
EXPECT(assert_equal(expectedPlane, transformedPlane2, 1e-5));
OrientedPlane3 transformedPlane = plane.transform(pose, none, none);
EXPECT(assert_equal(expectedPlane, transformedPlane, 1e-5));

// Test the jacobians of transform
Matrix actualH1, expectedH1, actualH2, expectedH2;
{
// because the Transform class uses a wrong order of Jacobians in interface
OrientedPlane3::Transform(plane, pose, actualH1, none);
expectedH1 = numericalDerivative22(Transform_, plane, pose);
EXPECT(assert_equal(expectedH1, actualH1, 1e-5));
OrientedPlane3::Transform(plane, pose, none, actualH2);
expectedH2 = numericalDerivative21(Transform_, plane, pose);
EXPECT(assert_equal(expectedH2, actualH2, 1e-5));
}
{
plane.transform(pose, actualH1, none);
expectedH1 = numericalDerivative21(transform_, plane, pose);
EXPECT(assert_equal(expectedH1, actualH1, 1e-5));
plane.transform(pose, none, actualH2);
expectedH2 = numericalDerivative22(Transform_, plane, pose);
EXPECT(assert_equal(expectedH2, actualH2, 1e-5));
}
expectedH1 = numericalDerivative21(transform_, plane, pose);
plane.transform(pose, actualH1, none);
EXPECT(assert_equal(expectedH1, actualH1, 1e-5));

expectedH2 = numericalDerivative22(transform_, plane, pose);
plane.transform(pose, none, actualH2);
EXPECT(assert_equal(expectedH2, actualH2, 1e-5));
}

//*******************************************************************************
Expand All @@ -109,7 +92,6 @@ inline static Vector randomVector(const Vector& minLimits,

//*******************************************************************************
TEST(OrientedPlane3, localCoordinates_retract) {

size_t numIterations = 10000;
Vector4 minPlaneLimit, maxPlaneLimit;
minPlaneLimit << -1.0, -1.0, -1.0, 0.01;
Expand All @@ -119,7 +101,6 @@ TEST(OrientedPlane3, localCoordinates_retract) {
minXiLimit << -M_PI, -M_PI, -10.0;
maxXiLimit << M_PI, M_PI, 10.0;
for (size_t i = 0; i < numIterations; i++) {

// Create a Plane
OrientedPlane3 p1(randomVector(minPlaneLimit, maxPlaneLimit));
Vector v12 = randomVector(minXiLimit, maxXiLimit);
Expand All @@ -138,22 +119,24 @@ TEST(OrientedPlane3, localCoordinates_retract) {
}

//*******************************************************************************
TEST (OrientedPlane3, error2) {
TEST(OrientedPlane3, errorVector) {
OrientedPlane3 plane1(-1, 0.1, 0.2, 5);
OrientedPlane3 plane2(-1.1, 0.2, 0.3, 5.4);

// Hard-coded regression values, to ensure the result doesn't change.
EXPECT(assert_equal((Vector) Z_3x1, plane1.errorVector(plane1), 1e-8));
EXPECT(assert_equal(Vector3(-0.0677674148, -0.0760543588, -0.4), plane1.errorVector(plane2), 1e-5));
EXPECT(assert_equal(Vector3(-0.0677674148, -0.0760543588, -0.4),
plane1.errorVector(plane2), 1e-5));

// Test the jacobians of transform
Matrix33 actualH1, expectedH1, actualH2, expectedH2;

Vector3 actual = plane1.errorVector(plane2, actualH1, actualH2);
EXPECT(assert_equal(plane1.normal().errorVector(plane2.normal()), Vector2(actual[0], actual[1])));
EXPECT(assert_equal(plane1.normal().errorVector(plane2.normal()),
Vector2(actual[0], actual[1])));
EXPECT(assert_equal(plane1.distance() - plane2.distance(), actual[2]));

boost::function<Vector3(const OrientedPlane3&, const OrientedPlane3&)> f = //
boost::function<Vector3(const OrientedPlane3&, const OrientedPlane3&)> f =
boost::bind(&OrientedPlane3::errorVector, _1, _2, boost::none, boost::none);
expectedH1 = numericalDerivative21(f, plane1, plane2);
expectedH2 = numericalDerivative22(f, plane1, plane2);
Expand All @@ -162,19 +145,19 @@ TEST (OrientedPlane3, error2) {
}

//*******************************************************************************
TEST (OrientedPlane3, jacobian_retract) {
TEST(OrientedPlane3, jacobian_retract) {
OrientedPlane3 plane(-1, 0.1, 0.2, 5);
Matrix33 H_actual;
boost::function<OrientedPlane3(const Vector3&)> f =
boost::bind(&OrientedPlane3::retract, plane, _1, boost::none);
{
Vector3 v (-0.1, 0.2, 0.3);
Vector3 v(-0.1, 0.2, 0.3);
plane.retract(v, H_actual);
Matrix H_expected_numerical = numericalDerivative11(f, v);
EXPECT(assert_equal(H_expected_numerical, H_actual, 1e-5));
}
{
Vector3 v (0, 0, 0);
Vector3 v(0, 0, 0);
plane.retract(v, H_actual);
Matrix H_expected_numerical = numericalDerivative11(f, v);
EXPECT(assert_equal(H_expected_numerical, H_actual, 1e-5));
Expand Down
1 change: 1 addition & 0 deletions gtsam/geometry/tests/testUnit3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ TEST(actualH, Serialization) {
EXPECT(serializationTestHelpers::equalsBinary(p));
}


/* ************************************************************************* */
int main() {
srand(time(nullptr));
Expand Down
Loading