blob: dfcaf3107b4c366310407a83ba5ecf8c30c6b397 [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -08006namespace y2017::control_loops::superstructure::intake {
Adam Snaider79900c22017-02-08 20:23:15 -08007
8constexpr double Intake::kZeroingVoltage;
9constexpr double Intake::kOperatingVoltage;
10
11Intake::Intake()
12 : profiled_subsystem_(
13 ::std::unique_ptr<
14 ::frc971::control_loops::SimpleCappedStateFeedbackLoop<3, 1, 1>>(
15 new ::frc971::control_loops::SimpleCappedStateFeedbackLoop<
16 3, 1, 1>(MakeIntegralIntakeLoop())),
17 constants::GetValues().intake.zeroing,
Austin Schuhd5ccb862017-03-11 22:06:36 -080018 constants::Values::kIntakeRange, 0.3, 5.0) {
19 clear_min_position();
20}
Adam Snaider79900c22017-02-08 20:23:15 -080021
22void Intake::Reset() {
23 state_ = State::UNINITIALIZED;
Austin Schuhd5ccb862017-03-11 22:06:36 -080024 clear_min_position();
Adam Snaider79900c22017-02-08 20:23:15 -080025 profiled_subsystem_.Reset();
Austin Schuhd5ccb862017-03-11 22:06:36 -080026 disable_count_ = 0;
Adam Snaider79900c22017-02-08 20:23:15 -080027}
28
Alex Perrycb7da4b2019-08-28 19:35:56 -070029flatbuffers::Offset<
30 frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus>
31Intake::Iterate(const IntakeGoal *unsafe_goal,
32 const ::frc971::PotAndAbsolutePosition *position,
33 double *output, flatbuffers::FlatBufferBuilder *fbb) {
Adam Snaider79900c22017-02-08 20:23:15 -080034 bool disable = output == nullptr;
35 profiled_subsystem_.Correct(*position);
36
37 switch (state_) {
38 case State::UNINITIALIZED:
39 // Wait in the uninitialized state until the intake is initialized.
Austin Schuhf257f3c2019-10-27 21:00:43 -070040 AOS_LOG(DEBUG, "Uninitialized, waiting for intake\n");
Adam Snaider79900c22017-02-08 20:23:15 -080041 if (profiled_subsystem_.initialized()) {
42 state_ = State::DISABLED_INITIALIZED;
43 }
44 disable = true;
45 break;
46
47 case State::DISABLED_INITIALIZED:
48 // Wait here until we are either fully zeroed while disabled, or we become
49 // enabled.
50 if (disable) {
51 if (profiled_subsystem_.zeroed()) {
52 state_ = State::RUNNING;
53 }
54 } else {
55 state_ = State::ZEROING;
56 }
57
58 // Set the goals to where we are now so when we start back up, we don't
59 // jump.
60 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
61 // Set up the profile to be the zeroing profile.
62 profiled_subsystem_.AdjustProfile(0.10, 1);
63
64 // We are not ready to start doing anything yet.
65 disable = true;
66 break;
67
68 case State::ZEROING:
69 // Now, zero by actively holding still.
70 if (profiled_subsystem_.zeroed()) {
71 state_ = State::RUNNING;
72 } else if (disable) {
73 state_ = State::DISABLED_INITIALIZED;
74 }
75 break;
76
77 case State::RUNNING: {
78 if (disable) {
79 // Reset the profile to the current position so it starts from here when
80 // we get re-enabled.
81 profiled_subsystem_.ForceGoal(profiled_subsystem_.position());
82 }
83
84 if (unsafe_goal) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070085 profiled_subsystem_.AdjustProfile(unsafe_goal->profile_params());
86 profiled_subsystem_.set_unprofiled_goal(unsafe_goal->distance());
87 if (unsafe_goal->disable_intake()) {
Austin Schuh6a421742017-03-22 22:35:27 -070088 if (disable_count_ > 100) {
89 disable = true;
90 }
Austin Schuhd5ccb862017-03-11 22:06:36 -080091 ++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_) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700102 AOS_LOG(DEBUG, "Limiting intake to %f from %f\n", min_position_,
103 profiled_subsystem_.unprofiled_goal(0, 0));
Austin Schuhd5ccb862017-03-11 22:06:36 -0800104 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:
Austin Schuhf257f3c2019-10-27 21:00:43 -0700115 AOS_LOG(ERROR, "Estop\n");
Adam Snaider79900c22017-02-08 20:23:15 -0800116 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
Alex Perrycb7da4b2019-08-28 19:35:56 -0700134 frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus::Builder
135 status_builder = profiled_subsystem_.BuildStatus<
136 frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus::
137 Builder>(fbb);
Adam Snaider79900c22017-02-08 20:23:15 -0800138
Alex Perrycb7da4b2019-08-28 19:35:56 -0700139 // Save debug/internal state.
140 status_builder.add_estopped((state_ == State::ESTOP));
141 status_builder.add_state(static_cast<int32_t>(state_));
142
143 return status_builder.Finish();
Adam Snaider79900c22017-02-08 20:23:15 -0800144}
145
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800146} // namespace y2017::control_loops::superstructure::intake