39#include "FGInertial.h"
40#include "input_output/FGXMLElement.h"
41#include "input_output/FGLog.h"
42#include "GeographicLib/Geodesic.hpp"
53FGInertial::FGInertial(FGFDMExec* fgex)
59 double RotationRate = 0.00007292115;
60 GM = 14.0764417572E15;
75 vOmegaPlanet = { 0.0, 0.0, RotationRate };
76 GroundCallback = std::make_unique<FGDefaultGroundCallback>(a, b);
85FGInertial::~FGInertial(
void)
92bool FGInertial::Load(Element* el)
94 if (!Upload(el,
true))
return false;
96 Name = el->GetAttributeValue(
"name");
98 if (el->FindElement(
"semimajor_axis"))
99 a = el->FindElementValueAsNumberConvertTo(
"semimajor_axis",
"FT");
100 else if (el->FindElement(
"equatorial_radius"))
101 a = el->FindElementValueAsNumberConvertTo(
"equatorial_radius",
"FT");
102 if (el->FindElement(
"semiminor_axis"))
103 b = el->FindElementValueAsNumberConvertTo(
"semiminor_axis",
"FT");
104 else if (el->FindElement(
"polar_radius"))
105 b = el->FindElementValueAsNumberConvertTo(
"polar_radius",
"FT");
109 GeographicLib::Geodesic geod(a, 1.-b/a);
111 if (el->FindElement(
"rotation_rate")) {
112 double RotationRate = el->FindElementValueAsNumberConvertTo(
"rotation_rate",
"RAD/SEC");
113 vOmegaPlanet = {0., 0., RotationRate};
115 if (el->FindElement(
"GM"))
116 GM = el->FindElementValueAsNumberConvertTo(
"GM",
"FT3/SEC2");
117 if (el->FindElement(
"J2"))
118 J2 = el->FindElementValueAsNumber(
"J2");
120 GroundCallback->SetEllipse(a, b);
124 FGLogging log(LogLevel::WARN);
125 if (a != b && J2 == 0.0)
126 log <<
"Gravitational constant J2 is null for a non-spherical planet." << endl;
127 if (a == b && J2 != 0.0)
128 log <<
"Gravitational constant J2 is non-zero for a spherical planet." << endl;
138bool FGInertial::Run(
bool Holding)
141 if (FGModel::Run(Holding))
return true;
142 if (Holding)
return false;
148 double radius = in.Position.GetRadius();
149 vGravAccel = -(GetGAccel(radius) / radius) * in.Position;
153 vGravAccel = GetGravityJ2(in.Position);
178 Down = GetGravityJ2(location);
179 Down -= vOmegaPlanet*(vOmegaPlanet*sea_level);}
185 return FGMatrix33{North(eX), East(eX), Down(eX),
186 North(eY), East(eY), Down(eY),
187 North(eZ), 0.0, Down(eZ)};
192double FGInertial::GetGAccel(
double r)
const
204FGColumnVector3 FGInertial::GetGravityJ2(
const FGLocation& position)
const
206 FGColumnVector3 J2Gravity;
209 double r = position.GetRadius();
210 double sinLat = sin(position.GetLatitude());
213 double preCommon = 1.5*J2*adivr*adivr;
214 double xy = 1.0 - 5.0*(sinLat*sinLat);
215 double z = 3.0 - 5.0*(sinLat*sinLat);
216 double GMOverr2 = GM/(r*r);
218 J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r);
219 J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r);
220 J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon * z)) * position(eZ)/r);
227void FGInertial::SetAltitudeAGL(
FGLocation& location,
double altitudeAGL)
232 GroundCallback->GetAGLevel(location, contact, vDummy, vDummy, vDummy);
237 groundHeight + altitudeAGL);
242void FGInertial::SetGravityType(
int gt)
248 case eGravType::gtStandard:
250 log <<
"Standard gravity model has been set for a non-spherical planet" << endl;
252 case eGravType::gtWGS84:
254 log <<
"WGS84 gravity model has been set without specifying the J2 gravitational constant." << endl;
262void FGInertial::bind(
void)
264 PropertyManager->Tie(
"inertial/sea-level-radius_ft", &in.Position,
265 &FGLocation::GetSeaLevelRadius);
266 PropertyManager->Tie(
"simulation/gravity-model",
this, &FGInertial::GetGravityType,
267 &FGInertial::SetGravityType);
289void FGInertial::Debug(
int from)
291 if (debug_lvl <= 0)
return;
294 FGLogging log(LogLevel::DEBUG);
297 log << endl <<
" Planet " << Name << endl
298 <<
" Semi major axis: " << a << endl
299 <<
" Semi minor axis: " << b << endl
300 <<
" Rotation rate : " << scientific << vOmegaPlanet(eZ) << endl
301 <<
" GM : " << GM << endl
302 <<
" J2 : " << J2 << endl << defaultfloat << endl;
305 if (debug_lvl & 2 ) {
306 FGLogging log(LogLevel::DEBUG);
307 if (from == 0) log <<
"Instantiated: FGInertial" << endl;
308 if (from == 1) log <<
"Destroyed: FGInertial" << endl;
310 if (debug_lvl & 4 ) {
312 if (debug_lvl & 8 ) {
314 if (debug_lvl & 16) {
316 if (debug_lvl & 64) {
This class implements a 3 element column vector.
FGColumnVector3 & Normalize(void)
Normalize.
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.
double GetGeodLatitudeRad(void) const
Get the GEODETIC latitude in radians.
double GetLongitude() const
Get the longitude.
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.
Main namespace for the JSBSim Flight Dynamics Model.