blob: f951791146a679256a7021365224fb3042041636 [file] [log] [blame]
Stephan Massaltd021f972020-01-05 20:41:23 -08001#include "y2020/control_loops/superstructure/superstructure.h"
2
milind-u0beb7dc2021-10-16 19:31:33 -07003#include "aos/containers/sized_array.h"
Stephan Massaltd021f972020-01-05 20:41:23 -08004#include "aos/events/event_loop.h"
Austin Schuh01d81c32021-11-06 22:59:56 -07005#include "aos/network/team_number.h"
Stephan Massaltd021f972020-01-05 20:41:23 -08006
Stephan Pleinesf63bde82024-01-13 15:59:33 -08007namespace y2020::control_loops::superstructure {
Stephan Massaltd021f972020-01-05 20:41:23 -08008
Ravago Jones937587c2020-12-26 17:21:09 -08009using frc971::control_loops::AbsoluteAndAbsoluteEncoderProfiledJointStatus;
Stephan Massaltd021f972020-01-05 20:41:23 -080010using frc971::control_loops::AbsoluteEncoderProfiledJointStatus;
11using frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus;
12
13Superstructure::Superstructure(::aos::EventLoop *event_loop,
14 const ::std::string &name)
James Kuszmaul61750662021-06-21 21:32:33 -070015 : frc971::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
16 name),
Sabina Davis0f2d38c2020-02-08 17:01:21 -080017 hood_(constants::GetValues().hood),
Kai Tinkessfb460372020-02-08 14:05:48 -080018 intake_joint_(constants::GetValues().intake),
Sabina Davis0f31d3f2020-02-20 20:41:00 -080019 turret_(constants::GetValues().turret.subsystem_params),
James Kuszmaulb1b2d8e2020-02-21 21:11:46 -080020 drivetrain_status_fetcher_(
21 event_loop->MakeFetcher<frc971::control_loops::drivetrain::Status>(
James Kuszmaula53c3ac2020-02-22 19:36:01 -080022 "/drivetrain")),
23 joystick_state_fetcher_(
Austin Schuh01d81c32021-11-06 22:59:56 -070024 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
25 has_turret_(::aos::network::GetTeamNumber() != 9971) {
Sabina Daviscf08b152020-01-31 22:12:09 -080026 event_loop->SetRuntimeRealtimePriority(30);
Stephan Massaltd021f972020-01-05 20:41:23 -080027}
28
milind upadhyayaec1aee2020-10-13 13:44:33 -070029double Superstructure::robot_speed() const {
30 return (drivetrain_status_fetcher_.get() != nullptr
31 ? drivetrain_status_fetcher_->robot_speed()
32 : 0.0);
33}
34
Sabina Daviscf08b152020-01-31 22:12:09 -080035void Superstructure::RunIteration(const Goal *unsafe_goal,
36 const Position *position,
Stephan Massaltd021f972020-01-05 20:41:23 -080037 aos::Sender<Output>::Builder *output,
38 aos::Sender<Status>::Builder *status) {
39 if (WasReset()) {
40 AOS_LOG(ERROR, "WPILib reset, restarting\n");
Sabina Daviscf08b152020-01-31 22:12:09 -080041 hood_.Reset();
Sabina Davis0f2d38c2020-02-08 17:01:21 -080042 intake_joint_.Reset();
Kai Tinkessfb460372020-02-08 14:05:48 -080043 turret_.Reset();
Stephan Massaltd021f972020-01-05 20:41:23 -080044 }
45
Sabina Davis0f31d3f2020-02-20 20:41:00 -080046 const aos::monotonic_clock::time_point position_timestamp =
47 event_loop()->context().monotonic_event_time;
48
James Kuszmaulb1b2d8e2020-02-21 21:11:46 -080049 if (drivetrain_status_fetcher_.Fetch()) {
James Kuszmaula53c3ac2020-02-22 19:36:01 -080050 aos::Alliance alliance = aos::Alliance::kInvalid;
James Kuszmaul519585d2020-03-08 22:32:48 -070051 joystick_state_fetcher_.Fetch();
52 if (joystick_state_fetcher_.get() != nullptr) {
James Kuszmaula53c3ac2020-02-22 19:36:01 -080053 alliance = joystick_state_fetcher_->alliance();
54 }
James Kuszmaul3b393d72020-02-26 19:43:51 -080055 const turret::Aimer::WrapMode mode =
James Kuszmaulb83d6e12020-02-22 20:44:48 -080056 (unsafe_goal != nullptr && unsafe_goal->shooting())
James Kuszmaul3b393d72020-02-26 19:43:51 -080057 ? turret::Aimer::WrapMode::kAvoidWrapping
58 : turret::Aimer::WrapMode::kAvoidEdges;
59 aimer_.Update(drivetrain_status_fetcher_.get(), alliance, mode,
60 turret::Aimer::ShotMode::kShootOnTheFly);
James Kuszmaulb1b2d8e2020-02-21 21:11:46 -080061 }
62
milind upadhyayaec1aee2020-10-13 13:44:33 -070063 const float velocity = robot_speed();
64
James Kuszmaulb1b2d8e2020-02-21 21:11:46 -080065 const flatbuffers::Offset<AimerStatus> aimer_status_offset =
66 aimer_.PopulateStatus(status->fbb());
67
James Kuszmaul98154a22021-04-03 16:09:29 -070068 const double distance_to_goal = aimer_.DistanceToGoal();
69
70 aos::FlatbufferFixedAllocatorArray<
71 frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal, 64>
72 hood_goal;
73 aos::FlatbufferFixedAllocatorArray<ShooterGoal, 64> shooter_goal;
74
75 constants::Values::ShotParams shot_params;
76 if (constants::GetValues().shot_interpolation_table.GetInRange(
milind-uf7fadbf2021-11-07 14:10:54 -080077 distance_to_goal, &shot_params)) {
James Kuszmaul98154a22021-04-03 16:09:29 -070078 hood_goal.Finish(frc971::control_loops::
79 CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
80 *hood_goal.fbb(), shot_params.hood_angle));
81
milind1f1dca32021-07-03 13:50:07 -070082 shooter_goal.Finish(CreateShooterGoal(*shooter_goal.fbb(),
83 shot_params.velocity_accelerator,
84 shot_params.velocity_finisher));
James Kuszmaul98154a22021-04-03 16:09:29 -070085 } else {
86 hood_goal.Finish(
87 frc971::control_loops::
88 CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
89 *hood_goal.fbb(), constants::GetValues().hood.range.upper));
90
91 shooter_goal.Finish(CreateShooterGoal(*shooter_goal.fbb(), 0.0, 0.0));
92 }
93
Sabina Daviscf08b152020-01-31 22:12:09 -080094 OutputT output_struct;
95
Ravago Jones937587c2020-12-26 17:21:09 -080096 flatbuffers::Offset<AbsoluteAndAbsoluteEncoderProfiledJointStatus>
97 hood_status_offset = hood_.Iterate(
James Kuszmaul98154a22021-04-03 16:09:29 -070098 unsafe_goal != nullptr
99 ? (unsafe_goal->hood_tracking() ? &hood_goal.message()
100 : unsafe_goal->hood())
101 : nullptr,
Ravago Jones937587c2020-12-26 17:21:09 -0800102 position->hood(),
103 output != nullptr ? &(output_struct.hood_voltage) : nullptr,
104 status->fbb());
Sabina Daviscf08b152020-01-31 22:12:09 -0800105
Austin Schuh346cdb72021-11-14 21:03:07 -0800106 bool intake_out_jostle = false;
107
Austin Schuh13e55522020-02-29 23:11:17 -0800108 if (unsafe_goal != nullptr) {
109 if (unsafe_goal->shooting() &&
110 shooting_start_time_ == aos::monotonic_clock::min_time) {
111 shooting_start_time_ = position_timestamp;
112 }
113
114 if (unsafe_goal->shooting()) {
Austin Schuh93ddcb42021-10-25 21:54:11 -0700115 intake_joint_.set_max_acceleration(30.0);
Austin Schuh13e55522020-02-29 23:11:17 -0800116 constexpr std::chrono::milliseconds kPeriod =
117 std::chrono::milliseconds(250);
118 if ((position_timestamp - shooting_start_time_) % (kPeriod * 2) <
119 kPeriod) {
120 intake_joint_.set_min_position(-0.25);
Austin Schuh346cdb72021-11-14 21:03:07 -0800121 intake_out_jostle = false;
Austin Schuh13e55522020-02-29 23:11:17 -0800122 } else {
Austin Schuh346cdb72021-11-14 21:03:07 -0800123 intake_out_jostle = true;
Austin Schuh13e55522020-02-29 23:11:17 -0800124 intake_joint_.set_min_position(-0.75);
125 }
126 } else {
Austin Schuh93ddcb42021-10-25 21:54:11 -0700127 intake_joint_.clear_max_acceleration();
Austin Schuh13e55522020-02-29 23:11:17 -0800128 intake_joint_.clear_min_position();
129 }
130
131 if (!unsafe_goal->shooting()) {
132 shooting_start_time_ = aos::monotonic_clock::min_time;
133 }
134 }
135
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800136 flatbuffers::Offset<AbsoluteEncoderProfiledJointStatus> intake_status_offset =
137 intake_joint_.Iterate(
138 unsafe_goal != nullptr ? unsafe_goal->intake() : nullptr,
139 position->intake_joint(),
140 output != nullptr ? &(output_struct.intake_joint_voltage) : nullptr,
141 status->fbb());
142
James Kuszmaulb1b2d8e2020-02-21 21:11:46 -0800143 const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
144 *turret_goal = unsafe_goal != nullptr ? (unsafe_goal->turret_tracking()
145 ? aimer_.TurretGoal()
146 : unsafe_goal->turret())
147 : nullptr;
James Kuszmaul98154a22021-04-03 16:09:29 -0700148
Kai Tinkessfb460372020-02-08 14:05:48 -0800149 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
Austin Schuhdce3f872021-11-12 11:55:14 -0800150 turret_status_offset;
151 if (has_turret_) {
152 turret_status_offset = turret_.Iterate(
153 turret_goal, position->turret(),
154 output != nullptr ? &(output_struct.turret_voltage) : nullptr,
155 status->fbb());
156 } else {
157 PotAndAbsoluteEncoderProfiledJointStatus::Builder turret_builder(
158 *status->fbb());
159 turret_builder.add_position(M_PI);
160 turret_builder.add_velocity(0.0);
161 turret_status_offset = turret_builder.Finish();
162 }
Kai Tinkessfb460372020-02-08 14:05:48 -0800163
Sabina Davis0f31d3f2020-02-20 20:41:00 -0800164 flatbuffers::Offset<ShooterStatus> shooter_status_offset =
165 shooter_.RunIteration(
James Kuszmaul98154a22021-04-03 16:09:29 -0700166 unsafe_goal != nullptr
167 ? (unsafe_goal->shooter_tracking() ? &shooter_goal.message()
168 : unsafe_goal->shooter())
169 : nullptr,
Sabina Davis0f31d3f2020-02-20 20:41:00 -0800170 position->shooter(), status->fbb(),
171 output != nullptr ? &(output_struct) : nullptr, position_timestamp);
172
Ravago Jones937587c2020-12-26 17:21:09 -0800173 const AbsoluteAndAbsoluteEncoderProfiledJointStatus *const hood_status =
Austin Schuh78f0bfd2020-02-29 23:04:21 -0800174 GetMutableTemporaryPointer(*status->fbb(), hood_status_offset);
175
Austin Schuh2fb23642020-02-29 15:10:51 -0800176 const PotAndAbsoluteEncoderProfiledJointStatus *const turret_status =
177 GetMutableTemporaryPointer(*status->fbb(), turret_status_offset);
178
179 if (output != nullptr) {
180 // Friction is a pain and putting a really high burden on the integrator.
James Kuszmaul9cbdb022021-09-19 17:42:29 -0700181 // TODO(james): I'm not sure how helpful this gain is.
James Kuszmaul519585d2020-03-08 22:32:48 -0700182 const double turret_velocity_sign =
183 turret_status->velocity() * kTurretFrictionGain;
Austin Schuh2fb23642020-02-29 15:10:51 -0800184 output_struct.turret_voltage +=
Austin Schuh78f0bfd2020-02-29 23:04:21 -0800185 std::clamp(turret_velocity_sign, -kTurretFrictionVoltageLimit,
Austin Schuh2fb23642020-02-29 15:10:51 -0800186 kTurretFrictionVoltageLimit);
James Kuszmaul9cbdb022021-09-19 17:42:29 -0700187 const double time_sec =
188 aos::time::DurationInSeconds(position_timestamp.time_since_epoch());
189 output_struct.turret_voltage +=
190 kTurretDitherGain * std::sin(2.0 * M_PI * time_sec * 30.0);
James Kuszmaulb7fe49e2020-03-05 08:24:44 -0800191 output_struct.turret_voltage =
192 std::clamp(output_struct.turret_voltage, -turret_.operating_voltage(),
193 turret_.operating_voltage());
Austin Schuh2fb23642020-02-29 15:10:51 -0800194 }
195
Sabina Daviscf08b152020-01-31 22:12:09 -0800196 bool zeroed;
197 bool estopped;
198
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800199 {
Kai Tinkessfb460372020-02-08 14:05:48 -0800200 const AbsoluteEncoderProfiledJointStatus *const intake_status =
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800201 GetMutableTemporaryPointer(*status->fbb(), intake_status_offset);
202
Kai Tinkessfb460372020-02-08 14:05:48 -0800203 zeroed = hood_status->zeroed() && intake_status->zeroed() &&
204 turret_status->zeroed();
205 estopped = hood_status->estopped() || intake_status->estopped() ||
206 turret_status->estopped();
Stephan Massaltd021f972020-01-05 20:41:23 -0800207 }
208
milind-u0beb7dc2021-10-16 19:31:33 -0700209 flatbuffers::Offset<flatbuffers::Vector<Subsystem>>
210 subsystems_not_ready_offset;
211 const bool turret_ready =
Austin Schuh01d81c32021-11-06 22:59:56 -0700212 (std::abs(turret_.goal(0) - turret_.position()) < 0.025) || !has_turret_;
milind-u0beb7dc2021-10-16 19:31:33 -0700213 if (unsafe_goal && unsafe_goal->shooting() &&
214 (!shooter_.ready() || !turret_ready)) {
215 aos::SizedArray<Subsystem, 3> subsystems_not_ready;
216 if (!shooter_.finisher_ready()) {
217 subsystems_not_ready.push_back(Subsystem::FINISHER);
218 }
219 if (!shooter_.accelerator_ready()) {
220 subsystems_not_ready.push_back(Subsystem::ACCELERATOR);
221 }
222 if (!turret_ready) {
223 subsystems_not_ready.push_back(Subsystem::TURRET);
224 }
225
Tyler Chatowd0a49742022-02-25 22:06:19 -0800226 subsystems_not_ready_offset = status->fbb()->CreateVector(
227 subsystems_not_ready.data(), subsystems_not_ready.size());
milind-u0beb7dc2021-10-16 19:31:33 -0700228 }
229
Stephan Massaltd021f972020-01-05 20:41:23 -0800230 Status::Builder status_builder = status->MakeBuilder<Status>();
231
Sabina Daviscf08b152020-01-31 22:12:09 -0800232 status_builder.add_zeroed(zeroed);
233 status_builder.add_estopped(estopped);
234
235 status_builder.add_hood(hood_status_offset);
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800236 status_builder.add_intake(intake_status_offset);
Kai Tinkessfb460372020-02-08 14:05:48 -0800237 status_builder.add_turret(turret_status_offset);
Sabina Davis0f31d3f2020-02-20 20:41:00 -0800238 status_builder.add_shooter(shooter_status_offset);
James Kuszmaulb1b2d8e2020-02-21 21:11:46 -0800239 status_builder.add_aimer(aimer_status_offset);
milind-u0beb7dc2021-10-16 19:31:33 -0700240 status_builder.add_subsystems_not_ready(subsystems_not_ready_offset);
Stephan Massaltd021f972020-01-05 20:41:23 -0800241
milind1f1dca32021-07-03 13:50:07 -0700242 status_builder.add_send_failures(status_failure_counter_.failures());
243
244 status_failure_counter_.Count(status->Send(status_builder.Finish()));
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800245
246 if (output != nullptr) {
Ravago Jonesf8b7bfe2021-10-09 16:25:29 -0700247 output_struct.washing_machine_spinner_voltage = 0.0;
248 output_struct.feeder_voltage = 0.0;
249 output_struct.intake_roller_voltage = 0.0;
Austin Schuh46712f52021-10-24 22:24:45 -0700250 output_struct.climber_voltage = 0.0;
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800251 if (unsafe_goal) {
Austin Schuh46712f52021-10-24 22:24:45 -0700252 if (unsafe_goal->has_turret()) {
253 output_struct.climber_voltage =
254 std::clamp(unsafe_goal->climber_voltage(), -12.0f, 12.0f);
Ravago Jonese92ff112021-10-23 17:27:44 -0700255
Austin Schuh46712f52021-10-24 22:24:45 -0700256 // Make sure the turret is relatively close to the goal before turning
257 // the climber on.
258 CHECK(unsafe_goal->has_turret());
259 if (std::abs(unsafe_goal->turret()->unsafe_goal() -
Austin Schuh77813e02021-11-07 23:30:46 -0800260 turret_.position()) > 0.1 &&
261 has_turret_) {
Austin Schuh46712f52021-10-24 22:24:45 -0700262 output_struct.climber_voltage = 0;
263 }
milind-ud6534142021-10-24 17:42:58 -0700264 }
265
Ravago Jonesac850da2021-10-13 20:38:29 -0700266 if (unsafe_goal->shooting() || unsafe_goal->intake_preloading()) {
267 preloading_timeout_ = position_timestamp + kPreloadingTimeout;
268 }
269
270 if (position_timestamp <= preloading_timeout_ &&
Ravago Jonesf8b7bfe2021-10-09 16:25:29 -0700271 !position->intake_beambreak_triggered()) {
272 output_struct.washing_machine_spinner_voltage = 5.0;
273 output_struct.feeder_voltage = 12.0;
Ravago Jonesac850da2021-10-13 20:38:29 -0700274
275 preloading_backpower_timeout_ =
276 position_timestamp + kPreloadingBackpowerDuration;
277 }
278
279 if (position->intake_beambreak_triggered() &&
280 position_timestamp <= preloading_backpower_timeout_) {
281 output_struct.feeder_voltage = -12.0;
Ravago Jonesf8b7bfe2021-10-09 16:25:29 -0700282 }
283
Austin Schuhb187ddb2021-11-13 16:16:16 -0800284 if (unsafe_goal->has_feed_voltage_override()) {
285 output_struct.feeder_voltage = unsafe_goal->feed_voltage_override();
286 output_struct.washing_machine_spinner_voltage = -5.0;
287 preloading_timeout_ = position_timestamp;
288 }
289
Austin Schuh43a220f2020-02-26 22:02:34 -0800290 if (unsafe_goal->shooting()) {
Austin Schuh01d81c32021-11-06 22:59:56 -0700291 if ((shooter_.ready() ||
292 (!has_turret_ && shooter_.accelerator_ready())) &&
293 turret_ready) {
Austin Schuh93109a52020-03-04 21:37:33 -0800294 output_struct.feeder_voltage = 12.0;
Austin Schuh13e55522020-02-29 23:11:17 -0800295 }
Austin Schuh346cdb72021-11-14 21:03:07 -0800296
297 if (!intake_out_jostle) {
298 output_struct.washing_machine_spinner_voltage = 5.0;
299 } else {
300 output_struct.washing_machine_spinner_voltage = -5.0;
301 }
Austin Schuh13e55522020-02-29 23:11:17 -0800302 output_struct.intake_roller_voltage = 3.0;
Austin Schuh43a220f2020-02-26 22:02:34 -0800303 } else {
milind upadhyayaec1aee2020-10-13 13:44:33 -0700304 output_struct.intake_roller_voltage =
305 unsafe_goal->roller_voltage() +
306 std::max(velocity * unsafe_goal->roller_speed_compensation(), 0.0f);
Austin Schuh43a220f2020-02-26 22:02:34 -0800307 }
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800308 }
Ravago Jonesf8b7bfe2021-10-09 16:25:29 -0700309
milind1f1dca32021-07-03 13:50:07 -0700310 output->CheckOk(output->Send(Output::Pack(*output->fbb(), &output_struct)));
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800311 }
Stephan Massaltd021f972020-01-05 20:41:23 -0800312}
313
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800314} // namespace y2020::control_loops::superstructure