blob: 615565ff9d8c9ae81bf0cd99f48354622a85dad2 [file] [log] [blame]
Austin Schuhd5ccb862017-03-11 22:06:36 -08001#ifndef Y2017_CONTROL_LOOPS_SUPERSTRUCTURE_COLUMN_COLUMN_H_
2#define Y2017_CONTROL_LOOPS_SUPERSTRUCTURE_COLUMN_COLUMN_H_
3
4#include <array>
5#include <chrono>
6#include <memory>
7#include <utility>
8
9#include "Eigen/Dense"
10
11#include "frc971/constants.h"
12#include "frc971/control_loops/profiled_subsystem.h"
13#include "frc971/control_loops/state_feedback_loop.h"
14#include "y2017/constants.h"
15#include "y2017/control_loops/superstructure/column/column_zeroing.h"
16#include "y2017/control_loops/superstructure/intake/intake.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070017#include "y2017/control_loops/superstructure/superstructure_position_generated.h"
18#include "y2017/control_loops/superstructure/superstructure_status_generated.h"
Austin Schuhac76bb32017-03-22 22:34:26 -070019#include "y2017/control_loops/superstructure/vision_time_adjuster.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070020#include "y2017/vision/vision_generated.h"
Austin Schuhd5ccb862017-03-11 22:06:36 -080021
22namespace y2017 {
23namespace control_loops {
24namespace superstructure {
25namespace column {
26
27class ColumnProfiledSubsystem
28 : public ::frc971::control_loops::ProfiledSubsystem<
29 6, 1, ColumnZeroingEstimator, 2, 2> {
30 public:
31 ColumnProfiledSubsystem(
32 ::std::unique_ptr<
33 ::frc971::control_loops::SimpleCappedStateFeedbackLoop<6, 2, 2>>
34 loop,
35 const ::y2017::constants::Values::Column &zeroing_constants,
36 const ::frc971::constants::Range &range, double default_angular_velocity,
37 double default_angular_acceleration);
38
39 // Updates our estimator with the latest position.
40 void Correct(const ColumnPosition &position);
41 // Runs the controller and profile generator for a cycle.
42 void Update(bool disabled);
43
44 // Fills out the ProfiledJointStatus structure with the current state.
Alex Perrycb7da4b2019-08-28 19:35:56 -070045 void PopulateTurretStatus(
46 TurretProfiledSubsystemStatus::Builder *status_builder,
47 flatbuffers::Offset<ColumnZeroingEstimator::State>
48 estimator_state_offset);
Austin Schuhd5ccb862017-03-11 22:06:36 -080049
50 // Forces the current goal to the provided goal, bypassing the profiler.
51 void ForceGoal(double goal_velocity, double goal);
52 // Sets the unprofiled goal. The profiler will generate a profile to go to
53 // this goal.
54 void set_indexer_unprofiled_goal(double goal_velocity);
55 void set_turret_unprofiled_goal(double unprofiled_goal);
56 void set_unprofiled_goal(double goal_velocity, double unprofiled_goal);
57 // Limits our profiles to a max velocity and acceleration for proper motion.
Alex Perrycb7da4b2019-08-28 19:35:56 -070058 void AdjustProfile(const ::frc971::ProfileParameters *profile_parameters);
Austin Schuhd5ccb862017-03-11 22:06:36 -080059 void AdjustProfile(double max_angular_velocity,
60 double max_angular_acceleration);
61
62 // Returns true if we have exceeded any hard limits.
63 bool CheckHardLimits();
64
65 // Returns the requested voltage.
66 double indexer_voltage() const { return loop_->U(0, 0); }
67 double uncapped_indexer_voltage() const { return loop_->U_uncapped(0, 0); }
68 double turret_voltage() const { return loop_->U(1, 0); }
69
70 // Returns the current Y.
71 const ::Eigen::Matrix<double, 2, 1> Y() const { return Y_; }
72 double Y(int i, int j) const { return Y_(i, j); }
73
74 // Returns the current indexer position.
75 double indexer_position() const { return Y_(0, 0); }
76
77 bool saturated() const { return saturated_; }
78
79 // Returns the current turret position.
80 double turret_position() const { return Y_(1, 0) + Y_(0, 0); }
81
82 // For testing:
83 // Triggers an estimator error.
84 void TriggerEstimatorError() { estimators_[0].TriggerError(); }
85
86 const ::frc971::constants::Range &range() const { return range_; }
87
88 bool IsIndexerStuck() const;
89 double IndexerStuckVoltage() const;
90 void PartialIndexerReset();
91 void PartialTurretReset();
Alex Perrycb7da4b2019-08-28 19:35:56 -070092 void PopulateIndexerStatus(IndexerStatus::Builder *status_builder);
Austin Schuhd5ccb862017-03-11 22:06:36 -080093
94 void AddOffset(double indexer_offset_delta, double turret_offset_delta);
95
96 protected:
97 // Limits the provided goal to the soft limits. Prints "name" when it fails
98 // to aid debugging.
99 virtual void CapGoal(const char *name, Eigen::Matrix<double, 6, 1> *goal);
100
101 private:
102 void UpdateOffset(double indexer_offset, double turret_offset);
103
104 ::std::unique_ptr<StateFeedbackLoop<6, 2, 2>> stuck_indexer_detector_;
105
106 // History array for calculating a filtered angular velocity.
107 static constexpr int kHistoryLength = 5;
108 ::std::array<double, kHistoryLength> indexer_history_;
109 ptrdiff_t indexer_history_position_ = 0;
110
111 double indexer_error_ = 0.0;
112 double indexer_dt_velocity_ = 0.0;
113 double indexer_last_position_ = 0.0;
114 double indexer_average_angular_velocity_ = 0.0;
115 double indexer_position_error_ = 0.0;
116 bool indexer_ready_ = false;
117
118 bool saturated_ = false;
119
120 Eigen::Matrix<double, 6, 1> X_hat_current_;
121 Eigen::Matrix<double, 6, 1> stuck_indexer_X_hat_current_;
122
123 aos::util::TrapezoidProfile profile_;
124
125 // Current measurement.
126 Eigen::Matrix<double, 2, 1> Y_;
127 // Current offset. Y_ = offset_ + raw_sensor;
128 Eigen::Matrix<double, 2, 1> offset_;
129
130 const ::frc971::constants::Range range_;
131
132 const double default_velocity_;
133 const double default_acceleration_;
134
135 double turret_last_position_ = 0;
136};
137
Austin Schuhd5ccb862017-03-11 22:06:36 -0800138class Column {
139 public:
Austin Schuhb6c5c852019-05-19 20:13:31 -0700140 Column(::aos::EventLoop *event_loop);
Austin Schuhd5ccb862017-03-11 22:06:36 -0800141 double goal(int row, int col) const {
142 return profiled_subsystem_.goal(row, col);
143 }
144
145 double turret_position() const {
146 return profiled_subsystem_.turret_position();
147 }
148
149 void set_freeze(bool freeze) { freeze_ = freeze; }
150
151 // The zeroing and operating voltages.
152 static constexpr double kZeroingVoltage = 5.0;
153 static constexpr double kOperatingVoltage = 12.0;
154 static constexpr double kIntakeZeroingMinDistance = 0.08;
155 static constexpr double kIntakeTolerance = 0.005;
156 static constexpr double kStuckZeroingTrackingError = 0.02;
Austin Schuh3ae47432017-04-16 19:15:46 -0700157 static constexpr double kTurretMin = -0.1;
158 static constexpr double kTurretMax = M_PI / 2.0 + 0.1;
Austin Schuhd5ccb862017-03-11 22:06:36 -0800159
Alex Perrycb7da4b2019-08-28 19:35:56 -0700160 std::pair<flatbuffers::Offset<IndexerStatus>,
161 flatbuffers::Offset<TurretProfiledSubsystemStatus>>
162 Iterate(::aos::monotonic_clock::time_point monotonic_now,
163 const IndexerGoalT *unsafe_indexer_goal,
164 const TurretGoal *unsafe_turret_goal, const ColumnPosition *position,
165 const vision::VisionStatus *vision_status, double *indexer_output,
166 double *turret_output, flatbuffers::FlatBufferBuilder *fbb,
167 // IndexerStatus *indexer_status,
168 // TurretProfiledSubsystemStatus *turret_status,
169 intake::Intake *intake);
Austin Schuhd5ccb862017-03-11 22:06:36 -0800170
171 void Reset();
172
173 enum class State : int32_t {
174 UNINITIALIZED = 0,
175 ZEROING_UNINITIALIZED = 1,
176 ZEROING_POSITIVE = 2,
177 ZEROING_NEGATIVE = 3,
178 RUNNING = 4,
179 ESTOP = 5,
180 };
181
182 enum class IndexerState : int32_t {
183 // The system is running correctly, no stuck condition detected.
184 RUNNING = 0,
185 // The system is reversing to unjam.
186 REVERSING = 1
187 };
188
189 State state() const { return state_; }
190 IndexerState indexer_state() const { return indexer_state_; }
191
192 private:
193 State state_ = State::UNINITIALIZED;
194
195 IndexerState indexer_state_ = IndexerState::RUNNING;
196
197 bool freeze_ = false;
198
Austin Schuhac76bb32017-03-22 22:34:26 -0700199 VisionTimeAdjuster vision_time_adjuster_;
200
Austin Schuhd5ccb862017-03-11 22:06:36 -0800201 // The last time that we transitioned from RUNNING to REVERSING or the
202 // reverse. Used to implement the timeouts.
203 ::aos::monotonic_clock::time_point last_transition_time_ =
204 ::aos::monotonic_clock::min_time;
205
206 ColumnProfiledSubsystem profiled_subsystem_;
Austin Schuh25db1262017-04-05 19:39:55 -0700207
208 const double vision_error_;
Austin Schuhd5ccb862017-03-11 22:06:36 -0800209};
210
211} // namespace column
212} // namespace superstructure
213} // namespace control_loops
214} // namespace y2017
215
216#endif // Y2017_CONTROL_LOOPS_SUPERSTRUCTURE_COLUMN_COLUMN_H_