Example #1
0
bool FGAerodynamics::Run(bool Holding)
{

  if (FGModel::Run(Holding)) return true;
  if (Holding) return false; // if paused don't execute

  unsigned int axis_ctr, ctr;
  const double twovel=2*in.Vt;

  RunPreFunctions();

  // calculate some oft-used quantities for speed

  if (twovel != 0) {
    bi2vel = in.Wingspan / twovel;
    ci2vel = in.Wingchord / twovel;
  }
  alphaw = in.Alpha + in.Wingincidence;
  qbar_area = in.Wingarea * in.Qbar;

  if (alphaclmax != 0) {
    if (in.Alpha > 0.85*alphaclmax) {
      impending_stall = 10*(in.Alpha/alphaclmax - 0.85);
    } else {
      impending_stall = 0;
    }
  }

  if (alphahystmax != 0.0 && alphahystmin != 0.0) {
    if (in.Alpha > alphahystmax) {
       stall_hyst = 1;
    } else if (in.Alpha < alphahystmin) {
       stall_hyst = 0;
    }
  }

  vFw.InitMatrix();
  vFnative.InitMatrix();

  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
    for (ctr=0; ctr < AeroFunctions[axis_ctr].size(); ctr++) {
      vFnative(axis_ctr+1) += AeroFunctions[axis_ctr][ctr]->GetValue();
    }
  }

  // Note that we still need to convert to wind axes here, because it is
  // used in the L/D calculation, and we still may want to look at Lift
  // and Drag.

  switch (axisType) {
    case atBodyXYZ:       // Forces already in body axes; no manipulation needed
      vFw = in.Tb2w*vFnative;
      vForces = vFnative;
      break;
    case atLiftDrag:      // Copy forces into wind axes
      vFw = vFnative;
      vFw(eDrag)*=-1; vFw(eLift)*=-1;
      vForces = in.Tw2b*vFw;
      break;
    case atAxialNormal:   // Convert native forces into Axial|Normal|Side system
      vFw = in.Tb2w*vFnative;
      vFnative(eX)*=-1; vFnative(eZ)*=-1;
      vForces = vFnative;
      break;
    default:
      cerr << endl << "  A proper axis type has NOT been selected. Check "
                   << "your aerodynamics definition." << endl;
      exit(-1);
  }

  // Calculate lift coefficient squared
  if ( in.Qbar > 0) {
    clsq = vFw(eLift) / (in.Wingarea*in.Qbar);
    clsq *= clsq;
  }

  // Calculate lift Lift over Drag
  if ( fabs(vFw(eDrag)) > 0.0) lod = fabs( vFw(eLift) / vFw(eDrag) );

  // Calculate aerodynamic reference point shift, if any. The shift
  // takes place in the structual axis. That is, if the shift is positive,
  // it is towards the back (tail) of the vehicle. The AeroRPShift
  // function should be non-dimensionalized by the wing chord. The
  // calculated vDeltaRP will be in feet.
  if (AeroRPShift) vDeltaRP(eX) = AeroRPShift->GetValue()*in.Wingchord;

  vDXYZcg(eX) = in.RPBody(eX) - vDeltaRP(eX); // vDeltaRP is given in the structural frame
  vDXYZcg(eY) = in.RPBody(eY) + vDeltaRP(eY);
  vDXYZcg(eZ) = in.RPBody(eZ) - vDeltaRP(eZ);

  vMoments = vDXYZcg*vForces; // M = r X F

  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
    for (ctr = 0; ctr < AeroFunctions[axis_ctr+3].size(); ctr++) {
      vMoments(axis_ctr+1) += AeroFunctions[axis_ctr+3][ctr]->GetValue();
    }
  }

  RunPostFunctions();

  return false;
}
Example #2
0
bool FGAerodynamics::Run(bool Holding)
{

  if (FGModel::Run(Holding)) return true;
  if (Holding) return false; // if paused don't execute

  unsigned int axis_ctr, ctr;
  const double twovel=2*in.Vt;

  RunPreFunctions();

  // calculate some oft-used quantities for speed

  if (twovel != 0) {
    bi2vel = in.Wingspan / twovel;
    ci2vel = in.Wingchord / twovel;
  }
  alphaw = in.Alpha + in.Wingincidence;
  qbar_area = in.Wingarea * in.Qbar;

  if (alphaclmax != 0) {
    if (in.Alpha > 0.85*alphaclmax) {
      impending_stall = 10*(in.Alpha/alphaclmax - 0.85);
    } else {
      impending_stall = 0;
    }
  }

  if (alphahystmax != 0.0 && alphahystmin != 0.0) {
    if (in.Alpha > alphahystmax) {
       stall_hyst = 1;
    } else if (in.Alpha < alphahystmin) {
       stall_hyst = 0;
    }
  }

  vFw.InitMatrix();
  vFwAtCG.InitMatrix();
  vFnative.InitMatrix();
  vFnativeAtCG.InitMatrix();

  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
    for (ctr=0; ctr < AeroFunctions[axis_ctr].size(); ctr++) {
      vFnative(axis_ctr+1) += AeroFunctions[axis_ctr][ctr]->GetValue();
    }
  }

  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
    for (ctr=0; ctr < AeroFunctionsAtCG[axis_ctr].size(); ctr++) {
      vFnativeAtCG(axis_ctr+1) += AeroFunctionsAtCG[axis_ctr][ctr]->GetValue();
    }
  }

  // Note that we still need to convert to wind axes here, because it is
  // used in the L/D calculation, and we still may want to look at Lift
  // and Drag.

  // JSB 4/27/12 - After use, convert wind axes to produce normal lift
  // and drag values - not negative ones!

  // As a clarification, JSBSim assumes that drag and lift values are defined 
  // in wind axes - BUT with a 180 rotation about the Y axis. That is, lift and
  // drag will be positive up and aft, respectively, so that they are reported
  // as positive numbers. However, the wind axes themselves assume that the X
  // and Z forces are positive forward and down.

  switch (axisType) {
    case atBodyXYZ:       // Forces already in body axes; no manipulation needed
      vFw = in.Tb2w*vFnative;
      vForces = vFnative;
      vFw(eDrag)*=-1; vFw(eLift)*=-1;

      vFwAtCG = in.Tb2w*vFnativeAtCG;
      vForcesAtCG = vFnativeAtCG;
      vFwAtCG(eDrag)*=-1; vFwAtCG(eLift)*=-1;
      break;
    case atLiftDrag:      // Copy forces into wind axes
      vFw = vFnative;
      vFw(eDrag)*=-1; vFw(eLift)*=-1;
      vForces = in.Tw2b*vFw;
      vFw(eDrag)*=-1; vFw(eLift)*=-1;

      vFwAtCG = vFnativeAtCG;
      vFwAtCG(eDrag)*=-1; vFwAtCG(eLift)*=-1;
      vForcesAtCG = in.Tw2b*vFwAtCG;
      vFwAtCG(eDrag)*=-1; vFwAtCG(eLift)*=-1;
      break;
    case atAxialNormal:   // Convert native forces into Axial|Normal|Side system
      vFw = in.Tb2w*vFnative;
      vFnative(eX)*=-1; vFnative(eZ)*=-1;
      vForces = vFnative;

      vFwAtCG = in.Tb2w*vFnativeAtCG;
      vFnativeAtCG(eX)*=-1; vFnativeAtCG(eZ)*=-1;
      vForcesAtCG = vFnativeAtCG;
      break;
    default:
      cerr << endl << "  A proper axis type has NOT been selected. Check "
                   << "your aerodynamics definition." << endl;
      exit(-1);
  }

  // Calculate lift coefficient squared
  if ( in.Qbar > 0) {
    clsq = (vFw(eLift) + vFwAtCG(eLift))/ (in.Wingarea*in.Qbar);
    clsq *= clsq;
  }

  // Calculate lift Lift over Drag
  if ( fabs(vFw(eDrag) + vFwAtCG(eDrag)) > 0.0)
    lod = fabs( (vFw(eLift) + vFwAtCG(eLift))/ (vFw(eDrag) + vFwAtCG(eDrag)));

  // Calculate aerodynamic reference point shift, if any. The shift
  // takes place in the structual axis. That is, if the shift is positive,
  // it is towards the back (tail) of the vehicle. The AeroRPShift
  // function should be non-dimensionalized by the wing chord. The
  // calculated vDeltaRP will be in feet.
  if (AeroRPShift) vDeltaRP(eX) = AeroRPShift->GetValue()*in.Wingchord;

  vDXYZcg(eX) = in.RPBody(eX) - vDeltaRP(eX); // vDeltaRP is given in the structural frame
  vDXYZcg(eY) = in.RPBody(eY) + vDeltaRP(eY);
  vDXYZcg(eZ) = in.RPBody(eZ) - vDeltaRP(eZ);

  vMomentsMRC.InitMatrix();

  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
    for (ctr = 0; ctr < AeroFunctions[axis_ctr+3].size(); ctr++) {
      vMomentsMRC(axis_ctr+1) += AeroFunctions[axis_ctr+3][ctr]->GetValue();
    }
  }
  vMoments = vMomentsMRC + vDXYZcg*vForces; // M = r X F
  // Now add the "at CG" values to base forces - after the moments have been transferred
  vForces += vForcesAtCG;
  vFnative += vFnativeAtCG;
  vFw += vFwAtCG;

  RunPostFunctions();

  return false;
}