WPILibC++ 2025.0.0-alpha-1-10-g1ccd8d1
LinearSystem.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 <algorithm>
8#include <concepts>
9#include <functional>
10#include <stdexcept>
11
12#include <wpi/Algorithm.h>
13#include <wpi/SmallVector.h>
14
15#include "frc/EigenCore.h"
16#include "frc/StateSpaceUtil.h"
18#include "units/time.h"
19
20namespace frc {
21
22/**
23 * A plant defined using state-space notation.
24 *
25 * A plant is a mathematical model of a system's dynamics.
26 *
27 * For more on the underlying math, read
28 * https://file.tavsys.net/control/controls-engineering-in-frc.pdf.
29 *
30 * @tparam States Number of states.
31 * @tparam Inputs Number of inputs.
32 * @tparam Outputs Number of outputs.
33 */
34template <int States, int Inputs, int Outputs>
36 public:
40
41 /**
42 * Constructs a discrete plant with the given continuous system coefficients.
43 *
44 * @param A System matrix.
45 * @param B Input matrix.
46 * @param C Output matrix.
47 * @param D Feedthrough matrix.
48 * @throws std::domain_error if any matrix element isn't finite.
49 */
54 if (!A.allFinite()) {
55 throw std::domain_error(
56 "Elements of A aren't finite. This is usually due to model "
57 "implementation errors.");
58 }
59 if (!B.allFinite()) {
60 throw std::domain_error(
61 "Elements of B aren't finite. This is usually due to model "
62 "implementation errors.");
63 }
64 if (!C.allFinite()) {
65 throw std::domain_error(
66 "Elements of C aren't finite. This is usually due to model "
67 "implementation errors.");
68 }
69 if (!D.allFinite()) {
70 throw std::domain_error(
71 "Elements of D aren't finite. This is usually due to model "
72 "implementation errors.");
73 }
74
75 m_A = A;
76 m_B = B;
77 m_C = C;
78 m_D = D;
79 }
80
81 LinearSystem(const LinearSystem&) = default;
85
86 /**
87 * Returns the system matrix A.
88 */
89 const Matrixd<States, States>& A() const { return m_A; }
90
91 /**
92 * Returns an element of the system matrix A.
93 *
94 * @param i Row of A.
95 * @param j Column of A.
96 */
97 double A(int i, int j) const { return m_A(i, j); }
98
99 /**
100 * Returns the input matrix B.
101 */
102 const Matrixd<States, Inputs>& B() const { return m_B; }
103
104 /**
105 * Returns an element of the input matrix B.
106 *
107 * @param i Row of B.
108 * @param j Column of B.
109 */
110 double B(int i, int j) const { return m_B(i, j); }
111
112 /**
113 * Returns the output matrix C.
114 */
115 const Matrixd<Outputs, States>& C() const { return m_C; }
116
117 /**
118 * Returns an element of the output matrix C.
119 *
120 * @param i Row of C.
121 * @param j Column of C.
122 */
123 double C(int i, int j) const { return m_C(i, j); }
124
125 /**
126 * Returns the feedthrough matrix D.
127 */
128 const Matrixd<Outputs, Inputs>& D() const { return m_D; }
129
130 /**
131 * Returns an element of the feedthrough matrix D.
132 *
133 * @param i Row of D.
134 * @param j Column of D.
135 */
136 double D(int i, int j) const { return m_D(i, j); }
137
138 /**
139 * Computes the new x given the old x and the control input.
140 *
141 * This is used by state observers directly to run updates based on state
142 * estimate.
143 *
144 * @param x The current state.
145 * @param clampedU The control input.
146 * @param dt Timestep for model update.
147 */
149 units::second_t dt) const {
152 DiscretizeAB<States, Inputs>(m_A, m_B, dt, &discA, &discB);
153
154 return discA * x + discB * clampedU;
155 }
156
157 /**
158 * Computes the new y given the control input.
159 *
160 * This is used by state observers directly to run updates based on state
161 * estimate.
162 *
163 * @param x The current state.
164 * @param clampedU The control input.
165 */
167 const InputVector& clampedU) const {
168 return m_C * x + m_D * clampedU;
169 }
170
171 /**
172 * Returns the LinearSystem with the outputs listed in outputIndices.
173 *
174 * <p>This is used by state observers such as the Kalman Filter.
175 *
176 * @param outputIndices the list of output indices to include in the sliced
177 * system.
178 * @return the sliced LinearSystem with outputs set to row vectors of
179 * LinearSystem.
180 * @throws std::domain_error if any outputIndices are outside the range of
181 * system outputs.
182 * @throws std::domain_error if number of outputIndices exceeds the system
183 * outputs.
184 * @throws std::domain_error if duplication exists in outputIndices.
185 */
186 template <std::same_as<int>... OutputIndices>
187 LinearSystem<States, Inputs, sizeof...(OutputIndices)> Slice(
188 OutputIndices... outputIndices) {
189 static_assert(sizeof...(OutputIndices) <= Outputs,
190 "More outputs requested than available. This is usually due "
191 "to model implementation errors.");
192
194 [](size_t i, const auto& elem) {
195 if (elem < 0 || elem >= Outputs) {
196 throw std::domain_error(
197 "Slice indices out of range. This is usually due to model "
198 "implementation errors.");
199 }
200 },
201 outputIndices...);
202
203 // Sort and deduplicate output indices
204 wpi::SmallVector<int> outputIndicesArray{outputIndices...};
205 std::sort(outputIndicesArray.begin(), outputIndicesArray.end());
206 auto last =
207 std::unique(outputIndicesArray.begin(), outputIndicesArray.end());
208 outputIndicesArray.erase(last, outputIndicesArray.end());
209
210 if (outputIndicesArray.size() != sizeof...(outputIndices)) {
211 throw std::domain_error(
212 "Duplicate indices exist. This is usually due to model "
213 "implementation errors.");
214 }
215
216 return LinearSystem<States, Inputs, sizeof...(OutputIndices)>{
217 m_A, m_B, m_C(outputIndicesArray, Eigen::placeholders::all),
218 m_D(outputIndicesArray, Eigen::placeholders::all)};
219 }
220
221 private:
222 /**
223 * Continuous system matrix.
224 */
226
227 /**
228 * Continuous input matrix.
229 */
231
232 /**
233 * Output matrix.
234 */
236
237 /**
238 * Feedthrough matrix.
239 */
241};
242
243} // namespace frc
This file defines the SmallVector class.
A plant defined using state-space notation.
Definition: LinearSystem.h:35
const Matrixd< States, Inputs > & B() const
Returns the input matrix B.
Definition: LinearSystem.h:102
LinearSystem & operator=(const LinearSystem &)=default
LinearSystem< States, Inputs, sizeof...(OutputIndices)> Slice(OutputIndices... outputIndices)
Returns the LinearSystem with the outputs listed in outputIndices.
Definition: LinearSystem.h:187
double D(int i, int j) const
Returns an element of the feedthrough matrix D.
Definition: LinearSystem.h:136
double B(int i, int j) const
Returns an element of the input matrix B.
Definition: LinearSystem.h:110
double A(int i, int j) const
Returns an element of the system matrix A.
Definition: LinearSystem.h:97
StateVector CalculateX(const StateVector &x, const InputVector &clampedU, units::second_t dt) const
Computes the new x given the old x and the control input.
Definition: LinearSystem.h:148
const Matrixd< States, States > & A() const
Returns the system matrix A.
Definition: LinearSystem.h:89
Vectord< Outputs > OutputVector
Definition: LinearSystem.h:39
LinearSystem(LinearSystem &&)=default
LinearSystem & operator=(LinearSystem &&)=default
const Matrixd< Outputs, Inputs > & D() const
Returns the feedthrough matrix D.
Definition: LinearSystem.h:128
OutputVector CalculateY(const StateVector &x, const InputVector &clampedU) const
Computes the new y given the control input.
Definition: LinearSystem.h:166
Vectord< States > StateVector
Definition: LinearSystem.h:37
const Matrixd< Outputs, States > & C() const
Returns the output matrix C.
Definition: LinearSystem.h:115
double C(int i, int j) const
Returns an element of the output matrix C.
Definition: LinearSystem.h:123
LinearSystem(const LinearSystem &)=default
LinearSystem(const Matrixd< States, States > &A, const Matrixd< States, Inputs > &B, const Matrixd< Outputs, States > &C, const Matrixd< Outputs, Inputs > &D)
Constructs a discrete plant with the given continuous system coefficients.
Definition: LinearSystem.h:50
Vectord< Inputs > InputVector
Definition: LinearSystem.h:38
Definition: AprilTagDetector_cv.h:11
Eigen::Matrix< double, Rows, Cols, Options, MaxRows, MaxCols > Matrixd
Definition: EigenCore.h:21
Eigen::Vector< double, Size > Vectord
Definition: EigenCore.h:12
constexpr void for_each(F &&f, Ts &&... elems)
Calls f(i, elem) for each element of elems where i is the index of the element in elems and elem is t...
Definition: Algorithm.h:29