WPILibC++ 2023.4.3
LinearSystemLoop.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <wpi/SymbolExports.h>
8
9#include "frc/EigenCore.h"
14#include "units/time.h"
15#include "units/voltage.h"
16
17namespace frc {
18
19/**
20 * Combines a controller, feedforward, and observer for controlling a mechanism
21 * with full state feedback.
22 *
23 * For everything in this file, "inputs" and "outputs" are defined from the
24 * perspective of the plant. This means U is an input and Y is an output
25 * (because you give the plant U (powers) and it gives you back a Y (sensor
26 * values). This is the opposite of what they mean from the perspective of the
27 * controller (U is an output because that's what goes to the motors and Y is an
28 * input because that's what comes back from the sensors).
29 *
30 * For more on the underlying math, read
31 * https://file.tavsys.net/control/controls-engineering-in-frc.pdf.
32 *
33 * @tparam States Number of states.
34 * @tparam Inputs Number of inputs.
35 * @tparam Outputs Number of outputs.
36 */
37template <int States, int Inputs, int Outputs>
39 public:
43
44 /**
45 * Constructs a state-space loop with the given plant, controller, and
46 * observer. By default, the initial reference is all zeros. Users should
47 * call reset with the initial system state before enabling the loop. This
48 * constructor assumes that the input(s) to this system are voltage.
49 *
50 * @param plant State-space plant.
51 * @param controller State-space controller.
52 * @param observer State-space observer.
53 * @param maxVoltage The maximum voltage that can be applied. Commonly 12.
54 * @param dt The nominal timestep.
55 */
59 units::volt_t maxVoltage, units::second_t dt)
61 plant, controller, observer,
62 [=](const InputVector& u) {
63 return frc::DesaturateInputVector<Inputs>(u, maxVoltage.value());
64 },
65 dt) {}
66
67 /**
68 * Constructs a state-space loop with the given plant, controller, and
69 * observer. By default, the initial reference is all zeros. Users should
70 * call reset with the initial system state before enabling the loop. This
71 * constructor assumes that the input(s) to this system are voltage.
72 *
73 * @param plant State-space plant.
74 * @param controller State-space controller.
75 * @param observer State-space observer.
76 * @param clampFunction The function used to clamp the input vector.
77 * @param dt The nominal timestep.
78 */
82 std::function<InputVector(const InputVector&)> clampFunction,
83 units::second_t dt)
85 controller,
86 LinearPlantInversionFeedforward<States, Inputs>{plant, dt},
87 observer, clampFunction) {}
88
89 /**
90 * Constructs a state-space loop with the given controller, feedforward and
91 * observer. By default, the initial reference is all zeros. Users should
92 * call reset with the initial system state.
93 *
94 * @param controller State-space controller.
95 * @param feedforward Plant inversion feedforward.
96 * @param observer State-space observer.
97 * @param maxVoltage The maximum voltage that can be applied. Assumes
98 * that the inputs are voltages.
99 */
103 KalmanFilter<States, Inputs, Outputs>& observer, units::volt_t maxVoltage)
105 controller, feedforward, observer, [=](const InputVector& u) {
106 return frc::DesaturateInputVector<Inputs>(u, maxVoltage.value());
107 }) {}
108
109 /**
110 * Constructs a state-space loop with the given controller, feedforward,
111 * observer and clamp function. By default, the initial reference is all
112 * zeros. Users should call reset with the initial system state.
113 *
114 * @param controller State-space controller.
115 * @param feedforward Plant-inversion feedforward.
116 * @param observer State-space observer.
117 * @param clampFunction The function used to clamp the input vector.
118 */
123 std::function<InputVector(const InputVector&)> clampFunction)
124 : m_controller(&controller),
125 m_feedforward(feedforward),
126 m_observer(&observer),
127 m_clampFunc(clampFunction) {
128 m_nextR.setZero();
129 Reset(m_nextR);
130 }
131
134
135 /**
136 * Returns the observer's state estimate x-hat.
137 */
138 const StateVector& Xhat() const { return m_observer->Xhat(); }
139
140 /**
141 * Returns an element of the observer's state estimate x-hat.
142 *
143 * @param i Row of x-hat.
144 */
145 double Xhat(int i) const { return m_observer->Xhat(i); }
146
147 /**
148 * Returns the controller's next reference r.
149 */
150 const StateVector& NextR() const { return m_nextR; }
151
152 /**
153 * Returns an element of the controller's next reference r.
154 *
155 * @param i Row of r.
156 */
157 double NextR(int i) const { return NextR()(i); }
158
159 /**
160 * Returns the controller's calculated control input u.
161 */
162 InputVector U() const {
163 return ClampInput(m_controller->U() + m_feedforward.Uff());
164 }
165
166 /**
167 * Returns an element of the controller's calculated control input u.
168 *
169 * @param i Row of u.
170 */
171 double U(int i) const { return U()(i); }
172
173 /**
174 * Set the initial state estimate x-hat.
175 *
176 * @param xHat The initial state estimate x-hat.
177 */
178 void SetXhat(const StateVector& xHat) { m_observer->SetXhat(xHat); }
179
180 /**
181 * Set an element of the initial state estimate x-hat.
182 *
183 * @param i Row of x-hat.
184 * @param value Value for element of x-hat.
185 */
186 void SetXhat(int i, double value) { m_observer->SetXhat(i, value); }
187
188 /**
189 * Set the next reference r.
190 *
191 * @param nextR Next reference.
192 */
193 void SetNextR(const StateVector& nextR) { m_nextR = nextR; }
194
195 /**
196 * Return the controller used internally.
197 */
199 return *m_controller;
200 }
201
202 /**
203 * Return the feedforward used internally.
204 *
205 * @return the feedforward used internally.
206 */
208 return m_feedforward;
209 }
210
211 /**
212 * Return the observer used internally.
213 */
215 return *m_observer;
216 }
217
218 /**
219 * Zeroes reference r and controller output u. The previous reference
220 * of the PlantInversionFeedforward and the initial state estimate of
221 * the KalmanFilter are set to the initial state provided.
222 *
223 * @param initialState The initial state.
224 */
225 void Reset(const StateVector& initialState) {
226 m_nextR.setZero();
227 m_controller->Reset();
228 m_feedforward.Reset(initialState);
229 m_observer->SetXhat(initialState);
230 }
231
232 /**
233 * Returns difference between reference r and current state x-hat.
234 */
235 StateVector Error() const { return m_controller->R() - m_observer->Xhat(); }
236
237 /**
238 * Correct the state estimate x-hat using the measurements in y.
239 *
240 * @param y Measurement vector.
241 */
242 void Correct(const OutputVector& y) { m_observer->Correct(U(), y); }
243
244 /**
245 * Sets new controller output, projects model forward, and runs observer
246 * prediction.
247 *
248 * After calling this, the user should send the elements of u to the
249 * actuators.
250 *
251 * @param dt Timestep for model update.
252 */
253 void Predict(units::second_t dt) {
254 InputVector u =
255 ClampInput(m_controller->Calculate(m_observer->Xhat(), m_nextR) +
256 m_feedforward.Calculate(m_nextR));
257 m_observer->Predict(u, dt);
258 }
259
260 /**
261 * Clamps input vector between system's minimum and maximum allowable input.
262 *
263 * @param u Input vector to clamp.
264 * @return Clamped input vector.
265 */
266 InputVector ClampInput(const InputVector& u) const { return m_clampFunc(u); }
267
268 protected:
272
273 /**
274 * Clamping function.
275 */
276 std::function<InputVector(const InputVector&)> m_clampFunc;
277
278 // Reference to go to in the next cycle (used by feedforward controller).
280
281 // These are accessible from non-templated subclasses.
282 static constexpr int kStates = States;
283 static constexpr int kInputs = Inputs;
284 static constexpr int kOutputs = Outputs;
285};
286
287extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT)
289extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT)
291
292} // namespace frc
#define WPILIB_DLLEXPORT
Definition: SymbolExports.h:36
A Kalman filter combines predictions from a model and measurements to give an estimate of the true sy...
Definition: KalmanFilter.h:37
Constructs a plant inversion model-based feedforward from a LinearSystem.
Definition: LinearPlantInversionFeedforward.h:32
Contains the controller coefficients and logic for a linear-quadratic regulator (LQR).
Definition: LinearQuadraticRegulator.h:28
A plant defined using state-space notation.
Definition: LinearSystem.h:31
Combines a controller, feedforward, and observer for controlling a mechanism with full state feedback...
Definition: LinearSystemLoop.h:38
void Correct(const OutputVector &y)
Correct the state estimate x-hat using the measurements in y.
Definition: LinearSystemLoop.h:242
static constexpr int kOutputs
Definition: LinearSystemLoop.h:284
double NextR(int i) const
Returns an element of the controller's next reference r.
Definition: LinearSystemLoop.h:157
InputVector U() const
Returns the controller's calculated control input u.
Definition: LinearSystemLoop.h:162
void SetXhat(const StateVector &xHat)
Set the initial state estimate x-hat.
Definition: LinearSystemLoop.h:178
LinearSystemLoop(LinearSystem< States, Inputs, Outputs > &plant, LinearQuadraticRegulator< States, Inputs > &controller, KalmanFilter< States, Inputs, Outputs > &observer, std::function< InputVector(const InputVector &)> clampFunction, units::second_t dt)
Constructs a state-space loop with the given plant, controller, and observer.
Definition: LinearSystemLoop.h:79
void Reset(const StateVector &initialState)
Zeroes reference r and controller output u.
Definition: LinearSystemLoop.h:225
LinearSystemLoop(LinearSystem< States, Inputs, Outputs > &plant, LinearQuadraticRegulator< States, Inputs > &controller, KalmanFilter< States, Inputs, Outputs > &observer, units::volt_t maxVoltage, units::second_t dt)
Constructs a state-space loop with the given plant, controller, and observer.
Definition: LinearSystemLoop.h:56
Vectord< States > StateVector
Definition: LinearSystemLoop.h:40
const LinearQuadraticRegulator< States, Inputs > & Controller() const
Return the controller used internally.
Definition: LinearSystemLoop.h:198
LinearSystemLoop(LinearSystemLoop &&)=default
StateVector m_nextR
Definition: LinearSystemLoop.h:279
Vectord< Inputs > InputVector
Definition: LinearSystemLoop.h:41
LinearSystemLoop(LinearQuadraticRegulator< States, Inputs > &controller, const LinearPlantInversionFeedforward< States, Inputs > &feedforward, KalmanFilter< States, Inputs, Outputs > &observer, std::function< InputVector(const InputVector &)> clampFunction)
Constructs a state-space loop with the given controller, feedforward, observer and clamp function.
Definition: LinearSystemLoop.h:119
void SetNextR(const StateVector &nextR)
Set the next reference r.
Definition: LinearSystemLoop.h:193
LinearQuadraticRegulator< States, Inputs > * m_controller
Definition: LinearSystemLoop.h:269
Vectord< Outputs > OutputVector
Definition: LinearSystemLoop.h:42
void Predict(units::second_t dt)
Sets new controller output, projects model forward, and runs observer prediction.
Definition: LinearSystemLoop.h:253
double Xhat(int i) const
Returns an element of the observer's state estimate x-hat.
Definition: LinearSystemLoop.h:145
static constexpr int kStates
Definition: LinearSystemLoop.h:282
LinearSystemLoop & operator=(LinearSystemLoop &&)=default
double U(int i) const
Returns an element of the controller's calculated control input u.
Definition: LinearSystemLoop.h:171
const StateVector & NextR() const
Returns the controller's next reference r.
Definition: LinearSystemLoop.h:150
std::function< InputVector(const InputVector &)> m_clampFunc
Clamping function.
Definition: LinearSystemLoop.h:276
const KalmanFilter< States, Inputs, Outputs > & Observer() const
Return the observer used internally.
Definition: LinearSystemLoop.h:214
LinearPlantInversionFeedforward< States, Inputs > m_feedforward
Definition: LinearSystemLoop.h:270
const StateVector & Xhat() const
Returns the observer's state estimate x-hat.
Definition: LinearSystemLoop.h:138
InputVector ClampInput(const InputVector &u) const
Clamps input vector between system's minimum and maximum allowable input.
Definition: LinearSystemLoop.h:266
const LinearPlantInversionFeedforward< States, Inputs > Feedforward() const
Return the feedforward used internally.
Definition: LinearSystemLoop.h:207
static constexpr int kInputs
Definition: LinearSystemLoop.h:283
void SetXhat(int i, double value)
Set an element of the initial state estimate x-hat.
Definition: LinearSystemLoop.h:186
KalmanFilter< States, Inputs, Outputs > * m_observer
Definition: LinearSystemLoop.h:271
StateVector Error() const
Returns difference between reference r and current state x-hat.
Definition: LinearSystemLoop.h:235
LinearSystemLoop(LinearQuadraticRegulator< States, Inputs > &controller, const LinearPlantInversionFeedforward< States, Inputs > &feedforward, KalmanFilter< States, Inputs, Outputs > &observer, units::volt_t maxVoltage)
Constructs a state-space loop with the given controller, feedforward and observer.
Definition: LinearSystemLoop.h:100
Definition: core.h:1240
const Scalar & y
Definition: MathFunctions.h:821
Definition: AprilTagFieldLayout.h:22
template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) LinearQuadraticRegulator< 1
Eigen::Vector< double, Size > Vectord
Definition: EigenCore.h:12