X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FFDM%2FYASim%2FAirplane.cpp;h=82b10d7d144844c255759b23206c5a6867243f0e;hb=adeeed1a0e9dba19ba9e02f3fb28ba080e6ff021;hp=da81beba2a6c01ab973b1ca0610725297c1cd9be;hpb=f0e6716953604730579a5e45f785fd063737dce4;p=flightgear.git diff --git a/src/FDM/YASim/Airplane.cpp b/src/FDM/YASim/Airplane.cpp index da81beba2..82b10d7d1 100644 --- a/src/FDM/YASim/Airplane.cpp +++ b/src/FDM/YASim/Airplane.cpp @@ -10,6 +10,10 @@ #include "Airplane.hpp" namespace yasim { +// gadgets +inline float norm(float f) { return f<1 ? 1/f : f; } +inline float abs(float f) { return f<0 ? -f : f; } + Airplane::Airplane() { _emptyWeight = 0; @@ -46,10 +50,15 @@ Airplane::~Airplane() delete (GearRec*)_gears.get(i); for(i=0; i<_surfs.size(); i++) delete (Surface*)_surfs.get(i); + for(i=0; i<_contacts.size(); i++) + delete[] (float*)_contacts.get(i); } void Airplane::iterate(float dt) { + // The gear might have moved. Change their aerodynamics. + updateGearState(); + _model.iterate(); // FIXME: Consume fuel @@ -71,7 +80,7 @@ void Airplane::getPilotAccel(float* out) // Gravity Glue::geodUp(s->pos, out); - Math::mul3(-9.8, out, out); + Math::mul3(-9.8f, out, out); // The regular acceleration float tmp[3]; @@ -106,27 +115,12 @@ Gear* Airplane::getGear(int g) return ((GearRec*)_gears.get(g))->gear; } -void Airplane::setGearState(bool down, float dt) +void Airplane::updateGearState() { - int i; - for(i=0; i<_gears.size(); i++) { + for(int i=0; i<_gears.size(); i++) { GearRec* gr = (GearRec*)_gears.get(i); - if(gr->time == 0) { - // Non-extensible - gr->gear->setExtension(1); - gr->surf->setXDrag(1); - gr->surf->setYDrag(1); - gr->surf->setZDrag(1); - continue; - } + float ext = gr->gear->getExtension(); - float diff = dt / gr->time; - if(!down) diff = -diff; - float ext = gr->gear->getExtension() + diff; - if(ext < 0) ext = 0; - if(ext > 1) ext = 1; - - gr->gear->setExtension(ext); gr->surf->setXDrag(ext); gr->surf->setYDrag(ext); gr->surf->setZDrag(ext); @@ -156,6 +150,13 @@ void Airplane::setCruise(float speed, float altitude) _tailIncidence = 0; } +void Airplane::setElevatorControl(int control) +{ + _approachElevator.control = control; + _approachElevator.val = 0; + _approachControls.add(&_approachElevator); +} + void Airplane::addApproachControl(int control, float val) { Control* c = new Control(); @@ -234,12 +235,11 @@ int Airplane::addTank(float* pos, float cap, float density) return _tanks.add(t); } -void Airplane::addGear(Gear* gear, float transitionTime) +void Airplane::addGear(Gear* gear) { GearRec* g = new GearRec(); g->gear = gear; g->surf = 0; - g->time = transitionTime; _gears.add(g); } @@ -350,8 +350,26 @@ void Airplane::setupState(float aoa, float speed, State* s) s->pos[2] = 1; } +void Airplane::addContactPoint(float* pos) +{ + float* cp = new float[3]; + cp[0] = pos[0]; + cp[1] = pos[1]; + cp[2] = pos[2]; + _contacts.add(cp); +} + float Airplane::compileWing(Wing* w) { + // The tip of the wing is a contact point + float tip[3]; + w->getTip(tip); + addContactPoint(tip); + if(w->isMirrored()) { + tip[1] *= -1; + addContactPoint(tip); + } + // Make sure it's initialized. The surfaces will pop out with // total drag coefficients equal to their areas, which is what we // want. @@ -379,6 +397,10 @@ float Airplane::compileWing(Wing* w) float Airplane::compileFuselage(Fuselage* f) { + // The front and back are contact points + addContactPoint(f->front); + addContactPoint(f->back); + float wgt = 0; float fwd[3]; Math::sub3(f->front, f->back, fwd); @@ -388,7 +410,7 @@ float Airplane::compileFuselage(Fuselage* f) float segWgt = len*wid/segs; int j; for(j=0; jmid) @@ -420,6 +442,8 @@ float Airplane::compileFuselage(Fuselage* f) Math::unit3(fwd, x); y[0] = 0; y[1] = 1; y[2] = 0; Math::cross3(x, y, z); + Math::unit3(z, z); + Math::cross3(z, x, y); s->setOrientation(o); _model.addSurface(s); @@ -456,6 +480,39 @@ void Airplane::compileGear(GearRec* gr) _surfs.add(s); } +void Airplane::compileContactPoints() +{ + // Figure it will compress by 20cm + float comp[3]; + float DIST = 0.2f; + comp[0] = 0; comp[1] = 0; comp[2] = DIST; + + // Give it a spring constant such that at full compression it will + // hold up 10 times the planes mass. That's about right. Yeah. + float mass = _model.getBody()->getTotalMass(); + float spring = (1/DIST) * 9.8f * 10.0f * mass; + float damp = 2 * Math::sqrt(spring * mass); + + int i; + for(i=0; i<_contacts.size(); i++) { + float *cp = (float*)_contacts.get(i); + + Gear* g = new Gear(); + g->setPosition(cp); + + g->setCompression(comp); + g->setSpring(spring); + g->setDamping(damp); + g->setBrake(1); + + // I made these up + g->setStaticFriction(0.6f); + g->setDynamicFriction(0.5f); + + _model.addGear(g); + } +} + void Airplane::compile() { double ground[3]; @@ -506,8 +563,8 @@ void Airplane::compile() t->handle = body->addMass(0, t->pos); totalFuel += t->cap; } - _cruiseWeight = _emptyWeight + totalFuel*0.5; - _approachWeight = _emptyWeight + totalFuel*0.2; + _cruiseWeight = _emptyWeight + totalFuel*0.5f; + _approachWeight = _emptyWeight + totalFuel*0.2f; body->recalc(); @@ -524,13 +581,14 @@ void Airplane::compile() // Ground effect float gepos[3]; float gespan = _wing->getGroundEffect(gepos); - _model.setGroundEffect(gepos, gespan, .3); + _model.setGroundEffect(gepos, gespan, 0.3f); solveGear(); solve(); - // Drop the gear (use a really big dt) - setGearState(true, 1000000); + // Do this after solveGear, because it creates "gear" objects that + // we don't want to affect. + compileContactPoints(); } void Airplane::solveGear() @@ -550,7 +608,7 @@ void Airplane::solveGear() Gear* g = gr->gear; g->getPosition(pos); Math::sub3(cg, pos, pos); - gr->wgt = 1/(0.5+Math::sqrt(pos[0]*pos[0] + pos[1]*pos[1])); + gr->wgt = 1.0f/(0.5f+Math::sqrt(pos[0]*pos[0] + pos[1]*pos[1])); total += gr->wgt; } @@ -561,12 +619,12 @@ void Airplane::solveGear() // The force at max compression should be sufficient to stop a // plane moving downwards at 3x the approach descent rate. Assume // a 3 degree approach. - float descentRate = 3*_approachSpeed/19.1; + float descentRate = 3.0f*_approachSpeed/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.5*_approachWeight*descentRate*descentRate; + float energy = 0.5f*_approachWeight*descentRate*descentRate; for(i=0; i<_gears.size(); i++) { GearRec* gr = (GearRec*)_gears.get(i); @@ -584,8 +642,16 @@ void Airplane::solveGear() gr->gear->setDamping(2*Math::sqrt(k*_approachWeight*gr->wgt)); // These are pretty generic - gr->gear->setStaticFriction(0.8); - gr->gear->setDynamicFriction(0.7); + gr->gear->setStaticFriction(0.8f); + gr->gear->setDynamicFriction(0.7f); + } +} + +void Airplane::initEngines() +{ + for(int i=0; i<_thrusters.size(); i++) { + ThrustRec* tr = (ThrustRec*)_thrusters.get(i); + tr->thruster->init(); } } @@ -609,16 +675,13 @@ void Airplane::runCruise() Control* c = (Control*)_cruiseControls.get(i); _controls.setInput(c->control, c->val); } - _controls.applyControls(); + _controls.applyControls(1000000); // Huge dt value // The local wind float wind[3]; Math::mul3(-1, _cruiseState.v, wind); Math::vmul33(_cruiseState.orient, wind, wind); - // Gear are up (if they're non-retractable, this is a noop) - setGearState(false, 100000); - // Cruise is by convention at 50% tank capacity setFuelFraction(0.5); @@ -631,6 +694,8 @@ void Airplane::runCruise() } stabilizeThrust(); + updateGearState(); + // Precompute thrust in the model, and calculate aerodynamic forces _model.getBody()->reset(); _model.initIteration(); @@ -650,7 +715,7 @@ void Airplane::runApproach() Control* c = (Control*)_approachControls.get(i); _controls.setInput(c->control, c->val); } - _controls.applyControls(); + _controls.applyControls(1000000); // The local wind float wind[3]; @@ -658,10 +723,7 @@ void Airplane::runApproach() Math::vmul33(_approachState.orient, wind, wind); // Approach is by convention at 20% tank capacity - setFuelFraction(0.2); - - // Gear are down - setGearState(true, 100000); + setFuelFraction(0.2f); // Run the thrusters until they get to a stable setting. FIXME: // this is lots of wasted work. @@ -672,6 +734,8 @@ void Airplane::runApproach() } stabilizeThrust(); + updateGearState(); + // Precompute thrust in the model, and calculate aerodynamic forces _model.getBody()->reset(); _model.initIteration(); @@ -724,7 +788,7 @@ float Airplane::normFactor(float f) void Airplane::solve() { - static const float ARCMIN = 0.0002909; + static const float ARCMIN = 0.0002909f; float tmp[3]; _solutionIterations = 0; @@ -751,6 +815,9 @@ void Airplane::solve() // Run an approach iteration, and do likewise runApproach(); + _model.getBody()->getAngularAccel(tmp); + float apitch0 = tmp[1]; + _model.getBody()->getAccel(tmp); float alift = _approachWeight * tmp[2]; @@ -771,7 +838,7 @@ void Airplane::solve() float pitch1 = tmp[1]; // Now calculate: - float awgt = 9.8 * _approachWeight; + float awgt = 9.8f * _approachWeight; float dragFactor = thrust / (thrust-xforce); float liftFactor = awgt / (awgt+alift); @@ -787,7 +854,23 @@ void Airplane::solve() return; } - // And apply: + // And the elevator control in the approach. This works just + // like the tail incidence computation (it's solving for the + // same thing -- pitching moment -- by diddling a different + // variable). + const float ELEVDIDDLE = 0.0001f; + _approachElevator.val += ELEVDIDDLE; + runApproach(); + _approachElevator.val -= ELEVDIDDLE; + + _model.getBody()->getAngularAccel(tmp); + float apitch1 = tmp[1]; + float elevDelta = -apitch0 * (ELEVDIDDLE/(apitch1-apitch0)); + + // Now apply the values we just computed. Note that the + // "minor" variables are deferred until we get the lift/drag + // numbers in the right ballpark. + applyDragFactor(dragFactor); applyLiftRatio(liftFactor); @@ -798,15 +881,20 @@ void Airplane::solve() continue; } - // OK, now we can adjust the minor variables - _cruiseAoA += 0.5*aoaDelta; - _tailIncidence += 0.5*tailDelta; + // OK, now we can adjust the minor variables: + _cruiseAoA += 0.5f*aoaDelta; + _tailIncidence += 0.5f*tailDelta; + _approachElevator.val += 0.5f*elevDelta; - _cruiseAoA = clamp(_cruiseAoA, -.174, .174); - _tailIncidence = clamp(_tailIncidence, -.174, .174); - - if(dragFactor < 1.00001 && liftFactor < 1.00001 && - aoaDelta < .000017 && tailDelta < .000017) + _cruiseAoA = clamp(_cruiseAoA, -0.174f, 0.174f); + _tailIncidence = clamp(_tailIncidence, -0.174f, 0.174f); + _approachElevator.val = clamp(_approachElevator.val, -1.f, 1.f); + + if(norm(dragFactor) < 1.00001 && + norm(liftFactor) < 1.00001 && + abs(aoaDelta) < .000017 && + abs(tailDelta) < .000017 && + abs(elevDelta) < 0.00001) { break; }