-
Notifications
You must be signed in to change notification settings - Fork 468
/
Copy pathFGInertial.cpp
236 lines (189 loc) · 7.67 KB
/
FGInertial.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGInertial.cpp
Author: Jon S. Berndt
Date started: 09/13/00
Purpose: Encapsulates the inertial frame forces (coriolis and centrifugal)
------------- Copyright (C) 2000 Jon S. Berndt ([email protected]) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be
found on the world wide web at http://www.gnu.org.
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGInertial.h"
#include "input_output/FGXMLElement.h"
using namespace std;
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGInertial::FGInertial(FGFDMExec* fgex)
: FGModel(fgex)
{
Name = "FGInertial";
// Earth defaults
double RotationRate = 0.00007292115;
GM = 14.0764417572E15; // WGS84 value
J2 = 1.08262982E-03; // WGS84 value for J2
a = 20925646.32546; // WGS84 semimajor axis length in feet
b = 20855486.5951; // WGS84 semiminor axis length in feet
gravType = gtWGS84;
// Lunar defaults
/*
double RotationRate = 0.0000026617;
GM = 1.7314079E14; // Lunar GM
J2 = 2.033542482111609E-4; // value for J2
a = 5702559.05; // semimajor axis length in feet
b = 5695439.63; // semiminor axis length in feet
*/
vOmegaPlanet = { 0.0, 0.0, RotationRate };
GroundCallback.reset(new FGDefaultGroundCallback(a, b));
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGInertial::~FGInertial(void)
{
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGInertial::Load(Element* el)
{
if (!Upload(el, true)) return false;
if (el->FindElement("semimajor_axis"))
a = el->FindElementValueAsNumberConvertTo("semimajor_axis", "FT");
if (el->FindElement("semiminor_axis"))
b = el->FindElementValueAsNumberConvertTo("semiminor_axis", "FT");
if (el->FindElement("rotation_rate")) {
double RotationRate = el->FindElementValueAsNumberConvertTo("rotation_rate", "RAD/SEC");
vOmegaPlanet = {0., 0., RotationRate};
}
if (el->FindElement("GM"))
GM = el->FindElementValueAsNumberConvertTo("GM", "FT3/SEC2");
if (el->FindElement("J2"))
J2 = el->FindElementValueAsNumber("J2"); // Dimensionless
GroundCallback->SetEllipse(a, b);
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGInertial::Run(bool Holding)
{
// Fast return if we have nothing to do ...
if (FGModel::Run(Holding)) return true;
if (Holding) return false;
// Gravitation accel
switch (gravType) {
case gtStandard:
{
double radius = in.Position.GetRadius();
vGravAccel = -(GetGAccel(radius) / radius) * in.Position;
}
break;
case gtWGS84:
vGravAccel = GetGravityJ2(in.Position);
break;
}
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGInertial::GetGAccel(double r) const
{
return GM/(r*r);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// Calculate the WGS84 gravitation value in ECEF frame. Pass in the ECEF
// position via the position parameter. The J2Gravity value returned is in ECEF
// frame, and therefore may need to be expressed (transformed) in another frame,
// depending on how it is used. See Stevens and Lewis eqn. 1.4-16.
FGColumnVector3 FGInertial::GetGravityJ2(const FGLocation& position) const
{
FGColumnVector3 J2Gravity;
// Gravitation accel
double r = position.GetRadius();
double sinLat = position.GetSinLatitude();
double adivr = a/r;
double preCommon = 1.5*J2*adivr*adivr;
double xy = 1.0 - 5.0*(sinLat*sinLat);
double z = 3.0 - 5.0*(sinLat*sinLat);
double GMOverr2 = GM/(r*r);
J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r);
J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r);
J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon * z)) * position(eZ)/r);
return J2Gravity;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGInertial::SetAltitudeAGL(FGLocation& location, double altitudeAGL)
{
FGLocation contact;
FGColumnVector3 vDummy;
GroundCallback->GetAGLevel(location, contact, vDummy, vDummy, vDummy);
double groundHeight = contact.GetGeodAltitude();
double longitude = location.GetLongitude();
double geodLat = location.GetGeodLatitudeRad();
location.SetPositionGeodetic(longitude, geodLat,
groundHeight + altitudeAGL);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGInertial::bind(void)
{
PropertyManager->Tie("inertial/sea-level-radius_ft", &in.Position,
&FGLocation::GetSeaLevelRadius);
PropertyManager->Tie("simulation/gravity-model", &gravType);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGInertial::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGInertial" << endl;
if (from == 1) cout << "Destroyed: FGInertial" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
}
}
}
}