John Park | 33858a3 | 2018-09-28 23:05:48 -0700 | [diff] [blame] | 1 | #include "aos/util/trapezoid_profile.h" |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 2 | |
John Park | 33858a3 | 2018-09-28 23:05:48 -0700 | [diff] [blame] | 3 | #include "aos/logging/logging.h" |
Brian Silverman | 38ea9bf | 2014-04-19 22:57:54 -0700 | [diff] [blame] | 4 | |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 5 | using ::Eigen::Matrix; |
| 6 | |
| 7 | namespace aos { |
| 8 | namespace util { |
| 9 | |
Austin Schuh | 214e9c1 | 2016-11-25 17:26:20 -0800 | [diff] [blame] | 10 | TrapezoidProfile::TrapezoidProfile(::std::chrono::nanoseconds delta_time) |
| 11 | : maximum_acceleration_(0), maximum_velocity_(0), timestep_(delta_time) { |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 12 | output_.setZero(); |
| 13 | } |
| 14 | |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 15 | void TrapezoidProfile::UpdateVals(double acceleration, double delta_time) { |
| 16 | output_(0) += |
| 17 | output_(1) * delta_time + 0.5 * acceleration * delta_time * delta_time; |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 18 | output_(1) += acceleration * delta_time; |
| 19 | } |
| 20 | |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 21 | const Matrix<double, 2, 1> &TrapezoidProfile::Update(double goal_position, |
| 22 | double goal_velocity) { |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 23 | CalculateTimes(goal_position - output_(0), goal_velocity); |
| 24 | |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 25 | double next_timestep = ::aos::time::DurationInSeconds(timestep_); |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 26 | |
| 27 | if (acceleration_time_ > next_timestep) { |
| 28 | UpdateVals(acceleration_, next_timestep); |
| 29 | } else { |
| 30 | UpdateVals(acceleration_, acceleration_time_); |
| 31 | |
| 32 | next_timestep -= acceleration_time_; |
| 33 | if (constant_time_ > next_timestep) { |
| 34 | UpdateVals(0, next_timestep); |
| 35 | } else { |
| 36 | UpdateVals(0, constant_time_); |
| 37 | next_timestep -= constant_time_; |
| 38 | if (deceleration_time_ > next_timestep) { |
| 39 | UpdateVals(deceleration_, next_timestep); |
| 40 | } else { |
| 41 | UpdateVals(deceleration_, deceleration_time_); |
| 42 | next_timestep -= deceleration_time_; |
| 43 | UpdateVals(0, next_timestep); |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | return output_; |
| 49 | } |
| 50 | |
| 51 | void TrapezoidProfile::CalculateTimes(double distance_to_target, |
| 52 | double goal_velocity) { |
| 53 | if (distance_to_target == 0) { |
| 54 | // We're there. Stop everything. |
| 55 | // TODO(aschuh): Deal with velocity not right. |
| 56 | acceleration_time_ = 0; |
| 57 | acceleration_ = 0; |
| 58 | constant_time_ = 0; |
| 59 | deceleration_time_ = 0; |
| 60 | deceleration_ = 0; |
| 61 | return; |
| 62 | } else if (distance_to_target < 0) { |
| 63 | // Recurse with everything inverted. |
| 64 | output_(1) *= -1; |
Diana Vandenberg | 19bb9e2 | 2016-02-03 21:24:31 -0800 | [diff] [blame] | 65 | CalculateTimes(-distance_to_target, -goal_velocity); |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 66 | output_(1) *= -1; |
| 67 | acceleration_ *= -1; |
| 68 | deceleration_ *= -1; |
| 69 | return; |
| 70 | } |
| 71 | |
| 72 | constant_time_ = 0; |
| 73 | acceleration_ = maximum_acceleration_; |
Diana Vandenberg | 19bb9e2 | 2016-02-03 21:24:31 -0800 | [diff] [blame] | 74 | double maximum_acceleration_velocity = |
| 75 | distance_to_target * 2 * std::abs(acceleration_) + |
| 76 | output_(1) * output_(1); |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 77 | if (maximum_acceleration_velocity > 0) { |
| 78 | maximum_acceleration_velocity = sqrt(maximum_acceleration_velocity); |
| 79 | } else { |
| 80 | maximum_acceleration_velocity = -sqrt(-maximum_acceleration_velocity); |
| 81 | } |
| 82 | |
| 83 | // Since we know what we'd have to do if we kept after it to decelerate, we |
| 84 | // know the sign of the acceleration. |
| 85 | if (maximum_acceleration_velocity > goal_velocity) { |
| 86 | deceleration_ = -maximum_acceleration_; |
| 87 | } else { |
| 88 | deceleration_ = maximum_acceleration_; |
| 89 | } |
| 90 | |
| 91 | // We now know the top velocity we can get to. |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 92 | double top_velocity = sqrt( |
| 93 | (distance_to_target + (output_(1) * output_(1)) / (2.0 * acceleration_) + |
| 94 | (goal_velocity * goal_velocity) / (2.0 * deceleration_)) / |
| 95 | (-1.0 / (2.0 * deceleration_) + 1.0 / (2.0 * acceleration_))); |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 96 | |
| 97 | // If it can go too fast, we now know how long we get to accelerate for and |
| 98 | // how long to go at constant velocity. |
| 99 | if (top_velocity > maximum_velocity_) { |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 100 | acceleration_time_ = |
| 101 | (maximum_velocity_ - output_(1)) / maximum_acceleration_; |
| 102 | constant_time_ = |
| 103 | (distance_to_target + (goal_velocity * goal_velocity - |
| 104 | maximum_velocity_ * maximum_velocity_) / |
| 105 | (2.0 * maximum_acceleration_)) / |
| 106 | maximum_velocity_; |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 107 | } else { |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 108 | acceleration_time_ = (top_velocity - output_(1)) / acceleration_; |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 109 | } |
| 110 | |
Brian Silverman | fe457de | 2014-05-26 22:04:08 -0700 | [diff] [blame] | 111 | CHECK_GT(top_velocity, -maximum_velocity_); |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 112 | |
Ben Fredrickson | f33d653 | 2015-03-15 00:29:29 -0700 | [diff] [blame] | 113 | if (output_(1) > maximum_velocity_) { |
| 114 | constant_time_ = 0; |
| 115 | acceleration_time_ = 0; |
| 116 | } |
| 117 | |
James Kuszmaul | 651fc3f | 2019-05-15 21:14:25 -0700 | [diff] [blame^] | 118 | deceleration_time_ = (goal_velocity - top_velocity) / deceleration_; |
brians | f0165ca | 2013-03-02 06:17:47 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | } // namespace util |
| 122 | } // namespace aos |