blob: c66e4932301aca20e50617121682efceef48e42c [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,
21 constants::Values::kIntakeRange, 0.3, 5.0) {}
22
23void Intake::Reset() {
24 state_ = State::UNINITIALIZED;
25 profiled_subsystem_.Reset();
26}
27
28void Intake::Iterate(
29 const control_loops::IntakeGoal *unsafe_goal,
30 const ::frc971::PotAndAbsolutePosition *position, double *output,
31 ::frc971::control_loops::AbsoluteProfiledJointStatus *status) {
32 bool disable = output == nullptr;
33 profiled_subsystem_.Correct(*position);
34
35 switch (state_) {
36 case State::UNINITIALIZED:
37 // Wait in the uninitialized state until the intake is initialized.
38 LOG(DEBUG, "Uninitialized, waiting for intake\n");
39 if (profiled_subsystem_.initialized()) {
40 state_ = State::DISABLED_INITIALIZED;
41 }
42 disable = true;
43 break;
44
45 case State::DISABLED_INITIALIZED:
46 // Wait here until we are either fully zeroed while disabled, or we become
47 // enabled.
48 if (disable) {
49 if (profiled_subsystem_.zeroed()) {
50 state_ = State::RUNNING;
51 }
52 } else {
53 state_ = State::ZEROING;
54 }
55
56 // Set the goals to where we are now so when we start back up, we don't
57 // jump.
58 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
59 // Set up the profile to be the zeroing profile.
60 profiled_subsystem_.AdjustProfile(0.10, 1);
61
62 // We are not ready to start doing anything yet.
63 disable = true;
64 break;
65
66 case State::ZEROING:
67 // Now, zero by actively holding still.
68 if (profiled_subsystem_.zeroed()) {
69 state_ = State::RUNNING;
70 } else if (disable) {
71 state_ = State::DISABLED_INITIALIZED;
72 }
73 break;
74
75 case State::RUNNING: {
76 if (disable) {
77 // Reset the profile to the current position so it starts from here when
78 // we get re-enabled.
79 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
80 }
81
82 if (unsafe_goal) {
83 profiled_subsystem_.AdjustProfile(unsafe_goal->profile_params);
84 profiled_subsystem_.set_unprofiled_goal(unsafe_goal->distance);
85 }
86
87 // ESTOP if we hit the hard limits.
88 if (profiled_subsystem_.CheckHardLimits()) {
89 state_ = State::ESTOP;
90 }
91 } break;
92
93 case State::ESTOP:
94 LOG(ERROR, "Estop\n");
95 disable = true;
96 break;
97 }
98
99 // Set the voltage limits.
100 const double max_voltage =
101 (state_ == State::RUNNING) ? kOperatingVoltage : kZeroingVoltage;
102
103 profiled_subsystem_.set_max_voltage({{max_voltage}});
104
105 // Calculate the loops for a cycle.
106 profiled_subsystem_.Update(disable);
107
108 // Write out all the voltages.
109 if (output) {
110 *output = profiled_subsystem_.voltage();
111 }
112
113 // Save debug/internal state.
114 // TODO(austin): Save more.
115 status->zeroed = profiled_subsystem_.zeroed();
116
117 profiled_subsystem_.PopulateStatus(status);
118 status->estopped = (state_ == State::ESTOP);
119 status->state = static_cast<int32_t>(state_);
120}
121
122} // namespace intake
123} // namespace superstructure
124} // namespace control_loops
125} // namespace y2017