blob: 0ba4bcf7d077b728ccb8ab5189994c00ff398568 [file] [log] [blame]
Austin Schuh6e242ac2015-03-07 17:08:21 -08001#ifndef FRC971_ACTORS_FRIDGE_PROFILE_LIB_H_
2#define FRC971_ACTORS_FRIDGE_PROFILE_LIB_H_
3
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"
Austin Schuh6e242ac2015-03-07 17:08:21 -08008#include "frc971/control_loops/fridge/fridge.q.h"
9
10namespace frc971 {
11namespace 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 Schuh6e242ac2015-03-07 17:08:21 -080037 auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
Austin Schuh1d44bd42015-03-15 16:40:45 -070038 new_fridge_goal->profiling_type = 0;
Austin Schuh6e242ac2015-03-07 17:08:21 -080039 new_fridge_goal->max_velocity = elevator_parameters.velocity;
40 new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
41 new_fridge_goal->height = height;
42 new_fridge_goal->velocity = 0.0;
43 new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
44 new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
45 new_fridge_goal->angle = angle;
46 new_fridge_goal->angular_velocity = 0.0;
47 new_fridge_goal->grabbers.top_front = top_grabbers;
48 new_fridge_goal->grabbers.top_back = top_grabbers;
49 new_fridge_goal->grabbers.bottom_front = front_grabbers;
50 new_fridge_goal->grabbers.bottom_back = back_grabbers;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070051 LOG(INFO, "Starting profile to %f, %f\n", height, angle);
Austin Schuh6e242ac2015-03-07 17:08:21 -080052
53 if (!new_fridge_goal.Send()) {
54 LOG(ERROR, "Failed to send fridge goal\n");
Austin Schuhfa65bfd2015-03-14 21:10:44 -070055 return false;
56 }
57 return true;
58 }
59
Brian Silvermaned86fc12015-03-19 23:37:35 -070060 enum ProfileStatus { RUNNING, DONE, CANCELED };
Austin Schuhfa65bfd2015-03-14 21:10:44 -070061
62 ProfileStatus IterateProfile(double height, double angle,
63 ProfileParams elevator_parameters,
64 ProfileParams arm_parameters, bool top_grabbers,
65 bool front_grabbers, bool back_grabbers) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -070066 if (this->ShouldCancel()) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -070067 LOG(INFO, "Canceling fridge movement\n");
68 auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
Austin Schuh1d44bd42015-03-15 16:40:45 -070069 new_fridge_goal->profiling_type = 0;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070070 new_fridge_goal->max_velocity = elevator_parameters.velocity;
71 new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
72 new_fridge_goal->height =
73 control_loops::fridge_queue.status->height +
74 (control_loops::fridge_queue.status->goal_velocity *
75 ::std::abs(control_loops::fridge_queue.status->goal_velocity)) /
76 (2.0 * new_fridge_goal->max_acceleration);
Austin Schuh511e8652015-03-15 17:53:31 -070077 height = new_fridge_goal->height;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070078 new_fridge_goal->velocity = 0.0;
79 new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
80 new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
81 new_fridge_goal->angle =
82 control_loops::fridge_queue.status->angle +
83 (control_loops::fridge_queue.status->goal_angular_velocity *
84 ::std::abs(
85 control_loops::fridge_queue.status->goal_angular_velocity)) /
86 (2.0 * new_fridge_goal->max_angular_acceleration);
Austin Schuh511e8652015-03-15 17:53:31 -070087 angle = new_fridge_goal->angle;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070088 new_fridge_goal->angular_velocity = 0.0;
89 new_fridge_goal->grabbers.top_front = top_grabbers;
90 new_fridge_goal->grabbers.top_back = top_grabbers;
91 new_fridge_goal->grabbers.bottom_front = front_grabbers;
92 new_fridge_goal->grabbers.bottom_back = back_grabbers;
93
94 if (!new_fridge_goal.Send()) {
95 LOG(ERROR, "Failed to send fridge goal\n");
Austin Schuhfa65bfd2015-03-14 21:10:44 -070096 }
Brian Silvermaned86fc12015-03-19 23:37:35 -070097 return CANCELED;
Austin Schuhfa65bfd2015-03-14 21:10:44 -070098 }
99 control_loops::fridge_queue.status.FetchAnother();
100
101 constexpr double kProfileError = 1e-5;
102 constexpr double kAngleEpsilon = 0.02, kHeightEpsilon = 0.015;
103
104 if (control_loops::fridge_queue.status->state != 4) {
105 LOG(ERROR, "Fridge no longer running, aborting action\n");
106 return CANCELED;
107 }
108
109 if (::std::abs(control_loops::fridge_queue.status->goal_angle - angle) <
110 kProfileError &&
111 ::std::abs(control_loops::fridge_queue.status->goal_height - height) <
112 kProfileError &&
113 ::std::abs(control_loops::fridge_queue.status->goal_angular_velocity) <
114 kProfileError &&
115 ::std::abs(control_loops::fridge_queue.status->goal_velocity) <
116 kProfileError) {
117 LOG(INFO, "Profile done.\n");
Brian Silvermaned86fc12015-03-19 23:37:35 -0700118 if (::std::abs(control_loops::fridge_queue.status->angle - angle) <
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700119 kAngleEpsilon &&
120 ::std::abs(control_loops::fridge_queue.status->height -
121 height) < kHeightEpsilon) {
122 LOG(INFO, "Near goal, done.\n");
123 return DONE;
124 }
125 }
126
Brian Silvermaned86fc12015-03-19 23:37:35 -0700127 return RUNNING;
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700128 }
129
130 void DoFridgeProfile(double height, double angle,
131 ProfileParams elevator_parameters,
132 ProfileParams arm_parameters, bool top_grabbers,
133 bool front_grabbers, bool back_grabbers) {
134 if (!StartFridgeProfile(height, angle, elevator_parameters, arm_parameters,
135 top_grabbers, front_grabbers, back_grabbers)) {
Austin Schuh6e242ac2015-03-07 17:08:21 -0800136 return;
137 }
138
139 while (true) {
Austin Schuhfa65bfd2015-03-14 21:10:44 -0700140 ProfileStatus status =
141 IterateProfile(height, angle, elevator_parameters, arm_parameters,
142 top_grabbers, front_grabbers, back_grabbers);
143 if (status == DONE || status == CANCELED) {
Austin Schuh6e242ac2015-03-07 17:08:21 -0800144 return;
145 }
Austin Schuh6e242ac2015-03-07 17:08:21 -0800146 }
147 }
Austin Schuh6e242ac2015-03-07 17:08:21 -0800148};
149
150} // namespace actors
151} // namespace frc971
152
153#endif // FRC971_ACTORS_FRIDGE_PROFILE_LIB_H_