Skip to content

Commit 29835d8

Browse files
author
Enrique Fernandez
committed
Add testCovariance helper function
1 parent e019e3a commit 29835d8

File tree

6 files changed

+110
-278
lines changed

6 files changed

+110
-278
lines changed

diff_drive_controller/include/diff_drive_controller/covariance.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141

4242
#include <Eigen/Dense>
4343

44+
#include <boost/array.hpp>
45+
4446
#include <limits>
4547

4648
namespace diff_drive_controller

diff_drive_controller/include/diff_drive_controller/rigid_body_motion.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ static void integrate_motion(double& x, double &y, double &yaw,
7878
* \param[in] v_y Velocity/Twist y component
7979
* \param[in] v_yaw Velocity/Twist yaw component
8080
* \param[in] dt Time step
81+
* \param[out] J_pose Jacobian wrt the pose
82+
* \param[out] J_twist Jacobian wrt the velocity/twist
8183
*/
8284
static void integrate_motion(double& x, double &y, double &yaw,
8385
const double v_x, const double v_y, const double v_yaw,

diff_drive_controller/test/diff_drive_test.cpp

Lines changed: 15 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -114,40 +114,17 @@ TEST_F(DiffDriveControllerTest, testNoMove)
114114

115115
// check we have a positive definite covariance matrix
116116
// isCovariance = isSymmetric + isPositiveDefinite
117-
const Eigen::IOFormat HeavyFmt(
118-
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
119-
120-
typedef Eigen::SelfAdjointEigenSolver<PoseCovariance> PoseEigenSolver;
121-
typedef Eigen::SelfAdjointEigenSolver<TwistCovariance> TwistEigenSolver;
122-
123-
PoseEigenSolver pose_eigensolver(pose_covariance);
124-
TwistEigenSolver twist_eigensolver(twist_covariance);
125-
126-
EXPECT_TRUE(isSymmetric(pose_covariance))
127-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt);
128-
EXPECT_TRUE(isPositiveDefinite(pose_covariance, no_tag()))
129-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt) << "\n"
130-
<< "Eigenvalues = " << pose_eigensolver.eigenvalues().transpose().format(HeavyFmt);
131-
EXPECT_LT(conditionNumber(pose_covariance),
132-
POSE_COVARIANCE_MAX_CONDITION_NUMBER)
133-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt) << "\n"
134-
<< "Eigenvalues = " << pose_eigensolver.eigenvalues().transpose().format(HeavyFmt);
135-
136-
EXPECT_TRUE(isSymmetric(twist_covariance))
137-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt);
138-
EXPECT_TRUE(isPositiveDefinite(twist_covariance, no_tag()))
139-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
140-
<< "Eigenvalues = " << twist_eigensolver.eigenvalues().transpose().format(HeavyFmt);
141-
EXPECT_LT(conditionNumber(pose_covariance),
142-
TWIST_COVARIANCE_MAX_CONDITION_NUMBER)
143-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
144-
<< "Eigenvalues = " << twist_eigensolver.eigenvalues().transpose().format(HeavyFmt);
117+
testCovariance(pose_covariance, POSE_COVARIANCE_MAX_CONDITION_NUMBER);
118+
testCovariance(twist_covariance, TWIST_COVARIANCE_MAX_CONDITION_NUMBER);
145119

