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"));
869 if (document->FindElement("altitude")) // This is feet above ground level
870 SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
871 else if (document->FindElement("altitudeAGL")) // This is feet above ground level
872 SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
873 else if (document->FindElement("altitudeMSL")) // This is feet above sea level
874 SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
876 if (document->FindElement("ubody"))
877 SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
878 if (document->FindElement("vbody"))
879 SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC"));
880 if (document->FindElement("wbody"))
881 SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC"));
882 if (document->FindElement("vnorth"))
883 SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC"));
884 if (document->FindElement("veast"))
885 SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC"));
886 if (document->FindElement("vdown"))
887 SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC"));
888 if (document->FindElement("winddir"))
889 SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
890 if (document->FindElement("vwind"))
891 SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS"));
892 if (document->FindElement("hwind"))
893 SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
894 if (document->FindElement("xwind"))
895 SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
896 if (document->FindElement("vc"))
897 SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS"));
898 if (document->FindElement("vt"))
899 SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS"));
900 if (document->FindElement("mach"))
901 SetMachIC(document->FindElementValueAsNumber("mach"));
902 if (document->FindElement("phi"))
903 SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG"));
904 if (document->FindElement("theta"))
905 SetThetaDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG"));
906 if (document->FindElement("psi"))
907 SetPsiDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG"));
908 if (document->FindElement("alpha"))
909 SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG"));
910 if (document->FindElement("beta"))
911 SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG"));
912 if (document->FindElement("gamma"))
913 SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG"));
914 if (document->FindElement("roc"))
915 SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
916 if (document->FindElement("vground"))
917 SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS"));
918 if (document->FindElement("targetNlf"))
920 SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
923 // Check to see if any engines are specified to be initialized in a running state
924 FGPropulsion* propulsion = fdmex->GetPropulsion();
925 Element* running_elements = document->FindElement("running");
926 while (running_elements) {
927 n = int(running_elements->GetDataAsNumber());
928 propulsion->InitRunning(n);
929 running_elements = document->FindNextElement("running");
937 //******************************************************************************
939 void FGInitialCondition::bind(void){
940 PropertyManager->Tie("ic/vc-kts", this,
941 &FGInitialCondition::GetVcalibratedKtsIC,
942 &FGInitialCondition::SetVcalibratedKtsIC,
944 PropertyManager->Tie("ic/ve-kts", this,
945 &FGInitialCondition::GetVequivalentKtsIC,
946 &FGInitialCondition::SetVequivalentKtsIC,
948 PropertyManager->Tie("ic/vg-kts", this,
949 &FGInitialCondition::GetVgroundKtsIC,
950 &FGInitialCondition::SetVgroundKtsIC,
952 PropertyManager->Tie("ic/vt-kts", this,
953 &FGInitialCondition::GetVtrueKtsIC,
954 &FGInitialCondition::SetVtrueKtsIC,
956 PropertyManager->Tie("ic/mach", this,
957 &FGInitialCondition::GetMachIC,
958 &FGInitialCondition::SetMachIC,
960 PropertyManager->Tie("ic/roc-fpm", this,
961 &FGInitialCondition::GetClimbRateFpmIC,
962 &FGInitialCondition::SetClimbRateFpmIC,
964 PropertyManager->Tie("ic/gamma-deg", this,
965 &FGInitialCondition::GetFlightPathAngleDegIC,
966 &FGInitialCondition::SetFlightPathAngleDegIC,
968 PropertyManager->Tie("ic/alpha-deg", this,
969 &FGInitialCondition::GetAlphaDegIC,
970 &FGInitialCondition::SetAlphaDegIC,
972 PropertyManager->Tie("ic/beta-deg", this,
973 &FGInitialCondition::GetBetaDegIC,
974 &FGInitialCondition::SetBetaDegIC,
976 PropertyManager->Tie("ic/theta-deg", this,
977 &FGInitialCondition::GetThetaDegIC,
978 &FGInitialCondition::SetThetaDegIC,
980 PropertyManager->Tie("ic/phi-deg", this,
981 &FGInitialCondition::GetPhiDegIC,
982 &FGInitialCondition::SetPhiDegIC,
984 PropertyManager->Tie("ic/psi-true-deg", this,
985 &FGInitialCondition::GetPsiDegIC );
986 PropertyManager->Tie("ic/lat-gc-deg", this,
987 &FGInitialCondition::GetLatitudeDegIC,
988 &FGInitialCondition::SetLatitudeDegIC,
990 PropertyManager->Tie("ic/long-gc-deg", this,
991 &FGInitialCondition::GetLongitudeDegIC,
992 &FGInitialCondition::SetLongitudeDegIC,
994 PropertyManager->Tie("ic/h-sl-ft", this,
995 &FGInitialCondition::GetAltitudeASLFtIC,
996 &FGInitialCondition::SetAltitudeASLFtIC,
998 PropertyManager->Tie("ic/h-agl-ft", this,
999 &FGInitialCondition::GetAltitudeAGLFtIC,
1000 &FGInitialCondition::SetAltitudeAGLFtIC,
1002 PropertyManager->Tie("ic/sea-level-radius-ft", this,
1003 &FGInitialCondition::GetSeaLevelRadiusFtIC,
1004 &FGInitialCondition::SetSeaLevelRadiusFtIC,
1006 PropertyManager->Tie("ic/terrain-elevation-ft", this,
1007 &FGInitialCondition::GetTerrainElevationFtIC,
1008 &FGInitialCondition::SetTerrainElevationFtIC,
1010 PropertyManager->Tie("ic/vg-fps", this,
1011 &FGInitialCondition::GetVgroundFpsIC,
1012 &FGInitialCondition::SetVgroundFpsIC,
1014 PropertyManager->Tie("ic/vt-fps", this,
1015 &FGInitialCondition::GetVtrueFpsIC,
1016 &FGInitialCondition::SetVtrueFpsIC,
1018 PropertyManager->Tie("ic/vw-bx-fps", this,
1019 &FGInitialCondition::GetWindUFpsIC);
1020 PropertyManager->Tie("ic/vw-by-fps", this,
1021 &FGInitialCondition::GetWindVFpsIC);
1022 PropertyManager->Tie("ic/vw-bz-fps", this,
1023 &FGInitialCondition::GetWindWFpsIC);
1024 PropertyManager->Tie("ic/vw-north-fps", this,
1025 &FGInitialCondition::GetWindNFpsIC);
1026 PropertyManager->Tie("ic/vw-east-fps", this,
1027 &FGInitialCondition::GetWindEFpsIC);
1028 PropertyManager->Tie("ic/vw-down-fps", this,
1029 &FGInitialCondition::GetWindDFpsIC);
1030 PropertyManager->Tie("ic/vw-mag-fps", this,
1031 &FGInitialCondition::GetWindFpsIC);
1032 PropertyManager->Tie("ic/vw-dir-deg", this,
1033 &FGInitialCondition::GetWindDirDegIC,
1034 &FGInitialCondition::SetWindDirDegIC,
1037 PropertyManager->Tie("ic/roc-fps", this,
1038 &FGInitialCondition::GetClimbRateFpsIC,
1039 &FGInitialCondition::SetClimbRateFpsIC,
1041 PropertyManager->Tie("ic/u-fps", this,
1042 &FGInitialCondition::GetUBodyFpsIC,
1043 &FGInitialCondition::SetUBodyFpsIC,
1045 PropertyManager->Tie("ic/v-fps", this,
1046 &FGInitialCondition::GetVBodyFpsIC,
1047 &FGInitialCondition::SetVBodyFpsIC,
1049 PropertyManager->Tie("ic/w-fps", this,
1050 &FGInitialCondition::GetWBodyFpsIC,
1051 &FGInitialCondition::SetWBodyFpsIC,
1053 PropertyManager->Tie("ic/vn-fps", this,
1054 &FGInitialCondition::GetVNorthFpsIC,
1055 &FGInitialCondition::SetVNorthFpsIC,
1057 PropertyManager->Tie("ic/ve-fps", this,
1058 &FGInitialCondition::GetVEastFpsIC,
1059 &FGInitialCondition::SetVEastFpsIC,
1061 PropertyManager->Tie("ic/vd-fps", this,
1062 &FGInitialCondition::GetVDownFpsIC,
1063 &FGInitialCondition::SetVDownFpsIC,
1065 PropertyManager->Tie("ic/gamma-rad", this,
1066 &FGInitialCondition::GetFlightPathAngleRadIC,
1067 &FGInitialCondition::SetFlightPathAngleRadIC,
1069 PropertyManager->Tie("ic/alpha-rad", this,
1070 &FGInitialCondition::GetAlphaRadIC,
1071 &FGInitialCondition::SetAlphaRadIC,
1073 PropertyManager->Tie("ic/theta-rad", this,
1074 &FGInitialCondition::GetThetaRadIC,
1075 &FGInitialCondition::SetThetaRadIC,
1077 PropertyManager->Tie("ic/beta-rad", this,
1078 &FGInitialCondition::GetBetaRadIC,
1079 &FGInitialCondition::SetBetaRadIC,
1081 PropertyManager->Tie("ic/phi-rad", this,
1082 &FGInitialCondition::GetPhiRadIC,
1083 &FGInitialCondition::SetPhiRadIC,
1085 PropertyManager->Tie("ic/psi-true-rad", this,
1086 &FGInitialCondition::GetPsiRadIC);
1087 PropertyManager->Tie("ic/lat-gc-rad", this,
1088 &FGInitialCondition::GetLatitudeRadIC,
1089 &FGInitialCondition::SetLatitudeRadIC,
1091 PropertyManager->Tie("ic/long-gc-rad", this,
1092 &FGInitialCondition::GetLongitudeRadIC,
1093 &FGInitialCondition::SetLongitudeRadIC,
1095 PropertyManager->Tie("ic/p-rad_sec", this,
1096 &FGInitialCondition::GetPRadpsIC,
1097 &FGInitialCondition::SetPRadpsIC,
1099 PropertyManager->Tie("ic/q-rad_sec", this,
1100 &FGInitialCondition::GetQRadpsIC,
1101 &FGInitialCondition::SetQRadpsIC,
1103 PropertyManager->Tie("ic/r-rad_sec", this,
1104 &FGInitialCondition::GetRRadpsIC,
1105 &FGInitialCondition::SetRRadpsIC,
1108 typedef int (FGInitialCondition::*iPMF)(void) const;
1109 PropertyManager->Tie("simulation/write-state-file",
1112 &FGInitialCondition::WriteStateFile);
1116 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 // The bitmasked value choices are as follows:
1118 // unset: In this case (the default) JSBSim would only print
1119 // out the normally expected messages, essentially echoing
1120 // the config files as they are read. If the environment
1121 // variable is not set, debug_lvl is set to 1 internally
1122 // 0: This requests JSBSim not to output any messages
1124 // 1: This value explicity requests the normal JSBSim
1126 // 2: This value asks for a message to be printed out when
1127 // a class is instantiated
1128 // 4: When this value is set, a message is displayed when a
1129 // FGModel object executes its Run() method
1130 // 8: When this value is set, various runtime state variables
1131 // are printed out periodically
1132 // 16: When set various parameters are sanity checked and
1133 // a message is printed out when they go out of bounds
1135 void FGInitialCondition::Debug(int from)
1137 if (debug_lvl <= 0) return;
1139 if (debug_lvl & 1) { // Standard console startup message output
1141 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1142 if (from == 0) cout << "Instantiated: FGInitialCondition" << endl;
1143 if (from == 1) cout << "Destroyed: FGInitialCondition" << endl;
1145 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1147 if (debug_lvl & 8 ) { // Runtime state variables
1149 if (debug_lvl & 16) { // Sanity checking
1151 if (debug_lvl & 64) {
1152 if (from == 0) { // Constructor
1153 cout << IdSrc << endl;
1154 cout << IdHdr << endl;