diff --git a/src/Quaternion/Quaternion.h b/src/Quaternion/Quaternion.h index a1641a5..b546b61 100644 --- a/src/Quaternion/Quaternion.h +++ b/src/Quaternion/Quaternion.h @@ -13,10 +13,40 @@ public: Quaternion(const Matrix<1, 4> &matrix) : Matrix<1, 4>(matrix) {} Quaternion(const std::array &array) : Matrix<1, 4>(array) {} + /** + * @brief Access the elements of the quaternion + * @param index The index of the element to access + * @return The value of the element at the index + */ float operator[](uint8_t index); + + /** + * @brief Add two quaternions together + * @param other The quaternion to add to this one + * @return The net quaternion + */ Quaternion operator+(const Quaternion &other); + + /** + * @brief Rotate a quaternion by another quaternion + * @param other The quaternion to rotate by + * @param buffer The buffer to store the result in + * @return A reference to the buffer + */ Quaternion &Rotate(Quaternion &other, Quaternion &buffer); + + /** + * @brief Calculate the Euler angles from the quaternion + * @param angleBuffer The buffer to store the angles in + * @return A reference to the buffer + */ Matrix<1, 3> &ToEulerAngles(Matrix<1, 3> &angleBuffer); + + /** + * @brief Convert the quaternion to a rotation matrix + * @param rotationMatrixBuffer The buffer to store the rotation matrix in + * @return A reference to the buffer + */ Matrix<3, 3> &ToRotationMatrix(Matrix<3, 3> &rotationMatrixBuffer); // Give people an easy way to access the elements diff --git a/unit-tests/CMakeLists.txt b/unit-tests/CMakeLists.txt index ab34785..9d2afc4 100644 --- a/unit-tests/CMakeLists.txt +++ b/unit-tests/CMakeLists.txt @@ -36,6 +36,6 @@ add_executable(quaternion-tests quaternion-tests.cpp) target_link_libraries(quaternion-tests PRIVATE - quaternion-intf + quaternion Catch2::Catch2WithMain ) \ No newline at end of file diff --git a/unit-tests/quaternion-tests.cpp b/unit-tests/quaternion-tests.cpp index 6737548..0b5f1ad 100644 --- a/unit-tests/quaternion-tests.cpp +++ b/unit-tests/quaternion-tests.cpp @@ -52,4 +52,55 @@ TEST_CASE("Vector Math", "Vector") REQUIRE(q6.v3 == 3); REQUIRE(q6.w == 4); } + + SECTION("Array access") + { + REQUIRE(q1[0] == 1); + REQUIRE(q1[1] == 2); + REQUIRE(q1[2] == 3); + REQUIRE(q1[3] == 4); + } + + SECTION("Addition") + { + Quaternion q3 = q1 + q2; + REQUIRE(q3.v1 == 5); + REQUIRE(q3.v2 == 12); + REQUIRE(q3.v3 == 21); + REQUIRE(q3.w == 32); + } + + SECTION("Rotation") + { + Quaternion q3; + q1.Rotate(q2, q3); + REQUIRE(q3.v1 == -24); + REQUIRE(q3.v2 == 48); + REQUIRE(q3.v3 == 48); + REQUIRE(q3.w == -6); + } + + SECTION("Euler Angles") + { + Matrix<1, 3> angles; + q1.ToEulerAngles(angles); + REQUIRE_THAT(angles.Get(0, 0), Catch::Matchers::WithinRel(-0.1973956f, 1e-6f)); + REQUIRE_THAT(angles.Get(0, 1), Catch::Matchers::WithinRel(0.823212f, 1e-6f)); + REQUIRE_THAT(angles.Get(0, 2), Catch::Matchers::WithinRel(1.3734008f, 1e-6f)); + } + + SECTION("Rotation Matrix") + { + Matrix<3, 3> rotationMatrix; + q1.ToRotationMatrix(rotationMatrix); + REQUIRE_THAT(rotationMatrix.Get(0, 0), Catch::Matchers::WithinRel(0.1333333f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(0, 1), Catch::Matchers::WithinRel(-0.6666667f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(0, 2), Catch::Matchers::WithinRel(0.7333333f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(1, 0), Catch::Matchers::WithinRel(0.9333333f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(1, 1), Catch::Matchers::WithinRel(0.3333333f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(1, 2), Catch::Matchers::WithinRel(0.1333333f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(2, 0), Catch::Matchers::WithinRel(-0.3333333f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(2, 1), Catch::Matchers::WithinRel(0.6666667f, 1e-6f)); + REQUIRE_THAT(rotationMatrix.Get(2, 2), Catch::Matchers::WithinRel(0.6666667f, 1e-6f)); + } } \ No newline at end of file