blob: 9d71eed40dd119bc794270af1f75780ffc9cb60e [file] [log] [blame]
Austin Schuhcd3237a2017-02-18 14:19:26 -08001#ifndef Y2017_CONTROL_LOOPS_INDEXER_INDEXER_H_
2#define Y2017_CONTROL_LOOPS_INDEXER_INDEXER_H_
3
4#include <memory>
5
6#include "aos/common/controls/control_loop.h"
7#include "aos/common/time.h"
8#include "frc971/control_loops/state_feedback_loop.h"
9
10#include "y2017/control_loops/superstructure/indexer/indexer_integral_plant.h"
11#include "y2017/control_loops/superstructure/superstructure.q.h"
12
13namespace y2017 {
14namespace control_loops {
15namespace superstructure {
16namespace indexer {
17
18class IndexerController {
19 public:
20 IndexerController();
21
22 // Sets the velocity goal in radians/sec
23 void set_goal(double angular_velocity_goal);
24 // Sets the current encoder position in radians
25 void set_position(double current_position);
26
27 // Populates the status structure.
28 void SetStatus(control_loops::IndexerStatus *status);
29
30 // Returns the control loop calculated voltage.
31 double voltage() const;
32
33 // Returns the instantaneous velocity.
34 double velocity() const { return loop_->X_hat(1, 0); }
35
36 double dt_velocity() const { return dt_velocity_; }
37
38 double error() const { return error_; }
39
40 // Returns true if the indexer is stuck.
41 bool IsStuck() const;
Austin Schuha4dd26d2017-02-24 19:14:39 -080042 double StuckVoltage() const;
Austin Schuhcd3237a2017-02-18 14:19:26 -080043
44 // Executes the control loop for a cycle.
45 void Update(bool disabled);
46
47 // Resets the kalman filter and any other internal state.
48 void Reset();
49 // Resets the voltage error for when we reverse directions.
50 void PartialReset();
51
52 private:
53 // The current sensor measurement.
54 Eigen::Matrix<double, 1, 1> Y_;
55 // The control loop.
56 ::std::unique_ptr<StateFeedbackLoop<3, 1, 1>> loop_;
57
58 // The stuck indexer detector
59 ::std::unique_ptr<StateFeedbackLoop<3, 1, 1>> stuck_indexer_detector_;
60
61 // History array for calculating a filtered angular velocity.
62 static constexpr int kHistoryLength = 5;
63 ::std::array<double, kHistoryLength> history_;
64 ptrdiff_t history_position_ = 0;
65
66 double error_ = 0.0;
67 double dt_velocity_ = 0.0;
68 double last_position_ = 0.0;
69 double average_angular_velocity_ = 0.0;
70 double position_error_ = 0.0;
71
72 Eigen::Matrix<double, 3, 1> X_hat_current_;
73 Eigen::Matrix<double, 3, 1> stuck_indexer_X_hat_current_;
74
75 bool ready_ = false;
76 bool reset_ = false;
77
78 DISALLOW_COPY_AND_ASSIGN(IndexerController);
79};
80
81class Indexer {
82 public:
83 Indexer() {}
84
85 enum class State {
86 // The system is running correctly, no stuck condition detected.
87 RUNNING = 0,
88 // The system is reversing to unjam.
89 REVERSING = 1
90 };
91
92 // Iterates the indexer control loop one cycle. position and status must
93 // never be nullptr. goal can be nullptr if no goal exists, and output should
94 // be nullptr if disabled.
95 void Iterate(const control_loops::IndexerGoal *goal, const double *position,
96 double *output, control_loops::IndexerStatus *status);
97
98 // Sets the indexer up to reset the kalman filter next time Iterate is called.
99 void Reset();
100
101 State state() const { return state_; }
102
103 private:
104 IndexerController indexer_;
105
106 State state_ = State::RUNNING;
107
108 // The last time that we transitioned from RUNNING to REVERSING or the
109 // reverse. Used to implement the timeouts.
110 ::aos::monotonic_clock::time_point last_transition_time_ =
111 ::aos::monotonic_clock::min_time;
112
113 DISALLOW_COPY_AND_ASSIGN(Indexer);
114};
115
116} // namespace indexer
117} // namespace superstructure
118} // namespace control_loops
119} // namespace y2017
120
121#endif // Y2017_CONTROL_LOOPS_INDEXER_INDEXER_H_