130std::vector<T>
fit_spline(
const std::vector<T> &path,
int precision,
int order,
131 float coeffs_ratio) {
141 size_t n = path.size();
147 size_t ncoeffs =
static_cast<size_t>(
static_cast<float>(n) / coeffs_ratio);
148 if (ncoeffs <
static_cast<size_t>(order)) {
157 const int nbreak =
static_cast<int>(ncoeffs) - order + 2;
159 if (nbreak < 2 || n == 0) {
160 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
161 "Too few points to calculate spline while executing 'fit_spline'"
162 "Number of cones was %i",
163 static_cast<int>(n));
167 gsl_bspline_workspace *bw =
168 ::gsl_bspline_alloc(
static_cast<size_t>(order),
static_cast<size_t>(nbreak));
169 gsl_bspline_workspace *cw = ::gsl_bspline_alloc(order, nbreak);
171 gsl_vector *B = ::gsl_vector_alloc(ncoeffs);
172 gsl_vector *C = ::gsl_vector_alloc(ncoeffs);
173 gsl_vector *c = ::gsl_vector_alloc(ncoeffs);
174 gsl_vector *c2 = ::gsl_vector_alloc(ncoeffs);
176 gsl_vector *w = ::gsl_vector_alloc(n);
177 gsl_vector *x_values = ::gsl_vector_alloc(n);
178 gsl_vector *y_values = ::gsl_vector_alloc(n);
179 gsl_vector *i_values = ::gsl_vector_alloc(n);
181 gsl_matrix *X = ::gsl_matrix_alloc(n, ncoeffs);
182 gsl_matrix *Y = ::gsl_matrix_alloc(n, ncoeffs);
184 gsl_matrix *cov = ::gsl_matrix_alloc(ncoeffs, ncoeffs);
185 gsl_matrix *cov2 = ::gsl_matrix_alloc(ncoeffs, ncoeffs);
187 gsl_multifit_linear_workspace *mw = ::gsl_multifit_linear_alloc(n, ncoeffs);
188 gsl_multifit_linear_workspace *mw2 = ::gsl_multifit_linear_alloc(n, ncoeffs);
194 for (
size_t i = 0; i < n; i++) {
195 ::gsl_vector_set(i_values, i,
static_cast<double>(i));
196 ::gsl_vector_set(x_values, i, path[i].position.x);
197 ::gsl_vector_set(y_values, i, path[i].position.y);
200 double dist_next = 1.0;
202 dist_next = path[i].position.euclidean_distance(path[i + 1].position);
204 dist_next = path[i].position.euclidean_distance(path[i - 1].position);
207 if (dist_next < 1e-6) {
211 ::gsl_vector_set(w, i, 1.0 / (dist_next * dist_next));
216 double t_max =
static_cast<double>(n - 1);
217 (void)::gsl_bspline_knots_uniform(t_min, t_max, bw);
218 (void)::gsl_bspline_knots_uniform(t_min, t_max, cw);
222 for (
int i = 0; i < static_cast<int>(n); i++) {
223 (void)::gsl_bspline_eval(i, B, bw);
224 (void)::gsl_bspline_eval(i, C, cw);
227 for (
int j = 0; j < static_cast<int>(ncoeffs); j++) {
228 ::gsl_matrix_set(X, i, j, ::gsl_vector_get(B, j));
229 ::gsl_matrix_set(Y, i, j, ::gsl_vector_get(C, j));
234 (void)::gsl_multifit_wlinear(X, w, x_values, c, cov, &chisq, mw);
235 (void)::gsl_multifit_wlinear(Y, w, y_values, c2, cov2, &chisq2, mw2);
238 std::vector<T> path_eval;
239 path_eval.reserve(n * precision);
240 for (
int i = 0; i < static_cast<int>(n)-1; i++) {
241 for (
int j = 0; j < precision; j++) {
243 double t =
static_cast<double>(i) +
static_cast<double>(j) / precision;
248 (void)::gsl_bspline_eval(t, B, bw);
249 (void)::gsl_bspline_eval(t, C, cw);
255 (void)::gsl_multifit_linear_est(B, c, cov, &xi, &err);
256 (void)::gsl_multifit_linear_est(C, c2, cov2, &yi, &err);
260 new_element.position.x = xi;
261 new_element.position.y = yi;
262 path_eval.push_back(new_element);
267 ::gsl_bspline_free(bw);
268 ::gsl_bspline_free(cw);
269 ::gsl_vector_free(B);
270 ::gsl_vector_free(C);
271 ::gsl_vector_free(c);
272 ::gsl_vector_free(c2);
273 ::gsl_vector_free(w);
274 ::gsl_vector_free(x_values);
275 ::gsl_vector_free(y_values);
276 ::gsl_vector_free(i_values);
277 ::gsl_matrix_free(X);
278 ::gsl_matrix_free(Y);
279 ::gsl_matrix_free(cov);
280 ::gsl_matrix_free(cov2);
281 ::gsl_multifit_linear_free(mw);
282 ::gsl_multifit_linear_free(mw2);
284 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"END fitSpline with %i points",
285 static_cast<int>(path_eval.size()));
316 const std::vector<T> &right,
int precision,
int order) {
327 const size_t n = center.size();
330 if (n < 2 || left.size() != n || right.size() != n) {
331 RCLCPP_INFO(rclcpp::get_logger(
"rclcpp"),
332 "Invalid input for fit_triple_spline: center has %zu points, "
333 "left has %zu points, right has %zu points. All must be >= 2 and equal.",
334 center.size(), left.size(), right.size());
340 std::vector<double> t_values(n);
343 for (
size_t i = 1; i < n; ++i) {
344 double dist = center[i].position.euclidean_distance(center[i - 1].position);
345 t_values[i] = t_values[i - 1] + dist;
349 std::vector<double> center_x(n);
350 std::vector<double> center_y(n);
351 std::vector<double> left_x(n);
352 std::vector<double> left_y(n);
353 std::vector<double> right_x(n);
354 std::vector<double> right_y(n);
356 for (
size_t i = 0; i < n; ++i) {
357 center_x[i] = center[i].position.x;
358 center_y[i] = center[i].position.y;
359 left_x[i] = left[i].position.x;
360 left_y[i] = left[i].position.y;
361 right_x[i] = right[i].position.x;
362 right_y[i] = right[i].position.y;
366 gsl_interp_accel *acc = ::gsl_interp_accel_alloc();
369 const gsl_interp_type *interp_type = ::gsl_interp_linear;
371 interp_type = ::gsl_interp_cspline;
376 gsl_spline *spline_center_x = ::gsl_spline_alloc(interp_type, n);
377 gsl_spline *spline_center_y = ::gsl_spline_alloc(interp_type, n);
378 gsl_spline *spline_left_x = ::gsl_spline_alloc(interp_type, n);
379 gsl_spline *spline_left_y = ::gsl_spline_alloc(interp_type, n);
380 gsl_spline *spline_right_x = ::gsl_spline_alloc(interp_type, n);
381 gsl_spline *spline_right_y = ::gsl_spline_alloc(interp_type, n);
385 (void)::gsl_spline_init(spline_center_x, t_values.data(), center_x.data(), n);
386 (void)::gsl_spline_init(spline_center_y, t_values.data(), center_y.data(), n);
387 (void)::gsl_spline_init(spline_left_x, t_values.data(), left_x.data(), n);
388 (void)::gsl_spline_init(spline_left_y, t_values.data(), left_y.data(), n);
389 (void)::gsl_spline_init(spline_right_x, t_values.data(), right_x.data(), n);
390 (void)::gsl_spline_init(spline_right_y, t_values.data(), right_y.data(), n);
393 const double t_min = t_values[0];
394 const double t_max = t_values[n - 1];
395 const size_t total_points = n * precision;
397 result.center.reserve(total_points);
398 result.left.reserve(total_points);
399 result.right.reserve(total_points);
401 for (
size_t i = 0; i < n-1; ++i) {
402 for (
int j = 0; j < precision; ++j) {
404 double t_start = t_values[i];
405 double t_end = t_max;
407 t_end = t_values[i + 1];
409 double t = t_start + (t_end - t_start) * (
static_cast<double>(j) / precision);
424 point_center.position.x = ::gsl_spline_eval(spline_center_x, t, acc);
425 point_center.position.y = ::gsl_spline_eval(spline_center_y, t, acc);
427 point_left.position.x = ::gsl_spline_eval(spline_left_x, t, acc);
428 point_left.position.y = ::gsl_spline_eval(spline_left_y, t, acc);
430 point_right.position.x = ::gsl_spline_eval(spline_right_x, t, acc);
431 point_right.position.y = ::gsl_spline_eval(spline_right_y, t, acc);
433 result.center.push_back(point_center);
434 result.left.push_back(point_left);
435 result.right.push_back(point_right);
440 ::gsl_spline_free(spline_center_x);
441 ::gsl_spline_free(spline_center_y);
442 ::gsl_spline_free(spline_left_x);
443 ::gsl_spline_free(spline_left_y);
444 ::gsl_spline_free(spline_right_x);
445 ::gsl_spline_free(spline_right_y);
446 ::gsl_interp_accel_free(acc);
448 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
449 "END fit_triple_spline with %zu center, %zu left, %zu right points",
450 result.center.size(), result.left.size(), result.right.size());