38 #include "FGInertial.h"
39 #include "input_output/FGXMLElement.h"
50 FGInertial::FGInertial(FGFDMExec* fgex)
56 double RotationRate = 0.00007292115;
57 GM = 14.0764417572E15;
72 vOmegaPlanet = { 0.0, 0.0, RotationRate };
73 GroundCallback.reset(
new FGDefaultGroundCallback(a, b));
82 FGInertial::~FGInertial(
void)
89 bool FGInertial::Load(Element* el)
91 if (!
Upload(el,
true))
return false;
93 Name = el->GetAttributeValue(
"name");
95 if (el->FindElement(
"semimajor_axis"))
96 a = el->FindElementValueAsNumberConvertTo(
"semimajor_axis",
"FT");
97 else if (el->FindElement(
"equatorial_radius"))
98 a = el->FindElementValueAsNumberConvertTo(
"equatorial_radius",
"FT");
99 if (el->FindElement(
"semiminor_axis"))
100 b = el->FindElementValueAsNumberConvertTo(
"semiminor_axis",
"FT");
101 else if (el->FindElement(
"polar_radius"))
102 b = el->FindElementValueAsNumberConvertTo(
"polar_radius",
"FT");
103 if (el->FindElement(
"rotation_rate")) {
104 double RotationRate = el->FindElementValueAsNumberConvertTo(
"rotation_rate",
"RAD/SEC");
105 vOmegaPlanet = {0., 0., RotationRate};
107 if (el->FindElement(
"GM"))
108 GM = el->FindElementValueAsNumberConvertTo(
"GM",
"FT3/SEC2");
109 if (el->FindElement(
"J2"))
110 J2 = el->FindElementValueAsNumber(
"J2");
112 GroundCallback->SetEllipse(a, b);
115 if (a != b && J2 == 0.0)
116 cout <<
"Gravitational constant J2 is null for a non-spherical planet." << endl;
117 if (a == b && J2 != 0.0)
118 cout <<
"Gravitational constant J2 is non-zero for a spherical planet." << endl;
131 if (Holding)
return false;
138 vGravAccel = -(GetGAccel(radius) / radius) * in.Position;
142 vGravAccel = GetGravityJ2(in.Position);
167 Down = GetGravityJ2(location);
168 Down -= vOmegaPlanet*(vOmegaPlanet*sea_level);}
174 return FGMatrix33{North(eX), East(eX), Down(eX),
175 North(eY), East(eY), Down(eY),
176 North(eZ), 0.0, Down(eZ)};
181 double FGInertial::GetGAccel(
double r)
const
193 FGColumnVector3 FGInertial::GetGravityJ2(
const FGLocation& position)
const
195 FGColumnVector3 J2Gravity;
198 double r = position.GetRadius();
199 double sinLat = sin(position.GetLatitude());
202 double preCommon = 1.5*J2*adivr*adivr;
203 double xy = 1.0 - 5.0*(sinLat*sinLat);
204 double z = 3.0 - 5.0*(sinLat*sinLat);
205 double GMOverr2 = GM/(r*r);
207 J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r);
208 J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r);
209 J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon * z)) * position(eZ)/r);
221 GroundCallback->GetAGLevel(location, contact, vDummy, vDummy, vDummy);
226 groundHeight + altitudeAGL);
236 case eGravType::gtStandard:
238 cout <<
"Warning: Standard gravity model has been set for a non-spherical planet" << endl;
240 case eGravType::gtWGS84:
242 cout <<
"Warning: WGS84 gravity model has been set without specifying the J2 gravitational constant." << endl;
250 void FGInertial::bind(
void)
252 PropertyManager->
Tie(
"inertial/sea-level-radius_ft", &in.Position,
277 void FGInertial::Debug(
int from)
279 if (debug_lvl <= 0)
return;
284 cout << endl <<
" Planet " << Name << endl;
285 cout <<
" Semi major axis: " << a << endl;
286 cout <<
" Semi minor axis: " << b << endl;
287 cout <<
" Rotation rate : " << scientific << vOmegaPlanet(eZ) << endl;
288 cout <<
" GM : " << GM << endl;
289 cout <<
" J2 : " << J2 << endl << defaultfloat;
292 if (debug_lvl & 2 ) {
293 if (from == 0) cout <<
"Instantiated: FGInertial" << endl;
294 if (from == 1) cout <<
"Destroyed: FGInertial" << endl;
296 if (debug_lvl & 4 ) {
298 if (debug_lvl & 8 ) {
300 if (debug_lvl & 16) {
302 if (debug_lvl & 64) {