1
0
Fork 0

[JSBSim] Takes into account the amount of unusable fuel.

Properties /consumable/fuel/tank[*]/unusable-* supplied in the -set.xml file are propagated to the aircraft model and accounted for in the tanks management.
This commit is contained in:
Bertrand Coconnier 2018-12-31 00:59:21 +01:00
parent 466fb0979d
commit e704d589f2
5 changed files with 115 additions and 64 deletions

View file

@ -273,19 +273,29 @@ FGJSBsim::FGJSBsim( double dt )
double d;
SGPropertyNode * node = fgGetNode("/consumables/fuel/tank", i, true);
FGTank* tank = Propulsion->GetTank(i);
SGPropertyNode * prop = node->getNode( "density-ppg", true );
d = node->getNode( "density-ppg", true )->getDoubleValue();
d = prop->getDoubleValue();
if( d > 0.0 ) {
tank->SetDensity( d );
} else {
node->getNode( "density-ppg", true )->setDoubleValue( SG_MAX2<double>(tank->GetDensity(), 0.1) );
prop->setDoubleValue( SG_MAX2<double>(tank->GetDensity(), 0.1) );
}
d = node->getNode( "level-lbs", true )->getDoubleValue();
prop = node->getNode( "level-lbs", true );
d = prop->getDoubleValue();
if( d > 0.0 ) {
tank->SetContents( d );
} else {
node->getNode( "level-lbs", true )->setDoubleValue( tank->GetContents() );
prop->setDoubleValue( tank->GetContents() );
}
prop = node->getNode( "unusable-gal_us", true );
d = prop->getDoubleValue();
if ( d > 0.0 ) {
tank->SetUnusableVolume( d );
} else {
prop->setDoubleValue(tank->GetUnusableVolume());
}
/* Capacity is read-only in FGTank and can't be overwritten from FlightGear */
node->getNode("capacity-gal_us", true )->setDoubleValue( tank->GetCapacityGallons() );

View file

@ -8,33 +8,27 @@
------------- Copyright (C) 2001 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
Foundation; either version 2 of the License, or (at your option) any later
version.
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
Further information about the GNU Lesser General Public License can also be
found on the world wide web at http://www.gnu.org.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include "FGXMLElement.h"
#include "string_utilities.h"
#include "FGJSBBase.h"
using namespace std;
@ -91,6 +85,12 @@ Element::Element(const string& nm)
convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
convert["LTR"]["IN3"] = 61.0237441;
convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
convert["GAL"]["FT3"] = 0.133681;
convert["FT3"]["GAL"] = 1.0/convert["GAL"]["FT3"];
convert["IN3"]["GAL"] = convert["IN3"]["FT3"]*convert["FT3"]["GAL"];
convert["LTR"]["GAL"] = convert["LTR"]["IN3"]*convert["IN3"]["GAL"];
convert["M3"]["GAL"] = 1000.*convert["LTR"]["GAL"];
convert["CC"]["GAL"] = convert["CC"]["IN3"]*convert["IN3"]["GAL"];
// Mass & Weight
convert["LBS"]["KG"] = 0.45359237;
convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
@ -177,6 +177,7 @@ Element::Element(const string& nm)
convert["M3"]["M3"] = 1.0;
convert["FT3"]["FT3"] = 1.0;
convert["LTR"]["LTR"] = 1.0;
convert["GAL"]["GAL"] = 1.0;
// Mass & Weight
convert["KG"]["KG"] = 1.00;
convert["LBS"]["LBS"] = 1.00;

View file

