blob: e6fa3cf7e88f6efd05f6e71c75e0f74ee67b5605 [file] [log] [blame]
Sabina Davisedf89472020-02-17 15:27:37 -08001#include "y2020/control_loops/superstructure/shooter/shooter.h"
2
3#include <chrono>
milind-u7baf7342021-08-25 18:31:26 -07004#include <cmath>
Sabina Davisedf89472020-02-17 15:27:37 -08005
6#include "aos/logging/logging.h"
7#include "y2020/control_loops/superstructure/accelerator/accelerator_plant.h"
8#include "y2020/control_loops/superstructure/finisher/finisher_plant.h"
9
10namespace y2020 {
11namespace control_loops {
12namespace superstructure {
13namespace shooter {
14
15Shooter::Shooter()
Austin Schuh80476772021-03-06 20:17:36 -080016 : finisher_(
17 finisher::MakeIntegralFinisherLoop(), finisher::kBemf,
18 // There are 2 motors. So the current limit per motor is going to be
19 // using resistance * 2 to un-parallel the motor resistances.
20 finisher::kResistance * 2.0),
Austin Schuhe8ca06a2020-03-07 22:27:39 -080021 accelerator_left_(accelerator::MakeIntegralAcceleratorLoop(),
22 accelerator::kBemf, accelerator::kResistance),
23 accelerator_right_(accelerator::MakeIntegralAcceleratorLoop(),
24 accelerator::kBemf, accelerator::kResistance) {}
Sabina Davisedf89472020-02-17 15:27:37 -080025
Sabina Davis0f31d3f2020-02-20 20:41:00 -080026bool Shooter::UpToSpeed(const ShooterGoal *goal) {
milind-u0beb7dc2021-10-16 19:31:33 -070027 finisher_ready_ =
28 (std::abs(goal->velocity_finisher() - finisher_.avg_angular_velocity()) <
29 kVelocityToleranceFinisher &&
30 std::abs(goal->velocity_finisher() - finisher_.velocity()) <
milind-u2450f1a2021-11-06 19:01:49 -070031 kVelocityToleranceFinisher &&
32 goal->velocity_finisher() > kVelocityToleranceFinisher);
milind-u0beb7dc2021-10-16 19:31:33 -070033 accelerator_ready_ =
34 (std::abs(goal->velocity_accelerator() -
35 accelerator_left_.avg_angular_velocity()) <
36 kVelocityToleranceAccelerator &&
37 std::abs(goal->velocity_accelerator() -
38 accelerator_right_.avg_angular_velocity()) <
39 kVelocityToleranceAccelerator &&
40 std::abs(goal->velocity_accelerator() - accelerator_left_.velocity()) <
41 kVelocityToleranceAccelerator &&
42 std::abs(goal->velocity_accelerator() - accelerator_right_.velocity()) <
milind-u2450f1a2021-11-06 19:01:49 -070043 kVelocityToleranceAccelerator &&
44 goal->velocity_accelerator() > kVelocityToleranceAccelerator);
milind-u0beb7dc2021-10-16 19:31:33 -070045 return (finisher_ready_ && accelerator_ready_);
Sabina Davis0f31d3f2020-02-20 20:41:00 -080046}
47
Sabina Davisedf89472020-02-17 15:27:37 -080048flatbuffers::Offset<ShooterStatus> Shooter::RunIteration(
49 const ShooterGoal *goal, const ShooterPosition *position,
Sabina Davis0f31d3f2020-02-20 20:41:00 -080050 flatbuffers::FlatBufferBuilder *fbb, OutputT *output,
51 const aos::monotonic_clock::time_point position_timestamp) {
milind-u7baf7342021-08-25 18:31:26 -070052 const double last_finisher_velocity = finisher_.velocity();
53
Sabina Davis0f31d3f2020-02-20 20:41:00 -080054 // Update position, output, and status for our two shooter sides.
55 finisher_.set_position(position->theta_finisher(), position_timestamp);
56 accelerator_left_.set_position(position->theta_accelerator_left(),
57 position_timestamp);
58 accelerator_right_.set_position(position->theta_accelerator_right(),
59 position_timestamp);
Sabina Davisedf89472020-02-17 15:27:37 -080060
Sabina Davis0f31d3f2020-02-20 20:41:00 -080061 // Update goal.
62 if (goal) {
milind-u7baf7342021-08-25 18:31:26 -070063 if (std::abs(goal->velocity_finisher() - finisher_goal()) >=
milind-u78f21b72021-10-10 13:47:28 -070064 kVelocityToleranceFinisher) {
milind-u7baf7342021-08-25 18:31:26 -070065 finisher_goal_changed_ = true;
66 last_finisher_velocity_max_ = 0.0;
67 }
68
Sabina Davis0f31d3f2020-02-20 20:41:00 -080069 finisher_.set_goal(goal->velocity_finisher());
70 accelerator_left_.set_goal(goal->velocity_accelerator());
71 accelerator_right_.set_goal(goal->velocity_accelerator());
Austin Schuh43b9ae92020-02-29 23:08:38 -080072 }
Sabina Davis0f31d3f2020-02-20 20:41:00 -080073
Austin Schuh43b9ae92020-02-29 23:08:38 -080074 finisher_.Update(output == nullptr);
75 accelerator_left_.Update(output == nullptr);
76 accelerator_right_.Update(output == nullptr);
77
78 if (goal) {
milind-u2450f1a2021-11-06 19:01:49 -070079 ready_ = UpToSpeed(goal);
Sabina Davis0f31d3f2020-02-20 20:41:00 -080080 }
81
Sabina Davisedf89472020-02-17 15:27:37 -080082 flatbuffers::Offset<FlywheelControllerStatus> finisher_status_offset =
83 finisher_.SetStatus(fbb);
84 flatbuffers::Offset<FlywheelControllerStatus> accelerator_left_status_offset =
85 accelerator_left_.SetStatus(fbb);
86 flatbuffers::Offset<FlywheelControllerStatus>
87 accelerator_right_status_offset = accelerator_right_.SetStatus(fbb);
88
89 ShooterStatusBuilder status_builder(*fbb);
90
91 status_builder.add_finisher(finisher_status_offset);
92 status_builder.add_accelerator_left(accelerator_left_status_offset);
93 status_builder.add_accelerator_right(accelerator_right_status_offset);
Austin Schuh5c40ea42021-09-26 13:28:03 -070094 status_builder.add_ready(ready());
Sabina Davisedf89472020-02-17 15:27:37 -080095
milind-u7baf7342021-08-25 18:31:26 -070096 if (finisher_goal_changed_) {
97 // If we have caught up to the new goal, we can start detecting if a ball
98 // was shot.
milind-u78f21b72021-10-10 13:47:28 -070099 finisher_goal_changed_ = (std::abs(finisher_.velocity() - finisher_goal()) >
100 kVelocityToleranceFinisher);
milind-u7baf7342021-08-25 18:31:26 -0700101 }
102
103 if (!finisher_goal_changed_) {
104 const bool finisher_was_accelerating = finisher_accelerating_;
105 finisher_accelerating_ = (finisher_.velocity() > last_finisher_velocity);
106 if (finisher_was_accelerating && !finisher_accelerating_) {
107 last_finisher_velocity_max_ = std::min(
108 last_finisher_velocity, static_cast<double>(finisher_goal()));
109 }
110
111 const double finisher_velocity_dip =
112 last_finisher_velocity_max_ - finisher_.velocity();
113
milind-u78f21b72021-10-10 13:47:28 -0700114 if (finisher_velocity_dip < kVelocityToleranceFinisher &&
115 ball_in_finisher_) {
milind-u7baf7342021-08-25 18:31:26 -0700116 // If we detected a ball in the flywheel and now the angular velocity has
117 // come back up close to the last local maximum or is greater than it, the
118 // ball has been shot.
119 balls_shot_++;
120 ball_in_finisher_ = false;
milind-u78f21b72021-10-10 13:47:28 -0700121 } else if (!ball_in_finisher_ &&
122 (finisher_goal() > kVelocityToleranceFinisher)) {
milind-u7baf7342021-08-25 18:31:26 -0700123 // There is probably a ball in the flywheel if the angular
124 // velocity is atleast kMinVelocityErrorWithBall less than the last local
125 // maximum.
126 ball_in_finisher_ =
127 (finisher_velocity_dip >= kMinFinisherVelocityDipWithBall);
128 }
129 }
130
131 status_builder.add_balls_shot(balls_shot_);
132
Sabina Davisedf89472020-02-17 15:27:37 -0800133 if (output) {
134 output->finisher_voltage = finisher_.voltage();
135 output->accelerator_left_voltage = accelerator_left_.voltage();
136 output->accelerator_right_voltage = accelerator_right_.voltage();
137 }
138
139 return status_builder.Finish();
140}
141
142} // namespace shooter
143} // namespace superstructure
144} // namespace control_loops
145} // namespace y2020