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

View file

@ -95,13 +95,13 @@ public:
int getSolutionIterations() const { return _solutionIterations; } int getSolutionIterations() const { return _solutionIterations; }
float getDragCoefficient() const { return _dragFactor; } float getDragCoefficient() const { return _dragFactor; }
float getLiftRatio() const { return _liftRatio; } float getLiftRatio() const { return _liftRatio; }
float getCruiseAoA() const { return _cruiseAoA; } float getCruiseAoA() const { return _cruiseConfig.aoa; }
float getTailIncidence() const { return _tailIncidence; } float getTailIncidence() const { return _tailIncidence; }
float getApproachElevator() const { return _approachElevator.val; } float getApproachElevator() const { return _approachElevator.val; }
const char* getFailureMsg() const { return _failureMsg; } const char* getFailureMsg() const { return _failureMsg; }
void loadApproachControls() { loadControls(_approachControls); } void loadApproachControls() { loadControls(_approachConfig.controls); }
void loadCruiseControls() { loadControls(_cruiseControls); } void loadCruiseControls() { loadControls(_cruiseConfig.controls); }
float getCGHardLimitXMin() const { return _cgMin; } // get min x-coordinate for c.g (from main gear) 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) 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; } void setAutoBallast(bool allowed) { _autoBallast = allowed; }
private: private:
struct Tank { float pos[3]; float cap; float fill; struct Tank {
float density; int handle; }; float pos[3];
struct Fuselage { float front[3], back[3], width, taper, mid, _cx, _cy, _cz, _idrag; float cap, fill, density;
Vector surfs; }; int handle;
struct GearRec { Gear* gear; Surface* surf; float wgt; }; };
struct ThrustRec { Thruster* thruster; struct Fuselage {
int handle; float cg[3]; float mass; }; float front[3], back[3];
struct Control { int control; float val; }; float width, taper, mid, _cx, _cy, _cz, _idrag;
struct WeightRec { int handle; Surface* surf; }; Vector surfs;
struct SolveWeight { bool approach; int idx; float wgt; }; };
struct ContactRec { Gear* gear; float p[3]; }; 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 loadControls(const Vector& controls);
void runCruise(); void runConfig(Config &cfg);
void runApproach();
void solveGear(); void solveGear();
void solve(); void solve();
void solveHelicopter(); void solveHelicopter();
@ -167,27 +206,9 @@ private:
Vector _solveWeights; 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}; int _solutionIterations {0};
float _dragFactor {1}; float _dragFactor {1};
float _liftRatio {1}; float _liftRatio {1};
float _cruiseAoA {0};
float _tailIncidence {0}; float _tailIncidence {0};
Control _approachElevator; Control _approachElevator;
const char* _failureMsg {0}; const char* _failureMsg {0};