Vulcan
Aerospace Engineering Utilities Built on Janus
Loading...
Searching...
No Matches
SecondOrder.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <janus/janus.hpp>
4
5namespace vulcan::tf {
6
16template <typename Scalar> struct SecondOrderCoeffs {
17 Eigen::Matrix<Scalar, 2, 2> A;
18 Eigen::Matrix<Scalar, 2, 1> B;
19 Eigen::Matrix<Scalar, 1, 2> C;
20 Scalar D;
21 double omega_n;
22 double zeta;
23 double K;
24 double dt;
25};
26
39template <typename Scalar>
40SecondOrderCoeffs<Scalar> second_order(double omega_n, double zeta, double K,
41 double dt) {
43 c.omega_n = omega_n;
44 c.zeta = zeta;
45 c.K = K;
46 c.dt = dt;
47
48 double wn = omega_n;
49 double z = zeta;
50 double wn2 = wn * wn;
51
52 if (z < 1.0) {
53 // Underdamped
54 double wd = wn * std::sqrt(1.0 - z * z);
55 double sigma = z * wn;
56 double e_sigma = std::exp(-sigma * dt);
57 double cos_wd = std::cos(wd * dt);
58 double sin_wd = std::sin(wd * dt);
59
60 c.A(0, 0) =
61 static_cast<Scalar>(e_sigma * (cos_wd + (sigma / wd) * sin_wd));
62 c.A(0, 1) = static_cast<Scalar>(e_sigma * sin_wd / wd);
63 c.A(1, 0) = static_cast<Scalar>(-e_sigma * wn2 * sin_wd / wd);
64 c.A(1, 1) =
65 static_cast<Scalar>(e_sigma * (cos_wd - (sigma / wd) * sin_wd));
66
67 double b0 = K * (1.0 - e_sigma * (cos_wd + (sigma / wd) * sin_wd));
68 double b1 = K * e_sigma * wn2 * sin_wd / wd;
69 c.B(0) = static_cast<Scalar>(b0);
70 c.B(1) = static_cast<Scalar>(b1);
71
72 } else if (z > 1.0) {
73 // Overdamped
74 double sqrtTerm = wn * std::sqrt(z * z - 1.0);
75 double p1 = -z * wn + sqrtTerm;
76 double p2 = -z * wn - sqrtTerm;
77 double e1 = std::exp(p1 * dt);
78 double e2 = std::exp(p2 * dt);
79 double dp = p1 - p2;
80
81 c.A(0, 0) = static_cast<Scalar>((p1 * e2 - p2 * e1) / dp);
82 c.A(0, 1) = static_cast<Scalar>((e1 - e2) / dp);
83 c.A(1, 0) = static_cast<Scalar>(p1 * p2 * (e2 - e1) / dp);
84 c.A(1, 1) = static_cast<Scalar>((p1 * e1 - p2 * e2) / dp);
85
86 double b0 = K * (1.0 - (p1 * e2 - p2 * e1) / dp);
87 double b1 = K * p1 * p2 * (e1 - e2) / dp;
88 c.B(0) = static_cast<Scalar>(b0);
89 c.B(1) = static_cast<Scalar>(b1);
90
91 } else {
92 // Critically damped
93 double e_wn = std::exp(-wn * dt);
94
95 c.A(0, 0) = static_cast<Scalar>(e_wn * (1.0 + wn * dt));
96 c.A(0, 1) = static_cast<Scalar>(e_wn * dt);
97 c.A(1, 0) = static_cast<Scalar>(-e_wn * wn * wn * dt);
98 c.A(1, 1) = static_cast<Scalar>(e_wn * (1.0 - wn * dt));
99
100 double b0 = K * (1.0 - e_wn * (1.0 + wn * dt));
101 double b1 = K * e_wn * wn * wn * dt;
102 c.B(0) = static_cast<Scalar>(b0);
103 c.B(1) = static_cast<Scalar>(b1);
104 }
105
106 c.C(0, 0) = static_cast<Scalar>(1.0);
107 c.C(0, 1) = static_cast<Scalar>(0.0);
108 c.D = static_cast<Scalar>(0.0);
109
110 return c;
111}
112
124template <typename Scalar>
125Eigen::Matrix<Scalar, 2, 1>
127 const Eigen::Matrix<Scalar, 2, 1> &state,
128 const Scalar &input) {
129 return coeffs.A * state + coeffs.B * input;
130}
131
143template <typename Scalar>
145 const Eigen::Matrix<Scalar, 2, 1> &state,
146 const Scalar &input) {
147 return (coeffs.C * state)(0) + coeffs.D * input;
148}
149
158inline std::tuple<double, double, double>
159second_order_characteristics(double omega_n, double zeta) {
160 double tr = (1.8 - 0.6 * zeta) / omega_n;
161 double ts = 4.0 / (zeta * omega_n);
162 double Mp = 0.0;
163 if (zeta < 1.0 && zeta > 0.0) {
164 Mp = 100.0 * std::exp(-zeta * M_PI / std::sqrt(1.0 - zeta * zeta));
165 }
166 return {tr, ts, Mp};
167}
168
169} // namespace vulcan::tf
Transfer function utilities for linear systems and nonlinear elements.
Definition Discretize.hpp:5
Eigen::Matrix< Scalar, 2, 1 > second_order_step(const SecondOrderCoeffs< Scalar > &coeffs, const Eigen::Matrix< Scalar, 2, 1 > &state, const Scalar &input)
Compute next state for second-order system (stateless).
Definition SecondOrder.hpp:126
SecondOrderCoeffs< Scalar > second_order(double omega_n, double zeta, double K, double dt)
Compute second-order discrete-time system coefficients.
Definition SecondOrder.hpp:40
std::tuple< double, double, double > second_order_characteristics(double omega_n, double zeta)
Compute theoretical system characteristics.
Definition SecondOrder.hpp:159
Scalar second_order_output(const SecondOrderCoeffs< Scalar > &coeffs, const Eigen::Matrix< Scalar, 2, 1 > &state, const Scalar &input)
Extract output from state (stateless).
Definition SecondOrder.hpp:144
Second-order discrete-time system coefficients.
Definition SecondOrder.hpp:16
Eigen::Matrix< Scalar, 2, 2 > A
Discrete state matrix.
Definition SecondOrder.hpp:17
double K
DC gain.
Definition SecondOrder.hpp:23
double omega_n
Natural frequency [rad/s].
Definition SecondOrder.hpp:21
Scalar D
Feedthrough (usually 0).
Definition SecondOrder.hpp:20
Eigen::Matrix< Scalar, 2, 1 > B
Discrete input matrix.
Definition SecondOrder.hpp:18
Eigen::Matrix< Scalar, 1, 2 > C
Output matrix.
Definition SecondOrder.hpp:19
double dt
Sample time [s].
Definition SecondOrder.hpp:24
double zeta
Damping ratio.
Definition SecondOrder.hpp:22