blob: cd8d02c337a56be19de1e2622f0f1cacf5bbe18f [file] [log] [blame]
briansf0165ca2013-03-02 06:17:47 +00001#include "aos/common/util/trapezoid_profile.h"
2
Brian Silverman38ea9bf2014-04-19 22:57:54 -07003#include "aos/common/logging/logging.h"
4
briansf0165ca2013-03-02 06:17:47 +00005using ::Eigen::Matrix;
6
7namespace aos {
8namespace util {
9
10TrapezoidProfile::TrapezoidProfile(const time::Time &delta_time)
11 : maximum_acceleration_(0),
12 maximum_velocity_(0),
13 timestep_(delta_time) {
14 output_.setZero();
15}
16
17void TrapezoidProfile::UpdateVals(double acceleration,
18 double delta_time) {
19 output_(0) += output_(1) * delta_time +
20 0.5 * acceleration * delta_time * delta_time;
21 output_(1) += acceleration * delta_time;
22}
23
24const Matrix<double, 2, 1> &TrapezoidProfile::Update(
25 double goal_position,
26 double goal_velocity) {
27 CalculateTimes(goal_position - output_(0), goal_velocity);
28
29 double next_timestep = timestep_.ToSeconds();
30
31 if (acceleration_time_ > next_timestep) {
32 UpdateVals(acceleration_, next_timestep);
33 } else {
34 UpdateVals(acceleration_, acceleration_time_);
35
36 next_timestep -= acceleration_time_;
37 if (constant_time_ > next_timestep) {
38 UpdateVals(0, next_timestep);
39 } else {
40 UpdateVals(0, constant_time_);
41 next_timestep -= constant_time_;
42 if (deceleration_time_ > next_timestep) {
43 UpdateVals(deceleration_, next_timestep);
44 } else {
45 UpdateVals(deceleration_, deceleration_time_);
46 next_timestep -= deceleration_time_;
47 UpdateVals(0, next_timestep);
48 }
49 }
50 }
51
52 return output_;
53}
54
55void TrapezoidProfile::CalculateTimes(double distance_to_target,
56 double goal_velocity) {
57 if (distance_to_target == 0) {
58 // We're there. Stop everything.
59 // TODO(aschuh): Deal with velocity not right.
60 acceleration_time_ = 0;
61 acceleration_ = 0;
62 constant_time_ = 0;
63 deceleration_time_ = 0;
64 deceleration_ = 0;
65 return;
66 } else if (distance_to_target < 0) {
67 // Recurse with everything inverted.
68 output_(1) *= -1;
69 CalculateTimes(-distance_to_target,
70 -goal_velocity);
71 output_(1) *= -1;
72 acceleration_ *= -1;
73 deceleration_ *= -1;
74 return;
75 }
76
77 constant_time_ = 0;
78 acceleration_ = maximum_acceleration_;
79 double maximum_acceleration_velocity = distance_to_target * 2 *
80 std::abs(acceleration_) + output_(1) * output_(1);
81 if (maximum_acceleration_velocity > 0) {
82 maximum_acceleration_velocity = sqrt(maximum_acceleration_velocity);
83 } else {
84 maximum_acceleration_velocity = -sqrt(-maximum_acceleration_velocity);
85 }
86
87 // Since we know what we'd have to do if we kept after it to decelerate, we
88 // know the sign of the acceleration.
89 if (maximum_acceleration_velocity > goal_velocity) {
90 deceleration_ = -maximum_acceleration_;
91 } else {
92 deceleration_ = maximum_acceleration_;
93 }
94
95 // We now know the top velocity we can get to.
96 double top_velocity = sqrt((distance_to_target +
97 (output_(1) * output_(1)) /
98 (2.0 * acceleration_) +
99 (goal_velocity * goal_velocity) /
100 (2.0 * deceleration_)) /
101 (-1.0 / (2.0 * deceleration_) +
102 1.0 / (2.0 * acceleration_)));
103
104 // If it can go too fast, we now know how long we get to accelerate for and
105 // how long to go at constant velocity.
106 if (top_velocity > maximum_velocity_) {
107 acceleration_time_ = (maximum_velocity_ - output_(1)) /
108 maximum_acceleration_;
109 constant_time_ = (distance_to_target +
110 (goal_velocity * goal_velocity -
111 maximum_velocity_ * maximum_velocity_) /
112 (2.0 * maximum_acceleration_)) / maximum_velocity_;
113 } else {
114 acceleration_time_ = (top_velocity - output_(1)) /
115 acceleration_;
116 }
117
Brian Silvermanfe457de2014-05-26 22:04:08 -0700118 CHECK_GT(top_velocity, -maximum_velocity_);
briansf0165ca2013-03-02 06:17:47 +0000119
Ben Fredricksonf33d6532015-03-15 00:29:29 -0700120 if (output_(1) > maximum_velocity_) {
121 constant_time_ = 0;
122 acceleration_time_ = 0;
123 }
124
briansf0165ca2013-03-02 06:17:47 +0000125 deceleration_time_ = (goal_velocity - top_velocity) /
126 deceleration_;
127}
128
129} // namespace util
130} // namespace aos