diff --git a/include/eal.h b/include/eal.h index 5858e7ae00c54b01023fb158bdb965bcbd269bdd..4d68e22144e14792ebbd353585a4d4f338a6afd1 100644 --- a/include/eal.h +++ b/include/eal.h @@ -24,8 +24,8 @@ namespace eal { std::vector times, double time, const interpolation interp); - std::vector getPosition(std::vector coeffs, double time); - std::vector getVelocity(std::vector coeffs, double time); + std::vector getPosition(std::vector> coeffs, double time); + std::vector getVelocity(std::vector> coeffs, double time); std::vector getRotation(std::string from, std::string to, std::vector> rotations, @@ -40,10 +40,8 @@ namespace eal { std::vector coefficients, double time); std::vector getAngularVelocity(std::string from, std::string to, std::vector coefficients, double time); - + double evaluatePolynomial(std::vector coeffs, double time); double interpolate(std::vector points, std::vector times, double time, interpolation interp, int d); - - } #endif // EAL_H diff --git a/src/eal.cpp b/src/eal.cpp index f02078caa264b2f82bb87af861da307c49ec1532..952c6089f8c6f633c0e3080eda4d2d18b40f14e6 100644 --- a/src/eal.cpp +++ b/src/eal.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -27,7 +28,6 @@ namespace eal { return state; } - // Positional Functions // Position Data Functions vector getPosition(vector> coords, vector times, double time, @@ -67,12 +67,31 @@ namespace eal { } // Postion Function Functions - vector getPosition(vector coeffs, double time) { - vector coordinate = {0.0, 0.0, 0.0}; + // vector coeffs = [[cx_0, cx_1, cx_2 ..., cx_n], + // [cy_0, cy_1, cy_2, ... cy_n], + // [cz_0, cz_1, cz_2, ... cz_n]] + // The equations evaluated by this function are: + // x = cx_n * t^n + cx_n-1 * t^(n-1) + ... + cx_0 + // y = cy_n * t^n + cy_n-1 * t^(n-1) + ... + cy_0 + // z = cz_n * t^n + cz_n-1 * t^(n-1) + ... + cz_0 + vector getPosition(vector> coeffs, double time) { + + if (coeffs.size() != 3) { + throw invalid_argument("Invalid input coeffs, expected three vectors."); + } + + vector coordinate = {0.0, 0.0, 0.0}; + coordinate[0] = evaluatePolynomial(coeffs[0], time); // X + coordinate[1] = evaluatePolynomial(coeffs[1], time); // Y + coordinate[2] = evaluatePolynomial(coeffs[2], time); // Z + return coordinate; } - vector getVelocity(vector coeffs, double time) { + + // Velocity Function + // Takes the coefficients from the position equation + vector getVelocity(vector> coeffs, double time) { vector coordinate = {0.0, 0.0, 0.0}; return coordinate; } @@ -105,6 +124,17 @@ namespace eal { return coordinate; } + // Polynomial evaluation helper function + // The equation evaluated by this function is: + // x = cx_0 + cx_1 * t^(1) + ... + cx_n * t^n + double evaluatePolynomial(vector coeffs, double time){ + if (coeffs.empty()) { + throw invalid_argument("Invalid input coeffs, must be non-empty."); + } + + const double *coeffsArray = coeffs.data(); + return gsl_poly_eval(coeffsArray, coeffs.size(), time); + } double interpolate(vector points, vector times, double time, interpolation interp, int d) { size_t numPoints = points.size(); diff --git a/tests/EalTest.cpp b/tests/EalTest.cpp index fd669b691ef9a94126c4e8911012b4bd27cb21fa..598b109539f5a77352feb194e35e82094f2fedef 100644 --- a/tests/EalTest.cpp +++ b/tests/EalTest.cpp @@ -135,3 +135,54 @@ TEST(SplineInterpTest, Extrapolate) { EXPECT_THROW(eal::interpolate(data, times, 4.0, eal::spline, 0), invalid_argument); } + +TEST(PoisitionCoeffTest, SecondOrderPolynomial) { + double time = 2.0; + vector> coeffs = {{1.0, 2.0, 3.0}, + {1.0, 3.0, 2.0}, + {3.0, 2.0, 1.0}}; + + vector coordinate = eal::getPosition(coeffs, time); + + ASSERT_EQ(3, coordinate.size()); + EXPECT_DOUBLE_EQ(17.0, coordinate[0]); + EXPECT_DOUBLE_EQ(15.0, coordinate[1]); + EXPECT_DOUBLE_EQ(11.0, coordinate[2]); +} + +TEST(PoisitionCoeffTest, DifferentPolynomialDegrees) { + double time = 2.0; + vector> coeffs = {{1.0}, + {1.0, 2.0}, + {1.0, 2.0, 3.0}}; + + vector coordinate = eal::getPosition(coeffs, time); + + ASSERT_EQ(3, coordinate.size()); + EXPECT_DOUBLE_EQ(1.0, coordinate[0]); + EXPECT_DOUBLE_EQ(5.0, coordinate[1]); + EXPECT_DOUBLE_EQ(17.0, coordinate[2]); +} + +TEST(PoisitionCoeffTest, NegativeInputs) { + double time = -2.0; + vector> coeffs = {{-1.0, -2.0, -3.0}, + {1.0, -2.0, 3.0}, + {-1.0, 2.0, -3.0}}; + + vector coordinate = eal::getPosition(coeffs, time); + + ASSERT_EQ(3, coordinate.size()); + EXPECT_DOUBLE_EQ(-9.0, coordinate[0]); + EXPECT_DOUBLE_EQ(17.0, coordinate[1]); + EXPECT_DOUBLE_EQ(-17.0, coordinate[2]); +} + + +TEST(PoisitionCoeffTest, InvalidInput) { + double valid_time = 0.0; + vector> invalid_coeffs_sizes = {{3.0, 2.0, 1.0}, + {1.0, 2.0, 3.0}}; + + EXPECT_THROW(eal::getPosition(invalid_coeffs_sizes, valid_time), invalid_argument); +}