YASim Airplane refactoring (code dedup).
This commit is contained in:
parent
e604f2f662
commit
0a0402f667
2 changed files with 145 additions and 155 deletions
|
@ -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()
|
||||
|
|
|
@ -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};
|
||||
|
|
Loading…
Reference in a new issue