JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
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 
25 namespace JSBSim
26 {
27 
28 void 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 
50 void 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  std::cout << std::scientific << "\ty:\t" << y.getName(iY) << "\tx:\t"
104  << x.getName(iX)
105  << "\tfn2:\t" << fn2 << "\tfn1:\t" << fn1
106  << "\tf1:\t" << f1 << "\tf2:\t" << f2
107  << "\tf1-fn1:\t" << f1-fn1
108  << "\tf2-fn2:\t" << f2-fn2
109  << "\tdf/dx:\t" << J[iY][iX]
110  << std::fixed << std::endl;
111  }
112  }
113  }
114 }
115 
116 std::ostream &operator<<( std::ostream &out, const FGStateSpace::Component &c )
117 {
118  out << "\t" << c.getName()
119  << "\t" << c.getUnit()
120  << "\t:\t" << c.get();
121  return out;
122 }
123 
124 std::ostream &operator<<( std::ostream &out, const FGStateSpace::ComponentVector &v )
125 {
126  for (unsigned int i=0; i< v.getSize(); i++)
127  {
128  out << *(v.getComp(i)) << "\n";
129  }
130  out << "";
131  return out;
132 }
133 
134 std::ostream &operator<<( std::ostream &out, const FGStateSpace &ss )
135 {
136  out << "\nX:\n" << ss.x
137  << "\nU:\n" << ss.u
138  << "\nY:\n" << ss.y;
139  return out;
140 }
141 
142 std::ostream &operator<<( std::ostream &out, const std::vector< std::vector<double> > &vec2d )
143 {
144  std::streamsize width = out.width();
145  size_t nI = vec2d.size();
146  out << std::left << std::setw(1) << "[" << std::right;
147  for (unsigned int i=0;i<nI;i++)
148  {
149  //std::cout << "i: " << i << std::endl;
150  size_t nJ = vec2d[i].size();
151  for (unsigned int j=0;j<nJ;j++)
152  {
153  //std::cout << "j: " << j << std::endl;
154  if (i==0 && j==0) out << std::setw(width-1) << vec2d[i][j];
155  else out << std::setw(width) << vec2d[i][j];
156 
157  if (j==nJ-1)
158  {
159  if ( i==nI-1 ) out << "]";
160  else out << ";\n";
161  }
162  else out << ",";
163  }
164  out << std::flush;
165  }
166  return out;
167 }
168 
169 std::ostream &operator<<( std::ostream &out, const std::vector<double> &vec )
170 {
171  std::streamsize width = out.width();
172  size_t nI = vec.size();
173  out << std::left << std::setw(1) << "[" << std::right;
174  for (unsigned int i=0;i<nI;i++)
175  {
176  if (i==0) out << std::setw(width-1) << vec[i];
177  else out << std::setw(width) << vec[i];
178 
179  if ( i==nI-1 ) out << "]";
180  else out << ";\n";
181  }
182  out << std::flush;
183  return out;
184 }
185 
186 
187 } // JSBSim
188 
189 
190 // vim:ts=4:sw=4
int GetDebugLevel(void) const
Retrieves the current debug level setting.
Definition: FGFDMExec.h:585