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