+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include "TurbineEngine.hpp"
#include "Rotor.hpp"
#include "Rotorpart.hpp"
-#include "Rotorblade.hpp"
+#include "Hitch.hpp"
#include "FGFDM.hpp"
FGFDM::~FGFDM()
{
- int i;
- for(i=0; i<_axes.size(); i++) {
- AxisRec* a = (AxisRec*)_axes.get(i);
- delete[] a->name;
- delete a;
+ for(int i=0; i<_axes.size(); i++) {
+ AxisRec* a = (AxisRec*)_axes.get(i);
+ delete[] a->name;
+ delete a;
}
- for(i=0; i<_thrusters.size(); i++) {
- EngRec* er = (EngRec*)_thrusters.get(i);
- delete[] er->prefix;
- delete er->eng;
- delete er;
+
+ for(int i=0; i<_thrusters.size(); i++) {
+ EngRec* er = (EngRec*)_thrusters.get(i);
+ delete[] er->prefix;
+ delete er->eng;
+ delete er;
}
- for(i=0; i<_weights.size(); i++) {
- WeightRec* wr = (WeightRec*)_weights.get(i);
- delete[] wr->prop;
- delete wr;
+
+ for(int i=0; i<_weights.size(); i++) {
+ WeightRec* wr = (WeightRec*)_weights.get(i);
+ delete[] wr->prop;
+ delete wr;
}
- for(i=0; i<_controlProps.size(); i++)
+
+ for(int i=0; i<_controlProps.size(); i++)
delete (PropOut*)_controlProps.get(i);
+
+ delete _turb;
}
void FGFDM::iterate(float dt)
getExternalInput(dt);
_airplane.iterate(dt);
- // Do fuel stuff (FIXME: should stash SGPropertyNode objects here)
- char buf[256];
+ // Do fuel stuff
for(int i=0; i<_airplane.numThrusters(); i++) {
Thruster* t = _airplane.getThruster(i);
- sprintf(buf, "/engines/engine[%d]/out-of-fuel", i);
- t->setFuelState(!fgGetBool(buf));
+ bool out_of_fuel = _fuel_props[i]._out_of_fuel->getBoolValue();
+ t->setFuelState(!out_of_fuel);
- sprintf(buf, "/engines/engine[%d]/fuel-consumed-lbs", i);
- double consumed = fgGetDouble(buf) + dt * KG2LBS * t->getFuelFlow();
- fgSetDouble(buf, consumed);
+ double consumed = _fuel_props[i]._fuel_consumed_lbs->getDoubleValue();
+ _fuel_props[i]._fuel_consumed_lbs->setDoubleValue(
+ consumed + dt * KG2LBS * t->getFuelFlow());
}
for(int i=0; i<_airplane.numTanks(); i++) {
- sprintf(buf, "/consumables/fuel/tank[%d]/level-lbs", i);
- _airplane.setFuel(i, LBS2KG * fgGetFloat(buf));
- }
+ _airplane.setFuel(i, LBS2KG * _tank_level_lbs[i]->getFloatValue());
+ }
_airplane.calcFuelWeights();
setOutputProperties(dt);
void FGFDM::init()
{
+ _turb_magnitude_norm = fgGetNode("/environment/turbulence/magnitude-norm", true);
+ _turb_rate_hz = fgGetNode("/environment/turbulence/rate-hz", true);
+ _gross_weight_lbs = fgGetNode("/yasim/gross-weight-lbs", true);
+
// Allows the user to start with something other than full fuel
_airplane.setFuelFraction(fgGetFloat("/sim/fuel-fraction", 1));
- // Read out the resulting fuel state
- char buf[256];
+ // Read out the resulting fuel state and stash engine/thruster properties
+ _thrust_props.clear();
+ for (int i=0; i<_thrusters.size(); i++) {
+ SGPropertyNode_ptr node = fgGetNode("engines/engine", i, true);
+ Thruster* t = ((EngRec*)_thrusters.get(i))->eng;
+
+ ThrusterProps tp;
+ tp._running = node->getChild("running", 0, true);
+ tp._cranking = node->getChild("cranking", 0, true);
+ tp._prop_thrust = node->getChild("prop-thrust", 0, true); // Deprecated name
+ tp._thrust_lbs = node->getChild("thrust-lbs", 0, true);
+ tp._fuel_flow_gph = node->getChild("fuel-flow-gph", 0, true);
+
+ if(t->getPropEngine())
+ {
+ tp._rpm = node->getChild("rpm", 0, true);
+ tp._torque_ftlb = node->getChild("torque-ftlb", 0, true);
+
+ PropEngine* p = t->getPropEngine();
+ if(p->getEngine()->isPistonEngine())
+ {
+ tp._mp_osi = node->getChild("mp-osi", 0, true);
+ tp._mp_inhg = node->getChild("mp-inhg", 0, true);
+ tp._egt_degf = node->getChild("egt-degf", 0, true);
+
+ tp._oil_temperature_degf = node->getChild("oil-temperature-degf", 0, true);
+ tp._boost_gauge_inhg = node->getChild("boost-gauge-inhg", 0, true);
+ } else if(p->getEngine()->isTurbineEngine()) {
+ tp._n2 = node->getChild("n2", 0, true);
+ }
+ }
+
+ if(t->getJet())
+ {
+ tp._n1 = node->getChild("n1", 0, true);
+ tp._n2 = node->getChild("n2", 0, true);
+ tp._epr = node->getChild("epr", 0, true);
+ tp._egt_degf = node->getChild("egt-degf", 0, true);
+ }
+ _thrust_props.push_back(tp);
+ }
+
+ // stash properties for engines/fuel state
+ _thrust_props.clear();
+ for(int i=0; i<_airplane.numThrusters(); i++) {
+ SGPropertyNode_ptr e = fgGetNode("engines/engine", i, true);
+ FuelProps f;
+ f._out_of_fuel = e->getChild("out-of-fuel", 0, true);
+ f._fuel_consumed_lbs = e->getChild("fuel-consumed-lbs", 0, true);
+ _fuel_props.push_back(f);
+ }
+
+ // initialize tanks and stash properties for tank level
+ _tank_level_lbs.clear();
for(int i=0; i<_airplane.numTanks(); i++) {
+ char buf[256];
sprintf(buf, "/consumables/fuel/tank[%d]/level-lbs", i);
fgSetDouble(buf, _airplane.getFuel(i) * KG2LBS);
+ _tank_level_lbs.push_back(fgGetNode(buf, true));
double density = _airplane.getFuelDensity(i);
sprintf(buf, "/consumables/fuel/tank[%d]/density-ppg", i);
fgSetDouble(buf, density * (KG2LBS/CM2GALS));
- sprintf(buf, "/consumables/fuel/tank[%d]/level-gal_us", i);
- fgSetDouble(buf, _airplane.getFuel(i) * CM2GALS / density);
+// set in TankProperties class
+// sprintf(buf, "/consumables/fuel/tank[%d]/level-gal_us", i);
+// fgSetDouble(buf, _airplane.getFuel(i) * CM2GALS / density);
sprintf(buf, "/consumables/fuel/tank[%d]/capacity-gal_us", i);
fgSetDouble(buf, CM2GALS * _airplane.getTankCapacity(i)/density);
- }
+ }
// This has a nasty habit of being false at startup. That's not
// good.
float spd = attrf(a, "speed") * KTS2MPS;
float alt = attrf(a, "alt", 0) * FT2M;
float aoa = attrf(a, "aoa", 0) * DEG2RAD;
- _airplane.setApproach(spd, alt, aoa, attrf(a, "fuel", 0.2));
+ float gla = attrf(a, "glide-angle", 0) * DEG2RAD;
+ _airplane.setApproach(spd, alt, aoa, attrf(a, "fuel", 0.2),gla);
_cruiseCurr = false;
} else if(eq(name, "cruise")) {
float spd = attrf(a, "speed") * KTS2MPS;
float alt = attrf(a, "alt") * FT2M;
- _airplane.setCruise(spd, alt, attrf(a, "fuel", 0.5));
+ float gla = attrf(a, "glide-angle", 0) * DEG2RAD;
+ _airplane.setCruise(spd, alt, attrf(a, "fuel", 0.5),gla);
_cruiseCurr = true;
} else if(eq(name, "solve-weight")) {
int idx = attri(a, "idx");
v[2] = attrf(a, "z");
_airplane.setPilotPos(v);
} else if(eq(name, "rotor")) {
- _airplane.addRotor(parseRotor(a, name));
+ _airplane.getModel()->getRotorgear()->addRotor(parseRotor(a, name));
+ } else if(eq(name, "rotorgear")) {
+ Rotorgear* r = _airplane.getModel()->getRotorgear();
+ _currObj = r;
+ #define p(x) if (a->hasAttribute(#x)) r->setParameter((char *)#x,attrf(a,#x) );
+ #define p2(x,y) if (a->hasAttribute(y)) r->setParameter((char *)#x,attrf(a,y) );
+ p2(max_power_engine,"max-power-engine")
+ p2(engine_prop_factor,"engine-prop-factor")
+ p(yasimdragfactor)
+ p(yasimliftfactor)
+ p2(max_power_rotor_brake,"max-power-rotor-brake")
+ p2(rotorgear_friction,"rotorgear-friction")
+ p2(engine_accel_limit,"engine-accel-limit")
+ #undef p
+ #undef p2
+ r->setInUse();
} else if(eq(name, "wing")) {
_airplane.setWing(parseWing(a, name));
} else if(eq(name, "hstab")) {
er->eng = j;
er->prefix = dup(buf);
_thrusters.add(er);
+ } else if(eq(name, "hitch")) {
+ Hitch* h = new Hitch(a->getValue("name"));
+ _currObj = h;
+ v[0] = attrf(a, "x");
+ v[1] = attrf(a, "y");
+ v[2] = attrf(a, "z");
+ h->setPosition(v);
+ if(a->hasAttribute("force-is-calculated-by-other")) h->setForceIsCalculatedByOther(attrb(a,"force-is-calculated-by-other"));
+ _airplane.addHitch(h);
+ } else if(eq(name, "tow")) {
+ Hitch* h = (Hitch*)_currObj;
+ if(a->hasAttribute("length"))
+ h->setTowLength(attrf(a, "length"));
+ if(a->hasAttribute("elastic-constant"))
+ h->setTowElasticConstant(attrf(a, "elastic-constant"));
+ if(a->hasAttribute("break-force"))
+ h->setTowBreakForce(attrf(a, "break-force"));
+ 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"));
+ } else if(eq(name, "winch")) {
+ Hitch* h = (Hitch*)_currObj;
+ double pos[3];
+ pos[0] = attrd(a, "x",0);
+ pos[1] = attrd(a, "y",0);
+ pos[2] = attrd(a, "z",0);
+ h->setWinchPosition(pos);
+ if(a->hasAttribute("max-speed"))
+ h->setWinchMaxSpeed(attrf(a, "max-speed"));
+ if(a->hasAttribute("power"))
+ h->setWinchPower(attrf(a, "power") * 1000);
+ if(a->hasAttribute("max-force"))
+ h->setWinchMaxForce(attrf(a, "max-force"));
+ if(a->hasAttribute("initial-tow-length"))
+ h->setWinchInitialTowLength(attrf(a, "initial-tow-length"));
+ 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"));
} else if(eq(name, "gear")) {
Gear* g = new Gear();
_currObj = g;
v[i] *= attrf(a, "compression", 1);
g->setCompression(v);
g->setBrake(attrf(a, "skid", 0));
+ g->setInitialLoad(attrf(a, "initial-load", 0));
g->setStaticFriction(attrf(a, "sfric", 0.8));
g->setDynamicFriction(attrf(a, "dfric", 0.7));
g->setSpring(attrf(a, "spring", 1));
g->setDamping(attrf(a, "damp", 1));
+ if(a->hasAttribute("on-water")) g->setOnWater(attrb(a,"on-water"));
+ if(a->hasAttribute("on-solid")) g->setOnSolid(attrb(a,"on-solid"));
+ if(a->hasAttribute("ignored-by-solver")) g->setIgnoreWhileSolving(attrb(a,"ignored-by-solver"));
+ g->setSpringFactorNotPlaning(attrf(a, "spring-factor-not-planing", 1));
+ g->setSpeedPlaning(attrf(a, "speed-planing", 0) * KTS2MPS);
+ g->setReduceFrictionByExtension(attrf(a, "reduce-friction-by-extension", 0));
_airplane.addGear(g);
} else if(eq(name, "hook")) {
Hook* h = new Hook();
l->setHoldbackMount(v);
float length = attrf(a, "length", 1.0);
l->setLength(length);
- l->setDownAngle(attrf(a, "down-angle", 30) * DEG2RAD);
- l->setUpAngle(attrf(a, "up-angle", -30) * DEG2RAD);
+ 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);
} else if(eq(name, "fuselage")) {
float b[3];
b[2] = attrf(a, "bz");
float taper = attrf(a, "taper", 1);
float mid = attrf(a, "midpoint", 0.5);
- _airplane.addFuselage(v, b, attrf(a, "width"), taper, mid);
+ float cx = attrf(a, "cx", 1);
+ float cy = attrf(a, "cy", 1);
+ float cz = attrf(a, "cz", 1);
+ float idrag = attrf(a, "idrag", 1);
+ _airplane.addFuselage(v, b, attrf(a, "width"), taper, mid,
+ cx, cy, cz, idrag);
} else if(eq(name, "tank")) {
v[0] = attrf(a, "x");
v[1] = attrf(a, "y");
{
char buf[256];
- _turb->setMagnitude(fgGetFloat("/environment/turbulence/magnitude-norm"));
- _turb->update(dt, fgGetFloat("/environment/turbulence/rate-hz"));
+ _turb->setMagnitude(_turb_magnitude_norm->getFloatValue());
+ _turb->update(dt, _turb_rate_hz->getFloatValue());
// The control axes
ControlMap* cm = _airplane.getControlMap();
cm->reset();
- int i;
- for(i=0; i<_axes.size(); i++) {
- AxisRec* a = (AxisRec*)_axes.get(i);
- float val = fgGetFloat(a->name, 0);
- cm->setInput(a->handle, val);
+
+ for(int i=0; i<_axes.size(); i++) {
+ AxisRec* a = (AxisRec*)_axes.get(i);
+ float val = fgGetFloat(a->name, 0);
+ cm->setInput(a->handle, val);
}
cm->applyControls(dt);
// Weights
- for(i=0; i<_weights.size(); i++) {
- WeightRec* wr = (WeightRec*)_weights.get(i);
- _airplane.setWeight(wr->handle, LBS2KG * fgGetFloat(wr->prop));
+ for(int i=0; i<_weights.size(); i++) {
+ WeightRec* wr = (WeightRec*)_weights.get(i);
+ _airplane.setWeight(wr->handle, LBS2KG * fgGetFloat(wr->prop));
}
- for(i=0; i<_thrusters.size(); i++) {
- EngRec* er = (EngRec*)_thrusters.get(i);
+ for(int i=0; i<_thrusters.size(); i++) {
+ EngRec* er = (EngRec*)_thrusters.get(i);
Thruster* t = er->eng;
- if(t->getPropEngine()) {
+ if(t->getPropEngine()) {
PropEngine* p = t->getPropEngine();
sprintf(buf, "%s/rpm", er->prefix);
p->setOmega(fgGetFloat(buf, 500) * RPM2RAD);
void FGFDM::setOutputProperties(float dt)
{
- // char buf[256];
- int i;
-
float grossWgt = _airplane.getModel()->getBody()->getTotalMass() * KG2LBS;
- fgSetFloat("/yasim/gross-weight-lbs", grossWgt);
+ _gross_weight_lbs->setFloatValue(grossWgt);
ControlMap* cm = _airplane.getControlMap();
- for(i=0; i<_controlProps.size(); i++) {
+ for(int i=0; i<_controlProps.size(); i++) {
PropOut* p = (PropOut*)_controlProps.get(i);
float val = (p->left
? cm->getOutput(p->handle)
p->prop->setFloatValue(val);
}
- for(i=0; i<_airplane.getNumRotors(); i++) {
- Rotor*r=(Rotor*)_airplane.getRotor(i);
+ for(int i=0; i<_airplane.getRotorgear()->getNumRotors(); i++) {
+ Rotor*r=(Rotor*)_airplane.getRotorgear()->getRotor(i);
int j = 0;
float f;
char b[256];
- while(j = r->getValueforFGSet(j, b, &f))
+ while((j = r->getValueforFGSet(j, b, &f)))
if(b[0]) fgSetFloat(b,f);
-
- for(j=0; j < r->numRotorparts(); j++) {
+ j=0;
+ while((j = _airplane.getRotorgear()->getValueforFGSet(j, b, &f)))
+ if(b[0]) fgSetFloat(b,f);
+ for(j=0; j < r->numRotorparts(); j+=r->numRotorparts()>>2) {
Rotorpart* s = (Rotorpart*)r->getRotorpart(j);
char *b;
int k;
if(b[0]) fgSetFloat(b, s->getAlpha(k));
}
}
- for(j=0; j < r->numRotorblades(); j++) {
- Rotorblade* s = (Rotorblade*)r->getRotorblade(j);
- char *b;
- int k;
- for (k=0; k<2; k++) {
- b = s->getAlphaoutput(k);
- if(b[0]) fgSetFloat(b, s->getAlpha(k));
- }
- }
}
- float fuelDensity = _airplane.getFuelDensity(0); // HACK
- for(i=0; i<_thrusters.size(); i++) {
- EngRec* er = (EngRec*)_thrusters.get(i);
+ // Use the density of the first tank, or a dummy value if no tanks
+ float fuelDensity = 1.0;
+ if(_airplane.numTanks())
+ fuelDensity = _airplane.getFuelDensity(0);
+ for(int i=0; i<_thrusters.size(); i++) {
+ EngRec* er = (EngRec*)_thrusters.get(i);
Thruster* t = er->eng;
SGPropertyNode * node = fgGetNode("engines/engine", i, true);
+ ThrusterProps& tp = _thrust_props[i];
+
// Set: running, cranking, prop-thrust, max-hp, power-pct
- node->setBoolValue("running", t->isRunning());
- node->setBoolValue("cranking", t->isCranking());
+ tp._running->setBoolValue(t->isRunning());
+ tp._cranking->setBoolValue(t->isCranking());
float tmp[3];
t->getThrust(tmp);
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);
+ tp._prop_thrust->setFloatValue(lbs); // Deprecated name
+ tp._thrust_lbs->setFloatValue(lbs);
+ tp._fuel_flow_gph->setFloatValue(
+ (t->getFuelFlow()/fuelDensity) * 3600 * CM2GALS);
- if(t->getPropEngine()) {
+ if(t->getPropEngine()) {
PropEngine* p = t->getPropEngine();
- node->setFloatValue("rpm", p->getOmega() * (1/RPM2RAD));
- node->setFloatValue("torque-ftlb",
- p->getEngine()->getTorque() * NM2FTLB);
-
+ tp._rpm->setFloatValue(p->getOmega() * (1/RPM2RAD));
+ tp._torque_ftlb->setFloatValue(
+ 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);
- node->setFloatValue("oil-temperature-degf",
- pe->getOilTemp() * K2DEGF + K2DEGFOFFSET);
- node->setFloatValue("boost-gauge-inhg",
- pe->getBoost() * (1/INHG2PA));
+ tp._mp_osi->setFloatValue(pe->getMP() * (1/INHG2PA));
+ tp._mp_inhg->setFloatValue(pe->getMP() * (1/INHG2PA));
+ tp._egt_degf->setFloatValue(
+ pe->getEGT() * K2DEGF + K2DEGFOFFSET);
+ tp._oil_temperature_degf->setFloatValue(
+ pe->getOilTemp() * K2DEGF + K2DEGFOFFSET);
+ tp._boost_gauge_inhg->setFloatValue(
+ pe->getBoost() * (1/INHG2PA));
} else if(p->getEngine()->isTurbineEngine()) {
TurbineEngine* te = p->getEngine()->isTurbineEngine();
- node->setFloatValue("n2", te->getN2());
+ tp._n2->setFloatValue(te->getN2());
}
}
if(t->getJet()) {
Jet* j = t->getJet();
- node->setFloatValue("n1", j->getN1());
- node->setFloatValue("n2", j->getN2());
- node->setFloatValue("epr", j->getEPR());
- node->setFloatValue("egt-degf",
- j->getEGT() * K2DEGF + K2DEGFOFFSET);
+ tp._n1->setFloatValue(j->getN1());
+ tp._n2->setFloatValue(j->getN2());
+ tp._epr->setFloatValue(j->getEPR());
+ tp._egt_degf->setFloatValue(
+ j->getEGT() * K2DEGF + K2DEGFOFFSET);
// These are "unmodeled" values that are still needed for
// many cockpits. Tie them all to the N1 speed, but
w->setTranslift(attrf(a, "translift", 0.05));
w->setC2(attrf(a, "dragfactor", 1));
w->setStepspersecond(attrf(a, "stepspersecond", 120));
+ w->setPhiNull((attrf(a, "phi0", 0))*YASIM_PI/180);
w->setRPM(attrf(a, "rpm", 424));
w->setRelLenHinge(attrf(a, "rellenflaphinge", 0.07));
w->setAlpha0((attrf(a, "flap0", -5))*YASIM_PI/180);
w->setTeeterdamp(attrf(a,"teeterdamp",.0001));
w->setMaxteeterdamp(attrf(a,"maxteeterdamp",1000));
w->setRelLenTeeterHinge(attrf(a,"rellenteeterhinge",0.01));
- void setAlphamin(float f);
- void setAlphamax(float f);
- void setAlpha0factor(float f);
-
+ w->setBalance(attrf(a,"balance",1.0));
+ w->setMinTiltYaw(attrf(a,"mintiltyaw",0.0));
+ w->setMinTiltPitch(attrf(a,"mintiltpitch",0.0));
+ w->setMinTiltRoll(attrf(a,"mintiltroll",0.0));
+ w->setMaxTiltYaw(attrf(a,"maxtiltyaw",0.0));
+ w->setMaxTiltPitch(attrf(a,"maxtiltpitch",0.0));
+ w->setMaxTiltRoll(attrf(a,"maxtiltroll",0.0));
+ w->setTiltCenterX(attrf(a,"tiltcenterx",0.0));
+ w->setTiltCenterY(attrf(a,"tiltcentery",0.0));
+ w->setTiltCenterZ(attrf(a,"tiltcenterz",0.0));
+ w->setDownwashFactor(attrf(a, "downwashfactor", 1));
if(attrb(a,"ccw"))
w->setCcw(1);
-
+ if(attrb(a,"sharedflaphinge"))
+ w->setSharedFlapHinge(true);
+
if(a->hasAttribute("name"))
w->setName(a->getValue("name") );
if(a->hasAttribute("alphaout0"))
if(a->hasAttribute("yawout")) w->setAlphaoutput(5,a->getValue("yawout") );
if(a->hasAttribute("rollout")) w->setAlphaoutput(6,a->getValue("rollout") );
- w->setPitchA(attrf(a, "pitch_a", 10));
- w->setPitchB(attrf(a, "pitch_b", 10));
- w->setForceAtPitchA(attrf(a, "forceatpitch_a", 3000));
- w->setPowerAtPitch0(attrf(a, "poweratpitch_0", 300));
- w->setPowerAtPitchB(attrf(a, "poweratpitch_b", 3000));
+ w->setPitchA(attrf(a, "pitch-a", 10));
+ w->setPitchB(attrf(a, "pitch-b", 10));
+ 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,"simblades"))
- w->setSimBlades(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) );
+ p2(translift_ve,"translift-ve")
+ p2(translift_maxfactor,"translift-maxfactor")
+ p2(ground_effect_constant,"ground-effect-constant")
+ p2(vortex_state_lift_factor,"vortex-state-lift-factor")
+ p2(vortex_state_c1,"vortex-state-c1")
+ p2(vortex_state_c2,"vortex-state-c2")
+ p2(vortex_state_c3,"vortex-state_c3")
+ p2(vortex_state_e1,"vortex-state-e1")
+ p2(vortex_state_e2,"vortex-state-e2")
+ p(twist)
+ p2(number_of_segments,"number-of-segments")
+ p2(number_of_parts,"number-of-parts")
+ p2(rel_len_where_incidence_is_measured,"rel-len-where-incidence-is-measured")
+ p(chord)
+ p(taper)
+ p2(airfoil_incidence_no_lift,"airfoil-incidence-no-lift")
+ p2(rel_len_blade_start,"rel-len-blade-start")
+ p2(incidence_stall_zero_speed,"incidence-stall-zero-speed")
+ p2(incidence_stall_half_sonic_speed,"incidence-stall-half-sonic-speed")
+ p2(lift_factor_stall,"lift-factor-stall")
+ p2(stall_change_over,"stall-change-over")
+ p2(drag_factor_stall,"drag-factor-stall")
+ p2(airfoil_lift_coefficient,"airfoil-lift-coefficient")
+ p2(airfoil_drag_coefficient0,"airfoil-drag-coefficient0")
+ p2(airfoil_drag_coefficient1,"airfoil-drag-coefficient1")
+ p2(cyclic_factor,"cyclic-factor")
+ p2(rotor_correction_factor,"rotor-correction-factor")
+#undef p
+#undef p2
_currObj = w;
return w;
}
if(a->hasAttribute("compression"))
eng->setCompression(attrf(a, "compression"));
+ if(a->hasAttribute("min-throttle"))
+ eng->setMinThrottle(attrf(a, "min-throttle"));
+
if(a->hasAttribute("turbo-mul")) {
float mul = attrf(a, "turbo-mul");
float mp = attrf(a, "wastegate-mp", 1e6) * INHG2PA;
eng->setTurboParams(mul, mp);
+ eng->setTurboLag(attrf(a, "turbo-lag", 2));
}
if(a->hasAttribute("supercharger"))
// yet.
int FGFDM::parseAxis(const char* name)
{
- int i;
- for(i=0; i<_axes.size(); i++) {
- AxisRec* a = (AxisRec*)_axes.get(i);
- if(eq(a->name, name))
- return a->handle;
+ for(int i=0; i<_axes.size(); i++) {
+ AxisRec* a = (AxisRec*)_axes.get(i);
+ if(eq(a->name, name))
+ return a->handle;
}
// Not there, make a new one.
if(eq(name, "EXTEND")) return ControlMap::EXTEND;
if(eq(name, "HEXTEND")) return ControlMap::HEXTEND;
if(eq(name, "LEXTEND")) return ControlMap::LEXTEND;
+ if(eq(name, "LACCEL")) return ControlMap::LACCEL;
if(eq(name, "INCIDENCE")) return ControlMap::INCIDENCE;
if(eq(name, "FLAP0")) return ControlMap::FLAP0;
+ if(eq(name, "FLAP0EFFECTIVENESS")) return ControlMap::FLAP0EFFECTIVENESS;
if(eq(name, "FLAP1")) return ControlMap::FLAP1;
+ if(eq(name, "FLAP1EFFECTIVENESS")) return ControlMap::FLAP1EFFECTIVENESS;
if(eq(name, "SLAT")) return ControlMap::SLAT;
if(eq(name, "SPOILER")) return ControlMap::SPOILER;
if(eq(name, "CASTERING")) return ControlMap::CASTERING;
if(eq(name, "COLLECTIVE")) return ControlMap::COLLECTIVE;
if(eq(name, "CYCLICAIL")) return ControlMap::CYCLICAIL;
if(eq(name, "CYCLICELE")) return ControlMap::CYCLICELE;
- if(eq(name, "ROTORENGINEON")) return ControlMap::ROTORENGINEON;
+ if(eq(name, "TILTROLL")) return ControlMap::TILTROLL;
+ if(eq(name, "TILTPITCH")) return ControlMap::TILTPITCH;
+ if(eq(name, "TILTYAW")) return ControlMap::TILTYAW;
+ if(eq(name, "ROTORGEARENGINEON")) return ControlMap::ROTORENGINEON;
+ if(eq(name, "ROTORBRAKE")) return ControlMap::ROTORBRAKE;
+ if(eq(name, "ROTORENGINEMAXRELTORQUE"))
+ return ControlMap::ROTORENGINEMAXRELTORQUE;
+ if(eq(name, "ROTORRELTARGET")) return ControlMap::ROTORRELTARGET;
+ if(eq(name, "ROTORBALANCE")) return ControlMap::ROTORBALANCE;
if(eq(name, "REVERSE_THRUST")) return ControlMap::REVERSE_THRUST;
+ if(eq(name, "WASTEGATE")) return ControlMap::WASTEGATE;
+ if(eq(name, "WINCHRELSPEED")) return ControlMap::WINCHRELSPEED;
+ if(eq(name, "HITCHOPEN")) return ControlMap::HITCHOPEN;
+ if(eq(name, "PLACEWINCH")) return ControlMap::PLACEWINCH;
+ if(eq(name, "FINDAITOW")) return ControlMap::FINDAITOW;
+
SG_LOG(SG_FLIGHT,SG_ALERT,"Unrecognized control type '"
<< name << "' in YASim aircraft description.");
exit(1);
return s2;
}
-int FGFDM::attri(XMLAttributes* atts, char* attr)
+int FGFDM::attri(XMLAttributes* atts, const char* attr)
{
if(!atts->hasAttribute(attr)) {
SG_LOG(SG_FLIGHT,SG_ALERT,"Missing '" << attr <<
return attri(atts, attr, 0);
}
-int FGFDM::attri(XMLAttributes* atts, char* attr, int def)
+int FGFDM::attri(XMLAttributes* atts, const char* attr, int def)
{
const char* val = atts->getValue(attr);
if(val == 0) return def;
else return atol(val);
}
-float FGFDM::attrf(XMLAttributes* atts, char* attr)
+float FGFDM::attrf(XMLAttributes* atts, const char* attr)
{
if(!atts->hasAttribute(attr)) {
SG_LOG(SG_FLIGHT,SG_ALERT,"Missing '" << attr <<
return attrf(atts, attr, 0);
}
-float FGFDM::attrf(XMLAttributes* atts, char* attr, float def)
+float FGFDM::attrf(XMLAttributes* atts, const char* attr, float def)
{
const char* val = atts->getValue(attr);
if(val == 0) return def;
else return (float)atof(val);
}
+double FGFDM::attrd(XMLAttributes* atts, const char* attr)
+{
+ if(!atts->hasAttribute(attr)) {
+ SG_LOG(SG_FLIGHT,SG_ALERT,"Missing '" << attr <<
+ "' in YASim aircraft description");
+ exit(1);
+ }
+ return attrd(atts, attr, 0);
+}
+
+double FGFDM::attrd(XMLAttributes* atts, const char* attr, double def)
+{
+ const char* val = atts->getValue(attr);
+ if(val == 0) return def;
+ else return atof(val);
+}
+
// ACK: the dreaded ambiguous string boolean. Remind me to shoot Maik
// when I have a chance. :). Unless you have a parser that can check
// symbol constants (we don't), this kind of coding is just a Bad
// Unfortunately, this usage creeped into existing configuration files
// while I wasn't active, and it's going to be hard to remove. Issue
// a warning to nag people into changing their ways for now...
-bool FGFDM::attrb(XMLAttributes* atts, char* attr)
+bool FGFDM::attrb(XMLAttributes* atts, const char* attr)
{
const char* val = atts->getValue(attr);
if(val == 0) return false;