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 *******************************************************************************/
46 # include <simgear/compiler.h>
47 # ifdef SG_HAVE_STD_INCLUDES
53 # if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
60 #include "FGInitialCondition.h"
61 #include <FGFDMExec.h>
62 #include <models/FGInertial.h>
63 #include <models/FGAtmosphere.h>
64 #include <models/FGAerodynamics.h>
65 #include <models/FGPropagate.h>
66 #include <input_output/FGPropertyManager.h>
67 #include <models/FGPropulsion.h>
68 #include <input_output/FGXMLParse.h>
70 #include <math/FGQuaternion.h>
74 static const char *IdSrc = "$Id$";
75 static const char *IdHdr = ID_INITIALCONDITION;
77 //******************************************************************************
79 FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) : fdmex(FDMExec)
83 if(FDMExec != NULL ) {
84 fdmex->GetPropagate()->Seth(altitude);
85 fdmex->GetAtmosphere()->Run();
86 PropertyManager=fdmex->GetPropertyManager();
89 cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
95 //******************************************************************************
97 FGInitialCondition::~FGInitialCondition()
102 //******************************************************************************
104 void FGInitialCondition::ResetIC(double u0, double v0, double w0,
105 double p0, double q0, double r0,
106 double alpha0, double beta0,
107 double phi0, double theta0, double psi0,
108 double latRad0, double lonRad0, double altAGLFt0,
113 u = u0; v = v0; w = w0;
114 p = p0; q = q0; r = r0;
115 alpha = alpha0; beta = beta0;
116 phi = phi0; theta = theta0; psi = psi0;
121 SetAltitudeAGLFtIC(altAGLFt0);
123 cphi = cos(phi); sphi = sin(phi); // phi, rad
124 ctheta = cos(theta); stheta = sin(theta); // theta, rad
125 cpsi = cos(psi); spsi = sin(psi); // psi, rad
127 FGQuaternion Quat( phi, theta, psi );
130 const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame
131 const FGMatrix33& _Tb2l = Quat.GetTInv(); // body to local
133 FGColumnVector3 _vUVW_BODY(u,v,w);
134 FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY;
135 FGColumnVector3 _vWIND_NED(wnorth,weast,wdown);
136 FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED );
138 uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3);
142 //******************************************************************************
144 void FGInitialCondition::InitializeIC(void)
151 latitude=longitude=0;
155 vnorth=veast=vdown=0;
156 wnorth=weast=wdown=0;
161 radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius();
162 terrain_altitude = 0;
166 salpha=sbeta=stheta=sphi=spsi=sgamma=0;
167 calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
170 //******************************************************************************
172 void FGInitialCondition::WriteStateFile(int num)
174 string filename = fdmex->GetFullAircraftPath() + "/" + "initfile.xml";
175 ofstream outfile(filename.c_str());
176 FGPropagate* Propagate = fdmex->GetPropagate();
178 if (outfile.is_open()) {
179 outfile << "<?xml version=\"1.0\"?>" << endl;
180 outfile << "<initialize name=\"reset00\">" << endl;
181 outfile << " <ubody unit=\"FT/SEC\"> " << Propagate->GetUVW(eX) << " </ubody> " << endl;
182 outfile << " <vbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eY) << " </vbody> " << endl;
183 outfile << " <wbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eZ) << " </wbody> " << endl;
184 outfile << " <phi unit=\"DEG\"> " << Propagate->GetEuler(ePhi) << " </phi>" << endl;
185 outfile << " <theta unit=\"DEG\"> " << Propagate->GetEuler(eTht) << " </theta>" << endl;
186 outfile << " <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl;
187 outfile << " <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl;
188 outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
189 outfile << " <altitude unit=\"FT\"> " << Propagate->Geth() << " </altitude>" << endl;
190 outfile << "</initialize>" << endl;
192 cerr << "Could not open and/or write the state to the initial conditions file." << endl;
198 //******************************************************************************
200 void FGInitialCondition::SetVcalibratedKtsIC(double tt) {
202 if(getMachFromVcas(&mach,tt*ktstofps)) {
203 //cout << "Mach: " << mach << endl;
206 vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
207 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
208 //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
211 cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl;
212 cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl;
216 //******************************************************************************
218 void FGInitialCondition::SetVequivalentKtsIC(double tt) {
221 vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
222 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
226 //******************************************************************************
228 void FGInitialCondition::SetVgroundFpsIC(double tt) {
234 vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0;
236 ua = u + uw; va = v + vw; wa = w + ww;
237 vt = sqrt( ua*ua + va*va + wa*wa );
239 vxz = sqrt( u*u + w*w );
240 if( w != 0 ) alpha = atan2( w, u );
241 if( vxz != 0 ) beta = atan2( v, vxz );
242 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
244 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
247 //******************************************************************************
249 void FGInitialCondition::SetVtrueFpsIC(double tt) {
252 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
254 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
257 //******************************************************************************
259 void FGInitialCondition::SetMachIC(double tt) {
261 lastSpeedSet=setmach;
262 vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
264 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
265 //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
268 //******************************************************************************
270 void FGInitialCondition::SetClimbRateFpmIC(double tt) {
271 SetClimbRateFpsIC(tt/60.0);
274 //******************************************************************************
276 void FGInitialCondition::SetClimbRateFpsIC(double tt) {
281 sgamma=sin(gamma); cgamma=cos(gamma);
285 //******************************************************************************
287 void FGInitialCondition::SetFlightPathAngleRadIC(double tt) {
289 sgamma=sin(gamma); cgamma=cos(gamma);
294 //******************************************************************************
296 void FGInitialCondition::SetAlphaRadIC(double tt) {
298 salpha=sin(alpha); calpha=cos(alpha);
302 //******************************************************************************
304 void FGInitialCondition::SetThetaRadIC(double tt) {
306 stheta=sin(theta); ctheta=cos(theta);
310 //******************************************************************************
312 void FGInitialCondition::SetBetaRadIC(double tt) {
314 sbeta=sin(beta); cbeta=cos(beta);
319 //******************************************************************************
321 void FGInitialCondition::SetPhiRadIC(double tt) {
323 sphi=sin(phi); cphi=cos(phi);
327 //******************************************************************************
329 void FGInitialCondition::SetPsiRadIC(double tt) {
331 spsi=sin(psi); cpsi=cos(psi);
335 //******************************************************************************
337 void FGInitialCondition::SetUBodyFpsIC(double tt) {
339 vt=sqrt(u*u + v*v + w*w);
343 //******************************************************************************
345 void FGInitialCondition::SetVBodyFpsIC(double tt) {
347 vt=sqrt(u*u + v*v + w*w);
351 //******************************************************************************
353 void FGInitialCondition::SetWBodyFpsIC(double tt) {
355 vt=sqrt( u*u + v*v + w*w );
360 //******************************************************************************
362 void FGInitialCondition::SetVNorthFpsIC(double tt) {
367 ua = u + uw; va = v + vw; wa = w + ww;
368 vt = sqrt( ua*ua + va*va + wa*wa );
370 vxz = sqrt( u*u + w*w );
371 if( w != 0 ) alpha = atan2( w, u );
372 if( vxz != 0 ) beta = atan2( v, vxz );
373 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
375 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
379 //******************************************************************************
381 void FGInitialCondition::SetVEastFpsIC(double tt) {
386 ua = u + uw; va = v + vw; wa = w + ww;
387 vt = sqrt( ua*ua + va*va + wa*wa );
389 vxz = sqrt( u*u + w*w );
390 if( w != 0 ) alpha = atan2( w, u );
391 if( vxz != 0 ) beta = atan2( v, vxz );
392 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
394 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
398 //******************************************************************************
400 void FGInitialCondition::SetVDownFpsIC(double tt) {
405 ua = u + uw; va = v + vw; wa = w + ww;
406 vt = sqrt( ua*ua + va*va + wa*wa );
408 vxz = sqrt( u*u + w*w );
409 if( w != 0 ) alpha = atan2( w, u );
410 if( vxz != 0 ) beta = atan2( v, vxz );
411 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
413 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
414 SetClimbRateFpsIC(-1*vdown);
418 //******************************************************************************
420 double FGInitialCondition::GetUBodyFpsIC(void) const {
421 if (lastSpeedSet == setvg || lastSpeedSet == setned)
424 return vt*calpha*cbeta - uw;
427 //******************************************************************************
429 double FGInitialCondition::GetVBodyFpsIC(void) const {
430 if (lastSpeedSet == setvg || lastSpeedSet == setned)
433 return vt*sbeta - vw;
437 //******************************************************************************
439 double FGInitialCondition::GetWBodyFpsIC(void) const {
440 if (lastSpeedSet == setvg || lastSpeedSet == setned)
443 return vt*salpha*cbeta -ww;
446 //******************************************************************************
448 void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) {
449 wnorth = wN; weast = wE; wdown = wD;
450 lastWindSet = setwned;
452 if(lastSpeedSet == setvg)
456 //******************************************************************************
458 void FGInitialCondition::SetCrossWindKtsIC(double cross){
459 wcross=cross*ktstofps;
462 if(lastSpeedSet == setvg)
467 //******************************************************************************
469 // positive from left
470 void FGInitialCondition::SetHeadWindKtsIC(double head){
474 if(lastSpeedSet == setvg)
479 //******************************************************************************
481 void FGInitialCondition::SetWindDownKtsIC(double wD) {
484 if(lastSpeedSet == setvg)
488 //******************************************************************************
490 void FGInitialCondition::SetWindMagKtsIC(double mag) {
494 if(lastSpeedSet == setvg)
498 //******************************************************************************
500 void FGInitialCondition::SetWindDirDegIC(double dir) {
504 if(lastSpeedSet == setvg)
509 //******************************************************************************
511 void FGInitialCondition::calcWindUVW(void) {
513 switch(lastWindSet) {
515 wnorth=wmag*cos(wdir);
516 weast=wmag*sin(wdir);
519 wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2);
520 weast=whead*sin(psi) + wcross*sin(psi+M_PI/2);
525 uw=wnorth*ctheta*cpsi +
528 vw=wnorth*( sphi*stheta*cpsi - cphi*spsi ) +
529 weast*( sphi*stheta*spsi + cphi*cpsi ) +
531 ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) +
532 weast*(cphi*stheta*spsi - sphi*cpsi) +
536 /* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown "
537 << wnorth << ", " << weast << ", " << wdown << endl;
538 cout << "FGInitialCondition::calcWindUVW: theta, phi, psi "
539 << theta << ", " << phi << ", " << psi << endl;
540 cout << "FGInitialCondition::calcWindUVW: uw, vw, ww "
541 << uw << ", " << vw << ", " << ww << endl; */
545 //******************************************************************************
547 void FGInitialCondition::SetAltitudeFtIC(double tt) {
549 fdmex->GetPropagate()->Seth(altitude);
550 fdmex->GetAtmosphere()->Run();
551 //lets try to make sure the user gets what they intended
553 switch(lastSpeedSet) {
557 SetVtrueKtsIC(vt*fpstokts);
560 SetVcalibratedKtsIC(vc*fpstokts);
563 SetVequivalentKtsIC(ve*fpstokts);
574 //******************************************************************************
576 void FGInitialCondition::SetAltitudeAGLFtIC(double tt) {
577 SetAltitudeFtIC(terrain_altitude + tt);
580 //******************************************************************************
582 void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) {
583 sea_level_radius = tt;
586 //******************************************************************************
588 void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
592 //******************************************************************************
594 void FGInitialCondition::calcUVWfromNED(void) {
595 u=vnorth*ctheta*cpsi +
598 v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) +
599 veast*( sphi*stheta*spsi + cphi*cpsi ) +
601 w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) +
602 veast*( cphi*stheta*spsi - sphi*cpsi ) +
606 //******************************************************************************
608 bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) {
614 sfunc=&FGInitialCondition::calcVcas;
615 if(findInterval(vcas,guess)) {
616 if(solve(&mach,vcas))
622 //******************************************************************************
624 bool FGInitialCondition::getAlpha(void) {
626 double guess=theta-gamma;
628 if(vt < 0.01) return 0;
631 xmin=fdmex->GetAerodynamics()->GetAlphaCLMin();
632 xmax=fdmex->GetAerodynamics()->GetAlphaCLMax();
633 sfunc=&FGInitialCondition::GammaEqOfAlpha;
634 if(findInterval(0,guess)){
645 //******************************************************************************
647 bool FGInitialCondition::getTheta(void) {
649 double guess=alpha+gamma;
651 if(vt < 0.01) return 0;
655 sfunc=&FGInitialCondition::GammaEqOfTheta;
656 if(findInterval(0,guess)){
667 //******************************************************************************
669 double FGInitialCondition::GammaEqOfTheta(double Theta) {
671 double sTheta,cTheta;
673 //theta=Theta; stheta=sin(theta); ctheta=cos(theta);
674 sTheta=sin(Theta); cTheta=cos(Theta);
676 a=wdown + vt*calpha*cbeta + uw;
677 b=vt*sphi*sbeta + vw*sphi;
678 c=vt*cphi*salpha*cbeta + ww*cphi;
679 return vt*sgamma - ( a*sTheta - (b+c)*cTheta);
682 //******************************************************************************
684 double FGInitialCondition::GammaEqOfAlpha(double Alpha) {
686 double sAlpha,cAlpha;
687 sAlpha=sin(Alpha); cAlpha=cos(Alpha);
688 a=wdown + vt*cAlpha*cbeta + uw;
689 b=vt*sphi*sbeta + vw*sphi;
690 c=vt*cphi*sAlpha*cbeta + ww*cphi;
692 return vt*sgamma - ( a*stheta - (b+c)*ctheta );
695 //******************************************************************************
697 double FGInitialCondition::calcVcas(double Mach) {
699 double p=fdmex->GetAtmosphere()->GetPressure();
700 double psl=fdmex->GetAtmosphere()->GetPressureSL();
701 double rhosl=fdmex->GetAtmosphere()->GetDensitySL();
702 double pt,A,B,D,vcas;
704 if(Mach < 1) //calculate total pressure assuming isentropic flow
705 pt=p*pow((1 + 0.2*Mach*Mach),3.5);
707 // shock in front of pitot tube, we'll assume its normal and use
708 // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
709 // pressure behind the shock to the static pressure in front
712 //the normal shock assumption should not be a bad one -- most supersonic
713 //aircraft place the pitot probe out front so that it is the forward
714 //most point on the aircraft. The real shock would, of course, take
715 //on something like the shape of a rounded-off cone but, here again,
716 //the assumption should be good since the opening of the pitot probe
717 //is very small and, therefore, the effects of the shock curvature
718 //should be small as well. AFAIK, this approach is fairly well accepted
719 //within the aerospace community
721 B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);
723 // The denominator above is zero for Mach ~ 0.38, for which
724 // we'll never be here, so we're safe
726 D = (2.8*Mach*Mach-0.4)*0.4167;
730 A = pow(((pt-p)/psl+1),0.28571);
731 vcas = sqrt(7*psl/rhosl*(A-1));
732 //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl;
736 //******************************************************************************
738 bool FGInitialCondition::findInterval(double x,double guess) {
739 //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){
743 double flo,fhi,fguess;
746 fguess=(this->*sfunc)(guess)-x;
752 if(lo < xmin) lo=xmin;
753 if(hi > xmax) hi=xmax;
755 flo=(this->*sfunc)(lo)-x;
756 fhi=(this->*sfunc)(hi)-x;
757 if(flo*fhi <=0) { //found interval with root
759 if(flo*fguess <= 0) { //narrow interval down a bit
760 hi=lo+step; //to pass solver interval that is as
763 else if(fhi*fguess <= 0) {
767 //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl;
769 while((found == 0) && (i <= 100));
775 //******************************************************************************
777 bool FGInitialCondition::solve(double *y,double x)
779 double x1,x2,x3,f1,f2,f3,d,d0;
781 double const relax =0.9;
789 f1=(this->*sfunc)(x1)-x;
790 f3=(this->*sfunc)(x3)-x;
795 while ((fabs(d) > eps) && (i < 100)) {
797 x2 = x1-d*d0*f1/(f3-f1);
799 f2=(this->*sfunc)(x2)-x;
800 //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
801 //cout << " " << f1 << "," << f2 << "," << f3 << endl;
803 if(fabs(f2) <= 0.001) {
805 } else if(f1*f2 <= 0.0) {
809 } else if(f2*f3 <= 0) {
822 //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl;
826 //******************************************************************************
828 double FGInitialCondition::GetWindDirDegIC(void) const {
830 return atan2(weast,wnorth)*radtodeg;
837 //******************************************************************************
839 bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
848 if( useStoredPath ) {
849 init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml";
851 init_file_name = rstfile;
854 document = LoadXMLDocument(init_file_name);
856 // Make sure that the document is valid
858 cerr << "File: " << init_file_name << " could not be read." << endl;
862 if (document->GetName() != string("initialize")) {
863 cerr << "File: " << init_file_name << " is not a reset file." << endl;
867 if (document->FindElement("latitude"))
868 SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
869 if (document->FindElement("longitude"))
870 SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
871 if (document->FindElement("altitude"))
872 SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
873 if (document->FindElement("ubody"))
874 SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
875 if (document->FindElement("vbody"))
876 SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC"));
877 if (document->FindElement("wbody"))
878 SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC"));
879 if (document->FindElement("vnorth"))
880 SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC"));
881 if (document->FindElement("veast"))
882 SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC"));
883 if (document->FindElement("vdown"))
884 SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC"));
885 if (document->FindElement("winddir"))
886 SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
887 if (document->FindElement("vwind"))
888 SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS"));
889 if (document->FindElement("hwind"))
890 SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
891 if (document->FindElement("xwind"))
892 SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
893 if (document->FindElement("vc"))
894 SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS"));
895 if (document->FindElement("vt"))
896 SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS"));
897 if (document->FindElement("mach"))
898 SetMachIC(document->FindElementValueAsNumber("mach"));
899 if (document->FindElement("phi"))
900 SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG"));
901 if (document->FindElement("theta"))
902 SetThetaDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG"));
903 if (document->FindElement("psi"))
904 SetPsiDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG"));
905 if (document->FindElement("alpha"))
906 SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG"));
907 if (document->FindElement("beta"))
908 SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG"));
909 if (document->FindElement("gamma"))
910 SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG"));
911 if (document->FindElement("roc"))
912 SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
913 if (document->FindElement("vground"))
914 SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS"));
915 if (document->FindElement("targetNlf"))
917 SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
920 // Check to see if any engines are specified to be initialized in a running state
921 FGPropulsion* propulsion = fdmex->GetPropulsion();
922 Element* running_elements = document->FindElement("running");
923 while (running_elements) {
924 n = int(running_elements->GetDataAsNumber());
925 propulsion->InitRunning(n);
926 running_elements = document->FindNextElement("running");
934 //******************************************************************************
936 void FGInitialCondition::bind(void){
937 PropertyManager->Tie("ic/vc-kts", this,
938 &FGInitialCondition::GetVcalibratedKtsIC,
939 &FGInitialCondition::SetVcalibratedKtsIC,
941 PropertyManager->Tie("ic/ve-kts", this,
942 &FGInitialCondition::GetVequivalentKtsIC,
943 &FGInitialCondition::SetVequivalentKtsIC,
945 PropertyManager->Tie("ic/vg-kts", this,
946 &FGInitialCondition::GetVgroundKtsIC,
947 &FGInitialCondition::SetVgroundKtsIC,
949 PropertyManager->Tie("ic/vt-kts", this,
950 &FGInitialCondition::GetVtrueKtsIC,
951 &FGInitialCondition::SetVtrueKtsIC,
953 PropertyManager->Tie("ic/mach", this,
954 &FGInitialCondition::GetMachIC,
955 &FGInitialCondition::SetMachIC,
957 PropertyManager->Tie("ic/roc-fpm", this,
958 &FGInitialCondition::GetClimbRateFpmIC,
959 &FGInitialCondition::SetClimbRateFpmIC,
961 PropertyManager->Tie("ic/gamma-deg", this,
962 &FGInitialCondition::GetFlightPathAngleDegIC,
963 &FGInitialCondition::SetFlightPathAngleDegIC,
965 PropertyManager->Tie("ic/alpha-deg", this,
966 &FGInitialCondition::GetAlphaDegIC,
967 &FGInitialCondition::SetAlphaDegIC,
969 PropertyManager->Tie("ic/beta-deg", this,
970 &FGInitialCondition::GetBetaDegIC,
971 &FGInitialCondition::SetBetaDegIC,
973 PropertyManager->Tie("ic/theta-deg", this,
974 &FGInitialCondition::GetThetaDegIC,
975 &FGInitialCondition::SetThetaDegIC,
977 PropertyManager->Tie("ic/phi-deg", this,
978 &FGInitialCondition::GetPhiDegIC,
979 &FGInitialCondition::SetPhiDegIC,
981 PropertyManager->Tie("ic/psi-true-deg", this,
982 &FGInitialCondition::GetPsiDegIC );
983 PropertyManager->Tie("ic/lat-gc-deg", this,
984 &FGInitialCondition::GetLatitudeDegIC,
985 &FGInitialCondition::SetLatitudeDegIC,
987 PropertyManager->Tie("ic/long-gc-deg", this,
988 &FGInitialCondition::GetLongitudeDegIC,
989 &FGInitialCondition::SetLongitudeDegIC,
991 PropertyManager->Tie("ic/h-sl-ft", this,
992 &FGInitialCondition::GetAltitudeFtIC,
993 &FGInitialCondition::SetAltitudeFtIC,
995 PropertyManager->Tie("ic/h-agl-ft", this,
996 &FGInitialCondition::GetAltitudeAGLFtIC,
997 &FGInitialCondition::SetAltitudeAGLFtIC,
999 PropertyManager->Tie("ic/sea-level-radius-ft", this,
1000 &FGInitialCondition::GetSeaLevelRadiusFtIC,
1001 &FGInitialCondition::SetSeaLevelRadiusFtIC,
1003 PropertyManager->Tie("ic/terrain-altitude-ft", this,
1004 &FGInitialCondition::GetTerrainAltitudeFtIC,
1005 &FGInitialCondition::SetTerrainAltitudeFtIC,
1007 PropertyManager->Tie("ic/vg-fps", this,
1008 &FGInitialCondition::GetVgroundFpsIC,
1009 &FGInitialCondition::SetVgroundFpsIC,
1011 PropertyManager->Tie("ic/vt-fps", this,
1012 &FGInitialCondition::GetVtrueFpsIC,
1013 &FGInitialCondition::SetVtrueFpsIC,
1015 PropertyManager->Tie("ic/vw-bx-fps", this,
1016 &FGInitialCondition::GetWindUFpsIC);
1017 PropertyManager->Tie("ic/vw-by-fps", this,
1018 &FGInitialCondition::GetWindVFpsIC);
1019 PropertyManager->Tie("ic/vw-bz-fps", this,
1020 &FGInitialCondition::GetWindWFpsIC);
1021 PropertyManager->Tie("ic/vw-north-fps", this,
1022 &FGInitialCondition::GetWindNFpsIC);
1023 PropertyManager->Tie("ic/vw-east-fps", this,
1024 &FGInitialCondition::GetWindEFpsIC);
1025 PropertyManager->Tie("ic/vw-down-fps", this,
1026 &FGInitialCondition::GetWindDFpsIC);
1027 PropertyManager->Tie("ic/vw-mag-fps", this,
1028 &FGInitialCondition::GetWindFpsIC);
1029 PropertyManager->Tie("ic/vw-dir-deg", this,
1030 &FGInitialCondition::GetWindDirDegIC,
1031 &FGInitialCondition::SetWindDirDegIC,
1034 PropertyManager->Tie("ic/roc-fps", this,
1035 &FGInitialCondition::GetClimbRateFpsIC,
1036 &FGInitialCondition::SetClimbRateFpsIC,
1038 PropertyManager->Tie("ic/u-fps", this,
1039 &FGInitialCondition::GetUBodyFpsIC,
1040 &FGInitialCondition::SetUBodyFpsIC,
1042 PropertyManager->Tie("ic/v-fps", this,
1043 &FGInitialCondition::GetVBodyFpsIC,
1044 &FGInitialCondition::SetVBodyFpsIC,
1046 PropertyManager->Tie("ic/w-fps", this,
1047 &FGInitialCondition::GetWBodyFpsIC,
1048 &FGInitialCondition::SetWBodyFpsIC,
1050 PropertyManager->Tie("ic/vn-fps", this,
1051 &FGInitialCondition::GetVNorthFpsIC,
1052 &FGInitialCondition::SetVNorthFpsIC,
1054 PropertyManager->Tie("ic/ve-fps", this,
1055 &FGInitialCondition::GetVEastFpsIC,
1056 &FGInitialCondition::SetVEastFpsIC,
1058 PropertyManager->Tie("ic/vd-fps", this,
1059 &FGInitialCondition::GetVDownFpsIC,
1060 &FGInitialCondition::SetVDownFpsIC,
1062 PropertyManager->Tie("ic/gamma-rad", this,
1063 &FGInitialCondition::GetFlightPathAngleRadIC,
1064 &FGInitialCondition::SetFlightPathAngleRadIC,
1066 PropertyManager->Tie("ic/alpha-rad", this,
1067 &FGInitialCondition::GetAlphaRadIC,
1068 &FGInitialCondition::SetAlphaRadIC,
1070 PropertyManager->Tie("ic/theta-rad", this,
1071 &FGInitialCondition::GetThetaRadIC,
1072 &FGInitialCondition::SetThetaRadIC,
1074 PropertyManager->Tie("ic/beta-rad", this,
1075 &FGInitialCondition::GetBetaRadIC,
1076 &FGInitialCondition::SetBetaRadIC,
1078 PropertyManager->Tie("ic/phi-rad", this,
1079 &FGInitialCondition::GetPhiRadIC,
1080 &FGInitialCondition::SetPhiRadIC,
1082 PropertyManager->Tie("ic/psi-true-rad", this,
1083 &FGInitialCondition::GetPsiRadIC);
1084 PropertyManager->Tie("ic/lat-gc-rad", this,
1085 &FGInitialCondition::GetLatitudeRadIC,
1086 &FGInitialCondition::SetLatitudeRadIC,
1088 PropertyManager->Tie("ic/long-gc-rad", this,
1089 &FGInitialCondition::GetLongitudeRadIC,
1090 &FGInitialCondition::SetLongitudeRadIC,
1092 PropertyManager->Tie("ic/p-rad_sec", this,
1093 &FGInitialCondition::GetPRadpsIC,
1094 &FGInitialCondition::SetPRadpsIC,
1096 PropertyManager->Tie("ic/q-rad_sec", this,
1097 &FGInitialCondition::GetQRadpsIC,
1098 &FGInitialCondition::SetQRadpsIC,
1100 PropertyManager->Tie("ic/r-rad_sec", this,
1101 &FGInitialCondition::GetRRadpsIC,
1102 &FGInitialCondition::SetRRadpsIC,
1105 typedef int (FGInitialCondition::*iPMF)(void) const;
1106 PropertyManager->Tie("simulation/write-state-file",
1109 &FGInitialCondition::WriteStateFile);
1113 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 // The bitmasked value choices are as follows:
1115 // unset: In this case (the default) JSBSim would only print
1116 // out the normally expected messages, essentially echoing
1117 // the config files as they are read. If the environment
1118 // variable is not set, debug_lvl is set to 1 internally
1119 // 0: This requests JSBSim not to output any messages
1121 // 1: This value explicity requests the normal JSBSim
1123 // 2: This value asks for a message to be printed out when
1124 // a class is instantiated
1125 // 4: When this value is set, a message is displayed when a
1126 // FGModel object executes its Run() method
1127 // 8: When this value is set, various runtime state variables
1128 // are printed out periodically
1129 // 16: When set various parameters are sanity checked and
1130 // a message is printed out when they go out of bounds
1132 void FGInitialCondition::Debug(int from)
1134 if (debug_lvl <= 0) return;
1136 if (debug_lvl & 1) { // Standard console startup message output
1138 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1139 if (from == 0) cout << "Instantiated: FGInitialCondition" << endl;
1140 if (from == 1) cout << "Destroyed: FGInitialCondition" << endl;
1142 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1144 if (debug_lvl & 8 ) { // Runtime state variables
1146 if (debug_lvl & 16) { // Sanity checking
1148 if (debug_lvl & 64) {
1149 if (from == 0) { // Constructor
1150 cout << IdSrc << endl;
1151 cout << IdHdr << endl;