146120
// when the robot doesn't move the twist covariance should be exactly the
147121
// minimum twist covariance, which is defined as a diagonal covariance matrix
148122
// like this:
149123
// Odometry::DEFAULT_MINIMUM_TWIST_COVARIANCE * TwistCovariance::Identity()
150124
// where Odometry::DEFAULT_MINIMUM_TWIST_COVARIANCE == 1e-9
125+
const Eigen::IOFormat HeavyFmt(
126+
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
127+
151128
TwistCovariance minimum_twist_covariance = 1e-9 * TwistCovariance::Identity();
152129
EXPECT_TRUE(((twist_covariance - minimum_twist_covariance).array() == 0).all())
153130
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
@@ -306,34 +283,8 @@ TEST_F(DiffDriveControllerTest, testForward)
306283

307284
// check we have a positive definite covariance matrix
308285
// isCovariance = isSymmetric + isPositiveDefinite
309-
const Eigen::IOFormat HeavyFmt(
310-
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
311-
312-
typedef Eigen::SelfAdjointEigenSolver<PoseCovariance> PoseEigenSolver;
313-
typedef Eigen::SelfAdjointEigenSolver<TwistCovariance> TwistEigenSolver;
314-
315-
PoseEigenSolver pose_eigensolver(pose_covariance);
316-
TwistEigenSolver twist_eigensolver(twist_covariance);
317-
318-
EXPECT_TRUE(isSymmetric(pose_covariance))
319-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt);
320-
EXPECT_TRUE(isPositiveDefinite(pose_covariance, no_tag()))
321-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt) << "\n"
322-
<< "Eigenvalues = " << pose_eigensolver.eigenvalues().transpose().format(HeavyFmt);
323-
EXPECT_LT(conditionNumber(pose_covariance),
324-
POSE_COVARIANCE_MAX_CONDITION_NUMBER)
325-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt) << "\n"
326-
<< "Eigenvalues = " << pose_eigensolver.eigenvalues().transpose().format(HeavyFmt);
327-
328-
EXPECT_TRUE(isSymmetric(twist_covariance))
329-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt);
330-
EXPECT_TRUE(isPositiveDefinite(twist_covariance, no_tag()))
331-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
332-
<< "Eigenvalues = " << twist_eigensolver.eigenvalues().transpose().format(HeavyFmt);
333-
EXPECT_LT(conditionNumber(pose_covariance),
334-
TWIST_COVARIANCE_MAX_CONDITION_NUMBER)
335-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
336-
<< "Eigenvalues = " << twist_eigensolver.eigenvalues().transpose().format(HeavyFmt);
286+
testCovariance(pose_covariance, POSE_COVARIANCE_MAX_CONDITION_NUMBER);
287+
testCovariance(twist_covariance, TWIST_COVARIANCE_MAX_CONDITION_NUMBER);
337288

338289
// Take the last two odometry messages:
339290
std::vector<nav_msgs::Odometry> odoms = getLastOdoms();
@@ -406,6 +357,9 @@ TEST_F(DiffDriveControllerTest, testForward)
406357
EXPECT_NEAR(yaw_0, yaw, std::numeric_limits<double>::epsilon());
407358

408359
// Check new pose covariance is equal to the expected one:
360+
const Eigen::IOFormat HeavyFmt(
361+
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
362+
409363
EXPECT_TRUE(((pose_covariance_0_expected - pose_covariance_0).array().abs() < 1e-5).all())
410364
<< "Pose covariance actual =\n" << pose_covariance_0.format(HeavyFmt)
411365
<< "\nPose covariance expected =\n" << pose_covariance_0_expected.format(HeavyFmt);
@@ -493,37 +447,8 @@ TEST_F(DiffDriveControllerTest, testTurn)
493447

494448
// check we have a positive definite covariance matrix
495449
// isCovariance = isSymmetric + isPositiveDefinite
496-
const Eigen::IOFormat HeavyFmt(
497-
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
498-
499-
typedef Eigen::SelfAdjointEigenSolver<PoseCovariance> PoseEigenSolver;
500-
typedef Eigen::SelfAdjointEigenSolver<TwistCovariance> TwistEigenSolver;
501-
502-
PoseEigenSolver pose_eigensolver(pose_covariance);
503-
TwistEigenSolver twist_eigensolver(twist_covariance);
504-
505-
EXPECT_TRUE(pose_eigensolver.info() == Eigen::Success);
506-
EXPECT_TRUE(twist_eigensolver.info() == Eigen::Success);
507-
508-
EXPECT_TRUE(isSymmetric(pose_covariance))
509-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt);
510-
EXPECT_TRUE(isPositiveDefinite(pose_covariance, no_tag()))
511-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt) << "\n"
512-
<< "Eigenvalues = " << pose_eigensolver.eigenvalues().transpose().format(HeavyFmt);
513-
EXPECT_LT(conditionNumber(pose_covariance),
514-
POSE_COVARIANCE_MAX_CONDITION_NUMBER)
515-
<< "Pose covariance =\n" << pose_covariance.format(HeavyFmt) << "\n"
516-
<< "Eigenvalues = " << pose_eigensolver.eigenvalues().transpose().format(HeavyFmt);
517-
518-
EXPECT_TRUE(isSymmetric(twist_covariance))
519-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt);
520-
EXPECT_TRUE(isPositiveDefinite(twist_covariance, no_tag()))
521-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
522-
<< "Eigenvalues = " << twist_eigensolver.eigenvalues().transpose().format(HeavyFmt);
523-
EXPECT_LT(conditionNumber(pose_covariance),
524-
TWIST_COVARIANCE_MAX_CONDITION_NUMBER)
525-
<< "Twist covariance =\n" << twist_covariance.format(HeavyFmt) << "\n"
526-
<< "Eigenvalues = " << twist_eigensolver.eigenvalues().transpose().format(HeavyFmt);
450+
testCovariance(pose_covariance, POSE_COVARIANCE_MAX_CONDITION_NUMBER);
451+
testCovariance(twist_covariance, TWIST_COVARIANCE_MAX_CONDITION_NUMBER);
527452

