Merge /u/jsb1685/flightgear/ branch yasim into next
https://sourceforge.net/p/flightgear/flightgear/merge-requests/89/
This commit is contained in:
commit
2747a33e6b
32 changed files with 546 additions and 758 deletions
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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?
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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];
|
||||||
|
|
12
src/FDM/YASim/yasim-atmotest.cpp
Normal file
12
src/FDM/YASim/yasim-atmotest.cpp
Normal 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;
|
||||||
|
}
|
34
src/FDM/YASim/yasim-common.hpp
Normal file
34
src/FDM/YASim/yasim-common.hpp
Normal 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
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in a new issue