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