blob: 854b29ce710d7954baa53d7c79b6d3d6a3dc8e31 [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;
Austin Schuh6328daf2013-03-05 00:53:15 -080056 // Delay between the negedge of the disc detect and when it engages on the
57 // indexer.
58 static const double kBottomDiscIndexDelay;
Austin Schuhf8c52252013-03-03 02:25:49 -080059
60 static const double kTopDiscDetectStart;
61 static const double kTopDiscDetectStop;
Austin Schuhd78ab542013-03-01 22:22:19 -080062
63 // Converts the angle of the indexer to the angle of the disc.
64 static double ConvertIndexToDiscAngle(const double angle);
65 // Converts the angle of the indexer to the position that the center of the
66 // disc has traveled.
67 static double ConvertIndexToDiscPosition(const double angle);
68
Austin Schuhf8c52252013-03-03 02:25:49 -080069 // Converts the angle of the transfer roller to the position that the center
70 // of the disc has traveled.
71 static double ConvertTransferToDiscPosition(const double angle);
72
73 // Converts the distance around the indexer to the position of
74 // the index roller.
75 static double ConvertDiscPositionToIndex(const double position);
Austin Schuhd78ab542013-03-01 22:22:19 -080076 // Converts the angle around the indexer to the position of the index roller.
77 static double ConvertDiscAngleToIndex(const double angle);
78 // Converts the angle around the indexer to the position of the disc in the
79 // indexer.
80 static double ConvertDiscAngleToDiscPosition(const double angle);
Austin Schuhf8c52252013-03-03 02:25:49 -080081 // Converts the distance around the indexer to the angle of the disc around
82 // the indexer.
83 static double ConvertDiscPositionToDiscAngle(const double position);
Austin Schuhd78ab542013-03-01 22:22:19 -080084
85 // Disc radius in meters.
Austin Schuhf8c52252013-03-03 02:25:49 -080086 static const double kDiscRadius;
Austin Schuhd78ab542013-03-01 22:22:19 -080087 // Roller radius in meters.
Austin Schuhf8c52252013-03-03 02:25:49 -080088 static const double kRollerRadius;
89 // Transfer roller radius in meters.
90 static const double kTransferRollerRadius;
Austin Schuhd78ab542013-03-01 22:22:19 -080091
Austin Schuhf8c52252013-03-03 02:25:49 -080092 // Time that it takes to grab the disc in cycles.
93 static const int kGrabbingDelay;
94 // Time that it takes to lift the loader in cycles.
95 static const int kLiftingDelay;
96 // Time that it takes to shoot the disc in cycles.
97 static const int kShootingDelay;
98 // Time that it takes to lower the loader in cycles.
99 static const int kLoweringDelay;
100
101 // Object representing a Frisbee tracked by the indexer.
Austin Schuhd78ab542013-03-01 22:22:19 -0800102 class Frisbee {
103 public:
104 Frisbee()
105 : bottom_posedge_time_(0, 0),
Austin Schuhf8c52252013-03-03 02:25:49 -0800106 bottom_negedge_time_(0, 0) {
Austin Schuhd78ab542013-03-01 22:22:19 -0800107 Reset();
108 }
109
Austin Schuhf8c52252013-03-03 02:25:49 -0800110 // Resets a Frisbee so it can be reused.
Austin Schuhd78ab542013-03-01 22:22:19 -0800111 void Reset() {
112 bottom_posedge_time_ = ::aos::time::Time(0, 0);
113 bottom_negedge_time_ = ::aos::time::Time(0, 0);
Austin Schuhd78ab542013-03-01 22:22:19 -0800114 has_been_indexed_ = false;
115 index_start_position_ = 0.0;
116 }
117
Austin Schuhf8c52252013-03-03 02:25:49 -0800118 // Returns true if the position is valid.
119 bool has_position() const {
120 return has_been_indexed_;
121 }
122
123 // Returns the most up to date and accurate position that we have for the
124 // disc. This is the indexer position that the disc grabbed at.
125 double position() const {
126 return index_start_position_;
127 }
128
Austin Schuhbcdb90c2013-03-03 23:24:58 -0800129 // Shifts the disc down the indexer by the provided offset. This is to
130 // handle when the cRIO reboots.
131 void OffsetDisc(double offset) {
132 index_start_position_ += offset;
133 }
134
Austin Schuh825bde92013-03-06 00:16:46 -0800135 // Potentially offsets the position with the knowledge that no discs are
136 // currently blocking the top sensor. This knowledge can be used to move
137 // this disc if it is believed to be blocking the top sensor.
Austin Schuhdff24e22013-03-06 00:41:21 -0800138 // Returns the amount that the disc moved due to this observation.
139 double ObserveNoTopDiscSensor(double index_position, double index_velocity);
Austin Schuh825bde92013-03-06 00:16:46 -0800140
Austin Schuhf8c52252013-03-03 02:25:49 -0800141 // Posedge and negedge disc times.
Austin Schuhd78ab542013-03-01 22:22:19 -0800142 ::aos::time::Time bottom_posedge_time_;
143 ::aos::time::Time bottom_negedge_time_;
Austin Schuhf8c52252013-03-03 02:25:49 -0800144
145 // True if the disc has a valid index position.
Austin Schuhd78ab542013-03-01 22:22:19 -0800146 bool has_been_indexed_;
Austin Schuhf8c52252013-03-03 02:25:49 -0800147 // Location of the index when the disc first contacted it.
Austin Schuhd78ab542013-03-01 22:22:19 -0800148 double index_start_position_;
149 };
150
151 protected:
152 virtual void RunIteration(
153 const control_loops::IndexLoop::Goal *goal,
154 const control_loops::IndexLoop::Position *position,
155 control_loops::IndexLoop::Output *output,
156 control_loops::IndexLoop::Status *status);
157
158 private:
Austin Schuhbcdb90c2013-03-03 23:24:58 -0800159 friend class testing::IndexTest_InvalidStateTest_Test;
Austin Schuh93485832013-03-04 00:01:34 -0800160
161 // This class implements the CapU function correctly given all the extra
162 // information that we know about from the wrist motor.
163 class IndexStateFeedbackLoop : public StateFeedbackLoop<2, 1, 1> {
164 public:
165 IndexStateFeedbackLoop(StateFeedbackLoop<2, 1, 1> loop)
166 : StateFeedbackLoop<2, 1, 1>(loop),
167 low_voltage_count_(0) {
168 }
169
170 // Voltage below which the indexer won't move with a disc in it.
171 static const double kMinMotionVoltage;
172 // Maximum number of cycles to apply a low voltage to the motor.
173 static const double kNoMotionCuttoffCount;
174
175 // Caps U, but disables the motor after a number of cycles of inactivity.
176 virtual void CapU();
177 private:
178 // Number of cycles that we have seen a small voltage being applied.
179 uint32_t low_voltage_count_;
180 };
181
Austin Schuhf8c52252013-03-03 02:25:49 -0800182 // Sets disc_position to the minimum or maximum disc position.
183 // Returns true if there were discs, and false if there weren't.
184 // On false, disc_position is left unmodified.
185 bool MinDiscPosition(double *disc_position);
186 bool MaxDiscPosition(double *disc_position);
Austin Schuhd78ab542013-03-01 22:22:19 -0800187
188 // The state feedback control loop to talk to for the index.
Austin Schuh93485832013-03-04 00:01:34 -0800189 ::std::unique_ptr<IndexStateFeedbackLoop> wrist_loop_;
Austin Schuhd78ab542013-03-01 22:22:19 -0800190
Austin Schuhd78ab542013-03-01 22:22:19 -0800191 // Count of the number of discs that we have collected.
192 uint32_t hopper_disc_count_;
193 uint32_t total_disc_count_;
194
Austin Schuhf8c52252013-03-03 02:25:49 -0800195 enum class Goal {
Austin Schuhd78ab542013-03-01 22:22:19 -0800196 // Hold position, in a low power state.
197 HOLD = 0,
198 // Get ready to load discs by shifting the discs down.
199 READY_LOWER = 1,
200 // Ready the discs, spin up the transfer roller, and accept discs.
201 INTAKE = 2,
202 // Get ready to shoot, and place a disc in the loader.
203 READY_SHOOTER = 3,
204 // Shoot at will.
205 SHOOT = 4
206 };
207
Austin Schuhf8c52252013-03-03 02:25:49 -0800208 // These two enums command and track the loader loading discs into the
209 // shooter.
210 enum class LoaderState {
211 // Open and down, ready to accept a disc.
212 READY,
213 // Closing the grabber.
214 GRABBING,
215 // Grabber closed.
216 GRABBED,
217 // Lifting the disc.
218 LIFTING,
219 // Disc lifted.
220 LIFTED,
221 // Ejecting the disc into the shooter.
222 SHOOTING,
223 // The disc has been shot.
224 SHOOT,
225 // Lowering the loader back down.
226 LOWERING,
227 // The indexer is lowered.
228 LOWERED
229 };
230
231 // TODO(aschuh): If we are grabbed and asked to be ready, now what?
232 // LOG ?
233 enum class LoaderGoal {
234 // Get the loader ready to accept another disc.
235 READY,
236 // Grab a disc now.
237 GRAB,
238 // Lift it up, shoot, and reset.
239 // Waits to shoot until the shooter is stable.
240 // Resets the goal to READY once one disc has been shot.
241 SHOOT_AND_RESET
242 };
243
Austin Schuhd78ab542013-03-01 22:22:19 -0800244 // The current goal
245 Goal safe_goal_;
246
Austin Schuhf8c52252013-03-03 02:25:49 -0800247 // Loader goal, state, and counter.
248 LoaderGoal loader_goal_;
249 LoaderState loader_state_;
250 int loader_countdown_;
251
Austin Schuhd78ab542013-03-01 22:22:19 -0800252 // Current state of the pistons.
253 bool loader_up_;
254 bool disc_clamped_;
255 bool disc_ejected_;
256
Austin Schuhd78ab542013-03-01 22:22:19 -0800257 // The frisbee that is flying through the transfer rollers.
258 Frisbee transfer_frisbee_;
259
Austin Schuhf8c52252013-03-03 02:25:49 -0800260 // Bottom disc detect from the last valid packet for detecting edges.
Austin Schuhd78ab542013-03-01 22:22:19 -0800261 bool last_bottom_disc_detect_;
Austin Schuh825bde92013-03-06 00:16:46 -0800262 bool last_top_disc_detect_;
Austin Schuh6328daf2013-03-05 00:53:15 -0800263 int32_t last_bottom_disc_posedge_count_;
264 int32_t last_bottom_disc_negedge_count_;
265 int32_t last_bottom_disc_negedge_wait_count_;
Austin Schuh825bde92013-03-06 00:16:46 -0800266 int32_t last_top_disc_posedge_count_;
Austin Schuhd78ab542013-03-01 22:22:19 -0800267
268 // Frisbees are in order such that the newest frisbee is on the front.
269 ::std::deque<Frisbee> frisbees_;
270 // std::array ?
271
Austin Schuhbcdb90c2013-03-03 23:24:58 -0800272 // True if we haven't seen a position before.
273 bool no_prior_position_;
274 // Number of position messages that we have missed in a row.
275 uint32_t missing_position_count_;
276
Austin Schuhd78ab542013-03-01 22:22:19 -0800277 DISALLOW_COPY_AND_ASSIGN(IndexMotor);
278};
279
280} // namespace control_loops
281} // namespace frc971
282
283#endif // FRC971_CONTROL_LOOPS_WRIST_H_