blob: 29b4cc9621bc5006cd92448a6f13042623d76919 [file] [log] [blame]
Niko Sohmers3860f8a2024-01-12 21:05:19 -08001#include "y2024/control_loops/superstructure/superstructure.h"
2
3#include "aos/events/event_loop.h"
4#include "aos/flatbuffer_merge.h"
5#include "aos/network/team_number.h"
6#include "frc971/shooter_interpolation/interpolation.h"
7#include "frc971/zeroing/wrap.h"
8
9DEFINE_bool(ignore_distance, false,
10 "If true, ignore distance when shooting and obay joystick_reader");
11
Stephan Pleinesf63bde82024-01-13 15:59:33 -080012namespace y2024::control_loops::superstructure {
Niko Sohmers3860f8a2024-01-12 21:05:19 -080013
14using ::aos::monotonic_clock;
15
16using frc971::control_loops::AbsoluteEncoderProfiledJointStatus;
17using frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus;
18using frc971::control_loops::RelativeEncoderProfiledJointStatus;
19
20Superstructure::Superstructure(::aos::EventLoop *event_loop,
21 std::shared_ptr<const constants::Values> values,
22 const ::std::string &name)
23 : frc971::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
24 name),
25 values_(values),
26 constants_fetcher_(event_loop),
Niko Sohmersafc51fe2024-01-29 17:48:35 -080027 robot_constants_(CHECK_NOTNULL(&constants_fetcher_.constants())),
Niko Sohmers3860f8a2024-01-12 21:05:19 -080028 drivetrain_status_fetcher_(
29 event_loop->MakeFetcher<frc971::control_loops::drivetrain::Status>(
30 "/drivetrain")),
31 joystick_state_fetcher_(
Niko Sohmersafc51fe2024-01-29 17:48:35 -080032 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
Niko Sohmerse735fa82024-02-02 16:49:02 -080033 transfer_goal_(TransferRollerGoal::NONE),
Niko Sohmers74b0ad52024-02-03 18:00:31 -080034 intake_pivot_(robot_constants_->common()->intake_pivot(),
35 robot_constants_->robot()->intake_constants()),
Filip Kujawa6d717632024-02-01 11:40:55 -080036 climber_(
37 robot_constants_->common()->climber(),
Niko Sohmersc4d2c502024-02-19 19:35:35 -080038 robot_constants_->robot()->climber_constants()->zeroing_constants()),
39 shooter_(event_loop, robot_constants_) {
Niko Sohmers3860f8a2024-01-12 21:05:19 -080040 event_loop->SetRuntimeRealtimePriority(30);
41}
42
43void Superstructure::RunIteration(const Goal *unsafe_goal,
44 const Position *position,
45 aos::Sender<Output>::Builder *output,
46 aos::Sender<Status>::Builder *status) {
47 const monotonic_clock::time_point timestamp =
48 event_loop()->context().monotonic_event_time;
49
Maxwell Henderson461a8a42024-02-23 17:07:39 -080050 (void)timestamp;
51
Niko Sohmers3860f8a2024-01-12 21:05:19 -080052 if (WasReset()) {
53 AOS_LOG(ERROR, "WPILib reset, restarting\n");
Niko Sohmersafc51fe2024-01-29 17:48:35 -080054 intake_pivot_.Reset();
Filip Kujawa6d717632024-02-01 11:40:55 -080055 climber_.Reset();
Niko Sohmersc4d2c502024-02-19 19:35:35 -080056 shooter_.Reset();
Niko Sohmers3860f8a2024-01-12 21:05:19 -080057 }
58
59 OutputT output_struct;
Niko Sohmersafc51fe2024-01-29 17:48:35 -080060
61 double intake_pivot_position =
62 robot_constants_->common()->intake_pivot_set_points()->retracted();
63
64 if (unsafe_goal != nullptr &&
65 unsafe_goal->intake_pivot_goal() == IntakePivotGoal::EXTENDED) {
66 intake_pivot_position =
67 robot_constants_->common()->intake_pivot_set_points()->extended();
68 }
69
Filip Kujawa102a9b22024-02-18 09:40:23 -080070 IntakeRollerStatus intake_roller_state = IntakeRollerStatus::NONE;
Niko Sohmersafc51fe2024-01-29 17:48:35 -080071
72 switch (unsafe_goal != nullptr ? unsafe_goal->intake_roller_goal()
73 : IntakeRollerGoal::NONE) {
74 case IntakeRollerGoal::NONE:
75 output_struct.intake_roller_voltage = 0.0;
76 break;
77 case IntakeRollerGoal::SPIT:
Niko Sohmerse735fa82024-02-02 16:49:02 -080078 transfer_goal_ = TransferRollerGoal::TRANSFER_OUT;
Filip Kujawa102a9b22024-02-18 09:40:23 -080079 intake_roller_state = IntakeRollerStatus::SPITTING;
Niko Sohmersafc51fe2024-01-29 17:48:35 -080080 output_struct.intake_roller_voltage =
81 robot_constants_->common()->intake_roller_voltages()->spitting();
82 break;
83 case IntakeRollerGoal::INTAKE:
Niko Sohmerse735fa82024-02-02 16:49:02 -080084 transfer_goal_ = TransferRollerGoal::TRANSFER_IN;
Filip Kujawa102a9b22024-02-18 09:40:23 -080085 intake_roller_state = IntakeRollerStatus::INTAKING;
Niko Sohmersafc51fe2024-01-29 17:48:35 -080086 output_struct.intake_roller_voltage =
87 robot_constants_->common()->intake_roller_voltages()->intaking();
88 break;
89 }
90
Filip Kujawa102a9b22024-02-18 09:40:23 -080091 TransferRollerStatus transfer_roller_state = TransferRollerStatus::NONE;
Niko Sohmerse735fa82024-02-02 16:49:02 -080092
93 switch (unsafe_goal != nullptr ? transfer_goal_ : TransferRollerGoal::NONE) {
94 case TransferRollerGoal::NONE:
95 output_struct.transfer_roller_voltage = 0.0;
96 break;
97 case TransferRollerGoal::TRANSFER_IN:
98 if (position->transfer_beambreak()) {
99 transfer_goal_ = TransferRollerGoal::NONE;
Filip Kujawa102a9b22024-02-18 09:40:23 -0800100 transfer_roller_state = TransferRollerStatus::NONE;
Niko Sohmerse735fa82024-02-02 16:49:02 -0800101 output_struct.transfer_roller_voltage = 0.0;
102 break;
103 }
Filip Kujawa102a9b22024-02-18 09:40:23 -0800104 transfer_roller_state = TransferRollerStatus::TRANSFERING_IN;
Niko Sohmerse735fa82024-02-02 16:49:02 -0800105 output_struct.transfer_roller_voltage =
106 robot_constants_->common()->transfer_roller_voltages()->transfer_in();
107 break;
108 case TransferRollerGoal::TRANSFER_OUT:
Filip Kujawa102a9b22024-02-18 09:40:23 -0800109 transfer_roller_state = TransferRollerStatus::TRANSFERING_OUT;
Niko Sohmerse735fa82024-02-02 16:49:02 -0800110 output_struct.transfer_roller_voltage = robot_constants_->common()
111 ->transfer_roller_voltages()
112 ->transfer_out();
113 break;
114 }
115
Filip Kujawa6d717632024-02-01 11:40:55 -0800116 double climber_position =
117 robot_constants_->common()->climber_set_points()->retract();
118
119 if (unsafe_goal != nullptr) {
120 switch (unsafe_goal->climber_goal()) {
121 case ClimberGoal::FULL_EXTEND:
122 climber_position =
123 robot_constants_->common()->climber_set_points()->full_extend();
124 break;
125 case ClimberGoal::HALF_EXTEND:
126 climber_position =
127 robot_constants_->common()->climber_set_points()->half_extend();
128 break;
129 case ClimberGoal::RETRACT:
130 climber_position =
131 robot_constants_->common()->climber_set_points()->retract();
132 break;
133 default:
134 break;
135 }
136 }
137
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800138 if (joystick_state_fetcher_.Fetch() &&
139 joystick_state_fetcher_->has_alliance()) {
140 alliance_ = joystick_state_fetcher_->alliance();
141 }
Niko Sohmersafc51fe2024-01-29 17:48:35 -0800142
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800143 drivetrain_status_fetcher_.Fetch();
144
Niko Sohmersac4d8872024-02-23 13:55:47 -0800145 const bool collided = collision_avoidance_.IsCollided(
146 {.intake_pivot_position = intake_pivot_.estimated_position(),
147 .turret_position = shooter_.turret().estimated_position()});
Niko Sohmersafc51fe2024-01-29 17:48:35 -0800148
Filip Kujawa6d717632024-02-01 11:40:55 -0800149 aos::FlatbufferFixedAllocatorArray<
150 frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal, 512>
151 climber_goal_buffer;
152
153 climber_goal_buffer.Finish(
154 frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
155 *climber_goal_buffer.fbb(), climber_position));
156
157 const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
158 *climber_goal = &climber_goal_buffer.message();
159
160 const flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
161 climber_status_offset = climber_.Iterate(
162 climber_goal, position->climber(),
163 output != nullptr ? &output_struct.climber_voltage : nullptr,
164 status->fbb());
165
Niko Sohmersac4d8872024-02-23 13:55:47 -0800166 double max_intake_pivot_position = 0;
167 double min_intake_pivot_position = 0;
168
169 aos::FlatbufferFixedAllocatorArray<
170 frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal, 512>
171 intake_pivot_goal_buffer;
172
173 intake_pivot_goal_buffer.Finish(
174 frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
175 *intake_pivot_goal_buffer.fbb(), intake_pivot_position));
176
177 const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
178 *intake_pivot_goal = &intake_pivot_goal_buffer.message();
179
180 double *intake_output =
181 (output != nullptr ? &output_struct.intake_pivot_voltage : nullptr);
182
183 const bool disabled = intake_pivot_.Correct(
184 intake_pivot_goal, position->intake_pivot(), intake_output == nullptr);
185
186 // TODO(max): Change how we handle the collision with the turret and intake to
187 // be clearer
Niko Sohmersc4d2c502024-02-19 19:35:35 -0800188 const flatbuffers::Offset<ShooterStatus> shooter_status_offset =
189 shooter_.Iterate(
190 position,
191 unsafe_goal != nullptr ? unsafe_goal->shooter_goal() : nullptr,
192 output != nullptr ? &output_struct.catapult_voltage : nullptr,
193 output != nullptr ? &output_struct.altitude_voltage : nullptr,
194 output != nullptr ? &output_struct.turret_voltage : nullptr,
195 output != nullptr ? &output_struct.retention_roller_voltage : nullptr,
Maxwell Henderson461a8a42024-02-23 17:07:39 -0800196 robot_state().voltage_battery(), &collision_avoidance_,
Niko Sohmersac4d8872024-02-23 13:55:47 -0800197 intake_pivot_.estimated_position(), &max_intake_pivot_position,
198 &min_intake_pivot_position, status->fbb());
199
200 intake_pivot_.set_min_position(min_intake_pivot_position);
201 intake_pivot_.set_max_position(max_intake_pivot_position);
202
203 // Calculate the loops for a cycle.
204 const double voltage = intake_pivot_.UpdateController(disabled);
205
206 intake_pivot_.UpdateObserver(voltage);
207
208 // Write out all the voltages.
209 if (intake_output) {
210 *intake_output = voltage;
211 }
212
213 const flatbuffers::Offset<AbsoluteEncoderProfiledJointStatus>
214 intake_pivot_status_offset = intake_pivot_.MakeStatus(status->fbb());
Niko Sohmersc4d2c502024-02-19 19:35:35 -0800215
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800216 if (output) {
217 output->CheckOk(output->Send(Output::Pack(*output->fbb(), &output_struct)));
218 }
219
220 Status::Builder status_builder = status->MakeBuilder<Status>();
Niko Sohmersafc51fe2024-01-29 17:48:35 -0800221
Niko Sohmersc4d2c502024-02-19 19:35:35 -0800222 const bool zeroed =
223 intake_pivot_.zeroed() && climber_.zeroed() && shooter_.zeroed();
224 const bool estopped =
225 intake_pivot_.estopped() || climber_.estopped() || shooter_.estopped();
Niko Sohmersafc51fe2024-01-29 17:48:35 -0800226
227 status_builder.add_zeroed(zeroed);
228 status_builder.add_estopped(estopped);
Filip Kujawa102a9b22024-02-18 09:40:23 -0800229 status_builder.add_intake_roller(intake_roller_state);
230 status_builder.add_intake_pivot(intake_pivot_status_offset);
231 status_builder.add_transfer_roller(transfer_roller_state);
232 status_builder.add_climber(climber_status_offset);
Niko Sohmersc4d2c502024-02-19 19:35:35 -0800233 status_builder.add_shooter(shooter_status_offset);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800234 status_builder.add_collided(collided);
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800235
236 (void)status->Send(status_builder.Finish());
237}
238
239double Superstructure::robot_velocity() const {
240 return (drivetrain_status_fetcher_.get() != nullptr
241 ? drivetrain_status_fetcher_->robot_speed()
242 : 0.0);
243}
244
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800245} // namespace y2024::control_loops::superstructure