blob: 4bc7d17c9323f952cb99b1690d4ee8c405f104cb [file] [log] [blame]
Stephan Massaltd021f972020-01-05 20:41:23 -08001#include "y2020/control_loops/superstructure/superstructure.h"
2
3#include "aos/events/event_loop.h"
4
5namespace y2020 {
6namespace control_loops {
7namespace superstructure {
8
9using frc971::control_loops::AbsoluteEncoderProfiledJointStatus;
10using frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus;
11
12Superstructure::Superstructure(::aos::EventLoop *event_loop,
13 const ::std::string &name)
14 : aos::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
Sabina Daviscf08b152020-01-31 22:12:09 -080015 name),
Sabina Davis0f2d38c2020-02-08 17:01:21 -080016 hood_(constants::GetValues().hood),
Kai Tinkessfb460372020-02-08 14:05:48 -080017 intake_joint_(constants::GetValues().intake),
Sabina Davis0f31d3f2020-02-20 20:41:00 -080018 turret_(constants::GetValues().turret.subsystem_params),
19 shooter_() {
Sabina Daviscf08b152020-01-31 22:12:09 -080020 event_loop->SetRuntimeRealtimePriority(30);
Stephan Massaltd021f972020-01-05 20:41:23 -080021}
22
Sabina Daviscf08b152020-01-31 22:12:09 -080023void Superstructure::RunIteration(const Goal *unsafe_goal,
24 const Position *position,
Stephan Massaltd021f972020-01-05 20:41:23 -080025 aos::Sender<Output>::Builder *output,
26 aos::Sender<Status>::Builder *status) {
27 if (WasReset()) {
28 AOS_LOG(ERROR, "WPILib reset, restarting\n");
Sabina Daviscf08b152020-01-31 22:12:09 -080029 hood_.Reset();
Sabina Davis0f2d38c2020-02-08 17:01:21 -080030 intake_joint_.Reset();
Kai Tinkessfb460372020-02-08 14:05:48 -080031 turret_.Reset();
Stephan Massaltd021f972020-01-05 20:41:23 -080032 }
33
Sabina Davis0f31d3f2020-02-20 20:41:00 -080034 const aos::monotonic_clock::time_point position_timestamp =
35 event_loop()->context().monotonic_event_time;
36
Sabina Daviscf08b152020-01-31 22:12:09 -080037 OutputT output_struct;
38
39 flatbuffers::Offset<AbsoluteEncoderProfiledJointStatus> hood_status_offset =
40 hood_.Iterate(unsafe_goal != nullptr ? unsafe_goal->hood() : nullptr,
41 position->hood(),
42 output != nullptr ? &(output_struct.hood_voltage) : nullptr,
43 status->fbb());
44
Austin Schuh13e55522020-02-29 23:11:17 -080045 if (unsafe_goal != nullptr) {
46 if (unsafe_goal->shooting() &&
47 shooting_start_time_ == aos::monotonic_clock::min_time) {
48 shooting_start_time_ = position_timestamp;
49 }
50
51 if (unsafe_goal->shooting()) {
52 constexpr std::chrono::milliseconds kPeriod =
53 std::chrono::milliseconds(250);
54 if ((position_timestamp - shooting_start_time_) % (kPeriod * 2) <
55 kPeriod) {
56 intake_joint_.set_min_position(-0.25);
57 } else {
58 intake_joint_.set_min_position(-0.75);
59 }
60 } else {
61 intake_joint_.clear_min_position();
62 }
63
64 if (!unsafe_goal->shooting()) {
65 shooting_start_time_ = aos::monotonic_clock::min_time;
66 }
67 }
68
Sabina Davis0f2d38c2020-02-08 17:01:21 -080069 flatbuffers::Offset<AbsoluteEncoderProfiledJointStatus> intake_status_offset =
70 intake_joint_.Iterate(
71 unsafe_goal != nullptr ? unsafe_goal->intake() : nullptr,
72 position->intake_joint(),
73 output != nullptr ? &(output_struct.intake_joint_voltage) : nullptr,
74 status->fbb());
75
Kai Tinkessfb460372020-02-08 14:05:48 -080076 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
77 turret_status_offset = turret_.Iterate(
78 unsafe_goal != nullptr ? unsafe_goal->turret() : nullptr,
79 position->turret(),
80 output != nullptr ? &(output_struct.turret_voltage) : nullptr,
81 status->fbb());
82
Sabina Davis0f31d3f2020-02-20 20:41:00 -080083 flatbuffers::Offset<ShooterStatus> shooter_status_offset =
84 shooter_.RunIteration(
85 unsafe_goal != nullptr ? unsafe_goal->shooter() : nullptr,
86 position->shooter(), status->fbb(),
87 output != nullptr ? &(output_struct) : nullptr, position_timestamp);
88
John Park0a245a02020-02-02 14:10:15 -080089 climber_.Iterate(unsafe_goal, output != nullptr ? &(output_struct) : nullptr);
90
Austin Schuh78f0bfd2020-02-29 23:04:21 -080091 const AbsoluteEncoderProfiledJointStatus *const hood_status =
92 GetMutableTemporaryPointer(*status->fbb(), hood_status_offset);
93
Austin Schuh2fb23642020-02-29 15:10:51 -080094 const PotAndAbsoluteEncoderProfiledJointStatus *const turret_status =
95 GetMutableTemporaryPointer(*status->fbb(), turret_status_offset);
96
97 if (output != nullptr) {
98 // Friction is a pain and putting a really high burden on the integrator.
Austin Schuh78f0bfd2020-02-29 23:04:21 -080099 const double turret_velocity_sign = turret_status->velocity() * kTurretFrictionGain;
Austin Schuh2fb23642020-02-29 15:10:51 -0800100 output_struct.turret_voltage +=
Austin Schuh78f0bfd2020-02-29 23:04:21 -0800101 std::clamp(turret_velocity_sign, -kTurretFrictionVoltageLimit,
Austin Schuh2fb23642020-02-29 15:10:51 -0800102 kTurretFrictionVoltageLimit);
Austin Schuh78f0bfd2020-02-29 23:04:21 -0800103
104 // Friction is a pain and putting a really high burden on the integrator.
105 const double hood_velocity_sign = hood_status->velocity() * kHoodFrictionGain;
106 output_struct.hood_voltage +=
107 std::clamp(hood_velocity_sign, -kHoodFrictionVoltageLimit,
108 kHoodFrictionVoltageLimit);
109
110 // And dither the output.
111 time_ += 0.00505;
112 output_struct.hood_voltage += 1.3 * std::sin(time_ * 2.0 * M_PI * 30.0);
Austin Schuh2fb23642020-02-29 15:10:51 -0800113 }
114
Sabina Daviscf08b152020-01-31 22:12:09 -0800115 bool zeroed;
116 bool estopped;
117
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800118 {
Kai Tinkessfb460372020-02-08 14:05:48 -0800119 const AbsoluteEncoderProfiledJointStatus *const intake_status =
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800120 GetMutableTemporaryPointer(*status->fbb(), intake_status_offset);
121
Kai Tinkessfb460372020-02-08 14:05:48 -0800122 zeroed = hood_status->zeroed() && intake_status->zeroed() &&
123 turret_status->zeroed();
124 estopped = hood_status->estopped() || intake_status->estopped() ||
125 turret_status->estopped();
Stephan Massaltd021f972020-01-05 20:41:23 -0800126 }
127
128 Status::Builder status_builder = status->MakeBuilder<Status>();
129
Sabina Daviscf08b152020-01-31 22:12:09 -0800130 status_builder.add_zeroed(zeroed);
131 status_builder.add_estopped(estopped);
132
133 status_builder.add_hood(hood_status_offset);
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800134 status_builder.add_intake(intake_status_offset);
Kai Tinkessfb460372020-02-08 14:05:48 -0800135 status_builder.add_turret(turret_status_offset);
Sabina Davis0f31d3f2020-02-20 20:41:00 -0800136 status_builder.add_shooter(shooter_status_offset);
Stephan Massaltd021f972020-01-05 20:41:23 -0800137
138 status->Send(status_builder.Finish());
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800139
140 if (output != nullptr) {
141 if (unsafe_goal) {
Austin Schuh13e55522020-02-29 23:11:17 -0800142 output_struct.washing_machine_spinner_voltage = 0.0;
Austin Schuh43a220f2020-02-26 22:02:34 -0800143 if (unsafe_goal->shooting()) {
Austin Schuh13e55522020-02-29 23:11:17 -0800144 if (shooter_.ready() &&
145 unsafe_goal->shooter()->velocity_accelerator() > 10.0 &&
146 unsafe_goal->shooter()->velocity_finisher() > 10.0) {
Austin Schuh93109a52020-03-04 21:37:33 -0800147 output_struct.feeder_voltage = 12.0;
Austin Schuh13e55522020-02-29 23:11:17 -0800148 } else {
149 output_struct.feeder_voltage = 0.0;
150 }
151 output_struct.washing_machine_spinner_voltage = 5.0;
152 output_struct.intake_roller_voltage = 3.0;
Austin Schuh43a220f2020-02-26 22:02:34 -0800153 } else {
154 output_struct.feeder_voltage = 0.0;
Austin Schuh13e55522020-02-29 23:11:17 -0800155 output_struct.intake_roller_voltage = unsafe_goal->roller_voltage();
Austin Schuh43a220f2020-02-26 22:02:34 -0800156 }
Sabina Davis0f2d38c2020-02-08 17:01:21 -0800157 } else {
158 output_struct.intake_roller_voltage = 0.0;
159 }
160 output->Send(Output::Pack(*output->fbb(), &output_struct));
161 }
Stephan Massaltd021f972020-01-05 20:41:23 -0800162}
163
Sabina Daviscf08b152020-01-31 22:12:09 -0800164} // namespace superstructure
Stephan Massaltd021f972020-01-05 20:41:23 -0800165} // namespace control_loops
166} // namespace y2020