Directory: | ./ |
---|---|
File: | include/parametric-curves/polynomial.hpp |
Date: | 2025-05-07 13:05:43 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 65 | 84 | 77.4% |
Branches: | 43 | 94 | 45.7% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * \file polynomial.hpp | ||
3 | * \brief Definition of a cubic spline. | ||
4 | * \author Steve T. | ||
5 | * \version 0.1 | ||
6 | * \date 06/17/2013 | ||
7 | * | ||
8 | * This file contains definitions for the Polynomial struct. | ||
9 | * It allows the creation and evaluation of natural | ||
10 | * smooth splines of arbitrary dimension and order | ||
11 | */ | ||
12 | |||
13 | #ifndef _parameteric_curves_polynomial_hpp | ||
14 | #define _parameteric_curves_polynomial_hpp | ||
15 | |||
16 | #include <Eigen/Dense> | ||
17 | #include <boost/archive/text_iarchive.hpp> | ||
18 | #include <boost/archive/text_oarchive.hpp> | ||
19 | #include <parametric-curves/abstract-curve.hpp> | ||
20 | #include <parametric-curves/serialization/eigen-matrix.hpp> | ||
21 | #include <stdexcept> | ||
22 | #include <vector> | ||
23 | |||
24 | namespace parametriccurves { | ||
25 | /// \class Polynomial | ||
26 | /// \brief Represents a Polynomialf arbitrary order defined on the interval | ||
27 | /// [tBegin, tEnd]. It follows the equation | ||
28 | /// x(t) = a + b(t - t_min_) + ... + d(t - t_min_)^N, where N is the order | ||
29 | /// | ||
30 | template <typename Numeric = double, Eigen::Index Dim = 3, | ||
31 | typename Point = Eigen::Matrix<Numeric, Dim, 1> > | ||
32 | struct Polynomial : public parametriccurves::AbstractCurve<Numeric, Point> { | ||
33 | typedef Point point_t; | ||
34 | typedef Numeric time_t; | ||
35 | typedef Numeric num_t; | ||
36 | typedef std::vector<Point, Eigen::aligned_allocator<Point> > t_point_t; | ||
37 | typedef AbstractCurve<Numeric, Point> curve_abc_t; | ||
38 | typedef Eigen::Matrix<double, Dim, Eigen::Dynamic> coeff_t; | ||
39 | typedef Eigen::Ref<coeff_t> coeff_t_ref; | ||
40 | |||
41 | public: | ||
42 | ///\brief Constructor | ||
43 | ///\param coefficients : a reference to an Eigen matrix where each column is a | ||
44 | /// coefficient, | ||
45 | /// from the zero order coefficient, up to the highest order. Spline order is | ||
46 | /// given by the number of the columns -1. | ||
47 | ///\param min: LOWER bound on interval definition of the spline | ||
48 | ///\param max: UPPER bound on interval definition of the spline | ||
49 | 1 | Polynomial(const coeff_t& coefficients, const time_t tmin, const time_t tmax) | |
50 | : curve_abc_t(tmin, tmax), | ||
51 | 1 | coefficients_(coefficients), | |
52 | 1 | dim_(Dim), | |
53 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | order_(coefficients_.cols() - 1) { |
54 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | safe_check(); |
55 | 1 | } | |
56 | |||
57 | ///\brief Constructor | ||
58 | ///\param coefficients : a container containing all coefficients of the | ||
59 | /// spline, starting | ||
60 | /// with the zero order coefficient, up to the highest order. Spline order is | ||
61 | /// given by the size of the coefficients | ||
62 | ///\param min: LOWER bound on interval definition of the spline | ||
63 | ///\param max: UPPER bound on interval definition of the spline | ||
64 | 1 | Polynomial(const t_point_t& coefficients, const time_t tmin, | |
65 | const time_t tmax) | ||
66 | : curve_abc_t(tmin, tmax), | ||
67 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | coefficients_(init_coeffs(coefficients.begin(), coefficients.end())), |
68 | 1 | dim_(Dim), | |
69 | 2 | order_(coefficients_.cols() - 1) { | |
70 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | safe_check(); |
71 | 1 | } | |
72 | |||
73 | ✗ | Polynomial() {} | |
74 | |||
75 | ///\brief Constructor | ||
76 | ///\param zeroOrderCoefficient : an iterator pointing to the first element of | ||
77 | /// a structure containing the coefficients | ||
78 | /// it corresponds to the zero degree coefficient | ||
79 | ///\param out : an iterator pointing to the last element of a structure | ||
80 | /// ofcoefficients \param min: LOWER bound on interval definition of the | ||
81 | /// spline \param max: UPPER bound on interval definition of the spline | ||
82 | template <typename In> | ||
83 | 56 | Polynomial(In zeroOrderCoefficient, In out, const time_t tmin, | |
84 | const time_t tmax) | ||
85 | : curve_abc_t(tmin, tmax), | ||
86 | 56 | coefficients_(init_coeffs(zeroOrderCoefficient, out)), | |
87 | 56 | dim_(Dim), | |
88 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
56 | order_(coefficients_.cols() - 1) { |
89 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
56 | safe_check(); |
90 | 56 | } | |
91 | |||
92 | ///\brief Destructor | ||
93 | 116 | ~Polynomial() { | |
94 | // NOTHING | ||
95 | 116 | } | |
96 | |||
97 | 54 | Polynomial(const Polynomial& other) | |
98 | 54 | : curve_abc_t(other.t_min, other.t_max), | |
99 | 54 | coefficients_(other.coefficients_), | |
100 | 54 | dim_(other.dim_), | |
101 |
1/2✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
54 | order_(other.order_) {} |
102 | |||
103 | // Polynomial& operator=(const Polynomial& other); | ||
104 | |||
105 | private: | ||
106 | 59 | void safe_check() { | |
107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
59 | if (this->t_min > this->t_max) std::out_of_range("TODO"); |
108 |
2/2✓ Branch 1 taken 27 times.
✓ Branch 2 taken 3 times.
|
59 | if (static_cast<std::size_t>(coefficients_.size()) != order_ + 1) |
109 | 53 | std::runtime_error("Spline order and coefficients do not match"); | |
110 | 59 | } | |
111 | |||
112 | /* Constructors - destructors */ | ||
113 | |||
114 | /*Operations*/ | ||
115 | public: | ||
116 | /*/// \brief Evaluation of the cubic spline at time t. | ||
117 | /// \param t : the time when to evaluate the spine | ||
118 | /// \param return : the value x(t) | ||
119 | virtual point_t operator()(const time_t t) const | ||
120 | { | ||
121 | if((t < t_min_ || t > t_max_) && Safe){ throw | ||
122 | std::out_of_range("TODO");} time_t const dt (t-t_min_); time_t cdt(1); | ||
123 | point_t currentPoint_ = point_t::Zero(); | ||
124 | for(int i = 0; i < order_+1; ++i, cdt*=dt) | ||
125 | currentPoint_ += cdt *coefficients_.col(i); | ||
126 | return currentPoint_; | ||
127 | }*/ | ||
128 | |||
129 | /// \brief Evaluation of the cubic spline at time t using horner's scheme. | ||
130 | /// \param t : the time when to evaluate the spine | ||
131 | /// \param return : the value x(t) | ||
132 | 60 | virtual const point_t operator()(const time_t& t) const { | |
133 |
4/4✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 28 times.
|
60 | if ((t < this->t_min || t > this->t_max)) { |
134 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | throw std::out_of_range("TODO"); |
135 | } | ||
136 | 56 | const time_t& dt(t); | |
137 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
56 | point_t h = coefficients_.col(order_); |
138 | 56 | std::size_t i = order_ - 1; | |
139 | 56 | bool ok = true; | |
140 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
56 | if (order_ != 0) { |
141 |
3/4✓ Branch 0 taken 88 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
|
232 | while (ok && order_ != 0) { |
142 |
3/6✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 88 times.
✗ Branch 9 not taken.
|
176 | h = dt * h + coefficients_.col(i); |
143 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 60 times.
|
176 | if (i == 0) |
144 | 56 | ok = false; | |
145 | else | ||
146 | 120 | i--; | |
147 | } | ||
148 | 56 | return h; | |
149 | } else | ||
150 | ✗ | return h; | |
151 | } | ||
152 | |||
153 | /// \brief Evaluation of the derivative spline at time t. | ||
154 | /// \param t : the time when to evaluate the spline | ||
155 | /// \param order : order of the derivative | ||
156 | /// \param return : the value x(t) | ||
157 | 48 | virtual const point_t derivate(const time_t& t, | |
158 | const std::size_t& order) const { | ||
159 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
|
48 | if ((t < this->t_min || t > this->t_max)) { |
160 | ✗ | throw std::out_of_range("TODO"); | |
161 | } | ||
162 | 48 | const time_t& dt(t); | |
163 | 48 | time_t cdt(1); | |
164 |
2/4✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
48 | point_t currentPoint_ = point_t::Zero(dim_); |
165 |
2/2✓ Branch 0 taken 68 times.
✓ Branch 1 taken 24 times.
|
184 | for (std::size_t i = order; i < order_ + 1; ++i, cdt *= dt) |
166 |
4/8✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 68 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 68 times.
✗ Branch 12 not taken.
|
136 | currentPoint_ += cdt * coefficients_.col(i) * fact(i, order); |
167 | 96 | return currentPoint_; | |
168 | } | ||
169 | |||
170 | ✗ | virtual const std::size_t& size() const { return dim_; } | |
171 | |||
172 | ✗ | virtual bool setInitialPoint(const point_t& /*x_init*/) { return false; } | |
173 | ✗ | virtual bool setInitialPoint(const num_t& /*x_init*/) { return false; } | |
174 | |||
175 | protected: | ||
176 | coeff_t coefficients_; // const | ||
177 | std::size_t dim_; // const | ||
178 | std::size_t order_; // const | ||
179 | |||
180 | private: | ||
181 | // Serialization of the class | ||
182 | friend class boost::serialization::access; | ||
183 | template <class Archive> | ||
184 | ✗ | void save(Archive& ar, const unsigned int /*version*/) const { | |
185 | ✗ | ar& boost::serialization::make_nvp("dim", dim_); | |
186 | ✗ | ar& boost::serialization::make_nvp("order", order_); | |
187 | ✗ | ar& boost::serialization::make_nvp("coefficients", coefficients_); | |
188 | ✗ | ar& boost::serialization::make_nvp("t_min", this->t_min); | |
189 | ✗ | ar& boost::serialization::make_nvp("t_max", this->t_max); | |
190 | } | ||
191 | |||
192 | template <class Archive> | ||
193 | ✗ | void load(Archive& ar, const unsigned int /*version*/) { | |
194 | ✗ | ar& boost::serialization::make_nvp("dim", dim_); | |
195 | ✗ | ar& boost::serialization::make_nvp("order", order_); | |
196 | ✗ | ar& boost::serialization::make_nvp("coefficients", coefficients_); | |
197 | ✗ | ar& boost::serialization::make_nvp("t_min", this->t_min); | |
198 | ✗ | ar& boost::serialization::make_nvp("t_max", this->t_max); | |
199 | } | ||
200 | |||
201 | ✗ | BOOST_SERIALIZATION_SPLIT_MEMBER() | |
202 | |||
203 | 136 | num_t fact(const std::size_t n, const std::size_t order) const { | |
204 | 136 | std::size_t res(1); | |
205 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 68 times.
|
328 | for (std::size_t i = 0; i < order; ++i) res *= n - i; |
206 | 136 | return static_cast<num_t>(res); | |
207 | } | ||
208 | |||
209 | /*Attributes*/ | ||
210 | template <typename In> | ||
211 | 58 | coeff_t init_coeffs(In zeroOrderCoefficient, In highestOrderCoefficient) { | |
212 | 58 | std::size_t size = | |
213 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
58 | std::distance(zeroOrderCoefficient, highestOrderCoefficient); |
214 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
58 | coeff_t res = coeff_t(Dim, size); |
215 | 58 | int i = 0; | |
216 |
2/2✓ Branch 1 taken 120 times.
✓ Branch 2 taken 29 times.
|
298 | for (In cit = zeroOrderCoefficient; cit != highestOrderCoefficient; |
217 | 240 | ++cit, ++i) | |
218 |
2/4✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 120 times.
✗ Branch 6 not taken.
|
240 | res.col(i) = *cit; |
219 | 116 | return res; | |
220 | } | ||
221 | }; // class Polynomial | ||
222 | } // namespace parametriccurves | ||
223 | #endif //_STRUCT_POLYNOMIAL | ||
224 |