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