5#include "core/math/geometry/rotation2d.h"
6#include "core/math/geometry/translation2d.h"
7#include "core/math/units.h"
39 virtual Translation2d
position(
double u)
const = 0;
46 virtual Translation2d
velocity(
double u)
const = 0;
61 const Translation2d vel =
velocity(clamp_u(u));
71 const Translation2d vel =
velocity(clamp_u(u));
73 const units::Length speed = vel.
norm();
74 if (speed < 1e-4_in) {
78 const units::Area cross_product = (vel.
x() * acc.
y()) - (vel.
y() * acc.
x());
79 return (cross_product * 1_rad) / units::cube(speed);
86 double length()
const {
return arc_lengths_.empty() ? 0.0 : arc_lengths_.back(); }
94 if (arc_lengths_.empty() || us_.empty()) {
104 auto upper = std::lower_bound(arc_lengths_.begin(), arc_lengths_.end(), s);
105 const size_t idx =
static_cast<size_t>(upper - arc_lengths_.begin());
110 const double s0 = arc_lengths_[idx - 1];
111 const double s1 = arc_lengths_[idx];
112 const double u0 = us_[idx - 1];
113 const double u1 = us_[idx];
114 const double alpha = (s - s0) / std::max(s1 - s0, 1e-9);
115 return u0 + ((u1 - u0) * alpha);
125 const double clamped_u = clamp_u(u);
128 .s = s_from_u(clamped_u),
144 out.
s = clamp_value(s, 0.0,
length());
154 std::vector<Translation2d> points;
163 points.reserve(
static_cast<size_t>(count));
164 for (
int i = 0; i < count; ++i) {
165 const double u =
static_cast<double>(i) /
static_cast<double>(count - 1);
177 std::vector<Translation2d> points;
178 if (ds <= 0.0 ||
length() <= 0.0) {
182 for (
double s = 0.0; s <
length(); s += ds) {
196 static double eval_poly(
const std::array<double, N>& coeffs,
double u) {
198 for (
size_t i = N; i-- > 0;) {
199 out = (out * u) + coeffs[i];
210 for (
size_t i = N - 1; i-- > 0;) {
211 out = (out * u) + (coeffs[i + 1] *
static_cast<double>(i + 1));
222 for (
size_t i = N - 2; i-- > 0;) {
223 out = (out * u) + (coeffs[i + 2] *
static_cast<double>((i + 1) * (i + 2)));
233 constexpr double x[5] = {
234 0.0, -0.5384693101056831, 0.5384693101056831, -0.9061798459386640, 0.9061798459386640
236 constexpr double w[5] = {
237 0.5688888888888889, 0.4786286704993665, 0.4786286704993665, 0.2369268850561891,
241 const double half_len = (u1 - u0) * 0.5;
242 const double mid = (u0 + u1) * 0.5;
244 for (
int i = 0; i < 5; ++i) {
245 const double u = mid + (half_len * x[i]);
248 return half_len * sum;
255 double u0,
double u1,
double s0,
double segment_length,
double max_err
257 double mid_u = (u0 + u1) * 0.5;
261 double actual_mid_s = s0 + len1;
262 double linear_mid_s = s0 + segment_length * 0.5;
264 double integral_err = units::abs((len1 + len2) - segment_length);
265 double interp_err = units::abs(actual_mid_s - linear_mid_s);
267 if ((integral_err > max_err || interp_err > max_err) && (u1 - u0) > 1e-5) {
272 arc_lengths_.push_back(s0 + len1 + len2);
283 arc_lengths_.clear();
286 arc_lengths_.push_back(0.0);
288 const int initial_segments = 10;
290 for (
int i = 0; i < initial_segments; ++i) {
291 double u0 =
static_cast<double>(i) / initial_segments;
292 double u1 =
static_cast<double>(i + 1) / initial_segments;
295 s0 = arc_lengths_.back();
299 static double clamp_u(
double u) {
return clamp_value(u, 0.0, 1.0); }
301 static double clamp_value(
double value,
double lo,
double hi) {
312 double s_from_u(
double u)
const {
313 if (us_.empty() || arc_lengths_.empty()) {
323 auto upper = std::lower_bound(us_.begin(), us_.end(), u);
324 const size_t idx =
static_cast<size_t>(upper - us_.begin());
326 return arc_lengths_.front();
329 const double u0 = us_[idx - 1];
330 const double u1 = us_[idx];
331 const double s0 = arc_lengths_[idx - 1];
332 const double s1 = arc_lengths_[idx];
333 const double alpha = (u - u0) / std::max(u1 - u0, 1e-9);
334 return s0 + ((s1 - s0) * alpha);
337 std::vector<double> us_;
338 std::vector<double> arc_lengths_;
345template <
size_t Order>
349 const double clamped_u = clamp_u(u);
350 return Translation2d(
eval_poly(x_, clamped_u) * 1_in,
eval_poly(y_, clamped_u) * 1_in);
354 const double clamped_u = clamp_u(u);
355 return Translation2d(
361 const double clamped_u = clamp_u(u);
362 return Translation2d(
369 std::array<double, Order + 1> x_{};
370 std::array<double, Order + 1> y_{};
CRTP base class for Hermite splines of specific polynomial order.
Definition spline_base.h:346
Translation2d position(double u) const override
Computes 2D position at spline parameter u.
Definition spline_base.h:348
Translation2d acceleration(double u) const override
Computes 2D parametric acceleration (second derivative) at parameter u.
Definition spline_base.h:360
Translation2d velocity(double u) const override
Computes 2D parametric velocity (first derivative) at parameter u.
Definition spline_base.h:353
constexpr Rotation2d theta() const
Gets the angle of the vector from the x axis.
Definition translation2d.h:82
constexpr Q x() const
Gets the x component.
Definition translation2d.h:64
constexpr Q norm() const
Gets the norm of the vector.
Definition translation2d.h:93
constexpr Q y() const
Gets the y component.
Definition translation2d.h:73
Definition rotation2d.h:16
constexpr Rotation2d()=default
Default Constructor for Rotation2d.
Abstract base class for parametric 2D Hermite splines.
Definition spline_base.h:30
SplineSample sample_by_s(double s) const
Samples complete state at arc distance s.
Definition spline_base.h:142
virtual Translation2d position(double u) const =0
Computes 2D position at spline parameter u.
virtual Translation2d acceleration(double u) const =0
Computes 2D parametric acceleration (second derivative) at parameter u.
static double eval_poly_derivative(const std::array< double, N > &coeffs, double u)
Evaluates first derivative P'(u) using Horner's method.
Definition spline_base.h:208
static double eval_poly(const std::array< double, N > &coeffs, double u)
Evaluates polynomial P(u) using Horner's method.
Definition spline_base.h:196
void build_arc_table_recursive(double u0, double u1, double s0, double segment_length, double max_err)
Recursively builds the arc table to satisfy a linear interpolation error bound.
Definition spline_base.h:254
Rotation2d heading(double u) const
Computes heading angle theta at spline parameter u.
Definition spline_base.h:60
SplineSample sample(double u) const
Samples complete state (position, velocity, acceleration, heading, curvature) at parameter u.
Definition spline_base.h:124
double u_from_s(double s) const
Inverts arc distance s to spline parameter u.
Definition spline_base.h:93
double length() const
Returns total arc length of the spline in inches.
Definition spline_base.h:86
static double eval_poly_second_derivative(const std::array< double, N > &coeffs, double u)
Evaluates second derivative P''(u) using Horner's method.
Definition spline_base.h:220
double integrate_segment_length(double u0, double u1) const
Computes high-accuracy arc length over sub-interval [u0, u1] using 5-point Gauss-Legendre quadrature.
Definition spline_base.h:232
void build_arc_table(double max_err=1e-4)
Builds pre-computed parameter u and arc-length lookup tables using adaptive refinement.
Definition spline_base.h:281
virtual Translation2d velocity(double u) const =0
Computes 2D parametric velocity (first derivative) at parameter u.
std::vector< Translation2d > sample_by_count(int count) const
Samples 2D positions uniformly spaced in parameter u.
Definition spline_base.h:153
units::Curvature curvature(double u) const
Computes path curvature at parameter u.
Definition spline_base.h:70
std::vector< Translation2d > sample_by_spacing(double ds) const
Samples 2D positions uniformly spaced by arc distance ds.
Definition spline_base.h:176
Evaluated state sample at a specific parameter u or distance s along a spline.
Definition spline_base.h:14
units::Curvature curvature
Path curvature (rad/meter).
Definition spline_base.h:21
Translation2d acceleration
1D/2D parametric acceleration vector (d^2x/du^2, d^2y/du^2)
Definition spline_base.h:19
Translation2d position
2D position (x, y)
Definition spline_base.h:17
double s
Arc length along spline from start in inches.
Definition spline_base.h:16
double u
Spline parameter in range [0, 1].
Definition spline_base.h:15
Translation2d velocity
1D/2D parametric velocity vector (dx/du, dy/du)
Definition spline_base.h:18
Rotation2d heading
Heading angle theta along path.
Definition spline_base.h:20