47#include "FGInitialCondition.h"
48#include "models/FGInertial.h"
49#include "models/FGAtmosphere.h"
50#include "models/FGAccelerations.h"
51#include "models/FGAuxiliary.h"
52#include "input_output/FGXMLFileRead.h"
55#include "input_output/string_utilities.h"
56#include "input_output/FGLog.h"
72 throw BaseException(
"FGInitialCondition: This class requires a pointer to a valid FGFDMExec object");
88 double p0,
double q0,
double r0,
89 double alpha0,
double beta0,
90 double phi0,
double theta0,
double psi0,
91 double latRad0,
double lonRad0,
double altAGLFt0,
94 double calpha = cos(alpha0), cbeta = cos(beta0);
95 double salpha = sin(alpha0), sbeta = sin(beta0);
99 vPQR_body = {p0, q0, r0};
100 alpha = alpha0; beta = beta0;
104 fdmex->
GetInertial()->SetAltitudeAGL(position, altAGLFt0);
105 lastLatitudeSet = setgeoc;
106 lastAltitudeSet = setagl;
113 lastSpeedSet = setuvw;
115 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
117 salpha*cbeta, -salpha*sbeta, calpha };
138 vUVW_NED.InitMatrix();
139 vPQR_body.InitMatrix();
144 Tw2b = { 1., 0., 0., 0., 1., 0., 0., 0., 1. };
145 Tb2w = { 1., 0., 0., 0., 1., 0., 0., 0., 1. };
147 lastSpeedSet = setvt;
148 lastAltitudeSet = setasl;
149 lastLatitudeSet = setgeoc;
151 trimRequested = TrimMode::tNone;
158 const auto Atmosphere = fdmex->GetAtmosphere();
160 double rho = Atmosphere->GetDensity(altitudeASL);
161 SetVtrueFpsIC(ve*ktstofps*sqrt(FGAtmosphere::StdDaySLdensity/rho));
162 lastSpeedSet = setve;
169 const auto Atmosphere = fdmex->GetAtmosphere();
171 double soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
173 lastSpeedSet = setmach;
180 const auto Atmosphere = fdmex->GetAtmosphere();
182 double pressure = Atmosphere->GetPressure(altitudeASL);
183 double mach = Auxiliary->MachFromVcalibrated(fabs(vcas)*ktstofps, pressure);
184 double soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
187 lastSpeedSet = setvc;
198 double ua = _vt_BODY(eX);
199 double va = _vt_BODY(eY);
200 double wa = _vt_BODY(eZ);
201 double uwa = sqrt(ua*ua + wa*wa);
202 double calpha, cbeta;
203 double salpha, sbeta;
206 calpha = cbeta = 1.0;
207 salpha = sbeta = 0.0;
210 alpha = atan2( wa, ua );
219 beta = atan2( va, uwa );
231 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
233 salpha*cbeta, -salpha*sbeta, calpha };
250 _vt_NED = vUVW_NED + _vWIND_NED;
253 calcAeroAngles(_vt_NED);
255 lastSpeedSet = setvg;
272 _vt_NED *= vtrue / vt;
277 vUVW_NED = _vt_NED - _vWIND_NED;
279 calcAeroAngles(_vt_NED);
281 lastSpeedSet = setvt;
291 if (fabs(hdot) > vt) {
293 log <<
"The climb rate cannot be higher than the true speed.\n";
300 double hdot0 = -_vt_NED(eW);
302 if (fabs(hdot0) < vt) {
303 double scale = sqrt((vt*vt-hdot*hdot)/(vt*vt-hdot0*hdot0));
304 _vt_NED(eU) *= scale;
305 _vt_NED(eV) *= scale;
308 vUVW_NED = _vt_NED - _WIND_NED;
311 calcThetaBeta(alpha, _vt_NED);
323 calcThetaBeta(alfa, _vt_NED);
331void FGInitialCondition::calcThetaBeta(
double alfa,
const FGColumnVector3& _vt_NED)
334 double calpha = cos(alfa), salpha = sin(alfa);
345 -salpha, 0., calpha);
351 FGColumnVector3 p = y * n;
367 FGLogging log(LogLevel::ERROR);
368 log <<
"Cannot modify angle 'alpha' from " << alpha <<
" to " << alfa <<
"\n";
374 FGColumnVector3 v0xz(v0(eU), 0., v0(eW));
375 FGColumnVector3 v1xz(v1(eU), 0., v1(eW));
378 double sinTheta = (v1xz * v0xz)(eY);
379 vOrient(eTht) = asin(sinTheta);
381 orientation = FGQuaternion(vOrient);
383 const FGMatrix33& Tl2b = orientation.
GetT();
384 FGColumnVector3 v2 = Talpha * Tl2b * _vt_NED;
387 beta = atan2(v2(eV), v2(eU));
388 double cbeta=1.0, sbeta=0.0;
393 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
395 salpha*cbeta, -salpha*sbeta, calpha };
412 double calpha = cos(alpha), salpha = sin(alpha);
413 double cbeta = cos(beta), sbeta = sin(beta);
419 Tw2b = { calpha*cbeta, -calpha*sbeta, -salpha,
421 salpha*cbeta, -salpha*sbeta, calpha };
426 FGColumnVector3 v1xy(sqrt(v0xy(eX)*v0xy(eX)+v0xy(eY)*v0xy(eY)-vf(eY)*vf(eY)),vf(eY),0.);
430 if (vf(eX) < 0.) v0xy(eX) *= -1.0;
432 double sinPsi = (v1xy * v0xy)(eZ);
434 vOrient(ePsi) = atan2(sinPsi, cosPsi);
441 v2xz(eV) = vfxz(eV) = 0.0;
444 double sinTheta = (v2xz * vfxz)(eY);
445 vOrient(eTht) = -asin(sinTheta);
453void FGInitialCondition::SetEulerAngleRadIC(
int idx,
double angle)
462 vOrient(idx) = angle;
465 if ((lastSpeedSet != setned) && (lastSpeedSet != setvg)) {
467 vUVW_NED = newTb2l * _vUVW_BODY;
468 _vt_NED = vUVW_NED + _vWIND_NED;
472 calcAeroAngles(_vt_NED);
480void FGInitialCondition::SetBodyVelFpsIC(
int idx,
double vel)
482 const FGMatrix33& Tb2l = orientation.
GetTInv();
483 const FGMatrix33& Tl2b = orientation.
GetT();
484 FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
485 FGColumnVector3 _vUVW_BODY = Tl2b * vUVW_NED;
486 FGColumnVector3 _vWIND_NED = _vt_NED - vUVW_NED;
488 _vUVW_BODY(idx) = vel;
489 vUVW_NED = Tb2l * _vUVW_BODY;
490 _vt_NED = vUVW_NED + _vWIND_NED;
491 vt = _vt_NED.Magnitude();
493 calcAeroAngles(_vt_NED);
495 lastSpeedSet = setuvw;
503void FGInitialCondition::SetNEDVelFpsIC(
int idx,
double vel)
505 const FGMatrix33& Tb2l = orientation.
GetTInv();
506 FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
507 FGColumnVector3 _vWIND_NED = _vt_NED - vUVW_NED;
510 _vt_NED = vUVW_NED + _vWIND_NED;
511 vt = _vt_NED.Magnitude();
513 calcAeroAngles(_vt_NED);
515 lastSpeedSet = setned;
527 calcAeroAngles(_vt_NED);
543 _vWIND_NED -=
DotProduct(_vWIND_NED, _vCROSS) * _vCROSS;
546 _vWIND_NED += (cross * ktstofps) * _vCROSS;
547 _vt_NED = vUVW_NED + _vWIND_NED;
550 calcAeroAngles(_vt_NED);
570 _vWIND_NED -=
DotProduct(_vWIND_NED, _vHEAD) * _vHEAD;
573 _vWIND_NED += (head * ktstofps) * _vHEAD;
574 _vt_NED = vUVW_NED + _vWIND_NED;
578 calcAeroAngles(_vt_NED);
591 _vt_NED(eW) = vUVW_NED(eW) + wD * ktstofps;
594 calcAeroAngles(_vt_NED);
611 _vHEAD *= (mag*ktstofps) / windMag;
613 _vHEAD = {mag*ktstofps, 0., 0.};
615 _vWIND_NED(eU) = _vHEAD(eU);
616 _vWIND_NED(eV) = _vHEAD(eV);
617 _vt_NED = vUVW_NED + _vWIND_NED;
620 calcAeroAngles(_vt_NED);
633 double mag = _vWIND_NED.
Magnitude(eU, eV);
634 FGColumnVector3 _vHEAD(mag*cos(dir*degtorad), mag*sin(dir*degtorad), 0.);
636 _vWIND_NED(eU) = _vHEAD(eU);
637 _vWIND_NED(eV) = _vHEAD(eV);
638 _vt_NED = vUVW_NED + _vWIND_NED;
641 calcAeroAngles(_vt_NED);
651 if (lastAltitudeSet == setagl)
666 return fdmex->
GetInertial()->GetAltitudeAGL(position);
678 fdmex->
GetInertial()->GetContactPoint(position, contact, normal, v, w);
686 const auto Atmosphere = fdmex->GetAtmosphere();
688 double pressure = Atmosphere->GetPressure(altitudeASL);
689 double soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
690 double rho = Atmosphere->GetDensity(altitudeASL);
692 double mach0 = vt / soundSpeed;
693 double vc0 = Auxiliary->VcalibratedFromMach(mach0, pressure);
694 double ve0 = vt * sqrt(rho/FGAtmosphere::StdDaySLdensity);
696 switch(lastLatitudeSet) {
698 fdmex->
GetInertial()->SetAltitudeAGL(position, agl);
704 double e2 = 1.0-b*b/(a*a);
711 double h = -2.0*max(a,b);
713 while ((fabs(n-prev_n) > 1E-15 || fabs(h-agl) > 1E-10) && iter < 10) {
714 geodLat = atan(tanlat/(1-n));
718 double sinGeodLat = sin(geodLat);
719 double N = a/sqrt(1-e2*sinGeodLat*sinGeodLat);
729 soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
730 rho = Atmosphere->GetDensity(altitudeASL);
731 pressure = Atmosphere->GetPressure(altitudeASL);
733 switch(lastSpeedSet) {
735 mach0 = Auxiliary->MachFromVcalibrated(vc0, pressure);
742 SetVtrueFpsIC(ve0 * sqrt(FGAtmosphere::StdDaySLdensity/rho));
748 lastAltitudeSet = setagl;
758 const auto Atmosphere = fdmex->GetAtmosphere();
760 double pressure = Atmosphere->GetPressure(altitudeASL);
761 double soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
762 double rho = Atmosphere->GetDensity(altitudeASL);
764 double mach0 = vt / soundSpeed;
765 double vc0 = Auxiliary->VcalibratedFromMach(mach0, pressure);
766 double ve0 = vt * sqrt(rho/FGAtmosphere::StdDaySLdensity);
768 switch(lastLatitudeSet) {
775 double e2 = 1.0-b*b/(a*a);
777 double cosGeodLat = cos(geodLatitude);
778 double sinGeodLat = sin(geodLatitude);
779 double N = a/sqrt(1-e2*sinGeodLat*sinGeodLat);
780 double geodAlt = 0.0;
786 if (cosGeodLat > fabs(sinGeodLat)) {
787 double tanGeodLat = sinGeodLat/cosGeodLat;
788 double x0 = N*e2*cosGeodLat;
790 while (fabs(n-prev_n) > 1E-15 && iter < 10) {
791 double tanLat = (1-n)*tanGeodLat;
792 double cos2Lat = 1./(1.+tanLat*tanLat);
793 double slr = b/sqrt(1.-e2*cos2Lat);
794 double R = slr + alt;
800 geodAlt = x/cosGeodLat-N;
803 double cotanGeodLat = cosGeodLat/sinGeodLat;
804 double z0 = N*e2*sinGeodLat;
806 while (fabs(n-prev_n) > 1E-15 && iter < 10) {
807 double cotanLat = cotanGeodLat/(1-n);
808 double sin2Lat = 1./(1.+cotanLat*cotanLat);
809 double cos2Lat = 1.-sin2Lat;
810 double slr = b/sqrt(1.-e2*cos2Lat);
811 double R = slr + alt;
812 z = R*sign(cotanLat)*sqrt(sin2Lat);
817 geodAlt = z/sinGeodLat-N*(1-e2);
833 soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
834 rho = Atmosphere->GetDensity(altitudeASL);
835 pressure = Atmosphere->GetPressure(altitudeASL);
837 switch(lastSpeedSet) {
839 mach0 = Auxiliary->MachFromVcalibrated(vc0, pressure);
846 SetVtrueFpsIC(ve0 * sqrt(FGAtmosphere::StdDaySLdensity/rho));
852 lastAltitudeSet = setasl;
860 lastLatitudeSet = setgeod;
862 switch (lastAltitudeSet)
868 fdmex->
GetInertial()->SetAltitudeAGL(position, agl);
887 lastLatitudeSet = setgeoc;
889 switch(lastAltitudeSet) {
909 switch(lastAltitudeSet) {
929 return _vWIND_NED.
Magnitude(eU, eV) == 0.0 ? 0.0
930 : atan2(_vWIND_NED(eV), _vWIND_NED(eU))*radtodeg;
938 return _vt_NED - vUVW_NED;
954double FGInitialCondition::GetBodyWindFpsIC(
int idx)
const
961 return _vWIND_BODY(idx);
968 const auto Atmosphere = fdmex->GetAtmosphere();
970 double pressure = Atmosphere->GetPressure(altitudeASL);
971 double soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
972 double mach = vt / soundSpeed;
974 return fpstokts * Auxiliary->VcalibratedFromMach(mach, pressure);
981 const auto Atmosphere = fdmex->GetAtmosphere();
983 double rho = Atmosphere->GetDensity(altitudeASL);
984 return fpstokts * vt * sqrt(rho/FGAtmosphere::StdDaySLdensity);
991 const auto Atmosphere = fdmex->GetAtmosphere();
993 double soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL);
994 return vt / soundSpeed;
999double FGInitialCondition::GetBodyVelFpsIC(
int idx)
const
1004 return _vUVW_BODY(idx);
1011 SGPath init_file_name;
1012 if(useAircraftPath && rstfile.isRelative()) {
1015 init_file_name = rstfile;
1019 Element* document = XMLFileRead.LoadXMLDocument(init_file_name);
1024 err <<
"File: " << init_file_name <<
" could not be read.\n";
1028 if (document->
GetName() !=
"initialize") {
1030 err <<
"File: " << init_file_name <<
" is not a reset file.\n";
1034 bool result =
false;
1040 if (version >= 3.0) {
1042 err <<
"Only initialization file formats 1 and 2 are currently supported\n";
1044 }
else if (version >= 2.0) {
1045 result = Load_v2(document);
1046 }
else if (version >= 1.0) {
1047 result = Load_v1(document);
1051 result = Load_v1(document);
1056 while (running_elements) {
1058 enginesRunning |= engineNumber == -1 ? engineNumber : 1 << engineNumber;
1067bool FGInitialCondition::LoadLatitude(
Element* position_el)
1074 if (fabs(latitude) > 0.5*M_PI) {
1076 if (unit_type.empty()) unit_type=
"RAD";
1079 log << latitude_el->
ReadFrom() <<
"The latitude value "
1081 <<
" is outside the range [";
1082 if (unit_type ==
"DEG")
1083 log <<
"-90 DEG ; +90 DEG]" << endl;
1085 log <<
"-PI/2 RAD; +PI/2 RAD]" << endl;
1092 if (lat_type ==
"geod" || lat_type ==
"geodetic") {
1094 lastLatitudeSet = setgeod;
1098 lastLatitudeSet = setgeoc;
1107void FGInitialCondition::SetTrimRequest(std::string trim)
1109 std::string& trimOption = to_lower(trim);
1110 if (trimOption ==
"1")
1111 trimRequested = TrimMode::tGround;
1112 else if (trimOption ==
"longitudinal")
1113 trimRequested = TrimMode::tLongitudinal;
1114 else if (trimOption ==
"full")
1115 trimRequested = TrimMode::tFull;
1116 else if (trimOption ==
"ground")
1117 trimRequested = TrimMode::tGround;
1118 else if (trimOption ==
"pullup")
1119 trimRequested = TrimMode::tPullup;
1120 else if (trimOption ==
"custom")
1121 trimRequested = TrimMode::tCustom;
1122 else if (trimOption ==
"turn")
1123 trimRequested = TrimMode::tTurn;
1128bool FGInitialCondition::Load_v1(Element* document)
1132 if (document->FindElement(
"longitude"))
1133 SetLongitudeRadIC(document->FindElementValueAsNumberConvertTo(
"longitude",
"RAD"));
1134 if (document->FindElement(
"elevation"))
1137 if (document->FindElement(
"altitude"))
1139 else if (document->FindElement(
"altitudeAGL"))
1140 SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo(
"altitudeAGL",
"FT"));
1141 else if (document->FindElement(
"altitudeMSL"))
1142 SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo(
"altitudeMSL",
"FT"));
1144 result = LoadLatitude(document);
1146 FGColumnVector3 vOrient = orientation.
GetEuler();
1148 if (document->FindElement(
"phi"))
1149 vOrient(ePhi) = document->FindElementValueAsNumberConvertTo(
"phi",
"RAD");
1150 if (document->FindElement(
"theta"))
1151 vOrient(eTht) = document->FindElementValueAsNumberConvertTo(
"theta",
"RAD");
1152 if (document->FindElement(
"psi"))
1153 vOrient(ePsi) = document->FindElementValueAsNumberConvertTo(
"psi",
"RAD");
1155 orientation = FGQuaternion(vOrient);
1157 if (document->FindElement(
"ubody"))
1158 SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo(
"ubody",
"FT/SEC"));
1159 if (document->FindElement(
"vbody"))
1160 SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo(
"vbody",
"FT/SEC"));
1161 if (document->FindElement(
"wbody"))
1162 SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo(
"wbody",
"FT/SEC"));
1163 if (document->FindElement(
"vnorth"))
1164 SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo(
"vnorth",
"FT/SEC"));
1165 if (document->FindElement(
"veast"))
1166 SetVEastFpsIC(document->FindElementValueAsNumberConvertTo(
"veast",
"FT/SEC"));
1167 if (document->FindElement(
"vdown"))
1168 SetVDownFpsIC(document->FindElementValueAsNumberConvertTo(
"vdown",
"FT/SEC"));
1169 if (document->FindElement(
"vc"))
1171 if (document->FindElement(
"vt"))
1172 SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo(
"vt",
"KTS"));
1173 if (document->FindElement(
"mach"))
1174 SetMachIC(document->FindElementValueAsNumber(
"mach"));
1175 if (document->FindElement(
"gamma"))
1177 if (document->FindElement(
"roc"))
1178 SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo(
"roc",
"FT/SEC"));
1179 if (document->FindElement(
"vground"))
1180 SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo(
"vground",
"KTS"));
1181 if (document->FindElement(
"alpha"))
1182 SetAlphaDegIC(document->FindElementValueAsNumberConvertTo(
"alpha",
"DEG"));
1183 if (document->FindElement(
"beta"))
1184 SetBetaDegIC(document->FindElementValueAsNumberConvertTo(
"beta",
"DEG"));
1185 if (document->FindElement(
"vwind"))
1186 SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo(
"vwind",
"KTS"));
1187 if (document->FindElement(
"winddir"))
1188 SetWindDirDegIC(document->FindElementValueAsNumberConvertTo(
"winddir",
"DEG"));
1189 if (document->FindElement(
"hwind"))
1190 SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo(
"hwind",
"KTS"));
1191 if (document->FindElement(
"xwind"))
1193 if (document->FindElement(
"targetNlf"))
1195 if (document->FindElement(
"trim"))
1196 SetTrimRequest(document->FindElementValue(
"trim"));
1198 vPQR_body.InitMatrix();
1205bool FGInitialCondition::Load_v2(Element* document)
1207 FGColumnVector3 vOrient;
1211 if (document->FindElement(
"earth_position_angle"))
1212 epa = document->FindElementValueAsNumberConvertTo(
"earth_position_angle",
"RAD");
1213 if (document->FindElement(
"planet_position_angle"))
1214 epa = document->FindElementValueAsNumberConvertTo(
"planet_position_angle",
"RAD");
1217 FGMatrix33 Ti2ec(cos(epa), sin(epa), 0.0,
1218 -sin(epa), cos(epa), 0.0,
1220 FGMatrix33 Tec2i = Ti2ec.Transposed();
1222 if (document->FindElement(
"planet_rotation_rate")) {
1223 fdmex->
GetInertial()->SetOmegaPlanet(document->FindElementValueAsNumberConvertTo(
"planet_rotation_rate",
"RAD"));
1227 FGColumnVector3 vOmegaEarth = fdmex->
GetInertial()->GetOmegaPlanet();
1229 if (document->FindElement(
"elevation")) {
1230 fdmex->
GetInertial()->SetTerrainElevation(document->FindElementValueAsNumberConvertTo(
"elevation",
"FT"));
1239 Element* position_el = document->
FindElement(
"position");
1242 frame = to_lower(frame);
1243 if (frame ==
"eci") {
1244 position = Ti2ec * position_el->FindElementTripletConvertTo(
"FT");
1245 }
else if (frame ==
"ecef") {
1246 if (!position_el->FindElement(
"x") && !position_el->FindElement(
"y") && !position_el->FindElement(
"z")) {
1247 if (position_el->FindElement(
"longitude")) {
1248 SetLongitudeRadIC(position_el->FindElementValueAsNumberConvertTo(
"longitude",
"RAD"));
1250 if (position_el->FindElement(
"radius")) {
1251 position.
SetRadius(position_el->FindElementValueAsNumberConvertTo(
"radius",
"FT"));
1252 }
else if (position_el->FindElement(
"altitudeAGL")) {
1253 SetAltitudeAGLFtIC(position_el->FindElementValueAsNumberConvertTo(
"altitudeAGL",
"FT"));
1254 }
else if (position_el->FindElement(
"altitudeMSL")) {
1255 SetAltitudeASLFtIC(position_el->FindElementValueAsNumberConvertTo(
"altitudeMSL",
"FT"));
1257 FGXMLLogging log(position_el, LogLevel::ERROR);
1258 log <<
" No altitude or radius initial condition is given.\n";
1263 result = LoadLatitude(position_el);
1266 position = position_el->FindElementTripletConvertTo(
"FT");
1269 FGXMLLogging log(position_el, LogLevel::ERROR);
1270 log <<
" Neither ECI nor ECEF frame is specified for initial position.\n";
1274 FGXMLLogging log(document, LogLevel::ERROR);
1275 log <<
" Initial position not specified in this initialization file.\n";
1304 Element* orientation_el = document->FindElement(
"orientation");
1305 if (orientation_el) {
1306 string frame = orientation_el->GetAttributeValue(
"frame");
1307 frame = to_lower(frame);
1308 vOrient = orientation_el->FindElementTripletConvertTo(
"RAD");
1309 if (frame ==
"eci") {
1321 FGQuaternion QuatI2Body = FGQuaternion(vOrient);
1322 QuatI2Body.Normalize();
1323 FGQuaternion QuatLocal2I = Tec2i * position.
GetTl2ec();
1324 QuatLocal2I.Normalize();
1325 orientation = QuatLocal2I * QuatI2Body;
1327 }
else if (frame ==
"ecef") {
1339 FGQuaternion QuatEC2Body(vOrient);
1340 QuatEC2Body.Normalize();
1341 FGQuaternion QuatLocal2EC = position.
GetTl2ec();
1342 QuatLocal2EC.Normalize();
1343 orientation = QuatLocal2EC * QuatEC2Body;
1345 }
else if (frame ==
"local") {
1347 orientation = FGQuaternion(vOrient);
1350 FGXMLLogging log(orientation_el, LogLevel::ERROR);
1351 log <<
"\n" << LogFormat::RED <<
" Orientation frame type: \"" << frame
1352 <<
"\" is not supported!\n\n" << LogFormat::RESET;
1365 Element* velocity_el = document->FindElement(
"velocity");
1366 FGMatrix33 mTec2l = position.
GetTec2l();
1367 const FGMatrix33& Tb2l = orientation.
GetTInv();
1371 string frame = velocity_el->GetAttributeValue(
"frame");
1372 frame = to_lower(frame);
1373 FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo(
"FT/SEC");
1375 if (frame ==
"eci") {
1376 FGColumnVector3 omega_cross_r = vOmegaEarth * (Tec2i * position);
1377 vUVW_NED = mTec2l * (vInitVelocity - omega_cross_r);
1378 lastSpeedSet = setned;
1379 }
else if (frame ==
"ecef") {
1380 vUVW_NED = mTec2l * vInitVelocity;
1381 lastSpeedSet = setned;
1382 }
else if (frame ==
"local") {
1383 vUVW_NED = vInitVelocity;
1384 lastSpeedSet = setned;
1385 }
else if (frame ==
"body") {
1386 vUVW_NED = Tb2l * vInitVelocity;
1387 lastSpeedSet = setuvw;
1389 FGXMLLogging log(velocity_el, LogLevel::ERROR);
1390 log <<
"\n" << LogFormat::RED <<
" Velocity frame type: \"" << frame
1391 <<
"\" is not supported!\n\n" << LogFormat::RESET;
1397 vUVW_NED.InitMatrix();
1401 vt = vUVW_NED.Magnitude();
1403 calcAeroAngles(vUVW_NED);
1411 Element* attrate_el = document->FindElement(
"attitude_rate");
1415 string frame = attrate_el->GetAttributeValue(
"frame");
1416 frame = to_lower(frame);
1417 const FGMatrix33& Tl2b = orientation.
GetT();
1418 FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo(
"RAD/SEC");
1420 if (frame ==
"eci") {
1421 FGMatrix33 Ti2l = position.
GetTec2l() * Ti2ec;
1422 vPQR_body = Tl2b * Ti2l * (vAttRate - vOmegaEarth);
1423 }
else if (frame ==
"ecef") {
1424 vPQR_body = Tl2b * position.
GetTec2l() * vAttRate;
1425 }
else if (frame ==
"local") {
1428 double radInv = 1.0 / position.
GetRadius();
1429 FGColumnVector3 vOmegaLocal = {radInv*vUVW_NED(eEast),
1430 -radInv*vUVW_NED(eNorth),
1431 -radInv*vUVW_NED(eEast)*tan(position.
GetLatitude())};
1432 vPQR_body = Tl2b * (vAttRate + vOmegaLocal);
1433 }
else if (frame ==
"body") {
1434 vPQR_body = vAttRate;
1435 }
else if (!frame.empty()) {
1436 FGXMLLogging log(attrate_el, LogLevel::ERROR);
1437 log << endl << LogFormat::RED <<
" Attitude rate frame type: \"" << frame
1438 <<
"\" is not supported!\n\n" << LogFormat::RESET;
1440 }
else if (frame.empty()) {
1441 vPQR_body.InitMatrix();
1445 vPQR_body.InitMatrix();
1453void FGInitialCondition::bind(FGPropertyManager* PropertyManager)
1455 PropertyManager->Tie(
"ic/vc-kts",
this,
1458 PropertyManager->Tie(
"ic/ve-kts",
this,
1461 PropertyManager->Tie(
"ic/vg-kts",
this,
1464 PropertyManager->Tie(
"ic/vt-kts",
this,
1467 PropertyManager->Tie(
"ic/mach",
this,
1470 PropertyManager->Tie(
"ic/roc-fpm",
this,
1473 PropertyManager->Tie(
"ic/gamma-deg",
this,
1476 PropertyManager->Tie(
"ic/alpha-deg",
this,
1479 PropertyManager->Tie(
"ic/beta-deg",
this,
1482 PropertyManager->Tie(
"ic/theta-deg",
this,
1485 PropertyManager->Tie(
"ic/phi-deg",
this,
1488 PropertyManager->Tie(
"ic/psi-true-deg",
this,
1491 PropertyManager->Tie(
"ic/lat-gc-deg",
this,
1494 PropertyManager->Tie(
"ic/long-gc-deg",
this,
1497 PropertyManager->Tie(
"ic/h-sl-ft",
this,
1500 PropertyManager->Tie(
"ic/h-agl-ft",
this,
1503 PropertyManager->Tie(
"ic/terrain-elevation-ft",
this,
1506 PropertyManager->Tie(
"ic/vg-fps",
this,
1509 PropertyManager->Tie(
"ic/vt-fps",
this,
1512 PropertyManager->Tie(
"ic/vw-bx-fps",
this,
1514 PropertyManager->Tie(
"ic/vw-by-fps",
this,
1516 PropertyManager->Tie(
"ic/vw-bz-fps",
this,
1518 PropertyManager->Tie(
"ic/vw-north-fps",
this,
1520 PropertyManager->Tie(
"ic/vw-east-fps",
this,
1522 PropertyManager->Tie(
"ic/vw-down-fps",
this,
1524 PropertyManager->Tie(
"ic/vw-mag-fps",
this,
1527 PropertyManager->Tie(
"ic/vw-dir-deg",
this,
1531 PropertyManager->Tie(
"ic/roc-fps",
this,
1534 PropertyManager->Tie(
"ic/u-fps",
this,
1537 PropertyManager->Tie(
"ic/v-fps",
this,
1540 PropertyManager->Tie(
"ic/w-fps",
this,
1543 PropertyManager->Tie(
"ic/vn-fps",
this,
1546 PropertyManager->Tie(
"ic/ve-fps",
this,
1549 PropertyManager->Tie(
"ic/vd-fps",
this,
1552 PropertyManager->Tie(
"ic/gamma-rad",
this,
1555 PropertyManager->Tie(
"ic/alpha-rad",
this,
1558 PropertyManager->Tie(
"ic/theta-rad",
this,
1561 PropertyManager->Tie(
"ic/beta-rad",
this,
1564 PropertyManager->Tie(
"ic/phi-rad",
this,
1567 PropertyManager->Tie(
"ic/psi-true-rad",
this,
1570 PropertyManager->Tie(
"ic/lat-gc-rad",
this,
1573 PropertyManager->Tie(
"ic/long-gc-rad",
this,
1576 PropertyManager->Tie(
"ic/p-rad_sec",
this,
1579 PropertyManager->Tie(
"ic/q-rad_sec",
this,
1582 PropertyManager->Tie(
"ic/r-rad_sec",
this,
1585 PropertyManager->Tie(
"ic/lat-geod-rad",
this,
1588 PropertyManager->Tie(
"ic/lat-geod-deg",
this,
1591 PropertyManager->Tie(
"ic/geod-alt-ft", &position,
1594 PropertyManager->Tie(
"ic/targetNlf",
this,
1618void FGInitialCondition::Debug(
int from)
1620 if (debug_lvl <= 0)
return;
1622 if (debug_lvl & 1) {
1624 if (debug_lvl & 2 ) {
1625 FGLogging log(LogLevel::DEBUG);
1626 if (from == 0) log <<
"Instantiated: FGInitialCondition\n";
1627 if (from == 1) log <<
"Destroyed: FGInitialCondition\n";
1629 if (debug_lvl & 4 ) {
1631 if (debug_lvl & 8 ) {
1633 if (debug_lvl & 16) {
1635 if (debug_lvl & 64) {
Element * FindElement(const std::string &el="")
Searches for a specified element.
const std::string & GetName(void) const
Retrieves the element name.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
double FindElementValueAsNumberConvertTo(const std::string &el, const std::string &target_units)
Searches for the named element and converts and returns the data belonging to it.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
double GetDataAsNumber(void)
Converts the element data to a number.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
This class implements a 3 element column vector.
double Magnitude(void) const
Length of the vector.
FGColumnVector3 & Normalize(void)
Normalize.
Encapsulates the JSBSim simulation executive.
std::shared_ptr< FGAircraft > GetAircraft(void) const
Returns the FGAircraft pointer.
const SGPath & GetFullAircraftPath(void)
Retrieves the full aircraft path name.
std::shared_ptr< FGPropagate > GetPropagate(void) const
Returns the FGPropagate pointer.
std::shared_ptr< FGInertial > GetInertial(void) const
Returns the FGInertial pointer.
std::shared_ptr< FGAuxiliary > GetAuxiliary(void) const
Returns the FGAuxiliary pointer.
std::shared_ptr< FGAccelerations > GetAccelerations(void) const
Returns the FGAccelerations pointer.
void SetPsiRadIC(double psi)
Sets the initial heading angle.
double GetPRadpsIC() const
Gets the initial body axis roll rate.
double GetVNorthFpsIC(void) const
Gets the initial local frame X (North) velocity.
void SetThetaDegIC(double theta)
Sets pitch angle initial condition in degrees.
void SetVequivalentKtsIC(double ve)
Set equivalent airspeed initial condition in knots.
double GetPhiRadIC(void) const
Gets the initial roll angle.
double GetVBodyFpsIC(void) const
Gets the initial body axis Y velocity.
double GetVEastFpsIC(void) const
Gets the initial local frame Y (East) velocity.
double GetLatitudeDegIC(void) const
Gets the initial latitude.
void SetWindDownKtsIC(double wD)
Sets the initial wind downward speed.
void ResetIC(double u0, double v0, double w0, double p0, double q0, double r0, double alpha0, double beta0, double phi0, double theta0, double psi0, double latitudeRad0, double longitudeRad0, double altitudeAGL0, double gamma0)
Resets the IC data structure to new values.
double GetVgroundFpsIC(void) const
Gets the initial ground velocity.
double GetLongitudeRadIC(void) const
Gets the initial longitude.
double GetFlightPathAngleDegIC(void) const
Gets the initial flight path angle.
double GetThetaDegIC(void) const
Gets the initial pitch angle.
double GetVgroundKtsIC(void) const
Gets the initial ground speed.
void SetUBodyFpsIC(double ubody)
Sets the initial body axis X velocity.
void SetWindMagKtsIC(double mag)
Sets the initial total wind speed.
double GetPhiDegIC(void) const
Gets the initial roll angle.
void InitializeIC(void)
Initialize the initial conditions to default values.
double GetAltitudeASLFtIC(void) const
Gets the initial altitude above sea level.
void SetClimbRateFpmIC(double roc)
Sets the climb rate initial condition in feet/minute.
double GetWindNFpsIC(void) const
Gets the initial wind velocity in local frame.
void SetFlightPathAngleRadIC(double gamma)
Sets the initial flight path angle.
void SetWBodyFpsIC(double wbody)
Sets the initial body axis Z velocity.
double GetTargetNlfIC(void) const
Gets the target normal load factor set from IC.
void SetMachIC(double mach)
Set mach initial condition.
void SetVtrueKtsIC(double vtrue)
Set true airspeed initial condition in knots.
void SetBetaRadIC(double beta)
Sets the initial sideslip angle.
double GetWindEFpsIC(void) const
Gets the initial wind velocity in local frame.
double GetTerrainElevationFtIC(void) const
Gets the initial terrain elevation.
void SetWindNEDFpsIC(double wN, double wE, double wD)
Sets the initial wind velocity.
void SetCrossWindKtsIC(double cross)
Sets the initial crosswind speed.
void SetVBodyFpsIC(double vbody)
Sets the initial body axis Y velocity.
void SetLongitudeRadIC(double lon)
Sets the initial longitude.
void SetAlphaDegIC(double a)
Sets angle of attack initial condition in degrees.
void SetPRadpsIC(double P)
Sets the initial body axis roll rate.
double GetVDownFpsIC(void) const
Gets the initial local frame Z (Down) velocity.
double GetVcalibratedKtsIC(void) const
Gets the initial calibrated airspeed.
double GetWindDirDegIC(void) const
Gets the initial wind direction.
void SetFlightPathAngleDegIC(double gamma)
Sets the flight path angle initial condition in degrees.
double GetWBodyFpsIC(void) const
Gets the initial body axis Z velocity.
double GetBetaDegIC(void) const
Gets the initial sideslip angle.
FGColumnVector3 GetWindNEDFpsIC(void) const
Gets the initial wind velocity in the NED local frame.
void SetVgroundKtsIC(double vg)
Set ground speed initial condition in knots.
void SetLongitudeDegIC(double lon)
Sets the initial longitude.
double GetClimbRateFpsIC(void) const
Gets the initial climb rate.
void SetGeodLatitudeRadIC(double glat)
Sets the initial geodetic latitude.
void SetAltitudeAGLFtIC(double agl)
Sets the initial Altitude above ground level.
FGInitialCondition(FGFDMExec *fdmex)
Constructor.
~FGInitialCondition()
Destructor.
double GetWindMagFpsIC(void) const
Gets the initial total wind velocity in feet/sec.
double GetAltitudeAGLFtIC(void) const
Gets the initial altitude above ground level.
double GetMachIC(void) const
Gets the initial mach.
void SetThetaRadIC(double theta)
Sets the initial pitch angle.
double GetVtrueFpsIC(void) const
Gets the initial true velocity.
double GetGeodLatitudeDegIC(void) const
Gets the initial geodetic latitude.
void SetTerrainElevationFtIC(double elev)
Sets the initial terrain elevation.
double GetRRadpsIC() const
Gets the initial body axis yaw rate.
double GetAlphaRadIC(void) const
Gets the initial angle of attack.
double GetAlphaDegIC(void) const
Gets the initial angle of attack.
void SetClimbRateFpsIC(double roc)
Sets the initial climb rate.
void SetTargetNlfIC(double nlf)
Sets the target normal load factor.
void SetVtrueFpsIC(double vt)
Sets the initial true airspeed.
void SetPsiDegIC(double psi)
Sets the heading angle initial condition in degrees.
void SetAlphaRadIC(double alpha)
Sets the initial angle of attack.
double GetGeodLatitudeRadIC(void) const
Gets the initial geodetic latitude.
void SetHeadWindKtsIC(double head)
Sets the initial headwind velocity.
void SetRRadpsIC(double R)
Sets the initial body axis yaw rate.
void SetQRadpsIC(double Q)
Sets the initial body axis pitch rate.
double GetUBodyFpsIC(void) const
Gets the initial body axis X velocity.
double GetQRadpsIC() const
Gets the initial body axis pitch rate.
void SetVDownFpsIC(double vd)
Sets the initial local axis down velocity.
void SetLatitudeRadIC(double lat)
Sets the initial latitude.
void SetGeodLatitudeDegIC(double glat)
Sets the initial geodetic latitude.
void SetVcalibratedKtsIC(double vc)
Set calibrated airspeed initial condition in knots.
double GetVequivalentKtsIC(void) const
Gets the initial equivalent airspeed.
void SetPhiDegIC(double phi)
Sets the roll angle initial condition in degrees.
void SetBetaDegIC(double b)
Sets angle of sideslip initial condition in degrees.
double GetFlightPathAngleRadIC(void) const
Gets the initial flight path angle.
double GetPsiRadIC(void) const
Gets the initial heading angle.
bool Load(const SGPath &rstname, bool useAircraftPath=true)
Loads the initial conditions.
void SetWindDirDegIC(double dir)
Sets the initial wind direction.
double GetClimbRateFpmIC(void) const
Gets the initial climb rate.
double GetThetaRadIC(void) const
Gets the initial pitch angle.
void SetVNorthFpsIC(double vn)
Sets the initial local axis north velocity.
void SetPhiRadIC(double phi)
Sets the initial roll angle.
double GetWindUFpsIC(void) const
Gets the initial body axis X wind velocity.
void SetLatitudeDegIC(double lat)
Sets the initial latitude.
double GetWindVFpsIC(void) const
Gets the initial body axis Y wind velocity.
void SetAltitudeASLFtIC(double altitudeASL)
Sets the altitude above sea level initial condition in feet.
void SetWindMagFpsIC(double mag)
Sets the initial total wind speed.
double GetVtrueKtsIC(void) const
Gets the initial true velocity.
double GetPsiDegIC(void) const
Gets the initial heading angle.
double GetLatitudeRadIC(void) const
Gets the initial latitude.
double GetWindDFpsIC(void) const
Gets the initial wind velocity in local frame.
void SetVEastFpsIC(double ve)
Sets the initial local axis east velocity.
void SetVgroundFpsIC(double vg)
Sets the initial ground speed.
double GetWindWFpsIC(void) const
Gets the initial body axis Z wind velocity.
double GetBetaRadIC(void) const
Gets the initial angle of sideslip.
double GetLongitudeDegIC(void) const
Gets the initial longitude.
FGLocation holds an arbitrary location in the Earth centered Earth fixed reference frame (ECEF).
void SetEllipse(double semimajor, double semiminor)
Sets the semimajor and semiminor axis lengths for this planet.
void SetLongitude(double longitude)
Set the longitude.
const FGMatrix33 & GetTl2ec(void) const
Transform matrix from local horizontal to earth centered frame.
double GetLatitude() const
Get the GEOCENTRIC latitude in radians.
const FGMatrix33 & GetTec2l(void) const
Transform matrix from the earth centered to local horizontal frame.
double GetGeodLatitudeRad(void) const
Get the GEODETIC latitude in radians.
double GetLongitude() const
Get the longitude.
void SetLatitude(double latitude)
Set the GEOCENTRIC latitude.
double GetRadius() const
Get the distance from the center of the earth in feet.
double GetSeaLevelRadius(void) const
Get the sea level radius in feet below the current location.
void SetRadius(double radius)
Set the distance from the center of the earth.
double GetGeodAltitude(void) const
Gets the geodetic altitude in feet.
void SetPositionGeodetic(double lon, double lat, double height)
Sets the longitude, latitude and the distance above the reference spheroid.
Handles matrix math operations.
FGMatrix33 Transposed(void) const
Transposed matrix.
Models the Quaternion representation of rotations.
double GetSinEuler(int i) const
Retrieves sine of the given euler angle.
double GetCosEuler(int i) const
Retrieves cosine of the given euler angle.
const FGMatrix33 & GetTInv(void) const
Backward transformation matrix.
const FGColumnVector3 & GetEuler(void) const
Retrieves the Euler angles.
const FGMatrix33 & GetT(void) const
Transformation matrix.
Main namespace for the JSBSim Flight Dynamics Model.
double DotProduct(const FGColumnVector3 &v1, const FGColumnVector3 &v2)
Dot product of two vectors Compute and return the euclidean dot (or scalar) product of two vectors v1...