Question about aircraft physics.

Started by
16 comments, last by MrRowl 12 years, 1 month ago
Alright, I've hit another wall, and that is with how to calculate airflow. Can anyone point me in the right direction?

No one expects the Spanish Inquisition!

Advertisement
Here's a really lazy answer - just the function I use to calculate the lift/drag, based on the environment wind, the transform of the aerofoil, and a graph of CL vs angle of attack (plus an indicator of whether the aerofoil is stalled), plus a few other params. You won't want to use as it is, but maybe it will give a few hints at how to get things started.

void AerofoilDefinition::ApplyForces(
Aeroplane* aeroplane,
const AerofoilConfiguration& configuration,
const AerofoilParameters& parameters,
const AerofoilControl& control,
const Environment& environment) const
{
Vector3 globalWind = environment.GetWindAtPosition(parameters.mTM.GetTrans());
// Airflow is relative to the aerofoil so +ve X is forward, +ve Y is left, +ve Z is up
Vector3 airflow = parameters.mTM.GetTranspose().RotateVec(globalWind - parameters.mVel);
float speedSq = Square(airflow.x) + Square(airflow.z);
if (speedSq < Square(0.01f))
return;
float angleOfAttack = atan2f(airflow.z, -airflow.x);
angleOfAttack += control.mExtraAngle;
float cosAngleOfAttack = cosf(angleOfAttack);
float sinAngleOfAttack = sinf(angleOfAttack);
float CL, flying;
GetGraphData(angleOfAttack, CL, flying);
CL += control.mExtraCL;
// Calculate CD
float CD = CL * CL * mCDInducedFrac;
CD += control.mExtraCD;
CD += Square(1.0f - flying) * mCDMax * Square(sinAngleOfAttack);
// Calculate the force application point
Vector3 forceApplicationPoint = parameters.mTM.GetTrans();
if (flying > 0.0f)
forceApplicationPoint += parameters.mTM.RowX() * flying * mLiftPositionOffsetFractionForwards * configuration.mExtents.x * 0.5f;
else
forceApplicationPoint += parameters.mTM.RowX() * flying * mLiftPositionOffsetFractionReverse * configuration.mExtents.x * 0.5f;
// Calculate the forces
float forceScale = configuration.mArea * 0.5f * speedSq;
// These forces are relative to the airflow (not to the airofoil)
// Assume air density = 1
float liftForce = forceScale * CL;
float dragForce = forceScale * CD;
const float forceRenderScale = 0.3f;
Transform t;
t.SetAxisAngle(parameters.mTM.RowY(), angleOfAttack - control.mExtraAngle);
Vector3 dragDir = -t.RotateVec(parameters.mTM.RowX());
Vector3 liftDir = t.RotateVec(parameters.mTM.RowZ());
Vector3 force = liftForce * liftDir + dragForce * dragDir;
aeroplane->GetPhysics()->ApplyWorldForceAtWorldPosition(force, forceApplicationPoint);
}


//----------------------------------------------------------------------------------------------------------------------
void AerofoilDefinition::GetGraphData(float angleOfAttack, float& CL, float& flying) const
{
if (angleOfAttack > PI)
angleOfAttack -= 2.0f * PI;
else if (angleOfAttack < -PI)
angleOfAttack += 2.0f * PI;

size_t numData = mGraphData.size();
for (size_t i = 0 ; i != numData ; ++i)
{
const AerodynamicData& d0 = mGraphData;
if (d0.mAngle <= angleOfAttack)
{
const AerodynamicData& d1 = mGraphData[(i+1) % numData];
float angle1 = d1.mAngle;
if (i == numData-1)
angle1 += PI * 2.0f;
if (angle1 >= angleOfAttack)
{
float frac = (angleOfAttack - d0.mAngle) / (angle1 - d0.mAngle);
CL = frac * d1.mCL + (1.0f - frac) * d0.mCL;
flying = frac * d1.mFlying + (1.0f - frac) * d1.mFlying;
return;
}
}
}
// TODO implement this better and handle out of range etc
CL = 0.0f;
flying = 0.0f;
IwAssert(MY_APP, false);
}


