JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGLinearization.cpp
1 /*
2  * FGLinearization.cpp
3  * Copyright (C) James Goppert 2011 <james.goppert@gmail.com>
4  *
5  * FGLinearization.h 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  * FGLinearization.h 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 "FGInitialCondition.h"
20 #include "FGLinearization.h"
21 #include <ctime>
22 
23 namespace JSBSim {
24 
25 // TODO make FGLinearization have X,U,Y selectable by xml config file
26 
27 FGLinearization::FGLinearization(FGFDMExec * fdm, int mode)
28 {
29  std::cout << "\nlinearization: " << std::endl;
30  std::clock_t time_start=clock(), time_linDone;
31  FGStateSpace ss(fdm);
32 
33  ss.x.add(new FGStateSpace::Vt);
34  ss.x.add(new FGStateSpace::Alpha);
35  ss.x.add(new FGStateSpace::Theta);
36  ss.x.add(new FGStateSpace::Q);
37 
38  // get propulsion pointer to determine type/ etc.
39  FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0);
40  FGThruster * thruster0 = engine0->GetThruster();
41 
42  if (thruster0->GetType()==FGThruster::ttPropeller)
43  {
44  ss.x.add(new FGStateSpace::Rpm0);
45  // TODO add variable prop pitch property
46  // if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
47  int numEngines = fdm->GetPropulsion()->GetNumEngines();
48  if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
49  if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
50  if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
51  if (numEngines>4) {
52  std::cerr << "more than 4 engines not currently handled" << std::endl;
53  }
54  }
55  ss.x.add(new FGStateSpace::Beta);
56  ss.x.add(new FGStateSpace::Phi);
57  ss.x.add(new FGStateSpace::P);
58  ss.x.add(new FGStateSpace::Psi);
59  ss.x.add(new FGStateSpace::R);
60  ss.x.add(new FGStateSpace::Latitude);
61  ss.x.add(new FGStateSpace::Longitude);
62  ss.x.add(new FGStateSpace::Alt);
63 
64  ss.u.add(new FGStateSpace::ThrottleCmd);
65  ss.u.add(new FGStateSpace::DaCmd);
66  ss.u.add(new FGStateSpace::DeCmd);
67  ss.u.add(new FGStateSpace::DrCmd);
68 
69  // state feedback
70  ss.y = ss.x;
71 
72  std::vector< std::vector<double> > A,B,C,D;
73  std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
74  std::vector<double> y0 = x0; // state feedback
75  std::cout << ss << std::endl;
76 
77  ss.linearize(x0,u0,y0,A,B,C,D);
78 
79  int width=10;
80  std::cout.precision(3);
81  std::cout
82  << std::fixed
83  << std::right
84  << "\nA=\n" << std::setw(width) << A
85  << "\nB=\n" << std::setw(width) << B
86  << "\nC=\n" << std::setw(width) << C
87  << "\n* note: C should be identity, if not, indicates problem with model"
88  << "\nD=\n" << std::setw(width) << D
89  << std::endl;
90 
91  // write scicoslab file
92  std::string aircraft = fdm->GetAircraft()->GetAircraftName();
93  std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
94  scicos.precision(10);
95  width=20;
96  scicos
97  << std::scientific
98  << aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
99  << aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
100  << aircraft << ".sys = syslin('c',..\n"
101  << std::setw(width) << A << ",..\n"
102  << std::setw(width) << B << ",..\n"
103  << std::setw(width) << C << ",..\n"
104  << std::setw(width) << D << ");\n"
105  << aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
106  << std::endl;
107 
108  time_linDone = std::clock();
109  std::cout << "\nlinearization computation time: " << (time_linDone - time_start)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
110 }
111 
112 
113 } // JSBSim
114 
115 // vim:ts=4:sw=4