1
0
Fork 0

Merge /u/jsb1685/flightgear/ branch yasim into next

https://sourceforge.net/p/flightgear/flightgear/merge-requests/89/
This commit is contained in:
James Turner 2017-05-02 15:09:13 +00:00
commit 2747a33e6b
32 changed files with 546 additions and 758 deletions

View file

@ -33,30 +33,7 @@ const float SOLVE_TWEAK = 0.3226;
Airplane::Airplane() Airplane::Airplane()
{ {
_emptyWeight = 0; _approachConfig.isApproach = true;
_pilotPos[0] = _pilotPos[1] = _pilotPos[2] = 0;
_wing = 0;
_tail = 0;
_ballast = 0;
_cruiseP = 0;
_cruiseT = 0;
_cruiseSpeed = 0;
_cruiseWeight = 0;
_cruiseGlideAngle = 0;
_approachP = 0;
_approachT = 0;
_approachSpeed = 0;
_approachAoA = 0;
_approachWeight = 0;
_approachGlideAngle = 0;
_dragFactor = 1;
_liftRatio = 1;
_cruiseAoA = 0;
_tailIncidence = 0;
_failureMsg = 0;
_wingsN = 0;
} }
Airplane::~Airplane() Airplane::~Airplane()
@ -82,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;
} }
@ -148,30 +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;
_approachP = Atmosphere::getStdPressure(altitude); _approachConfig.altitude = altitude;
_approachT = Atmosphere::getStdTemperature(altitude); _approachConfig.state.setupOrientationFromAoa(aoa); // see runConfig()
_approachAoA = aoa; _approachConfig.aoa = aoa; // not strictly needed, see runConfig()
_approachFuel = fuel; _approachConfig.fuel = fuel;
_approachGlideAngle = gla; _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;
_cruiseP = Atmosphere::getStdPressure(altitude); _cruiseConfig.altitude = altitude;
_cruiseT = Atmosphere::getStdTemperature(altitude); _cruiseConfig.aoa = 0;
_cruiseAoA = 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)
@ -179,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)
@ -187,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)
@ -300,31 +276,11 @@ void Airplane::setFuelFraction(float frac)
} }
} }
void Airplane::setupState(const float aoa, const float speed, const float gla, State* s)
{
float cosAoA = Math::cos(aoa);
float sinAoA = Math::sin(aoa);
s->orient[0] = cosAoA; s->orient[1] = 0; s->orient[2] = sinAoA;
s->orient[3] = 0; s->orient[4] = 1; s->orient[5] = 0;
s->orient[6] = -sinAoA; s->orient[7] = 0; s->orient[8] = cosAoA;
//? what is gla? v[1]=y, v[2]=z? should sin go to v2 instead v1?
s->v[0] = speed*Math::cos(gla); s->v[1] = -speed*Math::sin(gla); s->v[2] = 0;
for(int i=0; i<3; i++)
s->pos[i] = s->rot[i] = s->acc[i] = s->racc[i] = 0;
// Put us 1m above the origin, or else the gravity computation in
// Model goes nuts
s->pos[2] = 1;
}
/** /**
* @brief add contact point for crash detection * @brief add contact point for crash detection
* used to add wingtips and fuselage nose and tail * used to add wingtips and fuselage nose and tail
* *
* @param pos ... * @param pos ...
* @return void
*/ */
void Airplane::addContactPoint(float* pos) void Airplane::addContactPoint(float* pos)
@ -638,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.
@ -723,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);
@ -743,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());
} }
} }
@ -789,7 +746,7 @@ void Airplane::setupWeights(bool isApproach)
} }
/// load values for controls as defined in cruise configuration /// load values for controls as defined in cruise configuration
void Airplane::loadControls(Vector& controls) void Airplane::loadControls(const Vector& controls)
{ {
_controls.reset(); _controls.reset();
for(int i=0; i < controls.size(); i++) { for(int i=0; i < controls.size(); i++) {
@ -800,81 +757,43 @@ void Airplane::loadControls(Vector& controls)
} }
/// Helper for solve() /// Helper for solve()
void Airplane::runCruise() void Airplane::runConfig(Config &cfg)
{ {
setupState(_cruiseAoA, _cruiseSpeed,_cruiseGlideAngle, &_cruiseState); // aoa is consider to be given for approach so we calculate orientation
_model.setState(&_cruiseState); // only once in setApproach()
_model.setAir(_cruiseP, _cruiseT, if (!cfg.isApproach) {
Atmosphere::calcStdDensity(_cruiseP, _cruiseT)); cfg.state.setupOrientationFromAoa(cfg.aoa);
}
// The control configuration cfg.state.setupSpeedAndPosition(cfg.speed, cfg.glideAngle);
loadControls(_cruiseControls); _model.setState(&cfg.state);
_model.setStandardAtmosphere(cfg.altitude);
// The local wind loadControls(cfg.controls);
float wind[3];
Math::mul3(-1, _cruiseState.v, wind); // The local wind
Math::vmul33(_cruiseState.orient, wind, wind); float wind[3];
Math::mul3(-1, cfg.state.v, wind);
setFuelFraction(_cruiseFuel); cfg.state.globalToLocal(wind, wind);
setupWeights(false);
setFuelFraction(cfg.fuel);
// Set up the thruster parameters and iterate until the thrust setupWeights(cfg.isApproach);
// stabilizes.
for(int i=0; i<_thrusters.size(); i++) { // Set up the thruster parameters and iterate until the thrust
Thruster* t = ((ThrustRec*)_thrusters.get(i))->thruster; // stabilizes.
t->setWind(wind); for(int i=0; i<_thrusters.size(); i++) {
t->setAir(_cruiseP, _cruiseT, Thruster* t = ((ThrustRec*)_thrusters.get(i))->thruster;
Atmosphere::calcStdDensity(_cruiseP, _cruiseT)); t->setWind(wind);
} t->setStandardAtmosphere(cfg.altitude);
stabilizeThrust(); }
updateGearState(); stabilizeThrust();
updateGearState();
// Precompute thrust in the model, and calculate aerodynamic forces
_model.getBody()->recalc(); // Precompute thrust in the model, and calculate aerodynamic forces
_model.getBody()->reset(); _model.getBody()->recalc();
_model.initIteration(); _model.getBody()->reset();
_model.calcForces(&_cruiseState); _model.initIteration();
_model.calcForces(&cfg.state);
} }
/// Helper for solve()
void Airplane::runApproach()
{
setupState(_approachAoA, _approachSpeed,_approachGlideAngle, &_approachState);
_model.setState(&_approachState);
_model.setAir(_approachP, _approachT,
Atmosphere::calcStdDensity(_approachP, _approachT));
// 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->setAir(_approachP, _approachT,
Atmosphere::calcStdDensity(_approachP, _approachT));
}
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)
{ {
@ -960,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);
@ -1021,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));
@ -1044,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)
{ {
@ -1074,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) {
@ -1102,14 +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));
} }
setupState(0,0,0, &_cruiseState); _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.setAir(_cruiseP, _cruiseT, _model.setStandardAtmosphere(_cruiseConfig.altitude);
Atmosphere::calcStdDensity(_cruiseP, _cruiseT));
} }
float Airplane::getCGMAC() float Airplane::getCGMAC()

View file

@ -95,14 +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; }
static void setupState(const float aoa, const float speed, const float gla, yasim::State* s); // utility void loadApproachControls() { loadControls(_approachConfig.controls); }
void loadApproachControls() { loadControls(_approachControls); } void loadCruiseControls() { loadControls(_cruiseConfig.controls); }
void loadCruiseControls() { loadControls(_cruiseControls); }
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)
@ -114,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(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();
@ -148,17 +186,17 @@ private:
Model _model; Model _model;
ControlMap _controls; ControlMap _controls;
float _emptyWeight; float _emptyWeight {0};
float _pilotPos[3]; float _pilotPos[3] {0, 0, 0};
Wing* _wing; Wing* _wing {nullptr};
Wing* _tail; Wing* _tail {nullptr};
Vector _fuselages; Vector _fuselages;
Vector _vstabs; Vector _vstabs;
Vector _tanks; Vector _tanks;
Vector _thrusters; Vector _thrusters;
float _ballast; float _ballast {0};
Vector _gears; Vector _gears;
Vector _contacts; // non-gear ground contact points Vector _contacts; // non-gear ground contact points
@ -168,39 +206,19 @@ private:
Vector _solveWeights; Vector _solveWeights;
Vector _cruiseControls; int _solutionIterations {0};
State _cruiseState; float _dragFactor {1};
float _cruiseP; float _liftRatio {1};
float _cruiseT; float _tailIncidence {0};
float _cruiseSpeed;
float _cruiseWeight;
float _cruiseFuel;
float _cruiseGlideAngle;
Vector _approachControls;
State _approachState;
float _approachP;
float _approachT;
float _approachSpeed;
float _approachAoA;
float _approachWeight;
float _approachFuel;
float _approachGlideAngle;
int _solutionIterations;
float _dragFactor;
float _liftRatio;
float _cruiseAoA;
float _tailIncidence;
Control _approachElevator; Control _approachElevator;
const char* _failureMsg; const char* _failureMsg {0};
float _cgMax = -1e6; // hard limits for cg from gear position float _cgMax {-1e6}; // hard limits for cg from gear position
float _cgMin = 1e6; // hard limits for cg from gear position float _cgMin {1e6}; // hard limits for cg from gear position
float _cgDesiredMax = 0.3f; // desired cg max in %MAC from config float _cgDesiredMax {0.3f}; // desired cg max in %MAC from config
float _cgDesiredMin = 0.25f; // desired cg min in %MAC from config float _cgDesiredMin {0.25f}; // desired cg min in %MAC from config
float _cgDesiredFront; // calculated desired cg x max float _cgDesiredFront {0}; // calculated desired cg x max
float _cgDesiredAft; // calculated desired cg x min float _cgDesiredAft {0}; // calculated desired cg x min
bool _autoBallast = false; bool _autoBallast = false;
}; };

