Vulcan
Aerospace Engineering Utilities Built on Janus
Loading...
Searching...
No Matches
Discretize.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <janus/janus.hpp>
4
5namespace vulcan::tf {
6
7// =============================================================================
8// Matrix Exponential (Padé approximation)
9// =============================================================================
10
18template <int N>
19Eigen::Matrix<double, N, N>
20matrix_exp_pade(const Eigen::Matrix<double, N, N> &A) {
21 static constexpr double b[] = {64764752532480000.0,
22 32382376266240000.0,
23 7771770303897600.0,
24 1187353796428800.0,
25 129060195264000.0,
26 10559470521600.0,
27 670442572800.0,
28 33522128640.0,
29 1323241920.0,
30 40840800.0,
31 960960.0,
32 16380.0,
33 182.0,
34 1.0};
35
36 double norm_A = A.cwiseAbs().colwise().sum().maxCoeff();
37 int s = 0;
38 if (norm_A > 0) {
39 s = std::max(0, static_cast<int>(std::ceil(std::log2(norm_A / 5.37))));
40 }
41 Eigen::Matrix<double, N, N> As = A / std::pow(2.0, s);
42
43 Eigen::Matrix<double, N, N> I = Eigen::Matrix<double, N, N>::Identity();
44 Eigen::Matrix<double, N, N> A2 = As * As;
45 Eigen::Matrix<double, N, N> A4 = A2 * A2;
46 Eigen::Matrix<double, N, N> A6 = A4 * A2;
47
48 Eigen::Matrix<double, N, N> U = b[13] * A6 + b[11] * A4 + b[9] * A2;
49 U = A6 * U;
50 U = U + b[7] * A6 + b[5] * A4 + b[3] * A2 + b[1] * I;
51 U = As * U;
52
53 Eigen::Matrix<double, N, N> V = b[12] * A6 + b[10] * A4 + b[8] * A2;
54 V = A6 * V;
55 V = V + b[6] * A6 + b[4] * A4 + b[2] * A2 + b[0] * I;
56
57 Eigen::Matrix<double, N, N> P = (V - U).fullPivLu().solve(V + U);
58
59 for (int i = 0; i < s; ++i) {
60 P = P * P;
61 }
62 return P;
63}
64
65// =============================================================================
66// Discretization Methods
67// =============================================================================
68
79template <int N>
80void discretize_zoh(const Eigen::Matrix<double, N, N> &A_c,
81 const Eigen::Matrix<double, N, 1> &B_c, double dt,
82 Eigen::Matrix<double, N, N> &A_d,
83 Eigen::Matrix<double, N, 1> &B_d) {
84 constexpr int M = N + 1;
85 Eigen::Matrix<double, M, M> aug = Eigen::Matrix<double, M, M>::Zero();
86 aug.template topLeftCorner<N, N>() = A_c * dt;
87 aug.template block<N, 1>(0, N) = B_c * dt;
88
89 Eigen::Matrix<double, M, M> exp_aug = matrix_exp_pade<M>(aug);
90 A_d = exp_aug.template topLeftCorner<N, N>();
91 B_d = exp_aug.template block<N, 1>(0, N);
92}
93
99template <int N>
100void discretize_tustin(const Eigen::Matrix<double, N, N> &A_c,
101 const Eigen::Matrix<double, N, 1> &B_c, double dt,
102 Eigen::Matrix<double, N, N> &A_d,
103 Eigen::Matrix<double, N, 1> &B_d) {
104 Eigen::Matrix<double, N, N> I = Eigen::Matrix<double, N, N>::Identity();
105 Eigen::Matrix<double, N, N> A_half = A_c * (dt / 2.0);
106 Eigen::FullPivLU<Eigen::Matrix<double, N, N>> lu(I - A_half);
107 A_d = lu.solve(I + A_half);
108 B_d = lu.solve(B_c * dt);
109}
110
116template <int N>
117void discretize_euler(const Eigen::Matrix<double, N, N> &A_c,
118 const Eigen::Matrix<double, N, 1> &B_c, double dt,
119 Eigen::Matrix<double, N, N> &A_d,
120 Eigen::Matrix<double, N, 1> &B_d) {
121 Eigen::Matrix<double, N, N> I = Eigen::Matrix<double, N, N>::Identity();
122 A_d = I + A_c * dt;
123 B_d = B_c * dt;
124}
125
131template <int N>
132void discretize_backward_euler(const Eigen::Matrix<double, N, N> &A_c,
133 const Eigen::Matrix<double, N, 1> &B_c,
134 double dt, Eigen::Matrix<double, N, N> &A_d,
135 Eigen::Matrix<double, N, 1> &B_d) {
136 Eigen::Matrix<double, N, N> I = Eigen::Matrix<double, N, N>::Identity();
137 Eigen::FullPivLU<Eigen::Matrix<double, N, N>> lu(I - A_c * dt);
138 A_d = lu.solve(I);
139 B_d = A_d * B_c * dt;
140}
141
142} // namespace vulcan::tf
Transfer function utilities for linear systems and nonlinear elements.
Definition Discretize.hpp:5
void discretize_backward_euler(const Eigen::Matrix< double, N, N > &A_c, const Eigen::Matrix< double, N, 1 > &B_c, double dt, Eigen::Matrix< double, N, N > &A_d, Eigen::Matrix< double, N, 1 > &B_d)
Backward Euler discretization.
Definition Discretize.hpp:132
void discretize_zoh(const Eigen::Matrix< double, N, N > &A_c, const Eigen::Matrix< double, N, 1 > &B_c, double dt, Eigen::Matrix< double, N, N > &A_d, Eigen::Matrix< double, N, 1 > &B_d)
Zero-order hold (ZOH) discretization.
Definition Discretize.hpp:80
Eigen::Matrix< double, N, N > matrix_exp_pade(const Eigen::Matrix< double, N, N > &A)
Compute matrix exponential using Padé(13,13) approximation.
Definition Discretize.hpp:20
void discretize_tustin(const Eigen::Matrix< double, N, N > &A_c, const Eigen::Matrix< double, N, 1 > &B_c, double dt, Eigen::Matrix< double, N, N > &A_d, Eigen::Matrix< double, N, 1 > &B_d)
Tustin (bilinear) discretization.
Definition Discretize.hpp:100
void discretize_euler(const Eigen::Matrix< double, N, N > &A_c, const Eigen::Matrix< double, N, 1 > &B_c, double dt, Eigen::Matrix< double, N, N > &A_d, Eigen::Matrix< double, N, 1 > &B_d)
Forward Euler discretization.
Definition Discretize.hpp:117