INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include <iostream>
+#include <iomanip>
+#include <cstdlib>
#include "FGMassBalance.h"
-#include "FGPropulsion.h"
-#include "FGBuoyantForces.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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGMassBalance::InitModel(void)
{
- if (!FGModel::InitModel()) return false;
-
vLastXYZcg.InitMatrix(0.0);
vDeltaXYZcg.InitMatrix(0.0);
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) {
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.
vDeltaXYZcg = vXYZcg - vLastXYZcg;
vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg);
vLastXYZcg = vXYZcg;
- Propagate->NudgeBodyLocation(vDeltaXYZcgBody);
+ FDMExec->GetPropagate()->NudgeBodyLocation(vDeltaXYZcgBody);
// Calculate new total moments of inertia
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);
k2, k4, k5,
k3, k5, k6 );
+ RunPostFunctions();
+
Debug(0);
return false;
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) {
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;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
+const FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
{
PointMassCG.InitMatrix();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGMatrix33& FGMassBalance::CalculatePMInertias(void)
+const FGMatrix33& FGMassBalance::CalculatePMInertias(void)
{
unsigned int size;
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;
}
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,
(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
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++) {