blob: 346a33bb1a29e6b9d0ad969f712f1eb1543b8b51 [file] [log] [blame]
Comran Morshed25f81a02016-01-23 13:40:10 +00001#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 Schuh2fc10fa2016-02-08 00:44:34 -08007#include "aos/common/util/trapezoid_profile.h"
Austin Schuh10c2d112016-02-14 13:42:28 -08008#include "frc971/control_loops/state_feedback_loop.h"
Comran Morshed25f81a02016-01-23 13:40:10 +00009
Austin Schuh2fc10fa2016-02-08 00:44:34 -080010#include "frc971/zeroing/zeroing.h"
Comran Morshed25f81a02016-01-23 13:40:10 +000011#include "y2016/control_loops/superstructure/superstructure.q.h"
Austin Schuh10c2d112016-02-14 13:42:28 -080012#include "y2016/control_loops/superstructure/superstructure_controls.h"
Comran Morshed25f81a02016-01-23 13:40:10 +000013
14namespace y2016 {
15namespace control_loops {
Austin Schuh2fc10fa2016-02-08 00:44:34 -080016namespace superstructure {
17namespace testing {
Philipp Schrader0119eb12016-02-15 18:16:21 +000018class SuperstructureTest_RespectsRange_Test;
Austin Schuh2fc10fa2016-02-08 00:44:34 -080019class SuperstructureTest_DisabledGoalTest_Test;
Diana Vandenberge2843c62016-02-13 17:44:20 -080020class SuperstructureTest_ArmZeroingErrorTest_Test;
21class SuperstructureTest_IntakeZeroingErrorTest_Test;
Philipp Schrader0119eb12016-02-15 18:16:21 +000022class SuperstructureTest_UpperHardstopStartup_Test;
Austin Schuh2fc10fa2016-02-08 00:44:34 -080023} // namespace testing
24
Philipp Schrader0119eb12016-02-15 18:16:21 +000025// 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.
39class 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 Morshed25f81a02016-01-23 13:40:10 +000084class 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 Snaider06779722016-02-14 15:26:22 -080090
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 Schuh2fc10fa2016-02-08 00:44:34 -0800123 enum State {
Adam Snaider06779722016-02-14 15:26:22 -0800124 // Wait for all the filters to be ready before starting the initialization
125 // process.
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800126 UNINITIALIZED = 0,
Adam Snaider06779722016-02-14 15:26:22 -0800127
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 Schuh2fc10fa2016-02-08 00:44:34 -0800149 // Internal error caused the superstructure to abort.
Adam Snaider06779722016-02-14 15:26:22 -0800150 ESTOP = 14,
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800151 };
152
153 State state() const { return state_; }
Comran Morshed25f81a02016-01-23 13:40:10 +0000154
Adam Snaider06779722016-02-14 15:26:22 -0800155 // 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 Schrader0119eb12016-02-15 18:16:21 +0000164 // Returns true if collision avoidance is turned on. False if not.
165 bool collision_avoidance_enabled() { return collision_avoidance_enabled_; }
166
Comran Morshed25f81a02016-01-23 13:40:10 +0000167 protected:
168 virtual void RunIteration(
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800169 const control_loops::SuperstructureQueue::Goal *unsafe_goal,
Comran Morshed25f81a02016-01-23 13:40:10 +0000170 const control_loops::SuperstructureQueue::Position *position,
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800171 control_loops::SuperstructureQueue::Output *output,
Comran Morshed25f81a02016-01-23 13:40:10 +0000172 control_loops::SuperstructureQueue::Status *status) override;
173
174 private:
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800175 friend class testing::SuperstructureTest_DisabledGoalTest_Test;
Diana Vandenberge2843c62016-02-13 17:44:20 -0800176 friend class testing::SuperstructureTest_ArmZeroingErrorTest_Test;
177 friend class testing::SuperstructureTest_IntakeZeroingErrorTest_Test;
Philipp Schrader0119eb12016-02-15 18:16:21 +0000178 friend class testing::SuperstructureTest_RespectsRange_Test;
179 friend class testing::SuperstructureTest_UpperHardstopStartup_Test;
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800180 Intake intake_;
181 Arm arm_;
182
Philipp Schrader0119eb12016-02-15 18:16:21 +0000183 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 Schuh2fc10fa2016-02-08 00:44:34 -0800188 State state_ = UNINITIALIZED;
189 State last_state_ = UNINITIALIZED;
190
Adam Snaider06779722016-02-14 15:26:22 -0800191 // 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 Schuh2fc10fa2016-02-08 00:44:34 -0800196
Comran Morshed25f81a02016-01-23 13:40:10 +0000197 DISALLOW_COPY_AND_ASSIGN(Superstructure);
198};
199
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800200} // namespace superstructure
Comran Morshed25f81a02016-01-23 13:40:10 +0000201} // namespace control_loops
202} // namespace y2016
203
204#endif // Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_