blob: 04b8e8a32b8537004f41775affcc2667b2fb1d47 [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
11namespace y2022 {
12namespace control_loops {
13namespace superstructure {
14
15// Returns the wrapped angle as well as number of wraps (positive or negative).
16// The returned angle will be inside [0.0, 2 * M_PI).
17std::pair<double, int> WrapTurretAngle(double turret_angle);
18
19// Returns the absolute angle given the wrapped angle and number of wraps.
20double UnwrapTurretAngle(double wrapped, int wraps);
21
Milind Upadhyay8e2582b2022-03-06 15:14:15 -080022// Checks if theta is between theta_min and theta_max. Expects all angles to be
23// wrapped from 0 to 2pi
24bool AngleInRange(double theta, double theta_min, double theta_max);
25
Milind Upadhyay225156b2022-02-25 22:42:12 -080026// 1. Prevent the turret from moving if the intake is up
Henry Speiser28288cc2022-03-09 22:59:24 -080027// and prevent the back of the turret (where the catapult is)
28// from colliding with the intake when it's up.
Milind Upadhyay225156b2022-02-25 22:42:12 -080029// 2. If the intake is up, drop it so it is not in the way
30// 3. Move the turret to the desired position.
31// 4. When the turret moves away, if the intake is down, move it back up.
32class CollisionAvoidance {
33 public:
34 struct Status {
35 double intake_front_position;
36 double intake_back_position;
37 double turret_position;
Henry Speiser28288cc2022-03-09 22:59:24 -080038 bool shooting;
Milind Upadhyay225156b2022-02-25 22:42:12 -080039
40 bool operator==(const Status &s) const {
41 return (intake_front_position == s.intake_front_position &&
42 intake_back_position == s.intake_back_position &&
Henry Speiser28288cc2022-03-09 22:59:24 -080043 turret_position == s.turret_position && shooting == s.shooting);
Milind Upadhyay225156b2022-02-25 22:42:12 -080044 }
45 bool operator!=(const Status &s) const { return !(*this == s); }
46 };
47
48 // TODO(henry): put actual constants here.
49
50 // Reference angles between which the turret will be careful
Austin Schuh00ec0da2022-03-13 18:10:35 -070051 static constexpr double kCollisionZoneTurret = M_PI * 7.0 / 18.0;
Milind Upadhyay225156b2022-02-25 22:42:12 -080052
53 // For the turret, 0 rad is pointing straight forwards
54 static constexpr double kMinCollisionZoneFrontTurret =
55 M_PI - kCollisionZoneTurret;
56 static constexpr double kMaxCollisionZoneFrontTurret =
57 M_PI + kCollisionZoneTurret;
58
Milind Upadhyay8e2582b2022-03-06 15:14:15 -080059 static constexpr double kMinCollisionZoneBackTurret =
60 (2.0 * M_PI) - kCollisionZoneTurret;
Milind Upadhyay225156b2022-02-25 22:42:12 -080061 static constexpr double kMaxCollisionZoneBackTurret = kCollisionZoneTurret;
62
milind-u3e297d32022-03-05 10:31:12 -080063 // Maximum position of the intake to avoid collisions
Austin Schuh00ec0da2022-03-13 18:10:35 -070064 static constexpr double kCollisionZoneIntake = 1.33;
Milind Upadhyay225156b2022-02-25 22:42:12 -080065
Henry Speiser28288cc2022-03-09 22:59:24 -080066 // Tolerances for the subsystems
Milind Upadhyay225156b2022-02-25 22:42:12 -080067 static constexpr double kEpsTurret = 0.05;
Milind Upadhyay225156b2022-02-25 22:42:12 -080068 static constexpr double kEpsIntake = 0.05;
69
70 CollisionAvoidance();
71
72 // Reports if the superstructure is collided.
73 bool IsCollided(const Status &status);
74 // Checks if there is a collision on either intake.
75 bool TurretCollided(double intake_position, double turret_position,
76 double min_turret_collision_position,
77 double max_turret_collision_position);
78 // Checks and alters goals to make sure they're safe.
Ravago Jones5da06352022-03-04 20:26:24 -080079 void UpdateGoal(
80 const Status &status,
81 const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
82 *unsafe_turret_goal);
Milind Upadhyay225156b2022-02-25 22:42:12 -080083 // Limits if goal is in collision spots.
Henry Speiser28288cc2022-03-09 22:59:24 -080084 void CalculateAvoidance(bool intake_front, bool catapult,
85 double intake_position, double turret_position,
86 double turret_goal, double min_turret_collision_goal,
87 double max_turret_collision_goal);
Milind Upadhyay225156b2022-02-25 22:42:12 -080088
89 // Returns the goals to give to the respective control loops in
90 // superstructure.
91 double min_turret_goal() const { return min_turret_goal_; }
92 double max_turret_goal() const { return max_turret_goal_; }
93 double min_intake_front_goal() const { return min_intake_front_goal_; }
94 double max_intake_front_goal() const { return max_intake_front_goal_; }
95 double min_intake_back_goal() const { return min_intake_back_goal_; }
96 double max_intake_back_goal() const { return max_intake_back_goal_; }
97
98 void update_max_turret_goal(double max_turret_goal) {
99 max_turret_goal_ = ::std::min(max_turret_goal, max_turret_goal_);
100 }
101 void update_min_turret_goal(double min_turret_goal) {
102 min_turret_goal_ = ::std::max(min_turret_goal, min_turret_goal_);
103 }
104 void update_max_intake_front_goal(double max_intake_front_goal) {
105 max_intake_front_goal_ =
106 ::std::min(max_intake_front_goal, max_intake_front_goal_);
107 }
108 void update_min_intake_front_goal(double min_intake_front_goal) {
109 min_intake_front_goal_ =
110 ::std::max(min_intake_front_goal, min_intake_front_goal_);
111 }
112 void update_max_intake_back_goal(double max_intake_back_goal) {
113 max_intake_back_goal_ =
114 ::std::min(max_intake_back_goal, max_intake_back_goal_);
115 }
116 void update_min_intake_back_goal(double min_intake_back_goal) {
117 min_intake_back_goal_ =
118 ::std::max(min_intake_back_goal, min_intake_back_goal_);
119 }
120
121 private:
122 void clear_min_intake_front_goal() {
123 min_intake_front_goal_ = -::std::numeric_limits<double>::infinity();
124 }
125 void clear_max_intake_front_goal() {
126 max_intake_front_goal_ = ::std::numeric_limits<double>::infinity();
127 }
128 void clear_min_intake_back_goal() {
129 min_intake_back_goal_ = -::std::numeric_limits<double>::infinity();
130 }
131 void clear_max_intake_back_goal() {
132 max_intake_back_goal_ = ::std::numeric_limits<double>::infinity();
133 }
134 void clear_min_turret_goal() {
135 min_turret_goal_ = -::std::numeric_limits<double>::infinity();
136 }
137 void clear_max_turret_goal() {
138 max_turret_goal_ = ::std::numeric_limits<double>::infinity();
139 }
140
141 double min_intake_front_goal_;
142 double max_intake_front_goal_;
143 double min_intake_back_goal_;
144 double max_intake_back_goal_;
145 double min_turret_goal_;
146 double max_turret_goal_;
147};
148
149} // namespace superstructure
150} // namespace control_loops
151} // namespace y2022
152
153#endif