blob: 27922051555abb54be8e691ed0c7f72e23c8e427 [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"
Maxwell Henderson34242992024-01-07 12:39:11 -08008#include "y2020/control_loops/superstructure/accelerator/integral_accelerator_plant.h"
Sabina Davisedf89472020-02-17 15:27:37 -08009#include "y2020/control_loops/superstructure/finisher/finisher_plant.h"
Maxwell Henderson34242992024-01-07 12:39:11 -080010#include "y2020/control_loops/superstructure/finisher/integral_finisher_plant.h"
Sabina Davisedf89472020-02-17 15:27:37 -080011
Stephan Pleinesf63bde82024-01-13 15:59:33 -080012namespace y2020::control_loops::superstructure::shooter {
Sabina Davisedf89472020-02-17 15:27:37 -080013
14Shooter::Shooter()
Austin Schuh80476772021-03-06 20:17:36 -080015 : finisher_(
16 finisher::MakeIntegralFinisherLoop(), finisher::kBemf,
17 // There are 2 motors. So the current limit per motor is going to be
18 // using resistance * 2 to un-parallel the motor resistances.
19 finisher::kResistance * 2.0),
Austin Schuhe8ca06a2020-03-07 22:27:39 -080020 accelerator_left_(accelerator::MakeIntegralAcceleratorLoop(),
21 accelerator::kBemf, accelerator::kResistance),
22 accelerator_right_(accelerator::MakeIntegralAcceleratorLoop(),
23 accelerator::kBemf, accelerator::kResistance) {}
Sabina Davisedf89472020-02-17 15:27:37 -080024
Austin Schuh01d81c32021-11-06 22:59:56 -070025void Shooter::UpToSpeed(const ShooterGoal *goal) {
milind-u0beb7dc2021-10-16 19:31:33 -070026 finisher_ready_ =
27 (std::abs(goal->velocity_finisher() - finisher_.avg_angular_velocity()) <
28 kVelocityToleranceFinisher &&
29 std::abs(goal->velocity_finisher() - finisher_.velocity()) <
milind-u2450f1a2021-11-06 19:01:49 -070030 kVelocityToleranceFinisher &&
31 goal->velocity_finisher() > kVelocityToleranceFinisher);
milind-u0beb7dc2021-10-16 19:31:33 -070032 accelerator_ready_ =
33 (std::abs(goal->velocity_accelerator() -
34 accelerator_left_.avg_angular_velocity()) <
35 kVelocityToleranceAccelerator &&
36 std::abs(goal->velocity_accelerator() -
37 accelerator_right_.avg_angular_velocity()) <
38 kVelocityToleranceAccelerator &&
39 std::abs(goal->velocity_accelerator() - accelerator_left_.velocity()) <
40 kVelocityToleranceAccelerator &&
41 std::abs(goal->velocity_accelerator() - accelerator_right_.velocity()) <
milind-u2450f1a2021-11-06 19:01:49 -070042 kVelocityToleranceAccelerator &&
43 goal->velocity_accelerator() > kVelocityToleranceAccelerator);
Sabina Davis0f31d3f2020-02-20 20:41:00 -080044}
45
Sabina Davisedf89472020-02-17 15:27:37 -080046flatbuffers::Offset<ShooterStatus> Shooter::RunIteration(
47 const ShooterGoal *goal, const ShooterPosition *position,
Sabina Davis0f31d3f2020-02-20 20:41:00 -080048 flatbuffers::FlatBufferBuilder *fbb, OutputT *output,
49 const aos::monotonic_clock::time_point position_timestamp) {
milind-u7baf7342021-08-25 18:31:26 -070050 const double last_finisher_velocity = finisher_.velocity();
51
Sabina Davis0f31d3f2020-02-20 20:41:00 -080052 // Update position, output, and status for our two shooter sides.
53 finisher_.set_position(position->theta_finisher(), position_timestamp);
54 accelerator_left_.set_position(position->theta_accelerator_left(),
55 position_timestamp);
56 accelerator_right_.set_position(position->theta_accelerator_right(),
57 position_timestamp);
Sabina Davisedf89472020-02-17 15:27:37 -080058
Sabina Davis0f31d3f2020-02-20 20:41:00 -080059 // Update goal.
60 if (goal) {
milind-u7baf7342021-08-25 18:31:26 -070061 if (std::abs(goal->velocity_finisher() - finisher_goal()) >=
milind-u78f21b72021-10-10 13:47:28 -070062 kVelocityToleranceFinisher) {
milind-u7baf7342021-08-25 18:31:26 -070063 finisher_goal_changed_ = true;
64 last_finisher_velocity_max_ = 0.0;
65 }
66
Sabina Davis0f31d3f2020-02-20 20:41:00 -080067 finisher_.set_goal(goal->velocity_finisher());
68 accelerator_left_.set_goal(goal->velocity_accelerator());
69 accelerator_right_.set_goal(goal->velocity_accelerator());
Austin Schuh43b9ae92020-02-29 23:08:38 -080070 }
Sabina Davis0f31d3f2020-02-20 20:41:00 -080071
Austin Schuh43b9ae92020-02-29 23:08:38 -080072 finisher_.Update(output == nullptr);
73 accelerator_left_.Update(output == nullptr);
74 accelerator_right_.Update(output == nullptr);
75
76 if (goal) {
Austin Schuh01d81c32021-11-06 22:59:56 -070077 UpToSpeed(goal);
Sabina Davis0f31d3f2020-02-20 20:41:00 -080078 }
79
Maxwell Henderson34242992024-01-07 12:39:11 -080080 flatbuffers::Offset<frc971::control_loops::flywheel::FlywheelControllerStatus>
81 finisher_status_offset = finisher_.SetStatus(fbb);
82 flatbuffers::Offset<frc971::control_loops::flywheel::FlywheelControllerStatus>
83 accelerator_left_status_offset = accelerator_left_.SetStatus(fbb);
84 flatbuffers::Offset<frc971::control_loops::flywheel::FlywheelControllerStatus>
Sabina Davisedf89472020-02-17 15:27:37 -080085 accelerator_right_status_offset = accelerator_right_.SetStatus(fbb);
86
87 ShooterStatusBuilder status_builder(*fbb);
88
89 status_builder.add_finisher(finisher_status_offset);
90 status_builder.add_accelerator_left(accelerator_left_status_offset);
91 status_builder.add_accelerator_right(accelerator_right_status_offset);
Austin Schuh5c40ea42021-09-26 13:28:03 -070092 status_builder.add_ready(ready());
Sabina Davisedf89472020-02-17 15:27:37 -080093
milind-u7baf7342021-08-25 18:31:26 -070094 if (finisher_goal_changed_) {
95 // If we have caught up to the new goal, we can start detecting if a ball
96 // was shot.
milind-u78f21b72021-10-10 13:47:28 -070097 finisher_goal_changed_ = (std::abs(finisher_.velocity() - finisher_goal()) >
98 kVelocityToleranceFinisher);
milind-u7baf7342021-08-25 18:31:26 -070099 }
100
101 if (!finisher_goal_changed_) {
102 const bool finisher_was_accelerating = finisher_accelerating_;
103 finisher_accelerating_ = (finisher_.velocity() > last_finisher_velocity);
104 if (finisher_was_accelerating && !finisher_accelerating_) {
105 last_finisher_velocity_max_ = std::min(
106 last_finisher_velocity, static_cast<double>(finisher_goal()));
107 }
108
109 const double finisher_velocity_dip =
110 last_finisher_velocity_max_ - finisher_.velocity();
111
milind-u78f21b72021-10-10 13:47:28 -0700112 if (finisher_velocity_dip < kVelocityToleranceFinisher &&
113 ball_in_finisher_) {
milind-u7baf7342021-08-25 18:31:26 -0700114 // If we detected a ball in the flywheel and now the angular velocity has
115 // come back up close to the last local maximum or is greater than it, the
116 // ball has been shot.
117 balls_shot_++;
Austin Schuheb240f62021-11-07 19:57:06 -0800118 VLOG(1) << "Shot ball at " << position_timestamp;
milind-u7baf7342021-08-25 18:31:26 -0700119 ball_in_finisher_ = false;
milind-u78f21b72021-10-10 13:47:28 -0700120 } else if (!ball_in_finisher_ &&
121 (finisher_goal() > kVelocityToleranceFinisher)) {
milind-u7baf7342021-08-25 18:31:26 -0700122 // There is probably a ball in the flywheel if the angular
123 // velocity is atleast kMinVelocityErrorWithBall less than the last local
124 // maximum.
125 ball_in_finisher_ =
126 (finisher_velocity_dip >= kMinFinisherVelocityDipWithBall);
127 }
128 }
129
130 status_builder.add_balls_shot(balls_shot_);
131
Sabina Davisedf89472020-02-17 15:27:37 -0800132 if (output) {
133 output->finisher_voltage = finisher_.voltage();
134 output->accelerator_left_voltage = accelerator_left_.voltage();
135 output->accelerator_right_voltage = accelerator_right_.voltage();
136 }
137
138 return status_builder.Finish();
139}
140
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800141} // namespace y2020::control_loops::superstructure::shooter