Skip to content

Commit c409297

Browse files
authored
feat: ssa template overload for containers (#18)
1 parent 152f8a2 commit c409297

4 files changed

Lines changed: 78 additions & 3 deletions

File tree

cpp_test/test_math.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,43 @@ TEST(ssa, test_ssa_minus_3_5) {
2525
EXPECT_NEAR(2.78, ssa(-3.5), 0.01);
2626
}
2727

28+
TEST(ssa, test_ssa_minus_pi) {
29+
EXPECT_EQ(M_PI, ssa(-M_PI));
30+
}
31+
32+
TEST(ssa, test_ssa_pi) {
33+
EXPECT_EQ(M_PI, ssa(M_PI));
34+
}
35+
36+
TEST(ssa, test_ssa_vector) {
37+
Eigen::VectorXd angles(6);
38+
angles << 0.0, M_PI / 2, M_PI, 3 * M_PI, -4 * M_PI, -3 * M_PI / 2.0;
39+
40+
Eigen::VectorXd expected(6);
41+
expected << 0.0, M_PI / 2, M_PI, M_PI, 0.0, M_PI / 2.0;
42+
43+
Eigen::VectorXd result = ssa(angles);
44+
EXPECT_TRUE(result.isApprox(expected, 1e-12));
45+
46+
std::vector<double> angle_vec{0.0, M_PI / 2, M_PI,
47+
3 * M_PI, -4 * M_PI, -3 * M_PI / 2.0};
48+
std::vector<double> expected_vec{0.0, M_PI / 2, M_PI,
49+
M_PI, 0.0, M_PI / 2.0};
50+
std::vector<double> result_vec = ssa(angle_vec);
51+
for (size_t i = 0; i < angle_vec.size(); ++i) {
52+
EXPECT_NEAR(expected_vec[i], result_vec[i], 1e-12);
53+
}
54+
55+
std::array<double, 6> angle_array{0.0, M_PI / 2, M_PI,
56+
3 * M_PI, -4 * M_PI, -3 * M_PI / 2.0};
57+
std::array<double, 6> expected_array{0.0, M_PI / 2, M_PI,
58+
M_PI, 0.0, M_PI / 2.0};
59+
std::array<double, 6> result_array = ssa(angle_array);
60+
for (size_t i = 0; i < angle_array.size(); ++i) {
61+
EXPECT_NEAR(expected_array[i], result_array[i], 1e-12);
62+
}
63+
}
64+
2865
// Test that the skew-symmetric matrix is correctly calculated
2966
TEST(get_skew_symmetric_matrix, test_skew_symmetric) {
3067
Eigen::Vector3d vector(1, 2, 3);

include/vortex/utils/math.hpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,48 @@
22
#define VORTEX_UTILS_MATH_HPP
33

44
#include <cmath>
5+
#include <concepts>
56
#include <eigen3/Eigen/Dense>
67
#include <eigen3/Eigen/Geometry>
78

89
namespace vortex::utils::math {
910

1011
/**
11-
* @brief Function to calculate the smallest signed angle between two angles.
12-
* Maps the angle to the interval [-pi, pi].
12+
* @brief Function to calculate the smallest signed angle.
13+
* Maps the angle to the interval (-pi, pi].
1314
* @param angle The input angle in radians.
1415
* @return The smallest signed angle in radians.
1516
*/
1617
double ssa(const double angle);
1718

19+
/**
20+
* @brief Function to calculate the smallest signed angles in a container.
21+
* Maps the angles to the interval [-pi, pi]. Works with containers like
22+
* std::vector, std::array, Eigen::VectorXd etc.
23+
* @param angles The input angles in radians.
24+
* @return The smallest signed angles in radians.
25+
*/
26+
template <typename T>
27+
concept VectorLike = !std::is_arithmetic_v<std::decay_t<T>> && requires(T t) {
28+
{ *std::begin(t) } -> std::convertible_to<double>;
29+
};
30+
template <VectorLike Container>
31+
auto ssa(Container&& angles_in) {
32+
using ContainerT = std::decay_t<Container>;
33+
using std::begin;
34+
35+
ContainerT angles = std::forward<Container>(angles_in);
36+
37+
using value_type = std::decay_t<decltype(*begin(angles))>;
38+
static_assert(std::is_floating_point_v<value_type>);
39+
40+
for (auto& a : angles) {
41+
a = static_cast<value_type>(ssa(static_cast<double>(a)));
42+
}
43+
44+
return angles;
45+
}
46+
1847
/**
1948
* @brief Calculates the skew-symmetric matrix from a 3D vector.
2049
* @param vector Eigen::Vector3d

include/vortex/utils/types.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ struct Eta {
6060
return Eigen::Vector<double, 6>{x, y, z, roll, pitch, yaw};
6161
}
6262

63+
/**
64+
* @brief Apply smallest signed angle to roll, pitch, and yaw.
65+
*/
66+
void apply_ssa() {
67+
roll = vortex::utils::math::ssa(roll);
68+
pitch = vortex::utils::math::ssa(pitch);
69+
yaw = vortex::utils::math::ssa(yaw);
70+
}
71+
6372
/**
6473
* @brief Make the rotation matrix corresponding to eq. 2.31 in Fossen, 2021
6574
* @return Eigen::Matrix3d rotation matrix

src/math.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace vortex::utils::math {
44

55
double ssa(const double angle) {
66
double angle_ssa{fmod(angle + M_PI, 2 * M_PI)};
7-
return angle_ssa < 0 ? angle_ssa + M_PI : angle_ssa - M_PI;
7+
return angle_ssa <= 0 ? angle_ssa + M_PI : angle_ssa - M_PI;
88
}
99

1010
Eigen::Matrix3d get_skew_symmetric_matrix(const Eigen::Vector3d& vector) {

0 commit comments

Comments
 (0)