blob: 31836345a0731ead795c31bec23b8b5f9b3232ad [file] [log] [blame]
Adam Snaider79900c22017-02-08 20:23:15 -08001#include "y2017/control_loops/superstructure/intake/intake.h"
2
3#include "y2017/constants.h"
4#include "y2017/control_loops/superstructure/intake/intake_integral_plant.h"
5
6namespace y2017 {
7namespace control_loops {
8namespace superstructure {
9namespace intake {
10
11constexpr double Intake::kZeroingVoltage;
12constexpr double Intake::kOperatingVoltage;
13
14Intake::Intake()
15 : profiled_subsystem_(
16 ::std::unique_ptr<
17 ::frc971::control_loops::SimpleCappedStateFeedbackLoop<3, 1, 1>>(
18 new ::frc971::control_loops::SimpleCappedStateFeedbackLoop<
19 3, 1, 1>(MakeIntegralIntakeLoop())),
20 constants::GetValues().intake.zeroing,
Austin Schuhd5ccb862017-03-11 22:06:36 -080021 constants::Values::kIntakeRange, 0.3, 5.0) {
22 clear_min_position();
23}
Adam Snaider79900c22017-02-08 20:23:15 -080024
25void Intake::Reset() {
26 state_ = State::UNINITIALIZED;
Austin Schuhd5ccb862017-03-11 22:06:36 -080027 clear_min_position();
Adam Snaider79900c22017-02-08 20:23:15 -080028 profiled_subsystem_.Reset();
Austin Schuhd5ccb862017-03-11 22:06:36 -080029 disable_count_ = 0;
Adam Snaider79900c22017-02-08 20:23:15 -080030}
31
32void Intake::Iterate(
33 const control_loops::IntakeGoal *unsafe_goal,
34 const ::frc971::PotAndAbsolutePosition *position, double *output,
35 ::frc971::control_loops::AbsoluteProfiledJointStatus *status) {
36 bool disable = output == nullptr;
37 profiled_subsystem_.Correct(*position);
38
39 switch (state_) {
40 case State::UNINITIALIZED:
41 // Wait in the uninitialized state until the intake is initialized.
42 LOG(DEBUG, "Uninitialized, waiting for intake\n");
43 if (profiled_subsystem_.initialized()) {
44 state_ = State::DISABLED_INITIALIZED;
45 }
46 disable = true;
47 break;
48
49 case State::DISABLED_INITIALIZED:
50 // Wait here until we are either fully zeroed while disabled, or we become
51 // enabled.
52 if (disable) {
53 if (profiled_subsystem_.zeroed()) {
54 state_ = State::RUNNING;
55 }
56 } else {
57 state_ = State::ZEROING;
58 }
59
60 // Set the goals to where we are now so when we start back up, we don't
61 // jump.
62 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
63 // Set up the profile to be the zeroing profile.
64 profiled_subsystem_.AdjustProfile(0.10, 1);
65
66 // We are not ready to start doing anything yet.
67 disable = true;
68 break;
69
70 case State::ZEROING:
71 // Now, zero by actively holding still.
72 if (profiled_subsystem_.zeroed()) {
73 state_ = State::RUNNING;
74 } else if (disable) {
75 state_ = State::DISABLED_INITIALIZED;
76 }
77 break;
78
79 case State::RUNNING: {
80 if (disable) {
81 // Reset the profile to the current position so it starts from here when
82 // we get re-enabled.
83 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
84 }
85
86 if (unsafe_goal) {
87 profiled_subsystem_.AdjustProfile(unsafe_goal->profile_params);
88 profiled_subsystem_.set_unprofiled_goal(unsafe_goal->distance);
Austin Schuhd5ccb862017-03-11 22:06:36 -080089 if (unsafe_goal->disable_intake) {
90 disable = true;
91 ++disable_count_;
92 if (disable_count_ > 200) {
93 state_ = State::ESTOP;
94 }
95 } else {
96 disable_count_ = 0;
97 }
98 }
99
100 // Force the intake to be at least at min_position_ out.
101 if (profiled_subsystem_.unprofiled_goal(0, 0) < min_position_) {
102 LOG(INFO, "Limiting intake to %f from %f\n", min_position_,
103 profiled_subsystem_.unprofiled_goal(0, 0));
104 profiled_subsystem_.set_unprofiled_goal(min_position_);
Adam Snaider79900c22017-02-08 20:23:15 -0800105 }
106
107 // ESTOP if we hit the hard limits.
Austin Schuhd93160a2017-03-05 01:00:54 -0800108 if (profiled_subsystem_.CheckHardLimits() ||
109 profiled_subsystem_.error()) {
Adam Snaider79900c22017-02-08 20:23:15 -0800110 state_ = State::ESTOP;
111 }
112 } break;
113
114 case State::ESTOP:
115 LOG(ERROR, "Estop\n");
116 disable = true;
117 break;
118 }
119
120 // Set the voltage limits.
121 const double max_voltage =
122 (state_ == State::RUNNING) ? kOperatingVoltage : kZeroingVoltage;
123
124 profiled_subsystem_.set_max_voltage({{max_voltage}});
125
126 // Calculate the loops for a cycle.
127 profiled_subsystem_.Update(disable);
128
129 // Write out all the voltages.
130 if (output) {
131 *output = profiled_subsystem_.voltage();
132 }
133
134 // Save debug/internal state.
135 // TODO(austin): Save more.
136 status->zeroed = profiled_subsystem_.zeroed();
137
138 profiled_subsystem_.PopulateStatus(status);
139 status->estopped = (state_ == State::ESTOP);
140 status->state = static_cast<int32_t>(state_);
141}
142
143} // namespace intake
144} // namespace superstructure
145} // namespace control_loops
146} // namespace y2017