Skip to content

Commit 3125660

Browse files
Add analytical Jacobian for EdgeSE2PointXYBearing type (#818)
* Add analytical Jacobian for EdgeSE2PointXYBearing type
1 parent de58780 commit 3125660

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

g2o/types/slam2d/edge_se2_pointxy_bearing.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ void EdgeSE2PointXYBearing::initialEstimate(
5252
l2->setEstimate(t * vr);
5353
}
5454

55+
#ifndef NUMERIC_JACOBIAN_TWO_D_TYPES
56+
void EdgeSE2PointXYBearing::linearizeOplus() {
57+
const VertexSE2* vi = static_cast<const VertexSE2*>(_vertices[0]);
58+
const VertexPointXY* vj = static_cast<const VertexPointXY*>(_vertices[1]);
59+
const double& x1 = vi->estimate().translation()[0];
60+
const double& y1 = vi->estimate().translation()[1];
61+
const double& x2 = vj->estimate()[0];
62+
const double& y2 = vj->estimate()[1];
63+
64+
double aux = (std::pow(x2 - x1, 2) + std::pow(y2 - y1, 2));
65+
66+
_jacobianOplusXi(0, 0) = (y1 - y2) / aux;
67+
_jacobianOplusXi(0, 1) = (x2 - x1) / aux;
68+
_jacobianOplusXi(0, 2) = 1;
69+
70+
_jacobianOplusXj(0, 0) = (y2 - y1) / aux;
71+
_jacobianOplusXj(0, 1) = (x1 - x2) / aux;
72+
}
73+
#endif
74+
5575
bool EdgeSE2PointXYBearing::read(std::istream& is) {
5676
is >> _measurement >> information()(0, 0);
5777
return true;

g2o/types/slam2d/edge_se2_pointxy_bearing.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class G2O_TYPES_SLAM2D_API EdgeSE2PointXYBearing
7777
}
7878
virtual void initialEstimate(const OptimizableGraph::VertexSet& from,
7979
OptimizableGraph::Vertex* to);
80+
81+
#ifndef NUMERIC_JACOBIAN_TWO_D_TYPES
82+
virtual void linearizeOplus();
83+
#endif
8084
};
8185

8286
class G2O_TYPES_SLAM2D_API EdgeSE2PointXYBearingWriteGnuplotAction

unit_test/slam2d/jacobians_slam2d.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,17 @@ TEST(Slam2D, EdgeSE2PointXYBearingJacobian) {
156156
numericJacobianWorkspace.allocate();
157157

158158
for (int k = 0; k < 10000; ++k) {
159-
v1.setEstimate(randomSE2());
160-
v2.setEstimate(Eigen::Vector2d::Random());
161-
e.setMeasurement(g2o::Sampler::uniformRand(0., 1.) * M_PI);
162-
163-
evaluateJacobian(e, jacobianWorkspace, numericJacobianWorkspace);
159+
/* Generate random estimate states, but don't evaluate those that are too
160+
* close to error function singularity. */
161+
do {
162+
v1.setEstimate(randomSE2());
163+
v2.setEstimate(Eigen::Vector2d::Random());
164+
e.setMeasurement(g2o::Sampler::uniformRand(-1., 1.) * M_PI);
165+
} while ((v1.estimate().inverse() * v2.estimate()).norm() < 1e-6);
166+
167+
/* Note a larger tolerance versus the default of 1e-6 must be used due to
168+
* poor behaviour of the numerical difference function that is used to
169+
* provide golden data. */
170+
evaluateJacobian(e, jacobianWorkspace, numericJacobianWorkspace, 1e-5);
164171
}
165172
}

unit_test/test_helper/evaluate_jacobian.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ void evaluateJacobianUnary(EdgeType& e, JacobianWorkspace& jacobianWorkspace,
6363

6464
template <typename EdgeType>
6565
void evaluateJacobian(EdgeType& e, JacobianWorkspace& jacobianWorkspace,
66-
JacobianWorkspace& numericJacobianWorkspace) {
66+
JacobianWorkspace& numericJacobianWorkspace,
67+
double tolerance = 1e-6) {
6768
// calling the analytic Jacobian but writing to the numeric workspace
6869
e.BaseBinaryEdge<EdgeType::Dimension, typename EdgeType::Measurement,
6970
typename EdgeType::VertexXiType,
@@ -88,7 +89,7 @@ void evaluateJacobian(EdgeType& e, JacobianWorkspace& jacobianWorkspace,
8889
else
8990
numElems *= EdgeType::VertexXjType::Dimension;
9091
for (int j = 0; j < numElems; ++j) {
91-
EXPECT_NEAR(n[j], a[j], 1e-6);
92+
EXPECT_NEAR(n[j], a[j], tolerance);
9293
}
9394
}
9495
}

0 commit comments

Comments
 (0)