528453
// Take the last two odometry messages:
529454
std::vector<nav_msgs::Odometry> odoms = getLastOdoms();
@@ -596,6 +521,9 @@ TEST_F(DiffDriveControllerTest, testTurn)
596521
EXPECT_NEAR(yaw_0, yaw, ORIENTATION_TOLERANCE);
597522

598523
// Check new pose covariance is equal to the expected one:
524+
const Eigen::IOFormat HeavyFmt(
525+
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
526+
599527
EXPECT_TRUE(((pose_covariance_0_expected - pose_covariance_0).array().abs() < 1e-5).all())
600528
<< "Pose covariance actual =\n" << pose_covariance_0.format(HeavyFmt)
601529
<< "\nPose covariance expected =\n" << pose_covariance_0_expected.format(HeavyFmt);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
///////////////////////////////////////////////////////////////////////////////
2+
// Copyright (C) 2013, PAL Robotics S.L.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
// * Redistributions of source code must retain the above copyright notice,
7+
// this list of conditions and the following disclaimer.
8+
// * Redistributions in binary form must reproduce the above copyright
9+
// notice, this list of conditions and the following disclaimer in the
10+
// documentation and/or other materials provided with the distribution.
11+
// * Neither the name of PAL Robotics, Inc. nor the names of its
12+
// contributors may be used to endorse or promote products derived from
13+
// this software without specific prior written permission.
14+
//
15+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25+
// POSSIBILITY OF SUCH DAMAGE.
26+
///////////////////////////////////////////////////////////////////////////////
27+
28+
/// \author Enrique Fernandez
29+
30+
#include <diff_drive_controller/covariance.h>
31+
32+
#include <gtest/gtest.h>
33+
34+
#include <Eigen/Dense>
35+
36+
template <typename T, int N>
37+
void testCovariance(const Eigen::Matrix<T, N, N>& covariance,
38+
const double max_condition_number = 1e3)
39+
{
40+
using namespace diff_drive_controller;
41+
42+
static const Eigen::IOFormat HeavyFmt(
43+
Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
44+
45+
typedef Eigen::SelfAdjointEigenSolver< Eigen::Matrix<T, N, N> > EigenSolver;
46+
47+
EigenSolver eigensolver(covariance);
48+
49+
EXPECT_TRUE(eigensolver.info() == Eigen::Success)
50+
<< "Covariance =\n" << covariance.format(HeavyFmt);
51+
52+
EXPECT_TRUE(isSymmetric(covariance))
53+
<< "Covariance =\n" << covariance.format(HeavyFmt);
54+
EXPECT_TRUE(isPositiveDefinite(covariance, no_tag()))
55+
<< "Covariance =\n" << covariance.format(HeavyFmt) << "\n"
56+
<< "Eigenvalues = " << eigensolver.eigenvalues().transpose().format(HeavyFmt);
57+
EXPECT_LT(conditionNumber(covariance), max_condition_number)
58+
<< "Covariance =\n" << covariance.format(HeavyFmt) << "\n"
59+
<< "Condition number = " << conditionNumber(covariance) << "\n"
60+
<< "Eigenvalues = " << eigensolver.eigenvalues().transpose().format(HeavyFmt);
61+
}

0 commit comments

Comments
 (0)