blob: 8f82ce200d6672774c7d82001d91d51fd9b24607 [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
Austin Schuh813b9af2015-03-08 18:46:58 -07006#include "aos/common/controls/control_loop.h"
Austin Schuh6e242ac2015-03-07 17:08:21 -08007#include "aos/common/actions/actor.h"
Austin Schuh813b9af2015-03-08 18:46:58 -07008#include "aos/common/util/phased_loop.h"
Austin Schuh6e242ac2015-03-07 17:08:21 -08009#include "frc971/control_loops/fridge/fridge.q.h"
10
11namespace frc971 {
12namespace actors {
13
14struct ProfileParams {
15 double velocity;
16 double acceleration;
17};
18
19// Base class to provide helper utilities to all Actors who want to control the
20// fridge.
21template <typename T>
22class FridgeActorBase : public aos::common::actions::ActorBase<T> {
23 public:
24 FridgeActorBase(T *queues) : aos::common::actions::ActorBase<T>(queues) {}
25
26 protected:
27 void DoFridgeProfile(double height, double angle,
28 ProfileParams elevator_parameters,
29 ProfileParams arm_parameters, bool grabbers) {
30 DoFridgeProfile(height, angle, elevator_parameters, arm_parameters,
31 grabbers, grabbers, grabbers);
32 }
33
34 void DoFridgeProfile(double height, double angle,
35 ProfileParams elevator_parameters,
36 ProfileParams arm_parameters, bool top_grabbers,
37 bool front_grabbers, bool back_grabbers) {
38 auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
39 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;
51
52 if (!new_fridge_goal.Send()) {
53 LOG(ERROR, "Failed to send fridge goal\n");
54 return;
55 }
56
57 while (true) {
58 control_loops::fridge_queue.status.FetchAnother();
59
60 constexpr double kProfileError = 1e-5;
61 constexpr double kAngleEpsilon = 0.02, kHeightEpsilon = 0.015;
62
63 if (::std::abs(control_loops::fridge_queue.status->goal_angle - angle) <
64 kProfileError &&
65 ::std::abs(control_loops::fridge_queue.status->goal_height - height) <
66 kProfileError &&
67 ::std::abs(
68 control_loops::fridge_queue.status->goal_angular_velocity) <
69 kProfileError &&
70 ::std::abs(control_loops::fridge_queue.status->goal_velocity) <
71 kProfileError &&
72 ::std::abs(control_loops::fridge_queue.status->angle - angle) <
73 kAngleEpsilon &&
74 ::std::abs(control_loops::fridge_queue.status->height - height) <
75 kHeightEpsilon) {
76 return;
77 }
78
79 if (this->ShouldCancel()) {
80 auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
81 new_fridge_goal->max_velocity = elevator_parameters.velocity;
82 new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
83 new_fridge_goal->height =
84 control_loops::fridge_queue.status->height +
85 ::std::pow(control_loops::fridge_queue.status->goal_velocity, 2.0) /
86 (2.0 * new_fridge_goal->max_acceleration);
87 new_fridge_goal->velocity = 0.0;
88 new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
89 new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
90 new_fridge_goal->angle =
91 control_loops::fridge_queue.status->angle +
92 ::std::pow(
93 control_loops::fridge_queue.status->goal_angular_velocity,
94 2.0) /
95 (2.0 * new_fridge_goal->max_angular_acceleration);
96 new_fridge_goal->angular_velocity = 0.0;
97 new_fridge_goal->grabbers.top_front = top_grabbers;
98 new_fridge_goal->grabbers.top_back = top_grabbers;
99 new_fridge_goal->grabbers.bottom_front = front_grabbers;
100 new_fridge_goal->grabbers.bottom_back = back_grabbers;
101
102 if (!new_fridge_goal.Send()) {
103 LOG(ERROR, "Failed to send fridge goal\n");
104 return;
105 }
106 }
107 }
108 }
Austin Schuh813b9af2015-03-08 18:46:58 -0700109
110 bool WaitOrCancel(::aos::time::Time duration) {
111 ::aos::time::Time end_time = ::aos::time::Time::Now() + duration;
112 while (::aos::time::Time::Now() <= end_time) {
113 ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(),
114 2500);
115 if (this->ShouldCancel()) return false;
116 }
117 return true;
118 }
Austin Schuh6e242ac2015-03-07 17:08:21 -0800119};
120
121} // namespace actors
122} // namespace frc971
123
124#endif // FRC971_ACTORS_FRIDGE_PROFILE_LIB_H_