diff --git a/src/FDM/YASim/Airplane.cpp b/src/FDM/YASim/Airplane.cpp index 3ae8cac67..7cbfe44c1 100644 --- a/src/FDM/YASim/Airplane.cpp +++ b/src/FDM/YASim/Airplane.cpp @@ -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() diff --git a/src/FDM/YASim/Airplane.hpp b/src/FDM/YASim/Airplane.hpp index 3a25cd226..3aee7c224 100644 --- a/src/FDM/YASim/Airplane.hpp +++ b/src/FDM/YASim/Airplane.hpp @@ -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};