blob: 621ff300ca79d9029ebef68fe9f2905a2735720c [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_UTIL_TRAPEZOID_PROFILE_H_
2#define AOS_UTIL_TRAPEZOID_PROFILE_H_
briansf0165ca2013-03-02 06:17:47 +00003
4#include "Eigen/Dense"
Philipp Schrader790cb542023-07-05 21:06:52 -07005
John Park33858a32018-09-28 23:05:48 -07006#include "aos/macros.h"
7#include "aos/time/time.h"
briansf0165ca2013-03-02 06:17:47 +00008
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08009namespace aos::util {
briansf0165ca2013-03-02 06:17:47 +000010
11// Calculates a trapezoidal motion profile (like for a control loop's goals).
Austin Schuhe197a962024-02-20 18:10:12 -080012// Supports having the destination position, acceleration, and velocity caps
13// changed in the middle, and for having different accelerations and
14// decelerations.
briansf0165ca2013-03-02 06:17:47 +000015//
16// The only units assumption that this class makes is that the unit of time is
17// seconds.
Austin Schuhe197a962024-02-20 18:10:12 -080018class AsymmetricTrapezoidProfile {
briansf0165ca2013-03-02 06:17:47 +000019 public:
Austin Schuhe197a962024-02-20 18:10:12 -080020 // Constructs a profile. delta_time is the timestep to assume when solving.
21 AsymmetricTrapezoidProfile(::std::chrono::nanoseconds delta_time);
briansf0165ca2013-03-02 06:17:47 +000022
Austin Schuhe197a962024-02-20 18:10:12 -080023 // Updates the state to provide the next position and velocity to go to to
24 // follow the profile.
briansf0165ca2013-03-02 06:17:47 +000025 const Eigen::Matrix<double, 2, 1> &Update(double goal_position,
26 double goal_velocity);
Austin Schuhe197a962024-02-20 18:10:12 -080027
28 // Updates the internal position. Useful for handling windup when a loop
29 // saturates or gets disabled.
Austin Schuh69365d32015-02-22 21:38:24 -080030 void MoveCurrentState(const Eigen::Matrix<double, 2, 1> &current) {
31 output_ = current;
32 }
briansf0165ca2013-03-02 06:17:47 +000033
Austin Schuhe197a962024-02-20 18:10:12 -080034 // Adjusts the internal position by the provided position delta.
Austin Schuh69365d32015-02-22 21:38:24 -080035 void MoveGoal(double dx) { output_(0, 0) += dx; }
Brian Silvermanb94069c2014-04-17 14:34:24 -070036
Austin Schuhe197a962024-02-20 18:10:12 -080037 // Sets the internal position to the provided position.
Austin Schuh69365d32015-02-22 21:38:24 -080038 void SetGoal(double x) { output_(0, 0) = x; }
Brian Silvermanb94069c2014-04-17 14:34:24 -070039
briansf0165ca2013-03-02 06:17:47 +000040 void set_maximum_acceleration(double maximum_acceleration) {
41 maximum_acceleration_ = maximum_acceleration;
42 }
Austin Schuhe197a962024-02-20 18:10:12 -080043 void set_maximum_deceleration(double maximum_deceleration) {
44 maximum_deceleration_ = maximum_deceleration;
45 }
46
briansf0165ca2013-03-02 06:17:47 +000047 void set_maximum_velocity(double maximum_velocity) {
48 maximum_velocity_ = maximum_velocity;
49 }
50
51 private:
Austin Schuhe197a962024-02-20 18:10:12 -080052 // Updates output_ to match the basic kinematics, given that we are going to
53 // accelerate by acceleration over delta_time.
briansf0165ca2013-03-02 06:17:47 +000054 void UpdateVals(double acceleration, double delta_time);
55 // Calculates how long to go for each segment.
Austin Schuhe197a962024-02-20 18:10:12 -080056 void CalculateTimes(double distance_to_target, double goal_velocity,
57 Eigen::Matrix<double, 2, 1> current);
briansf0165ca2013-03-02 06:17:47 +000058 // output_ is where it should go at time_.
59 Eigen::Matrix<double, 2, 1> output_;
60
Austin Schuhe197a962024-02-20 18:10:12 -080061 // Time and acceleration to slow down if we need to reverse directions.
62 double deceleration_reversal_time_;
63 double deceleration_reversal_;
64
65 // Time and acceleration to speed up with.
briansf0165ca2013-03-02 06:17:47 +000066 double acceleration_time_;
67 double acceleration_;
Austin Schuhe197a962024-02-20 18:10:12 -080068 // Time to go at max speed at.
briansf0165ca2013-03-02 06:17:47 +000069 double constant_time_;
Austin Schuhe197a962024-02-20 18:10:12 -080070 // Time and acceleration to slow down with.
briansf0165ca2013-03-02 06:17:47 +000071 double deceleration_time_;
72 double deceleration_;
briansf0165ca2013-03-02 06:17:47 +000073
Austin Schuhe197a962024-02-20 18:10:12 -080074 double maximum_acceleration_ = 0;
75 double maximum_deceleration_ = 0;
76 double maximum_velocity_ = 0;
briansf0165ca2013-03-02 06:17:47 +000077
78 // How long between calls to Update.
Austin Schuh214e9c12016-11-25 17:26:20 -080079 ::std::chrono::nanoseconds timestep_;
briansf0165ca2013-03-02 06:17:47 +000080
Austin Schuhe197a962024-02-20 18:10:12 -080081 DISALLOW_COPY_AND_ASSIGN(AsymmetricTrapezoidProfile);
82};
83
84// Class to implement a AsymmetricTrapezoidProfile where both acceleration and
85// deceleration match.
86class TrapezoidProfile {
87 public:
88 TrapezoidProfile(::std::chrono::nanoseconds delta_time)
89 : asymmetric_trapezoid_profile_(delta_time) {}
90
91 // Updates the state to provide the next position and velocity to go to to
92 // follow the profile.
93 const Eigen::Matrix<double, 2, 1> &Update(double goal_position,
94 double goal_velocity) {
95 return asymmetric_trapezoid_profile_.Update(goal_position, goal_velocity);
96 }
97
98 // Updates the internal position. Useful for handling windup when a loop
99 // saturates or gets disabled.
100 void MoveCurrentState(const Eigen::Matrix<double, 2, 1> &current) {
101 asymmetric_trapezoid_profile_.MoveCurrentState(current);
102 }
103
104 // Adjusts the internal position by the provided position delta.
105 void MoveGoal(double dx) { asymmetric_trapezoid_profile_.MoveGoal(dx); }
106
107 // Sets the internal position to the provided position.
108 void SetGoal(double x) { asymmetric_trapezoid_profile_.SetGoal(x); }
109
110 void set_maximum_acceleration(double maximum_acceleration) {
111 asymmetric_trapezoid_profile_.set_maximum_acceleration(
112 maximum_acceleration);
113 asymmetric_trapezoid_profile_.set_maximum_deceleration(
114 maximum_acceleration);
115 }
116 void set_maximum_velocity(double maximum_velocity) {
117 asymmetric_trapezoid_profile_.set_maximum_velocity(maximum_velocity);
118 }
119
120 private:
121 AsymmetricTrapezoidProfile asymmetric_trapezoid_profile_;
briansf0165ca2013-03-02 06:17:47 +0000122};
123
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800124} // namespace aos::util
briansf0165ca2013-03-02 06:17:47 +0000125
John Park33858a32018-09-28 23:05:48 -0700126#endif // AOS_UTIL_TRAPEZOID_PROFILE_H_