@ -204,7 +204,7 @@ void FGPropulsion::ConsumeFuel(FGEngine* engine)
if (TankPriority != 0) {
switch(Tank->GetType()) {
case FGTank::ttFUEL:
if ((Tank->GetContents() > 0.0) && Tank->GetSelected() && (TankPriority == CurrentFuelTankPriority)) {
if ((Tank->GetContents() > Tank->GetUnusable()) && Tank->GetSelected() && (TankPriority == CurrentFuelTankPriority)) {
TanksWithFuel++;
Starved = false;
FeedListFuel.push_back(TankId);
@ -236,7 +236,7 @@ void FGPropulsion::ConsumeFuel(FGEngine* engine)
break;
case FGTank::ttOXIDIZER:
hasOxTanks = true;
if (Tank->GetContents() > 0.0 && Tank->GetSelected() && TankPriority == CurrentOxidizerTankPriority) {
if (Tank->GetContents() > Tank->GetUnusable() && Tank->GetSelected() && TankPriority == CurrentOxidizerTankPriority) {
TanksWithOxidizer++;
if (TanksWithFuel > 0) Starved = false;
FeedListOxi.push_back(TankId);

View file

@ -63,7 +63,7 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
ExternalFlow = 0.0;
InitialStandpipe = 0.0;
Capacity = 0.00001;
Capacity = 0.00001; UnusableVol = 0.0;
Priority = InitialPriority = 1;
vXYZ.InitMatrix();
vXYZ_drain.InitMatrix();
@ -95,6 +95,8 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS");
if (el->FindElement("contents"))
InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS");
if (el->FindElement("unusable-volume"))
UnusableVol = el->FindElementValueAsNumberConvertTo("unusable-volume", "GAL");
if (el->FindElement("temperature"))
InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature");
if (el->FindElement("standpipe"))
@ -115,6 +117,13 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
Capacity = 0.00001;
Contents = 0.0;
}
if (Capacity <= GetUnusable()) {
cerr << el->ReadFrom() << "Tank capacity (" << Capacity
<< " lbs) is lower than the amount of unusable fuel (" << GetUnusable()
<< " lbs) for tank " << tank_number
<< "! Did you accidentally swap unusable and capacity?" << endl;
throw("tank definition error");
}
if (Contents > Capacity) {
cerr << el->ReadFrom() << "Tank content (" << Contents
<< " lbs) is greater than tank capacity (" << Capacity
@ -122,6 +131,11 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
<< "! Did you accidentally swap contents and capacity?" << endl;
throw("tank definition error");
}
if (Contents < GetUnusable()) {
cerr << el->ReadFrom() << "Tank content (" << Contents
<< " lbs) is lower than the amount of unusable fuel (" << GetUnusable()
<< " lbs) for tank " << tank_number << endl;
}
PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
@ -253,17 +267,16 @@ double FGTank::Drain(double used)
{
double remaining = Contents - used;
if (remaining >= 0) { // Reduce contents by amount used.
if (remaining >= GetUnusable()) { // Reduce contents by amount used.
Contents -= used;
PctFull = 100.0*Contents/Capacity;
} else { // This tank must be empty.
if (Contents > GetUnusable())
Contents = GetUnusable();
Contents = 0.0;
PctFull = 0.0;
remaining = Contents;
}
PctFull = 100.0*Contents/Capacity;
CalculateInertias();
return remaining;
@ -443,6 +456,9 @@ void FGTank::bind(FGPropertyManager* PropertyManager)
property_name = base_property_name + "/contents-lbs";
PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
&FGTank::SetContents );
property_name = base_property_name + "/unusable-volume-gal";
PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetUnusableVolume,
&FGTank::SetUnusableVolume );
property_name = base_property_name + "/pct-full";
PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);

View file

@ -7,21 +7,21 @@
------------- Copyright (C) 1999 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
Foundation; either version 2 of the License, or (at your option) any later
version.
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
Further information about the GNU Lesser General Public License can also be
found on the world wide web at http://www.gnu.org.
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
@ -46,8 +46,6 @@ INCLUDES
#include "FGJSBBase.h"
#include "math/FGColumnVector3.h"
#include "math/FGFunction.h"
#include <string>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -58,6 +56,7 @@ namespace JSBSim {
class Element;
class FGPropertyManager;
class FGFDMExec;
class FGFunction;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
@ -69,8 +68,8 @@ CLASS DOCUMENTATION
Fuel temperature is calculated using the following assumptions:
Fuel temperature will only be calculated for tanks which have an initial fuel
temperature specified in the configuration file.
Fuel temperature will only be calculated for tanks which have an initial
fuel temperature specified in the configuration file.
The surface area of the tank is estimated from the capacity in pounds. It
is assumed that the tank is a wing tank with dimensions h by 4h by 10h. The
@ -84,27 +83,30 @@ CLASS DOCUMENTATION
<h3>Fuel Dump:</h3>
Fuel dumping is handled by the FGPropulsion class. A standpipe can be defined
here for each tank which sets the level of contents (in pounds) which is not dumpable.
Default standpipe level is zero, making all contents dumpable.
Fuel dumping is handled by the FGPropulsion class. A standpipe can be
defined here for each tank which sets the level of contents (in pounds)
which is not dumpable. Default standpipe level is zero, making all contents
dumpable.
<h3>Fuel Transfer:</h3>
Fuel transfer is handled by the FGPropulsion class, however the contents of tanks
may be manipulated directly using the SetContents() function here, or via the property
tree at <tt>propulsion/tank[i]/contents-lbs</tt>, where i is the tank number (Tanks
are automatically numbered, starting at zero, in the order in which they are read in
the aircraft configuration file). The latter method allows one to use a system of FCS
components to control tank contents.
Fuel transfer is handled by the FGPropulsion class, however the contents of
tanks may be manipulated directly using the SetContents() function here, or
via the property tree at <tt>propulsion/tank[i]/contents-lbs</tt>, where i
is the tank number (Tanks are automatically numbered, starting at zero, in
the order in which they are read in the aircraft configuration file). The
latter method allows one to use a system of FCS components to control tank
contents.
There is also a property <tt>propulsion/tank[i]/external-flow-rate-pps</tt>. Setting
this property to a positive value causes the tank to fill at the rate specified.
Setting a negative number causes the tank to drain. The value is the rate in pounds
of fuel per second. The tank will not fill past 100% full and will not drain below 0%.
Fuel may be transfered between two tanks by setting the source tank's external flow rate
to a negative value and the destination's external flow rate to the same positive value.
Care must be taken to stop fuel flow before the source tank becomes empty to prevent
phantom fuel being created.
There is also a property
<tt>propulsion/tank[i]/external-flow-rate-pps</tt>. Setting this property to
a positive value causes the tank to fill at the rate specified. Setting a
negative number causes the tank to drain. The value is the rate in pounds of
fuel per second. The tank will not fill past 100% full and will not drain
below 0%. Fuel may be transfered between two tanks by setting the source
tank's external flow rate to a negative value and the destination's external
flow rate to the same positive value. Care must be taken to stop fuel flow
before the source tank becomes empty to prevent phantom fuel being created.
<h3>Configuration File Format:</h3>
@ -133,6 +135,7 @@ CLASS DOCUMENTATION
<contents unit="{LBS | KG}"> {number} </contents>
<temperature> {number} </temperature> <!-- must be degrees fahrenheit -->
<standpipe unit="{LBS | KG"}> {number} </standpipe>
<unusable unit="{LBS | KG}"> {number} </unusable>
<priority> {integer} </priority>
<density unit="{KG/L | LBS/GAL}"> {number} </density>
<type> {string} </type> <!-- will override previous density setting -->
@ -144,16 +147,19 @@ CLASS DOCUMENTATION
- \b type - One of FUEL or OXIDIZER. This is required.
- \b radius - Equivalent radius of tank for modeling slosh, defaults to inches.
- \b grain_config type - One of CYLINDRICAL or ENDBURNING.
- \b length - length of tank for modeling solid fuel propellant grain, defaults to inches.
- \b length - length of tank for modeling solid fuel propellant grain, defaults
to inches.
- \b capacity - Capacity, defaults to pounds.
- \b contents - Initial contents, defaults to pounds.
- \b temperature - Initial temperature, defaults to degrees Fahrenheit.
- \b standpipe - Minimum contents to which tank can dump, defaults to pounds.
- \b unusable - Contents that cannot be used for combustion in the engine,
defaults to pounds.
- \b priority - Establishes feed sequence of tank. "1" is the highest priority.
- \b density - Density of liquid tank contents.
- \b type - Named fuel type. One of AVGAS, JET-A, JET-A1, JET-B, JP-1, JP-2, JP-3,
- \b JP-4, JP-5, JP-6, JP-7, JP-8, JP-8+100, RP-1, T-1, ETHANOL, HYDRAZINE,
- \b F-34, F-35, F-40, F-44, AVTAG, AVCAT
- \b type - Named fuel type. One of AVGAS, JET-A, JET-A1, JET-B, JP-1, JP-2,
JP-3, JP-4, JP-5, JP-6, JP-7, JP-8, JP-8+100, RP-1, T-1, ETHANOL,
HYDRAZINE, F-34, F-35, F-40, F-44, AVTAG, AVCAT
location:
- \b x - Location of tank on aircraft's x-axis, defaults to inches.
@ -178,6 +184,7 @@ be printed to the console if the location is not given
- \b contents - 0.0
- \b temperature - -9999.0 (flag which indicates no temperature is set)
- \b standpipe - 0.0 (all contents may be dumped)
- \b unusable - 0.0 (all contents may be burnt)
- \b priority - 1 (highest feed sequence priority)
- \b density - 6.6
@ -195,7 +202,8 @@ class FGTank : public FGJSBBase
{
public:
/** Constructor.
The constructor reads in the defining parameters from a configuration file.
The constructor reads in the defining parameters from a configuration
file.
@param exec a pointer to the base FGFDMExec instance.
@param el a pointer to the Tank element.
@param tank_number the tank number (zero based).
@ -271,7 +279,19 @@ public:
/** Returns the density of a named fuel type.
@return the density, in lbs/gal, or 6.6 if name cannot be resolved. */
double ProcessFuelName(const std::string& name);
double ProcessFuelName(const std::string& name);
/** Returns the amount of unusable fuel in the tank.
@return the amount in lbs. */
double GetUnusable(void) const {return UnusableVol*Density;}
/** Returns the unusable volume of fuel in the tank.
@return the volume in gal. */
double GetUnusableVolume(void) const {return UnusableVol;}
/** Sets the volume of unusable fuel in the tank.
@param amount the amount of unusable fuel in gal. */
void SetUnusableVolume(double volume) {UnusableVol = volume;}
double GetIxx(void) const {return Ixx;}
double GetIyy(void) const {return Iyy;}
@ -289,7 +309,11 @@ public:
int GetPriority(void) const {return Priority;}
void SetPriority(int p) { Priority = p; Selected = p>0 ? true:false; }
/** Returns the fuel density.
@return the density in lbs/gal. */
double GetDensity(void) const {return Density;}
/** Sets the fuel density.
@param d the density in lbs/gal. */
void SetDensity(double d) { Density = d; }
double GetExternalFlow(void) const {return ExternalFlow;}
@ -298,7 +322,7 @@ public:
FGColumnVector3 GetXYZ(void) const;
double GetXYZ(int idx) const;
const GrainType GetGrainType(void) const {return grainType;}
GrainType GetGrainType(void) const {return grainType;}
double Fill(double amount);
void SetContents(double amount);
@ -321,7 +345,7 @@ private:
FGFunction* function_ixx;
FGFunction* function_iyy;
FGFunction* function_izz;
double Capacity;
double Capacity, UnusableVol;
double Radius;
double InnerRadius;
double Length;