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()->Seth(altitude);
70 fdmex->GetAtmosphere()->Run();
71 PropertyManager=fdmex->GetPropertyManager();
74 cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
80 //******************************************************************************
82 FGInitialCondition::~FGInitialCondition()
87 //******************************************************************************
89 void FGInitialCondition::ResetIC(double u0, double v0, double w0,
90 double p0, double q0, double r0,
91 double alpha0, double beta0,
92 double phi0, double theta0, double psi0,
93 double latRad0, double lonRad0, double altAGLFt0,
98 u = u0; v = v0; w = w0;
99 p = p0; q = q0; r = r0;
100 alpha = alpha0; beta = beta0;
101 phi = phi0; theta = theta0; psi = psi0;
106 SetAltitudeAGLFtIC(altAGLFt0);
108 cphi = cos(phi); sphi = sin(phi); // phi, rad
109 ctheta = cos(theta); stheta = sin(theta); // theta, rad
110 cpsi = cos(psi); spsi = sin(psi); // psi, rad
112 FGQuaternion Quat( phi, theta, psi );
115 const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame
116 const FGMatrix33& _Tb2l = Quat.GetTInv(); // body to local
118 FGColumnVector3 _vUVW_BODY(u,v,w);
119 FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY;
120 FGColumnVector3 _vWIND_NED(wnorth,weast,wdown);
121 FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED );
123 uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3);
127 //******************************************************************************
129 void FGInitialCondition::InitializeIC(void)
136 latitude=longitude=0;
140 vnorth=veast=vdown=0;
141 wnorth=weast=wdown=0;
146 radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius();
147 terrain_altitude = 0;
151 salpha=sbeta=stheta=sphi=spsi=sgamma=0;
152 calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
155 //******************************************************************************
157 void FGInitialCondition::WriteStateFile(int num)
159 string filename = fdmex->GetFullAircraftPath();
161 if (filename.empty())
162 filename = "initfile.xml";
164 filename.append("/initfile.xml");
166 ofstream outfile(filename.c_str());
167 FGPropagate* Propagate = fdmex->GetPropagate();
169 if (outfile.is_open()) {
170 outfile << "<?xml version=\"1.0\"?>" << endl;
171 outfile << "<initialize name=\"reset00\">" << endl;
172 outfile << " <ubody unit=\"FT/SEC\"> " << Propagate->GetUVW(eX) << " </ubody> " << endl;
173 outfile << " <vbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eY) << " </vbody> " << endl;
174 outfile << " <wbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eZ) << " </wbody> " << endl;
175 outfile << " <phi unit=\"DEG\"> " << Propagate->GetEuler(ePhi) << " </phi>" << endl;
176 outfile << " <theta unit=\"DEG\"> " << Propagate->GetEuler(eTht) << " </theta>" << endl;
177 outfile << " <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl;
178 outfile << " <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl;
179 outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
180 outfile << " <altitude unit=\"FT\"> " << Propagate->Geth() << " </altitude>" << endl;
181 outfile << "</initialize>" << endl;
184 cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl;
188 //******************************************************************************
190 void FGInitialCondition::SetVcalibratedKtsIC(double tt) {
192 if(getMachFromVcas(&mach,tt*ktstofps)) {
193 //cout << "Mach: " << mach << endl;
196 vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
197 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
198 //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
201 cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl;
202 cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl;
206 //******************************************************************************
208 void FGInitialCondition::SetVequivalentKtsIC(double tt) {
211 vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
212 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
216 //******************************************************************************
218 void FGInitialCondition::SetVgroundFpsIC(double tt) {
224 vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0;
226 ua = u + uw; va = v + vw; wa = w + ww;
227 vt = sqrt( ua*ua + va*va + wa*wa );
229 vxz = sqrt( u*u + w*w );
230 if( w != 0 ) alpha = atan2( w, u );
231 if( vxz != 0 ) beta = atan2( v, vxz );
232 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
234 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
237 //******************************************************************************
239 void FGInitialCondition::SetVtrueFpsIC(double tt) {
242 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
244 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
247 //******************************************************************************
249 void FGInitialCondition::SetMachIC(double tt) {
251 lastSpeedSet=setmach;
252 vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
254 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
255 //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
258 //******************************************************************************
260 void FGInitialCondition::SetClimbRateFpmIC(double tt) {
261 SetClimbRateFpsIC(tt/60.0);
264 //******************************************************************************
266 void FGInitialCondition::SetClimbRateFpsIC(double tt) {
271 sgamma=sin(gamma); cgamma=cos(gamma);
275 //******************************************************************************
277 void FGInitialCondition::SetFlightPathAngleRadIC(double tt) {
279 sgamma=sin(gamma); cgamma=cos(gamma);
284 //******************************************************************************
286 void FGInitialCondition::SetAlphaRadIC(double tt) {
288 salpha=sin(alpha); calpha=cos(alpha);
292 //******************************************************************************
294 void FGInitialCondition::SetThetaRadIC(double tt) {
296 stheta=sin(theta); ctheta=cos(theta);
300 //******************************************************************************
302 void FGInitialCondition::SetBetaRadIC(double tt) {
304 sbeta=sin(beta); cbeta=cos(beta);
309 //******************************************************************************
311 void FGInitialCondition::SetPhiRadIC(double tt) {
313 sphi=sin(phi); cphi=cos(phi);
317 //******************************************************************************
319 void FGInitialCondition::SetPsiRadIC(double tt) {
321 spsi=sin(psi); cpsi=cos(psi);
325 //******************************************************************************
327 void FGInitialCondition::SetUBodyFpsIC(double tt) {
329 vt=sqrt(u*u + v*v + w*w);
333 //******************************************************************************
335 void FGInitialCondition::SetVBodyFpsIC(double tt) {
337 vt=sqrt(u*u + v*v + w*w);
341 //******************************************************************************
343 void FGInitialCondition::SetWBodyFpsIC(double tt) {
345 vt=sqrt( u*u + v*v + w*w );
350 //******************************************************************************
352 void FGInitialCondition::SetVNorthFpsIC(double tt) {
357 ua = u + uw; va = v + vw; wa = w + ww;
358 vt = sqrt( ua*ua + va*va + wa*wa );
360 vxz = sqrt( u*u + w*w );
361 if( w != 0 ) alpha = atan2( w, u );
362 if( vxz != 0 ) beta = atan2( v, vxz );
363 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
365 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
369 //******************************************************************************
371 void FGInitialCondition::SetVEastFpsIC(double tt) {
376 ua = u + uw; va = v + vw; wa = w + ww;
377 vt = sqrt( ua*ua + va*va + wa*wa );
379 vxz = sqrt( u*u + w*w );
380 if( w != 0 ) alpha = atan2( w, u );
381 if( vxz != 0 ) beta = atan2( v, vxz );
382 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
384 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
388 //******************************************************************************
390 void FGInitialCondition::SetVDownFpsIC(double tt) {
395 ua = u + uw; va = v + vw; wa = w + ww;
396 vt = sqrt( ua*ua + va*va + wa*wa );
398 vxz = sqrt( u*u + w*w );
399 if( w != 0 ) alpha = atan2( w, u );
400 if( vxz != 0 ) beta = atan2( v, vxz );
401 mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
403 ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
404 SetClimbRateFpsIC(-1*vdown);
408 //******************************************************************************
410 double FGInitialCondition::GetUBodyFpsIC(void) const {
411 if (lastSpeedSet == setvg || lastSpeedSet == setned)
414 return vt*calpha*cbeta - uw;
417 //******************************************************************************
419 double FGInitialCondition::GetVBodyFpsIC(void) const {
420 if (lastSpeedSet == setvg || lastSpeedSet == setned)
423 return vt*sbeta - vw;
427 //******************************************************************************
429 double FGInitialCondition::GetWBodyFpsIC(void) const {
430 if (lastSpeedSet == setvg || lastSpeedSet == setned)
433 return vt*salpha*cbeta -ww;
436 //******************************************************************************
438 void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) {
439 wnorth = wN; weast = wE; wdown = wD;
440 lastWindSet = setwned;
442 if(lastSpeedSet == setvg)
446 //******************************************************************************
448 void FGInitialCondition::SetCrossWindKtsIC(double cross){
449 wcross=cross*ktstofps;
452 if(lastSpeedSet == setvg)
457 //******************************************************************************
459 // positive from left
460 void FGInitialCondition::SetHeadWindKtsIC(double head){
464 if(lastSpeedSet == setvg)
469 //******************************************************************************
471 void FGInitialCondition::SetWindDownKtsIC(double wD) {
474 if(lastSpeedSet == setvg)
478 //******************************************************************************
480 void FGInitialCondition::SetWindMagKtsIC(double mag) {
484 if(lastSpeedSet == setvg)
488 //******************************************************************************
490 void FGInitialCondition::SetWindDirDegIC(double dir) {
494 if(lastSpeedSet == setvg)
499 //******************************************************************************
501 void FGInitialCondition::calcWindUVW(void) {
503 switch(lastWindSet) {
505 wnorth=wmag*cos(wdir);
506 weast=wmag*sin(wdir);
509 wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2);
510 weast=whead*sin(psi) + wcross*sin(psi+M_PI/2);
515 uw=wnorth*ctheta*cpsi +
518 vw=wnorth*( sphi*stheta*cpsi - cphi*spsi ) +
519 weast*( sphi*stheta*spsi + cphi*cpsi ) +
521 ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) +
522 weast*(cphi*stheta*spsi - sphi*cpsi) +
526 /* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown "
527 << wnorth << ", " << weast << ", " << wdown << endl;
528 cout << "FGInitialCondition::calcWindUVW: theta, phi, psi "
529 << theta << ", " << phi << ", " << psi << endl;
530 cout << "FGInitialCondition::calcWindUVW: uw, vw, ww "
531 << uw << ", " << vw << ", " << ww << endl; */
535 //******************************************************************************
537 void FGInitialCondition::SetAltitudeFtIC(double tt) {
539 fdmex->GetPropagate()->Seth(altitude);
540 fdmex->GetAtmosphere()->Run();
541 //lets try to make sure the user gets what they intended
543 switch(lastSpeedSet) {
547 SetVtrueKtsIC(vt*fpstokts);
550 SetVcalibratedKtsIC(vc*fpstokts);
553 SetVequivalentKtsIC(ve*fpstokts);
564 //******************************************************************************
566 void FGInitialCondition::SetAltitudeAGLFtIC(double tt) {
567 SetAltitudeFtIC(terrain_altitude + tt);
570 //******************************************************************************
572 void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) {
573 sea_level_radius = tt;
576 //******************************************************************************
578 void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
582 //******************************************************************************
584 void FGInitialCondition::calcUVWfromNED(void) {
585 u=vnorth*ctheta*cpsi +
588 v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) +
589 veast*( sphi*stheta*spsi + cphi*cpsi ) +
591 w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) +
592 veast*( cphi*stheta*spsi - sphi*cpsi ) +
596 //******************************************************************************
598 bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) {
604 sfunc=&FGInitialCondition::calcVcas;
605 if(findInterval(vcas,guess)) {
606 if(solve(&mach,vcas))
612 //******************************************************************************
614 bool FGInitialCondition::getAlpha(void) {
616 double guess=theta-gamma;
618 if(vt < 0.01) return 0;
621 xmin=fdmex->GetAerodynamics()->GetAlphaCLMin();
622 xmax=fdmex->GetAerodynamics()->GetAlphaCLMax();
623 sfunc=&FGInitialCondition::GammaEqOfAlpha;
624 if(findInterval(0,guess)){
635 //******************************************************************************
637 bool FGInitialCondition::getTheta(void) {
639 double guess=alpha+gamma;
641 if(vt < 0.01) return 0;
645 sfunc=&FGInitialCondition::GammaEqOfTheta;
646 if(findInterval(0,guess)){
657 //******************************************************************************
659 double FGInitialCondition::GammaEqOfTheta(double Theta) {
661 double sTheta,cTheta;
663 //theta=Theta; stheta=sin(theta); ctheta=cos(theta);
664 sTheta=sin(Theta); cTheta=cos(Theta);
666 a=wdown + vt*calpha*cbeta + uw;
667 b=vt*sphi*sbeta + vw*sphi;
668 c=vt*cphi*salpha*cbeta + ww*cphi;
669 return vt*sgamma - ( a*sTheta - (b+c)*cTheta);
672 //******************************************************************************
674 double FGInitialCondition::GammaEqOfAlpha(double Alpha) {
676 double sAlpha,cAlpha;
677 sAlpha=sin(Alpha); cAlpha=cos(Alpha);
678 a=wdown + vt*cAlpha*cbeta + uw;
679 b=vt*sphi*sbeta + vw*sphi;
680 c=vt*cphi*sAlpha*cbeta + ww*cphi;
682 return vt*sgamma - ( a*stheta - (b+c)*ctheta );
685 //******************************************************************************
687 double FGInitialCondition::calcVcas(double Mach) {
689 double p=fdmex->GetAtmosphere()->GetPressure();
690 double psl=fdmex->GetAtmosphere()->GetPressureSL();
691 double rhosl=fdmex->GetAtmosphere()->GetDensitySL();
692 double pt,A,B,D,vcas;
694 if(Mach < 1) //calculate total pressure assuming isentropic flow
695 pt=p*pow((1 + 0.2*Mach*Mach),3.5);
697 // shock in front of pitot tube, we'll assume its normal and use
698 // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
699 // pressure behind the shock to the static pressure in front
702 //the normal shock assumption should not be a bad one -- most supersonic
703 //aircraft place the pitot probe out front so that it is the forward
704 //most point on the aircraft. The real shock would, of course, take
705 //on something like the shape of a rounded-off cone but, here again,
706 //the assumption should be good since the opening of the pitot probe
707 //is very small and, therefore, the effects of the shock curvature
708 //should be small as well. AFAIK, this approach is fairly well accepted
709 //within the aerospace community
711 B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);
713 // The denominator above is zero for Mach ~ 0.38, for which
714 // we'll never be here, so we're safe
716 D = (2.8*Mach*Mach-0.4)*0.4167;
720 A = pow(((pt-p)/psl+1),0.28571);
721 vcas = sqrt(7*psl/rhosl*(A-1));
722 //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl;
726 //******************************************************************************
728 bool FGInitialCondition::findInterval(double x,double guess) {
729 //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){
733 double flo,fhi,fguess;
736 fguess=(this->*sfunc)(guess)-x;
742 if(lo < xmin) lo=xmin;
743 if(hi > xmax) hi=xmax;
745 flo=(this->*sfunc)(lo)-x;
746 fhi=(this->*sfunc)(hi)-x;
747 if(flo*fhi <=0) { //found interval with root
749 if(flo*fguess <= 0) { //narrow interval down a bit
750 hi=lo+step; //to pass solver interval that is as
753 else if(fhi*fguess <= 0) {
757 //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl;
759 while((found == 0) && (i <= 100));
765 //******************************************************************************
767 bool FGInitialCondition::solve(double *y,double x)
769 double x1,x2,x3,f1,f2,f3,d,d0;
771 double const relax =0.9;
779 f1=(this->*sfunc)(x1)-x;
780 f3=(this->*sfunc)(x3)-x;
785 while ((fabs(d) > eps) && (i < 100)) {
787 x2 = x1-d*d0*f1/(f3-f1);
789 f2=(this->*sfunc)(x2)-x;
790 //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
791 //cout << " " << f1 << "," << f2 << "," << f3 << endl;
793 if(fabs(f2) <= 0.001) {
795 } else if(f1*f2 <= 0.0) {
799 } else if(f2*f3 <= 0) {
812 //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl;
816 //******************************************************************************
818 double FGInitialCondition::GetWindDirDegIC(void) const {
820 return atan2(weast,wnorth)*radtodeg;
827 //******************************************************************************
829 bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
834 if( useStoredPath ) {
835 init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml";
837 init_file_name = rstfile;
840 document = LoadXMLDocument(init_file_name);
842 // Make sure that the document is valid
844 cerr << "File: " << init_file_name << " could not be read." << endl;
848 if (document->GetName() != string("initialize")) {
849 cerr << "File: " << init_file_name << " is not a reset file." << endl;
853 if (document->FindElement("latitude"))
854 SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
855 if (document->FindElement("longitude"))
856 SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
857 if (document->FindElement("altitude"))
858 SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
859 if (document->FindElement("ubody"))
860 SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
861 if (document->FindElement("vbody"))
862 SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC"));
863 if (document->FindElement("wbody"))
864 SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC"));
865 if (document->FindElement("vnorth"))
866 SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC"));
867 if (document->FindElement("veast"))
868 SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC"));
869 if (document->FindElement("vdown"))
870 SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC"));
871 if (document->FindElement("winddir"))
872 SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
873 if (document->FindElement("vwind"))
874 SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS"));
875 if (document->FindElement("hwind"))
876 SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
877 if (document->FindElement("xwind"))
878 SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
879 if (document->FindElement("vc"))
880 SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS"));
881 if (document->FindElement("vt"))
882 SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS"));
883 if (document->FindElement("mach"))
884 SetMachIC(document->FindElementValueAsNumber("mach"));
885 if (document->FindElement("phi"))
886 SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG"));
887 if (document->FindElement("theta"))
888 SetThetaDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG"));
889 if (document->FindElement("psi"))
890 SetPsiDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG"));
891 if (document->FindElement("alpha"))
892 SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG"));
893 if (document->FindElement("beta"))
894 SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG"));
895 if (document->FindElement("gamma"))
896 SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG"));
897 if (document->FindElement("roc"))
898 SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
899 if (document->FindElement("vground"))
900 SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS"));
901 if (document->FindElement("targetNlf"))
903 SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
906 // Check to see if any engines are specified to be initialized in a running state
907 FGPropulsion* propulsion = fdmex->GetPropulsion();
908 Element* running_elements = document->FindElement("running");
909 while (running_elements) {
910 n = int(running_elements->GetDataAsNumber());
911 propulsion->InitRunning(n);
912 running_elements = document->FindNextElement("running");
920 //******************************************************************************
922 void FGInitialCondition::bind(void){
923 PropertyManager->Tie("ic/vc-kts", this,
924 &FGInitialCondition::GetVcalibratedKtsIC,
925 &FGInitialCondition::SetVcalibratedKtsIC,
927 PropertyManager->Tie("ic/ve-kts", this,
928 &FGInitialCondition::GetVequivalentKtsIC,
929 &FGInitialCondition::SetVequivalentKtsIC,
931 PropertyManager->Tie("ic/vg-kts", this,
932 &FGInitialCondition::GetVgroundKtsIC,
933 &FGInitialCondition::SetVgroundKtsIC,
935 PropertyManager->Tie("ic/vt-kts", this,
936 &FGInitialCondition::GetVtrueKtsIC,
937 &FGInitialCondition::SetVtrueKtsIC,
939 PropertyManager->Tie("ic/mach", this,
940 &FGInitialCondition::GetMachIC,
941 &FGInitialCondition::SetMachIC,
943 PropertyManager->Tie("ic/roc-fpm", this,
944 &FGInitialCondition::GetClimbRateFpmIC,
945 &FGInitialCondition::SetClimbRateFpmIC,
947 PropertyManager->Tie("ic/gamma-deg", this,
948 &FGInitialCondition::GetFlightPathAngleDegIC,
949 &FGInitialCondition::SetFlightPathAngleDegIC,
951 PropertyManager->Tie("ic/alpha-deg", this,
952 &FGInitialCondition::GetAlphaDegIC,
953 &FGInitialCondition::SetAlphaDegIC,
955 PropertyManager->Tie("ic/beta-deg", this,
956 &FGInitialCondition::GetBetaDegIC,
957 &FGInitialCondition::SetBetaDegIC,
959 PropertyManager->Tie("ic/theta-deg", this,
960 &FGInitialCondition::GetThetaDegIC,
961 &FGInitialCondition::SetThetaDegIC,
963 PropertyManager->Tie("ic/phi-deg", this,
964 &FGInitialCondition::GetPhiDegIC,
965 &FGInitialCondition::SetPhiDegIC,
967 PropertyManager->Tie("ic/psi-true-deg", this,
968 &FGInitialCondition::GetPsiDegIC );
969 PropertyManager->Tie("ic/lat-gc-deg", this,
970 &FGInitialCondition::GetLatitudeDegIC,
971 &FGInitialCondition::SetLatitudeDegIC,
973 PropertyManager->Tie("ic/long-gc-deg", this,
974 &FGInitialCondition::GetLongitudeDegIC,
975 &FGInitialCondition::SetLongitudeDegIC,
977 PropertyManager->Tie("ic/h-sl-ft", this,
978 &FGInitialCondition::GetAltitudeFtIC,
979 &FGInitialCondition::SetAltitudeFtIC,
981 PropertyManager->Tie("ic/h-agl-ft", this,
982 &FGInitialCondition::GetAltitudeAGLFtIC,
983 &FGInitialCondition::SetAltitudeAGLFtIC,
985 PropertyManager->Tie("ic/sea-level-radius-ft", this,
986 &FGInitialCondition::GetSeaLevelRadiusFtIC,
987 &FGInitialCondition::SetSeaLevelRadiusFtIC,
989 PropertyManager->Tie("ic/terrain-altitude-ft", this,
990 &FGInitialCondition::GetTerrainAltitudeFtIC,
991 &FGInitialCondition::SetTerrainAltitudeFtIC,
993 PropertyManager->Tie("ic/vg-fps", this,
994 &FGInitialCondition::GetVgroundFpsIC,
995 &FGInitialCondition::SetVgroundFpsIC,
997 PropertyManager->Tie("ic/vt-fps", this,
998 &FGInitialCondition::GetVtrueFpsIC,
999 &FGInitialCondition::SetVtrueFpsIC,
1001 PropertyManager->Tie("ic/vw-bx-fps", this,
1002 &FGInitialCondition::GetWindUFpsIC);
1003 PropertyManager->Tie("ic/vw-by-fps", this,
1004 &FGInitialCondition::GetWindVFpsIC);
1005 PropertyManager->Tie("ic/vw-bz-fps", this,
1006 &FGInitialCondition::GetWindWFpsIC);
1007 PropertyManager->Tie("ic/vw-north-fps", this,
1008 &FGInitialCondition::GetWindNFpsIC);
1009 PropertyManager->Tie("ic/vw-east-fps", this,
1010 &FGInitialCondition::GetWindEFpsIC);
1011 PropertyManager->Tie("ic/vw-down-fps", this,
1012 &FGInitialCondition::GetWindDFpsIC);
1013 PropertyManager->Tie("ic/vw-mag-fps", this,
1014 &FGInitialCondition::GetWindFpsIC);
1015 PropertyManager->Tie("ic/vw-dir-deg", this,
1016 &FGInitialCondition::GetWindDirDegIC,
1017 &FGInitialCondition::SetWindDirDegIC,
1020 PropertyManager->Tie("ic/roc-fps", this,
1021 &FGInitialCondition::GetClimbRateFpsIC,
1022 &FGInitialCondition::SetClimbRateFpsIC,
1024 PropertyManager->Tie("ic/u-fps", this,
1025 &FGInitialCondition::GetUBodyFpsIC,
1026 &FGInitialCondition::SetUBodyFpsIC,
1028 PropertyManager->Tie("ic/v-fps", this,
1029 &FGInitialCondition::GetVBodyFpsIC,
1030 &FGInitialCondition::SetVBodyFpsIC,
1032 PropertyManager->Tie("ic/w-fps", this,
1033 &FGInitialCondition::GetWBodyFpsIC,
1034 &FGInitialCondition::SetWBodyFpsIC,
1036 PropertyManager->Tie("ic/vn-fps", this,
1037 &FGInitialCondition::GetVNorthFpsIC,
1038 &FGInitialCondition::SetVNorthFpsIC,
1040 PropertyManager->Tie("ic/ve-fps", this,
1041 &FGInitialCondition::GetVEastFpsIC,
1042 &FGInitialCondition::SetVEastFpsIC,
1044 PropertyManager->Tie("ic/vd-fps", this,
1045 &FGInitialCondition::GetVDownFpsIC,
1046 &FGInitialCondition::SetVDownFpsIC,
1048 PropertyManager->Tie("ic/gamma-rad", this,
1049 &FGInitialCondition::GetFlightPathAngleRadIC,
1050 &FGInitialCondition::SetFlightPathAngleRadIC,
1052 PropertyManager->Tie("ic/alpha-rad", this,
1053 &FGInitialCondition::GetAlphaRadIC,
1054 &FGInitialCondition::SetAlphaRadIC,
1056 PropertyManager->Tie("ic/theta-rad", this,
1057 &FGInitialCondition::GetThetaRadIC,
1058 &FGInitialCondition::SetThetaRadIC,
1060 PropertyManager->Tie("ic/beta-rad", this,
1061 &FGInitialCondition::GetBetaRadIC,
1062 &FGInitialCondition::SetBetaRadIC,
1064 PropertyManager->Tie("ic/phi-rad", this,
1065 &FGInitialCondition::GetPhiRadIC,
1066 &FGInitialCondition::SetPhiRadIC,
1068 PropertyManager->Tie("ic/psi-true-rad", this,
1069 &FGInitialCondition::GetPsiRadIC);
1070 PropertyManager->Tie("ic/lat-gc-rad", this,
1071 &FGInitialCondition::GetLatitudeRadIC,
1072 &FGInitialCondition::SetLatitudeRadIC,
1074 PropertyManager->Tie("ic/long-gc-rad", this,
1075 &FGInitialCondition::GetLongitudeRadIC,
1076 &FGInitialCondition::SetLongitudeRadIC,
1078 PropertyManager->Tie("ic/p-rad_sec", this,
1079 &FGInitialCondition::GetPRadpsIC,
1080 &FGInitialCondition::SetPRadpsIC,
1082 PropertyManager->Tie("ic/q-rad_sec", this,
1083 &FGInitialCondition::GetQRadpsIC,
1084 &FGInitialCondition::SetQRadpsIC,
1086 PropertyManager->Tie("ic/r-rad_sec", this,
1087 &FGInitialCondition::GetRRadpsIC,
1088 &FGInitialCondition::SetRRadpsIC,
1091 typedef int (FGInitialCondition::*iPMF)(void) const;
1092 PropertyManager->Tie("simulation/write-state-file",
1095 &FGInitialCondition::WriteStateFile);
1099 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100 // The bitmasked value choices are as follows:
1101 // unset: In this case (the default) JSBSim would only print
1102 // out the normally expected messages, essentially echoing
1103 // the config files as they are read. If the environment
1104 // variable is not set, debug_lvl is set to 1 internally
1105 // 0: This requests JSBSim not to output any messages
1107 // 1: This value explicity requests the normal JSBSim
1109 // 2: This value asks for a message to be printed out when
1110 // a class is instantiated
1111 // 4: When this value is set, a message is displayed when a
1112 // FGModel object executes its Run() method
1113 // 8: When this value is set, various runtime state variables
1114 // are printed out periodically
1115 // 16: When set various parameters are sanity checked and
1116 // a message is printed out when they go out of bounds
1118 void FGInitialCondition::Debug(int from)
1120 if (debug_lvl <= 0) return;
1122 if (debug_lvl & 1) { // Standard console startup message output
1124 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1125 if (from == 0) cout << "Instantiated: FGInitialCondition" << endl;
1126 if (from == 1) cout << "Destroyed: FGInitialCondition" << endl;
1128 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1130 if (debug_lvl & 8 ) { // Runtime state variables
1132 if (debug_lvl & 16) { // Sanity checking
1134 if (debug_lvl & 64) {
1135 if (from == 0) { // Constructor
1136 cout << IdSrc << endl;
1137 cout << IdHdr << endl;