57 std::ofstream file(path);
58 if (!file.is_open()) {
59 throw IOError(
"Failed to open file for MATLAB export: " + path);
64 file.exceptions(std::ios::failbit | std::ios::badbit);
66 file << std::setprecision(15);
67 file <<
"% Linear state-space model\n";
69 file <<
"% Operating point: t = " <<
t0 <<
"\n\n";
72 auto write_matrix = [&](
const std::string &name,
const Eigen::MatrixXd &M) {
73 file << name <<
" = [\n";
74 for (Eigen::Index i = 0; i < M.rows(); ++i) {
76 for (Eigen::Index j = 0; j < M.cols(); ++j) {
92 file <<
"sys = ss(A, B, C, D);\n\n";
96 file <<
"sys.StateName = {";
97 for (std::size_t i = 0; i <
state_names.size(); ++i) {
107 file <<
"sys.InputName = {";
108 for (std::size_t i = 0; i <
input_names.size(); ++i) {
118 file <<
"sys.OutputName = {";
127 file <<
"\ndisp('Linear model loaded successfully.');\n";
129 }
catch (
const std::ios_base::failure &e) {
130 throw IOError(
"Failed to write MATLAB export file '" + path +
"': " + e.what());
138 std::ofstream file(path);
139 if (!file.is_open()) {
140 throw IOError(
"Failed to open file for NumPy export: " + path);
145 file.exceptions(std::ios::failbit | std::ios::badbit);
147 file << std::setprecision(15);
148 file <<
"\"\"\"Linear state-space model\n";
150 file <<
"Operating point: t = " <<
t0 <<
"\n";
151 file <<
"\"\"\"\n\n";
152 file <<
"import numpy as np\n\n";
155 auto write_matrix = [&](
const std::string &name,
const Eigen::MatrixXd &M) {
156 file << name <<
" = np.array([\n";
157 for (Eigen::Index i = 0; i < M.rows(); ++i) {
159 for (Eigen::Index j = 0; j < M.cols(); ++j) {
161 if (j < M.cols() - 1)
165 if (i < M.rows() - 1)
172 write_matrix(
"A",
A);
173 write_matrix(
"B",
B);
174 write_matrix(
"C",
C);
175 write_matrix(
"D",
D);
178 file <<
"state_names = [";
179 for (std::size_t i = 0; i <
state_names.size(); ++i) {
186 file <<
"input_names = [";
187 for (std::size_t i = 0; i <
input_names.size(); ++i) {
194 file <<
"output_names = [";
203 file <<
"x0 = np.array([";
204 for (Eigen::Index i = 0; i <
x0.size(); ++i) {
206 if (i <
x0.size() - 1)
211 file <<
"u0 = np.array([";
212 for (Eigen::Index i = 0; i <
u0.size(); ++i) {
214 if (i <
u0.size() - 1)
219 file <<
"t0 = " <<
t0 <<
"\n";
221 }
catch (
const std::ios_base::failure &e) {
222 throw IOError(
"Failed to write NumPy export file '" + path +
"': " + e.what());
230 std::ofstream file(path);
231 if (!file.is_open()) {
232 throw IOError(
"Failed to open file for JSON export: " + path);
237 file.exceptions(std::ios::failbit | std::ios::badbit);
239 file << std::setprecision(15);
242 file <<
" \"t0\": " <<
t0 <<
",\n";
245 auto write_matrix = [&](
const std::string &name,
const Eigen::MatrixXd &M,
bool last) {
246 file <<
" \"" << name <<
"\": [\n";
247 for (Eigen::Index i = 0; i < M.rows(); ++i) {
249 for (Eigen::Index j = 0; j < M.cols(); ++j) {
251 if (j < M.cols() - 1)
255 if (i < M.rows() - 1)
259 file <<
" ]" << (last ?
"" :
",") <<
"\n";
263 auto write_strings = [&](
const std::string &name,
const std::vector<std::string> &arr,
265 file <<
" \"" << name <<
"\": [";
266 for (std::size_t i = 0; i < arr.size(); ++i) {
267 file <<
"\"" << arr[i] <<
"\"";
268 if (i < arr.size() - 1)
271 file <<
"]" << (last ?
"" :
",") <<
"\n";
275 auto write_vector = [&](
const std::string &name,
const Eigen::VectorXd &v,
bool last) {
276 file <<
" \"" << name <<
"\": [";
277 for (Eigen::Index i = 0; i < v.size(); ++i) {
279 if (i < v.size() - 1)
282 file <<
"]" << (last ?
"" :
",") <<
"\n";
288 write_vector(
"x0",
x0,
false);
289 write_vector(
"u0",
u0,
false);
290 write_matrix(
"A",
A,
false);
291 write_matrix(
"B",
B,
false);
292 write_matrix(
"C",
C,
false);
293 write_matrix(
"D",
D,
true);
297 }
catch (
const std::ios_base::failure &e) {
298 throw IOError(
"Failed to write JSON export file '" + path +
"': " + e.what());
315 const Eigen::Index n =
A.rows();
316 const Eigen::Index m =
B.cols();
319 if (m == 0 || n == 0) {
323 Eigen::MatrixXd W(n, n * m);
324 Eigen::MatrixXd Ak = Eigen::MatrixXd::Identity(n, n);
326 for (Eigen::Index k = 0; k < n; ++k) {
327 W.block(0, k * m, n, m) = Ak *
B;
331 Eigen::JacobiSVD<Eigen::MatrixXd> svd(W);
332 return static_cast<int>(svd.rank());
344 const Eigen::Index n =
A.rows();
345 const Eigen::Index p =
C.rows();
348 if (p == 0 || n == 0) {
352 Eigen::MatrixXd O(n * p, n);
353 Eigen::MatrixXd Ak = Eigen::MatrixXd::Identity(n, n);
355 for (Eigen::Index k = 0; k < n; ++k) {
356 O.block(k * p, 0, p, n) =
C * Ak;
360 Eigen::JacobiSVD<Eigen::MatrixXd> svd(O);
361 return static_cast<int>(svd.rank());
368 Eigen::EigenSolver<Eigen::MatrixXd> solver(
A,
false);
369 for (Eigen::Index i = 0; i <
A.rows(); ++i) {
370 if (solver.eigenvalues()(i).real() >= 0) {
381 Eigen::EigenSolver<Eigen::MatrixXd> solver(
A,
false);
382 return solver.eigenvalues();
Core type definitions, concepts, and configuration for Icarus.
Consolidated error handling for Icarus.
File and I/O operation errors.
Definition Error.hpp:356
Definition Simulator.hpp:53
constexpr const char * Version()
Version string (derived from components).
Definition CoreTypes.hpp:152
Linear state-space model.
Definition LinearModel.hpp:31
bool IsStable() const
Check if system is stable (all eigenvalues have negative real part).
Definition LinearModel.hpp:367
std::vector< std::string > state_names
Definition LinearModel.hpp:37
Eigen::MatrixXd B
Input matrix (n_states x n_inputs).
Definition LinearModel.hpp:33
double t0
Definition LinearModel.hpp:44
int ObservabilityRank() const
Compute observability matrix rank.
Definition LinearModel.hpp:343
void ExportJSON(const std::string &path) const
Export to JSON file.
Definition LinearModel.hpp:229
void ExportMatlab(const std::string &path) const
Export to MATLAB .m file.
Definition LinearModel.hpp:56
Eigen::MatrixXd D
Feedthrough matrix (n_outputs x n_inputs).
Definition LinearModel.hpp:35
Eigen::MatrixXd C
Output matrix (n_outputs x n_states).
Definition LinearModel.hpp:34
Eigen::MatrixXd A
State matrix (n_states x n_states).
Definition LinearModel.hpp:32
Eigen::VectorXcd Eigenvalues() const
Get eigenvalues of A matrix.
Definition LinearModel.hpp:380
void ExportNumPy(const std::string &path) const
Export to Python/NumPy .py file.
Definition LinearModel.hpp:137
Eigen::VectorXd u0
Definition LinearModel.hpp:43
Eigen::VectorXd x0
Operating point where linearization was performed.
Definition LinearModel.hpp:42
std::vector< std::string > input_names
Definition LinearModel.hpp:38
std::vector< std::string > output_names
Definition LinearModel.hpp:39
int ControllabilityRank() const
Compute controllability matrix rank.
Definition LinearModel.hpp:314