and example data for a symmetric aerofoil might be something like this:

[xml]<Aerofoil
name="StandardSymmetric"
liftPositionOffsetFractionForwards="0.5"
liftPositionOffsetFractionReverse="-0.5"
CDInducedFrac="0.2"
CDMax="3.0"
CMNeutral="0.0"
/>
<Data angle="-180.0f" CL="-0.0f" flying="-1"/>
<Data angle="-164.0f" CL="0.6f" flying="-1"/>
<Data angle="-163.0f" CL="0.25f" flying=" 0"/>
<Data angle=" -90.0f" CL="0.0f" flying=" 0"/>
<Data angle=" -13.0f" CL="-0.5f" flying=" 0"/>
<Data angle=" -12.0f" CL="-1.2f" flying=" 1"/>
<Data angle=" 0.0f" CL="0.0f" flying=" 1"/>
<Data angle=" 12.0f" CL="1.2f" flying=" 1"/>
<Data angle=" 13.0f" CL="0.5f" flying=" 0"/>
<Data angle=" 90.0f" CL="0.0f" flying=" 0"/>
<Data angle=" 163.0f" CL="-0.25f" flying=" 0"/>
<Data angle=" 164.0f" CL="-0.6f" flying="-1"/>
[/xml]
Alright, but how are you calculating the global wind at the particular position? Is that the same everywhere? Also, you are rotating the global wind to get the airflow? Why?

No one expects the Spanish Inquisition!


Alright, but how are you calculating the global wind at the particular position? Is that the same everywhere? Also, you are rotating the global wind to get the airflow? Why?


In my sim the wind varies from place to place, and that's particularly important to me because I'm simulating gliders flying on uplift as the wind blows over hills etc.

This line:


[color=#660066]Vector3[color=#000000] airflow [color=#666600]=[color=#000000] parameters[color=#666600].[color=#000000]mTM[color=#666600].[color=#660066]GetTranspose[color=#666600]().[color=#660066]RotateVec[color=#666600]([color=#000000]globalWind [color=#666600]-[color=#000000] parameters[color=#666600].[color=#000000]mVel[color=#666600]);

transforms the airflow relative to the aerofoil (globalWind - parameters.mVel) in the coordinate frame of the aerofoil itself, by rotating it (as you say). That's because zero angle attack is defined as being when the air is flowing straight past the aerofoil (i.e. in the negative x direction, because I define my aerofoils such that x is forward and z is up). It's easiest to define the lift/drag formulae in a reference frame that moves with the aerofoil, so the steps are:

1. Convert everything into that reference frame
2. Calculate the forces in that reference frame
3. Convert the forces into the global reference frame, and apply them
I know I'm asking lots of questions, so bear with me here. So the global wind is generally always constant, or does it change?

No one expects the Spanish Inquisition!


So the global wind is generally always constant, or does it change?


It's a function of position and time. But I can't see how that's relevant.
No, I meant that for my simulation would the global wind change, or would it remain the same? I'm making a basic combat flight simulator, so I'm curious as to how wind applies to that.

No one expects the Spanish Inquisition!


No, I meant that for my simulation would the global wind change, or would it remain the same? I'm making a basic combat flight simulator, so I'm curious as to how wind applies to that.


By wind, we're meaning the ambient flow of air relative to the ground, right? In which case it's entirely up to you whether you want to model it in your sim or not. For my sim it's vital, because wind/thermals are required for gliders to stay aloft. For a combat flight sim with powered aircraft it's probably entirely optional (but also probably trivial compared to the rest of what you need to do), depending on how detailed you want the simulation to be. It would likely only be noticed by the player during landing and takeoff.

This topic is closed to new replies.

Advertisement