blob: bd82fe094537d155bb356b301d3d1a2487fb5a69 [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();
Austin Schuh027fd622024-03-01 21:26:07 -080015 clear_min_extend_goal();
16 clear_max_extend_goal();
Niko Sohmersac4d8872024-02-23 13:55:47 -080017}
18
19bool CollisionAvoidance::IsCollided(const CollisionAvoidance::Status &status) {
20 // Checks if intake front is collided.
21 if (TurretCollided(status.intake_pivot_position, status.turret_position,
Austin Schuh027fd622024-03-01 21:26:07 -080022 status.extend_position)) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080023 return true;
24 }
25
26 return false;
27}
28
29bool AngleInRange(double theta, double theta_min, double theta_max) {
30 return (
31 (theta >= theta_min && theta <= theta_max) ||
32 (theta_min > theta_max && (theta >= theta_min || theta <= theta_max)));
33}
34
35bool CollisionAvoidance::TurretCollided(double intake_position,
36 double turret_position,
Austin Schuh027fd622024-03-01 21:26:07 -080037 double extend_position) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080038 // Checks if turret is in the collision area.
Austin Schuh027fd622024-03-01 21:26:07 -080039 if (AngleInRange(turret_position, kMinCollisionZoneTurret,
40 kMaxCollisionZoneTurret)) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080041 // Returns true if the intake is raised.
42 if (intake_position > kCollisionZoneIntake) {
43 return true;
44 }
Niko Sohmersac4d8872024-02-23 13:55:47 -080045 }
Austin Schuh027fd622024-03-01 21:26:07 -080046 return ExtendCollided(intake_position, turret_position, extend_position);
47}
48
49bool CollisionAvoidance::ExtendCollided(double /*intake_position*/,
50 double turret_position,
51 double extend_position) {
52 // Checks if turret is in the collision area.
53 if (!AngleInRange(turret_position, kSafeTurretExtendedPosition - kEpsTurret,
54 kSafeTurretExtendedPosition + kEpsTurret)) {
55 // Returns true if the extend is raised.
56 if (extend_position > kMinCollisionZoneExtend) {
57 return true;
58 }
59 }
60
Niko Sohmersac4d8872024-02-23 13:55:47 -080061 return false;
62}
63
64void CollisionAvoidance::UpdateGoal(const CollisionAvoidance::Status &status,
Austin Schuh027fd622024-03-01 21:26:07 -080065 const double turret_goal_position,
66 const double extend_goal_position) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080067 // Start with our constraints being wide open.
Austin Schuh027fd622024-03-01 21:26:07 -080068 clear_min_extend_goal();
69 clear_max_extend_goal();
Niko Sohmersac4d8872024-02-23 13:55:47 -080070 clear_max_turret_goal();
71 clear_min_turret_goal();
72 clear_max_intake_pivot_goal();
73 clear_min_intake_pivot_goal();
74
75 const double intake_pivot_position = status.intake_pivot_position;
76 const double turret_position = status.turret_position;
Austin Schuh027fd622024-03-01 21:26:07 -080077 const double extend_position = status.extend_position;
Niko Sohmersac4d8872024-02-23 13:55:47 -080078
79 const double turret_goal = turret_goal_position;
Austin Schuh027fd622024-03-01 21:26:07 -080080 const double extend_goal = extend_goal_position;
Niko Sohmersac4d8872024-02-23 13:55:47 -080081
82 // Calculating the avoidance with the intake
83
Austin Schuh027fd622024-03-01 21:26:07 -080084 CalculateAvoidance(intake_pivot_position, turret_position, extend_position,
85 turret_goal, extend_goal);
Niko Sohmersac4d8872024-02-23 13:55:47 -080086}
87
Austin Schuh027fd622024-03-01 21:26:07 -080088void CollisionAvoidance::CalculateAvoidance(double intake_position,
Niko Sohmersac4d8872024-02-23 13:55:47 -080089 double turret_position,
Austin Schuh027fd622024-03-01 21:26:07 -080090 double extend_position,
Niko Sohmersac4d8872024-02-23 13:55:47 -080091 double turret_goal,
Austin Schuh027fd622024-03-01 21:26:07 -080092 double extend_goal) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080093 // If the turret goal is in a collison zone or moving through one, limit
94 // intake.
Austin Schuh027fd622024-03-01 21:26:07 -080095 const bool turret_intake_pos_unsafe = AngleInRange(
96 turret_position, kMinCollisionZoneTurret, kMaxCollisionZoneTurret);
97 const bool turret_extend_pos_unsafe =
98 turret_position > kEpsTurret + kSafeTurretExtendedPosition ||
99 turret_position < -kEpsTurret + kSafeTurretExtendedPosition;
100
101 const bool extend_goal_unsafe =
102 extend_goal > kMinCollisionZoneExtend - kEpsExtend;
103 const bool extend_position_unsafe =
104 extend_position > kMinCollisionZoneExtend - kEpsExtend;
105
106 // OK, we are trying to move the extend, and need the turret to be at 0.
107 // Pretend that's the goal.
108 if (extend_goal_unsafe || extend_position_unsafe) {
109 turret_goal = kSafeTurretExtendedPosition;
110 }
Niko Sohmersac4d8872024-02-23 13:55:47 -0800111
112 const bool turret_moving_forward = (turret_goal > turret_position);
113
114 // Check if the closest angles are going to be passed
115 const bool turret_moving_past_intake =
Austin Schuh027fd622024-03-01 21:26:07 -0800116 ((turret_moving_forward && (turret_position <= kMaxCollisionZoneTurret &&
117 turret_goal >= kMinCollisionZoneTurret)) ||
118 (!turret_moving_forward && (turret_position >= kMinCollisionZoneTurret &&
119 turret_goal <= kMaxCollisionZoneTurret)));
Niko Sohmersac4d8872024-02-23 13:55:47 -0800120
Austin Schuh027fd622024-03-01 21:26:07 -0800121 if (turret_intake_pos_unsafe || turret_moving_past_intake) {
Niko Sohmersac4d8872024-02-23 13:55:47 -0800122 // If the turret is unsafe, limit the intake
Austin Schuh027fd622024-03-01 21:26:07 -0800123 update_max_intake_pivot_goal(kCollisionZoneIntake - kEpsIntake);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800124
125 // If the intake is in the way, limit the turret until moved. Otherwise,
126 // let'errip!
Austin Schuh027fd622024-03-01 21:26:07 -0800127 if (!turret_intake_pos_unsafe && (intake_position > kCollisionZoneIntake)) {
Niko Sohmersac4d8872024-02-23 13:55:47 -0800128 if (turret_position <
Austin Schuh027fd622024-03-01 21:26:07 -0800129 (kMinCollisionZoneTurret + kMaxCollisionZoneTurret) / 2.) {
130 update_max_turret_goal(kMinCollisionZoneTurret - kEpsTurret);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800131 } else {
Austin Schuh027fd622024-03-01 21:26:07 -0800132 update_min_turret_goal(kMaxCollisionZoneTurret + kEpsTurret);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800133 }
134 }
135 }
Austin Schuh027fd622024-03-01 21:26:07 -0800136
137 // OK, the logic is pretty simple. The turret needs to be at
138 // kSafeTurretExtendedPosition any time extend is > kMinCollisionZoneExtend.
139 //
140 // Extend can't go up if the turret isn't near 0.
141 if (turret_extend_pos_unsafe) {
142 update_max_extend_goal(kMinCollisionZoneExtend - kEpsExtend);
143 }
144
145 // Turret is bound to the safe position if extend wants to be, or is unsafe.
146 if (extend_goal_unsafe || extend_position_unsafe) {
147 // If the turret isn't allowed to go to 0, don't drive it there.
148 if (min_turret_goal() < kSafeTurretExtendedPosition &&
149 max_turret_goal() > kSafeTurretExtendedPosition) {
150 update_min_turret_goal(kSafeTurretExtendedPosition);
151 update_max_turret_goal(kSafeTurretExtendedPosition);
152 }
153 }
Niko Sohmersac4d8872024-02-23 13:55:47 -0800154}
155
156} // namespace y2024::control_loops::superstructure