blob: 9e7a5fef54c50c9057256b6b49b677ca5aacb08f [file] [log] [blame]
Tyler Chatowe51334a2019-01-20 16:58:16 -08001#include "y2019/control_loops/superstructure/superstructure.h"
2
Alex Perrycb7da4b2019-08-28 19:35:56 -07003#include "aos/events/event_loop.h"
4#include "frc971/control_loops/control_loops_generated.h"
5#include "frc971/control_loops/drivetrain/drivetrain_status_generated.h"
Theo Bafrali00e42272019-02-12 01:07:46 -08006#include "frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include "y2019/status_light_generated.h"
Sabina Davisc6329342019-03-01 20:44:42 -08008
Tyler Chatowe51334a2019-01-20 16:58:16 -08009namespace y2019 {
10namespace control_loops {
11namespace superstructure {
12
Alex Perrycb7da4b2019-08-28 19:35:56 -070013using frc971::control_loops::AbsoluteEncoderProfiledJointStatus;
James Kuszmaul61750662021-06-21 21:32:33 -070014using frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus;
Alex Perrycb7da4b2019-08-28 19:35:56 -070015
Austin Schuh55a13dc2019-01-27 22:39:03 -080016Superstructure::Superstructure(::aos::EventLoop *event_loop,
17 const ::std::string &name)
James Kuszmaul61750662021-06-21 21:32:33 -070018 : frc971::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
19 name),
Austin Schuhff973552019-05-19 16:49:28 -070020 status_light_sender_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070021 event_loop->MakeSender<::y2019::StatusLight>("/superstructure")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070022 drivetrain_status_fetcher_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070023 event_loop->MakeFetcher<::frc971::control_loops::drivetrain::Status>(
24 "/drivetrain")),
Theo Bafrali00e42272019-02-12 01:07:46 -080025 elevator_(constants::GetValues().elevator.subsystem_params),
26 wrist_(constants::GetValues().wrist.subsystem_params),
27 intake_(constants::GetValues().intake),
Austin Schuh59dddac2019-12-22 16:44:49 -080028 stilts_(constants::GetValues().stilts.subsystem_params) {
29 event_loop->SetRuntimeRealtimePriority(30);
30}
Tyler Chatowe51334a2019-01-20 16:58:16 -080031
Alex Perrycb7da4b2019-08-28 19:35:56 -070032void Superstructure::RunIteration(const Goal *unsafe_goal,
33 const Position *position,
34 aos::Sender<Output>::Builder *output,
35 aos::Sender<Status>::Builder *status) {
Tyler Chatowe51334a2019-01-20 16:58:16 -080036 if (WasReset()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070037 AOS_LOG(ERROR, "WPILib reset, restarting\n");
Theo Bafrali00e42272019-02-12 01:07:46 -080038 elevator_.Reset();
39 wrist_.Reset();
40 intake_.Reset();
41 stilts_.Reset();
Tyler Chatowe51334a2019-01-20 16:58:16 -080042 }
Theo Bafrali00e42272019-02-12 01:07:46 -080043
Alex Perrycb7da4b2019-08-28 19:35:56 -070044 OutputT output_struct;
Theo Bafrali00e42272019-02-12 01:07:46 -080045
Alex Perrycb7da4b2019-08-28 19:35:56 -070046 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
47 elevator_status_offset = elevator_.Iterate(
48 unsafe_goal != nullptr ? unsafe_goal->elevator() : nullptr,
49 position->elevator(),
50 output != nullptr ? &(output_struct.elevator_voltage) : nullptr,
51 status->fbb());
Theo Bafrali00e42272019-02-12 01:07:46 -080052
Alex Perrycb7da4b2019-08-28 19:35:56 -070053 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
54 wrist_status_offset = wrist_.Iterate(
55 unsafe_goal != nullptr ? unsafe_goal->wrist() : nullptr,
56 position->wrist(),
57 output != nullptr ? &(output_struct.wrist_voltage) : nullptr,
58 status->fbb());
Theo Bafrali00e42272019-02-12 01:07:46 -080059
Alex Perrycb7da4b2019-08-28 19:35:56 -070060 flatbuffers::Offset<AbsoluteEncoderProfiledJointStatus> intake_status_offset =
61 intake_.Iterate(
62 unsafe_goal != nullptr ? unsafe_goal->intake() : nullptr,
63 position->intake_joint(),
64 output != nullptr ? &(output_struct.intake_joint_voltage) : nullptr,
65 status->fbb());
Theo Bafrali00e42272019-02-12 01:07:46 -080066
Alex Perrycb7da4b2019-08-28 19:35:56 -070067 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
68 stilts_status_offset = stilts_.Iterate(
69 unsafe_goal != nullptr ? unsafe_goal->stilts() : nullptr,
70 position->stilts(),
71 output != nullptr ? &(output_struct.stilts_voltage) : nullptr,
72 status->fbb());
73
74 bool has_piece;
75 vacuum_.Iterate(unsafe_goal != nullptr ? unsafe_goal->suction() : nullptr,
76 position->suction_pressure(), &output_struct, &has_piece,
Theo Bafrali3274a182019-02-17 20:01:38 -080077 event_loop());
Austin Schuhe8354752019-02-17 14:59:05 -080078
Alex Perrycb7da4b2019-08-28 19:35:56 -070079 bool zeroed;
80 bool estopped;
81 {
82 PotAndAbsoluteEncoderProfiledJointStatus *elevator_status =
83 GetMutableTemporaryPointer(*status->fbb(), elevator_status_offset);
84 PotAndAbsoluteEncoderProfiledJointStatus *wrist_status =
85 GetMutableTemporaryPointer(*status->fbb(), wrist_status_offset);
86 AbsoluteEncoderProfiledJointStatus *intake_status =
87 GetMutableTemporaryPointer(*status->fbb(), intake_status_offset);
88 PotAndAbsoluteEncoderProfiledJointStatus *stilts_status =
89 GetMutableTemporaryPointer(*status->fbb(), stilts_status_offset);
Theo Bafrali00e42272019-02-12 01:07:46 -080090
Alex Perrycb7da4b2019-08-28 19:35:56 -070091 zeroed = elevator_status->zeroed() && wrist_status->zeroed() &&
92 intake_status->zeroed() && stilts_status->zeroed();
93
94 estopped = elevator_status->estopped() || wrist_status->estopped() ||
95 intake_status->estopped() || stilts_status->estopped();
96 }
97
98 Status::Builder status_builder = status->MakeBuilder<Status>();
99
100 status_builder.add_zeroed(zeroed);
101 status_builder.add_estopped(estopped);
102 status_builder.add_has_piece(has_piece);
103
104 status_builder.add_elevator(elevator_status_offset);
105 status_builder.add_wrist(wrist_status_offset);
106 status_builder.add_intake(intake_status_offset);
107 status_builder.add_stilts(stilts_status_offset);
108
109 flatbuffers::Offset<Status> status_offset = status_builder.Finish();
110
111 Status *status_flatbuffer =
112 GetMutableTemporaryPointer(*status->fbb(), status_offset);
Theo Bafrali00e42272019-02-12 01:07:46 -0800113
Theo Bafrali09517b92019-02-16 15:59:17 -0800114 if (output) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700115 if (unsafe_goal &&
116 status_flatbuffer->intake()->position() > kMinIntakeAngleForRollers) {
117 output_struct.intake_roller_voltage = unsafe_goal->roller_voltage();
Theo Bafrali09517b92019-02-16 15:59:17 -0800118 } else {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700119 output_struct.intake_roller_voltage = 0.0;
Theo Bafrali09517b92019-02-16 15:59:17 -0800120 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700121
122 output->Send(Output::Pack(*output->fbb(), &output_struct));
Theo Bafrali09517b92019-02-16 15:59:17 -0800123 }
124
Tyler Chatow993fe282019-04-06 22:24:36 -0700125 if (unsafe_goal) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700126 if (!unsafe_goal->has_suction() || !unsafe_goal->suction()->grab_piece()) {
Tyler Chatow993fe282019-04-06 22:24:36 -0700127 wrist_.set_controller_index(0);
128 elevator_.set_controller_index(0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700129 } else if (unsafe_goal->suction()->gamepiece_mode() == 0) {
Tyler Chatow993fe282019-04-06 22:24:36 -0700130 wrist_.set_controller_index(1);
131 elevator_.set_controller_index(1);
132 } else {
133 wrist_.set_controller_index(2);
134 elevator_.set_controller_index(2);
135 }
136 }
137
Theo Bafrali00e42272019-02-12 01:07:46 -0800138 // TODO(theo) move these up when Iterate() is split
139 // update the goals
Alex Perrycb7da4b2019-08-28 19:35:56 -0700140 collision_avoidance_.UpdateGoal(status_flatbuffer, unsafe_goal);
Theo Bafrali00e42272019-02-12 01:07:46 -0800141
142 elevator_.set_min_position(collision_avoidance_.min_elevator_goal());
143 wrist_.set_min_position(collision_avoidance_.min_wrist_goal());
144 wrist_.set_max_position(collision_avoidance_.max_wrist_goal());
145 intake_.set_min_position(collision_avoidance_.min_intake_goal());
146 intake_.set_max_position(collision_avoidance_.max_intake_goal());
Sabina Davisc6329342019-03-01 20:44:42 -0800147
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700148 drivetrain_status_fetcher_.Fetch();
Austin Schuh194c43c2019-03-22 20:40:53 -0700149
Sabina Davisc6329342019-03-01 20:44:42 -0800150 if (status && unsafe_goal) {
151 // Light Logic
Alex Perrycb7da4b2019-08-28 19:35:56 -0700152 if (status_flatbuffer->estopped()) {
Sabina Davisc6329342019-03-01 20:44:42 -0800153 // Estop is red
Sabina Davis77a11cf2019-03-09 18:20:26 -0800154 SendColors(1.0, 0.0, 0.0);
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700155 } else if (drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700156 drivetrain_status_fetcher_->line_follow_logging()->frozen()) {
James Kuszmaul4c1d4f42019-03-24 13:10:00 -0700157 // Vision align is flashing white for button pressed, purple for target
158 // acquired.
Austin Schuh194c43c2019-03-22 20:40:53 -0700159 ++line_blink_count_;
160 if (line_blink_count_ < 20) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700161 if (drivetrain_status_fetcher_->line_follow_logging()->have_target()) {
James Kuszmaul4c1d4f42019-03-24 13:10:00 -0700162 SendColors(1.0, 0.0, 1.0);
163 } else {
164 SendColors(1.0, 1.0, 1.0);
165 }
Austin Schuh194c43c2019-03-22 20:40:53 -0700166 } else {
167 // And then flash with green if we have a game piece.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700168 if (status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700169 SendColors(0.0, 1.0, 0.0);
170 } else {
171 SendColors(0.0, 0.0, 0.0);
172 }
173 }
174
175 if (line_blink_count_ > 40) {
176 line_blink_count_ = 0;
177 }
Sabina Davisc6329342019-03-01 20:44:42 -0800178 } else {
Austin Schuh194c43c2019-03-22 20:40:53 -0700179 line_blink_count_ = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700180 if (status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700181 // Green if we have a game piece.
182 SendColors(0.0, 1.0, 0.0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700183 } else if ((!unsafe_goal->has_suction() ||
184 unsafe_goal->suction()->gamepiece_mode() == 0) &&
185 !status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700186 // Ball mode is orange
187 SendColors(1.0, 0.1, 0.0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700188 } else if (unsafe_goal->has_suction() &&
189 unsafe_goal->suction()->gamepiece_mode() == 1 &&
190 !status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700191 // Disk mode is deep blue
192 SendColors(0.05, 0.1, 0.5);
193 } else {
194 SendColors(0.0, 0.0, 0.0);
195 }
Sabina Davisc6329342019-03-01 20:44:42 -0800196 }
197 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700198
199 status->Send(status_offset);
Tyler Chatowe51334a2019-01-20 16:58:16 -0800200}
201
Austin Schuhff973552019-05-19 16:49:28 -0700202void Superstructure::SendColors(float red, float green, float blue) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700203 auto builder = status_light_sender_.MakeBuilder();
Austin Schuhff973552019-05-19 16:49:28 -0700204
Alex Perrycb7da4b2019-08-28 19:35:56 -0700205 StatusLight::Builder status_light_builder =
206 builder.MakeBuilder<StatusLight>();
207 status_light_builder.add_red(red);
208 status_light_builder.add_green(green);
209 status_light_builder.add_blue(blue);
210
211 if (!builder.Send(status_light_builder.Finish())) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700212 AOS_LOG(ERROR, "Failed to send lights.\n");
Austin Schuhff973552019-05-19 16:49:28 -0700213 }
214}
215
Tyler Chatowe51334a2019-01-20 16:58:16 -0800216} // namespace superstructure
217} // namespace control_loops
Austin Schuh55a13dc2019-01-27 22:39:03 -0800218} // namespace y2019