blob: 91e17048be715e09ace3ffcb615ba023ccb4dce0 [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::PotAndAbsoluteEncoderProfiledJointStatus;
14using frc971::control_loops::AbsoluteEncoderProfiledJointStatus;
15
Austin Schuh55a13dc2019-01-27 22:39:03 -080016Superstructure::Superstructure(::aos::EventLoop *event_loop,
17 const ::std::string &name)
Alex Perrycb7da4b2019-08-28 19:35:56 -070018 : aos::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),
28 stilts_(constants::GetValues().stilts.subsystem_params) {}
Tyler Chatowe51334a2019-01-20 16:58:16 -080029
Alex Perrycb7da4b2019-08-28 19:35:56 -070030void Superstructure::RunIteration(const Goal *unsafe_goal,
31 const Position *position,
32 aos::Sender<Output>::Builder *output,
33 aos::Sender<Status>::Builder *status) {
Tyler Chatowe51334a2019-01-20 16:58:16 -080034 if (WasReset()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070035 AOS_LOG(ERROR, "WPILib reset, restarting\n");
Theo Bafrali00e42272019-02-12 01:07:46 -080036 elevator_.Reset();
37 wrist_.Reset();
38 intake_.Reset();
39 stilts_.Reset();
Tyler Chatowe51334a2019-01-20 16:58:16 -080040 }
Theo Bafrali00e42272019-02-12 01:07:46 -080041
Alex Perrycb7da4b2019-08-28 19:35:56 -070042 OutputT output_struct;
Theo Bafrali00e42272019-02-12 01:07:46 -080043
Alex Perrycb7da4b2019-08-28 19:35:56 -070044 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
45 elevator_status_offset = elevator_.Iterate(
46 unsafe_goal != nullptr ? unsafe_goal->elevator() : nullptr,
47 position->elevator(),
48 output != nullptr ? &(output_struct.elevator_voltage) : nullptr,
49 status->fbb());
Theo Bafrali00e42272019-02-12 01:07:46 -080050
Alex Perrycb7da4b2019-08-28 19:35:56 -070051 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
52 wrist_status_offset = wrist_.Iterate(
53 unsafe_goal != nullptr ? unsafe_goal->wrist() : nullptr,
54 position->wrist(),
55 output != nullptr ? &(output_struct.wrist_voltage) : nullptr,
56 status->fbb());
Theo Bafrali00e42272019-02-12 01:07:46 -080057
Alex Perrycb7da4b2019-08-28 19:35:56 -070058 flatbuffers::Offset<AbsoluteEncoderProfiledJointStatus> intake_status_offset =
59 intake_.Iterate(
60 unsafe_goal != nullptr ? unsafe_goal->intake() : nullptr,
61 position->intake_joint(),
62 output != nullptr ? &(output_struct.intake_joint_voltage) : nullptr,
63 status->fbb());
Theo Bafrali00e42272019-02-12 01:07:46 -080064
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
66 stilts_status_offset = stilts_.Iterate(
67 unsafe_goal != nullptr ? unsafe_goal->stilts() : nullptr,
68 position->stilts(),
69 output != nullptr ? &(output_struct.stilts_voltage) : nullptr,
70 status->fbb());
71
72 bool has_piece;
73 vacuum_.Iterate(unsafe_goal != nullptr ? unsafe_goal->suction() : nullptr,
74 position->suction_pressure(), &output_struct, &has_piece,
Theo Bafrali3274a182019-02-17 20:01:38 -080075 event_loop());
Austin Schuhe8354752019-02-17 14:59:05 -080076
Alex Perrycb7da4b2019-08-28 19:35:56 -070077 bool zeroed;
78 bool estopped;
79 {
80 PotAndAbsoluteEncoderProfiledJointStatus *elevator_status =
81 GetMutableTemporaryPointer(*status->fbb(), elevator_status_offset);
82 PotAndAbsoluteEncoderProfiledJointStatus *wrist_status =
83 GetMutableTemporaryPointer(*status->fbb(), wrist_status_offset);
84 AbsoluteEncoderProfiledJointStatus *intake_status =
85 GetMutableTemporaryPointer(*status->fbb(), intake_status_offset);
86 PotAndAbsoluteEncoderProfiledJointStatus *stilts_status =
87 GetMutableTemporaryPointer(*status->fbb(), stilts_status_offset);
Theo Bafrali00e42272019-02-12 01:07:46 -080088
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 zeroed = elevator_status->zeroed() && wrist_status->zeroed() &&
90 intake_status->zeroed() && stilts_status->zeroed();
91
92 estopped = elevator_status->estopped() || wrist_status->estopped() ||
93 intake_status->estopped() || stilts_status->estopped();
94 }
95
96 Status::Builder status_builder = status->MakeBuilder<Status>();
97
98 status_builder.add_zeroed(zeroed);
99 status_builder.add_estopped(estopped);
100 status_builder.add_has_piece(has_piece);
101
102 status_builder.add_elevator(elevator_status_offset);
103 status_builder.add_wrist(wrist_status_offset);
104 status_builder.add_intake(intake_status_offset);
105 status_builder.add_stilts(stilts_status_offset);
106
107 flatbuffers::Offset<Status> status_offset = status_builder.Finish();
108
109 Status *status_flatbuffer =
110 GetMutableTemporaryPointer(*status->fbb(), status_offset);
Theo Bafrali00e42272019-02-12 01:07:46 -0800111
Theo Bafrali09517b92019-02-16 15:59:17 -0800112 if (output) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700113 if (unsafe_goal &&
114 status_flatbuffer->intake()->position() > kMinIntakeAngleForRollers) {
115 output_struct.intake_roller_voltage = unsafe_goal->roller_voltage();
Theo Bafrali09517b92019-02-16 15:59:17 -0800116 } else {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700117 output_struct.intake_roller_voltage = 0.0;
Theo Bafrali09517b92019-02-16 15:59:17 -0800118 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700119
120 output->Send(Output::Pack(*output->fbb(), &output_struct));
Theo Bafrali09517b92019-02-16 15:59:17 -0800121 }
122
Tyler Chatow993fe282019-04-06 22:24:36 -0700123 if (unsafe_goal) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700124 if (!unsafe_goal->has_suction() || !unsafe_goal->suction()->grab_piece()) {
Tyler Chatow993fe282019-04-06 22:24:36 -0700125 wrist_.set_controller_index(0);
126 elevator_.set_controller_index(0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700127 } else if (unsafe_goal->suction()->gamepiece_mode() == 0) {
Tyler Chatow993fe282019-04-06 22:24:36 -0700128 wrist_.set_controller_index(1);
129 elevator_.set_controller_index(1);
130 } else {
131 wrist_.set_controller_index(2);
132 elevator_.set_controller_index(2);
133 }
134 }
135
Theo Bafrali00e42272019-02-12 01:07:46 -0800136 // TODO(theo) move these up when Iterate() is split
137 // update the goals
Alex Perrycb7da4b2019-08-28 19:35:56 -0700138 collision_avoidance_.UpdateGoal(status_flatbuffer, unsafe_goal);
Theo Bafrali00e42272019-02-12 01:07:46 -0800139
140 elevator_.set_min_position(collision_avoidance_.min_elevator_goal());
141 wrist_.set_min_position(collision_avoidance_.min_wrist_goal());
142 wrist_.set_max_position(collision_avoidance_.max_wrist_goal());
143 intake_.set_min_position(collision_avoidance_.min_intake_goal());
144 intake_.set_max_position(collision_avoidance_.max_intake_goal());
Sabina Davisc6329342019-03-01 20:44:42 -0800145
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700146 drivetrain_status_fetcher_.Fetch();
Austin Schuh194c43c2019-03-22 20:40:53 -0700147
Sabina Davisc6329342019-03-01 20:44:42 -0800148 if (status && unsafe_goal) {
149 // Light Logic
Alex Perrycb7da4b2019-08-28 19:35:56 -0700150 if (status_flatbuffer->estopped()) {
Sabina Davisc6329342019-03-01 20:44:42 -0800151 // Estop is red
Sabina Davis77a11cf2019-03-09 18:20:26 -0800152 SendColors(1.0, 0.0, 0.0);
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700153 } else if (drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700154 drivetrain_status_fetcher_->line_follow_logging()->frozen()) {
James Kuszmaul4c1d4f42019-03-24 13:10:00 -0700155 // Vision align is flashing white for button pressed, purple for target
156 // acquired.
Austin Schuh194c43c2019-03-22 20:40:53 -0700157 ++line_blink_count_;
158 if (line_blink_count_ < 20) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700159 if (drivetrain_status_fetcher_->line_follow_logging()->have_target()) {
James Kuszmaul4c1d4f42019-03-24 13:10:00 -0700160 SendColors(1.0, 0.0, 1.0);
161 } else {
162 SendColors(1.0, 1.0, 1.0);
163 }
Austin Schuh194c43c2019-03-22 20:40:53 -0700164 } else {
165 // And then flash with green if we have a game piece.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700166 if (status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700167 SendColors(0.0, 1.0, 0.0);
168 } else {
169 SendColors(0.0, 0.0, 0.0);
170 }
171 }
172
173 if (line_blink_count_ > 40) {
174 line_blink_count_ = 0;
175 }
Sabina Davisc6329342019-03-01 20:44:42 -0800176 } else {
Austin Schuh194c43c2019-03-22 20:40:53 -0700177 line_blink_count_ = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700178 if (status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700179 // Green if we have a game piece.
180 SendColors(0.0, 1.0, 0.0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700181 } else if ((!unsafe_goal->has_suction() ||
182 unsafe_goal->suction()->gamepiece_mode() == 0) &&
183 !status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700184 // Ball mode is orange
185 SendColors(1.0, 0.1, 0.0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700186 } else if (unsafe_goal->has_suction() &&
187 unsafe_goal->suction()->gamepiece_mode() == 1 &&
188 !status_flatbuffer->has_piece()) {
Austin Schuh194c43c2019-03-22 20:40:53 -0700189 // Disk mode is deep blue
190 SendColors(0.05, 0.1, 0.5);
191 } else {
192 SendColors(0.0, 0.0, 0.0);
193 }
Sabina Davisc6329342019-03-01 20:44:42 -0800194 }
195 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700196
197 status->Send(status_offset);
Tyler Chatowe51334a2019-01-20 16:58:16 -0800198}
199
Austin Schuhff973552019-05-19 16:49:28 -0700200void Superstructure::SendColors(float red, float green, float blue) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700201 auto builder = status_light_sender_.MakeBuilder();
Austin Schuhff973552019-05-19 16:49:28 -0700202
Alex Perrycb7da4b2019-08-28 19:35:56 -0700203 StatusLight::Builder status_light_builder =
204 builder.MakeBuilder<StatusLight>();
205 status_light_builder.add_red(red);
206 status_light_builder.add_green(green);
207 status_light_builder.add_blue(blue);
208
209 if (!builder.Send(status_light_builder.Finish())) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700210 AOS_LOG(ERROR, "Failed to send lights.\n");
Austin Schuhff973552019-05-19 16:49:28 -0700211 }
212}
213
Tyler Chatowe51334a2019-01-20 16:58:16 -0800214} // namespace superstructure
215} // namespace control_loops
Austin Schuh55a13dc2019-01-27 22:39:03 -0800216} // namespace y2019