View file

@ -1,7 +1,8 @@
#include <string>
#include "Math.hpp" #include "Math.hpp"
#include "Atmosphere.hpp" #include "Atmosphere.hpp"
namespace yasim {
namespace yasim {
// Copied from McCormick, who got it from "The ARDC Model Atmosphere" // Copied from McCormick, who got it from "The ARDC Model Atmosphere"
// Note that there's an error in the text in the first entry, // Note that there's an error in the text in the first entry,
// McCormick lists 299.16/101325/1.22500, but those don't agree with // McCormick lists 299.16/101325/1.22500, but those don't agree with
@ -9,7 +10,7 @@ namespace yasim {
// pretty hot for a "standard" atmosphere. // pretty hot for a "standard" atmosphere.
// Numbers above 19000 meters calculated from src/Environment/environment.cxx // Numbers above 19000 meters calculated from src/Environment/environment.cxx
// meters kelvin Pa kg/m^3 // meters kelvin Pa kg/m^3
float Atmosphere::data[][4] = {{ -900.0f, 293.91f, 111679.0f, 1.32353f }, float Atmosphere::data[][Atmosphere::numColumns] = {{ -900.0f, 293.91f, 111679.0f, 1.32353f },
{ 0.0f, 288.11f, 101325.0f, 1.22500f }, { 0.0f, 288.11f, 101325.0f, 1.22500f },
{ 900.0f, 282.31f, 90971.0f, 1.12260f }, { 900.0f, 282.31f, 90971.0f, 1.12260f },
{ 1800.0f, 276.46f, 81494.0f, 1.02690f }, { 1800.0f, 276.46f, 81494.0f, 1.02690f },
@ -48,28 +49,34 @@ float Atmosphere::data[][4] = {{ -900.0f, 293.91f, 111679.0f, 1.32353f },
// Universal gas constant for air, in SI units. P = R * rho * T. // Universal gas constant for air, in SI units. P = R * rho * T.
// P in pascals (N/m^2), rho is kg/m^3, T in kelvin. // P in pascals (N/m^2), rho is kg/m^3, T in kelvin.
const float R = 287.1f; const float R = 287.058f;
// Specific heat ratio for air, at "low" temperatures. // Specific heat ratio for air, at "low" temperatures.
const float GAMMA = 1.4f; const float GAMMA = 1.4f;
void Atmosphere::setStandard(float altitude)
{
_density = getStdDensity(altitude);
_pressure = getStdPressure(altitude);
_temperature = getStdTemperature(altitude);
}
float Atmosphere::getStdTemperature(float alt) float Atmosphere::getStdTemperature(float alt)
{ {
return getRecord(alt, 1); return getRecord(alt, TEMPERATURE);
} }
float Atmosphere::getStdPressure(float alt) float Atmosphere::getStdPressure(float alt)
{ {
return getRecord(alt, 2); return getRecord(alt, PRESSURE);
} }
float Atmosphere::getStdDensity(float alt) float Atmosphere::getStdDensity(float alt)
{ {
return getRecord(alt, 3); return getRecord(alt, DENSITY);
} }
float Atmosphere::calcVEAS(float spd, float Atmosphere::calcVEAS(float spd, float pressure, float temp, float density)
float pressure, float temp, float density)
{ {
static float rho0 = getStdDensity(0); static float rho0 = getStdDensity(0);
float densityRatio = density / rho0; float densityRatio = density / rho0;
@ -122,9 +129,14 @@ float Atmosphere::spdFromMach(float mach, float temp)
return mach * Math::sqrt(GAMMA * R * temp); return mach * Math::sqrt(GAMMA * R * temp);
} }
float Atmosphere::spdFromMach(float mach)
{
return spdFromMach(mach, _temperature);
}
float Atmosphere::spdFromVCAS(float vcas, float pressure, float temp) float Atmosphere::spdFromVCAS(float vcas, float pressure, float temp)
{ {
// FIXME: does not account for supersonic // FIXME: does not account for supersonic
float p0 = getStdPressure(0); float p0 = getStdPressure(0);
float rho0 = getStdDensity(0); float rho0 = getStdDensity(0);
@ -136,6 +148,11 @@ float Atmosphere::spdFromVCAS(float vcas, float pressure, float temp)
return vtas; return vtas;
} }
float Atmosphere::spdFromVCAS(float vcas)
{
return spdFromVCAS(vcas, _pressure, _temperature);
}
void Atmosphere::calcStaticAir(float p0, float t0, float d0, float v, void Atmosphere::calcStaticAir(float p0, float t0, float d0, float v,
float* pOut, float* tOut, float* dOut) float* pOut, float* tOut, float* dOut)
{ {
@ -147,14 +164,24 @@ void Atmosphere::calcStaticAir(float p0, float t0, float d0, float v,
*pOut = (*dOut) * R * (*tOut); *pOut = (*dOut) * R * (*tOut);
} }
float Atmosphere::getRecord(float alt, int recNum) void Atmosphere::calcStaticAir(float v, float* pOut, float* tOut, float* dOut)
{ {
int hi = (sizeof(data) / (4*sizeof(float))) - 1; return calcStaticAir(_pressure, _temperature, _density, v, pOut, tOut, dOut);
}
float Atmosphere::getRecord(float alt, Column recNum)
{
int hi = maxTableIndex();
int lo = 0; int lo = 0;
// safety valve, clamp to the edges of the table // safety valve, clamp to the edges of the table
if(alt < data[0][0]) hi=1; if(alt < data[0][ALTITUDE]) {
else if(alt > data[hi][0]) lo = hi-1; hi = 1;
}
else if(alt > data[hi][ALTITUDE]) {
lo = hi-1;
}
// binary search // binary search
while(1) { while(1) {
@ -165,10 +192,38 @@ float Atmosphere::getRecord(float alt, int recNum)
} }
// interpolate // interpolate
float frac = (alt - data[lo][0])/(data[hi][0] - data[lo][0]); float frac = (alt - data[lo][ALTITUDE])/(data[hi][ALTITUDE] - data[lo][ALTITUDE]);
float a = data[lo][recNum]; float a = data[lo][recNum];
float b = data[hi][recNum]; float b = data[hi][recNum];
return a + frac * (b-a); return a + frac * (b-a);
} }
int Atmosphere::maxTableIndex() {
return (sizeof(data) / (numColumns * sizeof(float))) - 1;
}
bool Atmosphere::test() {
bool passed = true;
int rows = maxTableIndex() + 1;
const float maxDeviation = 0.0002f;
fprintf(stderr, "Atmosphere::test()\n");
fprintf(stderr, "Columns = %d\n", numColumns);
fprintf(stderr, "Rows = %d\n", rows);
for (int alt = 0; alt < maxTableIndex(); alt++) {
float density = calcStdDensity(data[alt][PRESSURE], data[alt][TEMPERATURE]);
float delta = data[alt][DENSITY] - density;
fprintf(stderr, "%d : %f \n", alt, delta);
if (Math::abs(delta) > maxDeviation) {
passed = false;
fprintf(stderr,"FAIL: Deviation above limit of %1.6f\n", maxDeviation);
}
}
if (passed) {
fprintf(stderr,"Deviation below %1.6f for all rows.\n", maxDeviation);
}
return passed;
}
}; // namespace yasim }; // namespace yasim

View file

@ -3,8 +3,28 @@
namespace yasim { namespace yasim {
//constexpr int Atmosphere::numColumns {4};
class Atmosphere { class Atmosphere {
enum Column {
ALTITUDE,
TEMPERATURE,
PRESSURE,
DENSITY
};
static const int numColumns {4};
public: public:
void setTemperature(float t) { _temperature = t; }
void setPressure(float p) { _pressure = p; }
void setDensity(float d) { _density = d; }
//set temperature, pressure and density to standard values for given altitude
void setStandard(float altitude);
float getTemperature() const { return _temperature; }
float getPressure() const { return _pressure; }
float getDensity() const { return _density; }
static float getStdTemperature(float alt); static float getStdTemperature(float alt);
static float getStdPressure(float alt); static float getStdPressure(float alt);
static float getStdDensity(float alt); static float getStdDensity(float alt);
@ -16,6 +36,8 @@ public:
static float spdFromMach(float mach, float temp); static float spdFromMach(float mach, float temp);
static float spdFromVCAS(float vcas, float pressure, float temp); static float spdFromVCAS(float vcas, float pressure, float temp);
float spdFromMach(float mach);
float spdFromVCAS(float vcas);
// Given ambient ("0") pressure/density/temperature values, // Given ambient ("0") pressure/density/temperature values,
// calculate the properties of static air (air accelerated to the // calculate the properties of static air (air accelerated to the
@ -23,10 +45,17 @@ public:
// compressibility, but not shock effects. // compressibility, but not shock effects.
static void calcStaticAir(float p0, float t0, float d0, float v, static void calcStaticAir(float p0, float t0, float d0, float v,
float* pOut, float* tOut, float* dOut); float* pOut, float* tOut, float* dOut);
void calcStaticAir(float v, float* pOut, float* tOut, float* dOut);
static bool test();
private: private:
static float getRecord(float alt, int idx); static float getRecord(float alt, Atmosphere::Column recNum);
static float data[][4]; static float data[][numColumns];
static int maxTableIndex();
float _temperature = 288.11f;
float _pressure = 101325.0f;
float _density = 1.22500f;
}; };
}; // namespace yasim }; // namespace yasim

View file

@ -13,45 +13,41 @@ namespace yasim {
// You can get local->global transformations by calling Math::tmul33() // You can get local->global transformations by calling Math::tmul33()
// and using the same matrix. // and using the same matrix.
struct State { struct State {
double pos[3]; // position double pos[3] {0, 0, 0}; // position
float orient[9]; // global->local xform matrix float orient[9] {1,0,0, 0,1,0, 0,0,1}; // global->local xform matrix
float v[3]; // velocity float v[3] {0, 0, 0}; // velocity
float rot[3]; // rotational velocity float rot[3] {0, 0, 0}; // rotational velocity
float acc[3]; // acceleration float acc[3] {0, 0, 0}; // acceleration
float racc[3]; // rotational acceleration float racc[3] {0, 0, 0}; // rotational acceleration
// Simple initialization // Simple initialization
State() { State() {
int i;
for(i=0; i<3; i++) {
pos[i] = v[i] = rot[i] = acc[i] = racc[i] = 0;
int j;
for(j=0; j<3; j++)
orient[3*i+j] = i==j ? 1.0f : 0.0f;
}
} }
void posLocalToGlobal(float* lpos, double *gpos) { void posLocalToGlobal(const float* lpos, double *gpos) const {
float tmp[3]; float tmp[3];
Math::tmul33(orient, lpos, tmp); Math::tmul33(orient, lpos, tmp);
gpos[0] = tmp[0] + pos[0]; gpos[0] = tmp[0] + pos[0];
gpos[1] = tmp[1] + pos[1]; gpos[1] = tmp[1] + pos[1];
gpos[2] = tmp[2] + pos[2]; gpos[2] = tmp[2] + pos[2];
} }
void posGlobalToLocal(double* gpos, float *lpos) {
void posGlobalToLocal(const double* gpos, float *lpos) const {
lpos[0] = (float)(gpos[0] - pos[0]); lpos[0] = (float)(gpos[0] - pos[0]);
lpos[1] = (float)(gpos[1] - pos[1]); lpos[1] = (float)(gpos[1] - pos[1]);
lpos[2] = (float)(gpos[2] - pos[2]); lpos[2] = (float)(gpos[2] - pos[2]);
Math::vmul33(orient, lpos, lpos); Math::vmul33(orient, lpos, lpos);
} }
void velLocalToGlobal(float* lvel, float *gvel) {
Math::tmul33(orient, lvel, gvel); void localToGlobal(const float* local, float *global) const {
Math::tmul33(orient, local, global);
} }
void velGlobalToLocal(float* gvel, float *lvel) {
Math::vmul33(orient, gvel, lvel); void globalToLocal(const float* global, float *local) const {
Math::vmul33(orient, global, local);
} }
void planeGlobalToLocal(double* gplane, float *lplane) { void planeGlobalToLocal(const double* gplane, float *lplane) const {
// First the normal vector transformed to local coordinates. // First the normal vector transformed to local coordinates.
lplane[0] = (float)-gplane[0]; lplane[0] = (float)-gplane[0];
lplane[1] = (float)-gplane[1]; lplane[1] = (float)-gplane[1];
@ -62,7 +58,35 @@ struct State {
lplane[3] = (float)(pos[0]*gplane[0] + pos[1]*gplane[1] lplane[3] = (float)(pos[0]*gplane[0] + pos[1]*gplane[1]
+ pos[2]*gplane[2] - gplane[3]); + pos[2]*gplane[2] - gplane[3]);
} }
// used by Airplane::runCruise, runApproach, solveHelicopter and in yasim-test
void setupOrientationFromAoa(float aoa)
{
float cosAoA = Math::cos(aoa);
float sinAoA = Math::sin(aoa);
orient[0] = cosAoA; orient[1] = 0; orient[2] = sinAoA;
orient[3] = 0; orient[4] = 1; orient[5] = 0;
orient[6] = -sinAoA; orient[7] = 0; orient[8] = cosAoA;
}
void setupSpeedAndPosition(float speed, float gla)
{
// FIXME check axis, guess sin should go to 2 instead of 1?
v[0] = speed*Math::cos(gla);
v[1] = -speed*Math::sin(gla);
v[2] = 0;
for(int i=0; i<3; i++) {
pos[i] = rot[i] = acc[i] = racc[i] = 0;
}
pos[2] = 1;
}
void setupState(float aoa, float speed, float gla) {
setupOrientationFromAoa(aoa);
setupSpeedAndPosition(speed, gla);
}
}; };
// //

View file

@ -22,7 +22,6 @@ set(COMMON
Rotorpart.cpp Rotorpart.cpp
SimpleJet.cpp SimpleJet.cpp
Surface.cpp Surface.cpp
Thruster.cpp
TurbineEngine.cpp TurbineEngine.cpp
Turbulence.cpp Turbulence.cpp
Wing.cpp Wing.cpp
@ -40,6 +39,7 @@ flightgear_component(YASim "${SOURCES}")
if(ENABLE_TESTS) if(ENABLE_TESTS)
add_executable(yasim yasim-test.cpp ${COMMON}) add_executable(yasim yasim-test.cpp ${COMMON})
add_executable(yasim-proptest proptest.cpp ${COMMON}) add_executable(yasim-proptest proptest.cpp ${COMMON})
add_executable(yasim-atmotest yasim-atmotest.cpp Atmosphere.cpp )
target_link_libraries(yasim SimGearCore) target_link_libraries(yasim SimGearCore)
target_link_libraries(yasim-proptest SimGearCore) target_link_libraries(yasim-proptest SimGearCore)

View file

@ -27,25 +27,6 @@
namespace yasim { namespace yasim {
// Some conversion factors
static const float KTS2MPS = 0.514444444444;
static const float KMH2MPS = 1/3.6;
static const float FT2M = 0.3048;
static const float DEG2RAD = 0.0174532925199;
static const float RPM2RAD = 0.10471975512;
static const float LBS2N = 4.44822;
static const float LBS2KG = 0.45359237;
static const float KG2LBS = 2.2046225;
static const float CM2GALS = 264.172037284;
static const float HP2W = 745.700;
static const float INHG2PA = 3386.389;
static const float K2DEGF = 1.8;
static const float K2DEGFOFFSET = -459.4;
static const float CIN2CM = 1.6387064e-5;
static const float YASIM_PI = 3.14159265358979323846;
static const float NM2FTLB = (1/(LBS2N*FT2M));
// Stubs, so that this can be compiled without the FlightGear // Stubs, so that this can be compiled without the FlightGear
// binary. What's the best way to handle this? // binary. What's the best way to handle this?

View file

@ -4,6 +4,7 @@
#include <simgear/xml/easyxml.hxx> #include <simgear/xml/easyxml.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include "yasim-common.hpp"
#include "Airplane.hpp" #include "Airplane.hpp"
#include "Vector.hpp" #include "Vector.hpp"

View file

@ -165,7 +165,7 @@ void Gear::calcForce(RigidBody* body, State *s, float* v, float* rot)
// The velocity of the contact patch transformed to local coordinates. // The velocity of the contact patch transformed to local coordinates.
float glvel[3]; float glvel[3];
s->velGlobalToLocal(_global_vel, glvel); s->globalToLocal(_global_vel, glvel);
// First off, make sure that the gear "tip" is below the ground. // First off, make sure that the gear "tip" is below the ground.
// If it's not, there's no force. // If it's not, there's no force.

View file

@ -413,7 +413,7 @@ void Hitch::calcForce(Ground *g_cb, RigidBody* body, State* s)
//With this trick, both player in aerotow get the same length //With this trick, both player in aerotow get the same length
Math::unit3(delta,deltaN); Math::unit3(delta,deltaN);
float lvel[3]; float lvel[3];
s->velGlobalToLocal(s->v,lvel); s->globalToLocal(s->v,lvel);
_speed_in_tow_direction=Math::dot3(lvel,deltaN); _speed_in_tow_direction=Math::dot3(lvel,deltaN);
if (_towEndIsConnectedToProperty && _nodeIsMultiplayer) if (_towEndIsConnectedToProperty && _nodeIsMultiplayer)
{ {
@ -421,7 +421,7 @@ void Hitch::calcForce(Ground *g_cb, RigidBody* body, State* s)
_timeLagCorrectedDist=_dist+mp_delta_dist_due_to_time_lag; _timeLagCorrectedDist=_dist+mp_delta_dist_due_to_time_lag;
if(_forceIsCalculatedByMaster && !_open) if(_forceIsCalculatedByMaster && !_open)
{ {
s->velGlobalToLocal(_mp_force,_force); s->globalToLocal(_mp_force,_force);
return; return;
} }
} }
@ -528,7 +528,7 @@ void Hitch::calcForce(Ground *g_cb, RigidBody* body, State* s)
//the same for the tow end: //the same for the tow end:
Math::mul3(grav_frac_tow_end*grav_force,ground,grav_force_v); Math::mul3(grav_frac_tow_end*grav_force,ground,grav_force_v);
Math::add3(grav_force_v,_towEndForce,_towEndForce); Math::add3(grav_force_v,_towEndForce,_towEndForce);
s->velLocalToGlobal(_towEndForce,_towEndForce); s->localToGlobal(_towEndForce,_towEndForce);
if(_forceMagnitude>=_towBrakeForce) if(_forceMagnitude>=_towBrakeForce)
{ {

View file

@ -216,8 +216,8 @@ void Hook::calcForce(Ground* g_cb, RigidBody* body, State* s, float* lv, float*
float wire_lpos[2][3]; float wire_lpos[2][3];
s->posGlobalToLocal(dpos[0], wire_lpos[0]); s->posGlobalToLocal(dpos[0], wire_lpos[0]);
s->posGlobalToLocal(dpos[1], wire_lpos[1]); s->posGlobalToLocal(dpos[1], wire_lpos[1]);
s->velGlobalToLocal(wire_vel[0], wire_vel[0]); s->globalToLocal(wire_vel[0], wire_vel[0]);
s->velGlobalToLocal(wire_vel[1], wire_vel[1]); s->globalToLocal(wire_vel[1], wire_vel[1]);
// Compute the velocity of the hooks mount point in the local frame. // Compute the velocity of the hooks mount point in the local frame.
float mount_vel[3]; float mount_vel[3];

View file

@ -2,43 +2,6 @@
#include "Integrator.hpp" #include "Integrator.hpp"
namespace yasim { namespace yasim {
void Integrator::setBody(RigidBody* body)
{
_body = body;
}
void Integrator::setEnvironment(BodyEnvironment* env)
{
_env = env;
}
void Integrator::setInterval(float dt)
{
_dt = dt;
}
float Integrator::getInterval()
{
return _dt;
}
void Integrator::setState(State* s)
{
_s = *s;
}
State* Integrator::getState()
{
return &_s;
}
// Transforms a "local" vector to a "global" vector (not coordinate!)
// using the specified orientation.
void Integrator::l2gVector(float* orient, float* v, float* out)
{
Math::tmul33(orient, v, out);
}
// Updates a position vector for a body c.g. motion with velocity v // Updates a position vector for a body c.g. motion with velocity v
// over time dt, from orientation o0 to o1. Because the position // over time dt, from orientation o0 to o1. Because the position
// references the local coordinate origin, but the velocity is that of // references the local coordinate origin, but the velocity is that of

View file

@ -17,24 +17,24 @@ class Integrator
{ {
public: public:
// Sets the RigidBody that will be integrated. // Sets the RigidBody that will be integrated.
void setBody(RigidBody* body); void setBody(RigidBody* body) { _body = body; }
// Sets the BodyEnvironment object used to calculate the second // Sets the BodyEnvironment object used to calculate the second
// derivatives. // derivatives.
void setEnvironment(BodyEnvironment* env); void setEnvironment(BodyEnvironment* env) { _env = env; }
// Sets the time interval between steps. Units can be anything, // Sets the time interval between steps. Units can be anything,
// but they must match the other values (if you specify speed in // but they must match the other values (if you specify speed in
// m/s, then angular acceleration had better be in 1/s^2 and the // m/s, then angular acceleration had better be in 1/s^2 and the
// time interval should be in seconds, etc...) // time interval should be in seconds, etc...)
void setInterval(float dt); void setInterval(float dt) { _dt = dt; }
float getInterval(); float getInterval() const { return _dt; }
// The current state, i.e. initial conditions for the next // The current state, i.e. initial conditions for the next
// integration iteration. Note that the acceleration parameters // integration iteration. Note that the acceleration parameters
// in the State object are ignored. // in the State object are ignored.
State* getState(); State* getState() { return &_s; }
void setState(State* s); void setState(State* s) { _s = *s; }
// Do a 4th order Runge-Kutta integration over one time interval. // Do a 4th order Runge-Kutta integration over one time interval.
// This is the top level of the simulation. // This is the top level of the simulation.
@ -43,9 +43,13 @@ public:
private: private:
void orthonormalize(float* m); void orthonormalize(float* m);
void rotMatrix(float* r, float dt, float* out); void rotMatrix(float* r, float dt, float* out);
void l2gVector(float* orient, float* v, float* out);
void extrapolatePosition(double* pos, float* v, float dt, // Transforms a "local" vector to a "global" vector (not coordinate!)
float* o1, float* o2); // using the specified orientation.
void l2gVector(const float* orient, const float* v, float* out) {
Math::tmul33(orient, v, out); }
void extrapolatePosition(double* pos, float* v, float dt, float* o1, float* o2);
BodyEnvironment* _env; BodyEnvironment* _env;
RigidBody* _body; RigidBody* _body;

View file

@ -59,21 +59,6 @@ void Jet::setMaxThrust(float thrust, float afterburner)
} }
} }
void Jet::setVMax(float spd)
{
_vMax = spd;
}
void Jet::setTSFC(float tsfc)
{
_tsfc = tsfc;
}
void Jet::setATSFC(float atsfc)
{
_atsfc = atsfc;
}
void Jet::setRPMs(float idleN1, float maxN1, float idleN2, float maxN2) void Jet::setRPMs(float idleN1, float maxN1, float idleN2, float maxN2)
{ {
_n1Min = idleN1; _n1Min = idleN1;
@ -82,16 +67,6 @@ void Jet::setRPMs(float idleN1, float maxN1, float idleN2, float maxN2)
_n2Max = maxN2; _n2Max = maxN2;
} }
void Jet::setEGT(float takeoffEGT)
{
_egt0 = takeoffEGT;
}
void Jet::setEPR(float takeoffEPR)
{
_epr0 = takeoffEPR;
}
void Jet::setSpooling(float time) void Jet::setSpooling(float time)
{ {
// 2.3 = -ln(0.1), i.e. x=2.3 is the 90% point we're defining // 2.3 = -ln(0.1), i.e. x=2.3 is the 90% point we're defining
@ -100,11 +75,6 @@ void Jet::setSpooling(float time)
_decay = 1.5f * 2.3f / time; _decay = 1.5f * 2.3f / time;
} }
void Jet::setVectorAngle(float angle)
{
_maxRot = angle;
}
void Jet::setReheat(float reheat) void Jet::setReheat(float reheat)
{ {
_reheat = Math::clamp(reheat, 0, 1); _reheat = Math::clamp(reheat, 0, 1);
@ -112,9 +82,7 @@ void Jet::setReheat(float reheat)
void Jet::setRotation(float rot) void Jet::setRotation(float rot)
{ {
if(rot < 0) rot = 0; _rotControl = Math::clamp(rot, 0, 1);
if(rot > 1) rot = 1;
_rotControl = rot;
} }
float Jet::getN1() float Jet::getN1()
@ -127,16 +95,12 @@ float Jet::getN2()
return _n2 * _tempCorrect; return _n2 * _tempCorrect;
} }
float Jet::getEPR()
{
return _epr;
}
float Jet::getEGT() float Jet::getEGT()
{ {
// Exactly zero means "off" -- return the ambient temperature // Exactly zero means "off" -- return the ambient temperature
if(_egt == 0) return _temp; if(_egt == 0) {
return _atmo.getTemperature();
}
return _egt * _tempCorrect * _tempCorrect; return _egt * _tempCorrect * _tempCorrect;
} }
@ -155,8 +119,7 @@ void Jet::integrate(float dt)
float spd = -Math::dot3(_wind, _dir); float spd = -Math::dot3(_wind, _dir);
float statT, statP, statD; float statT, statP, statD;
Atmosphere::calcStaticAir(_pressure, _temp, _rho, spd, _atmo.calcStaticAir(spd, &statP, &statT, &statD);
&statP, &statT, &statD);
_pressureCorrect = statP/P0; _pressureCorrect = statP/P0;
_tempCorrect = Math::sqrt(statT/T0); _tempCorrect = Math::sqrt(statT/T0);
@ -175,8 +138,8 @@ void Jet::integrate(float dt)
// Now get a "beta" (i.e. EPR - 1) value. The output values are // Now get a "beta" (i.e. EPR - 1) value. The output values are
// expressed as functions of beta. // expressed as functions of beta.
float ibeta0 = 1/(_epr0 - 1); float ibeta0 = 1/(_epr0 - 1);
float betaTarget = (_epr0 - 1) * (setThrust/_maxThrust) * (P0/_pressure) float betaTarget = (_epr0 - 1) * (setThrust/_maxThrust) * (P0/_atmo.getPressure())
* (_temp/statT); * (_atmo.getTemperature()/statT);
float n2Target = _n2Min + (betaTarget*ibeta0) * (_n2Max - _n2Min); float n2Target = _n2Min + (betaTarget*ibeta0) * (_n2Max - _n2Min);
// Note that this "first" beta value is used to compute a target // Note that this "first" beta value is used to compute a target
@ -191,7 +154,7 @@ void Jet::integrate(float dt)
// The actual thrust produced is keyed to the N1 speed. Add the // The actual thrust produced is keyed to the N1 speed. Add the
// afterburners in at the end. // afterburners in at the end.
float betaN1 = (_epr0-1) * (_n1 - _n1Min) / (_n1Max - _n1Min); float betaN1 = (_epr0-1) * (_n1 - _n1Min) / (_n1Max - _n1Min);
_thrust = _maxThrust * betaN1/((_epr0-1)*(P0/_pressure)*(_temp/statT)); _thrust = _maxThrust * betaN1/((_epr0-1)*(P0/_atmo.getPressure())*(_atmo.getTemperature()/statT));
_thrust *= 1 + _reheat*(_abFactor-1); _thrust *= 1 + _reheat*(_abFactor-1);
// Finally, calculate the output variables. Use a 80/20 mix of // Finally, calculate the output variables. Use a 80/20 mix of
@ -214,16 +177,6 @@ void Jet::integrate(float dt)
if(_reverseThrust) _thrust *= -_reverseEff; if(_reverseThrust) _thrust *= -_reverseEff;
} }
bool Jet::isRunning()
{
return _running;
}
bool Jet::isCranking()
{
return _cranking;
}
void Jet::getThrust(float* out) void Jet::getThrust(float* out)
{ {
Math::mul3(_thrust, _dir, out); Math::mul3(_thrust, _dir, out);
@ -240,13 +193,11 @@ void Jet::getThrust(float* out)
void Jet::getTorque(float* out) void Jet::getTorque(float* out)
{ {
out[0] = out[1] = out[2] = 0; out[0] = out[1] = out[2] = 0;
return;
} }
void Jet::getGyro(float* out) void Jet::getGyro(float* out)
{ {
out[0] = out[1] = out[2] = 0; out[0] = out[1] = out[2] = 0;
return;
} }
}; // namespace yasim }; // namespace yasim

View file

@ -12,13 +12,13 @@ public:
virtual Jet* getJet() { return this; } virtual Jet* getJet() { return this; }
void setMaxThrust(float thrust, float afterburner=0); void setMaxThrust(float thrust, float afterburner=0);
void setVMax(float spd); void setVMax(float spd) { _vMax = spd; };
void setTSFC(float tsfc); void setTSFC(float tsfc) { _tsfc = tsfc; };
void setATSFC(float atsfc); void setATSFC(float atsfc) { _atsfc = atsfc; };
void setRPMs(float idleN1, float maxN1, float idleN2, float maxN2); void setRPMs(float idleN1, float maxN1, float idleN2, float maxN2);
void setEGT(float takeoffEGT); void setEGT(float takeoffEGT) { _egt0 = takeoffEGT; };
void setEPR(float takeoffEPR); void setEPR(float takeoffEPR) { _epr0 = takeoffEPR; };
void setVectorAngle(float angle); void setVectorAngle(float angle) { _maxRot = angle; };
// The time it takes the engine to reach 90% thrust from idle // The time it takes the engine to reach 90% thrust from idle
void setSpooling(float time); void setSpooling(float time);
@ -37,15 +37,15 @@ public:
float getN1(); float getN1();
float getN2(); float getN2();
float getEPR(); float getEPR() const { return _epr; };
float getEGT(); float getEGT();
// Normalized "performance" number. Used for fuzzy numbers in FGFDM // Normalized "performance" number. Used for fuzzy numbers in FGFDM
float getPerfNorm() { return (_n1 - _n1Min) / (_n1Max - _n1Min); } float getPerfNorm() { return (_n1 - _n1Min) / (_n1Max - _n1Min); }
// From Thruster: // From Thruster:
virtual bool isRunning(); virtual bool isRunning() { return _running; };
virtual bool isCranking(); virtual bool isCranking() { return _cranking; };
virtual void getThrust(float* out); virtual void getThrust(float* out);
virtual void getTorque(float* out); virtual void getTorque(float* out);
virtual void getGyro(float* out); virtual void getGyro(float* out);

View file

@ -374,8 +374,8 @@ void Launchbar::calcForce(Ground *g_cb, RigidBody* body, State* s, float* lv, fl
// Transform the velocities of the endpoints to the // Transform the velocities of the endpoints to the
// local coordinate sytem. // local coordinate sytem.
float lvel[2][3]; float lvel[2][3];
s->velGlobalToLocal(vel[0], lvel[0]); s->globalToLocal(vel[0], lvel[0]);
s->velGlobalToLocal(vel[1], lvel[1]); s->globalToLocal(vel[1], lvel[1]);
// Compute the position of the launchbar tip relative to the cat. // Compute the position of the launchbar tip relative to the cat.
float tip_pos_on_cat = getPercentPosOnCat(llb_mount, 0.0, lend); float tip_pos_on_cat = getPercentPosOnCat(llb_mount, 0.0, lend);

View file

@ -50,28 +50,13 @@ void printState(State* s)
Model::Model() Model::Model()
{ {
int i;
for(i=0; i<3; i++) _wind[i] = 0;
_integrator.setBody(&_body); _integrator.setBody(&_body);
_integrator.setEnvironment(this); _integrator.setEnvironment(this);
// Default value of 30 Hz // Default value of 30 Hz
_integrator.setInterval(1.0f/30.0f); _integrator.setInterval(1.0f/30.0f);
_agl = 0;
_crashed = false;
_turb = 0;
_ground_cb = new Ground(); _ground_cb = new Ground();
_hook = 0;
_launchbar = 0;
_wingSpan = 0;
_groundEffect = 0;
for(i=0; i<3; i++) _geRefPoint[i] = 0;
_global_ground[0] = 0; _global_ground[1] = 0; _global_ground[2] = 1;
_global_ground[3] = -100000;
_modelN = fgGetNode("/fdm/yasim/forces", true); _modelN = fgGetNode("/fdm/yasim/forces", true);
_fAeroXN = _modelN->getNode("f-x-drag", true); _fAeroXN = _modelN->getNode("f-x-drag", true);
_fAeroYN = _modelN->getNode("f-y-side", true); _fAeroYN = _modelN->getNode("f-y-side", true);
@ -98,11 +83,10 @@ void Model::getThrust(float* out) const
{ {
float tmp[3]; float tmp[3];
out[0] = out[1] = out[2] = 0; out[0] = out[1] = out[2] = 0;
int i; for(int i=0; i<_thrusters.size(); i++) {
for(i=0; i<_thrusters.size(); i++) { Thruster* t = (Thruster*)_thrusters.get(i);
Thruster* t = (Thruster*)_thrusters.get(i); t->getThrust(tmp);
t->getThrust(tmp); Math::add3(tmp, out, out);
Math::add3(tmp, out, out);
} }
} }
@ -127,7 +111,7 @@ void Model::initIteration()
localWind(pos, _s, v, alt); localWind(pos, _s, v, alt);
t->setWind(v); t->setWind(v);
t->setAir(_pressure, _temp, _rho); t->setAtmosphere(_atmo);
t->integrate(_integrator.getInterval()); t->integrate(_integrator.getInterval());
t->getTorque(v); t->getTorque(v);
@ -153,8 +137,6 @@ void Model::initIteration()
Hitch* h = (Hitch*)_hitches.get(i); Hitch* h = (Hitch*)_hitches.get(i);
h->integrate(_integrator.getInterval()); h->integrate(_integrator.getInterval());
} }
} }
// This function initializes some variables for the rotor calculation // This function initializes some variables for the rotor calculation
@ -186,7 +168,7 @@ void Model::iterate()
void Model::setState(State* s) void Model::setState(State* s)
{ {
_integrator.setState(s); _integrator.setState(s);
_s = _integrator.getState(); _s = s;
} }
@ -203,20 +185,6 @@ void Model::setGroundEffect(const float* pos, float span, float mul)
_groundEffect = mul; _groundEffect = mul;
} }
void Model::setAir(float pressure, float temp, float density)
{
_pressure = pressure;
_temp = temp;
_rho = density;
}
void Model::setAirFromStandardAtmosphere(float altitude)
{
_pressure = Atmosphere::getStdPressure(altitude);
_temp = Atmosphere::getStdTemperature(altitude);
_rho = Atmosphere::getStdDensity(altitude);
}
void Model::updateGround(State* s) void Model::updateGround(State* s)
{ {
float dummy[3]; float dummy[3];
@ -336,7 +304,7 @@ void Model::calcForces(State* s)
localWind(pos, s, vs, alt); localWind(pos, s, vs, alt);
float force[3], torque[3]; float force[3], torque[3];
sf->calcForce(vs, _rho, force, torque); sf->calcForce(vs, _atmo.getDensity(), force, torque);
Math::add3(faero, force, faero); Math::add3(faero, force, faero);
_body.addForce(pos, force); _body.addForce(pos, force);
@ -349,7 +317,7 @@ void Model::calcForces(State* s)
float vs[3], pos[3]; float vs[3], pos[3];
r->getPosition(pos); r->getPosition(pos);
localWind(pos, s, vs, alt); localWind(pos, s, vs, alt);
r->calcLiftFactor(vs, _rho,s); r->calcLiftFactor(vs, _atmo.getDensity(), s);
float tq=0; float tq=0;
// total torque of rotor (scalar) for calculating new rotor rpm // total torque of rotor (scalar) for calculating new rotor rpm
@ -363,7 +331,7 @@ void Model::calcForces(State* s)
localWind(pos, s, vs, alt,true); localWind(pos, s, vs, alt,true);
float force[3], torque[3]; float force[3], torque[3];
rp->calcForce(vs, _rho, force, torque, &torque_scalar); rp->calcForce(vs, _atmo.getDensity(), force, torque, &torque_scalar);
tq+=torque_scalar; tq+=torque_scalar;
rp->getPositionForceAttac(pos); rp->getPositionForceAttac(pos);
@ -486,7 +454,7 @@ void Model::newState(State* s)
// Calculates the airflow direction at the given point and for the // Calculates the airflow direction at the given point and for the
// specified aircraft velocity. // specified aircraft velocity.
void Model::localWind(const float* pos, yasim::State* s, float* out, float alt, bool is_rotor) void Model::localWind(const float* pos, const yasim::State* s, float* out, float alt, bool is_rotor)
{ {
float tmp[3], lwind[3], lrot[3], lv[3]; float tmp[3], lwind[3], lrot[3], lv[3];
@ -521,8 +489,6 @@ void Model::localWind(const float* pos, yasim::State* s, float* out, float alt,
_rotorgear.getDownWash(pos,lv,tmp); _rotorgear.getDownWash(pos,lv,tmp);
Math::add3(out,tmp, out); // + downwash Math::add3(out,tmp, out); // + downwash
} }
} }
}; // namespace yasim }; // namespace yasim

View file

@ -7,6 +7,7 @@
#include "Vector.hpp" #include "Vector.hpp"
#include "Turbulence.hpp" #include "Turbulence.hpp"
#include "Rotor.hpp" #include "Rotor.hpp"
#include "Atmosphere.hpp"
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
namespace yasim { namespace yasim {
@ -68,8 +69,8 @@ public:
// //
void setGroundEffect(const float* pos, float span, float mul); void setGroundEffect(const float* pos, float span, float mul);
void setWind(float* wind) { Math::set3(wind, _wind); } void setWind(float* wind) { Math::set3(wind, _wind); }
void setAir(float pressure, float temp, float density); void setAtmosphere(Atmosphere a) { _atmo = a; };
void setAirFromStandardAtmosphere(float altitude); void setStandardAtmosphere(float altitude) { _atmo.setStandard(altitude); };
void updateGround(State* s); void updateGround(State* s);
@ -81,39 +82,38 @@ private:
void initRotorIteration(); void initRotorIteration();
void calcGearForce(Gear* g, float* v, float* rot, float* ground); void calcGearForce(Gear* g, float* v, float* rot, float* ground);
float gearFriction(float wgt, float v, Gear* g); float gearFriction(float wgt, float v, Gear* g);
void localWind(const float* pos, State* s, float* out, float alt, bool is_rotor = false); void localWind(const float* pos, const yasim::State* s, float* out, float alt, bool is_rotor = false);
Integrator _integrator; Integrator _integrator;
RigidBody _body; RigidBody _body;
Turbulence* _turb; Turbulence* _turb {nullptr};
Vector _thrusters; Vector _thrusters;
Vector _surfaces; Vector _surfaces;
Rotorgear _rotorgear; Rotorgear _rotorgear;
Vector _gears; Vector _gears;
Hook* _hook; Hook* _hook {nullptr};
Launchbar* _launchbar; Launchbar* _launchbar {nullptr};
Vector _hitches; Vector _hitches;
float _wingSpan; float _wingSpan {0};
float _groundEffect; float _groundEffect {0};
float _geRefPoint[3]; float _geRefPoint[3] {0,0,0};
Ground* _ground_cb; Ground* _ground_cb;
double _global_ground[4]; double _global_ground[4] {0,0,1, -1e5};
float _pressure; Atmosphere _atmo;
float _temp; float _wind[3] {0,0,0};
float _rho;
float _wind[3];
// Accumulators for the total internal gyro and engine torque // Accumulators for the total internal gyro and engine torque
float _gyro[3]; float _gyro[3] {0,0,0};
float _torque[3]; float _torque[3] {0,0,0};
State* _s; State* _s;
bool _crashed; bool _crashed {false};
float _agl; float _agl {0};
SGPropertyNode_ptr _modelN; SGPropertyNode_ptr _modelN;
SGPropertyNode_ptr _fAeroXN; SGPropertyNode_ptr _fAeroXN;
SGPropertyNode_ptr _fAeroYN; SGPropertyNode_ptr _fAeroYN;

View file

@ -123,8 +123,8 @@ void PropEngine::stabilize()
// If we cannot manage this in 100 iterations, give up. // If we cannot manage this in 100 iterations, give up.
for (int n = 0; n < 100; n++) { for (int n = 0; n < 100; n++) {
float ptau, thrust; float ptau, thrust;
_prop->calc(_rho, speed, _omega * _gearRatio, &thrust, &ptau); _prop->calc(_atmo.getDensity(), speed, _omega * _gearRatio, &thrust, &ptau);
_eng->calc(_pressure, _temp, _omega); _eng->calc(_atmo.getPressure(), _atmo.getTemperature(), _omega);
_eng->stabilize(); _eng->stabilize();
// Do it again -- the turbo sets the target MP in the first // Do it again -- the turbo sets the target MP in the first
@ -133,7 +133,7 @@ void PropEngine::stabilize()
// it works without side effects (other than solver // it works without side effects (other than solver
// performance). In the future, the Engine objects should // performance). In the future, the Engine objects should
// store state to allow them to do the work themselves. // store state to allow them to do the work themselves.
_eng->calc(_pressure, _temp, _omega); _eng->calc(_atmo.getPressure(), _atmo.getTemperature(), _omega);
// Compute torque as seen by the engine's end of the gearbox. // Compute torque as seen by the engine's end of the gearbox.
// The propeller will be moving more slowly (for gear ratios // The propeller will be moving more slowly (for gear ratios
@ -185,11 +185,11 @@ void PropEngine::integrate(float dt)
_eng->setMixture(_mixture); _eng->setMixture(_mixture);
_eng->setFuelState(_fuel); _eng->setFuelState(_fuel);
_prop->calc(_rho, speed, _omega * _gearRatio, &thrust, &propTorque); _prop->calc(_atmo.getDensity(), speed, _omega * _gearRatio, &thrust, &propTorque);
if(_omega == 0.0) if(_omega == 0.0)
_omega = 0.001; // hack to get around reports of NaNs somewhere... _omega = 0.001; // hack to get around reports of NaNs somewhere...
propTorque *= _gearRatio; propTorque *= _gearRatio;
_eng->calc(_pressure, _temp, _omega); _eng->calc(_atmo.getPressure(), _atmo.getTemperature(), _omega);
_eng->integrate(dt); _eng->integrate(dt);
engTorque = _eng->getTorque(); engTorque = _eng->getTorque();
_fuelFlow = _eng->getFuelFlow(); _fuelFlow = _eng->getFuelFlow();

View file

@ -829,7 +829,7 @@ void Rotor::calcLiftFactor(float* v, float rho, State *s)
//store the gravity direction //store the gravity direction
Glue::geodUp(s->pos, _grav_direction); Glue::geodUp(s->pos, _grav_direction);
s->velGlobalToLocal(_grav_direction, _grav_direction); s->globalToLocal(_grav_direction, _grav_direction);
} }
void Rotor::findGroundEffectAltitude(Ground * ground_cb,State *s) void Rotor::findGroundEffectAltitude(Ground * ground_cb,State *s)

View file

@ -7,35 +7,12 @@ int Surface::s_idGenerator = 0;
Surface::Surface( Version * version ) : Surface::Surface( Version * version ) :
_version(version) _version(version)
{ {
// create id for surface
_id = s_idGenerator++; _id = s_idGenerator++;
// Start in a "sane" mode, so unset stuff doesn't freak us out
_c0 = 1;
_cx = _cy = _cz = 1;
_cz0 = 0;
_peaks[0] = _peaks[1] = 1;
int i;
for(i=0; i<4; i++) {
_stalls[i] = 0;
_widths[i] = 0.01; // half a degree
}
_orient[0] = 1; _orient[1] = 0; _orient[2] = 0; _orient[0] = 1; _orient[1] = 0; _orient[2] = 0;
_orient[3] = 0; _orient[4] = 1; _orient[5] = 0; _orient[3] = 0; _orient[4] = 1; _orient[5] = 0;
_orient[6] = 0; _orient[7] = 0; _orient[8] = 1; _orient[6] = 0; _orient[7] = 0; _orient[8] = 1;
_chord = 0;
_incidence = 0;
_twist = 0;
_slatPos = _spoilerPos = _flapPos = 0;
_slatDrag = _spoilerDrag = _flapDrag = 1;
_flapLift = 0;
_flapEffectiveness = 1;
_slatAlpha = 0;
_spoilerLift = 1;
_inducedDrag = 1;
_stallAlpha = 0;
_alpha = 0;
_surfN = fgGetNode("/fdm/yasim/debug/surfaces", true); _surfN = fgGetNode("/fdm/yasim/debug/surfaces", true);
if (_surfN != 0) { if (_surfN != 0) {
_surfN = _surfN->getChild("surface", _id, true); _surfN = _surfN->getChild("surface", _id, true);

View file

@ -92,36 +92,36 @@ private:
float flapLift(float alpha); float flapLift(float alpha);
float controlDrag(float lift, float drag); float controlDrag(float lift, float drag);
float _chord; // X-axis size float _chord {0}; // X-axis size
float _c0; // total force coefficient float _c0 {1}; // total force coefficient
float _cx; // X-axis force coefficient float _cx {1}; // X-axis force coefficient
float _cy; // Y-axis force coefficient float _cy {1}; // Y-axis force coefficient
float _cz; // Z-axis force coefficient float _cz {1}; // Z-axis force coefficient
float _cz0; // Z-axis force offset float _cz0 {0}; // Z-axis force offset
float _peaks[2]; // Stall peak coefficients (fwd, back) float _peaks[2] {1, 1}; // Stall peak coefficients (fwd, back)
float _stalls[4]; // Stall angles (fwd/back, pos/neg) float _stalls[4] {0, 0, 0, 0}; // Stall angles (fwd/back, pos/neg)
float _widths[4]; // Stall widths " " float _widths[4] {0.01, 0.01, 0.01, 0.01}; // Stall widths " "
float _pos[3]; // position in local coords float _pos[3]; // position in local coords
float _orient[9]; // local->surface orthonormal matrix float _orient[9]; // local->surface orthonormal matrix
float _slatAlpha; float _slatAlpha {0};
float _slatDrag; float _slatDrag {1};
float _flapLift; float _flapLift {0};
float _flapDrag; float _flapDrag {1};
float _flapEffectiveness; float _flapEffectiveness {1};
float _spoilerLift; float _spoilerLift {1};
float _spoilerDrag; float _spoilerDrag {1};
float _slatPos; float _slatPos {0};
float _flapPos; float _flapPos {0};
float _spoilerPos; float _spoilerPos {0};
float _incidence; float _incidence {0};
float _twist; float _twist {0};
float _inducedDrag; float _inducedDrag {1};
// used during calculations // used during calculations
float _stallAlpha; float _stallAlpha {0};
float _alpha; float _alpha {0};
Version * _version; Version * _version;
SGPropertyNode* _fxN; SGPropertyNode* _fxN;

View file

@ -1,72 +0,0 @@
#include "Math.hpp"
#include "Thruster.hpp"
namespace yasim {
Thruster::Thruster()
{
_dir[0] = 1; _dir[1] = 0; _dir[2] = 0;
int i;
for(i=0; i<3; i++) _pos[i] = _wind[i] = 0;
_throttle = 0;
_mixture = 0;
_starter = false;
_pressure = _temp = _rho = 0;
}
Thruster::~Thruster()
{
}
void Thruster::getPosition(float* out)
{
int i;
for(i=0; i<3; i++) out[i] = _pos[i];
}
void Thruster::setPosition(float* pos)
{
int i;
for(i=0; i<3; i++) _pos[i] = pos[i];
}
void Thruster::getDirection(float* out)
{
int i;
for(i=0; i<3; i++) out[i] = _dir[i];
}
void Thruster::setDirection(float* dir)
{
Math::unit3(dir, _dir);
}
void Thruster::setThrottle(float throttle)
{
_throttle = Math::clamp(throttle, -1, 1);
}
void Thruster::setMixture(float mixture)
{
_mixture = Math::clamp(mixture, 0, 1);
}
void Thruster::setStarter(bool starter)
{
_starter = starter;
}
void Thruster::setWind(float* wind)
{
int i;
for(i=0; i<3; i++) _wind[i] = wind[i];
}
void Thruster::setAir(float pressure, float temp, float density)
{
_pressure = pressure;
_temp = temp;
_rho = density;
}
}; // namespace yasim

View file

@ -1,6 +1,9 @@
#ifndef _THRUSTER_HPP #ifndef _THRUSTER_HPP
#define _THRUSTER_HPP #define _THRUSTER_HPP
#include "Atmosphere.hpp"
#include "Math.hpp"
namespace yasim { namespace yasim {
class Jet; class Jet;
@ -10,8 +13,8 @@ class Engine;
class Thruster { class Thruster {
public: public:
Thruster(); Thruster() {};
virtual ~Thruster(); virtual ~Thruster() {};
// Typing info, these are the possible sub-type (or sub-parts) // Typing info, these are the possible sub-type (or sub-parts)
// that a thruster might have. Any might return null. A little // that a thruster might have. Any might return null. A little
@ -22,15 +25,15 @@ public:
virtual Engine* getEngine() { return 0; } virtual Engine* getEngine() { return 0; }
// Static data // Static data
void getPosition(float* out); void getPosition(float* out) const { Math::set3(_pos, out); }
void setPosition(float* pos); void setPosition(const float* pos) { Math::set3(pos, _pos); }
void getDirection(float* out); void getDirection(float* out) const { Math::set3(_dir, out); }
void setDirection(float* dir); void setDirection(const float* dir) { Math::unit3(dir, _dir); }
// Controls // Controls
void setThrottle(float throttle); void setThrottle(float throttle) { _throttle = Math::clamp(throttle, -1, 1); }
void setMixture(float mixture); void setMixture(float mixture) { _mixture = Math::clamp(mixture, 0, 1); }
void setStarter(bool starter); void setStarter(bool starter) { _starter = starter; }
void setFuelState(bool hasFuel) { _fuel = hasFuel; } void setFuelState(bool hasFuel) { _fuel = hasFuel; }
// Dynamic output // Dynamic output
@ -42,26 +45,24 @@ public:
virtual float getFuelFlow()=0; // in kg/s virtual float getFuelFlow()=0; // in kg/s
// Runtime instructions // Runtime instructions
void setWind(float* wind); void setWind(const float* wind) { Math::set3(wind, _wind); };
void setAir(float pressure, float temp, float density); void setAtmosphere(Atmosphere a) { _atmo = a; };
void setStandardAtmosphere(float altitude) { _atmo.setStandard(altitude); };
virtual void init() {} virtual void init() {}
virtual void integrate(float dt)=0; virtual void integrate(float dt)=0;
virtual void stabilize()=0; virtual void stabilize()=0;
protected: protected:
float _pos[3]; float _pos[3] {0, 0, 0};
float _dir[3]; float _dir[3] {1, 0, 0};
float _throttle; float _throttle = 0;
float _mixture; float _mixture = 0;
bool _starter; // true=engaged, false=disengaged bool _starter = false; // true=engaged, false=disengaged
bool _fuel; // true=available, false=out bool _fuel; // true=available, false=out
float _wind[3]; float _wind[3] {0, 0, 0};
float _pressure; Atmosphere _atmo;
float _temp;
float _rho;
}; };
}; // namespace yasim }; // namespace yasim
#endif // _THRUSTER_HPP #endif // _THRUSTER_HPP

View file

@ -16,20 +16,20 @@ public:
} YASIM_VERSION; } YASIM_VERSION;
void setVersion( const char * version ); void setVersion( const char * version );
int getVersion() { return _version; } int getVersion() const { return _version; }
bool isVersion( YASIM_VERSION version ); bool isVersion( YASIM_VERSION version ) const;
bool isVersionOrNewer( YASIM_VERSION version ); bool isVersionOrNewer( YASIM_VERSION version ) const;
private: private:
YASIM_VERSION _version; YASIM_VERSION _version;
}; };
inline bool Version::isVersion( YASIM_VERSION version ) inline bool Version::isVersion( YASIM_VERSION version ) const
{ {
return _version == version; return _version == version;
} }
inline bool Version::isVersionOrNewer( YASIM_VERSION version ) inline bool Version::isVersionOrNewer( YASIM_VERSION version ) const
{ {
return _version >= version; return _version >= version;
} }

View file

@ -7,47 +7,12 @@ static const float RAD2DEG = 57.2957795131;
Wing::Wing( Version * version ) : Wing::Wing( Version * version ) :
_version(version) _version(version)
{ {
_mirror = false;
_base[0] = _base[1] = _base[2] = 0;
_length = 0;
_chord = 0;
_taper = 0;
_sweep = 0;
_dihedral = 0;
_stall = 0;
_stallWidth = 0;
_stallPeak = 0;
_twist = 0;
_camber = 0;
_incidence = 0;
_inducedDrag = 1;
_dragScale = 1;
_liftRatio = 1;
_flap0Start = 0;
_flap0End = 0;
_flap0Lift = 0;
_flap0Drag = 0;
_flap1Start = 0;
_flap1End = 0;
_flap1Lift = 0;
_flap1Drag = 0;
_spoilerStart = 0;
_spoilerEnd = 0;
_spoilerLift = 0;
_spoilerDrag = 0;
_slatStart = 0;
_slatEnd = 0;
_slatAoA = 0;
_slatDrag = 0;
_meanChord = 0;
_wingspan = 0;
_aspectRatio = 1;
} }
Wing::~Wing() Wing::~Wing()
{ {
int i; for(int i=0; i<_surfs.size(); i++) {
for(i=0; i<_surfs.size(); i++) {
SurfRec* s = (SurfRec*)_surfs.get(i); SurfRec* s = (SurfRec*)_surfs.get(i);
delete s->surface; delete s->surface;
delete s; delete s;
@ -57,8 +22,7 @@ Wing::~Wing()
void Wing::setIncidence(float incidence) void Wing::setIncidence(float incidence)
{ {
_incidence = incidence; _incidence = incidence;
int i; for(int i=0; i<_surfs.size(); i++)
for(i=0; i<_surfs.size(); i++)
((SurfRec*)_surfs.get(i))->surface->setIncidence(incidence); ((SurfRec*)_surfs.get(i))->surface->setIncidence(incidence);
} }

View file

@ -106,55 +106,55 @@ private:
Vector _slatSurfs; Vector _slatSurfs;
Vector _spoilerSurfs; Vector _spoilerSurfs;
bool _mirror; bool _mirror {false};
float _base[3]; float _base[3] {0,0,0};
float _length; float _length {0};
float _chord; float _chord {0};
float _taper; float _taper {1};
float _sweep; float _sweep {0};
float _dihedral; float _dihedral {0};
// calculated from above // calculated from above
float _tip[3]; float _tip[3] {0,0,0};
float _meanChord; // std. mean chord float _meanChord {0}; // std. mean chord
float _mac; // mean aerodynamic chord length float _mac {0}; // mean aerodynamic chord length
float _macRootDistance; // y-distance of mac from root float _macRootDistance {0}; // y-distance of mac from root
float _macX; // x-coordinate of mac (leading edge) float _macX {0}; // x-coordinate of mac (leading edge)
float _netSpan; float _netSpan {0};
float _wingspan; float _wingspan {0};
float _aspectRatio; float _aspectRatio {1};
float _stall; float _stall {0};
float _stallWidth; float _stallWidth {0};
float _stallPeak; float _stallPeak {0};
float _twist; float _twist {0};
float _camber; float _camber {0};
float _incidence; float _incidence {0};
float _inducedDrag; float _inducedDrag {1};
float _dragScale; float _dragScale {1};
float _liftRatio; float _liftRatio {1};
float _flap0Start; float _flap0Start {0};
float _flap0End; float _flap0End {0};
float _flap0Lift; float _flap0Lift {0};
float _flap0Drag; float _flap0Drag {0};
float _flap1Start; float _flap1Start {0};
float _flap1End; float _flap1End {0};
float _flap1Lift; float _flap1Lift {0};
float _flap1Drag; float _flap1Drag {0};
float _spoilerStart; float _spoilerStart {0};
float _spoilerEnd; float _spoilerEnd {0};
float _spoilerLift; float _spoilerLift {0};
float _spoilerDrag; float _spoilerDrag {0};
float _slatStart; float _slatStart {0};
float _slatEnd; float _slatEnd {0};
float _slatAoA; float _slatAoA {0};
float _slatDrag; float _slatDrag {0};
Version * _version; Version * _version;
}; };

View file

@ -15,6 +15,7 @@
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include "yasim-common.hpp"
#include "FGFDM.hpp" #include "FGFDM.hpp"
#include "Atmosphere.hpp" #include "Atmosphere.hpp"
#include "Math.hpp" #include "Math.hpp"
@ -34,22 +35,6 @@
using namespace yasim; using namespace yasim;
using std::string; using std::string;
static const float YASIM_PI = 3.14159265358979323846;
static const float RAD2DEG = 180/YASIM_PI;
static const float PI2 = YASIM_PI*2;
static const float M2FT = 3.2808399;
static const float FT2M = 0.3048;
static const float MPS2KTS = 3600.0/1852.0;
static const float INHG2PA = 3386.389;
static const float SLUG2KG = 14.59390;
#if 0 // unused constant values
static const float RAD2RPM = 9.54929658551;
static const float CM2GALS = 264.172037284; // gallons/cubic meter
static const float KG2LBS = 2.20462262185;
static const float W2HP = 1.3416e-3;
#endif
YASim::YASim(double dt) : YASim::YASim(double dt) :
_simTime(0) _simTime(0)
{ {
@ -312,7 +297,11 @@ void YASim::copyToYASim(bool copyState)
float temp = _temp_degc->getFloatValue() + 273.15; float temp = _temp_degc->getFloatValue() + 273.15;
float dens = _density_slugft3->getFloatValue() * float dens = _density_slugft3->getFloatValue() *
SLUG2KG * M2FT*M2FT*M2FT; SLUG2KG * M2FT*M2FT*M2FT;
Atmosphere atmo;
atmo.setDensity(dens);
atmo.setTemperature(temp);
atmo.setPressure(pressure);
// Convert and set: // Convert and set:
Model* model = _fdm->getAirplane()->getModel(); Model* model = _fdm->getAirplane()->getModel();
State s; State s;
@ -332,7 +321,7 @@ void YASim::copyToYASim(bool copyState)
Math::mmul33(s.orient, xyz2ned, s.orient); Math::mmul33(s.orient, xyz2ned, s.orient);
// Velocity // Velocity
float v[3]; float v[3] {0, 0, 0};
bool needCopy = false; bool needCopy = false;
switch (_speed_set) { switch (_speed_set) {
case NED: case NED:
@ -347,15 +336,14 @@ void YASim::copyToYASim(bool copyState)
Math::tmul33(s.orient, v, v); Math::tmul33(s.orient, v, v);
break; break;
case KNOTS: case KNOTS:
v[0] = Atmosphere::spdFromVCAS(get_V_calibrated_kts()/MPS2KTS, v[0] = atmo.spdFromVCAS(get_V_calibrated_kts()/MPS2KTS);
pressure, temp);
v[1] = 0; v[1] = 0;
v[2] = 0; v[2] = 0;
Math::tmul33(s.orient, v, v); Math::tmul33(s.orient, v, v);
needCopy = true; needCopy = true;
break; break;
case MACH: case MACH:
v[0] = Atmosphere::spdFromMach(get_Mach_number(), temp); v[0] = atmo.spdFromMach(get_Mach_number());
v[1] = 0; v[1] = 0;
v[2] = 0; v[2] = 0;
Math::tmul33(s.orient, v, v); Math::tmul33(s.orient, v, v);
@ -374,20 +362,18 @@ void YASim::copyToYASim(bool copyState)
if(copyState || needCopy) if(copyState || needCopy)
model->setState(&s); model->setState(&s);
// wind
Math::tmul33(xyz2ned, wind, wind); Math::tmul33(xyz2ned, wind, wind);
model->setWind(wind); model->setWind(wind);
model->setAtmosphere(atmo);
// air
model->setAir(pressure, temp, dens);
// Query a ground plane for each gear/hook/launchbar and // Query a ground plane for each gear/hook/launchbar and
// write that value into the corresponding class. // write that value into the corresponding class.
_fdm->getAirplane()->getModel()->updateGround(&s); _fdm->getAirplane()->getModel()->updateGround(&s);
Launchbar* l = model->getLaunchbar(); Launchbar* l = model->getLaunchbar();
if (l) if (l) {
l->setLaunchCmd(0.0 < _catapult_launch_cmd->getFloatValue()); l->setLaunchCmd(0.0 < _catapult_launch_cmd->getFloatValue());
}
} }
// All the settables: // All the settables:

View file

@ -29,23 +29,6 @@ float fgGetFloat (const char * name, float defaultValue) { return 0; }
double fgGetDouble (const char * name, double defaultValue) { return 0; } double fgGetDouble (const char * name, double defaultValue) { return 0; }
bool fgSetDouble (const char * name, double defaultValue) { return false; } bool fgSetDouble (const char * name, double defaultValue) { return false; }
static const float KTS2MPS = 0.514444444444;
static const float RPM2RAD = 0.10471975512;
static const float HP2W = 745.700;
static const float FT2M = 0.3048;
static const float N2LB = 0.224809;
// static const float DEG2RAD = 0.0174532925199;
// static const float LBS2N = 4.44822;
// static const float LBS2KG = 0.45359237;
// static const float KG2LBS = 2.2046225;
// static const float CM2GALS = 264.172037284;
// static const float INHG2PA = 3386.389;
// static const float K2DEGF = 1.8;
// static const float K2DEGFOFFSET = -459.4;
// static const float CIN2CM = 1.6387064e-5;
// static const float YASIM_PI = 3.14159265358979323846;
const int COUNT = 100; const int COUNT = 100;
int main(int argc, char** argv) int main(int argc, char** argv)
@ -71,9 +54,7 @@ int main(int argc, char** argv)
eng->setBoost(1); eng->setBoost(1);
float alt = (argc > 2 ? atof(argv[2]) : 0) * FT2M; float alt = (argc > 2 ? atof(argv[2]) : 0) * FT2M;
pe->setAir(Atmosphere::getStdPressure(alt), pe->setStandardAtmosphere(alt);
Atmosphere::getStdTemperature(alt),
Atmosphere::getStdDensity(alt));
float speed = (argc > 3 ? atof(argv[3]) : 0) * KTS2MPS; float speed = (argc > 3 ? atof(argv[3]) : 0) * KTS2MPS;
float wind[3]; float wind[3];

View file

@ -0,0 +1,12 @@
#include "Atmosphere.hpp"
using namespace yasim;
int main(int argc, char** argv)
{
Atmosphere a;
if (a.test()) {
return 0;
}
return 1;
}

View file

@ -0,0 +1,34 @@
#ifndef _YASIM_COMMON_HPP
#define _YASIM_COMMON_HPP
namespace yasim {
static const float YASIM_PI = 3.14159265358979323846;
static const float PI2 = YASIM_PI*2;
static const float RAD2DEG = 180/YASIM_PI;
static const float DEG2RAD = YASIM_PI/180;
static const float RPM2RAD = YASIM_PI/30;
static const float KTS2MPS = 1852.0/3600.0;
static const float MPS2KTS = 3600.0/1852.0;
static const float KMH2MPS = 1/3.6;
static const float FT2M = 0.3048;
static const float M2FT = 1/FT2M;
static const float LBS2N = 4.44822;
static const float N2LB = 1/LBS2N;
static const float LBS2KG = 0.45359237;
static const float KG2LBS = 1/LBS2KG;
static const float CM2GALS = 264.172037284;
static const float HP2W = 745.700;
static const float INHG2PA = 3386.389;
static const float K2DEGF = 1.8;
static const float K2DEGFOFFSET = -459.4;
static const float CIN2CM = 1.6387064e-5;
static const float NM2FTLB = (1/(LBS2N*FT2M));
static const float SLUG2KG = 14.59390;
};
#endif // ifndef _YASIM_COMMON_HPP

View file

@ -7,6 +7,7 @@
#include <simgear/xml/easyxml.hxx> #include <simgear/xml/easyxml.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include "yasim-common.hpp"
#include "FGFDM.hpp" #include "FGFDM.hpp"
#include "Atmosphere.hpp" #include "Atmosphere.hpp"
#include "RigidBody.hpp" #include "RigidBody.hpp"
@ -26,11 +27,6 @@ float fgGetFloat (const char * name, float defaultValue) { return 0; }
double fgGetDouble (const char * name, double defaultValue = 0.0) { return 0; } double fgGetDouble (const char * name, double defaultValue = 0.0) { return 0; }
bool fgSetDouble (const char * name, double defaultValue = 0.0) { return 0; } bool fgSetDouble (const char * name, double defaultValue = 0.0) { return 0; }
static const float RAD2DEG = 57.2957795131;
static const float DEG2RAD = 0.0174532925199;
/// knots 2 meters per second
static const float KTS2MPS = 0.514444444444;
enum Config enum Config
{ {
@ -54,7 +50,7 @@ void yasim_graph(Airplane* a, const float alt, const float kts, int cfg = CONFIG
Model* m = a->getModel(); Model* m = a->getModel();
State s; State s;
m->setAirFromStandardAtmosphere(alt); m->setStandardAtmosphere(alt);
switch (cfg) { switch (cfg) {
case CONFIG_APPROACH: case CONFIG_APPROACH:
@ -74,7 +70,7 @@ void yasim_graph(Airplane* a, const float alt, const float kts, int cfg = CONFIG
for(int deg=-15; deg<=90; deg++) { for(int deg=-15; deg<=90; deg++) {
float aoa = deg * DEG2RAD; float aoa = deg * DEG2RAD;
Airplane::setupState(aoa, kts * KTS2MPS, 0 ,&s); s.setupState(aoa, kts * KTS2MPS, 0);
m->getBody()->reset(); m->getBody()->reset();
m->initIteration(); m->initIteration();
m->calcForces(&s); m->calcForces(&s);
@ -129,7 +125,7 @@ void yasim_drag(Airplane* a, const float aoa, const float alt, int cfg = CONFIG_
Model* m = a->getModel(); Model* m = a->getModel();
State s; State s;
m->setAirFromStandardAtmosphere(alt); m->setStandardAtmosphere(alt);
switch (cfg) { switch (cfg) {
case CONFIG_APPROACH: case CONFIG_APPROACH:
@ -148,7 +144,7 @@ void yasim_drag(Airplane* a, const float aoa, const float alt, int cfg = CONFIG_
printf("#kts, drag\n"); printf("#kts, drag\n");
for(int kts=15; kts<=150; kts++) { for(int kts=15; kts<=150; kts++) {
Airplane::setupState(aoa, kts * KTS2MPS, 0 ,&s); s.setupState(aoa, kts * KTS2MPS, 0);
m->getBody()->reset(); m->getBody()->reset();
m->initIteration(); m->initIteration();
m->calcForces(&s); m->calcForces(&s);
@ -254,11 +250,11 @@ int main(int argc, char** argv)
float MACy = a->getWing()->getMACy(); float MACy = a->getWing()->getMACy();
printf(" Iterations: %d\n", a->getSolutionIterations()); printf(" Iterations: %d\n", a->getSolutionIterations());
printf(" Drag Coefficient: %f\n", drag); printf(" Drag Coefficient: %.3f\n", drag);
printf(" Lift Ratio: %f\n", a->getLiftRatio()); printf(" Lift Ratio: %.3f\n", a->getLiftRatio());
printf(" Cruise AoA: %f deg\n", aoa); printf(" Cruise AoA: %.2f deg\n", aoa);
printf(" Tail Incidence: %f deg\n", tail); printf(" Tail Incidence: %.2f deg\n", tail);
printf("Approach Elevator: %f\n\n", a->getApproachElevator()); printf("Approach Elevator: %.3f\n\n", a->getApproachElevator());
printf(" CG: x:%.3f, y:%.3f, z:%.3f\n", cg[0], cg[1], cg[2]); printf(" CG: x:%.3f, y:%.3f, z:%.3f\n", cg[0], cg[1], cg[2]);
printf(" Wing MAC (*1): x:%.2f, y:%.2f, length:%.1f \n", MACx, MACy, MAC); printf(" Wing MAC (*1): x:%.2f, y:%.2f, length:%.1f \n", MACx, MACy, MAC);
printf(" CG-x rel. MAC: %.3f\n", a->getCGMAC()); printf(" CG-x rel. MAC: %.3f\n", a->getCGMAC());