FlightGear next
FGInertial.cpp
Go to the documentation of this file.
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGInertial.cpp
4 Author: Jon S. Berndt
5 Date started: 09/13/00
6 Purpose: Encapsulates the inertial frame forces (coriolis and centrifugal)
7
8 ------------- Copyright (C) 2000 Jon S. Berndt (jon@jsbsim.org) -------------
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 2 of the License, or (at your option) any
13 later version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along
21 with this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 Further information about the GNU Lesser General Public License can also be
25 found on the world wide web at http://www.gnu.org.
26
27FUNCTIONAL DESCRIPTION
28--------------------------------------------------------------------------------
29
30HISTORY
31--------------------------------------------------------------------------------
3209/13/00 JSB Created
33
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35INCLUDES
36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37
38#include "FGInertial.h"
40
41using namespace std;
42
43namespace JSBSim {
44
45/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
46CLASS IMPLEMENTATION
47%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
48
49
51 : FGModel(fgex)
52{
53 Name = "Earth";
54
55 // Earth defaults
56 double RotationRate = 0.00007292115;
57 GM = 14.0764417572E15; // WGS84 value
58 J2 = 1.08262982E-03; // WGS84 value for J2
59 a = 20925646.32546; // WGS84 semimajor axis length in feet
60 b = 20855486.5951; // WGS84 semiminor axis length in feet
61 gravType = gtWGS84;
62
63 // Lunar defaults
64 /*
65 double RotationRate = 0.0000026617;
66 GM = 1.7314079E14; // Lunar GM
67 J2 = 2.033542482111609E-4; // value for J2
68 a = 5702559.05; // semimajor axis length in feet
69 b = 5695439.63; // semiminor axis length in feet
70 */
71
72 vOmegaPlanet = { 0.0, 0.0, RotationRate };
73 GroundCallback.reset(new FGDefaultGroundCallback(a, b));
74
75 bind();
76
77 Debug(0);
78}
79
80//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81
83{
84 Debug(1);
85}
86
87//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88
90{
91 if (!Upload(el, true)) return false;
92
93 Name = el->GetAttributeValue("name");
94
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};
106 }
107 if (el->FindElement("GM"))
108 GM = el->FindElementValueAsNumberConvertTo("GM", "FT3/SEC2");
109 if (el->FindElement("J2"))
110 J2 = el->FindElementValueAsNumber("J2"); // Dimensionless
111
112 GroundCallback->SetEllipse(a, b);
113
114 // Messages to warn the user about possible inconsistencies.
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;
119
120 Debug(2);
121
122 return true;
123}
124
125//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126
127bool FGInertial::Run(bool Holding)
128{
129 // Fast return if we have nothing to do ...
130 if (FGModel::Run(Holding)) return true;
131 if (Holding) return false;
132
133 // Gravitation accel
134 switch (gravType) {
135 case gtStandard:
136 {
137 double radius = in.Position.GetRadius();
138 vGravAccel = -(GetGAccel(radius) / radius) * in.Position;
139 }
140 break;
141 case gtWGS84:
142 vGravAccel = GetGravityJ2(in.Position);
143 break;
144 }
145
146 return false;
147}
148
149//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150
152{
153 FGColumnVector3 North, Down, East{-location(eY), location(eX), 0.};
154
155 switch (gravType) {
156 case gtStandard:
157 {
158 Down = location;
159 Down *= -1.0;
160 }
161 break;
162 case gtWGS84:
163 {
164 FGLocation sea_level = location;
165 sea_level.SetPositionGeodetic(location.GetLongitude(),
166 location.GetGeodLatitudeRad(), 0.0);
167 Down = GetGravityJ2(location);
168 Down -= vOmegaPlanet*(vOmegaPlanet*sea_level);}
169 }
170 Down.Normalize();
171 East.Normalize();
172 North = East*Down;
173
174 return FGMatrix33{North(eX), East(eX), Down(eX),
175 North(eY), East(eY), Down(eY),
176 North(eZ), 0.0, Down(eZ)};
177}
178
179//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181double FGInertial::GetGAccel(double r) const
182{
183 return GM/(r*r);
184}
185
186//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187//
188// Calculate the WGS84 gravitation value in ECEF frame. Pass in the ECEF
189// position via the position parameter. The J2Gravity value returned is in ECEF
190// frame, and therefore may need to be expressed (transformed) in another frame,
191// depending on how it is used. See Stevens and Lewis eqn. 1.4-16.
192
193FGColumnVector3 FGInertial::GetGravityJ2(const FGLocation& position) const
194{
195 FGColumnVector3 J2Gravity;
196
197 // Gravitation accel
198 double r = position.GetRadius();
199 double sinLat = sin(position.GetLatitude());
200
201 double adivr = a/r;
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);
206
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);
210
211 return J2Gravity;
212}
213
214//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215
216void FGInertial::SetAltitudeAGL(FGLocation& location, double altitudeAGL)
217{
218 FGColumnVector3 vDummy;
219 FGLocation contact;
220 contact.SetEllipse(a, b);
221 GroundCallback->GetAGLevel(location, contact, vDummy, vDummy, vDummy);
222 double groundHeight = contact.GetGeodAltitude();
223 double longitude = location.GetLongitude();
224 double geodLat = location.GetGeodLatitudeRad();
225 location.SetPositionGeodetic(longitude, geodLat,
226 groundHeight + altitudeAGL);
227}
228
229//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230
232{
233 // Messages to warn the user about possible inconsistencies.
234 switch (gt)
235 {
237 if (a != b)
238 cout << "Warning: Standard gravity model has been set for a non-spherical planet" << endl;
239 break;
241 if (J2 == 0.0)
242 cout << "Warning: WGS84 gravity model has been set without specifying the J2 gravitational constant." << endl;
243 }
244
245 gravType = gt;
246}
247
248//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249
250void FGInertial::bind(void)
251{
252 PropertyManager->Tie("inertial/sea-level-radius_ft", &in.Position,
254 PropertyManager->Tie("simulation/gravity-model", this, &FGInertial::GetGravityType,
256}
257
258//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
259// The bitmasked value choices are as follows:
260// unset: In this case (the default) JSBSim would only print
261// out the normally expected messages, essentially echoing
262// the config files as they are read. If the environment
263// variable is not set, debug_lvl is set to 1 internally
264// 0: This requests JSBSim not to output any messages
265// whatsoever.
266// 1: This value explicity requests the normal JSBSim
267// startup messages
268// 2: This value asks for a message to be printed out when
269// a class is instantiated
270// 4: When this value is set, a message is displayed when a
271// FGModel object executes its Run() method
272// 8: When this value is set, various runtime state variables
273// are printed out periodically
274// 16: When set various parameters are sanity checked and
275// a message is printed out when they go out of bounds
276
277void FGInertial::Debug(int from)
278{
279 if (debug_lvl <= 0) return;
280
281 if (debug_lvl & 1) { // Standard console startup message output
282 if (from == 0) {} // Constructor
283 if (from == 2) { // Loading
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;
290 }
291 }
292 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
293 if (from == 0) cout << "Instantiated: FGInertial" << endl;
294 if (from == 1) cout << "Destroyed: FGInertial" << endl;
295 }
296 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
297 }
298 if (debug_lvl & 8 ) { // Runtime state variables
299 }
300 if (debug_lvl & 16) { // Sanity checking
301 }
302 if (debug_lvl & 64) {
303 if (from == 0) { // Constructor
304 }
305 }
306}
307}
double longitude
Definition ADA.cxx:54
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.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Element * FindElement(const std::string &el="")
Searches for a specified element.
This class implements a 3 element column vector.
FGColumnVector3 & Normalize(void)
Normalize.
void SetGravityType(int gt)
Set the gravity type.
bool Run(bool Holding) override
Runs the Inertial model; called by the Executive Can pass in a value indicating if the executive is d...
bool Load(Element *el) override
@ gtStandard
Evaluate gravity using Newton's classical formula assuming the Earth is spherical.
Definition FGInertial.h:156
@ gtWGS84
Evaluate gravity using WGS84 formulas that take the Earth oblateness into account.
Definition FGInertial.h:159
void SetAltitudeAGL(FGLocation &location, double altitudeAGL)
Set the altitude above ground level.
FGInertial(FGFDMExec *)
struct JSBSim::FGInertial::Inputs in
int GetGravityType(void) const
Get the gravity type.
Definition FGInertial.h:163
FGMatrix33 GetTl2ec(const FGLocation &location) const
Transform matrix from the local horizontal frame to earth centered.
static short debug_lvl
Definition FGJSBBase.h:190
FGLocation holds an arbitrary location in the Earth centered Earth fixed reference frame (ECEF).
Definition FGLocation.h:152
double GetGeodAltitude(void) const
Gets the geodetic altitude in feet.
Definition FGLocation.h:279
void SetPositionGeodetic(double lon, double lat, double height)
Sets the longitude, latitude and the distance above the reference spheroid.
double GetLongitude() const
Get the longitude.
Definition FGLocation.h:234
double GetGeodLatitudeRad(void) const
Get the GEODETIC latitude in radians.
Definition FGLocation.h:258
double GetSeaLevelRadius(void) const
Get the sea level radius in feet below the current location.
void SetEllipse(double semimajor, double semiminor)
Sets the semimajor and semiminor axis lengths for this planet.
Handles matrix math operations.
Definition FGMatrix33.h:70
FGPropertyManager * PropertyManager
Definition FGModel.h:117
FGModel(FGFDMExec *)
Constructor.
Definition FGModel.cpp:57
bool Upload(Element *el, bool preLoad)
Uploads this model in memory.
Definition FGModel.cpp:110
std::string Name
Definition FGModel.h:103
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
Definition FGModel.cpp:89
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
short debug_lvl