1
0
Fork 0

YASim-0.1.3 updates.

This commit is contained in:
curt 2001-12-10 23:13:54 +00:00
parent ec346bf0ef
commit 9f73588b31
9 changed files with 99 additions and 62 deletions

View file

@ -31,6 +31,10 @@ float Atmosphere::data[][4] = {{ 0, 288.20, 101325, 1.22500 },
{ 18000, 216.66, 7565, 0.12165 }, { 18000, 216.66, 7565, 0.12165 },
{ 18900, 216.66, 6570, 0.10564 }}; { 18900, 216.66, 6570, 0.10564 }};
// 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.
const float R = 287.1;
float Atmosphere::getStdTemperature(float alt) float Atmosphere::getStdTemperature(float alt)
{ {
return getRecord(alt, 1); return getRecord(alt, 1);
@ -48,7 +52,9 @@ float Atmosphere::getStdDensity(float alt)
float Atmosphere::calcVEAS(float spd, float pressure, float temp) float Atmosphere::calcVEAS(float spd, float pressure, float temp)
{ {
return 0; //FIXME static float rho0 = getStdDensity(0);
float densityRatio = calcDensity(pressure, temp) / rho0;
return spd * Math::sqrt(densityRatio);
} }
float Atmosphere::calcVCAS(float spd, float pressure, float temp) float Atmosphere::calcVCAS(float spd, float pressure, float temp)
@ -84,13 +90,12 @@ float Atmosphere::calcVCAS(float spd, float pressure, float temp)
float Atmosphere::calcDensity(float pressure, float temp) float Atmosphere::calcDensity(float pressure, float temp)
{ {
// P = rho*R*T, R == 287 kPa*m^3 per kg*kelvin for air return pressure / (R * temp);
return pressure / (287 * temp);
} }
float Atmosphere::calcMach(float spd, float temp) float Atmosphere::calcMach(float spd, float temp)
{ {
return spd / Math::sqrt(1.4 * 287 * temp); return spd / Math::sqrt(1.4 * R * temp);
} }
float Atmosphere::getRecord(float alt, int recNum) float Atmosphere::getRecord(float alt, int recNum)

View file

@ -77,23 +77,10 @@ Airplane* FGFDM::getAirplane()
void FGFDM::init() void FGFDM::init()
{ {
// We don't want to use these ties (we set the values ourselves, // We don't want to use these ties (we set the values ourselves)
// and this works only for the first piston engine anyway).
fgUntie("/engines/engine[0]/rpm");
fgUntie("/engines/engine[0]/egt-degf");
fgUntie("/engines/engine[0]/cht-degf");
fgUntie("/engines/engine[0]/oil-temperature-degf");
fgUntie("/engines/engine[0]/mp-osi");
fgUntie("/engines/engine[0]/fuel-flow-gph");
fgUntie("/engines/engine[0]/running");
fgUntie("/engines/engine[0]/cranking");
fgUntie("/consumables/fuel/tank[0]/level-gal_us"); fgUntie("/consumables/fuel/tank[0]/level-gal_us");
fgUntie("/consumables/fuel/tank[1]/level-gal_us"); fgUntie("/consumables/fuel/tank[1]/level-gal_us");
// Set these to sane values. We don't support engine start yet.
fgSetBool("/engines/engine[0]/running", true);
fgSetBool("/engines/engine[0]/cranking", false);
// Allows the user to start with something other than full fuel // Allows the user to start with something other than full fuel
_airplane.setFuelFraction(fgGetFloat("/yasim/fuel-fraction", 1)); _airplane.setFuelFraction(fgGetFloat("/yasim/fuel-fraction", 1));

View file

@ -143,8 +143,11 @@ void Gear::calcForce(RigidBody* body, float* v, float* rot, float* ground)
// 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.
float a = ground[3] - Math::dot3(_pos, ground); float a = ground[3] - Math::dot3(_pos, ground);
if(a > 0) if(a > 0) {
_wow = 0;
_frac = 0;
return; return;
}
// Now a is the distance from the tip to ground, so make b the // Now a is the distance from the tip to ground, so make b the
// distance from the base to ground. We can get the fraction // distance from the base to ground. We can get the fraction
@ -169,11 +172,10 @@ void Gear::calcForce(RigidBody* body, float* v, float* rot, float* ground)
body->pointVelocity(_contact, rot, cv); body->pointVelocity(_contact, rot, cv);
Math::add3(cv, v, cv); Math::add3(cv, v, cv);
// Finally, we can start adding up the forces. First the // Finally, we can start adding up the forces. First the spring
// spring compression (note the clamping of _frac to 1): // compression. (note the clamping of _frac to 1):
_frac = (_frac > 1) ? 1 : _frac; _frac = (_frac > 1) ? 1 : _frac;
float fmag = _frac*clen*_spring; float fmag = _frac*clen*_spring;
Math::mul3(fmag, cmpr, _force);
// Then the damping. Use the only the velocity into the ground // Then the damping. Use the only the velocity into the ground
// (projection along "ground") projected along the compression // (projection along "ground") projected along the compression
@ -183,10 +185,11 @@ void Gear::calcForce(RigidBody* body, float* v, float* rot, float* ground)
float damp = _damp * dv; float damp = _damp * dv;
if(damp > fmag) damp = fmag; // can't pull the plane down! if(damp > fmag) damp = fmag; // can't pull the plane down!
if(damp < -fmag) damp = -fmag; // sanity if(damp < -fmag) damp = -fmag; // sanity
Math::mul3(-damp, cmpr, tmp);
Math::add3(_force, tmp, _force);
_wow = fmag - damp; // The actual force applied is only the component perpendicular to
// the ground. Side forces come from velocity only.
_wow = (fmag - damp) * -Math::dot3(cmpr, ground);
Math::mul3(-_wow, ground, _force);
// Wheels are funky. Split the velocity along the ground plane // Wheels are funky. Split the velocity along the ground plane
// into rolling and skidding components. Assuming small angles, // into rolling and skidding components. Assuming small angles,

View file

@ -20,11 +20,6 @@ float Math::sqrt(float f)
return ::sqrt(f); return ::sqrt(f);
} }
float Math::pow(float base, float exp)
{
return ::pow(base, exp);
}
float Math::ceil(float f) float Math::ceil(float f)
{ {
return ::ceil(f); return ::ceil(f);
@ -60,7 +55,7 @@ double Math::sqrt(double f)
return ::sqrt(f); return ::sqrt(f);
} }
double Math::pow(double base, double exp) float Math::pow(double base, double exp)
{ {
return ::pow(base, exp); return ::pow(base, exp);
} }

View file

@ -12,17 +12,18 @@ public:
// Simple wrappers around library routines // Simple wrappers around library routines
static float abs(float f); static float abs(float f);
static float sqrt(float f); static float sqrt(float f);
static float pow(float base, float exp);
static float ceil(float f); static float ceil(float f);
static float sin(float f); static float sin(float f);
static float cos(float f); static float cos(float f);
static float tan(float f); static float tan(float f);
static float atan2(float y, float x); static float atan2(float y, float x);
// Takes two args and runs afoul of the Koenig rules.
static float pow(double base, double exp);
// double variants of the above // double variants of the above
static double abs(double f); static double abs(double f);
static double sqrt(double f); static double sqrt(double f);
static double pow(double base, double exp);
static double ceil(double f); static double ceil(double f);
static double sin(double f); static double sin(double f);
static double cos(double f); static double cos(double f);

View file

@ -47,6 +47,9 @@ Model::Model()
// Default value of 30 Hz // Default value of 30 Hz
_integrator.setInterval(1.0/30.0); _integrator.setInterval(1.0/30.0);
_agl = 0;
_crashed = false;
} }
Model::~Model() Model::~Model()
@ -99,6 +102,21 @@ void Model::iterate()
_integrator.calcNewInterval(); _integrator.calcNewInterval();
} }
bool Model::isCrashed()
{
return _crashed;
}
void Model::setCrashed(bool crashed)
{
_crashed = crashed;
}
float Model::getAGL()
{
return _agl;
}
State* Model::getState() State* Model::getState()
{ {
return _s; return _s;
@ -269,20 +287,27 @@ void Model::newState(State* s)
//printState(s); //printState(s);
// Some simple collision detection // Some simple collision detection
float min = 1e8;
float ground[4], pos[3], cmpr[3]; float ground[4], pos[3], cmpr[3];
ground[3] = localGround(s, ground); ground[3] = localGround(s, ground);
int i; int i;
for(i=0; i<_gears.size(); i++) { for(i=0; i<_gears.size(); i++) {
Gear* g = (Gear*)_gears.get(i); Gear* g = (Gear*)_gears.get(i);
// Get the point of ground contact
g->getPosition(pos); g->getPosition(pos);
g->getCompression(cmpr); g->getCompression(cmpr);
Math::mul3(g->getCompressFraction(), cmpr, cmpr);
Math::add3(cmpr, pos, pos); Math::add3(cmpr, pos, pos);
float dist = ground[3] - Math::dot3(pos, ground); float dist = ground[3] - Math::dot3(pos, ground);
if(dist < 0) {
printf("CRASH: gear %d\n", i); // Find the lowest one
*(int*)0=0; if(dist < min)
} min = dist;
} }
_agl = min;
if(_agl < -1) // Allow for some integration slop
_crashed = true;
} }
// Returns a unit "down" vector for the ground in out, and the // Returns a unit "down" vector for the ground in out, and the

