]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/models/FGMassBalance.cpp
Merge branch 'next' of gitorious.org:fg/flightgear into next
[flightgear.git] / src / FDM / JSBSim / models / FGMassBalance.cpp
index 967f0ff44d388838438b907878edda97f8906e63..dbd8ab3a64565c40fa7b0ac28d4bab5bcd69a30c 100644 (file)
@@ -5,7 +5,7 @@
  Date started: 09/12/2000
  Purpose:      This module models weight and balance
 
- ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) --------------
+ ------------- Copyright (C) 2000  Jon S. Berndt (jon@jsbsim.org) --------------
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free Software
@@ -38,14 +38,18 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <iostream>
+#include <iomanip>
+#include <cstdlib>
 #include "FGMassBalance.h"
-#include "FGPropulsion.h"
-#include "FGBuoyantForces.h"
-#include <input_output/FGPropertyManager.h>
+#include "FGFDMExec.h"
+#include "input_output/FGPropertyManager.h"
+
+using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.39 2011/11/09 21:58:26 bcoconni Exp $";
 static const char *IdHdr = ID_MASSBALANCE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -59,6 +63,9 @@ FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex)
   Weight = EmptyWeight = Mass = 0.0;
 
   vbaseXYZcg.InitMatrix(0.0);
+  vXYZcg.InitMatrix(0.0);
+  vLastXYZcg.InitMatrix(0.0);
+  vDeltaXYZcg.InitMatrix(0.0);
   baseJ.InitMatrix();
   mJ.InitMatrix();
   mJinv.InitMatrix();
@@ -83,7 +90,8 @@ FGMassBalance::~FGMassBalance()
 
 bool FGMassBalance::InitModel(void)
 {
-  if (!FGModel::InitModel()) return false;
+  vLastXYZcg.InitMatrix(0.0);
+  vDeltaXYZcg.InitMatrix(0.0);
 
   return true;
 }
@@ -96,6 +104,8 @@ bool FGMassBalance::Load(Element* el)
   string element_name = "";
   double bixx, biyy, bizz, bixy, bixz, biyz;
 
+  FGModel::Load(el); // Perform base class Load.
+
   bixx = biyy = bizz = bixy = bixz = biyz = 0.0;
   if (el->FindElement("ixx"))
     bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
@@ -112,7 +122,9 @@ bool FGMassBalance::Load(Element* el)
   SetAircraftBaseInertias(FGMatrix33(  bixx,  -bixy,  bixz,
                                       -bixy,  biyy,  -biyz,
                                        bixz,  -biyz,  bizz ));
-  EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
+  if (el->FindElement("emptywt")) {
+    EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
+  }
 
   element = el->FindElement("location");
   while (element) {
@@ -135,40 +147,53 @@ bool FGMassBalance::Load(Element* el)
     if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
   }
 
-  Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight()
-    + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight;
+  Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
+    + in.GasMass*slugtolb + ChildFDMWeight;
 
   Mass = lbtoslug*Weight;
 
+  PostLoad(el, PropertyManager);
+
   Debug(2);
   return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGMassBalance::Run(void)
+bool FGMassBalance::Run(bool Holding)
 {
   double denom, k1, k2, k3, k4, k5, k6;
   double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
 
-  if (FGModel::Run()) return true;
-  if (FDMExec->Holding()) return false;
+  if (FGModel::Run(Holding)) return true;
+  if (Holding) return false;
+
+  RunPreFunctions();
 
   double ChildFDMWeight = 0.0;
   for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
     if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
   }
 
-  Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight()
-    + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight;
+  Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
+    + in.GasMass*slugtolb + ChildFDMWeight;
 
   Mass = lbtoslug*Weight;
 
 // Calculate new CG
 
