26 #include "gtest/gtest.h" 29 namespace kalman_filter {
32 constexpr
double kOdometerVariance = 1e-12;
34 using transform::IsNearly;
38 class PoseTrackerTest :
public ::testing::Test {
43 orientation_model_variance = 1e-8, 44 position_model_variance = 1e-8, 45 velocity_model_variance = 1e-8, 46 imu_gravity_time_constant = 100., 47 imu_gravity_variance = 1e-9, 48 num_odometry_states = 1, 51 const proto::PoseTrackerOptions options =
60 TEST_F(PoseTrackerTest, SaveAndRestore) {
61 std::vector<Rigid3d> poses(3);
62 std::vector<PoseCovariance> covariances(3);
64 &poses[0], &covariances[0]);
71 const Eigen::Vector3d observation(2, 0, 8);
76 &poses[1], &covariances[1]);
78 copy_of_pose_tracker.AddImuLinearAccelerationObservation(
80 copy_of_pose_tracker.GetPoseEstimateMeanAndCovariance(
83 EXPECT_THAT(poses[0], Not(IsNearly(poses[1], 1e-6)));
84 EXPECT_FALSE((covariances[0].array() == covariances[1].array()).all());
85 EXPECT_THAT(poses[1], IsNearly(poses[2], 1e-6));
86 EXPECT_TRUE((covariances[1].array() == covariances[2].array()).all());
89 TEST_F(PoseTrackerTest, AddImuLinearAccelerationObservation) {
92 for (
int i = 0; i < 300; ++i) {
93 time += std::chrono::seconds(5);
95 time, Eigen::Vector3d(0., 0., 10.));
102 const Eigen::Quaterniond actual = Eigen::Quaterniond(pose.rotation());
103 const Eigen::Quaterniond expected = Eigen::Quaterniond::Identity();
104 EXPECT_TRUE(actual.isApprox(expected, 1e-3)) << expected.coeffs() <<
" vs\n" 108 for (
int i = 0; i < 300; ++i) {
109 time += std::chrono::seconds(5);
111 time, Eigen::Vector3d(0., 10., 0.));
114 time += std::chrono::milliseconds(5);
119 const Eigen::Quaterniond actual = Eigen::Quaterniond(pose.rotation());
120 const Eigen::Quaterniond expected = Eigen::Quaterniond(
121 Eigen::AngleAxisd(M_PI / 2., Eigen::Vector3d::UnitX()));
122 EXPECT_TRUE(actual.isApprox(expected, 1e-3)) << expected.coeffs() <<
" vs\n" 126 TEST_F(PoseTrackerTest, AddImuAngularVelocityObservation) {
129 for (
int i = 0; i < 300; ++i) {
130 time += std::chrono::milliseconds(5);
132 Eigen::Vector3d::Zero());
139 const Eigen::Quaterniond actual = Eigen::Quaterniond(pose.rotation());
140 const Eigen::Quaterniond expected = Eigen::Quaterniond::Identity();
141 EXPECT_TRUE(actual.isApprox(expected, 1e-3)) << expected.coeffs() <<
" vs\n" 145 const double target_radians = M_PI / 2.;
146 const double num_observations = 300.;
147 const double angular_velocity = target_radians / (num_observations * 5e-3);
148 for (
int i = 0; i < num_observations; ++i) {
149 time += std::chrono::milliseconds(5);
151 time, Eigen::Vector3d(angular_velocity, 0., 0.));
154 time += std::chrono::milliseconds(5);
159 const Eigen::Quaterniond actual = Eigen::Quaterniond(pose.rotation());
160 const Eigen::Quaterniond expected = Eigen::Quaterniond(
161 Eigen::AngleAxisd(M_PI / 2., Eigen::Vector3d::UnitX()));
162 EXPECT_TRUE(actual.isApprox(expected, 1e-3)) << expected.coeffs() <<
" vs\n" 166 TEST_F(PoseTrackerTest, AddPoseObservation) {
169 for (
int i = 0; i < 300; ++i) {
170 time += std::chrono::milliseconds(5);
172 time, Rigid3d::Identity(),
173 Eigen::Matrix<double, 6, 6>::Identity() * 1e-6);
180 EXPECT_THAT(actual, IsNearly(Rigid3d::Identity(), 1e-3));
184 Rigid3d::Translation(Eigen::Vector3d(1., 2., 3.)) *
185 Rigid3d::Rotation(Eigen::AngleAxisd(
186 M_PI / 2., Eigen::Vector3d(0., 0., 3.).normalized()));
188 for (
int i = 0; i < 300; ++i) {
189 time += std::chrono::milliseconds(15);
191 time, expected, Eigen::Matrix<double, 6, 6>::Identity() * 1e-9);
194 time += std::chrono::milliseconds(15);
199 EXPECT_THAT(actual, IsNearly(expected, 1e-3));
202 TEST_F(PoseTrackerTest, AddOdometerPoseObservation) {
205 std::vector<Rigid3d> odometer_track;
206 odometer_track.push_back(Rigid3d::Identity());
207 odometer_track.push_back(
208 Rigid3d::Rotation(Eigen::AngleAxisd(0.3, Eigen::Vector3d::UnitZ())));
209 odometer_track.push_back(
210 Rigid3d::Translation(Eigen::Vector3d(0.2, 0., 0.)) *
211 Rigid3d::Rotation(Eigen::AngleAxisd(0.3, Eigen::Vector3d::UnitZ())));
212 odometer_track.push_back(
213 Rigid3d::Translation(Eigen::Vector3d(0.3, 0.1, 0.)) *
214 Rigid3d::Rotation(Eigen::AngleAxisd(0.6, Eigen::Vector3d::UnitZ())));
215 odometer_track.push_back(
216 Rigid3d::Translation(Eigen::Vector3d(0.2, 0.2, 0.1)) *
217 Rigid3d::Rotation(Eigen::AngleAxisd(0.3, Eigen::Vector3d::UnitZ())));
218 odometer_track.push_back(
219 Rigid3d::Translation(Eigen::Vector3d(0.1, 0.2, 0.2)) *
220 Rigid3d::Rotation(Eigen::AngleAxisd(0.6, Eigen::Vector3d::UnitZ())));
221 odometer_track.push_back(Rigid3d::Translation(Eigen::Vector3d(0., 0.1, 0.2)));
226 time += std::chrono::seconds(1);
228 time,
pose, kOdometerVariance * PoseCovariance::Identity());
229 pose_tracker_->GetPoseEstimateMeanAndCovariance(time, &actual,
231 EXPECT_THAT(actual, IsNearly(
pose, 1e-2));
234 EXPECT_THAT(actual, Not(IsNearly(odometer_track[0], 1e-2)));
proto::PoseTrackerOptions CreatePoseTrackerOptions(common::LuaParameterDictionary *const parameter_dictionary)
Eigen::Matrix< double, 6, 6 > PoseCovariance
UniversalTimeScaleClock::time_point Time
std::unique_ptr< LuaParameterDictionary > MakeDictionary(const string &code)
Time FromUniversal(const int64 ticks)
std::unique_ptr< PoseTracker > pose_tracker_