blob: 0594af0f55ec84e8d7f5dd50c74c2ec7d18eb5f0 [file] [log] [blame]
Niko Sohmersac4d8872024-02-23 13:55:47 -08001#include "y2024/control_loops/superstructure/collision_avoidance.h"
2
3#include <cmath>
4
5#include "absl/functional/bind_front.h"
6#include "glog/logging.h"
7
8namespace y2024::control_loops::superstructure {
9
10CollisionAvoidance::CollisionAvoidance() {
11 clear_min_intake_pivot_goal();
12 clear_max_intake_pivot_goal();
13 clear_min_turret_goal();
14 clear_max_turret_goal();
15}
16
17bool CollisionAvoidance::IsCollided(const CollisionAvoidance::Status &status) {
18 // Checks if intake front is collided.
19 if (TurretCollided(status.intake_pivot_position, status.turret_position,
20 kMinCollisionZoneTurret, kMaxCollisionZoneTurret)) {
21 return true;
22 }
23
24 return false;
25}
26
27bool AngleInRange(double theta, double theta_min, double theta_max) {
28 return (
29 (theta >= theta_min && theta <= theta_max) ||
30 (theta_min > theta_max && (theta >= theta_min || theta <= theta_max)));
31}
32
33bool CollisionAvoidance::TurretCollided(double intake_position,
34 double turret_position,
35 double min_turret_collision_position,
36 double max_turret_collision_position) {
37 // Checks if turret is in the collision area.
38 if (AngleInRange(turret_position, min_turret_collision_position,
39 max_turret_collision_position)) {
40 // Returns true if the intake is raised.
41 if (intake_position > kCollisionZoneIntake) {
42 return true;
43 }
44 } else {
45 return false;
46 }
47 return false;
48}
49
50void CollisionAvoidance::UpdateGoal(const CollisionAvoidance::Status &status,
51 const double &turret_goal_position) {
52 // Start with our constraints being wide open.
53 clear_max_turret_goal();
54 clear_min_turret_goal();
55 clear_max_intake_pivot_goal();
56 clear_min_intake_pivot_goal();
57
58 const double intake_pivot_position = status.intake_pivot_position;
59 const double turret_position = status.turret_position;
60
61 const double turret_goal = turret_goal_position;
62
63 // Calculating the avoidance with the intake
64
65 CalculateAvoidance(true, intake_pivot_position, turret_position, turret_goal,
66 kMinCollisionZoneTurret, kMaxCollisionZoneTurret);
67}
68
69void CollisionAvoidance::CalculateAvoidance(bool intake_pivot,
70 double intake_position,
71 double turret_position,
72 double turret_goal,
73 double min_turret_collision_goal,
74 double max_turret_collision_goal) {
75 // If the turret goal is in a collison zone or moving through one, limit
76 // intake.
77 const bool turret_pos_unsafe = AngleInRange(
78 turret_position, min_turret_collision_goal, max_turret_collision_goal);
79
80 const bool turret_moving_forward = (turret_goal > turret_position);
81
82 // Check if the closest angles are going to be passed
83 const bool turret_moving_past_intake =
84 ((turret_moving_forward &&
85 (turret_position <= max_turret_collision_goal &&
86 turret_goal >= min_turret_collision_goal)) ||
87 (!turret_moving_forward &&
88 (turret_position >= min_turret_collision_goal &&
89 turret_goal <= max_turret_collision_goal)));
90
91 if (turret_pos_unsafe || turret_moving_past_intake) {
92 // If the turret is unsafe, limit the intake
93 if (intake_pivot) {
94 update_max_intake_pivot_goal(kCollisionZoneIntake - kEpsIntake);
95 }
96
97 // If the intake is in the way, limit the turret until moved. Otherwise,
98 // let'errip!
99 if (!turret_pos_unsafe && (intake_position > kCollisionZoneIntake)) {
100 if (turret_position <
101 (min_turret_collision_goal + max_turret_collision_goal / 2)) {
102 update_max_turret_goal(min_turret_collision_goal - kEpsTurret);
103 } else {
104 update_min_turret_goal(max_turret_collision_goal + kEpsTurret);
105 }
106 }
107 }
108}
109
110} // namespace y2024::control_loops::superstructure