blob: 9580ef880a9e410f20f5bafd7c65906098a02744 [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
Sabina Davis0f31d3f2020-02-20 20:41:00 -080015namespace {
Austin Schuh5c40ea42021-09-26 13:28:03 -070016const double kVelocityTolerance = 2.0;
Sabina Davis0f31d3f2020-02-20 20:41:00 -080017} // namespace
18
Sabina Davisedf89472020-02-17 15:27:37 -080019Shooter::Shooter()
Austin Schuh80476772021-03-06 20:17:36 -080020 : finisher_(
21 finisher::MakeIntegralFinisherLoop(), finisher::kBemf,
22 // There are 2 motors. So the current limit per motor is going to be
23 // using resistance * 2 to un-parallel the motor resistances.
24 finisher::kResistance * 2.0),
Austin Schuhe8ca06a2020-03-07 22:27:39 -080025 accelerator_left_(accelerator::MakeIntegralAcceleratorLoop(),
26 accelerator::kBemf, accelerator::kResistance),
27 accelerator_right_(accelerator::MakeIntegralAcceleratorLoop(),
28 accelerator::kBemf, accelerator::kResistance) {}
Sabina Davisedf89472020-02-17 15:27:37 -080029
Sabina Davis0f31d3f2020-02-20 20:41:00 -080030bool Shooter::UpToSpeed(const ShooterGoal *goal) {
31 return (
32 std::abs(goal->velocity_finisher() - finisher_.avg_angular_velocity()) <
33 kVelocityTolerance &&
34 std::abs(goal->velocity_accelerator() -
35 accelerator_left_.avg_angular_velocity()) < kVelocityTolerance &&
36 std::abs(goal->velocity_accelerator() -
Austin Schuh2efe1682021-03-06 22:47:15 -080037 accelerator_right_.avg_angular_velocity()) <
38 kVelocityTolerance &&
39 std::abs(goal->velocity_finisher() - finisher_.velocity()) <
40 kVelocityTolerance &&
Sabina Davis0f31d3f2020-02-20 20:41:00 -080041 std::abs(goal->velocity_accelerator() - accelerator_left_.velocity()) <
42 kVelocityTolerance &&
43 std::abs(goal->velocity_accelerator() - accelerator_right_.velocity()) <
44 kVelocityTolerance);
45}
46
Sabina Davisedf89472020-02-17 15:27:37 -080047flatbuffers::Offset<ShooterStatus> Shooter::RunIteration(
48 const ShooterGoal *goal, const ShooterPosition *position,
Sabina Davis0f31d3f2020-02-20 20:41:00 -080049 flatbuffers::FlatBufferBuilder *fbb, OutputT *output,
50 const aos::monotonic_clock::time_point position_timestamp) {
milind-u7baf7342021-08-25 18:31:26 -070051 const double last_finisher_velocity = finisher_.velocity();
52
Sabina Davis0f31d3f2020-02-20 20:41:00 -080053 // Update position, output, and status for our two shooter sides.
54 finisher_.set_position(position->theta_finisher(), position_timestamp);
55 accelerator_left_.set_position(position->theta_accelerator_left(),
56 position_timestamp);
57 accelerator_right_.set_position(position->theta_accelerator_right(),
58 position_timestamp);
Sabina Davisedf89472020-02-17 15:27:37 -080059
Sabina Davis0f31d3f2020-02-20 20:41:00 -080060 // Update goal.
61 if (goal) {
milind-u7baf7342021-08-25 18:31:26 -070062 if (std::abs(goal->velocity_finisher() - finisher_goal()) >=
63 kVelocityTolerance) {
64 finisher_goal_changed_ = true;
65 last_finisher_velocity_max_ = 0.0;
66 }
67
Sabina Davis0f31d3f2020-02-20 20:41:00 -080068 finisher_.set_goal(goal->velocity_finisher());
69 accelerator_left_.set_goal(goal->velocity_accelerator());
70 accelerator_right_.set_goal(goal->velocity_accelerator());
Austin Schuh43b9ae92020-02-29 23:08:38 -080071 }
Sabina Davis0f31d3f2020-02-20 20:41:00 -080072
Austin Schuh43b9ae92020-02-29 23:08:38 -080073 finisher_.Update(output == nullptr);
74 accelerator_left_.Update(output == nullptr);
75 accelerator_right_.Update(output == nullptr);
76
77 if (goal) {
Sabina Davis0f31d3f2020-02-20 20:41:00 -080078 if (UpToSpeed(goal) && goal->velocity_finisher() > kVelocityTolerance &&
79 goal->velocity_accelerator() > kVelocityTolerance) {
80 ready_ = true;
81 } else {
82 ready_ = false;
83 }
84 }
85
Sabina Davisedf89472020-02-17 15:27:37 -080086 flatbuffers::Offset<FlywheelControllerStatus> finisher_status_offset =
87 finisher_.SetStatus(fbb);
88 flatbuffers::Offset<FlywheelControllerStatus> accelerator_left_status_offset =
89 accelerator_left_.SetStatus(fbb);
90 flatbuffers::Offset<FlywheelControllerStatus>
91 accelerator_right_status_offset = accelerator_right_.SetStatus(fbb);
92
93 ShooterStatusBuilder status_builder(*fbb);
94
95 status_builder.add_finisher(finisher_status_offset);
96 status_builder.add_accelerator_left(accelerator_left_status_offset);
97 status_builder.add_accelerator_right(accelerator_right_status_offset);
Austin Schuh5c40ea42021-09-26 13:28:03 -070098 status_builder.add_ready(ready());
Sabina Davisedf89472020-02-17 15:27:37 -080099
milind-u7baf7342021-08-25 18:31:26 -0700100 if (finisher_goal_changed_) {
101 // If we have caught up to the new goal, we can start detecting if a ball
102 // was shot.
103 finisher_goal_changed_ =
104 (std::abs(finisher_.velocity() - finisher_goal()) > kVelocityTolerance);
105 }
106
107 if (!finisher_goal_changed_) {
108 const bool finisher_was_accelerating = finisher_accelerating_;
109 finisher_accelerating_ = (finisher_.velocity() > last_finisher_velocity);
110 if (finisher_was_accelerating && !finisher_accelerating_) {
111 last_finisher_velocity_max_ = std::min(
112 last_finisher_velocity, static_cast<double>(finisher_goal()));
113 }
114
115 const double finisher_velocity_dip =
116 last_finisher_velocity_max_ - finisher_.velocity();
117
118 if (finisher_velocity_dip < kVelocityTolerance && ball_in_finisher_) {
119 // If we detected a ball in the flywheel and now the angular velocity has
120 // come back up close to the last local maximum or is greater than it, the
121 // ball has been shot.
122 balls_shot_++;
123 ball_in_finisher_ = false;
124 } else if (!ball_in_finisher_ && (finisher_goal() > kVelocityTolerance)) {
125 // There is probably a ball in the flywheel if the angular
126 // velocity is atleast kMinVelocityErrorWithBall less than the last local
127 // maximum.
128 ball_in_finisher_ =
129 (finisher_velocity_dip >= kMinFinisherVelocityDipWithBall);
130 }
131 }
132
133 status_builder.add_balls_shot(balls_shot_);
134
Sabina Davisedf89472020-02-17 15:27:37 -0800135 if (output) {
136 output->finisher_voltage = finisher_.voltage();
137 output->accelerator_left_voltage = accelerator_left_.voltage();
138 output->accelerator_right_voltage = accelerator_right_.voltage();
139 }
140
141 return status_builder.Finish();
142}
143
144} // namespace shooter
145} // namespace superstructure
146} // namespace control_loops
147} // namespace y2020