blob: d0ee666218246e9f6c92e0a5ffa012a54740909c [file] [log] [blame]
Austin Schuhd78ab542013-03-01 22:22:19 -08001#ifndef FRC971_CONTROL_LOOPS_WRIST_H_
2#define FRC971_CONTROL_LOOPS_WRIST_H_
3
4#include <memory>
5#include <deque>
6
7#include "aos/common/control_loop/ControlLoop.h"
8#include "aos/common/time.h"
9#include "frc971/control_loops/state_feedback_loop.h"
Austin Schuh00558222013-03-03 14:16:16 -080010#include "frc971/control_loops/index/index_motor.q.h"
11#include "frc971/control_loops/index/index_motor_plant.h"
Austin Schuhd78ab542013-03-01 22:22:19 -080012
13namespace frc971 {
14namespace control_loops {
Austin Schuhbcdb90c2013-03-03 23:24:58 -080015namespace testing {
16class IndexTest_InvalidStateTest_Test;
17}
Austin Schuhd78ab542013-03-01 22:22:19 -080018
19class IndexMotor
20 : public aos::control_loops::ControlLoop<control_loops::IndexLoop> {
21 public:
22 explicit IndexMotor(
Austin Schuhf8c52252013-03-03 02:25:49 -080023 control_loops::IndexLoop *my_index = &control_loops::index_loop);
24
25 static const double kTransferStartPosition;
26 static const double kIndexStartPosition;
27 // The distance from where the disc first grabs on the indexer to where it
28 // just bairly clears the loader.
29 static const double kIndexFreeLength;
30 // The distance to where the disc just starts to enter the loader.
31 static const double kLoaderFreeStopPosition;
32
33 // Distance that the grabber pulls the disc in by.
34 static const double kGrabberLength;
35 // Distance to where the grabber takes over.
36 static const double kGrabberStartPosition;
37
38 // The distance to where the disc hits the back of the loader and is ready to
39 // lift.
40 static const double kReadyToLiftPosition;
41
42 static const double kGrabberMovementVelocity;
43 // TODO(aschuh): This depends on the shooter angle...
44 // Distance to where the shooter is up and ready to shoot.
45 static const double kLifterStopPosition;
46 static const double kLifterMovementVelocity;
47
48 // Distance to where the disc has been launched.
49 // TODO(aschuh): This depends on the shooter angle...
50 static const double kEjectorStopPosition;
51 static const double kEjectorMovementVelocity;
52
53 // Start and stop position of the bottom disc detect sensor in meters.
54 static const double kBottomDiscDetectStart;
55 static const double kBottomDiscDetectStop;
56
57 static const double kTopDiscDetectStart;
58 static const double kTopDiscDetectStop;
Austin Schuhd78ab542013-03-01 22:22:19 -080059
60 // Converts the angle of the indexer to the angle of the disc.
61 static double ConvertIndexToDiscAngle(const double angle);
62 // Converts the angle of the indexer to the position that the center of the
63 // disc has traveled.
64 static double ConvertIndexToDiscPosition(const double angle);
65
Austin Schuhf8c52252013-03-03 02:25:49 -080066 // Converts the angle of the transfer roller to the position that the center
67 // of the disc has traveled.
68 static double ConvertTransferToDiscPosition(const double angle);
69
70 // Converts the distance around the indexer to the position of
71 // the index roller.
72 static double ConvertDiscPositionToIndex(const double position);
Austin Schuhd78ab542013-03-01 22:22:19 -080073 // Converts the angle around the indexer to the position of the index roller.
74 static double ConvertDiscAngleToIndex(const double angle);
75 // Converts the angle around the indexer to the position of the disc in the
76 // indexer.
77 static double ConvertDiscAngleToDiscPosition(const double angle);
Austin Schuhf8c52252013-03-03 02:25:49 -080078 // Converts the distance around the indexer to the angle of the disc around
79 // the indexer.
80 static double ConvertDiscPositionToDiscAngle(const double position);
Austin Schuhd78ab542013-03-01 22:22:19 -080081
82 // Disc radius in meters.
Austin Schuhf8c52252013-03-03 02:25:49 -080083 static const double kDiscRadius;
Austin Schuhd78ab542013-03-01 22:22:19 -080084 // Roller radius in meters.
Austin Schuhf8c52252013-03-03 02:25:49 -080085 static const double kRollerRadius;
86 // Transfer roller radius in meters.
87 static const double kTransferRollerRadius;
Austin Schuhd78ab542013-03-01 22:22:19 -080088
Austin Schuhf8c52252013-03-03 02:25:49 -080089 // Time that it takes to grab the disc in cycles.
90 static const int kGrabbingDelay;
91 // Time that it takes to lift the loader in cycles.
92 static const int kLiftingDelay;
93 // Time that it takes to shoot the disc in cycles.
94 static const int kShootingDelay;
95 // Time that it takes to lower the loader in cycles.
96 static const int kLoweringDelay;
97
98 // Object representing a Frisbee tracked by the indexer.
Austin Schuhd78ab542013-03-01 22:22:19 -080099 class Frisbee {
100 public:
101 Frisbee()
102 : bottom_posedge_time_(0, 0),
Austin Schuhf8c52252013-03-03 02:25:49 -0800103 bottom_negedge_time_(0, 0) {
Austin Schuhd78ab542013-03-01 22:22:19 -0800104 Reset();
105 }
106
Austin Schuhf8c52252013-03-03 02:25:49 -0800107 // Resets a Frisbee so it can be reused.
Austin Schuhd78ab542013-03-01 22:22:19 -0800108 void Reset() {
109 bottom_posedge_time_ = ::aos::time::Time(0, 0);
110 bottom_negedge_time_ = ::aos::time::Time(0, 0);
Austin Schuhd78ab542013-03-01 22:22:19 -0800111 has_been_indexed_ = false;
112 index_start_position_ = 0.0;
113 }
114
Austin Schuhf8c52252013-03-03 02:25:49 -0800115 // Returns true if the position is valid.
116 bool has_position() const {
117 return has_been_indexed_;
118 }
119
120 // Returns the most up to date and accurate position that we have for the
121 // disc. This is the indexer position that the disc grabbed at.
122 double position() const {
123 return index_start_position_;
124 }
125
Austin Schuhbcdb90c2013-03-03 23:24:58 -0800126 // Shifts the disc down the indexer by the provided offset. This is to
127 // handle when the cRIO reboots.
128 void OffsetDisc(double offset) {
129 index_start_position_ += offset;
130 }
131
Austin Schuhf8c52252013-03-03 02:25:49 -0800132 // Posedge and negedge disc times.
Austin Schuhd78ab542013-03-01 22:22:19 -0800133 ::aos::time::Time bottom_posedge_time_;
134 ::aos::time::Time bottom_negedge_time_;
Austin Schuhf8c52252013-03-03 02:25:49 -0800135
136 // True if the disc has a valid index position.
Austin Schuhd78ab542013-03-01 22:22:19 -0800137 bool has_been_indexed_;
Austin Schuhf8c52252013-03-03 02:25:49 -0800138 // Location of the index when the disc first contacted it.
Austin Schuhd78ab542013-03-01 22:22:19 -0800139 double index_start_position_;
140 };
141
142 protected:
143 virtual void RunIteration(
144 const control_loops::IndexLoop::Goal *goal,
145 const control_loops::IndexLoop::Position *position,
146 control_loops::IndexLoop::Output *output,
147 control_loops::IndexLoop::Status *status);
148
149 private:
Austin Schuhbcdb90c2013-03-03 23:24:58 -0800150 friend class testing::IndexTest_InvalidStateTest_Test;
Austin Schuhf8c52252013-03-03 02:25:49 -0800151 // Sets disc_position to the minimum or maximum disc position.
152 // Returns true if there were discs, and false if there weren't.
153 // On false, disc_position is left unmodified.
154 bool MinDiscPosition(double *disc_position);
155 bool MaxDiscPosition(double *disc_position);
Austin Schuhd78ab542013-03-01 22:22:19 -0800156
157 // The state feedback control loop to talk to for the index.
158 ::std::unique_ptr<StateFeedbackLoop<2, 1, 1>> wrist_loop_;
159
Austin Schuhd78ab542013-03-01 22:22:19 -0800160 // Count of the number of discs that we have collected.
161 uint32_t hopper_disc_count_;
162 uint32_t total_disc_count_;
163
Austin Schuhf8c52252013-03-03 02:25:49 -0800164 enum class Goal {
Austin Schuhd78ab542013-03-01 22:22:19 -0800165 // Hold position, in a low power state.
166 HOLD = 0,
167 // Get ready to load discs by shifting the discs down.
168 READY_LOWER = 1,
169 // Ready the discs, spin up the transfer roller, and accept discs.
170 INTAKE = 2,
171 // Get ready to shoot, and place a disc in the loader.
172 READY_SHOOTER = 3,
173 // Shoot at will.
174 SHOOT = 4
175 };
176
Austin Schuhf8c52252013-03-03 02:25:49 -0800177 // These two enums command and track the loader loading discs into the
178 // shooter.
179 enum class LoaderState {
180 // Open and down, ready to accept a disc.
181 READY,
182 // Closing the grabber.
183 GRABBING,
184 // Grabber closed.
185 GRABBED,
186 // Lifting the disc.
187 LIFTING,
188 // Disc lifted.
189 LIFTED,
190 // Ejecting the disc into the shooter.
191 SHOOTING,
192 // The disc has been shot.
193 SHOOT,
194 // Lowering the loader back down.
195 LOWERING,
196 // The indexer is lowered.
197 LOWERED
198 };
199
200 // TODO(aschuh): If we are grabbed and asked to be ready, now what?
201 // LOG ?
202 enum class LoaderGoal {
203 // Get the loader ready to accept another disc.
204 READY,
205 // Grab a disc now.
206 GRAB,
207 // Lift it up, shoot, and reset.
208 // Waits to shoot until the shooter is stable.
209 // Resets the goal to READY once one disc has been shot.
210 SHOOT_AND_RESET
211 };
212
Austin Schuhd78ab542013-03-01 22:22:19 -0800213 // The current goal
214 Goal safe_goal_;
215
Austin Schuhf8c52252013-03-03 02:25:49 -0800216 // Loader goal, state, and counter.
217 LoaderGoal loader_goal_;
218 LoaderState loader_state_;
219 int loader_countdown_;
220
Austin Schuhd78ab542013-03-01 22:22:19 -0800221 // Current state of the pistons.
222 bool loader_up_;
223 bool disc_clamped_;
224 bool disc_ejected_;
225
Austin Schuhd78ab542013-03-01 22:22:19 -0800226 // The frisbee that is flying through the transfer rollers.
227 Frisbee transfer_frisbee_;
228
Austin Schuhf8c52252013-03-03 02:25:49 -0800229 // Bottom disc detect from the last valid packet for detecting edges.
Austin Schuhd78ab542013-03-01 22:22:19 -0800230 bool last_bottom_disc_detect_;
231
232 // Frisbees are in order such that the newest frisbee is on the front.
233 ::std::deque<Frisbee> frisbees_;
234 // std::array ?
235
Austin Schuhbcdb90c2013-03-03 23:24:58 -0800236 // True if we haven't seen a position before.
237 bool no_prior_position_;
238 // Number of position messages that we have missed in a row.
239 uint32_t missing_position_count_;
240
Austin Schuhd78ab542013-03-01 22:22:19 -0800241 DISALLOW_COPY_AND_ASSIGN(IndexMotor);
242};
243
244} // namespace control_loops
245} // namespace frc971
246
247#endif // FRC971_CONTROL_LOOPS_WRIST_H_