View file

@ -24,6 +24,9 @@ public:
State* getState(); State* getState();
void setState(State* s); void setState(State* s);
bool isCrashed();
void setCrashed(bool crashed);
float getAGL();
void iterate(); void iterate();
@ -81,6 +84,8 @@ private:
float _torque[3]; float _torque[3];
State* _s; State* _s;
bool _crashed;
float _agl;
}; };
}; // namespace yasim }; // namespace yasim

View file

@ -126,9 +126,6 @@ void PropEngine::integrate(float dt)
// needs to go away when the startup code gets written. // needs to go away when the startup code gets written.
if(_omega < 52.3) _omega = 52.3; if(_omega < 52.3) _omega = 52.3;
// FIXME: Integrate the propeller governor here, when that gets
// implemented...
// Store the total angular momentum into _gyro // Store the total angular momentum into _gyro
Math::mul3(_omega*_moment, _dir, _gyro); Math::mul3(_omega*_moment, _dir, _gyro);
@ -140,15 +137,25 @@ void PropEngine::integrate(float dt)
float tau = _moment < 0 ? engTorque : -engTorque; float tau = _moment < 0 ? engTorque : -engTorque;
Math::mul3(tau, _dir, _torque); Math::mul3(tau, _dir, _torque);
// Play with the variable propeller, but only if the propeller is // Iterate the propeller governor, if we have one. Since engine
// vaguely stable alread (accelerating less than 100 rpm/s) // torque is basically constant with RPM, we want to make the
if(_variable && Math::abs(rotacc) < 20) { // propeller torque at the target RPM equal to the engine by
float target = _minOmega + _advance*(_maxOmega-_minOmega); // varying the pitch. Assume the the torque goes as the square of
float mod = 1.04; // the RPM (roughly correct) and compute a "target" torque for the
if(target > _omega) mod = 1/mod; // _current_ RPM. Seek to that. This is sort of a continuous
float diff = Math::abs(target - _omega); // Newton-Raphson, basically.
if(diff < 1) mod = 1 + (mod-1)*diff; if(_variable) {
if(thrust < 0) mod = 1; float targetOmega = _minOmega + _advance*(_maxOmega-_minOmega);
float ratio2 = (_omega*_omega)/(targetOmega*targetOmega);
float targetTorque = engTorque * ratio2;
float mod = propTorque < targetTorque ? 1.04 : (1/1.04);
// Convert to an acceleration here, so that big propellers
// don't seek faster than small ones.
float diff = Math::abs(propTorque - targetTorque) / _moment;
if(diff < 10) mod = 1 + (mod-1)*(0.1*diff);
_prop->modPitch(mod); _prop->modPitch(mod);
} }
} }

