47 #include "FGInitialCondition.h"
48 #include "models/FGInertial.h"
49 #include "models/FGAtmosphere.h"
50 #include "models/FGAccelerations.h"
51 #include "input_output/FGXMLFileRead.h"
60 FGInitialCondition::FGInitialCondition(
FGFDMExec *FDMExec) : fdmex(FDMExec)
65 Atmosphere=fdmex->GetAtmosphere();
68 cout <<
"FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
84 double p0,
double q0,
double r0,
85 double alpha0,
double beta0,
86 double phi0,
double theta0,
double psi0,
87 double latRad0,
double lonRad0,
double altAGLFt0,
90 double calpha = cos(alpha0), cbeta = cos(beta0);
91 double salpha = sin(alpha0), sbeta = sin(beta0);
95 vPQR_body = {p0, q0, r0};
96 alpha = alpha0; beta = beta0;
101 lastLatitudeSet = setgeoc;
102 lastAltitudeSet = setagl;
109 lastSpeedSet = setuvw;
111 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
113 salpha*cbeta, -salpha*sbeta, calpha };
134 vUVW_NED.InitMatrix();
135 vPQR_body.InitMatrix();
140 Tw2b = { 1., 0., 0., 0., 1., 0., 0., 0., 1. };
141 Tb2w = { 1., 0., 0., 0., 1., 0., 0., 0., 1. };
143 lastSpeedSet = setvt;
144 lastAltitudeSet = setasl;
145 lastLatitudeSet = setgeoc;
147 trimRequested = TrimMode::tNone;
155 double rho = Atmosphere->
GetDensity(altitudeASL);
158 lastSpeedSet = setve;
168 lastSpeedSet = setmach;
176 double pressure = Atmosphere->
GetPressure(altitudeASL);
181 lastSpeedSet = setvc;
188 void FGInitialCondition::calcAeroAngles(
const FGColumnVector3& _vt_NED)
192 double ua = _vt_BODY(eX);
193 double va = _vt_BODY(eY);
194 double wa = _vt_BODY(eZ);
195 double uwa = sqrt(ua*ua + wa*wa);
196 double calpha, cbeta;
197 double salpha, sbeta;
200 calpha = cbeta = 1.0;
201 salpha = sbeta = 0.0;
204 alpha = atan2( wa, ua );
213 beta = atan2( va, uwa );
225 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
227 salpha*cbeta, -salpha*sbeta, calpha };
244 _vt_NED = vUVW_NED + _vWIND_NED;
247 calcAeroAngles(_vt_NED);
249 lastSpeedSet = setvg;
266 _vt_NED *= vtrue / vt;
271 vUVW_NED = _vt_NED - _vWIND_NED;
273 calcAeroAngles(_vt_NED);
275 lastSpeedSet = setvt;
285 if (fabs(hdot) > vt) {
286 cerr <<
"The climb rate cannot be higher than the true speed." << endl;
293 double hdot0 = -_vt_NED(eW);
295 if (fabs(hdot0) < vt) {
296 double scale = sqrt((vt*vt-hdot*hdot)/(vt*vt-hdot0*hdot0));
297 _vt_NED(eU) *= scale;
298 _vt_NED(eV) *= scale;
301 vUVW_NED = _vt_NED - _WIND_NED;
304 calcThetaBeta(alpha, _vt_NED);
316 calcThetaBeta(alfa, _vt_NED);
324 void FGInitialCondition::calcThetaBeta(
double alfa,
const FGColumnVector3& _vt_NED)
327 double calpha = cos(alfa), salpha = sin(alfa);
338 -salpha, 0., calpha);
343 FGColumnVector3 u = y - DotProduct(y, n) * n;
344 FGColumnVector3 p = y * n;
346 if (DotProduct(p, v0) < 0) p *= -1.0;
349 u *= DotProduct(v0, y) / DotProduct(u, y);
359 if (DotProduct(v0, v0) < DotProduct(u, u)) {
360 cerr <<
"Cannot modify angle 'alpha' from " << alpha <<
" to " << alfa << endl;
364 FGColumnVector3 v1 = u + sqrt(DotProduct(v0, v0) - DotProduct(u, u))*p;
366 FGColumnVector3 v0xz(v0(eU), 0., v0(eW));
367 FGColumnVector3 v1xz(v1(eU), 0., v1(eW));
370 double sinTheta = (v1xz * v0xz)(eY);
371 vOrient(eTht) = asin(sinTheta);
373 orientation = FGQuaternion(vOrient);
375 const FGMatrix33& Tl2b = orientation.
GetT();
376 FGColumnVector3 v2 = Talpha * Tl2b * _vt_NED;
379 beta = atan2(v2(eV), v2(eU));
380 double cbeta=1.0, sbeta=0.0;
385 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
387 salpha*cbeta, -salpha*sbeta, calpha };
404 double calpha = cos(alpha), salpha = sin(alpha);
405 double cbeta = cos(beta), sbeta = sin(beta);
411 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
413 salpha*cbeta, -salpha*sbeta, calpha };
418 FGColumnVector3 v1xy(sqrt(v0xy(eX)*v0xy(eX)+v0xy(eY)*v0xy(eY)-vf(eY)*vf(eY)),vf(eY),0.);
422 if (vf(eX) < 0.) v0xy(eX) *= -1.0;
424 double sinPsi = (v1xy * v0xy)(eZ);
425 double cosPsi = DotProduct(v0xy, v1xy);
426 vOrient(ePsi) = atan2(sinPsi, cosPsi);
433 v2xz(eV) = vfxz(eV) = 0.0;
436 double sinTheta = (v2xz * vfxz)(eY);
437 vOrient(eTht) = -asin(sinTheta);
445 void FGInitialCondition::SetEulerAngleRadIC(
int idx,
double angle)
454 vOrient(idx) = angle;
457 if ((lastSpeedSet != setned) && (lastSpeedSet != setvg)) {
459 vUVW_NED = newTb2l * _vUVW_BODY;
460 _vt_NED = vUVW_NED + _vWIND_NED;
464 calcAeroAngles(_vt_NED);
472 void FGInitialCondition::SetBodyVelFpsIC(
int idx,
double vel)
474 const FGMatrix33& Tb2l = orientation.
GetTInv();
475 const FGMatrix33& Tl2b = orientation.
GetT();
476 FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
477 FGColumnVector3 _vUVW_BODY = Tl2b * vUVW_NED;
478 FGColumnVector3 _vWIND_NED = _vt_NED - vUVW_NED;
480 _vUVW_BODY(idx) = vel;
481 vUVW_NED = Tb2l * _vUVW_BODY;
482 _vt_NED = vUVW_NED + _vWIND_NED;
483 vt = _vt_NED.Magnitude();
485 calcAeroAngles(_vt_NED);
487 lastSpeedSet = setuvw;
495 void FGInitialCondition::SetNEDVelFpsIC(
int idx,
double vel)
497 const FGMatrix33& Tb2l = orientation.
GetTInv();
498 FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
499 FGColumnVector3 _vWIND_NED = _vt_NED - vUVW_NED;
502 _vt_NED = vUVW_NED + _vWIND_NED;
503 vt = _vt_NED.Magnitude();
505 calcAeroAngles(_vt_NED);
507 lastSpeedSet = setned;
519 calcAeroAngles(_vt_NED);
535 _vWIND_NED -= DotProduct(_vWIND_NED, _vCROSS) * _vCROSS;
538 _vWIND_NED += (cross * ktstofps) * _vCROSS;
539 _vt_NED = vUVW_NED + _vWIND_NED;
542 calcAeroAngles(_vt_NED);
562 _vWIND_NED -= DotProduct(_vWIND_NED, _vHEAD) * _vHEAD;
565 _vWIND_NED += (head * ktstofps) * _vHEAD;
566 _vt_NED = vUVW_NED + _vWIND_NED;
570 calcAeroAngles(_vt_NED);
583 _vt_NED(eW) = vUVW_NED(eW) + wD;
586 calcAeroAngles(_vt_NED);
603 _vHEAD *= (mag*ktstofps) / windMag;
605 _vHEAD = {mag*ktstofps, 0., 0.};
607 _vWIND_NED(eU) = _vHEAD(eU);
608 _vWIND_NED(eV) = _vHEAD(eV);
609 _vt_NED = vUVW_NED + _vWIND_NED;
612 calcAeroAngles(_vt_NED);
625 double mag = _vWIND_NED.
Magnitude(eU, eV);
626 FGColumnVector3 _vHEAD(mag*cos(dir*degtorad), mag*sin(dir*degtorad), 0.);
628 _vWIND_NED(eU) = _vHEAD(eU);
629 _vWIND_NED(eV) = _vHEAD(eV);
630 _vt_NED = vUVW_NED + _vWIND_NED;
633 calcAeroAngles(_vt_NED);
643 if (lastAltitudeSet == setagl)
679 double pressure = Atmosphere->
GetPressure(altitudeASL);
681 double rho = Atmosphere->
GetDensity(altitudeASL);
684 double mach0 = vt / soundSpeed;
686 double ve0 = vt * sqrt(rho/rhoSL);
688 switch(lastLatitudeSet) {
696 double e2 = 1.0-b*b/(a*a);
703 double h = -2.0*max(a,b);
705 while ((fabs(n-prev_n) > 1E-15 || fabs(h-agl) > 1E-10) && iter < 10) {
706 geodLat = atan(tanlat/(1-n));
710 double sinGeodLat = sin(geodLat);
711 double N = a/sqrt(1-e2*sinGeodLat*sinGeodLat);
725 switch(lastSpeedSet) {
740 lastAltitudeSet = setagl;
751 double pressure = Atmosphere->
GetPressure(altitudeASL);
753 double rho = Atmosphere->
GetDensity(altitudeASL);
756 double mach0 = vt / soundSpeed;
758 double ve0 = vt * sqrt(rho/rhoSL);
760 switch(lastLatitudeSet) {
767 double e2 = 1.0-b*b/(a*a);
769 double cosGeodLat = cos(geodLatitude);
770 double sinGeodLat = sin(geodLatitude);
771 double N = a/sqrt(1-e2*sinGeodLat*sinGeodLat);
772 double geodAlt = 0.0;
778 if (cosGeodLat > fabs(sinGeodLat)) {
779 double tanGeodLat = sinGeodLat/cosGeodLat;
780 double x0 = N*e2*cosGeodLat;
782 while (fabs(n-prev_n) > 1E-15 && iter < 10) {
783 double tanLat = (1-n)*tanGeodLat;
784 double cos2Lat = 1./(1.+tanLat*tanLat);
785 double slr = b/sqrt(1.-e2*cos2Lat);
786 double R = slr + alt;
792 geodAlt = x/cosGeodLat-N;
795 double cotanGeodLat = cosGeodLat/sinGeodLat;
796 double z0 = N*e2*sinGeodLat;
798 while (fabs(n-prev_n) > 1E-15 && iter < 10) {
799 double cotanLat = cotanGeodLat/(1-n);
800 double sin2Lat = 1./(1.+cotanLat*cotanLat);
801 double cos2Lat = 1.-sin2Lat;
802 double slr = b/sqrt(1.-e2*cos2Lat);
803 double R = slr + alt;
804 z = R*sign(cotanLat)*sqrt(sin2Lat);
809 geodAlt = z/sinGeodLat-N*(1-e2);
829 switch(lastSpeedSet) {
844 lastAltitudeSet = setasl;
852 lastLatitudeSet = setgeod;
854 switch (lastAltitudeSet)
879 lastLatitudeSet = setgeoc;
881 switch(lastAltitudeSet) {
901 switch(lastAltitudeSet) {
921 return _vWIND_NED(eV) == 0.0 ? 0.0
922 : atan2(_vWIND_NED(eV), _vWIND_NED(eU))*radtodeg;
927 double FGInitialCondition::GetNEDWindFpsIC(
int idx)
const
933 return _vWIND_NED(idx);
949 double FGInitialCondition::GetBodyWindFpsIC(
int idx)
const
956 return _vWIND_BODY(idx);
964 double pressure = Atmosphere->
GetPressure(altitudeASL);
966 double mach = vt / soundSpeed;
976 double rho = Atmosphere->
GetDensity(altitudeASL);
978 return fpstokts * vt * sqrt(rho/rhoSL);
987 return vt / soundSpeed;
992 double FGInitialCondition::GetBodyVelFpsIC(
int idx)
const
997 return _vUVW_BODY(idx);
1004 SGPath init_file_name;
1005 if(useStoredPath && rstfile.isRelative()) {
1008 init_file_name = rstfile;
1012 Element* document = XMLFileRead.LoadXMLDocument(init_file_name);
1017 s <<
"File: " << init_file_name <<
" could not be read.";
1018 cerr << s.str() << endl;
1022 if (document->
GetName() !=
string(
"initialize")) {
1024 s <<
"File: " << init_file_name <<
" is not a reset file.";
1025 cerr << s.str() << endl;
1029 double version = HUGE_VAL;
1030 bool result =
false;
1035 if (version == HUGE_VAL) {
1036 result = Load_v1(document);
1037 }
else if (version >= 3.0) {
1038 const string s(
"Only initialization file formats 1 and 2 are currently supported");
1039 cerr << document->
ReadFrom() << endl << s << endl;
1041 }
else if (version >= 2.0) {
1042 result = Load_v2(document);
1043 }
else if (version >= 1.0) {
1044 result = Load_v1(document);
1049 while (running_elements) {
1051 enginesRunning |= engineNumber == -1 ? engineNumber : 1 << engineNumber;
1060 bool FGInitialCondition::LoadLatitude(
Element* position_el)
1067 if (fabs(latitude) > 0.5*M_PI) {
1069 if (unit_type.empty()) unit_type=
"RAD";
1071 cerr << latitude_el->
ReadFrom() <<
"The latitude value "
1073 <<
" is outside the range [";
1074 if (unit_type ==
"DEG")
1075 cerr <<
"-90 DEG ; +90 DEG]" << endl;
1077 cerr <<
"-PI/2 RAD; +PI/2 RAD]" << endl;
1084 if (lat_type ==
"geod" || lat_type ==
"geodetic") {
1086 lastLatitudeSet = setgeod;
1090 lastLatitudeSet = setgeoc;
1099 void FGInitialCondition::SetTrimRequest(std::string trim)
1101 std::string& trimOption = to_lower(trim);
1102 if (trimOption ==
"1")
1103 trimRequested = TrimMode::tGround;
1104 else if (trimOption ==
"longitudinal")
1105 trimRequested = TrimMode::tLongitudinal;
1106 else if (trimOption ==
"full")
1107 trimRequested = TrimMode::tFull;
1108 else if (trimOption ==
"ground")
1109 trimRequested = TrimMode::tGround;
1110 else if (trimOption ==
"pullup")
1111 trimRequested = TrimMode::tPullup;
1112 else if (trimOption ==
"custom")
1113 trimRequested = TrimMode::tCustom;
1114 else if (trimOption ==
"turn")
1115 trimRequested = TrimMode::tTurn;
1120 bool FGInitialCondition::Load_v1(Element* document)
1124 if (document->FindElement(
"longitude"))
1125 SetLongitudeRadIC(document->FindElementValueAsNumberConvertTo(
"longitude",
"RAD"));
1126 if (document->FindElement(
"elevation"))
1129 if (document->FindElement(
"altitude"))
1131 else if (document->FindElement(
"altitudeAGL"))
1132 SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo(
"altitudeAGL",
"FT"));
1133 else if (document->FindElement(
"altitudeMSL"))
1134 SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo(
"altitudeMSL",
"FT"));
1136 result = LoadLatitude(document);
1138 FGColumnVector3 vOrient = orientation.
GetEuler();
1140 if (document->FindElement(
"phi"))
1141 vOrient(ePhi) = document->FindElementValueAsNumberConvertTo(
"phi",
"RAD");
1142 if (document->FindElement(
"theta"))
1143 vOrient(eTht) = document->FindElementValueAsNumberConvertTo(
"theta",
"RAD");
1144 if (document->FindElement(
"psi"))
1145 vOrient(ePsi) = document->FindElementValueAsNumberConvertTo(
"psi",
"RAD");
1147 orientation = FGQuaternion(vOrient);
1149 if (document->FindElement(
"ubody"))
1150 SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo(
"ubody",
"FT/SEC"));
1151 if (document->FindElement(
"vbody"))
1152 SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo(
"vbody",
"FT/SEC"));
1153 if (document->FindElement(
"wbody"))
1154 SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo(
"wbody",
"FT/SEC"));
1155 if (document->FindElement(
"vnorth"))
1156 SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo(
"vnorth",
"FT/SEC"));
1157 if (document->FindElement(
"veast"))
1158 SetVEastFpsIC(document->FindElementValueAsNumberConvertTo(
"veast",
"FT/SEC"));
1159 if (document->FindElement(
"vdown"))
1160 SetVDownFpsIC(document->FindElementValueAsNumberConvertTo(
"vdown",
"FT/SEC"));
1161 if (document->FindElement(
"vc"))
1163 if (document->FindElement(
"vt"))
1164 SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo(
"vt",
"KTS"));
1165 if (document->FindElement(
"mach"))
1166 SetMachIC(document->FindElementValueAsNumber(
"mach"));
1167 if (document->FindElement(
"gamma"))
1169 if (document->FindElement(
"roc"))
1170 SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo(
"roc",
"FT/SEC"));
1171 if (document->FindElement(
"vground"))
1172 SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo(
"vground",
"KTS"));
1173 if (document->FindElement(
"alpha"))
1174 SetAlphaDegIC(document->FindElementValueAsNumberConvertTo(
"alpha",
"DEG"));
1175 if (document->FindElement(
"beta"))
1176 SetBetaDegIC(document->FindElementValueAsNumberConvertTo(
"beta",
"DEG"));
1177 if (document->FindElement(
"vwind"))
1178 SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo(
"vwind",
"KTS"));
1179 if (document->FindElement(
"winddir"))
1180 SetWindDirDegIC(document->FindElementValueAsNumberConvertTo(
"winddir",
"DEG"));
1181 if (document->FindElement(
"hwind"))
1182 SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo(
"hwind",
"KTS"));
1183 if (document->FindElement(
"xwind"))
1185 if (document->FindElement(
"targetNlf"))
1187 if (document->FindElement(
"trim"))
1188 SetTrimRequest(document->FindElementValue(
"trim"));
1190 vPQR_body.InitMatrix();
1197 bool FGInitialCondition::Load_v2(Element* document)
1199 FGColumnVector3 vOrient;
1203 if (document->FindElement(
"earth_position_angle"))
1204 epa = document->FindElementValueAsNumberConvertTo(
"earth_position_angle",
"RAD");
1205 if (document->FindElement(
"planet_position_angle"))
1206 epa = document->FindElementValueAsNumberConvertTo(
"planet_position_angle",
"RAD");
1209 FGMatrix33 Ti2ec(cos(epa), sin(epa), 0.0,
1210 -sin(epa), cos(epa), 0.0,
1212 FGMatrix33 Tec2i = Ti2ec.Transposed();
1214 if (document->FindElement(
"planet_rotation_rate")) {
1215 fdmex->
GetInertial()->SetOmegaPlanet(document->FindElementValueAsNumberConvertTo(
"planet_rotation_rate",
"RAD"));
1219 FGColumnVector3 vOmegaEarth = fdmex->
GetInertial()->GetOmegaPlanet();
1221 if (document->FindElement(
"elevation")) {
1231 Element* position_el = document->
FindElement(
"position");
1234 frame = to_lower(frame);
1235 if (frame ==
"eci") {
1236 position = Ti2ec * position_el->FindElementTripletConvertTo(
"FT");
1237 }
else if (frame ==
"ecef") {
1238 if (!position_el->FindElement(
"x") && !position_el->FindElement(
"y") && !position_el->FindElement(
"z")) {
1239 if (position_el->FindElement(
"longitude")) {
1240 SetLongitudeRadIC(position_el->FindElementValueAsNumberConvertTo(
"longitude",
"RAD"));
1242 if (position_el->FindElement(
"radius")) {
1243 position.
SetRadius(position_el->FindElementValueAsNumberConvertTo(
"radius",
"FT"));
1244 }
else if (position_el->FindElement(
"altitudeAGL")) {
1245 SetAltitudeAGLFtIC(position_el->FindElementValueAsNumberConvertTo(
"altitudeAGL",
"FT"));
1246 }
else if (position_el->FindElement(
"altitudeMSL")) {
1247 SetAltitudeASLFtIC(position_el->FindElementValueAsNumberConvertTo(
"altitudeMSL",
"FT"));
1249 cerr << endl <<
" No altitude or radius initial condition is given." << endl;
1254 result = LoadLatitude(position_el);
1257 position = position_el->FindElementTripletConvertTo(
"FT");
1260 cerr << endl <<
" Neither ECI nor ECEF frame is specified for initial position." << endl;
1264 cerr << endl <<
" Initial position not specified in this initialization file." << endl;
1293 Element* orientation_el = document->FindElement(
"orientation");
1294 if (orientation_el) {
1295 string frame = orientation_el->GetAttributeValue(
"frame");
1296 frame = to_lower(frame);
1297 vOrient = orientation_el->FindElementTripletConvertTo(
"RAD");
1298 if (frame ==
"eci") {
1310 FGQuaternion QuatI2Body = FGQuaternion(vOrient);
1311 QuatI2Body.Normalize();
1312 FGQuaternion QuatLocal2I = Tec2i * position.
GetTl2ec();
1313 QuatLocal2I.Normalize();
1314 orientation = QuatLocal2I * QuatI2Body;
1316 }
else if (frame ==
"ecef") {
1328 FGQuaternion QuatEC2Body(vOrient);
1329 QuatEC2Body.Normalize();
1330 FGQuaternion QuatLocal2EC = position.
GetTl2ec();
1331 QuatLocal2EC.Normalize();
1332 orientation = QuatLocal2EC * QuatEC2Body;
1334 }
else if (frame ==
"local") {
1336 orientation = FGQuaternion(vOrient);
1340 cerr << endl <<
fgred <<
" Orientation frame type: \"" << frame
1341 <<
"\" is not supported!" <<
reset << endl << endl;
1355 Element* velocity_el = document->FindElement(
"velocity");
1356 FGMatrix33 mTec2l = position.
GetTec2l();
1357 const FGMatrix33& Tb2l = orientation.
GetTInv();
1361 string frame = velocity_el->GetAttributeValue(
"frame");
1362 frame = to_lower(frame);
1363 FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo(
"FT/SEC");
1365 if (frame ==
"eci") {
1366 FGColumnVector3 omega_cross_r = vOmegaEarth * (Tec2i * position);
1367 vUVW_NED = mTec2l * (vInitVelocity - omega_cross_r);
1368 lastSpeedSet = setned;
1369 }
else if (frame ==
"ecef") {
1370 vUVW_NED = mTec2l * vInitVelocity;
1371 lastSpeedSet = setned;
1372 }
else if (frame ==
"local") {
1373 vUVW_NED = vInitVelocity;
1374 lastSpeedSet = setned;
1375 }
else if (frame ==
"body") {
1376 vUVW_NED = Tb2l * vInitVelocity;
1377 lastSpeedSet = setuvw;
1380 cerr << endl <<
fgred <<
" Velocity frame type: \"" << frame
1381 <<
"\" is not supported!" <<
reset << endl << endl;
1388 vUVW_NED.InitMatrix();
1392 vt = vUVW_NED.Magnitude();
1394 calcAeroAngles(vUVW_NED);
1402 Element* attrate_el = document->FindElement(
"attitude_rate");
1406 string frame = attrate_el->GetAttributeValue(
"frame");
1407 frame = to_lower(frame);
1408 const FGMatrix33& Tl2b = orientation.
GetT();
1409 FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo(
"RAD/SEC");
1411 if (frame ==
"eci") {
1412 FGMatrix33 Ti2l = position.
GetTec2l() * Ti2ec;
1413 vPQR_body = Tl2b * Ti2l * (vAttRate - vOmegaEarth);
1414 }
else if (frame ==
"ecef") {
1415 vPQR_body = Tl2b * position.
GetTec2l() * vAttRate;
1416 }
else if (frame ==
"local") {
1419 double radInv = 1.0 / position.
GetRadius();
1420 FGColumnVector3 vOmegaLocal = {radInv*vUVW_NED(eEast),
1421 -radInv*vUVW_NED(eNorth),
1422 -radInv*vUVW_NED(eEast)*tan(position.
GetLatitude())};
1423 vPQR_body = Tl2b * (vAttRate + vOmegaLocal);
1424 }
else if (frame ==
"body") {
1425 vPQR_body = vAttRate;
1426 }
else if (!frame.empty()) {
1428 cerr << endl <<
fgred <<
" Attitude rate frame type: \"" << frame
1429 <<
"\" is not supported!" <<
reset << endl << endl;
1432 }
else if (frame.empty()) {
1433 vPQR_body.InitMatrix();
1437 vPQR_body.InitMatrix();
1445 void FGInitialCondition::bind(FGPropertyManager* PropertyManager)
1447 PropertyManager->Tie(
"ic/vc-kts",
this,
1450 PropertyManager->Tie(
"ic/ve-kts",
this,
1453 PropertyManager->Tie(
"ic/vg-kts",
this,
1456 PropertyManager->Tie(
"ic/vt-kts",
this,
1459 PropertyManager->Tie(
"ic/mach",
this,
1462 PropertyManager->Tie(
"ic/roc-fpm",
this,
1465 PropertyManager->Tie(
"ic/gamma-deg",
this,
1468 PropertyManager->Tie(
"ic/alpha-deg",
this,
1471 PropertyManager->Tie(
"ic/beta-deg",
this,
1474 PropertyManager->Tie(
"ic/theta-deg",
this,
1477 PropertyManager->Tie(
"ic/phi-deg",
this,
1480 PropertyManager->Tie(
"ic/psi-true-deg",
this,
1483 PropertyManager->Tie(
"ic/lat-gc-deg",
this,
1486 PropertyManager->Tie(
"ic/long-gc-deg",
this,
1489 PropertyManager->Tie(
"ic/h-sl-ft",
this,
1492 PropertyManager->Tie(
"ic/h-agl-ft",
this,
1495 PropertyManager->Tie(
"ic/terrain-elevation-ft",
this,
1498 PropertyManager->Tie(
"ic/vg-fps",
this,
1501 PropertyManager->Tie(
"ic/vt-fps",
this,
1504 PropertyManager->Tie(
"ic/vw-bx-fps",
this,
1506 PropertyManager->Tie(
"ic/vw-by-fps",
this,
1508 PropertyManager->Tie(
"ic/vw-bz-fps",
this,
1510 PropertyManager->Tie(
"ic/vw-north-fps",
this,
1512 PropertyManager->Tie(
"ic/vw-east-fps",
this,
1514 PropertyManager->Tie(
"ic/vw-down-fps",
this,
1516 PropertyManager->Tie(
"ic/vw-mag-fps",
this,
1518 PropertyManager->Tie(
"ic/vw-dir-deg",
this,
1522 PropertyManager->Tie(
"ic/roc-fps",
this,
1525 PropertyManager->Tie(
"ic/u-fps",
this,
1528 PropertyManager->Tie(
"ic/v-fps",
this,
1531 PropertyManager->Tie(
"ic/w-fps",
this,
1534 PropertyManager->Tie(
"ic/vn-fps",
this,
1537 PropertyManager->Tie(
"ic/ve-fps",
this,
1540 PropertyManager->Tie(
"ic/vd-fps",
this,
1543 PropertyManager->Tie(
"ic/gamma-rad",
this,
1546 PropertyManager->Tie(
"ic/alpha-rad",
this,
1549 PropertyManager->Tie(
"ic/theta-rad",
this,
1552 PropertyManager->Tie(
"ic/beta-rad",
this,
1555 PropertyManager->Tie(
"ic/phi-rad",
this,
1558 PropertyManager->Tie(
"ic/psi-true-rad",
this,
1561 PropertyManager->Tie(
"ic/lat-gc-rad",
this,
1564 PropertyManager->Tie(
"ic/long-gc-rad",
this,
1567 PropertyManager->Tie(
"ic/p-rad_sec",
this,
1570 PropertyManager->Tie(
"ic/q-rad_sec",
this,
1573 PropertyManager->Tie(
"ic/r-rad_sec",
this,
1576 PropertyManager->Tie(
"ic/lat-geod-rad",
this,
1579 PropertyManager->Tie(
"ic/lat-geod-deg",
this,
1582 PropertyManager->Tie(
"ic/geod-alt-ft", &position,
1585 PropertyManager->Tie(
"ic/targetNlf",
this,
1609 void FGInitialCondition::Debug(
int from)
1611 if (debug_lvl <= 0)
return;
1613 if (debug_lvl & 1) {
1615 if (debug_lvl & 2 ) {
1616 if (from == 0) cout <<
"Instantiated: FGInitialCondition" << endl;
1617 if (from == 1) cout <<
"Destroyed: FGInitialCondition" << endl;
1619 if (debug_lvl & 4 ) {
1621 if (debug_lvl & 8 ) {
1623 if (debug_lvl & 16) {
1625 if (debug_lvl & 64) {