1
0
Fork 0

Add electric engine support to YASim.

This commit is contained in:
Jakub Kákona 2020-01-11 23:02:33 +01:00
parent a9365cd34e
commit 1822d003db
5 changed files with 186 additions and 89 deletions

View file

@ -4,6 +4,7 @@ set(COMMON
Airplane.cpp
Atmosphere.cpp
ControlMap.cpp
ElectricEngine.cpp
FGFDM.cpp
Gear.cpp
Glue.cpp

View file

@ -0,0 +1,40 @@
//
// Based on original patch from Ian Dall <ian@beware.dropbear.id.au>
// Date: Wed Jan 11 22:35:24 2012 +1030
// #595 Support for electric motors in YASim (patch provided)
////////////////////////////////////////////////////////
#include "Atmosphere.hpp"
#include "Math.hpp"
#include "ElectricEngine.hpp"
namespace yasim {
// explain parameters!
ElectricEngine::ElectricEngine(float V, float Kv, float Rm) :
_Rm(Rm)
{
_running = false;
_omega0 = V * Kv;
_K = 1/Kv;
_torque0 = _K * _K * _omega0 / _Rm;
}
void ElectricEngine::calc(float pressure, float temp, float omega)
{
_running = (_throttle > _minThrottle);
// There are a huge variety of electronic speed controls and there
// is nothing to say that there isn't feedback to provide
// essentially an arbitrary relationship between throttle and
// omega. However, below is essentially equivalent to an idealised
// DC motor where the throttle controls the terminal voltage. PWM
// controllers in conjunction with the inductance of the windings
// should approximate this.
if (_running) {
_torque = ((_throttle - _minThrottle) / (1 - _minThrottle) - omega / _omega0) * _torque0;
}
else {
_torque = 0;
}
}
}; // namespace yasim

View file

@ -0,0 +1,41 @@
// Based on original patch from Ian Dall <ian@beware.dropbear.id.au>
// Date: Wed Jan 11 22:35:24 2012 +1030
// #595 Support for electric motors in YASim (patch provided)
////////////////////////////////////////////////////////
#ifndef _ELECTRICENGINE_HPP
#define _ELECTRICENGINE_HPP
#include "Engine.hpp"
namespace yasim {
class ElectricEngine : public Engine {
public:
virtual ElectricEngine* isElectricEngine() { return this; }
// Initializes an engine from known "takeoff" parameters.
// explain parameters: physical meaning? which dimensions (volts, meters, kilogram...)?
ElectricEngine(float V, float Kv, float Rm);
virtual void calc(float pressure, float temp, float speed);
virtual void stabilize() { return; };
virtual void integrate(float dt) { return; };
virtual float getTorque() { return _torque; };
virtual float getFuelFlow() { return 0; };
virtual float getOmega0() { return _omega0; };
private:
// Static configuration:
float _omega0 {0}; // Reference engine speed
float _minThrottle {0.05f}; // minimum throttle [0:1]
float _K {0}; // _K = Eb/omega = tau/Ia
float _Rm {1};
// Runtime state/output:
float _torque {0};
float _torque0 {1};
};
}; // namespace yasim
#endif // _ELECTRICENGINE_HPP

View file

@ -20,6 +20,7 @@
#include "Propeller.hpp"
#include "PistonEngine.hpp"
#include "TurbineEngine.hpp"
#include "ElectricEngine.hpp"
#include "Rotor.hpp"
#include "Rotorpart.hpp"
#include "Hitch.hpp"
@ -83,7 +84,7 @@ void FGFDM::iterate(float dt)
_airplane.setFuel(i, LBS2KG * _tank_level_lbs[i]->getFloatValue());
}
_airplane.calcFuelWeights();
setOutputProperties(dt);
}
@ -109,7 +110,7 @@ void FGFDM::init()
_yasimN->getNode("config-version",true)->setIntValue(_airplane.getVersion());
_yasimN->getNode("model/cg-x-min",true)->setFloatValue(_airplane.getCGHardLimitXMin());
_yasimN->getNode("model/cg-x-max",true)->setFloatValue(_airplane.getCGHardLimitXMax());
// prepare nodes for write at runtime
_cg_x = _yasimN->getNode("cg-x-m", true);
_cg_xmacN = _yasimN->getNode("cg-x-mac", true);
@ -127,7 +128,7 @@ void FGFDM::init()
_arxN = _yasimN->getNode("accelerations/arot-x", true);
_aryN = _yasimN->getNode("accelerations/arot-y", true);
_arzN = _yasimN->getNode("accelerations/arot-z", true);
// Allows the user to start with something other than full fuel
_airplane.setFuelFraction(fgGetFloat("/sim/fuel-fraction", 1));
@ -215,45 +216,46 @@ void FGFDM::startElement(const char* name, const XMLAttributes &a)
{
//XMLAttributes* a = (XMLAttributes*)&atts;
float v[3] {0,0,0};
if(!strcmp(name, "airplane")) { parseAirplane(&a); }
else if(!strcmp(name, "approach") || !strcmp(name, "cruise")) {
parseApproachCruise(&a, name);
}
else if(!strcmp(name, "solve-weight")) { parseSolveWeight(&a); }
else if(!strcmp(name, "approach") || !strcmp(name, "cruise")) {
parseApproachCruise(&a, name);
}
else if(!strcmp(name, "solve-weight")) { parseSolveWeight(&a); }
else if(!strcmp(name, "cockpit")) { parseCockpit(&a); }
else if(!strcmp(name, "rotor")) { parseRotor(&a, name); }
else if(!strcmp(name, "rotorgear")) { parseRotorGear(&a); }
else if(!strcmp(name, "wing") || !strcmp(name, "hstab") || !strcmp(name, "vstab") || !strcmp(name, "mstab")) {
parseWing(&a, name, &_airplane);
}
else if(!strcmp(name, "wing") || !strcmp(name, "hstab") || !strcmp(name, "vstab") || !strcmp(name, "mstab")) {
parseWing(&a, name, &_airplane);
}
else if(!strcmp(name, "piston-engine")) { parsePistonEngine(&a); }
else if(!strcmp(name, "turbine-engine")) { parseTurbineEngine(&a); }
else if(!strcmp(name, "propeller")) { parsePropeller(&a); }
else if(!strcmp(name, "electric-engine")) { parseElectricEngine(&a); }
else if(!strcmp(name, "propeller")) { parsePropeller(&a); }
else if(!strcmp(name, "thruster")) { parseThruster(&a); }
else if(!strcmp(name, "jet")) { parseJet(&a); }
else if(!strcmp(name, "jet")) { parseJet(&a); }
else if(!strcmp(name, "hitch")) { parseHitch(&a); }
else if(!strcmp(name, "tow")) { parseTow(&a); }
else if(!strcmp(name, "winch")) { parseWinch(&a); }
else if(!strcmp(name, "gear")) { parseGear(&a); }
else if(!strcmp(name, "hook")) { parseHook(&a); }
else if(!strcmp(name, "launchbar")) { parseLaunchbar(&a); }
else if(!strcmp(name, "fuselage")) { parseFuselage(&a); }
else if(!strcmp(name, "tank")) { parseTank(&a); }
else if(!strcmp(name, "ballast")) { parseBallast(&a); }
else if(!strcmp(name, "weight")) { parseWeight(&a); }
else if(!strcmp(name, "tow")) { parseTow(&a); }
else if(!strcmp(name, "winch")) { parseWinch(&a); }
else if(!strcmp(name, "gear")) { parseGear(&a); }
else if(!strcmp(name, "hook")) { parseHook(&a); }
else if(!strcmp(name, "launchbar")) { parseLaunchbar(&a); }
else if(!strcmp(name, "fuselage")) { parseFuselage(&a); }
else if(!strcmp(name, "tank")) { parseTank(&a); }
else if(!strcmp(name, "ballast")) { parseBallast(&a); }
else if(!strcmp(name, "weight")) { parseWeight(&a); }
else if(!strcmp(name, "stall")) { parseStall(&a); }
else if(!strcmp(name, "flap0") || !strcmp(name, "flap1") || !strcmp(name, "spoiler") || !strcmp(name, "slat")) {
parseFlap(&a, name);
}
}
else if(!strcmp(name, "actionpt")) {
attrf_xyz(&a, v);
((Thruster*)_currObj)->setPosition(v);
}
}
else if(!strcmp(name, "dir")) {
attrf_xyz(&a, v);
((Thruster*)_currObj)->setDirection(v);
}
}
else if(!strcmp(name, "control-setting")) { parseControlSetting(&a); }
else if(!strcmp(name, "control-input")) { parseControlIn(&a); }
else if(!strcmp(name, "control-output")) { parseControlOut(&a); }
@ -267,34 +269,34 @@ void FGFDM::startElement(const char* name, const XMLAttributes &a)
void FGFDM::parseAirplane(const XMLAttributes* a)
{
float f {0};
if(a->hasAttribute("mass")) { f = attrf(a, "mass") * LBS2KG; }
else if (a->hasAttribute("mass-lbs")) { f = attrf(a, "mass-lbs") * LBS2KG; }
if(a->hasAttribute("mass")) { f = attrf(a, "mass") * LBS2KG; }
else if (a->hasAttribute("mass-lbs")) { f = attrf(a, "mass-lbs") * LBS2KG; }
else if (a->hasAttribute("mass-kg")) { f = attrf(a, "mass-kg"); }
else {
SG_LOG(SG_FLIGHT,SG_ALERT,"YASim fatal: missing attribute, airplane needs one of {mass-lbs, mass-kg}");
exit(1);
exit(1);
}
_airplane.setEmptyWeight(f);
if(a->hasAttribute("version")) { _airplane.setVersion(a->getValue("version")); }
if( !_airplane.isVersionOrNewer( Version::YASIM_VERSION_CURRENT ) ) {
SG_LOG(SG_FLIGHT, SG_DEV_ALERT, "This aircraft does not use the latest yasim configuration version.");
}
_airplane.setDesiredCGRangeInPercentOfMAC(attrf(a, "cg-min", 0.25f), attrf(a, "cg-max", 0.3f));
_airplane.setDesiredCGRangeInPercentOfMAC(attrf(a, "cg-min", 0.25f), attrf(a, "cg-max", 0.3f));
if (a->hasAttribute("mtow-lbs")) { _airplane.setMTOW(attrf(a, "mtow-lbs") * LBS2KG); }
else if (a->hasAttribute("mtow-kg")) { _airplane.setMTOW(attrf(a, "mtow-kg")); }
if (a->hasAttribute("solver-mode")) { _airplane.setSolverMode(attri(a, "solver-mode")); }
if (a->hasAttribute("solver-mode")) { _airplane.setSolverMode(attri(a, "solver-mode")); }
}
void FGFDM::parseApproachCruise(const XMLAttributes* a, const char* name)
{
{
float spd, alt = 0;
if (a->hasAttribute("speed")) { spd = attrf(a, "speed") * KTS2MPS; }
else if (a->hasAttribute("speed-kt")) { spd = attrf(a, "speed-kt") * KTS2MPS; }
else if (a->hasAttribute("speed-kmh")) { spd = attrf(a, "speed-kmh") * KMH2MPS; }
else {
SG_LOG(SG_FLIGHT,SG_ALERT,"YASim fatal: missing attribute, "<< name << " needs one of {speed-kt, speed-kmh}");
exit(1);
exit(1);
}
if (a->hasAttribute("alt")) { alt = attrf(a, "alt") * FT2M; }
else if (a->hasAttribute("alt-ft")) { alt = attrf(a, "alt-ft") * FT2M; }
@ -320,7 +322,7 @@ void FGFDM::parseSolveWeight(const XMLAttributes* a)
else if(a->hasAttribute("weight-kg")) { f = attrf(a, "weight-kg"); }
else {
SG_LOG(SG_FLIGHT,SG_ALERT,"YASim fatal: missing attribute, solve-weight needs one of {weight-lbs, weight-kg}");
exit(1);
exit(1);
}
_airplane.addSolutionWeight(_airplaneCfg, idx, f);
}
@ -507,7 +509,7 @@ void FGFDM::setOutputProperties(float dt)
// cockpit code can scale them to the right values.
float pnorm = j->getPerfNorm();
moveprop(node, "oilp-norm", pnorm, dt/3); // 3s seek time
moveprop(node, "oilt-norm", pnorm, dt/30); // 30s
moveprop(node, "oilt-norm", pnorm, dt/30); // 30s
moveprop(node, "itt-norm", pnorm, dt/1); // 1s
}
}
@ -522,17 +524,17 @@ void FGFDM::parseWing(const XMLAttributes* a, const char* type, Airplane* airpla
defDihed = 90;
mirror = false;
}
float base[3] {0,0,0};
float chord {0};
float length = attrf(a, "length");
// positive incidence/twist means positive AoA (leading edge up).
// positive incidence/twist means positive AoA (leading edge up).
// Due to the coordinate system used in class Surface the sign will be inverted (only) there.
float incidence {0};
float twist = attrf(a, "twist", 0) * DEG2RAD;
// if this element is declared as section of a wing, skip attributes
// if this element is declared as section of a wing, skip attributes
// that are ignored in class Wing anyway because they are calculated
float isSection = attrb(a, "append");
if (!isSection) {
@ -542,12 +544,12 @@ void FGFDM::parseWing(const XMLAttributes* a, const char* type, Airplane* airpla
}
else {
if (a->hasAttribute("x") || a->hasAttribute("y") || a->hasAttribute("z") ||
a->hasAttribute("chord") || a->hasAttribute("incidence")
a->hasAttribute("chord") || a->hasAttribute("incidence")
) {
SG_LOG(SG_FLIGHT, SG_WARN, "YASim warning: redundant attribute in wing definition \n"
SG_LOG(SG_FLIGHT, SG_WARN, "YASim warning: redundant attribute in wing definition \n"
"when using <wing append=\"1\" ...> x, y, z, chord and incidence will be ignored. ");
}
}
}
// optional attributes (with defaults)
float sweep = attrf(a, "sweep", 0) * DEG2RAD;
@ -559,17 +561,17 @@ void FGFDM::parseWing(const XMLAttributes* a, const char* type, Airplane* airpla
if (!airplane->isVersionOrNewer(Version::YASIM_VERSION_2017_2) && (camber == 0)) {
SG_LOG(SG_FLIGHT, SG_DEV_WARN, "YASIM warning: versions before 2017.2 are buggy for wings with camber=0");
}
// The 70% is a magic number that sorta kinda seems to match known
// throttle settings to approach speed.
float idrag = 0.7*attrf(a, "idrag", 1);
// get wing object by type
Wing* w;
if (!strcmp(type, "wing"))
{
w = airplane->getWing();
}
}
else if (!strcmp(type, "hstab")) {
w = airplane->getTail();
if (a->hasAttribute("incidence-max-deg")) w->setIncidenceMax(attrf(a, "incidence-max-deg") * DEG2RAD);
@ -577,23 +579,23 @@ void FGFDM::parseWing(const XMLAttributes* a, const char* type, Airplane* airpla
} else {
w = new Wing(airplane, mirror);
}
// add section; if wing object has already section, base will be overridden
// add section; if wing object has already section, base will be overridden
// by tip of last section
_wingSection = w->addWingSection(base, chord, length, taper, sweep, dihedral, twist, camber, idrag, incidence);
if (!strcmp(type, "vstab") || !strcmp(type, "mstab"))
{
airplane->addVStab(w);
}
}
float dragFactor = attrf(a, "pdrag", 1);
if (a->hasAttribute("effectiveness")) {
/* FIXME:
/* FIXME:
* check if all attibutes have "good" names and update parser AND documentation together
* only after that issue warnings
SG_LOG(SG_FLIGHT, SG_ALERT, "Warning: " <<
"deprecated attribute 'effectiveness' in YASim configuration file. " <<
"Use 'pdrag' instead to add parasitic drag.");
*/
*/
dragFactor = attrf(a, "effectiveness", 1);
}
w->setSectionDrag(_wingSection, dragFactor);
@ -674,9 +676,9 @@ void FGFDM::parseRotor(const XMLAttributes* a, const char* type)
w->setTiltCenterZ(attrf(a,"tiltcenterz",0.0));
w->setDownwashFactor(attrf(a, "downwashfactor", 1));
if(attrb(a,"ccw"))
w->setCcw(1);
w->setCcw(1);
if(attrb(a,"sharedflaphinge"))
w->setSharedFlapHinge(true);
w->setSharedFlapHinge(true);
if(a->hasAttribute("name")) w->setName(a->getValue("name"));
if(a->hasAttribute("alphaout0")) w->setAlphaoutput(0,a->getValue("alphaout0"));
@ -692,7 +694,7 @@ void FGFDM::parseRotor(const XMLAttributes* a, const char* type)
w->setForceAtPitchA(attrf(a, "forceatpitch-a", 3000));
w->setPowerAtPitch0(attrf(a, "poweratpitch-0", 300));
w->setPowerAtPitchB(attrf(a, "poweratpitch-b", 3000));
if(attrb(a,"notorque")) w->setNotorque(1);
if(attrb(a,"notorque")) w->setNotorque(1);
#define p(x) if (a->hasAttribute(#x)) w->setParameter((char *)#x,attrf(a,#x) );
#define p2(x,y) if (a->hasAttribute(y)) w->setParameter((char *)#x,attrf(a,y) );
@ -726,7 +728,7 @@ void FGFDM::parseRotor(const XMLAttributes* a, const char* type)
#undef p
#undef p2
_currObj = w;
_airplane.getModel()->getRotorgear()->addRotor(w);
_airplane.getModel()->getRotorgear()->addRotor(w);
} //parseRotor
void FGFDM::parseRotorGear(const XMLAttributes* a)
@ -758,7 +760,7 @@ void FGFDM::parsePistonEngine(const XMLAttributes* a)
eng->setDisplacement(attrf(a, "displacement") * CIN2CM);
if(a->hasAttribute("compression"))
eng->setCompression(attrf(a, "compression"));
eng->setCompression(attrf(a, "compression"));
if(a->hasAttribute("min-throttle"))
eng->setMinThrottle(attrf(a, "min-throttle"));
@ -795,6 +797,18 @@ void FGFDM::parseTurbineEngine(const XMLAttributes* a)
((PropEngine*)_currObj)->setEngine(eng);
}
void FGFDM::parseElectricEngine(XMLAttributes* a)
{
//Kv is expected to be given as RPM in XML
float Kv = attrf(a, "Kv") * RPM2RAD;
float V = attrf(a, "V");
float Rm = attrf(a, "Rm");
ElectricEngine* eng = new ElectricEngine(V, Kv, Rm);
((PropEngine*)_currObj)->setEngine(eng);
}
void FGFDM::parsePropeller(const XMLAttributes* a)
{
// Legacy Handling for the old engines syntax:
@ -809,7 +823,7 @@ void FGFDM::parsePropeller(const XMLAttributes* a)
if(a->hasAttribute("displacement"))
eng->setDisplacement(attrf(a, "displacement") * CIN2CM);
if(a->hasAttribute("compression"))
eng->setCompression(attrf(a, "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;
@ -878,7 +892,7 @@ void FGFDM::parseThruster(const XMLAttributes* a)
_airplane.addThruster(j, 0, v);
v[0] = attrf(a, "vx"); v[1] = attrf(a, "vy"); v[2] = attrf(a, "vz");
j->setDirection(v);
j->setThrust(attrf(a, "thrust") * LBS2N);
j->setThrust(attrf(a, "thrust") * LBS2N);
}
void FGFDM::parseJet(const XMLAttributes* a)
@ -893,8 +907,8 @@ void FGFDM::parseJet(const XMLAttributes* a)
else if(a->hasAttribute("mass-kg")) { mass = attrf(a, "mass-kg"); }
else {
SG_LOG(SG_FLIGHT,SG_ALERT,"YASim fatal: missing attribute, jet needs one of {mass-lbs, mass-kg}");
exit(1);
}
exit(1);
}
j->setMaxThrust(attrf(a, "thrust") * LBS2N, attrf(a, "afterburner", 0) * LBS2N);
j->setVectorAngle(attrf(a, "rotate", 0) * DEG2RAD);
j->setReverseThrust(attrf(a, "reverse", 0.2));
@ -913,7 +927,7 @@ void FGFDM::parseJet(const XMLAttributes* a)
j->setVMax(attrf(a, "exhaust-speed") * KTS2MPS);
if(a->hasAttribute("spool-time"))
j->setSpooling(attrf(a, "spool-time"));
j->setPosition(v);
_airplane.addThruster(j, mass, v);
char buf[64];
@ -921,7 +935,7 @@ void FGFDM::parseJet(const XMLAttributes* a)
EngRec* er = new EngRec();
er->eng = j;
er->prefix = strdup(buf);
_thrusters.add(er);
_thrusters.add(er);
}
void FGFDM::parseHitch(const XMLAttributes* a)
@ -932,9 +946,9 @@ void FGFDM::parseHitch(const XMLAttributes* a)
attrf_xyz(a, v);
h->setPosition(v);
if(a->hasAttribute("force-is-calculated-by-other")) h->setForceIsCalculatedByOther(attrb(a,"force-is-calculated-by-other"));
_airplane.addHitch(h);
_airplane.addHitch(h);
}
void FGFDM::parseTow(const XMLAttributes* a)
{
Hitch* h = (Hitch*)_currObj;
@ -947,9 +961,9 @@ void FGFDM::parseTow(const XMLAttributes* a)
if(a->hasAttribute("weight-per-meter"))
h->setTowWeightPerM(attrf(a, "weight-per-meter"));
if(a->hasAttribute("mp-auto-connect-period"))
h->setMpAutoConnectPeriod(attrf(a, "mp-auto-connect-period"));
h->setMpAutoConnectPeriod(attrf(a, "mp-auto-connect-period"));
}
void FGFDM::parseWinch(const XMLAttributes* a)
{
Hitch* h = (Hitch*)_currObj;
@ -969,7 +983,7 @@ void FGFDM::parseWinch(const XMLAttributes* a)
if(a->hasAttribute("max-tow-length"))
h->setWinchMaxTowLength(attrf(a, "max-tow-length"));
if(a->hasAttribute("min-tow-length"))
h->setWinchMinTowLength(attrf(a, "min-tow-length"));
h->setWinchMinTowLength(attrf(a, "min-tow-length"));
}
void FGFDM::parseGear(const XMLAttributes* a)
@ -1009,7 +1023,7 @@ void FGFDM::parseGear(const XMLAttributes* a)
g->setReduceFrictionByExtension(attrf(a, "reduce-friction-by-extension", 0));
g->setStiction(attrf(a, "stiction", 0));
g->setStictionABS(attrf(a, "stiction-abs", 0));
_airplane.addGear(g);
_airplane.addGear(g);
}
void FGFDM::parseHook(const XMLAttributes* a)
@ -1045,7 +1059,7 @@ void FGFDM::parseLaunchbar(const XMLAttributes* a)
l->setDownAngle(attrf(a, "down-angle", 45) * DEG2RAD);
l->setUpAngle(attrf(a, "up-angle", -45) * DEG2RAD);
l->setHoldbackLength(attrf(a, "holdback-length", 2.0));
_airplane.addLaunchbar(l);
_airplane.addLaunchbar(l);
}
void FGFDM::parseFuselage(const XMLAttributes* a)
@ -1081,7 +1095,7 @@ void FGFDM::parseTank(const XMLAttributes* a)
float v[3];
attrf_xyz(a, v);
float density = 6.0; // gasoline, in lbs/gal
if(a->hasAttribute("jet")) density = 6.72;
if(a->hasAttribute("jet")) density = 6.72;
density *= LBS2KG*CM2GALS;
float capacity = 0;
if(a->hasAttribute("capacity")) { capacity = attrf(a, "capacity") * LBS2KG; }
@ -1089,7 +1103,7 @@ void FGFDM::parseTank(const XMLAttributes* a)
else if(a->hasAttribute("capacity-kg")) { capacity = attrf(a, "capacity-kg"); }
else {
SG_LOG(SG_FLIGHT,SG_ALERT,"YASim fatal: missing attribute, tank needs one of {capacity-lbs, capacity-kg}");
exit(1);
exit(1);
}
_airplane.addTank(v, capacity, density);
}
@ -1099,12 +1113,12 @@ void FGFDM::parseBallast(const XMLAttributes* a)
float v[3];
float f;
attrf_xyz(a, v);
if(a->hasAttribute("mass")) { f = attrf(a, "mass") * LBS2KG; }
else if (a->hasAttribute("mass-lbs")) { f = attrf(a, "mass-lbs") * LBS2KG; }
if(a->hasAttribute("mass")) { f = attrf(a, "mass") * LBS2KG; }
else if (a->hasAttribute("mass-lbs")) { f = attrf(a, "mass-lbs") * LBS2KG; }
else if (a->hasAttribute("mass-kg")) { f = attrf(a, "mass-kg"); }
else {
SG_LOG(SG_FLIGHT,SG_ALERT,"YASim fatal: missing attribute, airplane needs one of {mass-lbs, mass-kg}");
exit(1);
exit(1);
}
_airplane.addBallast(v, f);
}
@ -1145,7 +1159,7 @@ void FGFDM::parseFlap(const XMLAttributes* a, const char* name)
fp.end = attrf(a, "end");
if (!strcmp(name, "slat")) {
fp.aoa = attrf(a, "aoa");
}
}
else {
fp.lift = attrf(a, "lift");
}
@ -1173,7 +1187,7 @@ void FGFDM::parseControlSetting(const XMLAttributes* a)
void FGFDM::parseControlIn(const XMLAttributes* a)
{
// map input property to a YASim control
// map input property to a YASim control
ControlMap::ControlType control = ControlMap::parseControl(a->getValue("control"));
int opt = 0;
opt |= a->hasAttribute("split") ? ControlMap::OPT_SPLIT : 0;
@ -1251,7 +1265,7 @@ float FGFDM::attrf(const XMLAttributes* atts, const char* attr, float def)
{
const char* val = atts->getValue(attr);
if(val == 0) return def;
else return (float)atof(val);
else return (float)atof(val);
}
void FGFDM::attrf_xyz(const XMLAttributes* atts, float* out)

View file

@ -31,30 +31,30 @@ public:
float getVehicleRadius(void) const { return _vehicle_radius; }
private:
struct EngRec {
char* prefix {nullptr};
Thruster* eng {nullptr};
struct EngRec {
char* prefix {nullptr};
Thruster* eng {nullptr};
};
struct WeightRec {
struct WeightRec {
char* prop {nullptr};
float size {0};
int handle {0};
};
struct ControlOutput {
struct ControlOutput {
int handle {0};
SGPropertyNode* prop {nullptr};
ControlMap::ControlType control;
bool left {false};
float min {0};
float max {0};
float max {0};
};
void parseAirplane(const XMLAttributes* a);
void parseApproachCruise(const XMLAttributes* a, const char* name);
void parseSolveWeight(const XMLAttributes* a);
void parseCockpit(const XMLAttributes* a);
void setOutputProperties(float dt);
void parseRotor(const XMLAttributes* a, const char* name);
@ -64,9 +64,10 @@ private:
void parseWeight(const XMLAttributes* a);
void parseStall(const XMLAttributes* a);
void parseFlap(const XMLAttributes* a, const char* name);
void parseTurbineEngine(const XMLAttributes* a);
void parsePistonEngine(const XMLAttributes* a);
void parseElectricEngine(const XMLAttributes* a);
void parsePropeller(const XMLAttributes* a);
void parseThruster(const XMLAttributes* a);
void parseJet(const XMLAttributes* a);
@ -83,15 +84,15 @@ private:
void parseControlIn(const XMLAttributes* a);
void parseControlOut(const XMLAttributes* a);
void parseControlSpeed(const XMLAttributes* a);
int attri(const XMLAttributes* atts, const char* attr);
int attri(const XMLAttributes* atts, const char* attr, int def);
int attri(const XMLAttributes* atts, const char* attr, int def);
float attrf(const XMLAttributes* atts, const char* attr);
float attrf(const XMLAttributes* atts, const char* attr, float def);
float attrf(const XMLAttributes* atts, const char* attr, float def);
void attrf_xyz(const XMLAttributes* atts, float* out);
double attrd(const XMLAttributes* atts, const char* attr);
double attrd(const XMLAttributes* atts, const char* attr, double def);
double attrd(const XMLAttributes* atts, const char* attr, double def);
bool attrb(const XMLAttributes* atts, const char* attr);
// The core Airplane object we manage.