19 #include "FGTrimmer.h" 20 #include "models/FGFCS.h" 21 #include "models/FGPropulsion.h" 22 #include "models/FGAccelerations.h" 23 #include "models/propulsion/FGEngine.h" 24 #include "models/propulsion/FGThruster.h" 25 #include "models/propulsion/FGTank.h" 26 #include "models/FGMassBalance.h" 27 #include "models/FGAuxiliary.h" 28 #include "models/FGAircraft.h" 32 #include "simgear/misc/stdint.hxx" 33 #include "FGInitialCondition.h" 38 FGTrimmer::FGTrimmer(FGFDMExec * fdm, Constraints * constraints) :
39 m_fdm(fdm), m_constraints(constraints)
43 FGTrimmer::~FGTrimmer()
47 std::vector<double> FGTrimmer::constrain(
const std::vector<double> & dv)
50 double throttle = dv[0];
51 double elevator = dv[1];
53 double aileron = dv[3];
54 double rudder = dv[4];
58 double vt = m_constraints->velocity;
59 double altitude = m_constraints->altitude;
60 double gamma = m_constraints->gamma;
61 double phi = m_fdm->GetIC()->GetPhiRadIC();
62 double theta = m_fdm->GetIC()->GetThetaRadIC();
63 double psi = m_fdm->GetIC()->GetPsiRadIC();
64 double p = 0.0, q = 0.0, r= 0.0;
65 double u = vt*cos(alpha)*cos(beta);
66 double v = vt*sin(beta);
67 double w = vt*sin(alpha)*cos(beta);
68 double lat = m_fdm->GetIC()->GetLatitudeRadIC();
69 double lon = m_fdm->GetIC()->GetLongitudeRadIC();
72 double sGam = sin(gamma);
73 double sBeta = sin(beta);
74 double cBeta = cos(beta);
75 double tAlpha = tan(alpha);
76 double cAlpha = cos(alpha);
79 double gd = m_fdm->GetInertial()->gravity();
80 double gc = m_constraints->yawRate*vt/gd;
81 double a = 1 - gc*tAlpha*sBeta;
82 double b = sGam/cBeta;
83 double c = 1 + gc*gc*cBeta*cBeta;
84 phi = atan((gc*cBeta*((a-b*b)+
85 b*tAlpha*sqrt(c*(1-b*b)+gc*gc*sBeta*sBeta)))/
86 (cAlpha*(a*a-b*b*(1+c*tAlpha*tAlpha))));
90 b = sin(phi)*sBeta+cos(phi)*sin(alpha)*cBeta;
91 theta = atan((a*b+sGam*sqrt(a*a-sGam*sGam+b*b))/(a*a-sGam*sGam));
94 if (m_constraints->rollRate != 0.0)
96 p = m_constraints->rollRate;
98 if (m_constraints->stabAxisRoll)
100 r = m_constraints->rollRate*tan(alpha);
104 r = m_constraints->rollRate;
107 else if (m_constraints->yawRate != 0.0)
109 p = -m_constraints->yawRate*sin(theta);
110 q = m_constraints->yawRate*sin(phi)*cos(theta);
111 r = m_constraints->yawRate*cos(phi)*cos(theta);
113 else if (m_constraints->pitchRate != 0.0)
116 q = m_constraints->pitchRate;
121 m_fdm->GetIC()->ResetIC(u, v, w,
129 m_fdm->GetFCS()->SetDeCmd(elevator);
130 m_fdm->GetFCS()->SetDePos(ofNorm,elevator);
132 m_fdm->GetFCS()->SetDaCmd(aileron);
133 m_fdm->GetFCS()->SetDaLPos(ofNorm,aileron);
134 m_fdm->GetFCS()->SetDaRPos(ofNorm,aileron);
136 m_fdm->GetFCS()->SetDrPos(ofNorm,rudder);
137 m_fdm->GetFCS()->SetDrCmd(rudder);
139 for (
unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++)
141 m_fdm->GetFCS()->SetThrottleCmd(i,throttle);
142 m_fdm->GetFCS()->SetThrottlePos(i,throttle);
146 m_fdm->Initialize(m_fdm->GetIC());
147 for (
unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) {
148 m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
152 double cost = compute_cost();
154 m_fdm->GetPropulsion()->GetSteadyState();
155 m_fdm->SetTrimStatus(
true);
156 m_fdm->DisableOutput();
157 m_fdm->SuspendIntegration();
159 m_fdm->SetTrimStatus(
false);
160 m_fdm->EnableOutput();
161 m_fdm->ResumeIntegration();
163 double costNew = compute_cost();
164 double dcost = fabs(costNew - cost);
165 if (dcost < std::numeric_limits<double>::epsilon()) {
166 if(m_fdm->GetDebugLevel() > 1) {
167 std::cout <<
"cost convergd, i: " << i << std::endl;
172 if(m_fdm->GetDebugLevel() > 1) {
173 std::cout <<
"cost failed to converge, dcost: " 175 << dcost << std::endl;
182 std::vector<double> data;
184 data.push_back(theta);
188 void FGTrimmer::printSolution(std::ostream & stream,
const std::vector<double> & v)
193 double elevator = m_fdm->GetFCS()->GetDePos(ofNorm);
194 double aileron = m_fdm->GetFCS()->GetDaLPos(ofNorm);
195 double rudder = m_fdm->GetFCS()->GetDrPos(ofNorm);
196 double throttle = m_fdm->GetFCS()->GetThrottlePos(0);
197 double lat = m_fdm->GetPropagate()->GetLatitudeDeg();
198 double lon = m_fdm->GetPropagate()->GetLongitudeDeg();
199 double vt = m_fdm->GetAuxiliary()->GetVt();
215 stream << std::setw(10)
218 <<
"\naircraft state" 219 <<
"\n\tvt\t\t:\t" << vt
220 <<
"\n\talpha, deg\t:\t" << m_fdm->GetIC()->GetAlphaDegIC()
221 <<
"\n\ttheta, deg\t:\t" << m_fdm->GetIC()->GetThetaDegIC()
222 <<
"\n\tq, rad/s\t:\t" << m_fdm->GetIC()->GetQRadpsIC()
223 <<
"\n\tthrust, lbf\t:\t" << m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust()
224 <<
"\n\tbeta, deg\t:\t" << m_fdm->GetIC()->GetBetaDegIC()
225 <<
"\n\tphi, deg\t:\t" << m_fdm->GetIC()->GetPhiDegIC()
226 <<
"\n\tp, rad/s\t:\t" << m_fdm->GetIC()->GetPRadpsIC()
227 <<
"\n\tr, rad/s\t:\t" << m_fdm->GetIC()->GetRRadpsIC()
228 <<
"\n\tmass (lbm)\t:\t" << m_fdm->GetMassBalance()->GetWeight()
231 <<
"\n\nactuator state" 232 <<
"\n\tthrottle, %\t:\t" << 100*throttle
233 <<
"\n\televator, %\t:\t" << 100*elevator
234 <<
"\n\taileron, %\t:\t" << 100*aileron
235 <<
"\n\trudder, %\t:\t" << 100*rudder
239 <<
"\n\taltitude, ft\t:\t" << m_fdm->GetIC()->GetAltitudeASLFtIC()
240 <<
"\n\tpsi, deg\t:\t" << m_fdm->GetIC()->GetPsiDegIC()
241 <<
"\n\tlat, deg\t:\t" << lat
242 <<
"\n\tlon, deg\t:\t" << lon
245 <<
"\n\naircraft d/dt state" 249 <<
"\n\td/dt alpha, deg/s\t:\t" << m_fdm->GetAuxiliary()->Getadot()*180/M_PI
250 <<
"\n\td/dt theta, deg/s\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(2)*180/M_PI
251 <<
"\n\td/dt q, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(2)
253 <<
"\n\td/dt beta, deg/s\t:\t" << m_fdm->GetAuxiliary()->Getbdot()*180/M_PI
254 <<
"\n\td/dt phi, deg/s\t\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(1)*180/M_PI
255 <<
"\n\td/dt p, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(1)
256 <<
"\n\td/dt r, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(3)
266 <<
"\n\nd/dt nav state" 267 <<
"\n\td/dt altitude, ft/s\t:\t" << m_fdm->GetPropagate()->Gethdot()
268 <<
"\n\td/dt psi, deg/s\t\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(3)
273 <<
"\n\npropulsion system state" 274 << std::scientific << std::setw(10);
276 for (
unsigned int i=0;i<m_fdm->GetPropulsion()->GetNumTanks();i++) {
278 <<
"\n\ttank " << i <<
": fuel (lbm)\t\t\t:\t" 279 << m_fdm->GetPropulsion()->GetTank(i)->GetContents();
282 for (
unsigned int i=0;i<m_fdm->GetPropulsion()->GetNumEngines();i++) {
283 m_fdm->GetPropulsion()->GetEngine(i)->CalcFuelNeed();
285 <<
"\n\tengine " << i
286 <<
"\n\t\tfuel flow rate (lbm/s)\t\t:\t" << m_fdm->GetPropulsion()->GetEngine(i)->GetFuelFlowRate()
287 <<
"\n\t\tfuel flow rate (gph)\t\t:\t" << m_fdm->GetPropulsion()->GetEngine(i)->GetFuelFlowRateGPH()
288 <<
"\n\t\tstarved\t\t\t\t:\t" << m_fdm->GetPropulsion()->GetEngine(i)->GetStarved()
289 <<
"\n\t\trunning\t\t\t\t:\t" << m_fdm->GetPropulsion()->GetEngine(i)->GetRunning()
294 void FGTrimmer::printState(std::ostream & stream)
297 stream << std::setw(10)
308 <<
"\n\naircraft state" 309 <<
"\nvt\t\t:\t" << m_fdm->GetAuxiliary()->GetVt()
310 <<
"\nalpha, deg\t:\t" << m_fdm->GetAuxiliary()->Getalpha(ofDeg)
311 <<
"\ntheta, deg\t:\t" << m_fdm->GetPropagate()->GetEuler(2)*180/M_PI
312 <<
"\nq, rad/s\t:\t" << m_fdm->GetPropagate()->GetPQR(2)
313 <<
"\nthrust, lbf\t:\t" << m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust()
314 <<
"\nbeta, deg\t:\t" << m_fdm->GetAuxiliary()->Getbeta(ofDeg)
315 <<
"\nphi, deg\t:\t" << m_fdm->GetPropagate()->GetEuler(1)*180/M_PI
316 <<
"\np, rad/s\t:\t" << m_fdm->GetPropagate()->GetPQR(1)
317 <<
"\nr, rad/s\t:\t" << m_fdm->GetPropagate()->GetPQR(3)
320 <<
"\n\nactuator state" 321 <<
"\nthrottle, %\t:\t" << 100*m_fdm->GetFCS()->GetThrottlePos(0)
322 <<
"\nelevator, %\t:\t" << 100*m_fdm->GetFCS()->GetDePos(ofNorm)
323 <<
"\naileron, %\t:\t" << 100*m_fdm->GetFCS()->GetDaLPos(ofNorm)
324 <<
"\nrudder, %\t:\t" << 100*m_fdm->GetFCS()->GetDrPos(ofNorm)
328 <<
"\naltitude, ft\t:\t" << m_fdm->GetPropagate()->GetAltitudeASL()
329 <<
"\npsi, deg\t:\t" << m_fdm->GetPropagate()->GetEuler(3)*180/M_PI
330 <<
"\nlat, deg\t:\t" << m_fdm->GetPropagate()->GetLatitudeDeg()
331 <<
"\nlon, deg\t:\t" << m_fdm->GetPropagate()->GetLongitudeDeg()
335 <<
"\nthrottle cmd, %\t:\t" << 100*m_fdm->GetFCS()->GetThrottleCmd(0)
336 <<
"\nelevator cmd, %\t:\t" << 100*m_fdm->GetFCS()->GetDeCmd()
337 <<
"\naileron cmd, %\t:\t" << 100*m_fdm->GetFCS()->GetDaCmd()
338 <<
"\nrudder cmd, %\t:\t" << 100*m_fdm->GetFCS()->GetDrCmd()
344 double FGTrimmer::compute_cost()
346 double dvt = (m_fdm->GetPropagate()->GetUVW(1)*m_fdm->GetAccelerations()->GetUVWdot(1) +
347 m_fdm->GetPropagate()->GetUVW(2)*m_fdm->GetAccelerations()->GetUVWdot(2) +
348 m_fdm->GetPropagate()->GetUVW(3)*m_fdm->GetAccelerations()->GetUVWdot(3))/
349 m_fdm->GetAuxiliary()->GetVt();
350 double dalpha = m_fdm->GetAuxiliary()->Getadot();
351 double dbeta = m_fdm->GetAuxiliary()->Getbdot();
352 double dp = m_fdm->GetAccelerations()->GetPQRdot(1);
353 double dq = m_fdm->GetAccelerations()->GetPQRdot(2);
354 double dr = m_fdm->GetAccelerations()->GetPQRdot(3);
356 if(m_fdm->GetDebugLevel() > 1) {
359 <<
"\tdalpha: " << dalpha
360 <<
"\tdbeta: " << dbeta
368 100.0*(dalpha*dalpha + dbeta*dbeta) +
369 10.0*(dp*dp + dq*dq + dr*dr);
372 double FGTrimmer::eval(
const std::vector<double> & v)
375 return compute_cost();