/* * Copyright 2017 The Cartographer Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "cartographer/mapping/imu_tracker.h" #include "absl/memory/memory.h" #include "cartographer/mapping/internal/eigen_quaterniond_from_two_vectors.h" #include "gtest/gtest.h" namespace cartographer { namespace mapping { namespace { constexpr double kDuration = 3.f; constexpr double kGravityTimeConstant = 0.1 * kDuration; constexpr double kPrecision = 1e-8; constexpr int kSteps = 10; class ImuTrackerTest : public ::testing::Test { protected: void SetUp() override { imu_tracker_ = absl::make_unique(kGravityTimeConstant, time_); angular_velocity_ = Eigen::Vector3d(0, 0, 0); linear_acceleration_ = Eigen::Vector3d(0, 0, 9.9); EXPECT_NEAR(0., imu_tracker_->orientation().angularDistance( Eigen::Quaterniond::Identity()), kPrecision); } void AdvanceImu() { for (int i = 0; i < kSteps; ++i) { imu_tracker_->AddImuLinearAccelerationObservation(linear_acceleration_); imu_tracker_->AddImuAngularVelocityObservation(angular_velocity_); time_ += common::FromSeconds(kDuration / kSteps); imu_tracker_->Advance(time_); } EXPECT_EQ(time_, imu_tracker_->time()); } Eigen::Vector3d angular_velocity_; std::unique_ptr imu_tracker_; Eigen::Vector3d linear_acceleration_; common::Time time_ = common::FromUniversal(12345678); }; TEST_F(ImuTrackerTest, IntegrateYawRotation) { angular_velocity_ = Eigen::Vector3d(0, 0, 0.3); AdvanceImu(); Eigen::Quaterniond expected_orientation(Eigen::AngleAxisd( kDuration * angular_velocity_.norm(), angular_velocity_.normalized())); EXPECT_NEAR(0., imu_tracker_->orientation().angularDistance(expected_orientation), kPrecision); } TEST_F(ImuTrackerTest, IntegrateFullRotation) { angular_velocity_ = Eigen::Vector3d(0.1, 0.4, 0.1); // Using a huge gravity time constant effectively disables gravity vector // tracking. imu_tracker_.reset(new ImuTracker(1e10 * kDuration, time_)); AdvanceImu(); Eigen::Quaterniond expected_orientation(Eigen::AngleAxisd( kDuration * angular_velocity_.norm(), angular_velocity_.normalized())); EXPECT_NEAR(0., imu_tracker_->orientation().angularDistance(expected_orientation), kPrecision); } TEST_F(ImuTrackerTest, LearnGravityVector) { linear_acceleration_ = Eigen::Vector3d(0.5, 0.3, 9.5); AdvanceImu(); const Eigen::Quaterniond expected_orientation = FromTwoVectors(linear_acceleration_, Eigen::Vector3d::UnitZ()); EXPECT_NEAR(0., imu_tracker_->orientation().angularDistance(expected_orientation), kPrecision); } } // namespace } // namespace mapping } // namespace cartographer