JSBSim Flight Dynamics Model 1.2.4 (07 Feb 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGMassBalance.cpp
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGMassBalance.cpp
4 Author: Jon S. Berndt
5 Date started: 09/12/2000
6 Purpose: This module models weight and balance
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
30This class models the change in weight and balance of the aircraft due to fuel
31burnoff, etc.
32
33HISTORY
34--------------------------------------------------------------------------------
3509/12/2000 JSB Created
36
37%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38INCLUDES
39%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40
41#include <iomanip>
42
43#include "FGMassBalance.h"
44#include "FGFDMExec.h"
45#include "input_output/FGXMLElement.h"
46
47using namespace std;
48
49namespace JSBSim {
50
51/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52CLASS IMPLEMENTATION
53%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54
55
56FGMassBalance::FGMassBalance(FGFDMExec* fdmex)
57 : FGModel(fdmex)
58{
59 Name = "FGMassBalance";
60 Weight = EmptyWeight = Mass = 0.0;
61
62 vbaseXYZcg.InitMatrix();
63 vXYZcg.InitMatrix();
64 vLastXYZcg.InitMatrix();
65 vDeltaXYZcg.InitMatrix();
66 baseJ.InitMatrix();
67 mJ.InitMatrix();
68 mJinv.InitMatrix();
69 pmJ.InitMatrix();
70 Propagate = fdmex->GetPropagate();
71
72 bind();
73
74 Debug(0);
75}
76
77//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78
79FGMassBalance::~FGMassBalance()
80{
81 for(auto pm: PointMasses) delete pm;
82
83 Debug(1);
84}
85
86//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87
88bool FGMassBalance::InitModel(void)
89{
90 if (!FGModel::InitModel()) return false;
91
92 vLastXYZcg.InitMatrix();
93 vDeltaXYZcg.InitMatrix();
94
95 return true;
96}
97
98//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99
100static FGMatrix33 ReadInertiaMatrix(Element* document)
101{
102 double bixx, biyy, bizz, bixy, bixz, biyz;
103
104 bixx = biyy = bizz = bixy = bixz = biyz = 0.0;
105 if (document->FindElement("ixx"))
106 bixx = document->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
107 if (document->FindElement("iyy"))
108 biyy = document->FindElementValueAsNumberConvertTo("iyy", "SLUG*FT2");
109 if (document->FindElement("izz"))
110 bizz = document->FindElementValueAsNumberConvertTo("izz", "SLUG*FT2");
111 if (document->FindElement("ixy"))
112 bixy = document->FindElementValueAsNumberConvertTo("ixy", "SLUG*FT2");
113 if (document->FindElement("ixz"))
114 bixz = document->FindElementValueAsNumberConvertTo("ixz", "SLUG*FT2");
115 if (document->FindElement("iyz"))
116 biyz = document->FindElementValueAsNumberConvertTo("iyz", "SLUG*FT2");
117
118 // Transform the inertia products from the structural frame to the body frame
119 // and create the inertia matrix.
120 if (document->GetAttributeValue("negated_crossproduct_inertia") == string("false"))
121 return FGMatrix33( bixx, bixy, -bixz,
122 bixy, biyy, biyz,
123 -bixz, biyz, bizz );
124 else
125 return FGMatrix33( bixx, -bixy, bixz,
126 -bixy, biyy, -biyz,
127 bixz, -biyz, bizz );
128}
129
130//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131
132bool FGMassBalance::Load(Element* document)
133{
134 string element_name = "";
135
136 Name = "Mass Properties Model: " + document->GetAttributeValue("name");
137
138 // Perform base class Pre-Load
139 if (!FGModel::Upload(document, true))
140 return false;
141
142 SetAircraftBaseInertias(ReadInertiaMatrix(document));
143 if (document->FindElement("emptywt")) {
144 EmptyWeight = document->FindElementValueAsNumberConvertTo("emptywt", "LBS");
145 }
146
147 Element *element = document->FindElement("location");
148 while (element) {
149 element_name = element->GetAttributeValue("name");
150 if (element_name == "CG") vbaseXYZcg = element->FindElementTripletConvertTo("IN");
151 element = document->FindNextElement("location");
152 }
153
154// Find all POINTMASS elements that descend from this METRICS branch of the
155// config file.
156
157 element = document->FindElement("pointmass");
158 while (element) {
159 AddPointMass(element);
160 element = document->FindNextElement("pointmass");
161 }
162
163 double ChildFDMWeight = 0.0;
164 for (size_t fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
165 if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
166 }
167
168 Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
169 + in.GasMass*slugtolb + ChildFDMWeight;
170
171 Mass = lbtoslug*Weight;
172
173 PostLoad(document, FDMExec);
174
175 Debug(2);
176 return true;
177}
178
179//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181bool FGMassBalance::Run(bool Holding)
182{
183 double denom, k1, k2, k3, k4, k5, k6;
184 double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
185
186 if (FGModel::Run(Holding)) return true;
187 if (Holding) return false;
188
189 RunPreFunctions();
190
191 double ChildFDMWeight = 0.0;
192 for (size_t fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
193 if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
194 }
195
196 Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
197 + in.GasMass*slugtolb + ChildFDMWeight;
198
199 Mass = lbtoslug*Weight;
200
201// Calculate new CG
202
203 vXYZcg = (EmptyWeight*vbaseXYZcg
204 + GetPointMassMoment()
205 + in.TanksMoment
206 + in.GasMoment) / Weight;
207
208 // Track frame-by-frame delta CG, and move the EOM-tracked location
209 // by this amount.
210 if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg;
211 vDeltaXYZcg = vXYZcg - vLastXYZcg;
212 vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg);
213 vLastXYZcg = vXYZcg;
214
215 // Compensate displacements of the structural frame when the mass distribution
216 // is modified while the aircraft is in contact with the ground.
217 if (FDMExec->GetHoldDown() || in.WOW)
218 Propagate->NudgeBodyLocation(vDeltaXYZcgBody);
219
220// Calculate new total moments of inertia
221
222 // At first it is the base configuration inertia matrix ...
223 mJ = baseJ;
224 // ... with the additional term originating from the parallel axis theorem.
225 mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
226 // Then add the contributions from the additional pointmasses.
227 mJ += CalculatePMInertias();
228 mJ += in.TankInertia;
229 mJ += in.GasInertia;
230
231 Ixx = mJ(1,1);
232 Iyy = mJ(2,2);
233 Izz = mJ(3,3);
234 Ixy = -mJ(1,2);
235 Ixz = -mJ(1,3);
236 Iyz = -mJ(2,3);
237
238// Calculate inertia matrix inverse (ref. Stevens and Lewis, "Flight Control &
239// Simulation")
240
241 k1 = (Iyy*Izz - Iyz*Iyz);
242 k2 = (Iyz*Ixz + Ixy*Izz);
243 k3 = (Ixy*Iyz + Iyy*Ixz);
244
245 denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
246 k1 = k1*denom;
247 k2 = k2*denom;
248 k3 = k3*denom;
249 k4 = (Izz*Ixx - Ixz*Ixz)*denom;
250 k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
251 k6 = (Ixx*Iyy - Ixy*Ixy)*denom;
252
253 mJinv = { k1, k2, k3,
254 k2, k4, k5,
255 k3, k5, k6 };
256
257 RunPostFunctions();
258
259 Debug(0);
260
261 return false;
262}
263
264//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265
266void FGMassBalance::AddPointMass(Element* el)
267{
268 Element* loc_element = el->FindElement("location");
269 string pointmass_name = el->GetAttributeValue("name");
270 if (!loc_element) {
271 stringstream s;
272 s << el->ReadFrom() << "Pointmass " << pointmass_name
273 << " has no location.";
274 cerr << endl << s.str() << endl;
275 throw BaseException(s.str());
276 }
277
278 double w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
279 FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN");
280
281 PointMass *pm = new PointMass(w, vXYZ);
282 pm->SetName(pointmass_name);
283
284 Element* form_element = el->FindElement("form");
285 if (form_element) {
286 double radius=0, length=0;
287 string shape = form_element->GetAttributeValue("shape");
288 Element* radius_element = form_element->FindElement("radius");
289 Element* length_element = form_element->FindElement("length");
290 if (radius_element) radius = form_element->FindElementValueAsNumberConvertTo("radius", "FT");
291 if (length_element) length = form_element->FindElementValueAsNumberConvertTo("length", "FT");
292 if (shape == "tube") {
293 pm->SetPointMassShapeType(PointMass::esTube);
294 pm->SetRadius(radius);
295 pm->SetLength(length);
296 pm->CalculateShapeInertia();
297 } else if (shape == "cylinder") {
298 pm->SetPointMassShapeType(PointMass::esCylinder);
299 pm->SetRadius(radius);
300 pm->SetLength(length);
301 pm->CalculateShapeInertia();
302 } else if (shape == "sphere") {
303 pm->SetPointMassShapeType(PointMass::esSphere);
304 pm->SetRadius(radius);
305 pm->CalculateShapeInertia();
306 } else if (shape == "ball") {
307 pm->SetPointMassShapeType(PointMass::esBall);
308 pm->SetRadius(radius);
309 pm->CalculateShapeInertia();
310 } else {
311 }
312 }
313 else {
314 pm->SetPointMassShapeType(PointMass::esUnspecified);
315 pm->SetPointMassMoI(ReadInertiaMatrix(el));
316 }
317
318 pm->bind(PropertyManager.get(), PointMasses.size());
319 PointMasses.push_back(pm);
320}
321
322//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323
324double FGMassBalance::GetTotalPointMassWeight(void) const
325{
326 double PM_total_weight = 0.0;
327
328 for(auto pm: PointMasses)
329 PM_total_weight += pm->Weight;
330
331 return PM_total_weight;
332}
333
334//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335
336const FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
337{
338 PointMassCG.InitMatrix();
339
340 for (auto pm: PointMasses)
341 PointMassCG += pm->Weight * pm->Location;
342
343 return PointMassCG;
344}
345
346//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347
348const FGMatrix33& FGMassBalance::CalculatePMInertias(void)
349{
350 if (PointMasses.empty()) return pmJ;
351
352 pmJ.InitMatrix();
353
354 for (auto pm: PointMasses) {
355 pmJ += GetPointmassInertia( lbtoslug * pm->Weight, pm->Location );
356 pmJ += pm->GetPointMassInertia();
357 }
358
359 return pmJ;
360}
361
362//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363
364FGColumnVector3 FGMassBalance::StructuralToBody(const FGColumnVector3& r) const
365{
366 // Under the assumption that in the structural frame the:
367 //
368 // - X-axis is directed afterwards,
369 // - Y-axis is directed towards the right,
370 // - Z-axis is directed upwards,
371 //
372 // (as documented in http://jsbsim.sourceforge.net/JSBSimCoordinates.pdf)
373 // we have to subtract first the center of gravity of the plane which
374 // is also defined in the structural frame:
375 //
376 // FGColumnVector3 cgOff = r - vXYZcg;
377 //
378 // Next, we do a change of units:
379 //
380 // cgOff *= inchtoft;
381 //
382 // And then a 180 degree rotation is done about the Y axis so that the:
383 //
384 // - X-axis is directed forward,
385 // - Y-axis is directed towards the right,
386 // - Z-axis is directed downward.
387 //
388 // This is needed because the structural and body frames are 180 degrees apart.
389
390 return FGColumnVector3(inchtoft*(vXYZcg(1)-r(1)),
391 inchtoft*(r(2)-vXYZcg(2)),
392 inchtoft*(vXYZcg(3)-r(3)));
393}
394
395//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396
397void FGMassBalance::bind(void)
398{
399 PropertyManager->Tie("inertia/mass-slugs", this, &FGMassBalance::GetMass);
400 PropertyManager->Tie("inertia/weight-lbs", this, &FGMassBalance::GetWeight);
401 PropertyManager->Tie("inertia/empty-weight-lbs", this, &FGMassBalance::GetEmptyWeight);
402 PropertyManager->Tie("inertia/cg-x-in", this, eX, &FGMassBalance::GetXYZcg);
403 PropertyManager->Tie("inertia/cg-y-in", this, eY, &FGMassBalance::GetXYZcg);
404 PropertyManager->Tie("inertia/cg-z-in", this, eZ, &FGMassBalance::GetXYZcg);
405 PropertyManager->Tie("inertia/ixx-slugs_ft2", this, &FGMassBalance::GetIxx);
406 PropertyManager->Tie("inertia/iyy-slugs_ft2", this, &FGMassBalance::GetIyy);
407 PropertyManager->Tie("inertia/izz-slugs_ft2", this, &FGMassBalance::GetIzz);
408 PropertyManager->Tie("inertia/ixy-slugs_ft2", this, &FGMassBalance::GetIxy);
409 PropertyManager->Tie("inertia/ixz-slugs_ft2", this, &FGMassBalance::GetIxz);
410 PropertyManager->Tie("inertia/iyz-slugs_ft2", this, &FGMassBalance::GetIyz);
411 PropertyManager->Tie<FGMassBalance, int>("inertia/print-mass-properties", this,
412 nullptr, &FGMassBalance::GetMassPropertiesReport);
413}
414
415//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416//
417// This function binds properties for each pointmass object created.
418//
419void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager,
420 unsigned int num) {
421 string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num);
422 PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight,
423 &PointMass::SetPointMassWeight);
424
425 tmp = CreateIndexedPropertyName("inertia/pointmass-location-X-inches", num);
426 PropertyManager->Tie( tmp.c_str(), this, eX, &PointMass::GetPointMassLocation,
427 &PointMass::SetPointMassLocation);
428 tmp = CreateIndexedPropertyName("inertia/pointmass-location-Y-inches", num);
429 PropertyManager->Tie( tmp.c_str(), this, eY, &PointMass::GetPointMassLocation,
430 &PointMass::SetPointMassLocation);
431 tmp = CreateIndexedPropertyName("inertia/pointmass-location-Z-inches", num);
432 PropertyManager->Tie( tmp.c_str(), this, eZ, &PointMass::GetPointMassLocation,
433 &PointMass::SetPointMassLocation);
434}
435
436//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437
438void FGMassBalance::GetMassPropertiesReport(int i)
439{
440 cout << endl << fgblue << highint
441 << " Mass Properties Report (English units: lbf, in, slug-ft^2)"
442 << reset << endl;
443 cout << " " << underon << " Weight CG-X CG-Y"
444 << " CG-Z Ixx Iyy Izz"
445 << " Ixy Ixz Iyz" << underoff << endl;
446 cout.precision(1);
447 cout << highint << setw(34) << left << " Base Vehicle " << normint
448 << right << setw(12) << EmptyWeight
449 << setw(8) << vbaseXYZcg(eX) << setw(8) << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ)
450 << setw(12) << baseJ(1,1) << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3)
451 << setw(12) << baseJ(1,2) << setw(12) << baseJ(1,3) << setw(12) << baseJ(2,3) << endl;
452
453 for (unsigned int i=0;i<PointMasses.size();i++) {
454 PointMass* pm = PointMasses[i];
455 double pmweight = pm->GetPointMassWeight();
456 cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint
457 << right << setw(12) << pmweight << setw(8) << pm->GetLocation()(eX)
458 << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ)
459 << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) << setw(12) << pm->GetPointMassMoI(3,3)
460 << setw(12) << pm->GetPointMassMoI(1,2) << setw(12) << pm->GetPointMassMoI(1,3) << setw(12) << pm->GetPointMassMoI(2,3) << endl;
461 }
462
463 cout << FDMExec->GetPropulsionTankReport();
464
465 cout << " " << underon << setw(136) << " " << underoff << endl;
466 cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight
467 << setw(8) << vXYZcg(eX)
468 << setw(8) << vXYZcg(eY)
469 << setw(8) << vXYZcg(eZ)
470 << setw(12) << mJ(1,1)
471 << setw(12) << mJ(2,2)
472 << setw(12) << mJ(3,3)
473 << setw(12) << mJ(1,2)
474 << setw(12) << mJ(1,3)
475 << setw(12) << mJ(2,3)
476 << normint << endl;
477
478 cout.setf(ios_base::fixed);
479}
480
481//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482// The bitmasked value choices are as follows:
483// unset: In this case (the default) JSBSim would only print
484// out the normally expected messages, essentially echoing
485// the config files as they are read. If the environment
486// variable is not set, debug_lvl is set to 1 internally
487// 0: This requests JSBSim not to output any messages
488// whatsoever.
489// 1: This value explicity requests the normal JSBSim
490// startup messages
491// 2: This value asks for a message to be printed out when
492// a class is instantiated
493// 4: When this value is set, a message is displayed when a
494// FGModel object executes its Run() method
495// 8: When this value is set, various runtime state variables
496// are printed out periodically
497// 16: When set various parameters are sanity checked and
498// a message is printed out when they go out of bounds
499
500void FGMassBalance::Debug(int from)
501{
502 if (debug_lvl <= 0) return;
503
504 if (debug_lvl & 1) { // Standard console startup message output
505 if (from == 2) { // Loading
506 cout << endl << " Mass and Balance:" << endl;
507 cout << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl;
508 cout << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl;
509 cout << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl;
510 cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
511 cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
512 cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
513 cout << " Empty Weight: " << EmptyWeight << " lbm" << endl;
514 cout << " CG (x, y, z): " << vbaseXYZcg << endl;
515 // ToDo: Need to add point mass outputs here
516 for (unsigned int i=0; i<PointMasses.size(); i++) {
517 cout << " Point Mass Object: " << PointMasses[i]->Weight << " lbs. at "
518 << "X, Y, Z (in.): " << PointMasses[i]->Location(eX) << " "
519 << PointMasses[i]->Location(eY) << " "
520 << PointMasses[i]->Location(eZ) << endl;
521 }
522 }
523 }
524 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
525 if (from == 0) cout << "Instantiated: FGMassBalance" << endl;
526 if (from == 1) cout << "Destroyed: FGMassBalance" << endl;
527 }
528 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
529 }
530 if (debug_lvl & 8 ) { // Runtime state variables
531 }
532 if (debug_lvl & 16) { // Sanity checking
533 if (from == 2) {
534 if (EmptyWeight <= 0.0 || EmptyWeight > 1e9)
535 cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl;
536 if (Weight <= 0.0 || Weight > 1e9)
537 cout << "MassBalance::Weight out of bounds: " << Weight << endl;
538 if (Mass <= 0.0 || Mass > 1e9)
539 cout << "MassBalance::Mass out of bounds: " << Mass << endl;
540 }
541 }
542 if (debug_lvl & 64) {
543 if (from == 0) { // Constructor
544 }
545 }
546}
547}
Element * FindElement(const std::string &el="")
Searches for a specified element.
FGColumnVector3 FindElementTripletConvertTo(const std::string &target_units)
Composes a 3-element column vector for the supplied location or orientation.
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.
This class implements a 3 element column vector.
bool GetHoldDown(void) const
Gets the value of the property forces/hold-down.
Definition FGFDMExec.h:616
size_t GetFDMCount(void) const
Gets the number of child FDMs.
Definition FGFDMExec.h:425
auto GetChildFDM(int i) const
Gets a particular child FDM.
Definition FGFDMExec.h:427
Models weight, balance and moment of inertia information.