blob: c65459114a580e33e2fd1576bfbffe0d7772808e [file] [log] [blame]
Adam Snaider18f44172016-10-22 15:30:21 -07001#ifndef Y2016_BOT3_CONTROL_LOOPS_INTAKE_INTAKE_H_
2#define Y2016_BOT3_CONTROL_LOOPS_INTAKE_INTAKE_H_
3
4#include <memory>
5
6#include "aos/common/controls/control_loop.h"
7#include "aos/common/util/trapezoid_profile.h"
8#include "frc971/control_loops/state_feedback_loop.h"
9
10#include "frc971/zeroing/zeroing.h"
11#include "y2016_bot3/control_loops/intake/intake.q.h"
12#include "y2016_bot3/control_loops/intake/intake_controls.h"
13
14namespace y2016_bot3 {
15namespace constants {
16static const int kZeroingSampleSize = 200;
17
18// Ratios for our subsystems.
19// TODO(constants): Update these.
20static constexpr double kIntakeEncoderRatio = 18.0 / 72.0 * 15.0 / 48.0;
21
22static constexpr double kIntakePotRatio = 15.0 / 48.0;
23
24// Difference in radians between index pulses.
25static constexpr double kIntakeEncoderIndexDifference =
26 2.0 * M_PI * kIntakeEncoderRatio;
27
28// Subsystem motion ranges, in whatever units that their respective queues say
29// the use.
30// TODO(constants): Update these.
31static constexpr ::frc971::constants::Range kIntakeRange{// Lower hard stop
Campbell Crowley483d6272016-11-05 14:11:34 -070032 -0.4,
Adam Snaider18f44172016-10-22 15:30:21 -070033 // Upper hard stop
Campbell Crowley051b4622016-11-05 15:07:54 -070034 2.90,
Adam Snaider18f44172016-10-22 15:30:21 -070035 // Lower soft stop
Campbell Crowley483d6272016-11-05 14:11:34 -070036 -0.28,
Adam Snaider18f44172016-10-22 15:30:21 -070037 // Uppper soft stop
Campbell Crowley483d6272016-11-05 14:11:34 -070038 2.77};
Adam Snaider18f44172016-10-22 15:30:21 -070039
40struct IntakeZero {
Adam Snaider5b7c1622017-01-04 21:39:34 -080041 static constexpr double pot_offset = 5.462409 + 0.333162;
Tyler Chatowf8f03112017-02-05 14:31:34 -080042 static constexpr ::frc971::constants::PotAndIndexPulseZeroingConstants
43 zeroing{kZeroingSampleSize, kIntakeEncoderIndexDifference,
44 0.148604 - 0.291240, 0.3};
Adam Snaider18f44172016-10-22 15:30:21 -070045};
46} // namespace constants
47namespace control_loops {
48namespace intake {
49namespace testing {
50class IntakeTest_RespectsRange_Test;
51class IntakeTest_DisabledGoalTest_Test;
52class IntakeTest_IntakeZeroingErrorTest_Test;
53class IntakeTest_UpperHardstopStartup_Test;
54class IntakeTest_DisabledWhileZeroingHigh_Test;
55class IntakeTest_DisabledWhileZeroingLow_Test;
56}
57
Adam Snaidera3271fe2016-10-26 21:03:38 -070058// TODO(Adam): Implement this class and delete it from here.
Adam Snaider18f44172016-10-22 15:30:21 -070059class LimitChecker {
Campbell Crowley483d6272016-11-05 14:11:34 -070060 public:
61 LimitChecker(IntakeArm *intake) : intake_(intake) {}
62 void UpdateGoal(double intake_angle_goal);
63
64 private:
65 IntakeArm *intake_;
Adam Snaider18f44172016-10-22 15:30:21 -070066};
67
68class Intake : public ::aos::controls::ControlLoop<control_loops::IntakeQueue> {
69 public:
70 explicit Intake(
71 control_loops::IntakeQueue *my_intake = &control_loops::intake_queue);
72
73 static constexpr double kZeroingVoltage = 6.0;
74 static constexpr double kOperatingVoltage = 12.0;
75
76 // This is the large scale movement tolerance.
77 static constexpr double kLooseTolerance = 0.05;
78
79 // This is the small scale movement tolerance.
80 static constexpr double kTightTolerance = 0.03;
81
82 static constexpr double kIntakeUpAngle = M_PI / 2;
83
84 static constexpr double kIntakeDownAngle = 0.0;
85
86 static constexpr double kIntakeMiddleAngle =
87 (kIntakeUpAngle + kIntakeDownAngle) / 2;
88
89 enum State {
90 // Wait for all the filters to be ready before starting the initialization
91 // process.
92 UNINITIALIZED = 0,
93
94 // We now are ready to decide how to zero. Decide what to do once we are
95 // enabled.
96 DISABLED_INITIALIZED = 1,
97
98 ZERO_LOWER_INTAKE = 2,
99
100 ZERO_LIFT_INTAKE = 3,
101 // Run, but limit power to zeroing voltages.
102 SLOW_RUNNING = 12,
103 // Run with full power.
104 RUNNING = 13,
105 // Internal error caused the intake to abort.
106 ESTOP = 16,
107 };
108
109 bool IsRunning() const {
110 return (state_ == SLOW_RUNNING || state_ == RUNNING);
111 }
112
113 State state() const { return state_; }
114
Adam Snaider18f44172016-10-22 15:30:21 -0700115 protected:
116 void RunIteration(const control_loops::IntakeQueue::Goal *unsafe_goal,
117 const control_loops::IntakeQueue::Position *position,
118 control_loops::IntakeQueue::Output *output,
119 control_loops::IntakeQueue::Status *status) override;
120
121 private:
122 friend class testing::IntakeTest_DisabledGoalTest_Test;
123 friend class testing::IntakeTest_IntakeZeroingErrorTest_Test;
124 friend class testing::IntakeTest_RespectsRange_Test;
125 friend class testing::IntakeTest_UpperHardstopStartup_Test;
126 friend class testing::IntakeTest_DisabledWhileZeroingHigh_Test;
127 friend class testing::IntakeTest_DisabledWhileZeroingLow_Test;
128 IntakeArm intake_;
129
130 State state_ = UNINITIALIZED;
131 State last_state_ = UNINITIALIZED;
132
133 float last_intake_angle_ = 0.0;
134 LimitChecker limit_checker_;
135 // Returns true if the profile has finished, and the joint is within the
136 // specified tolerance.
137 bool IsIntakeNear(double tolerance);
138
139 DISALLOW_COPY_AND_ASSIGN(Intake);
140};
141
Adam Snaider18f44172016-10-22 15:30:21 -0700142} // namespace intake
143} // namespace control_loops
144} // namespace y2016_bot3
145
146#endif // Y2016_BOT3_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_