COPP C++ API 0.2.3
C++ interface for COPP trajectory optimization
Loading...
Searching...
No Matches
path.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4#include <functional>
5#include <initializer_list>
6#include <memory>
7#include <optional>
8#include <utility>
9#include <vector>
10
11#include "copp/core.hpp"
12
13namespace copp
14{
15
16 class Path;
17
18 namespace detail
19 {
25 COPP_API const void *path_handle(const Path &path) noexcept;
26 } // namespace detail
27
43 struct Jet3
44 {
45 double v = 0.0;
46 double d1 = 0.0;
47 double d2 = 0.0;
48 double d3 = 0.0;
49
50 static constexpr Jet3 constant(double value) noexcept
51 {
52 return Jet3{value, 0.0, 0.0, 0.0};
53 }
54
55 static constexpr Jet3 seed(double value) noexcept
56 {
57 return Jet3{value, 1.0, 0.0, 0.0};
58 }
59 };
60
61 inline constexpr Jet3 operator+(Jet3 lhs, Jet3 rhs) noexcept
62 {
63 return Jet3{
64 lhs.v + rhs.v,
65 lhs.d1 + rhs.d1,
66 lhs.d2 + rhs.d2,
67 lhs.d3 + rhs.d3,
68 };
69 }
70
71 inline constexpr Jet3 operator+(Jet3 lhs, double rhs) noexcept
72 {
73 return Jet3{lhs.v + rhs, lhs.d1, lhs.d2, lhs.d3};
74 }
75
76 inline constexpr Jet3 operator+(double lhs, Jet3 rhs) noexcept
77 {
78 return rhs + lhs;
79 }
80
81 inline constexpr Jet3 operator-(Jet3 lhs, Jet3 rhs) noexcept
82 {
83 return Jet3{
84 lhs.v - rhs.v,
85 lhs.d1 - rhs.d1,
86 lhs.d2 - rhs.d2,
87 lhs.d3 - rhs.d3,
88 };
89 }
90
91 inline constexpr Jet3 operator-(Jet3 lhs, double rhs) noexcept
92 {
93 return Jet3{lhs.v - rhs, lhs.d1, lhs.d2, lhs.d3};
94 }
95
96 inline constexpr Jet3 operator-(double lhs, Jet3 rhs) noexcept
97 {
98 return Jet3{lhs - rhs.v, -rhs.d1, -rhs.d2, -rhs.d3};
99 }
100
101 inline constexpr Jet3 operator-(Jet3 value) noexcept
102 {
103 return Jet3{-value.v, -value.d1, -value.d2, -value.d3};
104 }
105
106 inline constexpr Jet3 operator*(Jet3 lhs, Jet3 rhs) noexcept
107 {
108 return Jet3{
109 lhs.v * rhs.v,
110 lhs.d1 * rhs.v + lhs.v * rhs.d1,
111 lhs.d2 * rhs.v + 2.0 * lhs.d1 * rhs.d1 + lhs.v * rhs.d2,
112 lhs.d3 * rhs.v + 3.0 * (lhs.d2 * rhs.d1 + lhs.d1 * rhs.d2) + lhs.v * rhs.d3,
113 };
114 }
115
116 inline constexpr Jet3 operator*(Jet3 lhs, double rhs) noexcept
117 {
118 return Jet3{
119 lhs.v * rhs,
120 lhs.d1 * rhs,
121 lhs.d2 * rhs,
122 lhs.d3 * rhs,
123 };
124 }
125
126 inline constexpr Jet3 operator*(double lhs, Jet3 rhs) noexcept
127 {
128 return rhs * lhs;
129 }
130
131 inline Jet3 operator/(double lhs, Jet3 rhs) noexcept
132 {
133 const double inv = 1.0 / rhs.v;
134 const double inv2 = inv * inv;
135 const double inv3 = inv2 * inv;
136 const double inv4 = inv3 * inv;
137 const double d1sq = rhs.d1 * rhs.d1;
138 return Jet3{
139 lhs * inv,
140 -lhs * inv2 * rhs.d1,
141 lhs * (2.0 * inv3 * d1sq - inv2 * rhs.d2),
142 lhs * (-6.0 * inv4 * d1sq * rhs.d1 + 6.0 * inv3 * rhs.d1 * rhs.d2 - inv2 * rhs.d3),
143 };
144 }
145
146 inline constexpr Jet3 operator/(Jet3 lhs, double rhs) noexcept
147 {
148 return lhs * (1.0 / rhs);
149 }
150
151 inline Jet3 operator/(Jet3 lhs, Jet3 rhs) noexcept
152 {
153 return lhs * (1.0 / rhs);
154 }
155
156 inline Jet3 sin(Jet3 x) noexcept
157 {
158 const double sv = std::sin(x.v);
159 const double cv = std::cos(x.v);
160 const double d1sq = x.d1 * x.d1;
161 return Jet3{
162 sv,
163 cv * x.d1,
164 -sv * d1sq + cv * x.d2,
165 -cv * d1sq * x.d1 - 3.0 * sv * x.d1 * x.d2 + cv * x.d3,
166 };
167 }
168
169 inline Jet3 cos(Jet3 x) noexcept
170 {
171 const double sv = std::sin(x.v);
172 const double cv = std::cos(x.v);
173 const double d1sq = x.d1 * x.d1;
174 return Jet3{
175 cv,
176 -sv * x.d1,
177 -cv * d1sq - sv * x.d2,
178 sv * d1sq * x.d1 - 3.0 * cv * x.d1 * x.d2 - sv * x.d3,
179 };
180 }
181
182 inline Jet3 exp(Jet3 x) noexcept
183 {
184 const double ev = std::exp(x.v);
185 const double d1sq = x.d1 * x.d1;
186 return Jet3{
187 ev,
188 ev * x.d1,
189 ev * (d1sq + x.d2),
190 ev * (d1sq * x.d1 + 3.0 * x.d1 * x.d2 + x.d3),
191 };
192 }
193
194 inline Jet3 log(Jet3 x) noexcept
195 {
196 const double inv = 1.0 / x.v;
197 const double inv2 = inv * inv;
198 const double inv3 = inv2 * inv;
199 const double d1sq = x.d1 * x.d1;
200 return Jet3{
201 std::log(x.v),
202 inv * x.d1,
203 -inv2 * d1sq + inv * x.d2,
204 2.0 * inv3 * d1sq * x.d1 - 3.0 * inv2 * x.d1 * x.d2 + inv * x.d3,
205 };
206 }
207
208 inline Jet3 ln(Jet3 x) noexcept
209 {
210 return log(x);
211 }
212
213 inline Jet3 sqrt(Jet3 x) noexcept
214 {
215 const double sqrtv = std::sqrt(x.v);
216 const double inv_sqrt = 1.0 / sqrtv;
217 const double inv_v_sqrt = inv_sqrt / x.v;
218 const double inv_v2_sqrt = inv_v_sqrt / x.v;
219 const double d1sq = x.d1 * x.d1;
220 return Jet3{
221 sqrtv,
222 0.5 * inv_sqrt * x.d1,
223 -0.25 * inv_v_sqrt * d1sq + 0.5 * inv_sqrt * x.d2,
224 0.375 * inv_v2_sqrt * d1sq * x.d1 - 0.75 * inv_v_sqrt * x.d1 * x.d2 +
225 0.5 * inv_sqrt * x.d3,
226 };
227 }
228
229 inline Jet3 powi(Jet3 x, int n) noexcept
230 {
231 if (n == 0)
232 {
233 return Jet3::constant(1.0);
234 }
235
236 const double nf = static_cast<double>(n);
237 const double coeff2 = nf * (nf - 1.0);
238 const double coeff3 = coeff2 * (nf - 2.0);
239 const double dv = nf * std::pow(x.v, nf - 1.0);
240 const double ddv = coeff2 == 0.0 ? 0.0 : coeff2 * std::pow(x.v, nf - 2.0);
241 const double dddv = coeff3 == 0.0 ? 0.0 : coeff3 * std::pow(x.v, nf - 3.0);
242 const double d1sq = x.d1 * x.d1;
243 return Jet3{
244 std::pow(x.v, nf),
245 dv * x.d1,
246 ddv * d1sq + dv * x.d2,
247 dddv * d1sq * x.d1 + 3.0 * ddv * x.d1 * x.d2 + dv * x.d3,
248 };
249 }
250
257 using PathParametric = std::function<std::vector<Jet3>(Jet3 s)>;
258
264 using PathParametricWriter = std::function<void(Jet3 s, Span<Jet3> q)>;
265
272 using PathEvaluator2nd = std::function<void(
274 MatrixRef q,
275 MatrixRef dq,
276 MatrixRef ddq)>;
277
284 using PathEvaluator3rd = std::function<void(
286 MatrixRef q,
287 MatrixRef dq,
288 MatrixRef ddq,
289 MatrixRef dddq)>;
290
296 enum class OutOfRangeMode
297 {
302 };
303
315 {
316 std::size_t order = 5;
317 double s_min = 0.0;
318 double s_max = 1.0;
325 std::optional<Matrix> start_state;
328 std::optional<Matrix> end_state;
329 };
330
349 {
352 double tolerance = 1.0e-3;
357 std::vector<double> tolerance_per_axis;
362 std::optional<std::vector<std::size_t>> axes;
366 std::optional<std::vector<double>> parameters;
368 std::size_t max_refinements = 20;
370 std::size_t max_segments = 20000;
373 };
374
384 {
386 std::vector<std::size_t> axes;
388 std::size_t segments = 0;
391 std::size_t interpolated_segments = 0;
393 std::size_t refinements = 0;
395 std::size_t fitting_rows = 0;
397 std::size_t checked_intervals = 0;
401 std::vector<double> max_errors;
402 };
403
413 {
415 std::optional<Matrix> dq;
416 std::optional<Matrix> ddq;
417 std::optional<Matrix> dddq;
418 };
419
426 {
427 public:
457 static Path from_waypoints(MatrixView waypoints, SplineConfig config = {});
458 static Expected<Path> from_waypoints(MatrixView waypoints, SplineConfig config, NoThrowTag);
459 static Expected<Path> from_waypoints(MatrixView waypoints, NoThrowTag);
460
479 std::initializer_list<std::initializer_list<double>> waypoints,
480 SplineConfig config = {});
481 static Expected<Path> from_waypoints(
482 std::initializer_list<std::initializer_list<double>> waypoints,
483 SplineConfig config,
484 NoThrowTag);
485 static Expected<Path> from_waypoints(
486 std::initializer_list<std::initializer_list<double>> waypoints,
487 NoThrowTag);
488
523 static Expected<Path> from_waypoints_interpolating(
524 MatrixView waypoints,
525 SplineConfig config,
526 NoThrowTag);
527 static Expected<Path> from_waypoints_interpolating(MatrixView waypoints, NoThrowTag);
528
543 std::initializer_list<std::initializer_list<double>> waypoints,
544 SplineConfig config = {});
545 static Expected<Path> from_waypoints_interpolating(
546 std::initializer_list<std::initializer_list<double>> waypoints,
547 SplineConfig config,
548 NoThrowTag);
549 static Expected<Path> from_waypoints_interpolating(
550 std::initializer_list<std::initializer_list<double>> waypoints,
551 NoThrowTag);
552
585 static Expected<Path> from_waypoints_fitting(
586 MatrixView waypoints,
587 SmoothingConfig config,
588 NoThrowTag);
589 static Expected<Path> from_waypoints_fitting(MatrixView waypoints, NoThrowTag);
590
597 std::initializer_list<std::initializer_list<double>> waypoints,
598 SmoothingConfig config = {});
599 static Expected<Path> from_waypoints_fitting(
600 std::initializer_list<std::initializer_list<double>> waypoints,
601 SmoothingConfig config,
602 NoThrowTag);
603 static Expected<Path> from_waypoints_fitting(
604 std::initializer_list<std::initializer_list<double>> waypoints,
605 NoThrowTag);
606
622 PathParametric parametric,
623 double s_min,
624 double s_max);
626 PathParametric parametric,
627 double s_min,
628 double s_max,
629 NoThrowTag);
630
641 std::size_t dim,
642 double s_min,
643 double s_max,
644 PathParametricWriter parametric);
646 std::size_t dim,
647 double s_min,
648 double s_max,
649 PathParametricWriter parametric,
650 NoThrowTag);
651
665 std::size_t dim,
666 double s_min,
667 double s_max,
668 PathEvaluator2nd evaluator);
670 std::size_t dim,
671 double s_min,
672 double s_max,
673 PathEvaluator2nd evaluator,
674 NoThrowTag);
675
685 std::size_t dim,
686 double s_min,
687 double s_max,
688 PathEvaluator3rd evaluator);
690 std::size_t dim,
691 double s_min,
692 double s_max,
693 PathEvaluator3rd evaluator,
694 NoThrowTag);
695
696 Path(Path &&) noexcept;
697 Path &operator=(Path &&) noexcept;
699
700 Path(const Path &) = delete;
701 Path &operator=(const Path &) = delete;
702
706 std::size_t dim() const;
707
711 std::pair<double, double> s_range() const;
712
721 PathDerivatives evaluate_q(Span<const double> s) const;
722 Expected<PathDerivatives> evaluate_q(Span<const double> s, NoThrowTag) const;
723
732
741
746 std::optional<SmoothingReport> smoothing_report() const;
747
748 private:
749 struct Impl;
750
751 explicit Path(std::unique_ptr<Impl> impl);
752
753 std::unique_ptr<Impl> impl_;
754
755 friend const void *detail::path_handle(const Path &path) noexcept;
756 };
757
759 MatrixView waypoints,
760 SplineConfig config,
762 {
763 return detail::expected_from([&] { return from_waypoints(waypoints, config); });
764 }
765
767 {
768 return from_waypoints(waypoints, SplineConfig{}, tag);
769 }
770
772 std::initializer_list<std::initializer_list<double>> waypoints,
773 SplineConfig config,
775 {
776 return detail::expected_from([&] { return from_waypoints(waypoints, config); });
777 }
778
780 std::initializer_list<std::initializer_list<double>> waypoints,
781 NoThrowTag tag)
782 {
783 return from_waypoints(waypoints, SplineConfig{}, tag);
784 }
785
787 MatrixView waypoints,
788 SplineConfig config,
790 {
791 return detail::expected_from([&] { return from_waypoints_interpolating(waypoints, config); });
792 }
793
798
800 std::initializer_list<std::initializer_list<double>> waypoints,
801 SplineConfig config,
803 {
804 return detail::expected_from([&] { return from_waypoints_interpolating(waypoints, config); });
805 }
806
808 std::initializer_list<std::initializer_list<double>> waypoints,
809 NoThrowTag tag)
810 {
811 return from_waypoints_interpolating(waypoints, SplineConfig{}, tag);
812 }
813
815 MatrixView waypoints,
816 SmoothingConfig config,
818 {
819 return detail::expected_from([&] { return from_waypoints_fitting(waypoints, config); });
820 }
821
823 {
824 return from_waypoints_fitting(waypoints, SmoothingConfig{}, tag);
825 }
826
828 std::initializer_list<std::initializer_list<double>> waypoints,
829 SmoothingConfig config,
831 {
832 return detail::expected_from([&] { return from_waypoints_fitting(waypoints, config); });
833 }
834
836 std::initializer_list<std::initializer_list<double>> waypoints,
837 NoThrowTag tag)
838 {
839 return from_waypoints_fitting(waypoints, SmoothingConfig{}, tag);
840 }
841
843 PathParametric parametric,
844 double s_min,
845 double s_max,
847 {
849 [&] { return from_parametric(std::move(parametric), s_min, s_max); });
850 }
851
853 std::size_t dim,
854 double s_min,
855 double s_max,
856 PathParametricWriter parametric,
858 {
860 [&] { return from_parametric(dim, s_min, s_max, std::move(parametric)); });
861 }
862
864 std::size_t dim,
865 double s_min,
866 double s_max,
867 PathEvaluator2nd evaluator,
869 {
871 [&] { return from_evaluator_2nd(dim, s_min, s_max, std::move(evaluator)); });
872 }
873
875 std::size_t dim,
876 double s_min,
877 double s_max,
878 PathEvaluator3rd evaluator,
880 {
882 [&] { return from_evaluator_3rd(dim, s_min, s_max, std::move(evaluator)); });
883 }
884
889
894
899
900} // namespace copp
Exception type thrown by the default C++ API.
Definition core.hpp:100
Small C++17 expected-like result used by no-throw overloads.
Definition core.hpp:527
Lightweight owned column-major matrix.
Definition core.hpp:352
Mutable column-major matrix view used by callback APIs.
Definition core.hpp:288
Non-owning view of a two-dimensional double matrix.
Definition core.hpp:205
Geometric path wrapper backed by Rust Path.
Definition path.hpp:426
static Path from_parametric(PathParametric parametric, double s_min, double s_max)
Build a path from a scalar-parametric formula.
std::size_t dim() const
Return the path dimension.
static Path from_waypoints_interpolating(std::initializer_list< std::initializer_list< double > > waypoints, SplineConfig config={})
Build an interpolating spline path from waypoint-list notation.
static Path from_evaluator_3rd(std::size_t dim, double s_min, double s_max, PathEvaluator3rd evaluator)
Build a path from a batch evaluator with explicit derivatives up to third order.
PathDerivatives evaluate_q(Span< const double > s) const
Evaluate position samples only.
static Path from_parametric(std::size_t dim, double s_min, double s_max, PathParametricWriter parametric)
Build a path from a scalar-parametric formula that writes into a buffer.
static Path from_waypoints_interpolating(MatrixView waypoints, SplineConfig config={})
Build a spline path that interpolates every waypoint.
static Path from_waypoints(std::initializer_list< std::initializer_list< double > > waypoints, SplineConfig config={})
Build a spline path from waypoint-list notation.
static Path from_waypoints(MatrixView waypoints, SplineConfig config={})
Build a spline path from waypoint positions.
PathDerivatives evaluate_up_to_3rd(Span< const double > s) const
Evaluate position, first derivative, second derivative, and third derivative.
Path(Path &&) noexcept
friend const void * detail::path_handle(const Path &path) noexcept
std::optional< SmoothingReport > smoothing_report() const
Return fitting diagnostics of a path built by from_waypoints_fitting.
static Path from_waypoints_fitting(std::initializer_list< std::initializer_list< double > > waypoints, SmoothingConfig config={})
Build a tolerance-bounded fitted path from waypoint-list notation.
static Path from_evaluator_2nd(std::size_t dim, double s_min, double s_max, PathEvaluator2nd evaluator)
Build a path from a batch evaluator with explicit derivatives up to second order.
static Path from_waypoints_fitting(MatrixView waypoints, SmoothingConfig config={})
Build a tolerance-bounded fitted path from waypoint positions.
std::pair< double, double > s_range() const
Return the valid path-parameter interval (s_min, s_max).
PathDerivatives evaluate_up_to_2nd(Span< const double > s) const
Evaluate position, first derivative, and second derivative.
Non-owning view of a contiguous one-dimensional array.
Definition core.hpp:139
#define COPP_API
Definition core.hpp:23
Internal helpers for error conversion, no-throw overloads, and small implementation utilities used by...
auto expected_from(Fn &&fn) -> Expected< typename std::decay< decltype(fn())>::type >
Definition core.hpp:580
COPP_API const void * path_handle(const Path &path) noexcept
Return the private bridge handle stored by Path.
Root namespace for the C++ facade: paths, robots, constraints, matrices, profiles,...
Jet3 sin(Jet3 x) noexcept
Definition path.hpp:156
Jet3 powi(Jet3 x, int n) noexcept
Definition path.hpp:229
std::function< void( Span< const double > s, MatrixRef q, MatrixRef dq, MatrixRef ddq, MatrixRef dddq)> PathEvaluator3rd
Batch third-order evaluator callback.
Definition path.hpp:284
constexpr Jet3 operator-(Jet3 lhs, Jet3 rhs) noexcept
Definition path.hpp:81
Jet3 sqrt(Jet3 x) noexcept
Definition path.hpp:213
std::function< std::vector< Jet3 >(Jet3 s)> PathParametric
Scalar-parametric path callback that returns one Jet3 per dimension.
Definition path.hpp:257
Jet3 log(Jet3 x) noexcept
Definition path.hpp:194
std::function< void( Span< const double > s, MatrixRef q, MatrixRef dq, MatrixRef ddq)> PathEvaluator2nd
Batch second-order evaluator callback.
Definition path.hpp:272
constexpr Jet3 operator+(Jet3 lhs, Jet3 rhs) noexcept
Definition path.hpp:61
OutOfRangeMode
Policy for evaluating a path outside its configured s range.
Definition path.hpp:297
@ Clamp
Clamp out-of-range query samples to the nearest endpoint.
Definition path.hpp:301
@ Error
Throw copp::Error when any query sample is outside [s_min, s_max].
Definition path.hpp:299
Jet3 exp(Jet3 x) noexcept
Definition path.hpp:182
Jet3 cos(Jet3 x) noexcept
Definition path.hpp:169
Jet3 operator/(double lhs, Jet3 rhs) noexcept
Definition path.hpp:131
std::function< void(Jet3 s, Span< Jet3 > q)> PathParametricWriter
Allocation-free scalar-parametric path callback that writes one Jet3 per dimension.
Definition path.hpp:264
Jet3 ln(Jet3 x) noexcept
Definition path.hpp:208
constexpr Jet3 operator*(Jet3 lhs, Jet3 rhs) noexcept
Definition path.hpp:106
Third-order forward-mode automatic-differentiation scalar.
Definition path.hpp:44
static constexpr Jet3 seed(double value) noexcept
Definition path.hpp:55
double d3
Definition path.hpp:48
static constexpr Jet3 constant(double value) noexcept
Definition path.hpp:50
double v
Definition path.hpp:45
double d2
Definition path.hpp:47
double d1
Definition path.hpp:46
Tag object selecting no-throw overloads.
Definition core.hpp:608
Result of path evaluation.
Definition path.hpp:413
std::optional< Matrix > dq
Definition path.hpp:415
std::optional< Matrix > ddq
Definition path.hpp:416
std::optional< Matrix > dddq
Definition path.hpp:417
Configuration for tolerance-bounded waypoint fitting.
Definition path.hpp:349
std::vector< double > tolerance_per_axis
Optional per-axis absolute tolerances.
Definition path.hpp:357
std::optional< std::vector< std::size_t > > axes
0-based input rows allowed to deviate from their reference polyline.
Definition path.hpp:362
std::size_t max_segments
Maximum number of polynomial spans used by the selected axes.
Definition path.hpp:370
std::optional< std::vector< double > > parameters
Optional common parameter per waypoint column: finite, strictly increasing, one entry per column.
Definition path.hpp:366
OutOfRangeMode out_of_range
Policy for later queries outside the path range.
Definition path.hpp:372
double tolerance
Absolute tolerance applied to every selected axis when tolerance_per_axis is empty.
Definition path.hpp:352
std::size_t max_refinements
Maximum number of adaptive knot-refinement passes.
Definition path.hpp:368
Diagnostics recorded while constructing a fitted waypoint path.
Definition path.hpp:384
std::vector< std::size_t > axes
Selected input-row indices, in tolerance/report order.
Definition path.hpp:386
std::size_t interpolated_segments
Number of spans in the separate unselected-axis interpolant; zero when every axis is selected.
Definition path.hpp:391
std::vector< double > max_errors
Final whole-domain absolute-error bound for each selected axis, in input units and axes order.
Definition path.hpp:401
std::size_t checked_intervals
Number of reference-polyline intervals visited by numerical audits.
Definition path.hpp:397
std::size_t fitting_rows
Number of discrete or quadrature fitting rows assembled.
Definition path.hpp:395
std::size_t refinements
Number of completed local knot-refinement passes.
Definition path.hpp:393
std::size_t segments
Number of final polynomial spans shared by the selected axes.
Definition path.hpp:388
Configuration for waypoint spline construction.
Definition path.hpp:315
std::size_t order
Definition path.hpp:316
std::optional< Matrix > end_state
Optional boundary derivatives at s_max; same shape convention as start_state.
Definition path.hpp:328
OutOfRangeMode out_of_range
Definition path.hpp:319
std::optional< Matrix > start_state
Optional boundary derivatives at s_min.
Definition path.hpp:325