From 069b576856c78e54eae9e670d273da0c3a0279ac Mon Sep 17 00:00:00 2001 From: Kristin <kberry@usgs.gov> Date: Mon, 6 Jul 2020 11:44:41 -0700 Subject: [PATCH] Normalize quaternions in Rotations (#377) * Update format of range conversion coefficients isd output to include a separate list for times. Also update driver, test data, and remove unneeded semicolons * Fix documentaion error * fix other documentation error * Add quaternion normalization * Add test that makes sure an unnormalized quaternion is normalized in the rotation constructor --- include/ale/Rotation.h | 2 +- src/Rotation.cpp | 5 +++-- tests/ctests/RotationTests.cpp | 12 ++++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/ale/Rotation.h b/include/ale/Rotation.h index 5b28031..2df46d6 100644 --- a/include/ale/Rotation.h +++ b/include/ale/Rotation.h @@ -77,7 +77,7 @@ namespace ale { std::vector<double> toRotationMatrix() const; /** - * Create a state rotation matrix from the rotation and an angula velocity. + * Create a state rotation matrix from the rotation and an angular velocity. * * @param av The angular velocity vector. * diff --git a/src/Rotation.cpp b/src/Rotation.cpp index bde05fd..07c691f 100644 --- a/src/Rotation.cpp +++ b/src/Rotation.cpp @@ -65,7 +65,7 @@ namespace ale { throw std::invalid_argument("Rotation matrix must be 3 by 3."); } // The data is in row major order, so take the transpose to get column major order - quat = Eigen::Quaterniond(Eigen::Quaterniond::Matrix3(matrix.data()).transpose()); + quat = Eigen::Quaterniond(Eigen::Quaterniond::Matrix3(matrix.data()).transpose()).normalized(); } @@ -81,6 +81,7 @@ namespace ale { for (size_t i = 0; i < angles.size(); i++) { quat *= Eigen::Quaterniond(Eigen::AngleAxisd(angles[i], axis(axes[i]))); } + quat = quat.normalized(); } @@ -89,7 +90,7 @@ namespace ale { throw std::invalid_argument("Rotation axis must have 3 elements."); } Eigen::Vector3d eigenAxis((double *) axis.data()); - quat = Eigen::Quaterniond(Eigen::AngleAxisd(theta, eigenAxis.normalized())); + quat = Eigen::Quaterniond(Eigen::AngleAxisd(theta, eigenAxis.normalized())).normalized(); } diff --git a/tests/ctests/RotationTests.cpp b/tests/ctests/RotationTests.cpp index 2271ace..8e4517c 100644 --- a/tests/ctests/RotationTests.cpp +++ b/tests/ctests/RotationTests.cpp @@ -28,6 +28,18 @@ TEST(RotationTest, QuaternionConstructor) { EXPECT_NEAR(quat[3], 0.0, 1e-10); } +TEST(RotationTest, UnnormalizedQuaternion) { + Rotation rotation(1.0, 1.0, 0.0, 0.0); + vector<double> quat = rotation.toQuaternion(); + ASSERT_EQ(quat.size(), 4); + // The constructor will normalize the quaternion. + EXPECT_NEAR(quat[0], 1.0/sqrt(2), 1e-10); + EXPECT_NEAR(quat[1], 1.0/sqrt(2), 1e-10); + EXPECT_NEAR(quat[2], 0.0, 1e-10); + EXPECT_NEAR(quat[3], 0.0, 1e-10); +} + + TEST(RotationTest, MatrixConstructor) { Rotation rotation( {0.0, 1.0, 0.0, -- GitLab