Brian Silverman | 43bb73e | 2013-03-17 13:39:47 -0700 | [diff] [blame] | 1 | #ifndef FRC971_CONTROL_LOOPS_INDEX_INDEX_H_ |
| 2 | #define FRC971_CONTROL_LOOPS_INDEX_INDEX_H_ |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 3 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 4 | #include <deque> |
Brian Silverman | 26683e2 | 2013-03-16 14:12:16 -0700 | [diff] [blame] | 5 | #include "aos/common/libstdc++/memory" |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 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 { |
Austin Schuh | bcdb90c | 2013-03-03 23:24:58 -0800 | [diff] [blame] | 15 | namespace testing { |
| 16 | class IndexTest_InvalidStateTest_Test; |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 17 | class IndexTest_LostDisc_Test; |
Austin Schuh | bcdb90c | 2013-03-03 23:24:58 -0800 | [diff] [blame] | 18 | } |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 19 | |
Austin Schuh | 723770b | 2013-03-10 13:26:20 -0700 | [diff] [blame] | 20 | // This class represents a region of space. |
| 21 | class Region { |
| 22 | public: |
| 23 | Region () : upper_bound_(0.0), lower_bound_(0.0) {} |
| 24 | |
| 25 | // Restarts the region tracking by starting over with a 0 width region with |
| 26 | // the bounds at [edge, edge]. |
| 27 | void Restart(double edge) { |
| 28 | upper_bound_ = edge; |
| 29 | lower_bound_ = edge; |
| 30 | } |
| 31 | |
| 32 | // Expands the region to include the new point. |
| 33 | void Expand(double new_point) { |
| 34 | if (new_point > upper_bound_) { |
| 35 | upper_bound_ = new_point; |
| 36 | } else if (new_point < lower_bound_) { |
| 37 | lower_bound_ = new_point; |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | // Returns the width of the region. |
| 42 | double width() const { return upper_bound_ - lower_bound_; } |
| 43 | // Returns the upper and lower bounds. |
| 44 | double upper_bound() const { return upper_bound_; } |
| 45 | double lower_bound() const { return lower_bound_; } |
| 46 | |
| 47 | private: |
| 48 | // Upper bound of the region. |
| 49 | double upper_bound_; |
| 50 | // Lower bound of the region. |
| 51 | double lower_bound_; |
| 52 | }; |
| 53 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 54 | class IndexMotor |
| 55 | : public aos::control_loops::ControlLoop<control_loops::IndexLoop> { |
| 56 | public: |
| 57 | explicit IndexMotor( |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 58 | control_loops::IndexLoop *my_index = &control_loops::index_loop); |
| 59 | |
| 60 | static const double kTransferStartPosition; |
| 61 | static const double kIndexStartPosition; |
| 62 | // The distance from where the disc first grabs on the indexer to where it |
| 63 | // just bairly clears the loader. |
| 64 | static const double kIndexFreeLength; |
| 65 | // The distance to where the disc just starts to enter the loader. |
| 66 | static const double kLoaderFreeStopPosition; |
Austin Schuh | 1b864a1 | 2013-03-07 00:46:50 -0800 | [diff] [blame] | 67 | // The distance to where the next disc gets positioned while the current disc |
| 68 | // is shooting. |
| 69 | static const double kReadyToPreload; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 70 | |
| 71 | // Distance that the grabber pulls the disc in by. |
| 72 | static const double kGrabberLength; |
| 73 | // Distance to where the grabber takes over. |
| 74 | static const double kGrabberStartPosition; |
| 75 | |
| 76 | // The distance to where the disc hits the back of the loader and is ready to |
| 77 | // lift. |
| 78 | static const double kReadyToLiftPosition; |
| 79 | |
| 80 | static const double kGrabberMovementVelocity; |
| 81 | // TODO(aschuh): This depends on the shooter angle... |
| 82 | // Distance to where the shooter is up and ready to shoot. |
| 83 | static const double kLifterStopPosition; |
| 84 | static const double kLifterMovementVelocity; |
| 85 | |
| 86 | // Distance to where the disc has been launched. |
| 87 | // TODO(aschuh): This depends on the shooter angle... |
| 88 | static const double kEjectorStopPosition; |
| 89 | static const double kEjectorMovementVelocity; |
| 90 | |
| 91 | // Start and stop position of the bottom disc detect sensor in meters. |
| 92 | static const double kBottomDiscDetectStart; |
| 93 | static const double kBottomDiscDetectStop; |
Austin Schuh | 6328daf | 2013-03-05 00:53:15 -0800 | [diff] [blame] | 94 | // Delay between the negedge of the disc detect and when it engages on the |
| 95 | // indexer. |
| 96 | static const double kBottomDiscIndexDelay; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 97 | |
Austin Schuh | d3d0fbf | 2013-03-14 00:37:00 -0700 | [diff] [blame] | 98 | // Time after seeing the fourth disc that we need to wait before turning the |
| 99 | // transfer roller off. |
| 100 | static const ::aos::time::Time kTransferOffDelay; |
| 101 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 102 | static const double kTopDiscDetectStart; |
| 103 | static const double kTopDiscDetectStop; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 104 | |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 105 | // Minimum distance between 2 frisbees as seen by the top disc detect sensor. |
| 106 | static const double kTopDiscDetectMinSeperation; |
| 107 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 108 | // Converts the angle of the indexer to the angle of the disc. |
| 109 | static double ConvertIndexToDiscAngle(const double angle); |
| 110 | // Converts the angle of the indexer to the position that the center of the |
| 111 | // disc has traveled. |
| 112 | static double ConvertIndexToDiscPosition(const double angle); |
| 113 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 114 | // Converts the angle of the transfer roller to the position that the center |
| 115 | // of the disc has traveled. |
| 116 | static double ConvertTransferToDiscPosition(const double angle); |
| 117 | |
| 118 | // Converts the distance around the indexer to the position of |
| 119 | // the index roller. |
| 120 | static double ConvertDiscPositionToIndex(const double position); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 121 | // Converts the angle around the indexer to the position of the index roller. |
| 122 | static double ConvertDiscAngleToIndex(const double angle); |
| 123 | // Converts the angle around the indexer to the position of the disc in the |
| 124 | // indexer. |
| 125 | static double ConvertDiscAngleToDiscPosition(const double angle); |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 126 | // Converts the distance around the indexer to the angle of the disc around |
| 127 | // the indexer. |
| 128 | static double ConvertDiscPositionToDiscAngle(const double position); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 129 | |
| 130 | // Disc radius in meters. |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 131 | static const double kDiscRadius; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 132 | // Roller radius in meters. |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 133 | static const double kRollerRadius; |
| 134 | // Transfer roller radius in meters. |
| 135 | static const double kTransferRollerRadius; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 136 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 137 | // Time that it takes to grab the disc in cycles. |
| 138 | static const int kGrabbingDelay; |
Brian Silverman | 25329e6 | 2013-09-21 23:52:10 -0700 | [diff] [blame] | 139 | // Time that it takes to finish lifting the loader after the sensor is |
| 140 | // triggered in cycles. |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 141 | static const int kLiftingDelay; |
Brian Silverman | c540ab8 | 2013-09-22 00:00:28 -0700 | [diff] [blame^] | 142 | // Time until we give up lifting and move on in cycles. |
| 143 | static const int kLiftingTimeout; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 144 | // Time that it takes to shoot the disc in cycles. |
| 145 | static const int kShootingDelay; |
| 146 | // Time that it takes to lower the loader in cycles. |
| 147 | static const int kLoweringDelay; |
| 148 | |
| 149 | // Object representing a Frisbee tracked by the indexer. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 150 | class Frisbee { |
| 151 | public: |
| 152 | Frisbee() |
| 153 | : bottom_posedge_time_(0, 0), |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 154 | bottom_negedge_time_(0, 0) { |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 155 | Reset(); |
| 156 | } |
| 157 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 158 | // Resets a Frisbee so it can be reused. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 159 | void Reset() { |
| 160 | bottom_posedge_time_ = ::aos::time::Time(0, 0); |
| 161 | bottom_negedge_time_ = ::aos::time::Time(0, 0); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 162 | has_been_indexed_ = false; |
| 163 | index_start_position_ = 0.0; |
| 164 | } |
| 165 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 166 | // Returns true if the position is valid. |
| 167 | bool has_position() const { |
| 168 | return has_been_indexed_; |
| 169 | } |
| 170 | |
| 171 | // Returns the most up to date and accurate position that we have for the |
| 172 | // disc. This is the indexer position that the disc grabbed at. |
| 173 | double position() const { |
| 174 | return index_start_position_; |
| 175 | } |
| 176 | |
Austin Schuh | 1b864a1 | 2013-03-07 00:46:50 -0800 | [diff] [blame] | 177 | // Returns the absolute position of the disc in meters in the hopper given |
| 178 | // that the indexer is at the provided position. |
| 179 | double absolute_position(const double index_position) const { |
| 180 | return IndexMotor::ConvertIndexToDiscPosition( |
| 181 | index_position - index_start_position_) + |
| 182 | IndexMotor::kIndexStartPosition; |
| 183 | } |
| 184 | |
Austin Schuh | bcdb90c | 2013-03-03 23:24:58 -0800 | [diff] [blame] | 185 | // Shifts the disc down the indexer by the provided offset. This is to |
| 186 | // handle when the cRIO reboots. |
| 187 | void OffsetDisc(double offset) { |
| 188 | index_start_position_ += offset; |
| 189 | } |
| 190 | |
Austin Schuh | 825bde9 | 2013-03-06 00:16:46 -0800 | [diff] [blame] | 191 | // Potentially offsets the position with the knowledge that no discs are |
| 192 | // currently blocking the top sensor. This knowledge can be used to move |
| 193 | // this disc if it is believed to be blocking the top sensor. |
Austin Schuh | dff24e2 | 2013-03-06 00:41:21 -0800 | [diff] [blame] | 194 | // Returns the amount that the disc moved due to this observation. |
Austin Schuh | 6b1ad2f | 2013-03-11 23:23:00 -0700 | [diff] [blame] | 195 | double ObserveNoTopDiscSensor(double index_position); |
Austin Schuh | 825bde9 | 2013-03-06 00:16:46 -0800 | [diff] [blame] | 196 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 197 | // Posedge and negedge disc times. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 198 | ::aos::time::Time bottom_posedge_time_; |
| 199 | ::aos::time::Time bottom_negedge_time_; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 200 | |
| 201 | // True if the disc has a valid index position. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 202 | bool has_been_indexed_; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 203 | // Location of the index when the disc first contacted it. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 204 | double index_start_position_; |
| 205 | }; |
| 206 | |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 207 | // Returns where the indexer thinks the frisbees are. |
Austin Schuh | 1b864a1 | 2013-03-07 00:46:50 -0800 | [diff] [blame] | 208 | const ::std::deque<Frisbee> &frisbees() const { return frisbees_; } |
| 209 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 210 | protected: |
| 211 | virtual void RunIteration( |
| 212 | const control_loops::IndexLoop::Goal *goal, |
| 213 | const control_loops::IndexLoop::Position *position, |
| 214 | control_loops::IndexLoop::Output *output, |
| 215 | control_loops::IndexLoop::Status *status); |
| 216 | |
| 217 | private: |
Austin Schuh | bcdb90c | 2013-03-03 23:24:58 -0800 | [diff] [blame] | 218 | friend class testing::IndexTest_InvalidStateTest_Test; |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 219 | friend class testing::IndexTest_LostDisc_Test; |
Austin Schuh | 9348583 | 2013-03-04 00:01:34 -0800 | [diff] [blame] | 220 | |
| 221 | // This class implements the CapU function correctly given all the extra |
| 222 | // information that we know about from the wrist motor. |
| 223 | class IndexStateFeedbackLoop : public StateFeedbackLoop<2, 1, 1> { |
| 224 | public: |
| 225 | IndexStateFeedbackLoop(StateFeedbackLoop<2, 1, 1> loop) |
| 226 | : StateFeedbackLoop<2, 1, 1>(loop), |
| 227 | low_voltage_count_(0) { |
| 228 | } |
| 229 | |
| 230 | // Voltage below which the indexer won't move with a disc in it. |
| 231 | static const double kMinMotionVoltage; |
| 232 | // Maximum number of cycles to apply a low voltage to the motor. |
| 233 | static const double kNoMotionCuttoffCount; |
| 234 | |
| 235 | // Caps U, but disables the motor after a number of cycles of inactivity. |
| 236 | virtual void CapU(); |
| 237 | private: |
| 238 | // Number of cycles that we have seen a small voltage being applied. |
| 239 | uint32_t low_voltage_count_; |
| 240 | }; |
| 241 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 242 | // Sets disc_position to the minimum or maximum disc position. |
Austin Schuh | 1b864a1 | 2013-03-07 00:46:50 -0800 | [diff] [blame] | 243 | // Sets found_disc to point to the frisbee that was found, and ignores it if |
| 244 | // found_disc is NULL. |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 245 | // Returns true if there were discs, and false if there weren't. |
| 246 | // On false, disc_position is left unmodified. |
Austin Schuh | 1b864a1 | 2013-03-07 00:46:50 -0800 | [diff] [blame] | 247 | bool MinDiscPosition(double *disc_position, Frisbee **found_disc); |
| 248 | bool MaxDiscPosition(double *disc_position, Frisbee **found_disc); |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 249 | |
| 250 | // The state feedback control loop to talk to for the index. |
Austin Schuh | 9348583 | 2013-03-04 00:01:34 -0800 | [diff] [blame] | 251 | ::std::unique_ptr<IndexStateFeedbackLoop> wrist_loop_; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 252 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 253 | // Count of the number of discs that we have collected. |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 254 | int32_t hopper_disc_count_; |
| 255 | int32_t total_disc_count_; |
Austin Schuh | 70be1ba | 2013-03-10 13:37:17 -0700 | [diff] [blame] | 256 | int32_t shot_disc_count_; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 257 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 258 | enum class Goal { |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 259 | // Hold position, in a low power state. |
| 260 | HOLD = 0, |
| 261 | // Get ready to load discs by shifting the discs down. |
| 262 | READY_LOWER = 1, |
| 263 | // Ready the discs, spin up the transfer roller, and accept discs. |
| 264 | INTAKE = 2, |
| 265 | // Get ready to shoot, and place a disc in the loader. |
| 266 | READY_SHOOTER = 3, |
| 267 | // Shoot at will. |
Brian Silverman | b8d389f | 2013-03-19 22:54:06 -0700 | [diff] [blame] | 268 | SHOOT = 4, |
| 269 | // Reinitialize. |
| 270 | REINITIALIZE = 5 |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 271 | }; |
| 272 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 273 | // These two enums command and track the loader loading discs into the |
| 274 | // shooter. |
| 275 | enum class LoaderState { |
| 276 | // Open and down, ready to accept a disc. |
| 277 | READY, |
| 278 | // Closing the grabber. |
| 279 | GRABBING, |
| 280 | // Grabber closed. |
| 281 | GRABBED, |
| 282 | // Lifting the disc. |
| 283 | LIFTING, |
| 284 | // Disc lifted. |
| 285 | LIFTED, |
| 286 | // Ejecting the disc into the shooter. |
| 287 | SHOOTING, |
| 288 | // The disc has been shot. |
| 289 | SHOOT, |
| 290 | // Lowering the loader back down. |
| 291 | LOWERING, |
| 292 | // The indexer is lowered. |
| 293 | LOWERED |
| 294 | }; |
| 295 | |
| 296 | // TODO(aschuh): If we are grabbed and asked to be ready, now what? |
| 297 | // LOG ? |
| 298 | enum class LoaderGoal { |
| 299 | // Get the loader ready to accept another disc. |
| 300 | READY, |
| 301 | // Grab a disc now. |
| 302 | GRAB, |
| 303 | // Lift it up, shoot, and reset. |
| 304 | // Waits to shoot until the shooter is stable. |
| 305 | // Resets the goal to READY once one disc has been shot. |
| 306 | SHOOT_AND_RESET |
| 307 | }; |
| 308 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 309 | // The current goal |
| 310 | Goal safe_goal_; |
| 311 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 312 | // Loader goal, state, and counter. |
| 313 | LoaderGoal loader_goal_; |
| 314 | LoaderState loader_state_; |
Brian Silverman | c540ab8 | 2013-09-22 00:00:28 -0700 | [diff] [blame^] | 315 | int loader_countdown_, loader_timeout_; |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 316 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 317 | // Current state of the pistons. |
| 318 | bool loader_up_; |
| 319 | bool disc_clamped_; |
| 320 | bool disc_ejected_; |
| 321 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 322 | // The frisbee that is flying through the transfer rollers. |
| 323 | Frisbee transfer_frisbee_; |
| 324 | |
Austin Schuh | f8c5225 | 2013-03-03 02:25:49 -0800 | [diff] [blame] | 325 | // Bottom disc detect from the last valid packet for detecting edges. |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 326 | bool last_bottom_disc_detect_; |
Austin Schuh | 825bde9 | 2013-03-06 00:16:46 -0800 | [diff] [blame] | 327 | bool last_top_disc_detect_; |
Austin Schuh | 6328daf | 2013-03-05 00:53:15 -0800 | [diff] [blame] | 328 | int32_t last_bottom_disc_posedge_count_; |
| 329 | int32_t last_bottom_disc_negedge_count_; |
| 330 | int32_t last_bottom_disc_negedge_wait_count_; |
Austin Schuh | 825bde9 | 2013-03-06 00:16:46 -0800 | [diff] [blame] | 331 | int32_t last_top_disc_posedge_count_; |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 332 | int32_t last_top_disc_negedge_count_; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 333 | |
| 334 | // Frisbees are in order such that the newest frisbee is on the front. |
| 335 | ::std::deque<Frisbee> frisbees_; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 336 | |
Austin Schuh | bcdb90c | 2013-03-03 23:24:58 -0800 | [diff] [blame] | 337 | // True if we haven't seen a position before. |
| 338 | bool no_prior_position_; |
| 339 | // Number of position messages that we have missed in a row. |
| 340 | uint32_t missing_position_count_; |
| 341 | |
Austin Schuh | 723770b | 2013-03-10 13:26:20 -0700 | [diff] [blame] | 342 | // The no-disc regions for both the bottom and top beam break sensors. |
| 343 | Region upper_open_region_; |
| 344 | Region lower_open_region_; |
Austin Schuh | 7c0e2aa | 2013-03-09 02:01:16 -0800 | [diff] [blame] | 345 | |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 346 | DISALLOW_COPY_AND_ASSIGN(IndexMotor); |
| 347 | }; |
Austin Schuh | d78ab54 | 2013-03-01 22:22:19 -0800 | [diff] [blame] | 348 | } // namespace control_loops |
| 349 | } // namespace frc971 |
| 350 | |
Brian Silverman | 43bb73e | 2013-03-17 13:39:47 -0700 | [diff] [blame] | 351 | #endif // FRC971_CONTROL_LOOPS_INDEX_INDEX_H_ |