COPP C++ API
C++ interface for COPP trajectory optimization
Loading...
Searching...
No Matches
Interpolation And Time Profiles

Interpolation helpers convert path-domain profiles into time-domain schedules. Solvers usually return profiles over station samples s[k]; controllers often need cumulative time t(s) or samples of the inverse map s(t).

Include

or:

TOPP2 Profile

TOPP2/COPP2 solvers return a node profile:

\[a_k = a(s_k) = \dot{s}(s_k)^2. \]

The segment profile is:

\[b_k = \frac{a_{k+1} - a_k}{2(s_{k+1} - s_k)}. \]

std::vector<double> s{0.0, 0.5, 1.0};
std::vector<double> a{1.0, 1.0, 1.0};
s,
a,
time.t_s,
0.1);
std::vector<double> t_query{0.0, 0.25, 0.5, 1.0};
s,
a,
time.t_s,
t_query);
COPP_API std::vector< double > t_to_s_topp2_uniform(Span< const double > s, Span< const double > a, Span< const double > t_s, double dt, TimeGridOptions options={})
Sample the inverse TOPP2 mapping s(t) on a uniform time grid.
COPP_API std::vector< double > a_to_b_topp2(Span< const double > s, Span< const double > a)
Compute segment profile b from node profile a.
COPP_API TimeProfile s_to_t_topp2(Span< const double > s, Span< const double > a, double t0=0.0)
Convert a second-order path profile a(s) = ds/dt squared to t(s).
COPP_API std::vector< double > t_to_s_topp2_samples(Span< const double > s, Span< const double > a, Span< const double > t_s, Span< const double > t_sample)
Sample the inverse TOPP2 mapping s(t) at explicit query times.

Input requirements:

  • s.size() >= 2
  • a.size() == s.size()
  • s is strictly increasing
  • all values are finite
  • every segment has a positive finite speed denominator

TOPP3 Profile

TOPP3/COPP3 use node-based a and b arrays:

\[a_k = \dot{s}(s_k)^2, \qquad b_k = \ddot{s}(s_k). \]

copp::Profile3rd owns those arrays:

std::vector<double> s{0.0, 0.5, 1.0};
{1.0, 1.0, 1.0},
{0.0, 0.0, 0.0},
};
auto time = copp::interpolation::s_to_t_topp3(s, profile);
s,
profile,
time.t_s,
0.1);
COPP_API TimeProfile s_to_t_topp3(Span< const double > s, const Profile3rd &profile, double t0=0.0)
Convert a third-order profile to cumulative time t(s).
COPP_API std::vector< double > t_to_s_topp3_uniform(Span< const double > s, const Profile3rd &profile, Span< const double > t_s, double dt, TimeGridOptions options={})
Sample the inverse TOPP3 mapping s(t) on a uniform time grid.
Owned third-order TOPP/COPP profile.

copp::Profile3rdRef is the zero-copy borrowed view. It is useful for external storage and for interpolating only part of a profile:

auto part = profile.slice(10, 40); // inclusive station indices
auto local_s = copp::Span<const double>(s.data() + 10, 31);
auto local_time = copp::interpolation::s_to_t_topp3(local_s, part);
Non-owning view of a contiguous one-dimensional array.
Definition core.hpp:139
Profile3rdRef slice(std::size_t idx_s_start, std::size_t idx_s_final) const
Borrow a closed station subrange idx_s_start..=idx_s_final.

Stationary counts are clipped to the local slice. A slice must still contain at least one non-stationary segment after that adjustment.

Uniform Versus Explicit Time Grids

Uniform sampling is convenient for controllers:

grid.t0 = 0.0;
grid.include_final = true;
s,
a,
time.t_s,
0.001,
grid);
Options for generating a uniform s(t) sampling grid.

Explicit samples are better for diagnostics, plotting, or synchronizing with an external time base:

std::vector<double> t_sample{0.0, 0.02, 0.05, time.t_final};
s,
profile,
time.t_s,
t_sample);
COPP_API std::vector< double > t_to_s_topp3_samples(Span< const double > s, const Profile3rd &profile, Span< const double > t_s, Span< const double > t_sample)
Sample the inverse TOPP3 mapping s(t) at explicit query times.

Out-of-range query times are returned as NaN, matching Rust/Python.

Tutorial Sources

  • bindings/cpp/tests/test_topp2_interpolation.cpp
  • bindings/cpp/tests/test_topp3_interpolation.cpp