blob: 32b299662a77c986044bf5eae3853fe64a94cb16 [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
Stephan Pleinesb1177672024-05-27 17:48:32 -07004#include <chrono>
5
6#include "Eigen/Core"
Philipp Schrader790cb542023-07-05 21:06:52 -07007
John Park33858a32018-09-28 23:05:48 -07008#include "aos/macros.h"
briansf0165ca2013-03-02 06:17:47 +00009
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080010namespace aos::util {
briansf0165ca2013-03-02 06:17:47 +000011
12// Calculates a trapezoidal motion profile (like for a control loop's goals).
Austin Schuhe197a962024-02-20 18:10:12 -080013// Supports having the destination position, acceleration, and velocity caps
14// changed in the middle, and for having different accelerations and
15// decelerations.
briansf0165ca2013-03-02 06:17:47 +000016//
17// The only units assumption that this class makes is that the unit of time is
18// seconds.
Austin Schuhe197a962024-02-20 18:10:12 -080019class AsymmetricTrapezoidProfile {
briansf0165ca2013-03-02 06:17:47 +000020 public:
Austin Schuhe197a962024-02-20 18:10:12 -080021 // Constructs a profile. delta_time is the timestep to assume when solving.
22 AsymmetricTrapezoidProfile(::std::chrono::nanoseconds delta_time);
briansf0165ca2013-03-02 06:17:47 +000023
Austin Schuhe197a962024-02-20 18:10:12 -080024 // Updates the state to provide the next position and velocity to go to to
25 // follow the profile.
briansf0165ca2013-03-02 06:17:47 +000026 const Eigen::Matrix<double, 2, 1> &Update(double goal_position,
27 double goal_velocity);
Austin Schuhe197a962024-02-20 18:10:12 -080028
29 // Updates the internal position. Useful for handling windup when a loop
30 // saturates or gets disabled.
Austin Schuh69365d32015-02-22 21:38:24 -080031 void MoveCurrentState(const Eigen::Matrix<double, 2, 1> &current) {
32 output_ = current;
33 }
briansf0165ca2013-03-02 06:17:47 +000034
Austin Schuhe197a962024-02-20 18:10:12 -080035 // Adjusts the internal position by the provided position delta.
Austin Schuh69365d32015-02-22 21:38:24 -080036 void MoveGoal(double dx) { output_(0, 0) += dx; }
Brian Silvermanb94069c2014-04-17 14:34:24 -070037
Austin Schuhe197a962024-02-20 18:10:12 -080038 // Sets the internal position to the provided position.
Austin Schuh69365d32015-02-22 21:38:24 -080039 void SetGoal(double x) { output_(0, 0) = x; }
Brian Silvermanb94069c2014-04-17 14:34:24 -070040
briansf0165ca2013-03-02 06:17:47 +000041 void set_maximum_acceleration(double maximum_acceleration) {
42 maximum_acceleration_ = maximum_acceleration;
43 }
Austin Schuhe197a962024-02-20 18:10:12 -080044 void set_maximum_deceleration(double maximum_deceleration) {
45 maximum_deceleration_ = maximum_deceleration;
46 }
47
briansf0165ca2013-03-02 06:17:47 +000048 void set_maximum_velocity(double maximum_velocity) {
49 maximum_velocity_ = maximum_velocity;
50 }
51
52 private:
Austin Schuhe197a962024-02-20 18:10:12 -080053 // Updates output_ to match the basic kinematics, given that we are going to
54 // accelerate by acceleration over delta_time.
briansf0165ca2013-03-02 06:17:47 +000055 void UpdateVals(double acceleration, double delta_time);
56 // Calculates how long to go for each segment.
Austin Schuhe197a962024-02-20 18:10:12 -080057 void CalculateTimes(double distance_to_target, double goal_velocity,
58 Eigen::Matrix<double, 2, 1> current);
briansf0165ca2013-03-02 06:17:47 +000059 // output_ is where it should go at time_.
60 Eigen::Matrix<double, 2, 1> output_;
61
Austin Schuhe197a962024-02-20 18:10:12 -080062 // Time and acceleration to slow down if we need to reverse directions.
63 double deceleration_reversal_time_;
64 double deceleration_reversal_;
65
66 // Time and acceleration to speed up with.
briansf0165ca2013-03-02 06:17:47 +000067 double acceleration_time_;
68 double acceleration_;
Austin Schuhe197a962024-02-20 18:10:12 -080069 // Time to go at max speed at.
briansf0165ca2013-03-02 06:17:47 +000070 double constant_time_;
Austin Schuhe197a962024-02-20 18:10:12 -080071 // Time and acceleration to slow down with.
briansf0165ca2013-03-02 06:17:47 +000072 double deceleration_time_;
73 double deceleration_;
briansf0165ca2013-03-02 06:17:47 +000074
Austin Schuhe197a962024-02-20 18:10:12 -080075 double maximum_acceleration_ = 0;
76 double maximum_deceleration_ = 0;
77 double maximum_velocity_ = 0;
briansf0165ca2013-03-02 06:17:47 +000078
79 // How long between calls to Update.
Austin Schuh214e9c12016-11-25 17:26:20 -080080 ::std::chrono::nanoseconds timestep_;
briansf0165ca2013-03-02 06:17:47 +000081
Austin Schuhe197a962024-02-20 18:10:12 -080082 DISALLOW_COPY_AND_ASSIGN(AsymmetricTrapezoidProfile);
83};
84
85// Class to implement a AsymmetricTrapezoidProfile where both acceleration and
86// deceleration match.
87class TrapezoidProfile {
88 public:
89 TrapezoidProfile(::std::chrono::nanoseconds delta_time)
90 : asymmetric_trapezoid_profile_(delta_time) {}
91
92 // Updates the state to provide the next position and velocity to go to to
93 // follow the profile.
94 const Eigen::Matrix<double, 2, 1> &Update(double goal_position,
95 double goal_velocity) {
96 return asymmetric_trapezoid_profile_.Update(goal_position, goal_velocity);
97 }
98
99 // Updates the internal position. Useful for handling windup when a loop
100 // saturates or gets disabled.
101 void MoveCurrentState(const Eigen::Matrix<double, 2, 1> &current) {
102 asymmetric_trapezoid_profile_.MoveCurrentState(current);
103 }
104
105 // Adjusts the internal position by the provided position delta.
106 void MoveGoal(double dx) { asymmetric_trapezoid_profile_.MoveGoal(dx); }
107
108 // Sets the internal position to the provided position.
109 void SetGoal(double x) { asymmetric_trapezoid_profile_.SetGoal(x); }
110
111 void set_maximum_acceleration(double maximum_acceleration) {
112 asymmetric_trapezoid_profile_.set_maximum_acceleration(
113 maximum_acceleration);
114 asymmetric_trapezoid_profile_.set_maximum_deceleration(
115 maximum_acceleration);
116 }
117 void set_maximum_velocity(double maximum_velocity) {
118 asymmetric_trapezoid_profile_.set_maximum_velocity(maximum_velocity);
119 }
120
121 private:
122 AsymmetricTrapezoidProfile asymmetric_trapezoid_profile_;
briansf0165ca2013-03-02 06:17:47 +0000123};
124
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800125} // namespace aos::util
briansf0165ca2013-03-02 06:17:47 +0000126
John Park33858a32018-09-28 23:05:48 -0700127#endif // AOS_UTIL_TRAPEZOID_PROFILE_H_