Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 1 | #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 Schuh | 0055822 | 2013-03-03 14:16:16 -0800 | [diff] [blame^] | 10 | #include "frc971/control_loops/index/index_motor.q.h" |
| 11 | #include "frc971/control_loops/index/index_motor_plant.h" |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 12 | |
| 13 | namespace frc971 { |
| 14 | namespace control_loops { |
| 15 | |
| 16 | class IndexMotor |
| 17 | : public aos::control_loops::ControlLoop<control_loops::IndexLoop> { |
| 18 | public: |
| 19 | explicit IndexMotor( |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 20 | control_loops::IndexLoop *my_index = &control_loops::index_loop); |
| 21 | |
| 22 | static const double kTransferStartPosition; |
| 23 | static const double kIndexStartPosition; |
| 24 | // The distance from where the disc first grabs on the indexer to where it |
| 25 | // just bairly clears the loader. |
| 26 | static const double kIndexFreeLength; |
| 27 | // The distance to where the disc just starts to enter the loader. |
| 28 | static const double kLoaderFreeStopPosition; |
| 29 | |
| 30 | // Distance that the grabber pulls the disc in by. |
| 31 | static const double kGrabberLength; |
| 32 | // Distance to where the grabber takes over. |
| 33 | static const double kGrabberStartPosition; |
| 34 | |
| 35 | // The distance to where the disc hits the back of the loader and is ready to |
| 36 | // lift. |
| 37 | static const double kReadyToLiftPosition; |
| 38 | |
| 39 | static const double kGrabberMovementVelocity; |
| 40 | // TODO(aschuh): This depends on the shooter angle... |
| 41 | // Distance to where the shooter is up and ready to shoot. |
| 42 | static const double kLifterStopPosition; |
| 43 | static const double kLifterMovementVelocity; |
| 44 | |
| 45 | // Distance to where the disc has been launched. |
| 46 | // TODO(aschuh): This depends on the shooter angle... |
| 47 | static const double kEjectorStopPosition; |
| 48 | static const double kEjectorMovementVelocity; |
| 49 | |
| 50 | // Start and stop position of the bottom disc detect sensor in meters. |
| 51 | static const double kBottomDiscDetectStart; |
| 52 | static const double kBottomDiscDetectStop; |
| 53 | |
| 54 | static const double kTopDiscDetectStart; |
| 55 | static const double kTopDiscDetectStop; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 56 | |
| 57 | // Converts the angle of the indexer to the angle of the disc. |
| 58 | static double ConvertIndexToDiscAngle(const double angle); |
| 59 | // Converts the angle of the indexer to the position that the center of the |
| 60 | // disc has traveled. |
| 61 | static double ConvertIndexToDiscPosition(const double angle); |
| 62 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 63 | // Converts the angle of the transfer roller to the position that the center |
| 64 | // of the disc has traveled. |
| 65 | static double ConvertTransferToDiscPosition(const double angle); |
| 66 | |
| 67 | // Converts the distance around the indexer to the position of |
| 68 | // the index roller. |
| 69 | static double ConvertDiscPositionToIndex(const double position); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 70 | // Converts the angle around the indexer to the position of the index roller. |
| 71 | static double ConvertDiscAngleToIndex(const double angle); |
| 72 | // Converts the angle around the indexer to the position of the disc in the |
| 73 | // indexer. |
| 74 | static double ConvertDiscAngleToDiscPosition(const double angle); |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 75 | // Converts the distance around the indexer to the angle of the disc around |
| 76 | // the indexer. |
| 77 | static double ConvertDiscPositionToDiscAngle(const double position); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 78 | |
| 79 | // Disc radius in meters. |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 80 | static const double kDiscRadius; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 81 | // Roller radius in meters. |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 82 | static const double kRollerRadius; |
| 83 | // Transfer roller radius in meters. |
| 84 | static const double kTransferRollerRadius; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 85 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 86 | // Time that it takes to grab the disc in cycles. |
| 87 | static const int kGrabbingDelay; |
| 88 | // Time that it takes to lift the loader in cycles. |
| 89 | static const int kLiftingDelay; |
| 90 | // Time that it takes to shoot the disc in cycles. |
| 91 | static const int kShootingDelay; |
| 92 | // Time that it takes to lower the loader in cycles. |
| 93 | static const int kLoweringDelay; |
| 94 | |
| 95 | // Object representing a Frisbee tracked by the indexer. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 96 | class Frisbee { |
| 97 | public: |
| 98 | Frisbee() |
| 99 | : bottom_posedge_time_(0, 0), |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 100 | bottom_negedge_time_(0, 0) { |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 101 | Reset(); |
| 102 | } |
| 103 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 104 | // Resets a Frisbee so it can be reused. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 105 | void Reset() { |
| 106 | bottom_posedge_time_ = ::aos::time::Time(0, 0); |
| 107 | bottom_negedge_time_ = ::aos::time::Time(0, 0); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 108 | has_been_indexed_ = false; |
| 109 | index_start_position_ = 0.0; |
| 110 | } |
| 111 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 112 | // Returns true if the position is valid. |
| 113 | bool has_position() const { |
| 114 | return has_been_indexed_; |
| 115 | } |
| 116 | |
| 117 | // Returns the most up to date and accurate position that we have for the |
| 118 | // disc. This is the indexer position that the disc grabbed at. |
| 119 | double position() const { |
| 120 | return index_start_position_; |
| 121 | } |
| 122 | |
| 123 | // Posedge and negedge disc times. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 124 | ::aos::time::Time bottom_posedge_time_; |
| 125 | ::aos::time::Time bottom_negedge_time_; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 126 | |
| 127 | // True if the disc has a valid index position. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 128 | bool has_been_indexed_; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 129 | // Location of the index when the disc first contacted it. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 130 | double index_start_position_; |
| 131 | }; |
| 132 | |
| 133 | protected: |
| 134 | virtual void RunIteration( |
| 135 | const control_loops::IndexLoop::Goal *goal, |
| 136 | const control_loops::IndexLoop::Position *position, |
| 137 | control_loops::IndexLoop::Output *output, |
| 138 | control_loops::IndexLoop::Status *status); |
| 139 | |
| 140 | private: |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 141 | // Sets disc_position to the minimum or maximum disc position. |
| 142 | // Returns true if there were discs, and false if there weren't. |
| 143 | // On false, disc_position is left unmodified. |
| 144 | bool MinDiscPosition(double *disc_position); |
| 145 | bool MaxDiscPosition(double *disc_position); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 146 | |
| 147 | // The state feedback control loop to talk to for the index. |
| 148 | ::std::unique_ptr<StateFeedbackLoop<2, 1, 1>> wrist_loop_; |
| 149 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 150 | // Count of the number of discs that we have collected. |
| 151 | uint32_t hopper_disc_count_; |
| 152 | uint32_t total_disc_count_; |
| 153 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 154 | enum class Goal { |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 155 | // Hold position, in a low power state. |
| 156 | HOLD = 0, |
| 157 | // Get ready to load discs by shifting the discs down. |
| 158 | READY_LOWER = 1, |
| 159 | // Ready the discs, spin up the transfer roller, and accept discs. |
| 160 | INTAKE = 2, |
| 161 | // Get ready to shoot, and place a disc in the loader. |
| 162 | READY_SHOOTER = 3, |
| 163 | // Shoot at will. |
| 164 | SHOOT = 4 |
| 165 | }; |
| 166 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 167 | // These two enums command and track the loader loading discs into the |
| 168 | // shooter. |
| 169 | enum class LoaderState { |
| 170 | // Open and down, ready to accept a disc. |
| 171 | READY, |
| 172 | // Closing the grabber. |
| 173 | GRABBING, |
| 174 | // Grabber closed. |
| 175 | GRABBED, |
| 176 | // Lifting the disc. |
| 177 | LIFTING, |
| 178 | // Disc lifted. |
| 179 | LIFTED, |
| 180 | // Ejecting the disc into the shooter. |
| 181 | SHOOTING, |
| 182 | // The disc has been shot. |
| 183 | SHOOT, |
| 184 | // Lowering the loader back down. |
| 185 | LOWERING, |
| 186 | // The indexer is lowered. |
| 187 | LOWERED |
| 188 | }; |
| 189 | |
| 190 | // TODO(aschuh): If we are grabbed and asked to be ready, now what? |
| 191 | // LOG ? |
| 192 | enum class LoaderGoal { |
| 193 | // Get the loader ready to accept another disc. |
| 194 | READY, |
| 195 | // Grab a disc now. |
| 196 | GRAB, |
| 197 | // Lift it up, shoot, and reset. |
| 198 | // Waits to shoot until the shooter is stable. |
| 199 | // Resets the goal to READY once one disc has been shot. |
| 200 | SHOOT_AND_RESET |
| 201 | }; |
| 202 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 203 | // The current goal |
| 204 | Goal safe_goal_; |
| 205 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 206 | // Loader goal, state, and counter. |
| 207 | LoaderGoal loader_goal_; |
| 208 | LoaderState loader_state_; |
| 209 | int loader_countdown_; |
| 210 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 211 | // Current state of the pistons. |
| 212 | bool loader_up_; |
| 213 | bool disc_clamped_; |
| 214 | bool disc_ejected_; |
| 215 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 216 | // The frisbee that is flying through the transfer rollers. |
| 217 | Frisbee transfer_frisbee_; |
| 218 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 219 | // Bottom disc detect from the last valid packet for detecting edges. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 220 | bool last_bottom_disc_detect_; |
| 221 | |
| 222 | // Frisbees are in order such that the newest frisbee is on the front. |
| 223 | ::std::deque<Frisbee> frisbees_; |
| 224 | // std::array ? |
| 225 | |
| 226 | DISALLOW_COPY_AND_ASSIGN(IndexMotor); |
| 227 | }; |
| 228 | |
| 229 | } // namespace control_loops |
| 230 | } // namespace frc971 |
| 231 | |
| 232 | #endif // FRC971_CONTROL_LOOPS_WRIST_H_ |