1
0
Fork 0

YASim Airplane refactoring (code dedup).

This commit is contained in:
Henning Stahlke 2017-04-25 09:02:01 +02:00
parent e604f2f662
commit 0a0402f667
2 changed files with 145 additions and 155 deletions

View file

@ -33,6 +33,7 @@ const float SOLVE_TWEAK = 0.3226;
Airplane::Airplane()
{
_approachConfig.isApproach = true;
}
Airplane::~Airplane()
@ -58,10 +59,10 @@ Airplane::~Airplane()
}
for(i=0; i<_solveWeights.size(); i++)
delete (SolveWeight*)_solveWeights.get(i);
for(i=0; i<_cruiseControls.size(); i++)
delete (Control*)_cruiseControls.get(i);
for(i=0; i<_approachControls.size(); i++) {
Control* c = (Control*)_approachControls.get(i);
for(i=0; i<_cruiseConfig.controls.size(); i++)
delete (Control*)_cruiseConfig.controls.get(i);
for(i=0; i<_approachConfig.controls.size(); i++) {
Control* c = (Control*)_approachConfig.controls.get(i);
if(c != &_approachElevator)
delete c;
}
@ -124,28 +125,29 @@ void Airplane::updateGearState()
void Airplane::setApproach(float speed, float altitude, float aoa, float fuel, float gla)
{
_approachSpeed = speed;
_approachAltitude = altitude;
_approachAoA = aoa;
_approachFuel = fuel;
_approachGlideAngle = gla;
_approachConfig.speed = speed;
_approachConfig.altitude = altitude;
_approachConfig.state.setupOrientationFromAoa(aoa); // see runConfig()
_approachConfig.aoa = aoa; // not strictly needed, see runConfig()
_approachConfig.fuel = fuel;
_approachConfig.glideAngle = gla;
}
void Airplane::setCruise(float speed, float altitude, float fuel, float gla)
{
_cruiseSpeed = speed;
_cruiseAltitude = altitude;
_cruiseAoA = 0;
_cruiseConfig.speed = speed;
_cruiseConfig.altitude = altitude;
_cruiseConfig.aoa = 0;
_tailIncidence = 0;
_cruiseFuel = fuel;
_cruiseGlideAngle = gla;
_cruiseConfig.fuel = fuel;
_cruiseConfig.glideAngle = gla;
}
void Airplane::setElevatorControl(int control)
{
_approachElevator.control = control;
_approachElevator.val = 0;
_approachControls.add(&_approachElevator);
_approachConfig.controls.add(&_approachElevator);
}
void Airplane::addApproachControl(int control, float val)
@ -153,7 +155,7 @@ void Airplane::addApproachControl(int control, float val)
Control* c = new Control();
c->control = control;
c->val = val;
_approachControls.add(c);
_approachConfig.controls.add(c);
}
void Airplane::addCruiseControl(int control, float val)
@ -161,7 +163,7 @@ void Airplane::addCruiseControl(int control, float val)
Control* c = new Control();
c->control = control;
c->val = val;
_cruiseControls.add(c);
_cruiseConfig.controls.add(c);
}
void Airplane::addSolutionWeight(bool approach, int idx, float wgt)
@ -592,9 +594,10 @@ void Airplane::compile()
t->handle = body->addMass(0, t->pos);
totalFuel += t->cap;
}
_cruiseWeight = _emptyWeight + totalFuel*_cruiseFuel;
_approachWeight = _emptyWeight + totalFuel*_approachFuel;
_cruiseConfig.weight = _emptyWeight + totalFuel*_cruiseConfig.fuel;
_approachConfig.weight = _emptyWeight + totalFuel*_approachConfig.fuel;
body->recalc();
// Add surfaces for the landing gear.
@ -677,12 +680,12 @@ void Airplane::solveGear()
// The force at max compression should be sufficient to stop a
// plane moving downwards at 2x the approach descent rate. Assume
// a 3 degree approach.
float descentRate = 2.0f*_approachSpeed/19.1f;
float descentRate = 2.0f*_approachConfig.speed/19.1f;
// Spread the kinetic energy according to the gear weights. This
// will results in an equal compression fraction (not distance) of
// each gear.
float energy = 0.5f*_approachWeight*descentRate*descentRate;
float energy = 0.5f*_approachConfig.weight*descentRate*descentRate;
for(i=0; i<_gears.size(); i++) {
GearRec* gr = (GearRec*)_gears.get(i);
@ -697,7 +700,7 @@ void Airplane::solveGear()
gr->gear->setSpring(k * gr->gear->getSpring());
// Critically damped (too damped, too!)
gr->gear->setDamping(2*Math::sqrt(k*_approachWeight*gr->wgt)
gr->gear->setDamping(2*Math::sqrt(k*_approachConfig.weight*gr->wgt)
* gr->gear->getDamping());
}
}
@ -754,77 +757,43 @@ void Airplane::loadControls(const Vector& controls)
}
/// Helper for solve()
void Airplane::runCruise()
void Airplane::runConfig(Config &cfg)
{
_cruiseState.setupState(_cruiseAoA, _cruiseSpeed,_cruiseGlideAngle);
_model.setState(&_cruiseState);
_model.setStandardAtmosphere(_cruiseAltitude);
// The control configuration
loadControls(_cruiseControls);
// The local wind
float wind[3];
Math::mul3(-1, _cruiseState.v, wind);
Math::vmul33(_cruiseState.orient, wind, wind);
setFuelFraction(_cruiseFuel);
setupWeights(false);
// Set up the thruster parameters and iterate until the thrust
// stabilizes.
for(int i=0; i<_thrusters.size(); i++) {
Thruster* t = ((ThrustRec*)_thrusters.get(i))->thruster;
t->setWind(wind);
t->setStandardAtmosphere(_cruiseAltitude);
}
stabilizeThrust();
updateGearState();
// Precompute thrust in the model, and calculate aerodynamic forces
_model.getBody()->recalc();
_model.getBody()->reset();
_model.initIteration();
_model.calcForces(&_cruiseState);
// aoa is consider to be given for approach so we calculate orientation
// only once in setApproach()
if (!cfg.isApproach) {
cfg.state.setupOrientationFromAoa(cfg.aoa);
}
cfg.state.setupSpeedAndPosition(cfg.speed, cfg.glideAngle);
_model.setState(&cfg.state);
_model.setStandardAtmosphere(cfg.altitude);
loadControls(cfg.controls);
// The local wind
float wind[3];
Math::mul3(-1, cfg.state.v, wind);
cfg.state.globalToLocal(wind, wind);
setFuelFraction(cfg.fuel);
setupWeights(cfg.isApproach);
// Set up the thruster parameters and iterate until the thrust
// stabilizes.
for(int i=0; i<_thrusters.size(); i++) {
Thruster* t = ((ThrustRec*)_thrusters.get(i))->thruster;
t->setWind(wind);
t->setStandardAtmosphere(cfg.altitude);
}
stabilizeThrust();
updateGearState();
// Precompute thrust in the model, and calculate aerodynamic forces
_model.getBody()->recalc();
_model.getBody()->reset();
_model.initIteration();
_model.calcForces(&cfg.state);
}
/// Helper for solve()
void Airplane::runApproach()
{
_approachState.setupState(_approachAoA, _approachSpeed,_approachGlideAngle);
_model.setState(&_approachState);
_model.setStandardAtmosphere(_approachAltitude);
// The control configuration
loadControls(_approachControls);
// The local wind
float wind[3];
Math::mul3(-1, _approachState.v, wind);
Math::vmul33(_approachState.orient, wind, wind);
setFuelFraction(_approachFuel);
setupWeights(true);
// Run the thrusters until they get to a stable setting. FIXME:
// this is lots of wasted work.
for(int i=0; i<_thrusters.size(); i++) {
Thruster* t = ((ThrustRec*)_thrusters.get(i))->thruster;
t->setWind(wind);
t->setStandardAtmosphere(_approachAltitude);
}
stabilizeThrust();
updateGearState();
// Precompute thrust in the model, and calculate aerodynamic forces
_model.getBody()->recalc();
_model.getBody()->reset();
_model.initIteration();
_model.calcForces(&_approachState);
}
/// Used only in Airplane::solve() and solveHelicopter(), not at runtime
void Airplane::applyDragFactor(float factor)
{
@ -910,51 +879,51 @@ void Airplane::solve()
}
// Run an iteration at cruise, and extract the needed numbers:
runCruise();
runConfig(_cruiseConfig);
_model.getThrust(tmp);
float thrust = tmp[0] + _cruiseWeight * Math::sin(_cruiseGlideAngle) * 9.81;
float thrust = tmp[0] + _cruiseConfig.weight * Math::sin(_cruiseConfig.glideAngle) * 9.81;
_model.getBody()->getAccel(tmp);
Math::tmul33(_cruiseState.orient, tmp, tmp);
float xforce = _cruiseWeight * tmp[0];
float clift0 = _cruiseWeight * tmp[2];
_cruiseConfig.state.localToGlobal(tmp, tmp);
float xforce = _cruiseConfig.weight * tmp[0];
float clift0 = _cruiseConfig.weight * tmp[2];
_model.getBody()->getAngularAccel(tmp);
Math::tmul33(_cruiseState.orient, tmp, tmp);
_cruiseConfig.state.localToGlobal(tmp, tmp);
float pitch0 = tmp[1];
// Run an approach iteration, and do likewise
runApproach();
runConfig(_approachConfig);
_model.getBody()->getAngularAccel(tmp);
Math::tmul33(_approachState.orient, tmp, tmp);
_approachConfig.state.localToGlobal(tmp, tmp);
double apitch0 = tmp[1];
_model.getBody()->getAccel(tmp);
Math::tmul33(_approachState.orient, tmp, tmp);
float alift = _approachWeight * tmp[2];
_approachConfig.state.localToGlobal(tmp, tmp);
float alift = _approachConfig.weight * tmp[2];
// Modify the cruise AoA a bit to get a derivative
_cruiseAoA += ARCMIN;
runCruise();
_cruiseAoA -= ARCMIN;
_cruiseConfig.aoa += ARCMIN;
runConfig(_cruiseConfig);
_cruiseConfig.aoa -= ARCMIN;
_model.getBody()->getAccel(tmp);
Math::tmul33(_cruiseState.orient, tmp, tmp);
float clift1 = _cruiseWeight * tmp[2];
_cruiseConfig.state.localToGlobal(tmp, tmp);
float clift1 = _cruiseConfig.weight * tmp[2];
// Do the same with the tail incidence
_tail->setIncidence(_tailIncidence + ARCMIN);
runCruise();
_tail->setIncidence(_tailIncidence);
runConfig(_cruiseConfig);
_tail->setIncidence(_tailIncidence);
_model.getBody()->getAngularAccel(tmp);
Math::tmul33(_cruiseState.orient, tmp, tmp);
_cruiseConfig.state.localToGlobal(tmp, tmp);
float pitch1 = tmp[1];
// Now calculate:
float awgt = 9.8f * _approachWeight;
float awgt = 9.8f * _approachConfig.weight;
float dragFactor = thrust / (thrust-xforce);
float liftFactor = awgt / (awgt+alift);
@ -971,11 +940,11 @@ void Airplane::solve()
// variable).
const float ELEVDIDDLE = 0.001f;
_approachElevator.val += ELEVDIDDLE;
runApproach();
runConfig(_approachConfig);
_approachElevator.val -= ELEVDIDDLE;
_model.getBody()->getAngularAccel(tmp);
Math::tmul33(_approachState.orient, tmp, tmp);
_approachConfig.state.localToGlobal(tmp, tmp);
double apitch1 = tmp[1];
float elevDelta = -apitch0 * (ELEVDIDDLE/(apitch1-apitch0));
@ -994,14 +963,14 @@ void Airplane::solve()
}
// OK, now we can adjust the minor variables:
_cruiseAoA += SOLVE_TWEAK*aoaDelta;
_cruiseConfig.aoa += SOLVE_TWEAK*aoaDelta;
_tailIncidence += SOLVE_TWEAK*tailDelta;
_cruiseAoA = Math::clamp(_cruiseAoA, -0.175f, 0.175f);
_cruiseConfig.aoa = Math::clamp(_cruiseConfig.aoa, -0.175f, 0.175f);
_tailIncidence = Math::clamp(_tailIncidence, -0.175f, 0.175f);
if(abs(xforce/_cruiseWeight) < STHRESH*0.0001 &&
abs(alift/_approachWeight) < STHRESH*0.0001 &&
if(abs(xforce/_cruiseConfig.weight) < STHRESH*0.0001 &&
abs(alift/_approachConfig.weight) < STHRESH*0.0001 &&
abs(aoaDelta) < STHRESH*.000017 &&
abs(tailDelta) < STHRESH*.000017)
{
@ -1024,7 +993,7 @@ void Airplane::solve()
} else if(_liftRatio < 1e-04 || _liftRatio > 1e4) {
_failureMsg = "Lift ratio beyond reasonable bounds.";
return;
} else if(Math::abs(_cruiseAoA) >= .17453293) {
} else if(Math::abs(_cruiseConfig.aoa) >= .17453293) {
_failureMsg = "Cruise AoA > 10 degrees";
return;
} else if(Math::abs(_tailIncidence) >= .17453293) {
@ -1052,12 +1021,12 @@ void Airplane::solveHelicopter()
applyDragFactor(Math::pow(15.7/1000, 1/SOLVE_TWEAK));
applyLiftRatio(Math::pow(104, 1/SOLVE_TWEAK));
}
_cruiseState.setupState(0,0,0);
_model.setState(&_cruiseState);
_cruiseConfig.state.setupState(0,0,0);
_model.setState(&_cruiseConfig.state);
setupWeights(true);
_controls.reset();
_model.getBody()->reset();
_model.setStandardAtmosphere(_cruiseAltitude);
_model.setStandardAtmosphere(_cruiseConfig.altitude);
}
float Airplane::getCGMAC()