-  vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg
+  vXYZcg = (EmptyWeight*vbaseXYZcg
             + GetPointMassMoment()
-            + BuoyantForces->GetGasMassMoment()) / Weight;
+            + in.TanksMoment
+            + in.GasMoment) / Weight;
+
+  // Track frame-by-frame delta CG, and move the EOM-tracked location
+  // by this amount.
+  if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg;
+  vDeltaXYZcg = vXYZcg - vLastXYZcg;
+  vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg);
+  vLastXYZcg = vXYZcg;
+  FDMExec->GetPropagate()->NudgeBodyLocation(vDeltaXYZcgBody);
 
 // Calculate new total moments of inertia
 
@@ -178,8 +203,8 @@ bool FGMassBalance::Run(void)
   mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
   // Then add the contributions from the additional pointmasses.
   mJ += CalculatePMInertias();
-  mJ += Propulsion->CalculateTankInertias();
-  mJ += BuoyantForces->GetGasMassInertia();
+  mJ += in.TankInertia;
+  mJ += in.GasInertia;
 
   Ixx = mJ(1,1);
   Iyy = mJ(2,2);
@@ -206,6 +231,8 @@ bool FGMassBalance::Run(void)
                     k2, k4, k5,
                     k3, k5, k6 );
 
+  RunPostFunctions();
+
   Debug(0);
 
   return false;
