JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
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 
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 
30 This class models the change in weight and balance of the aircraft due to fuel
31 burnoff, etc.
32 
33 HISTORY
34 --------------------------------------------------------------------------------
35 09/12/2000 JSB Created
36 
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40 
41 #include <iomanip>
42 
43 #include "FGMassBalance.h"
44 #include "FGFDMExec.h"
45 #include "input_output/FGXMLElement.h"
46 
47 using namespace std;
48 
49 namespace JSBSim {
50 
51 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 CLASS IMPLEMENTATION
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54 
55 
56 FGMassBalance::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 
79 FGMassBalance::~FGMassBalance()
80 {
81  for(auto pm: PointMasses) delete pm;
82 
83  Debug(1);
84 }
85 
86 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 
88 bool 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 
100 static 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 
132 bool 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 (int 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 
181 bool 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 (int 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 
266 void 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, PointMasses.size());
319  PointMasses.push_back(pm);
320 }
321 
322 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 
324 double 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 
336 const 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 
348 const 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 
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 
397 void FGMassBalance::bind(void)
398 {
399  typedef double (FGMassBalance::*PMF)(int) const;
400  PropertyManager->Tie("inertia/mass-slugs", this,
401  &FGMassBalance::GetMass);
402  PropertyManager->Tie("inertia/weight-lbs", this,
403  &FGMassBalance::GetWeight);
404  PropertyManager->Tie("inertia/empty-weight-lbs", this,
405  &FGMassBalance::GetEmptyWeight);
406  PropertyManager->Tie("inertia/cg-x-in", this,1,
408  PropertyManager->Tie("inertia/cg-y-in", this,2,
410  PropertyManager->Tie("inertia/cg-z-in", this,3,
412  PropertyManager->Tie("inertia/ixx-slugs_ft2", this,
413  &FGMassBalance::GetIxx);
414  PropertyManager->Tie("inertia/iyy-slugs_ft2", this,
415  &FGMassBalance::GetIyy);
416  PropertyManager->Tie("inertia/izz-slugs_ft2", this,
417  &FGMassBalance::GetIzz);
418  PropertyManager->Tie("inertia/ixy-slugs_ft2", this,
419  &FGMassBalance::GetIxy);
420  PropertyManager->Tie("inertia/ixz-slugs_ft2", this,
421  &FGMassBalance::GetIxz);
422  PropertyManager->Tie("inertia/iyz-slugs_ft2", this,
423  &FGMassBalance::GetIyz);
424  typedef int (FGMassBalance::*iOPV)() const;
425  PropertyManager->Tie("inertia/print-mass-properties", this, (iOPV)0,
426  &FGMassBalance::GetMassPropertiesReport);
427 }
428 
429 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 //
431 // This function binds properties for each pointmass object created.
432 //
433 void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager,
434  unsigned int num) {
435  string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num);
436  PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight,
437  &PointMass::SetPointMassWeight);
438 
439  tmp = CreateIndexedPropertyName("inertia/pointmass-location-X-inches", num);
440  PropertyManager->Tie( tmp.c_str(), this, eX, &PointMass::GetPointMassLocation,
441  &PointMass::SetPointMassLocation);
442  tmp = CreateIndexedPropertyName("inertia/pointmass-location-Y-inches", num);
443  PropertyManager->Tie( tmp.c_str(), this, eY, &PointMass::GetPointMassLocation,
444  &PointMass::SetPointMassLocation);
445  tmp = CreateIndexedPropertyName("inertia/pointmass-location-Z-inches", num);
446  PropertyManager->Tie( tmp.c_str(), this, eZ, &PointMass::GetPointMassLocation,
447  &PointMass::SetPointMassLocation);
448 }
449 
450 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 
452 void FGMassBalance::GetMassPropertiesReport(int i)
453 {
454  cout << endl << fgblue << highint
455  << " Mass Properties Report (English units: lbf, in, slug-ft^2)"
456  << reset << endl;
457  cout << " " << underon << " Weight CG-X CG-Y"
458  << " CG-Z Ixx Iyy Izz"
459  << " Ixy Ixz Iyz" << underoff << endl;
460  cout.precision(1);
461  cout << highint << setw(34) << left << " Base Vehicle " << normint
462  << right << setw(10) << EmptyWeight
463  << setw(8) << vbaseXYZcg(eX) << setw(8) << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ)
464  << setw(12) << baseJ(1,1) << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3)
465  << setw(12) << baseJ(1,2) << setw(12) << baseJ(1,3) << setw(12) << baseJ(2,3) << endl;
466 
467  for (unsigned int i=0;i<PointMasses.size();i++) {
468  PointMass* pm = PointMasses[i];
469  double pmweight = pm->GetPointMassWeight();
470  cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint
471  << right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX)
472  << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ)
473  << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) << setw(12) << pm->GetPointMassMoI(3,3)
474  << setw(12) << pm->GetPointMassMoI(1,2) << setw(12) << pm->GetPointMassMoI(1,3) << setw(12) << pm->GetPointMassMoI(2,3) << endl;
475  }
476 
477  cout << FDMExec->GetPropulsionTankReport();
478 
479  cout << " " << underon << setw(136) << " " << underoff << endl;
480  cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight
481  << setw(8) << vXYZcg(eX)
482  << setw(8) << vXYZcg(eY)
483  << setw(8) << vXYZcg(eZ)
484  << setw(12) << mJ(1,1)
485  << setw(12) << mJ(2,2)
486  << setw(12) << mJ(3,3)
487  << setw(12) << mJ(1,2)
488  << setw(12) << mJ(1,3)
489  << setw(12) << mJ(2,3)
490  << normint << endl;
491 
492  cout.setf(ios_base::fixed);
493 }
494 
495 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496 // The bitmasked value choices are as follows:
497 // unset: In this case (the default) JSBSim would only print
498 // out the normally expected messages, essentially echoing
499 // the config files as they are read. If the environment
500 // variable is not set, debug_lvl is set to 1 internally
501 // 0: This requests JSBSim not to output any messages
502 // whatsoever.
503 // 1: This value explicity requests the normal JSBSim
504 // startup messages
505 // 2: This value asks for a message to be printed out when
506 // a class is instantiated
507 // 4: When this value is set, a message is displayed when a
508 // FGModel object executes its Run() method
509 // 8: When this value is set, various runtime state variables
510 // are printed out periodically
511 // 16: When set various parameters are sanity checked and
512 // a message is printed out when they go out of bounds
513 
514 void FGMassBalance::Debug(int from)
515 {
516  if (debug_lvl <= 0) return;
517 
518  if (debug_lvl & 1) { // Standard console startup message output
519  if (from == 2) { // Loading
520  cout << endl << " Mass and Balance:" << endl;
521  cout << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl;
522  cout << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl;
523  cout << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl;
524  cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
525  cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
526  cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
527  cout << " Empty Weight: " << EmptyWeight << " lbm" << endl;
528  cout << " CG (x, y, z): " << vbaseXYZcg << endl;
529  // ToDo: Need to add point mass outputs here
530  for (unsigned int i=0; i<PointMasses.size(); i++) {
531  cout << " Point Mass Object: " << PointMasses[i]->Weight << " lbs. at "
532  << "X, Y, Z (in.): " << PointMasses[i]->Location(eX) << " "
533  << PointMasses[i]->Location(eY) << " "
534  << PointMasses[i]->Location(eZ) << endl;
535  }
536  }
537  }
538  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
539  if (from == 0) cout << "Instantiated: FGMassBalance" << endl;
540  if (from == 1) cout << "Destroyed: FGMassBalance" << endl;
541  }
542  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
543  }
544  if (debug_lvl & 8 ) { // Runtime state variables
545  }
546  if (debug_lvl & 16) { // Sanity checking
547  if (from == 2) {
548  if (EmptyWeight <= 0.0 || EmptyWeight > 1e9)
549  cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl;
550  if (Weight <= 0.0 || Weight > 1e9)
551  cout << "MassBalance::Weight out of bounds: " << Weight << endl;
552  if (Mass <= 0.0 || Mass > 1e9)
553  cout << "MassBalance::Mass out of bounds: " << Mass << endl;
554  }
555  }
556  if (debug_lvl & 64) {
557  if (from == 0) { // Constructor
558  }
559  }
560 }
561 }
JSBSim::FGModel::Upload
bool Upload(Element *el, bool preLoad)
Uploads this model in memory.
Definition: FGModel.cpp:110
JSBSim::FGColumnVector3
This class implements a 3 element column vector.
Definition: FGColumnVector3.h:63
JSBSim::FGMassBalance::StructuralToBody
FGColumnVector3 StructuralToBody(const FGColumnVector3 &r) const
Conversion from the structural frame to the body frame.
Definition: FGMassBalance.cpp:364
JSBSim::Element::GetAttributeValue
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Definition: FGXMLElement.cpp:260
JSBSim::FGMassBalance
Models weight, balance and moment of inertia information.
Definition: FGMassBalance.h:122
JSBSim::Element::FindElement
Element * FindElement(const std::string &el="")
Searches for a specified element.
Definition: FGXMLElement.cpp:389
JSBSim::Element::FindElementValueAsNumberConvertTo
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.
Definition: FGXMLElement.cpp:480
JSBSim::BaseException
Definition: FGJSBBase.h:59
JSBSim::FGJSBBase::slugtolb
static constexpr double slugtolb
Note that definition of lbtoslug by the inverse of slugtolb and not to a different constant you can a...
Definition: FGJSBBase.h:366
JSBSim::FGColumnVector3::Magnitude
double Magnitude(void) const
Length of the vector.
Definition: FGColumnVector3.cpp:109
JSBSim::FGFDMExec::GetChildFDM
childData * GetChildFDM(int i) const
Gets a particular child FDM.
Definition: FGFDMExec.h:426
JSBSim::FGFDMExec::GetFDMCount
int GetFDMCount(void) const
Gets the number of child FDMs.
Definition: FGFDMExec.h:424
JSBSim::FGFDMExec::GetHoldDown
bool GetHoldDown(void) const
Gets the value of the property forces/hold-down.
Definition: FGFDMExec.h:609
JSBSim::FGJSBBase::reset
static char reset[5]
resets text properties
Definition: FGJSBBase.h:129
JSBSim::FGModel::Run
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
Definition: FGModel.cpp:89
JSBSim::FGJSBBase::underon
static char underon[5]
underlines text
Definition: FGJSBBase.h:131
JSBSim::FGJSBBase::normint
static char normint[6]
normal intensity text
Definition: FGJSBBase.h:127
JSBSim::FGMassBalance::Run
bool Run(bool Holding) override
Runs the Mass Balance model; called by the Executive Can pass in a value indicating if the executive ...
Definition: FGMassBalance.cpp:181
JSBSim::Element::ReadFrom
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
Definition: FGXMLElement.cpp:738
JSBSim::FGJSBBase::highint
static char highint[5]
highlights text
Definition: FGJSBBase.h:123
JSBSim::FGMassBalance::GetXYZcg
const FGColumnVector3 & GetXYZcg(void) const
Returns the coordinates of the center of gravity expressed in the structural frame.
Definition: FGMassBalance.h:146
JSBSim::FGMatrix33::InitMatrix
void InitMatrix(void)
Initialize the matrix.
Definition: FGMatrix33.cpp:259
JSBSim::FGMassBalance::GetPointmassInertia
FGMatrix33 GetPointmassInertia(double mass_sl, const FGColumnVector3 &r) const
Computes the inertia contribution of a pointmass.
Definition: FGMassBalance.h:159
JSBSim::FGJSBBase::fgblue
static char fgblue[6]
blue text
Definition: FGJSBBase.h:135
JSBSim::Element
Definition: FGXMLElement.h:143
JSBSim::FGJSBBase::underoff
static char underoff[6]
underline off
Definition: FGJSBBase.h:133
JSBSim::FGPropertyManager::Tie
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
Definition: FGPropertyManager.h:449
JSBSim::Element::FindElementTripletConvertTo
FGColumnVector3 FindElementTripletConvertTo(const std::string &target_units)
Composes a 3-element column vector for the supplied location or orientation.
Definition: FGXMLElement.cpp:589