View file

@ -95,13 +95,13 @@ public:
int getSolutionIterations() const { return _solutionIterations; }
float getDragCoefficient() const { return _dragFactor; }
float getLiftRatio() const { return _liftRatio; }
float getCruiseAoA() const { return _cruiseAoA; }
float getCruiseAoA() const { return _cruiseConfig.aoa; }
float getTailIncidence() const { return _tailIncidence; }
float getApproachElevator() const { return _approachElevator.val; }
const char* getFailureMsg() const { return _failureMsg; }
void loadApproachControls() { loadControls(_approachControls); }
void loadCruiseControls() { loadControls(_cruiseControls); }
void loadApproachControls() { loadControls(_approachConfig.controls); }
void loadCruiseControls() { loadControls(_cruiseConfig.controls); }
float getCGHardLimitXMin() const { return _cgMin; } // get min x-coordinate for c.g (from main gear)
float getCGHardLimitXMax() const { return _cgMax; } // get max x-coordinate for c.g (from nose gear)
@ -113,21 +113,60 @@ public:
void setAutoBallast(bool allowed) { _autoBallast = allowed; }
private:
struct Tank { float pos[3]; float cap; float fill;
float density; int handle; };
struct Fuselage { float front[3], back[3], width, taper, mid, _cx, _cy, _cz, _idrag;
Vector surfs; };
struct GearRec { Gear* gear; Surface* surf; float wgt; };
struct ThrustRec { Thruster* thruster;
int handle; float cg[3]; float mass; };
struct Control { int control; float val; };
struct WeightRec { int handle; Surface* surf; };
struct SolveWeight { bool approach; int idx; float wgt; };
struct ContactRec { Gear* gear; float p[3]; };
struct Tank {
float pos[3];
float cap, fill, density;
int handle;
};
struct Fuselage {
float front[3], back[3];
float width, taper, mid, _cx, _cy, _cz, _idrag;
Vector surfs;
};
struct GearRec {
Gear* gear;
Surface* surf;
float wgt;
};
struct ThrustRec {
Thruster* thruster;
int handle;
float cg[3];
float mass;
};
struct Control {
int control;
float val;
};
struct WeightRec {
int handle;
Surface* surf;
};
struct SolveWeight {
bool approach;
int idx;
float wgt;
};
struct ContactRec {
Gear* gear;
float p[3];
};
struct Config {
bool isApproach {false};
float speed {0};
float fuel {0};
float glideAngle {0};
float aoa {0};
float altitude;
float weight;
State state;
Vector controls;
};
Config _cruiseConfig;
Config _approachConfig;
void loadControls(const Vector& controls);
void runCruise();
void runApproach();
void runConfig(Config &cfg);
void solveGear();
void solve();
void solveHelicopter();
@ -167,27 +206,9 @@ private:
Vector _solveWeights;
Vector _cruiseControls;
State _cruiseState;
float _cruiseAltitude;
float _cruiseSpeed{0};
float _cruiseWeight{0};
float _cruiseFuel{0};
float _cruiseGlideAngle{0};
Vector _approachControls;
State _approachState;
float _approachAltitude;
float _approachSpeed {0};
float _approachAoA {0};
float _approachWeight {0};
float _approachFuel {0};
float _approachGlideAngle {0};
int _solutionIterations {0};
float _dragFactor {1};
float _liftRatio {1};
float _cruiseAoA {0};
float _tailIncidence {0};
Control _approachElevator;
const char* _failureMsg {0};