Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 1 | #ifndef Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_ |
| 2 | #define Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_ |
| 3 | |
| 4 | #include <memory> |
| 5 | |
| 6 | #include "aos/common/controls/control_loop.h" |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 7 | #include "aos/common/util/trapezoid_profile.h" |
Austin Schuh | 10c2d11 | 2016-02-14 13:42:28 -0800 | [diff] [blame] | 8 | #include "frc971/control_loops/state_feedback_loop.h" |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 9 | |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 10 | #include "frc971/zeroing/zeroing.h" |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 11 | #include "y2016/control_loops/superstructure/superstructure.q.h" |
Austin Schuh | 10c2d11 | 2016-02-14 13:42:28 -0800 | [diff] [blame] | 12 | #include "y2016/control_loops/superstructure/superstructure_controls.h" |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 13 | |
| 14 | namespace y2016 { |
| 15 | namespace control_loops { |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 16 | namespace superstructure { |
| 17 | namespace testing { |
Philipp Schrader | 0119eb1 | 2016-02-15 18:16:21 +0000 | [diff] [blame^] | 18 | class SuperstructureTest_RespectsRange_Test; |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 19 | class SuperstructureTest_DisabledGoalTest_Test; |
Diana Vandenberg | e2843c6 | 2016-02-13 17:44:20 -0800 | [diff] [blame] | 20 | class SuperstructureTest_ArmZeroingErrorTest_Test; |
| 21 | class SuperstructureTest_IntakeZeroingErrorTest_Test; |
Philipp Schrader | 0119eb1 | 2016-02-15 18:16:21 +0000 | [diff] [blame^] | 22 | class SuperstructureTest_UpperHardstopStartup_Test; |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 23 | } // namespace testing |
| 24 | |
Philipp Schrader | 0119eb1 | 2016-02-15 18:16:21 +0000 | [diff] [blame^] | 25 | // Helper class to prevent parts from crashing into each other. The parts in |
| 26 | // question here are: the frame, the arm (plus shooter), and the intake. |
| 27 | // Assumptions: |
| 28 | // - The shoulder, the wrist, and intake are horizontal when at angle 0. |
| 29 | // - The arm (i.e. shoulder) and shooter (i.e. wrist) are stored when they are |
| 30 | // both at zero degrees. |
| 31 | // - The intake at angle 0 is in a position to help get a ball in the robot. |
| 32 | // - The intake at angle PI is in a "stowed" position. In other words, it is |
| 33 | // folded over the arm and shooter when they are also in a stowed position. |
| 34 | // - The shooter must remain horizontal when the arm is folding into the robot. |
| 35 | // Otherwise, the shooter will collide with the frame. |
| 36 | // - The arm has priority over the intake. If the arm wants to move in such a |
| 37 | // way that interferes with the intake's movement then the intake must move |
| 38 | // out of the way. |
| 39 | class CollisionAvoidance { |
| 40 | public: |
| 41 | // Set up collision avoidance for an arm and intake. |
| 42 | CollisionAvoidance(Intake *intake, Arm *arm) : intake_(intake), arm_(arm) {} |
| 43 | |
| 44 | // This function accepts goals for the intake and the arm and modifies them |
| 45 | // in such a way that collisions between all the different parts of the robot |
| 46 | // are avoided. The modified goals are then sent to the arm and intake as |
| 47 | // unprofiled goals. |
| 48 | void UpdateGoal(double shoulder_angle_goal, double wrist_angle_goal, |
| 49 | double intake_angle_goal); |
| 50 | |
| 51 | // TODO(phil): Verify that these numbers actually make sense. Someone needs |
| 52 | // to verify these either on the CAD or the real robot. |
| 53 | |
| 54 | // The shoulder angle (in radians) below which the shooter must be in a |
| 55 | // stowing position. In other words the wrist must be at angle zero if the |
| 56 | // shoulder is below this angle. |
| 57 | static constexpr double kMinShoulderAngleForHorizontalShooter = 0.1; |
| 58 | |
| 59 | // The shoulder angle (in radians) below which the arm as a whole has the |
| 60 | // potential to interfere with the intake. |
| 61 | static constexpr double kMinShoulderAngleForIntakeInterference = M_PI / 3.0; |
| 62 | |
| 63 | // The intake angle (in radians) above which the intake can interfere (i.e. |
| 64 | // collide) with the arm and/or shooter. |
| 65 | static constexpr double kMaxIntakeAngleBeforeArmInterference = M_PI / 2.0; |
| 66 | |
| 67 | // The maximum absolute angle (in radians) that the wrist must be below in |
| 68 | // order for the shouler to be allowed to move below |
| 69 | // kMinShoulderAngleForHorizontalShooter. In other words, only allow the arm |
| 70 | // to move down into the belly pan if the shooter is horizontal, ready to |
| 71 | // also be placed into the belly pan. |
| 72 | static constexpr double kMaxWristAngleForSafeArmStowing = 0.01; |
| 73 | |
| 74 | // The shoulder angle (in radians) below which the intake can safely move |
| 75 | // into the collision zone. This is necessary when the robot wants to fold up |
| 76 | // completely (i.e. stow the arm, shooter, and intake). |
| 77 | static constexpr double kMaxShoulderAngleUntilSafeIntakeStowing = 0.01; |
| 78 | |
| 79 | private: |
| 80 | Intake *intake_; |
| 81 | Arm *arm_; |
| 82 | }; |
| 83 | |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 84 | class Superstructure |
| 85 | : public ::aos::controls::ControlLoop<control_loops::SuperstructureQueue> { |
| 86 | public: |
| 87 | explicit Superstructure( |
| 88 | control_loops::SuperstructureQueue *my_superstructure = |
| 89 | &control_loops::superstructure_queue); |
Adam Snaider | 0677972 | 2016-02-14 15:26:22 -0800 | [diff] [blame] | 90 | |
| 91 | // This is the angle above which we will do a HIGH_ARM_ZERO, and below which |
| 92 | // we will do a LOW_ARM_ZERO. |
| 93 | static constexpr double kShoulderMiddleAngle = M_PI / 4.0; |
| 94 | // This is the large scale movement tolerance. |
| 95 | static constexpr double kLooseTolerance = 0.05; |
| 96 | |
| 97 | // This is the small scale movement tolerance. |
| 98 | static constexpr double kTightTolerance = 0.01; |
| 99 | |
| 100 | // This is the angle such that the intake will clear the arm when the shooter |
| 101 | // is level. |
| 102 | static constexpr double kIntakeUpperClear = 1.1; |
| 103 | // This is the angle such that the intake will clear the arm when the shooter |
| 104 | // is at almost any position. |
| 105 | static constexpr double kIntakeLowerClear = 0.5; |
| 106 | |
| 107 | // This is the angle that the shoulder will go to when doing the |
| 108 | // HIGH_ARM_ZERO. |
| 109 | static constexpr double kShoulderUpAngle = M_PI / 2.0; |
| 110 | |
| 111 | // This is the angle that the shoulder will go down to when landing in the |
| 112 | // bellypan. |
| 113 | static constexpr double kShoulderLanded = -0.02; |
| 114 | |
| 115 | // This is the angle below which we consider the wrist close enough to level |
| 116 | // that we should move it to level before doing anything. |
| 117 | static constexpr double kWristAlmostLevel = 0.10; |
| 118 | |
| 119 | // This is the angle that the shoulder will go down to when raising up before |
| 120 | // leveling the shooter for calibration. |
| 121 | static constexpr double kShoulderWristClearAngle = 0.6; |
| 122 | |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 123 | enum State { |
Adam Snaider | 0677972 | 2016-02-14 15:26:22 -0800 | [diff] [blame] | 124 | // Wait for all the filters to be ready before starting the initialization |
| 125 | // process. |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 126 | UNINITIALIZED = 0, |
Adam Snaider | 0677972 | 2016-02-14 15:26:22 -0800 | [diff] [blame] | 127 | |
| 128 | // We now are ready to decide how to zero. Decide what to do once we are |
| 129 | // enabled. |
| 130 | DISABLED_INITIALIZED = 1, |
| 131 | |
| 132 | // Lift the arm up out of the way. |
| 133 | HIGH_ARM_ZERO_LIFT_ARM = 2, |
| 134 | |
| 135 | HIGH_ARM_ZERO_LEVEL_SHOOTER = 3, |
| 136 | |
| 137 | HIGH_ARM_ZERO_MOVE_INTAKE_OUT = 4, |
| 138 | |
| 139 | HIGH_ARM_ZERO_LOWER_ARM = 6, |
| 140 | |
| 141 | LOW_ARM_ZERO_LOWER_INTAKE = 7, |
| 142 | LOW_ARM_ZERO_MAYBE_LEVEL_SHOOTER = 8, |
| 143 | LOW_ARM_ZERO_LIFT_SHOULDER = 9, |
| 144 | LOW_ARM_ZERO_LEVEL_SHOOTER = 11, |
| 145 | // Run, but limit power to zeroing voltages. |
| 146 | SLOW_RUNNING = 12, |
| 147 | // Run with full power. |
| 148 | RUNNING = 13, |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 149 | // Internal error caused the superstructure to abort. |
Adam Snaider | 0677972 | 2016-02-14 15:26:22 -0800 | [diff] [blame] | 150 | ESTOP = 14, |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 151 | }; |
| 152 | |
| 153 | State state() const { return state_; } |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 154 | |
Adam Snaider | 0677972 | 2016-02-14 15:26:22 -0800 | [diff] [blame] | 155 | // Returns the value to move the joint to such that it will stay below |
| 156 | // reference_angle starting at current_angle, but move at least move_distance |
| 157 | static double MoveButKeepBelow(double reference_angle, double current_angle, |
| 158 | double move_distance); |
| 159 | // Returns the value to move the joint to such that it will stay above |
| 160 | // reference_angle starting at current_angle, but move at least move_distance |
| 161 | static double MoveButKeepAbove(double reference_angle, double current_angle, |
| 162 | double move_distance); |
| 163 | |
Philipp Schrader | 0119eb1 | 2016-02-15 18:16:21 +0000 | [diff] [blame^] | 164 | // Returns true if collision avoidance is turned on. False if not. |
| 165 | bool collision_avoidance_enabled() { return collision_avoidance_enabled_; } |
| 166 | |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 167 | protected: |
| 168 | virtual void RunIteration( |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 169 | const control_loops::SuperstructureQueue::Goal *unsafe_goal, |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 170 | const control_loops::SuperstructureQueue::Position *position, |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 171 | control_loops::SuperstructureQueue::Output *output, |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 172 | control_loops::SuperstructureQueue::Status *status) override; |
| 173 | |
| 174 | private: |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 175 | friend class testing::SuperstructureTest_DisabledGoalTest_Test; |
Diana Vandenberg | e2843c6 | 2016-02-13 17:44:20 -0800 | [diff] [blame] | 176 | friend class testing::SuperstructureTest_ArmZeroingErrorTest_Test; |
| 177 | friend class testing::SuperstructureTest_IntakeZeroingErrorTest_Test; |
Philipp Schrader | 0119eb1 | 2016-02-15 18:16:21 +0000 | [diff] [blame^] | 178 | friend class testing::SuperstructureTest_RespectsRange_Test; |
| 179 | friend class testing::SuperstructureTest_UpperHardstopStartup_Test; |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 180 | Intake intake_; |
| 181 | Arm arm_; |
| 182 | |
Philipp Schrader | 0119eb1 | 2016-02-15 18:16:21 +0000 | [diff] [blame^] | 183 | CollisionAvoidance collision_avoidance_; |
| 184 | |
| 185 | // NOTE: Only touch this if you absolutely know what you're doing! |
| 186 | bool collision_avoidance_enabled_ = true; |
| 187 | |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 188 | State state_ = UNINITIALIZED; |
| 189 | State last_state_ = UNINITIALIZED; |
| 190 | |
Adam Snaider | 0677972 | 2016-02-14 15:26:22 -0800 | [diff] [blame] | 191 | // Returns true if the profile has finished, and the joint is within the |
| 192 | // specified tolerance. |
| 193 | bool IsArmNear(double tolerance); |
| 194 | bool IsArmNear(double shoulder_tolerance, double wrist_tolerance); |
| 195 | bool IsIntakeNear(double tolerance); |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 196 | |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 197 | DISALLOW_COPY_AND_ASSIGN(Superstructure); |
| 198 | }; |
| 199 | |
Austin Schuh | 2fc10fa | 2016-02-08 00:44:34 -0800 | [diff] [blame] | 200 | } // namespace superstructure |
Comran Morshed | 25f81a0 | 2016-01-23 13:40:10 +0000 | [diff] [blame] | 201 | } // namespace control_loops |
| 202 | } // namespace y2016 |
| 203 | |
| 204 | #endif // Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_ |