JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGSimplexTrim.cpp
1 /*
2  * FGSimplexTrim.cpp
3  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
4  *
5  * FGSimplexTrim.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  * FGSimplexTrim.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 "FGTrim.h"
20 #include "FGSimplexTrim.h"
21 #include <ctime>
22 
23 namespace JSBSim {
24 
25 FGSimplexTrim::FGSimplexTrim(FGFDMExec * fdm, TrimMode mode)
26 {
27  std::clock_t time_start=clock(), time_trimDone;
28 
29  // variables
30  FGTrimmer::Constraints constraints;
31 
32  if (fdm->GetDebugLevel() > 0) {
33  std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
34  }
35 
36  // defaults
37  std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
38  FGPropertyNode* node = fdm->GetPropertyManager()->GetNode();
39  double rtol = node->GetDouble("trim/solver/rtol");
40  double abstol = node->GetDouble("trim/solver/abstol");
41  double speed = node->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
42  double random = node->GetDouble("trim/solver/random");
43  int iterMax = node->GetInt("trim/solver/iterMax");
44  bool showConvergence = node->GetBool("trim/solver/showConvergence");
45  bool pause = node->GetBool("trim/solver/pause");
46  bool showSimplex = node->GetBool("trim/solver/showSimplex");
47 
48  // flight conditions
49  double phi = fdm->GetIC()->GetPhiRadIC();
50  double theta = fdm->GetIC()->GetThetaRadIC();
51  double gd = fdm->GetInertial()->gravity();
52 
53  constraints.velocity = fdm->GetIC()->GetVtrueFpsIC();
54  constraints.altitude = fdm->GetIC()->GetAltitudeASLFtIC();
55  constraints.gamma = fdm->GetIC()->GetFlightPathAngleRadIC();
56  constraints.rollRate = 0;
57  constraints.pitchRate = 0;
58  constraints.yawRate = tan(phi)*gd*cos(theta)/constraints.velocity;
59 
60  constraints.stabAxisRoll = true; // FIXME, make this an option
61 
62  // initial solver state
63  int n = 6;
64  std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
65 
66  lowerBound[0] = node->GetDouble("trim/solver/throttleMin");
67  lowerBound[1] = node->GetDouble("trim/solver/elevatorMin");
68  lowerBound[2] = node->GetDouble("trim/solver/alphaMin");
69  lowerBound[3] = node->GetDouble("trim/solver/aileronMin");
70  lowerBound[4] = node->GetDouble("trim/solver/rudderMin");
71  lowerBound[5] = node->GetDouble("trim/solver/betaMin");
72 
73  upperBound[0] = node->GetDouble("trim/solver/throttleMax");
74  upperBound[1] = node->GetDouble("trim/solver/elevatorMax");
75  upperBound[2] = node->GetDouble("trim/solver/alphaMax");
76  upperBound[3] = node->GetDouble("trim/solver/aileronMax");
77  upperBound[4] = node->GetDouble("trim/solver/rudderMax");
78  upperBound[5] = node->GetDouble("trim/solver/betaMax");
79 
80  initialStepSize[0] = node->GetDouble("trim/solver/throttleStep");
81  initialStepSize[1] = node->GetDouble("trim/solver/elevatorStep");
82  initialStepSize[2] = node->GetDouble("trim/solver/alphaStep");
83  initialStepSize[3] = node->GetDouble("trim/solver/aileronStep");
84  initialStepSize[4] = node->GetDouble("trim/solver/rudderStep");
85  initialStepSize[5] = node->GetDouble("trim/solver/betaStep");
86 
87  initialGuess[0] = node->GetDouble("trim/solver/throttleGuess");
88  initialGuess[1] = node->GetDouble("trim/solver/elevatorGuess");
89  initialGuess[2] = node->GetDouble("trim/solver/alphaGuess");
90  initialGuess[3] = node->GetDouble("trim/solver/aileronGuess");
91  initialGuess[4] = node->GetDouble("trim/solver/rudderGuess");
92  initialGuess[5] = node->GetDouble("trim/solver/betaGuess");
93 
94  // solve
95  FGTrimmer * trimmer = new FGTrimmer(fdm, &constraints);
96  Callback callback(aircraftName, trimmer);
97  FGNelderMead * solver = NULL;
98 
99  solver = new FGNelderMead(trimmer,initialGuess,
100  lowerBound, upperBound, initialStepSize,iterMax,rtol,
101  abstol,speed,random,showConvergence,showSimplex,pause,&callback);
102  while(solver->status()==1) solver->update();
103  time_trimDone = std::clock();
104 
105  // output
106  if (fdm->GetDebugLevel() > 0) {
107  trimmer->printSolution(std::cout,solver->getSolution());
108  std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer->eval(solver->getSolution()) << std::endl;
109  std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
110  }
111 
112  delete solver;
113  delete trimmer;
114 }
115 
116 } // JSBSim
117 
118 // vim:ts=4:sw=4