blob: fed17ab7486066f406960d146a61aba23da2f217 [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
32 -0.5,
33 // Upper hard stop
34 2.90,
35 // Lower soft stop
36 -0.300,
37 // Uppper soft stop
38 2.725};
39
40struct IntakeZero {
41 double pot_offset = 0.0;
42 ::frc971::constants::ZeroingConstants zeroing{
43 kZeroingSampleSize, kIntakeEncoderIndexDifference, 0.0, 0.3};
44};
45} // namespace constants
46namespace control_loops {
47namespace intake {
48namespace testing {
49class IntakeTest_RespectsRange_Test;
50class IntakeTest_DisabledGoalTest_Test;
51class IntakeTest_IntakeZeroingErrorTest_Test;
52class IntakeTest_UpperHardstopStartup_Test;
53class IntakeTest_DisabledWhileZeroingHigh_Test;
54class IntakeTest_DisabledWhileZeroingLow_Test;
55}
56
57class LimitChecker {
58 public:
59 LimitChecker(IntakeArm *intake) : intake_(intake) {}
60 void UpdateGoal(double intake_angle_goal);
61 private:
62 IntakeArm *intake_;
63};
64
65class Intake : public ::aos::controls::ControlLoop<control_loops::IntakeQueue> {
66 public:
67 explicit Intake(
68 control_loops::IntakeQueue *my_intake = &control_loops::intake_queue);
69
70 static constexpr double kZeroingVoltage = 6.0;
71 static constexpr double kOperatingVoltage = 12.0;
72
73 // This is the large scale movement tolerance.
74 static constexpr double kLooseTolerance = 0.05;
75
76 // This is the small scale movement tolerance.
77 static constexpr double kTightTolerance = 0.03;
78
79 static constexpr double kIntakeUpAngle = M_PI / 2;
80
81 static constexpr double kIntakeDownAngle = 0.0;
82
83 static constexpr double kIntakeMiddleAngle =
84 (kIntakeUpAngle + kIntakeDownAngle) / 2;
85
86 enum State {
87 // Wait for all the filters to be ready before starting the initialization
88 // process.
89 UNINITIALIZED = 0,
90
91 // We now are ready to decide how to zero. Decide what to do once we are
92 // enabled.
93 DISABLED_INITIALIZED = 1,
94
95 ZERO_LOWER_INTAKE = 2,
96
97 ZERO_LIFT_INTAKE = 3,
98 // Run, but limit power to zeroing voltages.
99 SLOW_RUNNING = 12,
100 // Run with full power.
101 RUNNING = 13,
102 // Internal error caused the intake to abort.
103 ESTOP = 16,
104 };
105
106 bool IsRunning() const {
107 return (state_ == SLOW_RUNNING || state_ == RUNNING);
108 }
109
110 State state() const { return state_; }
111
112 // Returns the value to move the joint to such that it will stay below
113 // reference_angle starting at current_angle, but move at least move_distance
114 static double MoveButKeepBelow(double reference_angle, double current_angle,
115 double move_distance);
116 // Returns the value to move the joint to such that it will stay above
117 // reference_angle starting at current_angle, but move at least move_distance
118 static double MoveButKeepAbove(double reference_angle, double current_angle,
119 double move_distance);
120
121 protected:
122 void RunIteration(const control_loops::IntakeQueue::Goal *unsafe_goal,
123 const control_loops::IntakeQueue::Position *position,
124 control_loops::IntakeQueue::Output *output,
125 control_loops::IntakeQueue::Status *status) override;
126
127 private:
128 friend class testing::IntakeTest_DisabledGoalTest_Test;
129 friend class testing::IntakeTest_IntakeZeroingErrorTest_Test;
130 friend class testing::IntakeTest_RespectsRange_Test;
131 friend class testing::IntakeTest_UpperHardstopStartup_Test;
132 friend class testing::IntakeTest_DisabledWhileZeroingHigh_Test;
133 friend class testing::IntakeTest_DisabledWhileZeroingLow_Test;
134 IntakeArm intake_;
135
136 State state_ = UNINITIALIZED;
137 State last_state_ = UNINITIALIZED;
138
139 float last_intake_angle_ = 0.0;
140 LimitChecker limit_checker_;
141 // Returns true if the profile has finished, and the joint is within the
142 // specified tolerance.
143 bool IsIntakeNear(double tolerance);
144
145 DISALLOW_COPY_AND_ASSIGN(Intake);
146};
147
148
149} // namespace intake
150} // namespace control_loops
151} // namespace y2016_bot3
152
153#endif // Y2016_BOT3_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_