blob: a4f3a35742729f104bf25348de4341d2d6660638 [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"
Austin Schuh99f7c6a2024-06-25 22:07:44 -07006#include "absl/log/check.h"
7#include "absl/log/log.h"
Niko Sohmersac4d8872024-02-23 13:55:47 -08008
9namespace y2024::control_loops::superstructure {
10
11CollisionAvoidance::CollisionAvoidance() {
12 clear_min_intake_pivot_goal();
13 clear_max_intake_pivot_goal();
14 clear_min_turret_goal();
15 clear_max_turret_goal();
Austin Schuh027fd622024-03-01 21:26:07 -080016 clear_min_extend_goal();
17 clear_max_extend_goal();
Niko Sohmersac4d8872024-02-23 13:55:47 -080018}
19
20bool CollisionAvoidance::IsCollided(const CollisionAvoidance::Status &status) {
21 // Checks if intake front is collided.
22 if (TurretCollided(status.intake_pivot_position, status.turret_position,
Austin Schuh027fd622024-03-01 21:26:07 -080023 status.extend_position)) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080024 return true;
25 }
26
27 return false;
28}
29
30bool AngleInRange(double theta, double theta_min, double theta_max) {
31 return (
32 (theta >= theta_min && theta <= theta_max) ||
33 (theta_min > theta_max && (theta >= theta_min || theta <= theta_max)));
34}
35
36bool CollisionAvoidance::TurretCollided(double intake_position,
37 double turret_position,
Austin Schuh027fd622024-03-01 21:26:07 -080038 double extend_position) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080039 // Checks if turret is in the collision area.
Austin Schuh027fd622024-03-01 21:26:07 -080040 if (AngleInRange(turret_position, kMinCollisionZoneTurret,
41 kMaxCollisionZoneTurret)) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080042 // Returns true if the intake is raised.
43 if (intake_position > kCollisionZoneIntake) {
44 return true;
45 }
Niko Sohmersac4d8872024-02-23 13:55:47 -080046 }
Austin Schuh027fd622024-03-01 21:26:07 -080047 return ExtendCollided(intake_position, turret_position, extend_position);
48}
49
50bool CollisionAvoidance::ExtendCollided(double /*intake_position*/,
51 double turret_position,
52 double extend_position) {
53 // Checks if turret is in the collision area.
54 if (!AngleInRange(turret_position, kSafeTurretExtendedPosition - kEpsTurret,
55 kSafeTurretExtendedPosition + kEpsTurret)) {
56 // Returns true if the extend is raised.
57 if (extend_position > kMinCollisionZoneExtend) {
58 return true;
59 }
60 }
61
Niko Sohmersac4d8872024-02-23 13:55:47 -080062 return false;
63}
64
65void CollisionAvoidance::UpdateGoal(const CollisionAvoidance::Status &status,
Austin Schuh027fd622024-03-01 21:26:07 -080066 const double turret_goal_position,
67 const double extend_goal_position) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080068 // Start with our constraints being wide open.
Austin Schuh027fd622024-03-01 21:26:07 -080069 clear_min_extend_goal();
70 clear_max_extend_goal();
Niko Sohmersac4d8872024-02-23 13:55:47 -080071 clear_max_turret_goal();
72 clear_min_turret_goal();
73 clear_max_intake_pivot_goal();
74 clear_min_intake_pivot_goal();
75
76 const double intake_pivot_position = status.intake_pivot_position;
77 const double turret_position = status.turret_position;
Austin Schuh027fd622024-03-01 21:26:07 -080078 const double extend_position = status.extend_position;
Niko Sohmersac4d8872024-02-23 13:55:47 -080079
80 const double turret_goal = turret_goal_position;
Austin Schuh027fd622024-03-01 21:26:07 -080081 const double extend_goal = extend_goal_position;
Niko Sohmersac4d8872024-02-23 13:55:47 -080082
83 // Calculating the avoidance with the intake
84
Austin Schuh027fd622024-03-01 21:26:07 -080085 CalculateAvoidance(intake_pivot_position, turret_position, extend_position,
86 turret_goal, extend_goal);
Niko Sohmersac4d8872024-02-23 13:55:47 -080087}
88
Austin Schuh027fd622024-03-01 21:26:07 -080089void CollisionAvoidance::CalculateAvoidance(double intake_position,
Niko Sohmersac4d8872024-02-23 13:55:47 -080090 double turret_position,
Austin Schuh027fd622024-03-01 21:26:07 -080091 double extend_position,
Niko Sohmersac4d8872024-02-23 13:55:47 -080092 double turret_goal,
Austin Schuh027fd622024-03-01 21:26:07 -080093 double extend_goal) {
Niko Sohmersac4d8872024-02-23 13:55:47 -080094 // If the turret goal is in a collison zone or moving through one, limit
95 // intake.
Austin Schuh027fd622024-03-01 21:26:07 -080096 const bool turret_intake_pos_unsafe = AngleInRange(
97 turret_position, kMinCollisionZoneTurret, kMaxCollisionZoneTurret);
98 const bool turret_extend_pos_unsafe =
99 turret_position > kEpsTurret + kSafeTurretExtendedPosition ||
100 turret_position < -kEpsTurret + kSafeTurretExtendedPosition;
101
102 const bool extend_goal_unsafe =
103 extend_goal > kMinCollisionZoneExtend - kEpsExtend;
104 const bool extend_position_unsafe =
105 extend_position > kMinCollisionZoneExtend - kEpsExtend;
106
107 // OK, we are trying to move the extend, and need the turret to be at 0.
108 // Pretend that's the goal.
109 if (extend_goal_unsafe || extend_position_unsafe) {
110 turret_goal = kSafeTurretExtendedPosition;
111 }
Niko Sohmersac4d8872024-02-23 13:55:47 -0800112
113 const bool turret_moving_forward = (turret_goal > turret_position);
114
115 // Check if the closest angles are going to be passed
116 const bool turret_moving_past_intake =
Austin Schuh027fd622024-03-01 21:26:07 -0800117 ((turret_moving_forward && (turret_position <= kMaxCollisionZoneTurret &&
118 turret_goal >= kMinCollisionZoneTurret)) ||
119 (!turret_moving_forward && (turret_position >= kMinCollisionZoneTurret &&
120 turret_goal <= kMaxCollisionZoneTurret)));
Niko Sohmersac4d8872024-02-23 13:55:47 -0800121
Austin Schuh027fd622024-03-01 21:26:07 -0800122 if (turret_intake_pos_unsafe || turret_moving_past_intake) {
Niko Sohmersac4d8872024-02-23 13:55:47 -0800123 // If the turret is unsafe, limit the intake
Austin Schuh027fd622024-03-01 21:26:07 -0800124 update_max_intake_pivot_goal(kCollisionZoneIntake - kEpsIntake);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800125
126 // If the intake is in the way, limit the turret until moved. Otherwise,
127 // let'errip!
Austin Schuh027fd622024-03-01 21:26:07 -0800128 if (!turret_intake_pos_unsafe && (intake_position > kCollisionZoneIntake)) {
Niko Sohmersac4d8872024-02-23 13:55:47 -0800129 if (turret_position <
Austin Schuh027fd622024-03-01 21:26:07 -0800130 (kMinCollisionZoneTurret + kMaxCollisionZoneTurret) / 2.) {
131 update_max_turret_goal(kMinCollisionZoneTurret - kEpsTurret);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800132 } else {
Austin Schuh027fd622024-03-01 21:26:07 -0800133 update_min_turret_goal(kMaxCollisionZoneTurret + kEpsTurret);
Niko Sohmersac4d8872024-02-23 13:55:47 -0800134 }
135 }
136 }
Austin Schuh027fd622024-03-01 21:26:07 -0800137
138 // OK, the logic is pretty simple. The turret needs to be at
139 // kSafeTurretExtendedPosition any time extend is > kMinCollisionZoneExtend.
140 //
141 // Extend can't go up if the turret isn't near 0.
142 if (turret_extend_pos_unsafe) {
143 update_max_extend_goal(kMinCollisionZoneExtend - kEpsExtend);
144 }
145
146 // Turret is bound to the safe position if extend wants to be, or is unsafe.
147 if (extend_goal_unsafe || extend_position_unsafe) {
148 // If the turret isn't allowed to go to 0, don't drive it there.
149 if (min_turret_goal() < kSafeTurretExtendedPosition &&
150 max_turret_goal() > kSafeTurretExtendedPosition) {
151 update_min_turret_goal(kSafeTurretExtendedPosition);
152 update_max_turret_goal(kSafeTurretExtendedPosition);
153 }
154 }
Niko Sohmersac4d8872024-02-23 13:55:47 -0800155}
156
157} // namespace y2024::control_loops::superstructure