blob: 89808480a70b599c279e08c9201ad5840e4ea25d [file] [log] [blame]
Brian Silvermanb691f5e2015-08-02 11:37:55 -07001#ifndef Y2015_ACTORS_FRIDGE_PROFILE_LIB_H_
2#define Y2015_ACTORS_FRIDGE_PROFILE_LIB_H_
Austin Schuh6e242ac2015-03-07 17:08:21 -08003
4#include <cmath>
5
6#include "aos/common/actions/actor.h"
Austin Schuh813b9af2015-03-08 18:46:58 -07007#include "aos/common/util/phased_loop.h"
Brian Silvermanb691f5e2015-08-02 11:37:55 -07008#include "y2015/control_loops/fridge/fridge.q.h"
Austin Schuh6e242ac2015-03-07 17:08:21 -08009
Austin Schuh88af0852016-12-04 20:31:32 -080010namespace y2015 {
Austin Schuh6e242ac2015-03-07 17:08:21 -080011namespace actors {
12
13struct ProfileParams {
14 double velocity;
15 double acceleration;
16};
17
18// Base class to provide helper utilities to all Actors who want to control the
19// fridge.
20template <typename T>
21class FridgeActorBase : public aos::common::actions::ActorBase<T> {
22 public:
23 FridgeActorBase(T *queues) : aos::common::actions::ActorBase<T>(queues) {}
24
25 protected:
26 void DoFridgeProfile(double height, double angle,
27 ProfileParams elevator_parameters,
28 ProfileParams arm_parameters, bool grabbers) {
29 DoFridgeProfile(height, angle, elevator_parameters, arm_parameters,
30 grabbers, grabbers, grabbers);
31 }
32
Austin Schuhfa65bfd2015-03-14 21:10:44 -070033 bool StartFridgeProfile(double height, double angle,
34 ProfileParams elevator_parameters,
35 ProfileParams arm_parameters, bool top_grabbers,
36 bool front_grabbers, bool back_grabbers) {
Austin Schuh88af0852016-12-04 20:31:32 -080037 auto new_fridge_goal =
38 control_loops::fridge::fridge_queue.goal.MakeMessage();
Austin Schuh1d44bd42015-03-15 16:40:45 -070039 new_fridge_goal->profiling_type = 0;
Austin Schuh6e242ac2015-03-07 17:08:21 -080040 new_fridge_goal->max_velocity = elevator_parameters.velocity;
41 new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
42 new_fridge_goal->height = height;
43 new_fridge_goal->velocity = 0.0;
44 new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
45 new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
46 new_fridge_goal->angle = angle;
47 new_fridge_goal->angular_velocity = 0.0;
48 new_fridge_goal->grabbers.top_front = top_grabbers;
49 new_fridge_goal->grabbers.top_back = top_grabbers;
50 new_fridge_goal->grabbers.bottom_front = front_grabbers;
51 new_fridge_goal->grabbers.bottom_back = back_grabbers;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070052 LOG(INFO, "Starting profile to %f, %f\n", height, angle);
Austin Schuh6e242ac2015-03-07 17:08:21 -080053
54 if (!new_fridge_goal.Send()) {
55 LOG(ERROR, "Failed to send fridge goal\n");
Austin Schuhfa65bfd2015-03-14 21:10:44 -070056 return false;
57 }
58 return true;
59 }
60
Brian Silvermaned86fc12015-03-19 23:37:35 -070061 enum ProfileStatus { RUNNING, DONE, CANCELED };
Austin Schuhfa65bfd2015-03-14 21:10:44 -070062
63 ProfileStatus IterateProfile(double height, double angle,
64 ProfileParams elevator_parameters,
65 ProfileParams arm_parameters, bool top_grabbers,
66 bool front_grabbers, bool back_grabbers) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -070067 if (this->ShouldCancel()) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -070068 LOG(INFO, "Canceling fridge movement\n");
Austin Schuh88af0852016-12-04 20:31:32 -080069 if (!control_loops::fridge::fridge_queue.status.get()) {
Brian Silvermanf1c5e7d2015-03-28 18:25:25 -040070 LOG(WARNING, "no fridge status so can't really cancel\n");
71 return CANCELED;
72 }
73
Austin Schuh88af0852016-12-04 20:31:32 -080074 auto new_fridge_goal =
75 control_loops::fridge::fridge_queue.goal.MakeMessage();
Austin Schuh1d44bd42015-03-15 16:40:45 -070076 new_fridge_goal->profiling_type = 0;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070077 new_fridge_goal->max_velocity = elevator_parameters.velocity;
78 new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
79 new_fridge_goal->height =
Austin Schuh88af0852016-12-04 20:31:32 -080080 control_loops::fridge::fridge_queue.status->height +
81 (control_loops::fridge::fridge_queue.status->goal_velocity *
82 ::std::abs(control_loops::fridge::fridge_queue.status->goal_velocity)) /
Austin Schuhfa65bfd2015-03-14 21:10:44 -070083 (2.0 * new_fridge_goal->max_acceleration);
Austin Schuh511e8652015-03-15 17:53:31 -070084 height = new_fridge_goal->height;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070085 new_fridge_goal->velocity = 0.0;
86 new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
87 new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
88 new_fridge_goal->angle =
Austin Schuh88af0852016-12-04 20:31:32 -080089 control_loops::fridge::fridge_queue.status->angle +
90 (control_loops::fridge::fridge_queue.status->goal_angular_velocity *
Austin Schuhfa65bfd2015-03-14 21:10:44 -070091 ::std::abs(
Austin Schuh88af0852016-12-04 20:31:32 -080092 control_loops::fridge::fridge_queue.status->goal_angular_velocity)) /
Austin Schuhfa65bfd2015-03-14 21:10:44 -070093 (2.0 * new_fridge_goal->max_angular_acceleration);
Austin Schuh511e8652015-03-15 17:53:31 -070094 angle = new_fridge_goal->angle;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070095 new_fridge_goal->angular_velocity = 0.0;
96 new_fridge_goal->grabbers.top_front = top_grabbers;
97 new_fridge_goal->grabbers.top_back = top_grabbers;
98 new_fridge_goal->grabbers.bottom_front = front_grabbers;
99 new_fridge_goal->grabbers.bottom_back = back_grabbers;
100
101 if (!new_fridge_goal.Send()) {
102 LOG(ERROR, "Failed to send fridge goal\n");
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700103 }
Brian Silvermaned86fc12015-03-19 23:37:35 -0700104 return CANCELED;
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700105 }
Austin Schuh88af0852016-12-04 20:31:32 -0800106 control_loops::fridge::fridge_queue.status.FetchAnother();
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700107
108 constexpr double kProfileError = 1e-5;
109 constexpr double kAngleEpsilon = 0.02, kHeightEpsilon = 0.015;
110
Austin Schuh88af0852016-12-04 20:31:32 -0800111 if (control_loops::fridge::fridge_queue.status->state != 4) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700112 LOG(ERROR, "Fridge no longer running, aborting action\n");
113 return CANCELED;
114 }
115
Austin Schuh88af0852016-12-04 20:31:32 -0800116 if (::std::abs(control_loops::fridge::fridge_queue.status->goal_angle -
117 angle) < kProfileError &&
118 ::std::abs(control_loops::fridge::fridge_queue.status->goal_height -
119 height) < kProfileError &&
120 ::std::abs(
121 control_loops::fridge::fridge_queue.status->goal_angular_velocity) <
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700122 kProfileError &&
Austin Schuh88af0852016-12-04 20:31:32 -0800123 ::std::abs(control_loops::fridge::fridge_queue.status->goal_velocity) <
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700124 kProfileError) {
125 LOG(INFO, "Profile done.\n");
Austin Schuh88af0852016-12-04 20:31:32 -0800126 if (::std::abs(control_loops::fridge::fridge_queue.status->angle -
127 angle) < kAngleEpsilon &&
128 ::std::abs(control_loops::fridge::fridge_queue.status->height -
129 height) < kHeightEpsilon) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700130 LOG(INFO, "Near goal, done.\n");
131 return DONE;
132 }
133 }
134
Brian Silvermaned86fc12015-03-19 23:37:35 -0700135 return RUNNING;
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700136 }
137
138 void DoFridgeProfile(double height, double angle,
139 ProfileParams elevator_parameters,
140 ProfileParams arm_parameters, bool top_grabbers,
141 bool front_grabbers, bool back_grabbers) {
142 if (!StartFridgeProfile(height, angle, elevator_parameters, arm_parameters,
143 top_grabbers, front_grabbers, back_grabbers)) {
Austin Schuh6e242ac2015-03-07 17:08:21 -0800144 return;
145 }
146
147 while (true) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700148 ProfileStatus status =
149 IterateProfile(height, angle, elevator_parameters, arm_parameters,
150 top_grabbers, front_grabbers, back_grabbers);
151 if (status == DONE || status == CANCELED) {
Austin Schuh6e242ac2015-03-07 17:08:21 -0800152 return;
153 }
Austin Schuh6e242ac2015-03-07 17:08:21 -0800154 }
155 }
Austin Schuh4c52fb02015-03-29 13:40:08 -0700156
157 void DoFridgeXYProfile(double x, double y, ProfileParams x_parameters,
158 ProfileParams y_parameters, bool grabbers) {
159 DoFridgeXYProfile(x, y, x_parameters, y_parameters, grabbers, grabbers,
160 grabbers);
161 }
162
163 void DoFridgeXYProfile(double x, double y, ProfileParams x_parameters,
164 ProfileParams y_parameters, bool top_grabbers,
165 bool front_grabbers, bool back_grabbers) {
166 if (!StartFridgeXYProfile(x, y, x_parameters, y_parameters, top_grabbers,
167 front_grabbers, back_grabbers)) {
168 return;
169 }
170
171 while (true) {
172 ProfileStatus status =
173 IterateXYProfile(x, y, x_parameters, y_parameters, top_grabbers,
174 front_grabbers, back_grabbers);
175 if (status == DONE || status == CANCELED) {
176 return;
177 }
178 }
179 }
180
181 void CancelXYMotion(ProfileParams x_parameters, ProfileParams y_parameters,
182 bool top_grabbers, bool front_grabbers,
183 bool back_grabbers) {
184 LOG(INFO, "Canceling fridge movement\n");
Austin Schuh88af0852016-12-04 20:31:32 -0800185 if (!control_loops::fridge::fridge_queue.status.get()) {
Austin Schuh4c52fb02015-03-29 13:40:08 -0700186 LOG(WARNING, "no fridge status so can't really cancel\n");
187 return;
188 }
189
Austin Schuh88af0852016-12-04 20:31:32 -0800190 auto new_fridge_goal =
191 control_loops::fridge::fridge_queue.goal.MakeMessage();
Austin Schuh4c52fb02015-03-29 13:40:08 -0700192 new_fridge_goal->profiling_type = 1;
193 new_fridge_goal->max_x_velocity = x_parameters.velocity;
194 new_fridge_goal->max_x_acceleration = x_parameters.acceleration;
195 new_fridge_goal->x =
Austin Schuh88af0852016-12-04 20:31:32 -0800196 control_loops::fridge::fridge_queue.status->x +
197 (control_loops::fridge::fridge_queue.status->goal_x_velocity *
198 ::std::abs(
199 control_loops::fridge::fridge_queue.status->goal_x_velocity)) /
Austin Schuh4c52fb02015-03-29 13:40:08 -0700200 (2.0 * new_fridge_goal->max_x_acceleration);
201 new_fridge_goal->x_velocity = 0.0;
202
203 new_fridge_goal->max_y_velocity = y_parameters.velocity;
204 new_fridge_goal->max_y_acceleration = y_parameters.acceleration;
205 new_fridge_goal->y =
Austin Schuh88af0852016-12-04 20:31:32 -0800206 control_loops::fridge::fridge_queue.status->y +
207 (control_loops::fridge::fridge_queue.status->goal_y_velocity *
208 ::std::abs(
209 control_loops::fridge::fridge_queue.status->goal_y_velocity)) /
Austin Schuh4c52fb02015-03-29 13:40:08 -0700210 (2.0 * new_fridge_goal->max_y_acceleration);
211 new_fridge_goal->y_velocity = 0.0;
212
213 new_fridge_goal->grabbers.top_front = top_grabbers;
214 new_fridge_goal->grabbers.top_back = top_grabbers;
215 new_fridge_goal->grabbers.bottom_front = front_grabbers;
216 new_fridge_goal->grabbers.bottom_back = back_grabbers;
217
218 if (!new_fridge_goal.Send()) {
219 LOG(ERROR, "Failed to send fridge goal\n");
220 }
221 }
222
223 ProfileStatus IterateXYProfile(double x, double y, ProfileParams x_parameters,
224 ProfileParams y_parameters, bool top_grabbers,
225 bool front_grabbers, bool back_grabbers) {
226 if (this->ShouldCancel()) {
227 CancelXYMotion(x_parameters, y_parameters, top_grabbers, front_grabbers,
228 back_grabbers);
229 return CANCELED;
230 }
Austin Schuh88af0852016-12-04 20:31:32 -0800231 control_loops::fridge::fridge_queue.status.FetchAnother();
Austin Schuh4c52fb02015-03-29 13:40:08 -0700232
233 constexpr double kProfileError = 1e-5;
234 constexpr double kXEpsilon = 0.02, kYEpsilon = 0.02;
235
Austin Schuh88af0852016-12-04 20:31:32 -0800236 if (control_loops::fridge::fridge_queue.status->state != 4) {
Austin Schuh4c52fb02015-03-29 13:40:08 -0700237 LOG(ERROR, "Fridge no longer running, aborting action\n");
238 return CANCELED;
239 }
240
Austin Schuh88af0852016-12-04 20:31:32 -0800241 if (::std::abs(control_loops::fridge::fridge_queue.status->goal_x - x) <
Austin Schuh4c52fb02015-03-29 13:40:08 -0700242 kProfileError &&
Austin Schuh88af0852016-12-04 20:31:32 -0800243 ::std::abs(control_loops::fridge::fridge_queue.status->goal_y - y) <
Austin Schuh4c52fb02015-03-29 13:40:08 -0700244 kProfileError &&
Austin Schuh88af0852016-12-04 20:31:32 -0800245 ::std::abs(
246 control_loops::fridge::fridge_queue.status->goal_x_velocity) <
Austin Schuh4c52fb02015-03-29 13:40:08 -0700247 kProfileError &&
Austin Schuh88af0852016-12-04 20:31:32 -0800248 ::std::abs(
249 control_loops::fridge::fridge_queue.status->goal_y_velocity) <
Austin Schuh4c52fb02015-03-29 13:40:08 -0700250 kProfileError) {
251 LOG(INFO, "Profile done.\n");
Austin Schuh88af0852016-12-04 20:31:32 -0800252 if (::std::abs(control_loops::fridge::fridge_queue.status->x - x) <
253 kXEpsilon &&
254 ::std::abs(control_loops::fridge::fridge_queue.status->y - y) <
255 kYEpsilon) {
Austin Schuh4c52fb02015-03-29 13:40:08 -0700256 LOG(INFO, "Near goal, done.\n");
257 return DONE;
258 }
259 }
260
261 return RUNNING;
262 }
263
264 bool StartFridgeXYProfile(double x, double y, ProfileParams x_parameters,
265 ProfileParams y_parameters, bool top_grabbers,
266 bool front_grabbers, bool back_grabbers) {
Austin Schuh88af0852016-12-04 20:31:32 -0800267 auto new_fridge_goal =
268 control_loops::fridge::fridge_queue.goal.MakeMessage();
Austin Schuh4c52fb02015-03-29 13:40:08 -0700269 new_fridge_goal->profiling_type = 1;
270 new_fridge_goal->max_x_velocity = x_parameters.velocity;
271 new_fridge_goal->max_x_acceleration = x_parameters.acceleration;
272 new_fridge_goal->x = x;
273 new_fridge_goal->x_velocity = 0.0;
274
275 new_fridge_goal->max_y_velocity = y_parameters.velocity;
276 new_fridge_goal->max_y_acceleration = y_parameters.acceleration;
277 new_fridge_goal->y = y;
278 new_fridge_goal->y_velocity = 0.0;
279 new_fridge_goal->grabbers.top_front = top_grabbers;
280 new_fridge_goal->grabbers.top_back = top_grabbers;
281 new_fridge_goal->grabbers.bottom_front = front_grabbers;
282 new_fridge_goal->grabbers.bottom_back = back_grabbers;
283 LOG(INFO, "Starting xy profile to %f, %f\n", x, y);
284
285 if (!new_fridge_goal.Send()) {
286 LOG(ERROR, "Failed to send fridge goal\n");
287 return false;
288 }
289 return true;
290 }
Austin Schuh6e242ac2015-03-07 17:08:21 -0800291};
292
293} // namespace actors
Austin Schuh88af0852016-12-04 20:31:32 -0800294} // namespace y2015
Austin Schuh6e242ac2015-03-07 17:08:21 -0800295
Brian Silvermanb691f5e2015-08-02 11:37:55 -0700296#endif // Y2015_ACTORS_FRIDGE_PROFILE_LIB_H_