blob: 034f72ff0f1d5f7d7e2b51b233731ba4495b5ccc [file] [log] [blame]
Milind Upadhyay225156b2022-02-25 22:42:12 -08001#ifndef Y2022_CONTROL_LOOPS_SUPERSTRUCTURE_COLLISION_AVOIDENCE_H_
2#define Y2022_CONTROL_LOOPS_SUPERSTRUCTURE_COLLISION_AVOIDENCE_H_
3
4#include <cmath>
5
6#include "frc971/control_loops/control_loops_generated.h"
7#include "frc971/control_loops/profiled_subsystem_generated.h"
8#include "y2022/control_loops/superstructure/superstructure_goal_generated.h"
9#include "y2022/control_loops/superstructure/superstructure_status_generated.h"
10
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080011namespace y2022::control_loops::superstructure {
Milind Upadhyay225156b2022-02-25 22:42:12 -080012
13// Returns the wrapped angle as well as number of wraps (positive or negative).
14// The returned angle will be inside [0.0, 2 * M_PI).
15std::pair<double, int> WrapTurretAngle(double turret_angle);
16
17// Returns the absolute angle given the wrapped angle and number of wraps.
18double UnwrapTurretAngle(double wrapped, int wraps);
19
Milind Upadhyay8e2582b2022-03-06 15:14:15 -080020// Checks if theta is between theta_min and theta_max. Expects all angles to be
21// wrapped from 0 to 2pi
22bool AngleInRange(double theta, double theta_min, double theta_max);
23
Milind Upadhyay225156b2022-02-25 22:42:12 -080024// 1. Prevent the turret from moving if the intake is up
Henry Speiser28288cc2022-03-09 22:59:24 -080025// and prevent the back of the turret (where the catapult is)
26// from colliding with the intake when it's up.
Milind Upadhyay225156b2022-02-25 22:42:12 -080027// 2. If the intake is up, drop it so it is not in the way
28// 3. Move the turret to the desired position.
29// 4. When the turret moves away, if the intake is down, move it back up.
30class CollisionAvoidance {
31 public:
32 struct Status {
33 double intake_front_position;
34 double intake_back_position;
35 double turret_position;
Henry Speiser28288cc2022-03-09 22:59:24 -080036 bool shooting;
Milind Upadhyay225156b2022-02-25 22:42:12 -080037
38 bool operator==(const Status &s) const {
39 return (intake_front_position == s.intake_front_position &&
40 intake_back_position == s.intake_back_position &&
Henry Speiser28288cc2022-03-09 22:59:24 -080041 turret_position == s.turret_position && shooting == s.shooting);
Milind Upadhyay225156b2022-02-25 22:42:12 -080042 }
43 bool operator!=(const Status &s) const { return !(*this == s); }
44 };
45
46 // TODO(henry): put actual constants here.
47
48 // Reference angles between which the turret will be careful
Austin Schuh00ec0da2022-03-13 18:10:35 -070049 static constexpr double kCollisionZoneTurret = M_PI * 7.0 / 18.0;
Milind Upadhyay225156b2022-02-25 22:42:12 -080050
51 // For the turret, 0 rad is pointing straight forwards
52 static constexpr double kMinCollisionZoneFrontTurret =
53 M_PI - kCollisionZoneTurret;
54 static constexpr double kMaxCollisionZoneFrontTurret =
55 M_PI + kCollisionZoneTurret;
56
Milind Upadhyay8e2582b2022-03-06 15:14:15 -080057 static constexpr double kMinCollisionZoneBackTurret =
58 (2.0 * M_PI) - kCollisionZoneTurret;
Milind Upadhyay225156b2022-02-25 22:42:12 -080059 static constexpr double kMaxCollisionZoneBackTurret = kCollisionZoneTurret;
60
milind-u3e297d32022-03-05 10:31:12 -080061 // Maximum position of the intake to avoid collisions
Austin Schuh463abe22022-04-15 19:15:49 -070062 static constexpr double kCollisionZoneIntake = 1.30;
Milind Upadhyay225156b2022-02-25 22:42:12 -080063
Henry Speiser28288cc2022-03-09 22:59:24 -080064 // Tolerances for the subsystems
Milind Upadhyay225156b2022-02-25 22:42:12 -080065 static constexpr double kEpsTurret = 0.05;
Milind Upadhyay225156b2022-02-25 22:42:12 -080066 static constexpr double kEpsIntake = 0.05;
67
68 CollisionAvoidance();
69
70 // Reports if the superstructure is collided.
71 bool IsCollided(const Status &status);
72 // Checks if there is a collision on either intake.
73 bool TurretCollided(double intake_position, double turret_position,
74 double min_turret_collision_position,
75 double max_turret_collision_position);
76 // Checks and alters goals to make sure they're safe.
Ravago Jones5da06352022-03-04 20:26:24 -080077 void UpdateGoal(
78 const Status &status,
79 const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
80 *unsafe_turret_goal);
Milind Upadhyay225156b2022-02-25 22:42:12 -080081 // Limits if goal is in collision spots.
Henry Speiser28288cc2022-03-09 22:59:24 -080082 void CalculateAvoidance(bool intake_front, bool catapult,
83 double intake_position, double turret_position,
84 double turret_goal, double min_turret_collision_goal,
85 double max_turret_collision_goal);
Milind Upadhyay225156b2022-02-25 22:42:12 -080086
87 // Returns the goals to give to the respective control loops in
88 // superstructure.
89 double min_turret_goal() const { return min_turret_goal_; }
90 double max_turret_goal() const { return max_turret_goal_; }
91 double min_intake_front_goal() const { return min_intake_front_goal_; }
92 double max_intake_front_goal() const { return max_intake_front_goal_; }
93 double min_intake_back_goal() const { return min_intake_back_goal_; }
94 double max_intake_back_goal() const { return max_intake_back_goal_; }
95
96 void update_max_turret_goal(double max_turret_goal) {
97 max_turret_goal_ = ::std::min(max_turret_goal, max_turret_goal_);
98 }
99 void update_min_turret_goal(double min_turret_goal) {
100 min_turret_goal_ = ::std::max(min_turret_goal, min_turret_goal_);
101 }
102 void update_max_intake_front_goal(double max_intake_front_goal) {
103 max_intake_front_goal_ =
104 ::std::min(max_intake_front_goal, max_intake_front_goal_);
105 }
106 void update_min_intake_front_goal(double min_intake_front_goal) {
107 min_intake_front_goal_ =
108 ::std::max(min_intake_front_goal, min_intake_front_goal_);
109 }
110 void update_max_intake_back_goal(double max_intake_back_goal) {
111 max_intake_back_goal_ =
112 ::std::min(max_intake_back_goal, max_intake_back_goal_);
113 }
114 void update_min_intake_back_goal(double min_intake_back_goal) {
115 min_intake_back_goal_ =
116 ::std::max(min_intake_back_goal, min_intake_back_goal_);
117 }
118
119 private:
120 void clear_min_intake_front_goal() {
121 min_intake_front_goal_ = -::std::numeric_limits<double>::infinity();
122 }
123 void clear_max_intake_front_goal() {
124 max_intake_front_goal_ = ::std::numeric_limits<double>::infinity();
125 }
126 void clear_min_intake_back_goal() {
127 min_intake_back_goal_ = -::std::numeric_limits<double>::infinity();
128 }
129 void clear_max_intake_back_goal() {
130 max_intake_back_goal_ = ::std::numeric_limits<double>::infinity();
131 }
132 void clear_min_turret_goal() {
133 min_turret_goal_ = -::std::numeric_limits<double>::infinity();
134 }
135 void clear_max_turret_goal() {
136 max_turret_goal_ = ::std::numeric_limits<double>::infinity();
137 }
138
139 double min_intake_front_goal_;
140 double max_intake_front_goal_;
141 double min_intake_back_goal_;
142 double max_intake_back_goal_;
143 double min_turret_goal_;
144 double max_turret_goal_;
145};
146
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800147} // namespace y2022::control_loops::superstructure
Milind Upadhyay225156b2022-02-25 22:42:12 -0800148
149#endif