Initial checkin of a TurbineEngine implementation. This hasn't been
tested at all yet, but it doesn't seem to have broken anything so it should be safe. See the README in the base package for docs.
This commit is contained in:
parent
9f2a8d4651
commit
a3ba94c39e
8 changed files with 195 additions and 23 deletions
|
@ -4,6 +4,7 @@
|
|||
namespace yasim {
|
||||
|
||||
class PistonEngine;
|
||||
class TurbineEngine;
|
||||
|
||||
//
|
||||
// Interface for the "Engine" part of a PropEngine object. This is a
|
||||
|
@ -15,6 +16,7 @@ class PistonEngine;
|
|||
class Engine {
|
||||
public:
|
||||
virtual PistonEngine* isPistonEngine() { return 0; }
|
||||
virtual TurbineEngine* isTurbineEngine() { return 0; }
|
||||
|
||||
void setThrottle(float throttle) { _throttle = throttle; }
|
||||
void setStarter(bool starter) { _starter = starter; }
|
||||
|
@ -28,6 +30,8 @@ public:
|
|||
virtual bool isCranking() { return false; }
|
||||
|
||||
virtual void calc(float pressure, float temp, float speed) = 0;
|
||||
virtual void stabilize() {}
|
||||
virtual void integrate(float dt) {}
|
||||
virtual float getTorque() = 0;
|
||||
virtual float getFuelFlow() = 0;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "PropEngine.hpp"
|
||||
#include "Propeller.hpp"
|
||||
#include "PistonEngine.hpp"
|
||||
#include "TurbineEngine.hpp"
|
||||
#include "Rotor.hpp"
|
||||
#include "Rotorpart.hpp"
|
||||
#include "Rotorblade.hpp"
|
||||
|
@ -35,6 +36,8 @@ static const float K2DEGFOFFSET = -459.4;
|
|||
static const float CIN2CM = 1.6387064e-5;
|
||||
static const float YASIM_PI = 3.14159265358979323846;
|
||||
|
||||
static const float NM2FTLB = (1/(LBS2N*FT2M));
|
||||
|
||||
// Stubs, so that this can be compiled without the FlightGear
|
||||
// binary. What's the best way to handle this?
|
||||
|
||||
|
@ -175,6 +178,10 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts)
|
|||
_airplane.setTail(parseWing(a, name));
|
||||
} else if(eq(name, "vstab") || eq(name, "mstab")) {
|
||||
_airplane.addVStab(parseWing(a, name));
|
||||
} else if(eq(name, "piston-engine")) {
|
||||
parsePistonEngine(a);
|
||||
} else if(eq(name, "turbine-engine")) {
|
||||
parseTurbineEngine(a);
|
||||
} else if(eq(name, "propeller")) {
|
||||
parsePropeller(a);
|
||||
} else if(eq(name, "thruster")) {
|
||||
|
@ -448,22 +455,24 @@ void FGFDM::setOutputProperties()
|
|||
float lbs = Math::mag3(tmp) * (KG2LBS/9.8);
|
||||
node->setFloatValue("prop-thrust", lbs); // Deprecated name
|
||||
node->setFloatValue("thrust-lbs", lbs);
|
||||
|
||||
node->setFloatValue("fuel-flow-gph",
|
||||
(t->getFuelFlow()/fuelDensity) * 3600 * CM2GALS);
|
||||
|
||||
if(t->getPropEngine()) {
|
||||
PropEngine* p = t->getPropEngine();
|
||||
node->setFloatValue("rpm", p->getOmega() * (1/RPM2RAD));
|
||||
|
||||
node->setFloatValue("torque-ftlb",
|
||||
p->getEngine()->getTorque() * NM2FTLB);
|
||||
|
||||
if(p->getEngine()->isPistonEngine()) {
|
||||
PistonEngine* pe = p->getEngine()->isPistonEngine();
|
||||
node->setFloatValue("mp-osi", pe->getMP() * (1/INHG2PA));
|
||||
node->setFloatValue("mp-inhg", pe->getMP() * (1/INHG2PA));
|
||||
node->setFloatValue("egt-degf",
|
||||
pe->getEGT() * K2DEGF + K2DEGFOFFSET);
|
||||
// } else if(p->isTurbineEngine()) {
|
||||
// TurbineEngine* te = p->isTurbineEngine();
|
||||
} else if(p->getEngine()->isTurbineEngine()) {
|
||||
TurbineEngine* te = p->getEngine()->isTurbineEngine();
|
||||
node->setFloatValue("n2", te->getN2());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -595,28 +604,12 @@ Rotor* FGFDM::parseRotor(XMLAttributes* a, const char* type)
|
|||
return w;
|
||||
}
|
||||
|
||||
void FGFDM::parsePropeller(XMLAttributes* a)
|
||||
void FGFDM::parsePistonEngine(XMLAttributes* a)
|
||||
{
|
||||
float cg[3];
|
||||
cg[0] = attrf(a, "x");
|
||||
cg[1] = attrf(a, "y");
|
||||
cg[2] = attrf(a, "z");
|
||||
float mass = attrf(a, "mass") * LBS2KG;
|
||||
float moment = attrf(a, "moment");
|
||||
float radius = attrf(a, "radius");
|
||||
float speed = attrf(a, "cruise-speed") * KTS2MPS;
|
||||
float omega = attrf(a, "cruise-rpm") * RPM2RAD;
|
||||
float power = attrf(a, "cruise-power") * HP2W;
|
||||
float rho = Atmosphere::getStdDensity(attrf(a, "cruise-alt") * FT2M);
|
||||
|
||||
// Hack, fix this pronto:
|
||||
float engP = attrf(a, "eng-power") * HP2W;
|
||||
float engS = attrf(a, "eng-rpm") * RPM2RAD;
|
||||
|
||||
Propeller* prop = new Propeller(radius, speed, omega, rho, power);
|
||||
PistonEngine* eng = new PistonEngine(engP, engS);
|
||||
PropEngine* thruster = new PropEngine(prop, eng, moment);
|
||||
_airplane.addThruster(thruster, mass, cg);
|
||||
|
||||
if(a->hasAttribute("displacement"))
|
||||
eng->setDisplacement(attrf(a, "displacement") * CIN2CM);
|
||||
|
@ -630,6 +623,66 @@ void FGFDM::parsePropeller(XMLAttributes* a)
|
|||
eng->setTurboParams(mul, mp);
|
||||
}
|
||||
|
||||
((PropEngine*)_currObj)->setEngine(eng);
|
||||
}
|
||||
|
||||
void FGFDM::parseTurbineEngine(XMLAttributes* a)
|
||||
{
|
||||
float power = attrf(a, "eng-power") * HP2W;
|
||||
float omega = attrf(a, "eng-rpm") * RPM2RAD;
|
||||
float alt = attrf(a, "alt") * FT2M;
|
||||
float flatRating = attrf(a, "flat-rating") * HP2W;
|
||||
TurbineEngine* eng = new TurbineEngine(power, omega, alt, flatRating);
|
||||
|
||||
if(a->hasAttribute("min-n2"))
|
||||
eng->setN2Range(attrf(a, "min-n2"), attrf(a, "max-n2"));
|
||||
|
||||
// Nasty units conversion: lbs/hr per hp -> kg/s per watt
|
||||
if(a->hasAttribute("bsfc"))
|
||||
eng->setFuelConsumption(attrf(a, "bsfc") * (LBS2KG/(3600*HP2W)));
|
||||
|
||||
((PropEngine*)_currObj)->setEngine(eng);
|
||||
}
|
||||
|
||||
void FGFDM::parsePropeller(XMLAttributes* a)
|
||||
{
|
||||
// Legacy Handling for the old engines syntax:
|
||||
PistonEngine* eng = 0;
|
||||
if(a->hasAttribute("eng-power")) {
|
||||
SG_LOG(SG_FLIGHT,SG_ALERT, "WARNING: "
|
||||
<< "Legacy engine definition in YASim configuration file. "
|
||||
<< "Please fix.");
|
||||
float engP = attrf(a, "eng-power") * HP2W;
|
||||
float engS = attrf(a, "eng-rpm") * RPM2RAD;
|
||||
eng = new PistonEngine(engP, engS);
|
||||
if(a->hasAttribute("displacement"))
|
||||
eng->setDisplacement(attrf(a, "displacement") * CIN2CM);
|
||||
if(a->hasAttribute("compression"))
|
||||
eng->setCompression(attrf(a, "compression"));
|
||||
if(a->hasAttribute("turbo-mul")) {
|
||||
float mul = attrf(a, "turbo-mul");
|
||||
float mp = attrf(a, "wastegate-mp", 1e6) * INHG2PA;
|
||||
eng->setTurboParams(mul, mp);
|
||||
}
|
||||
}
|
||||
|
||||
// Now parse the actual propeller definition:
|
||||
float cg[3];
|
||||
cg[0] = attrf(a, "x");
|
||||
cg[1] = attrf(a, "y");
|
||||
cg[2] = attrf(a, "z");
|
||||
float mass = attrf(a, "mass") * LBS2KG;
|
||||
float moment = attrf(a, "moment");
|
||||
float radius = attrf(a, "radius");
|
||||
float speed = attrf(a, "cruise-speed") * KTS2MPS;
|
||||
float omega = attrf(a, "cruise-rpm") * RPM2RAD;
|
||||
float power = attrf(a, "cruise-power") * HP2W;
|
||||
float rho = Atmosphere::getStdDensity(attrf(a, "cruise-alt") * FT2M);
|
||||
|
||||
Propeller* prop = new Propeller(radius, speed, omega, rho, power);
|
||||
PropEngine* thruster = new PropEngine(prop, eng, moment);
|
||||
_airplane.addThruster(thruster, mass, cg);
|
||||
|
||||
if(a->hasAttribute("takeoff-power")) {
|
||||
float power0 = attrf(a, "takeoff-power") * HP2W;
|
||||
float omega0 = attrf(a, "takeoff-rpm") * RPM2RAD;
|
||||
|
|
|
@ -41,6 +41,8 @@ private:
|
|||
int parseAxis(const char* name);
|
||||
int parseOutput(const char* name);
|
||||
void parseWeight(XMLAttributes* a);
|
||||
void parseTurbineEngine(XMLAttributes* a);
|
||||
void parsePistonEngine(XMLAttributes* a);
|
||||
void parsePropeller(XMLAttributes* a);
|
||||
bool eq(const char* a, const char* b);
|
||||
bool caseeq(const char* a, const char* b);
|
||||
|
|
|
@ -18,9 +18,11 @@ SHARED_SOURCE_FILES = \
|
|||
Jet.cpp Jet.hpp \
|
||||
Math.cpp Math.hpp \
|
||||
Model.cpp Model.hpp \
|
||||
PistonEngine.cpp PistonEngine.hpp \
|
||||
PropEngine.cpp PropEngine.hpp \
|
||||
Propeller.cpp Propeller.hpp \
|
||||
Engine.hpp \
|
||||
PistonEngine.cpp PistonEngine.hpp \
|
||||
TurbineEngine.cpp TurbineEngine.hpp \
|
||||
RigidBody.cpp RigidBody.hpp \
|
||||
Rotor.cpp Rotor.hpp \
|
||||
Rotorblade.cpp Rotorblade.hpp \
|
||||
|
|
|
@ -113,6 +113,7 @@ void PropEngine::stabilize()
|
|||
float ptau, dummy;
|
||||
_prop->calc(_rho, speed, _omega * _gearRatio, &dummy, &ptau);
|
||||
_eng->calc(_pressure, _temp, _omega);
|
||||
_eng->stabilize();
|
||||
float etau = _eng->getTorque();
|
||||
float tdiff = etau - ptau;
|
||||
|
||||
|
@ -157,6 +158,7 @@ void PropEngine::integrate(float dt)
|
|||
|
||||
_prop->calc(_rho, speed, _omega * _gearRatio, &thrust, &propTorque);
|
||||
_eng->calc(_pressure, _temp, _omega);
|
||||
_eng->integrate(dt);
|
||||
engTorque = _eng->getTorque();
|
||||
_fuelFlow = _eng->getFuelFlow();
|
||||
|
||||
|
|
|
@ -2,17 +2,19 @@
|
|||
#define _PROPENGINE_HPP
|
||||
|
||||
#include "Thruster.hpp"
|
||||
#include "Engine.hpp"
|
||||
|
||||
namespace yasim {
|
||||
|
||||
class Propeller;
|
||||
class Engine;
|
||||
|
||||
class PropEngine : public Thruster {
|
||||
public:
|
||||
PropEngine(Propeller* prop, Engine* eng, float moment);
|
||||
virtual ~PropEngine();
|
||||
|
||||
void setEngine(Engine* eng) { delete _eng; _eng = eng; }
|
||||
|
||||
void setMagnetos(int magnetos);
|
||||
void setAdvance(float advance);
|
||||
void setPropPitch(float proppitch);
|
||||
|
|
61
src/FDM/YASim/TurbineEngine.cpp
Normal file
61
src/FDM/YASim/TurbineEngine.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "Atmosphere.hpp"
|
||||
|
||||
#include "TurbineEngine.hpp"
|
||||
|
||||
namespace yasim {
|
||||
|
||||
TurbineEngine::TurbineEngine(float power, float omega, float alt,
|
||||
float flatRating)
|
||||
{
|
||||
_rho0 = Atmosphere::getStdDensity(0);
|
||||
_maxTorque = (power/omega) * _rho0 / Atmosphere::getStdDensity(alt);
|
||||
_flatRating = flatRating;
|
||||
_bsfc = 0.047; // == 0.5 lb/hr per hp
|
||||
_n2Min = 65;
|
||||
_n2Max = 100;
|
||||
|
||||
_rho = _rho0;
|
||||
_omega = 0;
|
||||
_n2 = _n2Target = _n2Min;
|
||||
_torque = 0;
|
||||
_fuelFlow = 0;
|
||||
}
|
||||
|
||||
void TurbineEngine::setOutputFromN2()
|
||||
{
|
||||
float frac = (_n2 - _n2Min) / (_n2Max - _n2Min);
|
||||
_torque = frac * _maxTorque * (_rho / _rho0);
|
||||
_fuelFlow = _bsfc * _torque * _omega;
|
||||
}
|
||||
|
||||
void TurbineEngine::stabilize()
|
||||
{
|
||||
_n2 = _n2Target;
|
||||
setOutputFromN2();
|
||||
}
|
||||
|
||||
void TurbineEngine::integrate(float dt)
|
||||
{
|
||||
// Low-pass the N2 speed to give a realistic spooling time. See
|
||||
// the notes in Jet::setSpooling() for details; this corresponds
|
||||
// to a hard-coded spool time of 2 seconds.
|
||||
const float DECAY = 1.15;
|
||||
_n2 = (_n2 + dt * DECAY * _n2Target)/(1 + dt * DECAY);
|
||||
setOutputFromN2();
|
||||
}
|
||||
|
||||
void TurbineEngine::calc(float pressure, float temp, float omega)
|
||||
{
|
||||
_omega = omega;
|
||||
_rho = Atmosphere::calcStdDensity(pressure, temp);
|
||||
|
||||
float torque = _throttle * _maxTorque * _rho / _rho0;
|
||||
float power = torque * omega;
|
||||
if(power > _flatRating)
|
||||
torque = _flatRating / omega;
|
||||
|
||||
float frac = torque / (_maxTorque * (_rho / _rho0));
|
||||
_n2Target = _n2Min + (_n2Max - _n2Min) * frac;
|
||||
}
|
||||
|
||||
}; // namespace yasim
|
46
src/FDM/YASim/TurbineEngine.hpp
Normal file
46
src/FDM/YASim/TurbineEngine.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef _TURBINEENGINE_HPP
|
||||
#define _TURBINEENGINE_HPP
|
||||
|
||||
#include "Engine.hpp"
|
||||
|
||||
namespace yasim {
|
||||
|
||||
class TurbineEngine : public Engine {
|
||||
public:
|
||||
virtual TurbineEngine* isTurbineEngine() { return this; }
|
||||
|
||||
TurbineEngine(float power, float omega, float alt, float flatRating);
|
||||
void setN2Range(float min, float max) { _n2Min = min; _n2Max = max; }
|
||||
void setFuelConsumption(float bsfc) { _bsfc = bsfc; }
|
||||
|
||||
virtual void calc(float pressure, float temp, float speed);
|
||||
virtual void stabilize();
|
||||
virtual void integrate(float dt);
|
||||
|
||||
virtual float getTorque() { return _torque; }
|
||||
virtual float getFuelFlow() { return _fuelFlow; }
|
||||
float getN2() { return _n2; }
|
||||
|
||||
private:
|
||||
void setOutputFromN2();
|
||||
|
||||
float _maxTorque;
|
||||
float _flatRating;
|
||||
float _rho0;
|
||||
float _bsfc; // SI units! kg/s per watt
|
||||
float _n2Min;
|
||||
float _n2Max;
|
||||
|
||||
float _n2Target;
|
||||
float _torqueTarget;
|
||||
float _fuelFlowTarget;
|
||||
|
||||
float _n2;
|
||||
float _rho;
|
||||
float _omega;
|
||||
float _torque;
|
||||
float _fuelFlow;
|
||||
};
|
||||
|
||||
}; // namespace yasim
|
||||
#endif // _TURBINEENGINE_HPP
|
Loading…
Add table
Reference in a new issue