JSBSim Flight Dynamics Model 1.3.0 (09 Apr 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGStateSpace.cpp
1/*
2 * FGStateSpace.cpp
3 * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
4 *
5 * FGStateSpace.cpp is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by the
7 * Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * FGStateSpace.cpp is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "initialization/FGInitialCondition.h"
20#include "FGStateSpace.h"
21#include <limits>
22#include <iomanip>
23#include <string>
24
25namespace JSBSim
26{
27
28void FGStateSpace::linearize(
29 std::vector<double> x0,
30 std::vector<double> u0,
31 std::vector<double> y0,
32 std::vector< std::vector<double> > & A,
33 std::vector< std::vector<double> > & B,
34 std::vector< std::vector<double> > & C,
35 std::vector< std::vector<double> > & D)
36{
37 double h = 1e-4;
38
39 // A, d(x)/dx
40 numericalJacobian(A,x,x,x0,x0,h,true);
41 // B, d(x)/du
42 numericalJacobian(B,x,u,x0,u0,h,true);
43 // C, d(y)/dx
44 numericalJacobian(C,y,x,y0,x0,h);
45 // D, d(y)/du
46 numericalJacobian(D,y,u,y0,u0,h);
47
48}
49
50void FGStateSpace::numericalJacobian(std::vector< std::vector<double> > & J, ComponentVector & y,
51 ComponentVector & x, const std::vector<double> & y0, const std::vector<double> & x0, double h, bool computeYDerivative)
52{
53 size_t nX = x.getSize();
54 size_t nY = y.getSize();
55 double f1 = 0, f2 = 0, fn1 = 0, fn2 = 0;
56 J.resize(nY);
57 for (unsigned int iY=0;iY<nY;iY++)
58 {
59 J[iY].resize(nX);
60 for (unsigned int iX=0;iX<nX;iX++)
61 {
62 x.set(x0);
63 x.set(iX,x.get(iX)+h);
64 if (computeYDerivative) f1 = y.getDeriv(iY);
65 else f1 = y.get(iY);
66
67 x.set(x0);
68 x.set(iX,x.get(iX)+2*h);
69 if (computeYDerivative) f2 = y.getDeriv(iY);
70 else f2 = y.get(iY);
71
72 x.set(x0);
73 x.set(iX,x.get(iX)-h);
74 if (computeYDerivative) fn1 = y.getDeriv(iY);
75 else fn1 = y.get(iY);
76
77 x.set(x0);
78 x.set(iX,x.get(iX)-2*h);
79 if (computeYDerivative) fn2 = y.getDeriv(iY);
80 else fn2 = y.get(iY);
81
82 double diff1 = f1-fn1;
83 double diff2 = f2-fn2;
84
85 // correct for angle wrap
86 if (x.getComp(iX)->getUnit().compare("rad") == 0) {
87 while(diff1 > M_PI) diff1 -= 2*M_PI;
88 if(diff1 < -M_PI) diff1 += 2*M_PI;
89 if(diff2 > M_PI) diff2 -= 2*M_PI;
90 if(diff2 < -M_PI) diff2 += 2*M_PI;
91 } else if (x.getComp(iX)->getUnit().compare("deg") == 0) {
92 if(diff1 > 180) diff1 -= 360;
93 if(diff1 < -180) diff1 += 360;
94 if(diff2 > 180) diff2 -= 360;
95 if(diff2 < -180) diff2 += 360;
96 }
97 J[iY][iX] = (8*diff1-diff2)/(12*h); // 3rd order taylor approx from lewis, pg 203
98
99 x.set(x0);
100
101 if (m_fdm->GetDebugLevel() > 1)
102 {
103 FGLogging log(LogLevel::DEBUG);
104 log << std::scientific << "\ty:\t" << y.getName(iY) << "\tx:\t"
105 << x.getName(iX)
106 << "\tfn2:\t" << fn2 << "\tfn1:\t" << fn1
107 << "\tf1:\t" << f1 << "\tf2:\t" << f2
108 << "\tf1-fn1:\t" << f1-fn1
109 << "\tf2-fn2:\t" << f2-fn2
110 << "\tdf/dx:\t" << J[iY][iX]
111 << std::fixed << "\n";
112 }
113 }
114 }
115}
116
117std::ostream &operator<<( std::ostream &out, const FGStateSpace::Component &c )
118{
119 out << "\t" << c.getName()
120 << "\t" << c.getUnit()
121 << "\t:\t" << c.get();
122 return out;
123}
124
125std::ostream &operator<<( std::ostream &out, const FGStateSpace::ComponentVector &v )
126{
127 for (unsigned int i=0; i< v.getSize(); i++)
128 {
129 out << *(v.getComp(i)) << "\n";
130 }
131 out << "";
132 return out;
133}
134
135std::ostream &operator<<( std::ostream &out, const FGStateSpace &ss )
136{
137 out << "\nX:\n" << ss.x
138 << "\nU:\n" << ss.u
139 << "\nY:\n" << ss.y;
140 return out;
141}
142
143std::ostream &operator<<( std::ostream &out, const std::vector< std::vector<double> > &vec2d )
144{
145 std::streamsize width = out.width();
146 size_t nI = vec2d.size();
147 out << std::left << std::setw(1) << "[" << std::right;
148 for (unsigned int i=0;i<nI;i++)
149 {
150 //FGLogging log(LogLevel::DEBUG);
151 //log << "i: " << i << "\n";
152 size_t nJ = vec2d[i].size();
153 for (unsigned int j=0;j<nJ;j++)
154 {
155 //log << "j: " << j << "\n";
156 if (i==0 && j==0) out << std::setw(width-1) << vec2d[i][j];
157 else out << std::setw(width) << vec2d[i][j];
158
159 if (j==nJ-1)
160 {
161 if ( i==nI-1 ) out << "]";
162 else out << ";\n";
163 }
164 else out << ",";
165 }
166 out << std::flush;
167 }
168 return out;
169}
170
171std::ostream &operator<<( std::ostream &out, const std::vector<double> &vec )
172{
173 std::streamsize width = out.width();
174 size_t nI = vec.size();
175 out << std::left << std::setw(1) << "[" << std::right;
176 for (unsigned int i=0;i<nI;i++)
177 {
178 if (i==0) out << std::setw(width-1) << vec[i];
179 else out << std::setw(width) << vec[i];
180
181 if ( i==nI-1 ) out << "]";
182 else out << ";\n";
183 }
184 out << std::flush;
185 return out;
186}
187
188
189} // JSBSim
190
191
192// vim:ts=4:sw=4
int GetDebugLevel(void) const
Retrieves the current debug level setting.
Definition FGFDMExec.h:602
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71
ostream & operator<<(ostream &os, const FGColumnVector3 &col)
Write vector to a stream.