@@ -215,6 +242,7 @@ bool FGMassBalance::Run(void)
 
 void FGMassBalance::AddPointMass(Element* el)
 {
+  double radius=0, length=0;
   Element* loc_element = el->FindElement("location");
   string pointmass_name = el->GetAttributeValue("name");
   if (!loc_element) {
@@ -225,13 +253,45 @@ void FGMassBalance::AddPointMass(Element* el)
   double w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
   FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN");
 
-  PointMasses.push_back(new PointMass(w, vXYZ));
-  PointMasses.back()->bind(PropertyManager, PointMasses.size()-1);
+  PointMass *pm = new PointMass(w, vXYZ);
+  pm->SetName(pointmass_name);
+
+  Element* form_element = el->FindElement("form");
+  if (form_element) {
+    string shape = form_element->GetAttributeValue("shape");
+    Element* radius_element = form_element->FindElement("radius");
+    Element* length_element = form_element->FindElement("length");
+    if (radius_element) radius = form_element->FindElementValueAsNumberConvertTo("radius", "FT");
+    if (length_element) length = form_element->FindElementValueAsNumberConvertTo("length", "FT");
+    if (shape == "tube") {
+      pm->SetPointMassShapeType(PointMass::esTube);
+      pm->SetRadius(radius);
+      pm->SetLength(length);
+      pm->CalculateShapeInertia();
+    } else if (shape == "cylinder") {
+      pm->SetPointMassShapeType(PointMass::esCylinder);
+      pm->SetRadius(radius);
+      pm->SetLength(length);
+      pm->CalculateShapeInertia();
+    } else if (shape == "sphere") {
+      pm->SetPointMassShapeType(PointMass::esSphere);
+      pm->SetRadius(radius);
+      pm->CalculateShapeInertia();
+    } else if (shape == "ball") {
+      pm->SetPointMassShapeType(PointMass::esBall);
+      pm->SetRadius(radius);
+      pm->CalculateShapeInertia();
+    } else {
+    }
+  }
+
+  pm->bind(PropertyManager, PointMasses.size());
+  PointMasses.push_back(pm);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGMassBalance::GetTotalPointMassWeight(void)
+double FGMassBalance::GetTotalPointMassWeight(void) const
 {
   double PM_total_weight = 0.0;
 
@@ -243,7 +303,7 @@ double FGMassBalance::GetTotalPointMassWeight(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
+const FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
 {
   PointMassCG.InitMatrix();
 
@@ -255,7 +315,7 @@ FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGMatrix33& FGMassBalance::CalculatePMInertias(void)
+const FGMatrix33& FGMassBalance::CalculatePMInertias(void)
 {
   unsigned int size;
 
@@ -264,8 +324,10 @@ FGMatrix33& FGMassBalance::CalculatePMInertias(void)
 
   pmJ = FGMatrix33();
 
-  for (unsigned int i=0; i<size; i++)
+  for (unsigned int i=0; i<size; i++) {
     pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location );
+    pmJ += PointMasses[i]->GetPointMassInertia();
+  }
 
   return pmJ;
 }
@@ -313,7 +375,7 @@ void FGMassBalance::bind(void)
   PropertyManager->Tie("inertia/weight-lbs", this,
                        &FGMassBalance::GetWeight);
   PropertyManager->Tie("inertia/empty-weight-lbs", this,
-    &FGMassBalance::GetWeight, &FGMassBalance::SetEmptyWeight);
+                       &FGMassBalance::GetEmptyWeight);
   PropertyManager->Tie("inertia/cg-x-in", this,1,
                        (PMF)&FGMassBalance::GetXYZcg);
   PropertyManager->Tie("inertia/cg-y-in", this,2,
@@ -322,6 +384,66 @@ void FGMassBalance::bind(void)
                        (PMF)&FGMassBalance::GetXYZcg);
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// This function binds properties for each pointmass object created.
+//
+void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) {
+  string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num);
+  PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight,
+                                       &PointMass::SetPointMassWeight);
+
+  tmp = CreateIndexedPropertyName("inertia/pointmass-location-X-inches", num);
+  PropertyManager->Tie( tmp.c_str(), this, eX, &PointMass::GetPointMassLocation,
+                                           &PointMass::SetPointMassLocation);
+  tmp = CreateIndexedPropertyName("inertia/pointmass-location-Y-inches", num);
+  PropertyManager->Tie( tmp.c_str(), this, eY, &PointMass::GetPointMassLocation,
+                                           &PointMass::SetPointMassLocation);
+  tmp = CreateIndexedPropertyName("inertia/pointmass-location-Z-inches", num);
+  PropertyManager->Tie( tmp.c_str(), this, eZ, &PointMass::GetPointMassLocation,
+                                           &PointMass::SetPointMassLocation);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMassBalance::GetMassPropertiesReport(void) const
+{
+  cout << endl << fgblue << highint 
+       << "  Mass Properties Report (English units: lbf, in, slug-ft^2)"
+       << reset << endl;
+  cout << "                                  " << underon << "    Weight    CG-X    CG-Y"
+       << "    CG-Z         Ixx         Iyy         Izz" << underoff << endl;
+  cout.precision(1);
+  cout << highint << setw(34) << left << "    Base Vehicle " << normint
+       << right << setw(10) << EmptyWeight << setw(8) << vbaseXYZcg(eX) << setw(8)
+       << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) << setw(12) << baseJ(1,1)
+       << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) << endl;
+
+  for (unsigned int i=0;i<PointMasses.size();i++) {
+    PointMass* pm = PointMasses[i];
+    double pmweight = pm->GetPointMassWeight();
+    cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint
+         << right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX)
+         << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ)
+         << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2)
+         << setw(12) << pm->GetPointMassMoI(3,3) << endl;
+  }
+
+  cout << FDMExec->GetPropulsionTankReport();
+
+  cout << underon << setw(104) << " " << underoff << endl;
+  cout << highint << left << setw(30) << "    Total: " << right << setw(14) << Weight 
+       << setw(8) << vXYZcg(eX)
+       << setw(8) << vXYZcg(eY)
+       << setw(8) << vXYZcg(eZ)
+       << setw(12) << mJ(1,1)
+       << setw(12) << mJ(2,2)
+       << setw(12) << mJ(3,3)
+       << normint << endl;
+
+  cout.setf(ios_base::fixed);
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
@@ -354,7 +476,7 @@ void FGMassBalance::Debug(int from)
       cout << "    baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
       cout << "    baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
       cout << "    baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
-      cout << "    EmptyWeight: " << EmptyWeight << " lbm" << endl;
+      cout << "    Empty Weight: " << EmptyWeight << " lbm" << endl;
       cout << "    CG (x, y, z): " << vbaseXYZcg << endl;
       // ToDo: Need to add point mass outputs here
       for (unsigned int i=0; i<PointMasses.size(); i++) {