blob: 89145a44b456b3be41df8e84174335a3eea0b10e [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) {
Austin Schuh6a421742017-03-22 22:35:27 -070090 if (disable_count_ > 100) {
91 disable = true;
92 }
Austin Schuhd5ccb862017-03-11 22:06:36 -080093 ++disable_count_;
94 if (disable_count_ > 200) {
95 state_ = State::ESTOP;
96 }
97 } else {
98 disable_count_ = 0;
99 }
100 }
101
102 // Force the intake to be at least at min_position_ out.
103 if (profiled_subsystem_.unprofiled_goal(0, 0) < min_position_) {
Austin Schuh169cc932017-11-23 13:23:40 -0800104 LOG(DEBUG, "Limiting intake to %f from %f\n", min_position_,
Austin Schuhd5ccb862017-03-11 22:06:36 -0800105 profiled_subsystem_.unprofiled_goal(0, 0));
106 profiled_subsystem_.set_unprofiled_goal(min_position_);
Adam Snaider79900c22017-02-08 20:23:15 -0800107 }
108
109 // ESTOP if we hit the hard limits.
Austin Schuhd93160a2017-03-05 01:00:54 -0800110 if (profiled_subsystem_.CheckHardLimits() ||
111 profiled_subsystem_.error()) {
Adam Snaider79900c22017-02-08 20:23:15 -0800112 state_ = State::ESTOP;
113 }
114 } break;
115
116 case State::ESTOP:
117 LOG(ERROR, "Estop\n");
118 disable = true;
119 break;
120 }
121
122 // Set the voltage limits.
123 const double max_voltage =
124 (state_ == State::RUNNING) ? kOperatingVoltage : kZeroingVoltage;
125
126 profiled_subsystem_.set_max_voltage({{max_voltage}});
127
128 // Calculate the loops for a cycle.
129 profiled_subsystem_.Update(disable);
130
131 // Write out all the voltages.
132 if (output) {
133 *output = profiled_subsystem_.voltage();
134 }
135
136 // Save debug/internal state.
137 // TODO(austin): Save more.
138 status->zeroed = profiled_subsystem_.zeroed();
139
140 profiled_subsystem_.PopulateStatus(status);
141 status->estopped = (state_ == State::ESTOP);
142 status->state = static_cast<int32_t>(state_);
143}
144
145} // namespace intake
146} // namespace superstructure
147} // namespace control_loops
148} // namespace y2017