45 #include "FGMassBalance.h" 46 #include "FGFDMExec.h" 47 #include "input_output/FGPropertyManager.h" 48 #include "input_output/FGXMLElement.h" 54 IDENT(IdSrc,
"$Id: FGMassBalance.cpp,v 1.55 2016/03/26 18:54:27 bcoconni Exp $");
55 IDENT(IdHdr,ID_MASSBALANCE);
62 FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex)
64 Name =
"FGMassBalance";
65 Weight = EmptyWeight = Mass = 0.0;
67 vbaseXYZcg.InitMatrix(0.0);
68 vXYZcg.InitMatrix(0.0);
69 vLastXYZcg.InitMatrix(0.0);
70 vDeltaXYZcg.InitMatrix(0.0);
83 FGMassBalance::~FGMassBalance()
85 for (
unsigned int i=0; i<PointMasses.size(); i++)
delete PointMasses[i];
93 bool FGMassBalance::InitModel(
void)
95 if (!FGModel::InitModel())
return false;
97 vLastXYZcg.InitMatrix(0.0);
98 vDeltaXYZcg.InitMatrix(0.0);
105 static FGMatrix33 ReadInertiaMatrix(Element* document)
107 double bixx, biyy, bizz, bixy, bixz, biyz;
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");
123 return FGMatrix33( bixx, -bixy, bixz,
132 string element_name =
"";
140 SetAircraftBaseInertias(ReadInertiaMatrix(document));
157 AddPointMass(element);
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();
166 Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
167 + in.GasMass*slugtolb + ChildFDMWeight;
169 Mass = lbtoslug*Weight;
171 PostLoad(document, PropertyManager);
181 double denom, k1, k2, k3, k4, k5, k6;
182 double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
185 if (Holding)
return false;
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();
194 Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
195 + in.GasMass*slugtolb + ChildFDMWeight;
197 Mass = lbtoslug*Weight;
201 vXYZcg = (EmptyWeight*vbaseXYZcg
202 + GetPointMassMoment()
204 + in.GasMoment) / Weight;
208 if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg;
209 vDeltaXYZcg = vXYZcg - vLastXYZcg;
210 vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg);
212 FDMExec->
GetPropagate()->NudgeBodyLocation(vDeltaXYZcgBody);
219 mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
221 mJ += CalculatePMInertias();
222 mJ += in.TankInertia;
234 k1 = (Iyy*Izz - Iyz*Iyz);
235 k2 = (Iyz*Ixz + Ixy*Izz);
236 k3 = (Ixy*Iyz + Iyy*Ixz);
238 denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
242 k4 = (Izz*Ixx - Ixz*Ixz)*denom;
243 k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
244 k6 = (Ixx*Iyy - Ixy*Ixy)*denom;
246 mJinv.InitMatrix( k1, k2, k3,
259 void FGMassBalance::AddPointMass(
Element* el)
264 cerr << el->
ReadFrom() <<
"Pointmass " << pointmass_name
265 <<
" has no location." << endl;
272 PointMass *pm =
new PointMass(w, vXYZ);
273 pm->SetName(pointmass_name);
277 double radius=0, length=0;
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();
305 pm->SetPointMassShapeType(PointMass::esUnspecified);
306 pm->SetPointMassMoI(ReadInertiaMatrix(el));
309 pm->bind(PropertyManager, PointMasses.size());
310 PointMasses.push_back(pm);
315 double FGMassBalance::GetTotalPointMassWeight(
void)
const 317 double PM_total_weight = 0.0;
319 for (
unsigned int i=0; i<PointMasses.size(); i++) {
320 PM_total_weight += PointMasses[i]->Weight;
322 return PM_total_weight;
329 PointMassCG.InitMatrix();
331 for (
unsigned int i=0; i<PointMasses.size(); i++) {
332 PointMassCG += PointMasses[i]->Weight*PointMasses[i]->Location;
339 const FGMatrix33& FGMassBalance::CalculatePMInertias(
void)
341 size_t size = PointMasses.size();
343 if (size == 0)
return pmJ;
347 for (
unsigned int i=0; i<size; i++) {
348 pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location );
349 pmJ += PointMasses[i]->GetPointMassInertia();
384 inchtoft*(r(2)-vXYZcg(2)),
385 inchtoft*(vXYZcg(3)-r(3)));
390 void FGMassBalance::bind(
void)
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);
418 PropertyManager->
Tie(
"inertia/print-mass-properties",
this, (iOPV)0,
419 &FGMassBalance::GetMassPropertiesReport,
false);
428 string tmp = CreateIndexedPropertyName(
"inertia/pointmass-weight-lbs", num);
429 PropertyManager->
Tie( tmp.c_str(),
this, &PointMass::GetPointMassWeight,
430 &PointMass::SetPointMassWeight);
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);
445 void FGMassBalance::GetMassPropertiesReport(
int i)
448 <<
" Mass Properties Report (English units: lbf, in, slug-ft^2)" 450 cout <<
" " <<
underon <<
" Weight CG-X CG-Y" 451 <<
" CG-Z Ixx Iyy Izz" 452 <<
" Ixy Ixz Iyz" <<
underoff << endl;
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;
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;
470 cout << FDMExec->GetPropulsionTankReport();
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)
485 cout.setf(ios_base::fixed);
507 void FGMassBalance::Debug(
int from)
509 if (debug_lvl <= 0)
return;
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;
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;
531 if (debug_lvl & 2 ) {
532 if (from == 0) cout <<
"Instantiated: FGMassBalance" << endl;
533 if (from == 1) cout <<
"Destroyed: FGMassBalance" << endl;
535 if (debug_lvl & 4 ) {
537 if (debug_lvl & 8 ) {
539 if (debug_lvl & 16) {
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;
549 if (debug_lvl & 64) {
551 cout << IdSrc << endl;
552 cout << IdHdr << endl;
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
Element * FindElement(const std::string &el="")
Searches for a specified element.
static char normint[6]
normal intensity text
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
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.
int GetFDMCount(void) const
Gets the number of child FDMs.
static char underoff[6]
underline off
This class implements a 3 element column vector.
static char fgblue[6]
blue text
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
Handles matrix math operations.
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.
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
FGPropagate * GetPropagate(void)
Returns the FGPropagate pointer.