1 /*******************************************************************************
3 Header: FGInitialCondition.cpp
7 ------------- Copyright (C) 1999 Anthony K. Peden (apeden@earthlink.net) -------------
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA.
23 Further information about the GNU Lesser General Public License can also be found on
24 the world wide web at http://www.gnu.org.
28 --------------------------------------------------------------------------------
32 FUNCTIONAL DESCRIPTION
33 --------------------------------------------------------------------------------
35 The purpose of this class is to take a set of initial conditions and provide
36 a kinematically consistent set of body axis velocity components, euler
37 angles, and altitude. This class does not attempt to trim the model i.e.
38 the sim will most likely start in a very dynamic state (unless, of course,
39 you have chosen your IC's wisely) even after setting it up with this class.
41 ********************************************************************************
43 *******************************************************************************/
45 #include "FGInitialCondition.h"
46 #include <FGFDMExec.h>
47 #include <models/FGInertial.h>
48 #include <models/FGAtmosphere.h>
49 #include <models/FGAerodynamics.h>
50 #include <models/FGPropagate.h>
51 #include <input_output/FGPropertyManager.h>
52 #include <models/FGPropulsion.h>
53 #include <input_output/FGXMLParse.h>
54 #include <math/FGQuaternion.h>
59 static const char *IdSrc = "$Id$";
60 static const char *IdHdr = ID_INITIALCONDITION;
62 //******************************************************************************
64 FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) : fdmex(FDMExec)
68 if(FDMExec != NULL ) {
69 fdmex->GetPropagate()->SetAltitudeASL(altitudeASL);
70 fdmex->GetAtmosphere()->Run();
71 PropertyManager=fdmex->GetPropertyManager();
76 cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
82 //******************************************************************************
84 FGInitialCondition::~FGInitialCondition()
89 //******************************************************************************
91 void FGInitialCondition::ResetIC(double u0, double v0, double w0,
92 double p0, double q0, double r0,
93 double alpha0, double beta0,
94 double phi0, double theta0, double psi0,
95 double latRad0, double lonRad0, double altAGLFt0,
100 u = u0; v = v0; w = w0;
101 p = p0; q = q0; r = r0;
102 alpha = alpha0; beta = beta0;
103 phi = phi0; theta = theta0; psi = psi0;
108 SetAltitudeAGLFtIC(altAGLFt0);
110 cphi = cos(phi); sphi = sin(phi); // phi, rad
111 ctheta = cos(theta); stheta = sin(theta); // theta, rad
112 cpsi = cos(psi); spsi = sin(psi); // psi, rad
114 FGQuaternion Quat( phi, theta, psi );
117 const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame
118 const FGMatrix33& _Tb2l = Quat.GetTInv(); // body to local
120 FGColumnVector3 _vUVW_BODY(u,v,w);
121 FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY;
122 FGColumnVector3 _vWIND_NED(wnorth,weast,wdown);
123 // FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED );
125 uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3);
129 //******************************************************************************
131 void FGInitialCondition::InitializeIC(void)
138 latitude=longitude=0;
142 vnorth=veast=vdown=0;
143 wnorth=weast=wdown=0;
148 radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius();
149 terrain_elevation = 0;
153 salpha=sbeta=stheta=sphi=spsi=sgamma=0;
154 calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
157 //******************************************************************************
159 void FGInitialCondition::WriteStateFile(int num)
161 if (Constructing) return;
163 string filename = fdmex->GetFullAircraftPath();
165 if (filename.empty())
166 filename = "initfile.xml";
168 filename.append("/initfile.xml");
170 ofstream outfile(filename.c_str());
171 FGPropagate* Propagate = fdmex->GetPropagate();
173 if (outfile.is_open()) {
174 outfile << "<?xml version=\"1.0\"?>" << endl;
175 outfile << "<initialize name=\"reset00\">" << endl;
176 outfile << " <ubody unit=\"FT/SEC\"> " << Propagate->GetUVW(eX) << " </ubody> " << endl;
177 outfile << " <vbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eY) << " </vbody> " << endl;
178 outfile << " <wbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eZ) << " </wbody> " << endl;
179 outfile << " <phi unit=\"DEG\"> " << Propagate->GetEuler(ePhi) << " </phi>" << endl;
180 outfile << " <theta unit=\"DEG\"> " << Propagate->GetEuler(eTht) << " </theta>" << endl;
181 outfile << " <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl;
182 outfile << " <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl;
183 outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
184 outfile << " <altitude unit=\"FT\"> " << Propagate->GetAltitudeASL() << " </altitude>" << endl;
185 outfile << "</initialize>" << endl;
188 cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl;
192 //******************************************************************************
194 void FGInitialCondition::SetVcalibratedKtsIC(double tt) {
196 if(getMachFromVcas(&mach,tt*ktstofps)) {
197 //cout << "Mach: " << mach << endl;
200 vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
201 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
202 //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
205 cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl;
206 cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl;
210 //******************************************************************************
212 void FGInitialCondition::SetVequivalentKtsIC(double tt) {
215 vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
216 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
220 //******************************************************************************
222 void FGInitialCondition::SetVgroundFpsIC(double tt) {
228 vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0;
230 ua = u + uw; va = v + vw; wa = w + ww;
231 vt = sqrt( ua*ua + va*va + wa*wa );
233 vxz = sqrt( u*u + w*w );
234 if( w != 0 ) alpha = atan2( w, u );
235 if( vxz != 0 ) beta = atan2( v, vxz );
236 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
238 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
241 //******************************************************************************
243 void FGInitialCondition::SetVtrueFpsIC(double tt) {
246 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
248 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
251 //******************************************************************************
253 void FGInitialCondition::SetMachIC(double tt) {
255 lastSpeedSet=setmach;
256 vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
258 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
259 //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
262 //******************************************************************************
264 void FGInitialCondition::SetClimbRateFpmIC(double tt) {
265 SetClimbRateFpsIC(tt/60.0);
268 //******************************************************************************
270 void FGInitialCondition::SetClimbRateFpsIC(double tt) {
275 sgamma=sin(gamma); cgamma=cos(gamma);
279 //******************************************************************************
281 void FGInitialCondition::SetFlightPathAngleRadIC(double tt) {
283 sgamma=sin(gamma); cgamma=cos(gamma);
288 //******************************************************************************
290 void FGInitialCondition::SetAlphaRadIC(double tt) {
292 salpha=sin(alpha); calpha=cos(alpha);
296 //******************************************************************************
298 void FGInitialCondition::SetThetaRadIC(double tt) {
300 stheta=sin(theta); ctheta=cos(theta);
304 //******************************************************************************
306 void FGInitialCondition::SetBetaRadIC(double tt) {
308 sbeta=sin(beta); cbeta=cos(beta);
313 //******************************************************************************
315 void FGInitialCondition::SetPhiRadIC(double tt) {
317 sphi=sin(phi); cphi=cos(phi);
321 //******************************************************************************
323 void FGInitialCondition::SetPsiRadIC(double tt) {
325 spsi=sin(psi); cpsi=cos(psi);
329 //******************************************************************************
331 void FGInitialCondition::SetUBodyFpsIC(double tt) {
333 vt=sqrt(u*u + v*v + w*w);
337 //******************************************************************************
339 void FGInitialCondition::SetVBodyFpsIC(double tt) {
341 vt=sqrt(u*u + v*v + w*w);
345 //******************************************************************************
347 void FGInitialCondition::SetWBodyFpsIC(double tt) {
349 vt=sqrt( u*u + v*v + w*w );
354 //******************************************************************************
356 void FGInitialCondition::SetVNorthFpsIC(double tt) {
361 ua = u + uw; va = v + vw; wa = w + ww;
362 vt = sqrt( ua*ua + va*va + wa*wa );
364 vxz = sqrt( u*u + w*w );
365 if( w != 0 ) alpha = atan2( w, u );
366 if( vxz != 0 ) beta = atan2( v, vxz );
367 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
369 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
373 //******************************************************************************
375 void FGInitialCondition::SetVEastFpsIC(double tt) {
380 ua = u + uw; va = v + vw; wa = w + ww;
381 vt = sqrt( ua*ua + va*va + wa*wa );
383 vxz = sqrt( u*u + w*w );
384 if( w != 0 ) alpha = atan2( w, u );
385 if( vxz != 0 ) beta = atan2( v, vxz );
386 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
388 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
392 //******************************************************************************
394 void FGInitialCondition::SetVDownFpsIC(double tt) {
399 ua = u + uw; va = v + vw; wa = w + ww;
400 vt = sqrt( ua*ua + va*va + wa*wa );
402 vxz = sqrt( u*u + w*w );
403 if( w != 0 ) alpha = atan2( w, u );
404 if( vxz != 0 ) beta = atan2( v, vxz );
405 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
407 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
408 SetClimbRateFpsIC(-1*vdown);
412 //******************************************************************************
414 double FGInitialCondition::GetUBodyFpsIC(void) const {
415 if (lastSpeedSet == setvg || lastSpeedSet == setned)
418 return vt*calpha*cbeta - uw;
421 //******************************************************************************
423 double FGInitialCondition::GetVBodyFpsIC(void) const {
424 if (lastSpeedSet == setvg || lastSpeedSet == setned)
427 return vt*sbeta - vw;
431 //******************************************************************************
433 double FGInitialCondition::GetWBodyFpsIC(void) const {
434 if (lastSpeedSet == setvg || lastSpeedSet == setned)
437 return vt*salpha*cbeta -ww;
440 //******************************************************************************
442 void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) {
443 wnorth = wN; weast = wE; wdown = wD;
444 lastWindSet = setwned;
446 if(lastSpeedSet == setvg)
450 //******************************************************************************
452 void FGInitialCondition::SetCrossWindKtsIC(double cross){
453 wcross=cross*ktstofps;
456 if(lastSpeedSet == setvg)
461 //******************************************************************************
463 // positive from left
464 void FGInitialCondition::SetHeadWindKtsIC(double head){
468 if(lastSpeedSet == setvg)
473 //******************************************************************************
475 void FGInitialCondition::SetWindDownKtsIC(double wD) {
478 if(lastSpeedSet == setvg)
482 //******************************************************************************
484 void FGInitialCondition::SetWindMagKtsIC(double mag) {
488 if(lastSpeedSet == setvg)
492 //******************************************************************************
494 void FGInitialCondition::SetWindDirDegIC(double dir) {
498 if(lastSpeedSet == setvg)
503 //******************************************************************************
505 void FGInitialCondition::calcWindUVW(void) {
507 switch(lastWindSet) {
509 wnorth=wmag*cos(wdir);
510 weast=wmag*sin(wdir);
513 wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2);
514 weast=whead*sin(psi) + wcross*sin(psi+M_PI/2);
519 uw=wnorth*ctheta*cpsi +
522 vw=wnorth*( sphi*stheta*cpsi - cphi*spsi ) +
523 weast*( sphi*stheta*spsi + cphi*cpsi ) +
525 ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) +
526 weast*(cphi*stheta*spsi - sphi*cpsi) +
530 /* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown "
531 << wnorth << ", " << weast << ", " << wdown << endl;
532 cout << "FGInitialCondition::calcWindUVW: theta, phi, psi "
533 << theta << ", " << phi << ", " << psi << endl;
534 cout << "FGInitialCondition::calcWindUVW: uw, vw, ww "
535 << uw << ", " << vw << ", " << ww << endl; */
539 //******************************************************************************
541 void FGInitialCondition::SetAltitudeASLFtIC(double tt)
544 fdmex->GetPropagate()->SetAltitudeASL(altitudeASL);
545 fdmex->GetAtmosphere()->Run();
546 //lets try to make sure the user gets what they intended
548 switch(lastSpeedSet) {
552 SetVtrueKtsIC(vt*fpstokts);
555 SetVcalibratedKtsIC(vc*fpstokts);
558 SetVequivalentKtsIC(ve*fpstokts);
569 //******************************************************************************
571 void FGInitialCondition::SetAltitudeAGLFtIC(double tt)
573 SetAltitudeASLFtIC(terrain_elevation + tt);
576 //******************************************************************************
578 void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt)
580 sea_level_radius = tt;
583 //******************************************************************************
585 void FGInitialCondition::SetTerrainElevationFtIC(double tt)
587 terrain_elevation=tt;
590 //******************************************************************************
592 void FGInitialCondition::calcUVWfromNED(void)
594 u=vnorth*ctheta*cpsi +
597 v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) +
598 veast*( sphi*stheta*spsi + cphi*cpsi ) +
600 w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) +
601 veast*( cphi*stheta*spsi - sphi*cpsi ) +
605 //******************************************************************************
607 bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) {
613 sfunc=&FGInitialCondition::calcVcas;
614 if(findInterval(vcas,guess)) {
615 if(solve(&mach,vcas))
621 //******************************************************************************
623 bool FGInitialCondition::getAlpha(void) {
625 double guess=theta-gamma;
627 if(vt < 0.01) return 0;
630 xmin=fdmex->GetAerodynamics()->GetAlphaCLMin();
631 xmax=fdmex->GetAerodynamics()->GetAlphaCLMax();
632 sfunc=&FGInitialCondition::GammaEqOfAlpha;
633 if(findInterval(0,guess)){
644 //******************************************************************************
646 bool FGInitialCondition::getTheta(void) {
648 double guess=alpha+gamma;
650 if(vt < 0.01) return 0;
654 sfunc=&FGInitialCondition::GammaEqOfTheta;
655 if(findInterval(0,guess)){
666 //******************************************************************************
668 double FGInitialCondition::GammaEqOfTheta(double Theta) {
670 double sTheta,cTheta;
672 //theta=Theta; stheta=sin(theta); ctheta=cos(theta);
673 sTheta=sin(Theta); cTheta=cos(Theta);
675 a=wdown + vt*calpha*cbeta + uw;
676 b=vt*sphi*sbeta + vw*sphi;
677 c=vt*cphi*salpha*cbeta + ww*cphi;
678 return vt*sgamma - ( a*sTheta - (b+c)*cTheta);
681 //******************************************************************************
683 double FGInitialCondition::GammaEqOfAlpha(double Alpha) {
685 double sAlpha,cAlpha;
686 sAlpha=sin(Alpha); cAlpha=cos(Alpha);
687 a=wdown + vt*cAlpha*cbeta + uw;
688 b=vt*sphi*sbeta + vw*sphi;
689 c=vt*cphi*sAlpha*cbeta + ww*cphi;
691 return vt*sgamma - ( a*stheta - (b+c)*ctheta );
694 //******************************************************************************
696 double FGInitialCondition::calcVcas(double Mach) {
698 double p=fdmex->GetAtmosphere()->GetPressure();
699 double psl=fdmex->GetAtmosphere()->GetPressureSL();
700 double rhosl=fdmex->GetAtmosphere()->GetDensitySL();
701 double pt,A,B,D,vcas;
703 if(Mach < 1) //calculate total pressure assuming isentropic flow
704 pt=p*pow((1 + 0.2*Mach*Mach),3.5);
706 // shock in front of pitot tube, we'll assume its normal and use
707 // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
708 // pressure behind the shock to the static pressure in front
711 //the normal shock assumption should not be a bad one -- most supersonic
712 //aircraft place the pitot probe out front so that it is the forward
713 //most point on the aircraft. The real shock would, of course, take
714 //on something like the shape of a rounded-off cone but, here again,
715 //the assumption should be good since the opening of the pitot probe
716 //is very small and, therefore, the effects of the shock curvature
717 //should be small as well. AFAIK, this approach is fairly well accepted
718 //within the aerospace community
720 B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);
722 // The denominator above is zero for Mach ~ 0.38, for which
723 // we'll never be here, so we're safe
725 D = (2.8*Mach*Mach-0.4)*0.4167;
729 A = pow(((pt-p)/psl+1),0.28571);
730 vcas = sqrt(7*psl/rhosl*(A-1));
731 //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl;
735 //******************************************************************************
737 bool FGInitialCondition::findInterval(double x,double guess) {
738 //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){
742 double flo,fhi,fguess;
745 fguess=(this->*sfunc)(guess)-x;
751 if(lo < xmin) lo=xmin;
752 if(hi > xmax) hi=xmax;
754 flo=(this->*sfunc)(lo)-x;
755 fhi=(this->*sfunc)(hi)-x;
756 if(flo*fhi <=0) { //found interval with root
758 if(flo*fguess <= 0) { //narrow interval down a bit
759 hi=lo+step; //to pass solver interval that is as
762 else if(fhi*fguess <= 0) {
766 //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl;
768 while((found == 0) && (i <= 100));
774 //******************************************************************************
776 bool FGInitialCondition::solve(double *y,double x)
778 double x1,x2,x3,f1,f2,f3,d,d0;
780 double const relax =0.9;
788 f1=(this->*sfunc)(x1)-x;
789 f3=(this->*sfunc)(x3)-x;
794 while ((fabs(d) > eps) && (i < 100)) {
796 x2 = x1-d*d0*f1/(f3-f1);
798 f2=(this->*sfunc)(x2)-x;
799 //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
800 //cout << " " << f1 << "," << f2 << "," << f3 << endl;
802 if(fabs(f2) <= 0.001) {
804 } else if(f1*f2 <= 0.0) {
808 } else if(f2*f3 <= 0) {
821 //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl;
825 //******************************************************************************
827 double FGInitialCondition::GetWindDirDegIC(void) const {
829 return atan2(weast,wnorth)*radtodeg;
836 //******************************************************************************
838 bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
843 if( useStoredPath ) {
844 init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml";
846 init_file_name = rstfile;
849 document = LoadXMLDocument(init_file_name);
851 // Make sure that the document is valid
853 cerr << "File: " << init_file_name << " could not be read." << endl;
857 if (document->GetName() != string("initialize")) {
858 cerr << "File: " << init_file_name << " is not a reset file." << endl;
862 if (document->FindElement("latitude"))
863 SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
864 if (document->FindElement("longitude"))
865 SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
866 if (document->FindElement("elevation"))
867 SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT"));
868 if (document->FindElement("altitude")) // This is feet above ground level
869 SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
870 if (document->FindElement("ubody"))
871 SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
872 if (document->FindElement("vbody"))
873 SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC"));
874 if (document->FindElement("wbody"))
875 SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC"));
876 if (document->FindElement("vnorth"))
877 SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC"));
878 if (document->FindElement("veast"))
879 SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC"));
880 if (document->FindElement("vdown"))
881 SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC"));
882 if (document->FindElement("winddir"))
883 SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
884 if (document->FindElement("vwind"))
885 SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS"));
886 if (document->FindElement("hwind"))
887 SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
888 if (document->FindElement("xwind"))
889 SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
890 if (document->FindElement("vc"))
891 SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS"));
892 if (document->FindElement("vt"))
893 SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS"));
894 if (document->FindElement("mach"))
895 SetMachIC(document->FindElementValueAsNumber("mach"));
896 if (document->FindElement("phi"))
897 SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG"));
898 if (document->FindElement("theta"))
899 SetThetaDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG"));
900 if (document->FindElement("psi"))
901 SetPsiDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG"));
902 if (document->FindElement("alpha"))
903 SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG"));
904 if (document->FindElement("beta"))
905 SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG"));
906 if (document->FindElement("gamma"))
907 SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG"));
908 if (document->FindElement("roc"))
909 SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
910 if (document->FindElement("vground"))
911 SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS"));
912 if (document->FindElement("targetNlf"))
914 SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
917 // Check to see if any engines are specified to be initialized in a running state
918 FGPropulsion* propulsion = fdmex->GetPropulsion();
919 Element* running_elements = document->FindElement("running");
920 while (running_elements) {
921 n = int(running_elements->GetDataAsNumber());
922 propulsion->InitRunning(n);
923 running_elements = document->FindNextElement("running");
931 //******************************************************************************
933 void FGInitialCondition::bind(void){
934 PropertyManager->Tie("ic/vc-kts", this,
935 &FGInitialCondition::GetVcalibratedKtsIC,
936 &FGInitialCondition::SetVcalibratedKtsIC,
938 PropertyManager->Tie("ic/ve-kts", this,
939 &FGInitialCondition::GetVequivalentKtsIC,
940 &FGInitialCondition::SetVequivalentKtsIC,
942 PropertyManager->Tie("ic/vg-kts", this,
943 &FGInitialCondition::GetVgroundKtsIC,
944 &FGInitialCondition::SetVgroundKtsIC,
946 PropertyManager->Tie("ic/vt-kts", this,
947 &FGInitialCondition::GetVtrueKtsIC,
948 &FGInitialCondition::SetVtrueKtsIC,
950 PropertyManager->Tie("ic/mach", this,
951 &FGInitialCondition::GetMachIC,
952 &FGInitialCondition::SetMachIC,
954 PropertyManager->Tie("ic/roc-fpm", this,
955 &FGInitialCondition::GetClimbRateFpmIC,
956 &FGInitialCondition::SetClimbRateFpmIC,
958 PropertyManager->Tie("ic/gamma-deg", this,
959 &FGInitialCondition::GetFlightPathAngleDegIC,
960 &FGInitialCondition::SetFlightPathAngleDegIC,
962 PropertyManager->Tie("ic/alpha-deg", this,
963 &FGInitialCondition::GetAlphaDegIC,
964 &FGInitialCondition::SetAlphaDegIC,
966 PropertyManager->Tie("ic/beta-deg", this,
967 &FGInitialCondition::GetBetaDegIC,
968 &FGInitialCondition::SetBetaDegIC,
970 PropertyManager->Tie("ic/theta-deg", this,
971 &FGInitialCondition::GetThetaDegIC,
972 &FGInitialCondition::SetThetaDegIC,
974 PropertyManager->Tie("ic/phi-deg", this,
975 &FGInitialCondition::GetPhiDegIC,
976 &FGInitialCondition::SetPhiDegIC,
978 PropertyManager->Tie("ic/psi-true-deg", this,
979 &FGInitialCondition::GetPsiDegIC );
980 PropertyManager->Tie("ic/lat-gc-deg", this,
981 &FGInitialCondition::GetLatitudeDegIC,
982 &FGInitialCondition::SetLatitudeDegIC,
984 PropertyManager->Tie("ic/long-gc-deg", this,
985 &FGInitialCondition::GetLongitudeDegIC,
986 &FGInitialCondition::SetLongitudeDegIC,
988 PropertyManager->Tie("ic/h-sl-ft", this,
989 &FGInitialCondition::GetAltitudeASLFtIC,
990 &FGInitialCondition::SetAltitudeASLFtIC,
992 PropertyManager->Tie("ic/h-agl-ft", this,
993 &FGInitialCondition::GetAltitudeAGLFtIC,
994 &FGInitialCondition::SetAltitudeAGLFtIC,
996 PropertyManager->Tie("ic/sea-level-radius-ft", this,
997 &FGInitialCondition::GetSeaLevelRadiusFtIC,
998 &FGInitialCondition::SetSeaLevelRadiusFtIC,
1000 PropertyManager->Tie("ic/terrain-elevation-ft", this,
1001 &FGInitialCondition::GetTerrainElevationFtIC,
1002 &FGInitialCondition::SetTerrainElevationFtIC,
1004 PropertyManager->Tie("ic/vg-fps", this,
1005 &FGInitialCondition::GetVgroundFpsIC,
1006 &FGInitialCondition::SetVgroundFpsIC,
1008 PropertyManager->Tie("ic/vt-fps", this,
1009 &FGInitialCondition::GetVtrueFpsIC,
1010 &FGInitialCondition::SetVtrueFpsIC,
1012 PropertyManager->Tie("ic/vw-bx-fps", this,
1013 &FGInitialCondition::GetWindUFpsIC);
1014 PropertyManager->Tie("ic/vw-by-fps", this,
1015 &FGInitialCondition::GetWindVFpsIC);
1016 PropertyManager->Tie("ic/vw-bz-fps", this,
1017 &FGInitialCondition::GetWindWFpsIC);
1018 PropertyManager->Tie("ic/vw-north-fps", this,
1019 &FGInitialCondition::GetWindNFpsIC);
1020 PropertyManager->Tie("ic/vw-east-fps", this,
1021 &FGInitialCondition::GetWindEFpsIC);
1022 PropertyManager->Tie("ic/vw-down-fps", this,
1023 &FGInitialCondition::GetWindDFpsIC);
1024 PropertyManager->Tie("ic/vw-mag-fps", this,
1025 &FGInitialCondition::GetWindFpsIC);
1026 PropertyManager->Tie("ic/vw-dir-deg", this,
1027 &FGInitialCondition::GetWindDirDegIC,
1028 &FGInitialCondition::SetWindDirDegIC,
1031 PropertyManager->Tie("ic/roc-fps", this,
1032 &FGInitialCondition::GetClimbRateFpsIC,
1033 &FGInitialCondition::SetClimbRateFpsIC,
1035 PropertyManager->Tie("ic/u-fps", this,
1036 &FGInitialCondition::GetUBodyFpsIC,
1037 &FGInitialCondition::SetUBodyFpsIC,
1039 PropertyManager->Tie("ic/v-fps", this,
1040 &FGInitialCondition::GetVBodyFpsIC,
1041 &FGInitialCondition::SetVBodyFpsIC,
1043 PropertyManager->Tie("ic/w-fps", this,
1044 &FGInitialCondition::GetWBodyFpsIC,
1045 &FGInitialCondition::SetWBodyFpsIC,
1047 PropertyManager->Tie("ic/vn-fps", this,
1048 &FGInitialCondition::GetVNorthFpsIC,
1049 &FGInitialCondition::SetVNorthFpsIC,
1051 PropertyManager->Tie("ic/ve-fps", this,
1052 &FGInitialCondition::GetVEastFpsIC,
1053 &FGInitialCondition::SetVEastFpsIC,
1055 PropertyManager->Tie("ic/vd-fps", this,
1056 &FGInitialCondition::GetVDownFpsIC,
1057 &FGInitialCondition::SetVDownFpsIC,
1059 PropertyManager->Tie("ic/gamma-rad", this,
1060 &FGInitialCondition::GetFlightPathAngleRadIC,
1061 &FGInitialCondition::SetFlightPathAngleRadIC,
1063 PropertyManager->Tie("ic/alpha-rad", this,
1064 &FGInitialCondition::GetAlphaRadIC,
1065 &FGInitialCondition::SetAlphaRadIC,
1067 PropertyManager->Tie("ic/theta-rad", this,
1068 &FGInitialCondition::GetThetaRadIC,
1069 &FGInitialCondition::SetThetaRadIC,
1071 PropertyManager->Tie("ic/beta-rad", this,
1072 &FGInitialCondition::GetBetaRadIC,
1073 &FGInitialCondition::SetBetaRadIC,
1075 PropertyManager->Tie("ic/phi-rad", this,
1076 &FGInitialCondition::GetPhiRadIC,
1077 &FGInitialCondition::SetPhiRadIC,
1079 PropertyManager->Tie("ic/psi-true-rad", this,
1080 &FGInitialCondition::GetPsiRadIC);
1081 PropertyManager->Tie("ic/lat-gc-rad", this,
1082 &FGInitialCondition::GetLatitudeRadIC,
1083 &FGInitialCondition::SetLatitudeRadIC,
1085 PropertyManager->Tie("ic/long-gc-rad", this,
1086 &FGInitialCondition::GetLongitudeRadIC,
1087 &FGInitialCondition::SetLongitudeRadIC,
1089 PropertyManager->Tie("ic/p-rad_sec", this,
1090 &FGInitialCondition::GetPRadpsIC,
1091 &FGInitialCondition::SetPRadpsIC,
1093 PropertyManager->Tie("ic/q-rad_sec", this,
1094 &FGInitialCondition::GetQRadpsIC,
1095 &FGInitialCondition::SetQRadpsIC,
1097 PropertyManager->Tie("ic/r-rad_sec", this,
1098 &FGInitialCondition::GetRRadpsIC,
1099 &FGInitialCondition::SetRRadpsIC,
1102 typedef int (FGInitialCondition::*iPMF)(void) const;
1103 PropertyManager->Tie("simulation/write-state-file",
1106 &FGInitialCondition::WriteStateFile);
1110 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 // The bitmasked value choices are as follows:
1112 // unset: In this case (the default) JSBSim would only print
1113 // out the normally expected messages, essentially echoing
1114 // the config files as they are read. If the environment
1115 // variable is not set, debug_lvl is set to 1 internally
1116 // 0: This requests JSBSim not to output any messages
1118 // 1: This value explicity requests the normal JSBSim
1120 // 2: This value asks for a message to be printed out when
1121 // a class is instantiated
1122 // 4: When this value is set, a message is displayed when a
1123 // FGModel object executes its Run() method
1124 // 8: When this value is set, various runtime state variables
1125 // are printed out periodically
1126 // 16: When set various parameters are sanity checked and
1127 // a message is printed out when they go out of bounds
1129 void FGInitialCondition::Debug(int from)
1131 if (debug_lvl <= 0) return;
1133 if (debug_lvl & 1) { // Standard console startup message output
1135 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1136 if (from == 0) cout << "Instantiated: FGInitialCondition" << endl;
1137 if (from == 1) cout << "Destroyed: FGInitialCondition" << endl;
1139 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1141 if (debug_lvl & 8 ) { // Runtime state variables
1143 if (debug_lvl & 16) { // Sanity checking
1145 if (debug_lvl & 64) {
1146 if (from == 0) { // Constructor
1147 cout << IdSrc << endl;
1148 cout << IdHdr << endl;