7#include "wpi/units/math.hpp"
8#include "wpi/units/time.hpp"
40template <
class Distance,
class Input>
45 wpi::units::compound_unit<Distance,
46 wpi::units::inverse<wpi::units::seconds>>;
50 wpi::units::inverse<wpi::units::seconds>>;
51 using Input_t = wpi::units::unit_t<Input>;
52 using A_t = wpi::units::unit_t<wpi::units::inverse<wpi::units::seconds>>;
53 using B_t = wpi::units::unit_t<
54 wpi::units::compound_unit<Acceleration, wpi::units::inverse<Input>>>;
55 using KV = wpi::units::compound_unit<Input, wpi::units::inverse<Velocity>>;
56 using kV_t = wpi::units::unit_t<KV>;
58 wpi::units::compound_unit<Input, wpi::units::inverse<Acceleration>>;
59 using kA_t = wpi::units::unit_t<KA>;
78 constexpr bool IsFinished(
const wpi::units::second_t& t)
const {
143 : m_constraints(constraints) {}
161 const State& goal)
const {
162 auto direction = ShouldFlipInput(current, goal) ? -1 : 1;
163 auto u = direction * m_constraints.maxInput;
170 }
else if (t < timing.inflectionTime) {
171 return {ComputeDistanceFromTime(t, u, current),
172 ComputeVelocityFromTime(t, u, current)};
173 }
else if (t < timing.totalTime) {
174 return {ComputeDistanceFromTime(t - timing.totalTime, -u, goal),
175 ComputeVelocityFromTime(t - timing.totalTime, -u, goal)};
190 const State& goal)
const {
191 auto direction = ShouldFlipInput(current, goal) ? -1 : 1;
192 auto u = direction * m_constraints.maxInput;
205 const State& goal)
const {
208 return timing.totalTime;
220 const State& goal)
const {
221 auto direction = ShouldFlipInput(current, goal) ? -1 : 1;
222 auto u = direction * m_constraints.maxInput;
244 if (current == goal) {
248 auto inflectionVelocity = SolveForInflectionVelocity(u, current, goal);
249 auto inflectionPosition =
250 ComputeDistanceFromVelocity(inflectionVelocity, -u, goal);
252 return {inflectionPosition, inflectionVelocity};
267 const State& inflectionPoint,
271 auto u_dir = wpi::units::math::abs(u) / u;
273 wpi::units::second_t inflectionT_forward;
287 if (wpi::units::math::abs(u_dir * m_constraints.MaxVelocity() -
288 inflectionPoint.velocity) < epsilon) {
289 auto solvableV = inflectionPoint.velocity;
290 wpi::units::second_t t_to_solvable_v;
292 if (wpi::units::math::abs(current.velocity - inflectionPoint.velocity) <
294 t_to_solvable_v = 0_s;
295 x_at_solvable_v = current.position;
297 if (wpi::units::math::abs(current.velocity) >
298 m_constraints.MaxVelocity()) {
299 solvableV += u_dir * epsilon;
301 solvableV -= u_dir * epsilon;
305 ComputeTimeFromVelocity(solvableV, u, current.velocity);
306 x_at_solvable_v = ComputeDistanceFromVelocity(solvableV, u, current);
309 inflectionT_forward =
310 t_to_solvable_v + u_dir *
311 (inflectionPoint.position - x_at_solvable_v) /
312 m_constraints.MaxVelocity();
314 inflectionT_forward = ComputeTimeFromVelocity(inflectionPoint.velocity, u,
318 auto inflectionT_backward =
319 ComputeTimeFromVelocity(inflectionPoint.velocity, -u, goal.velocity);
321 return {inflectionT_forward, inflectionT_forward - inflectionT_backward};
334 constexpr Distance_t ComputeDistanceFromTime(
const wpi::units::second_t& time,
336 const State& initial)
const {
337 auto A = m_constraints.A;
338 auto B = m_constraints.B;
341 return initial.position +
342 (-B * u * time + (initial.velocity + B * u / A) *
343 (wpi::units::math::exp(A * time) - 1)) /
357 constexpr Velocity_t ComputeVelocityFromTime(
const wpi::units::second_t& time,
359 const State& initial)
const {
360 auto A = m_constraints.A;
361 auto B = m_constraints.B;
364 return (initial.velocity + B * u / A) * wpi::units::math::exp(A * time) -
378 constexpr wpi::units::second_t ComputeTimeFromVelocity(
381 auto A = m_constraints.A;
382 auto B = m_constraints.B;
385 return wpi::units::math::log((A * velocity + B * u) /
386 (A * initial + B * u)) /
402 const State& initial)
const {
403 auto A = m_constraints.A;
404 auto B = m_constraints.B;
407 return initial.position + (velocity - initial.velocity) / A -
409 wpi::units::math::log((A * velocity + B * u) /
410 (A * initial.velocity + B * u));
424 const State& current,
425 const State& goal)
const {
426 auto A = m_constraints.A;
427 auto B = m_constraints.B;
430 auto u_dir = u / wpi::units::math::abs(u);
432 auto position_delta = goal.position - current.position;
433 auto velocity_delta = goal.velocity - current.velocity;
435 auto scalar = (A * current.velocity + B * u) * (A * goal.velocity - B * u);
436 auto power = -A / B / u * (A * position_delta - velocity_delta);
439 auto c = B * B * u * u + scalar * wpi::units::math::exp(power);
441 if (-1e-9 < c.value() && c.value() < 0) {
447 return u_dir * wpi::units::math::sqrt(-c / a);
459 constexpr bool ShouldFlipInput(
const State& current,
460 const State& goal)
const {
461 auto u = m_constraints.maxInput;
463 auto v0 = current.velocity;
464 auto xf = goal.position;
465 auto vf = goal.velocity;
467 auto x_forward = ComputeDistanceFromVelocity(vf, u, current);
468 auto x_reverse = ComputeDistanceFromVelocity(vf, -u, current);
470 if (v0 >= m_constraints.MaxVelocity()) {
471 return xf < x_reverse;
474 if (v0 <= -m_constraints.MaxVelocity()) {
475 return xf < x_forward;
480 auto c = xf >= x_forward;
481 auto d = xf >= x_reverse;
483 return (a && !d) || (b && !c) || (!c && !d);
Profile constraints.
Definition ExponentialProfile.hpp:86
Input_t maxInput
Maximum unsigned input voltage.
Definition ExponentialProfile.hpp:116
constexpr Constraints(Input_t maxInput, kV_t kV, kA_t kA)
Constructs constraints for an ExponentialProfile from characteristics.
Definition ExponentialProfile.hpp:105
B_t B
The State-Space 1x1 input matrix.
Definition ExponentialProfile.hpp:122
A_t A
The State-Space 1x1 system matrix.
Definition ExponentialProfile.hpp:119
constexpr Velocity_t MaxVelocity() const
Computes the max achievable velocity for an Exponential Profile.
Definition ExponentialProfile.hpp:113
constexpr Constraints(Input_t maxInput, A_t A, B_t B)
Constructs constraints for an ExponentialProfile.
Definition ExponentialProfile.hpp:95
Profile timing.
Definition ExponentialProfile.hpp:64
wpi::units::second_t totalTime
Total profile time.
Definition ExponentialProfile.hpp:70
constexpr bool IsFinished(const wpi::units::second_t &t) const
Decides if the profile is finished by time t.
Definition ExponentialProfile.hpp:78
wpi::units::second_t inflectionTime
Profile inflection time.
Definition ExponentialProfile.hpp:67
Profile state.
Definition ExponentialProfile.hpp:126
Velocity_t velocity
The velocity at this state.
Definition ExponentialProfile.hpp:132
constexpr bool operator==(const State &) const =default
Distance_t position
The position at this state.
Definition ExponentialProfile.hpp:129
constexpr ExponentialProfile(const ExponentialProfile &)=default
wpi::units::compound_unit< Input, wpi::units::inverse< Acceleration > > KA
Definition ExponentialProfile.hpp:57
wpi::units::unit_t< Input > Input_t
Definition ExponentialProfile.hpp:51
wpi::units::compound_unit< Distance, wpi::units::inverse< wpi::units::seconds > > Velocity
Definition ExponentialProfile.hpp:44
constexpr ExponentialProfile & operator=(const ExponentialProfile &)=default
wpi::units::unit_t< KV > kV_t
Definition ExponentialProfile.hpp:56
constexpr ProfileTiming CalculateProfileTiming(const State ¤t, const State &goal) const
Calculates the time it will take for this profile to reach the inflection point, and the time it will...
Definition ExponentialProfile.hpp:219
constexpr wpi::units::second_t TimeLeftUntil(const State ¤t, const State &goal) const
Calculates the time it will take for this profile to reach the goal state.
Definition ExponentialProfile.hpp:204
constexpr ExponentialProfile & operator=(ExponentialProfile &&)=default
wpi::units::unit_t< Velocity > Velocity_t
Definition ExponentialProfile.hpp:47
wpi::units::unit_t< KA > kA_t
Definition ExponentialProfile.hpp:59
wpi::units::unit_t< wpi::units::inverse< wpi::units::seconds > > A_t
Definition ExponentialProfile.hpp:52
constexpr ExponentialProfile(Constraints constraints)
Constructs a ExponentialProfile.
Definition ExponentialProfile.hpp:142
constexpr ExponentialProfile(ExponentialProfile &&)=default
wpi::units::compound_unit< Input, wpi::units::inverse< Velocity > > KV
Definition ExponentialProfile.hpp:55
wpi::units::unit_t< wpi::units::compound_unit< Acceleration, wpi::units::inverse< Input > > > B_t
Definition ExponentialProfile.hpp:53
wpi::units::compound_unit< Velocity, wpi::units::inverse< wpi::units::seconds > > Acceleration
Definition ExponentialProfile.hpp:48
wpi::units::unit_t< Distance > Distance_t
Definition ExponentialProfile.hpp:43
constexpr State CalculateInflectionPoint(const State ¤t, const State &goal) const
Calculates the point after which the fastest way to reach the goal state is to apply input in the opp...
Definition ExponentialProfile.hpp:189
constexpr State Calculate(const wpi::units::second_t &t, const State ¤t, const State &goal) const
Calculates the position and velocity for the profile at a time t where the current state is at time t...
Definition ExponentialProfile.hpp:160
Definition LinearSystem.hpp:20