View file

@ -105,6 +105,8 @@ void YASim::init()
// Superclass hook // Superclass hook
common_init(); common_init();
m->setCrashed(false);
// Build a filename and parse it // Build a filename and parse it
SGPath f(globals->get_fg_root()); SGPath f(globals->get_fg_root());
f.append("Aircraft-yasim"); f.append("Aircraft-yasim");
@ -141,16 +143,19 @@ void YASim::init()
} }
// Lift the plane up so the gear clear the ground // Are we at ground level? If so, lift the plane up so the gear
float minGearZ = 1e18; // clear the ground
for(i=0; i<a->numGear(); i++) { if(get_Altitude() - get_Runway_altitude() < 50) {
Gear* g = a->getGear(i); float minGearZ = 1e18;
float pos[3]; for(i=0; i<a->numGear(); i++) {
g->getPosition(pos); Gear* g = a->getGear(i);
if(pos[2] < minGearZ) float pos[3];
minGearZ = pos[2]; g->getPosition(pos);
if(pos[2] < minGearZ)
minGearZ = pos[2];
}
_set_Altitude(get_Runway_altitude() - minGearZ*M2FT);
} }
_set_Altitude(get_Altitude() - minGearZ*M2FT);
// The pilot's eyepoint // The pilot's eyepoint
float pilot[3]; float pilot[3];
@ -169,6 +174,10 @@ void YASim::init()
bool YASim::update(int iterations) bool YASim::update(int iterations)
{ {
// If we're crashed, then we don't care
if(_fdm->getAirplane()->getModel()->isCrashed())
return true;
int i; int i;
for(i=0; i<iterations; i++) { for(i=0; i<iterations; i++) {
// Remember, update only every 4th call // Remember, update only every 4th call
@ -310,10 +319,7 @@ void YASim::copyFromYASim()
// UNUSED // UNUSED
//_set_Geocentric_Position(Glue::geod2geocLat(lat), lon, alt*M2FT); //_set_Geocentric_Position(Glue::geod2geocLat(lat), lon, alt*M2FT);
// FIXME: there's a normal vector available too, use it. _set_Altitude_AGL(model->getAGL() * M2FT);
float groundMSL = scenery.get_cur_elev();
_set_Runway_altitude(groundMSL*M2FT);
_set_Altitude_AGL((alt - groundMSL)*M2FT);
// useful conversion matrix // useful conversion matrix
float xyz2ned[9]; float xyz2ned[9];
@ -390,6 +396,8 @@ void YASim::copyFromYASim()
fgg->SetBrake(true); fgg->SetBrake(true);
if(g->getCompressFraction() != 0) if(g->getCompressFraction() != 0)
fgg->SetWoW(true); fgg->SetWoW(true);
else
fgg->SetWoW(false);
fgg->SetPosition(g->getExtension()); fgg->SetPosition(g->getExtension());
} }
@ -398,6 +406,7 @@ void YASim::copyFromYASim()
Thruster* t = model->getThruster(i); Thruster* t = model->getThruster(i);
fge->set_Running_Flag(true); fge->set_Running_Flag(true);
fge->set_Cranking_Flag(false);
// Note: assumes all tanks have the same fuel density! // Note: assumes all tanks have the same fuel density!
fge->set_Fuel_Flow(CM2GALS * t->getFuelFlow() fge->set_Fuel_Flow(CM2GALS * t->getFuelFlow()