blob: ee631d7a5cb8991076617d9e14c9e570ef470e6e [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
Alex Perrycb7da4b2019-08-28 19:35:56 -070032flatbuffers::Offset<
33 frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus>
34Intake::Iterate(const IntakeGoal *unsafe_goal,
35 const ::frc971::PotAndAbsolutePosition *position,
36 double *output, flatbuffers::FlatBufferBuilder *fbb) {
Adam Snaider79900c22017-02-08 20:23:15 -080037 bool disable = output == nullptr;
38 profiled_subsystem_.Correct(*position);
39
40 switch (state_) {
41 case State::UNINITIALIZED:
42 // Wait in the uninitialized state until the intake is initialized.
Austin Schuhf257f3c2019-10-27 21:00:43 -070043 AOS_LOG(DEBUG, "Uninitialized, waiting for intake\n");
Adam Snaider79900c22017-02-08 20:23:15 -080044 if (profiled_subsystem_.initialized()) {
45 state_ = State::DISABLED_INITIALIZED;
46 }
47 disable = true;
48 break;
49
50 case State::DISABLED_INITIALIZED:
51 // Wait here until we are either fully zeroed while disabled, or we become
52 // enabled.
53 if (disable) {
54 if (profiled_subsystem_.zeroed()) {
55 state_ = State::RUNNING;
56 }
57 } else {
58 state_ = State::ZEROING;
59 }
60
61 // Set the goals to where we are now so when we start back up, we don't
62 // jump.
63 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
64 // Set up the profile to be the zeroing profile.
65 profiled_subsystem_.AdjustProfile(0.10, 1);
66
67 // We are not ready to start doing anything yet.
68 disable = true;
69 break;
70
71 case State::ZEROING:
72 // Now, zero by actively holding still.
73 if (profiled_subsystem_.zeroed()) {
74 state_ = State::RUNNING;
75 } else if (disable) {
76 state_ = State::DISABLED_INITIALIZED;
77 }
78 break;
79
80 case State::RUNNING: {
81 if (disable) {
82 // Reset the profile to the current position so it starts from here when
83 // we get re-enabled.
84 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
85 }
86
87 if (unsafe_goal) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 profiled_subsystem_.AdjustProfile(unsafe_goal->profile_params());
89 profiled_subsystem_.set_unprofiled_goal(unsafe_goal->distance());
90 if (unsafe_goal->disable_intake()) {
Austin Schuh6a421742017-03-22 22:35:27 -070091 if (disable_count_ > 100) {
92 disable = true;
93 }
Austin Schuhd5ccb862017-03-11 22:06:36 -080094 ++disable_count_;
95 if (disable_count_ > 200) {
96 state_ = State::ESTOP;
97 }
98 } else {
99 disable_count_ = 0;
100 }
101 }
102
103 // Force the intake to be at least at min_position_ out.
104 if (profiled_subsystem_.unprofiled_goal(0, 0) < min_position_) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700105 AOS_LOG(DEBUG, "Limiting intake to %f from %f\n", min_position_,
106 profiled_subsystem_.unprofiled_goal(0, 0));
Austin Schuhd5ccb862017-03-11 22:06:36 -0800107 profiled_subsystem_.set_unprofiled_goal(min_position_);
Adam Snaider79900c22017-02-08 20:23:15 -0800108 }
109
110 // ESTOP if we hit the hard limits.
Austin Schuhd93160a2017-03-05 01:00:54 -0800111 if (profiled_subsystem_.CheckHardLimits() ||
112 profiled_subsystem_.error()) {
Adam Snaider79900c22017-02-08 20:23:15 -0800113 state_ = State::ESTOP;
114 }
115 } break;
116
117 case State::ESTOP:
Austin Schuhf257f3c2019-10-27 21:00:43 -0700118 AOS_LOG(ERROR, "Estop\n");
Adam Snaider79900c22017-02-08 20:23:15 -0800119 disable = true;
120 break;
121 }
122
123 // Set the voltage limits.
124 const double max_voltage =
125 (state_ == State::RUNNING) ? kOperatingVoltage : kZeroingVoltage;
126
127 profiled_subsystem_.set_max_voltage({{max_voltage}});
128
129 // Calculate the loops for a cycle.
130 profiled_subsystem_.Update(disable);
131
132 // Write out all the voltages.
133 if (output) {
134 *output = profiled_subsystem_.voltage();
135 }
136
Alex Perrycb7da4b2019-08-28 19:35:56 -0700137 frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus::Builder
138 status_builder = profiled_subsystem_.BuildStatus<
139 frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus::
140 Builder>(fbb);
Adam Snaider79900c22017-02-08 20:23:15 -0800141
Alex Perrycb7da4b2019-08-28 19:35:56 -0700142 // Save debug/internal state.
143 status_builder.add_estopped((state_ == State::ESTOP));
144 status_builder.add_state(static_cast<int32_t>(state_));
145
146 return status_builder.Finish();
Adam Snaider79900c22017-02-08 20:23:15 -0800147}
148
149} // namespace intake
150} // namespace superstructure
151} // namespace control_loops
152} // namespace y2017