コード例 #1
0
ファイル: FGPropulsion.cpp プロジェクト: AEgisTG/jsbsim
bool FGPropulsion::Run(bool Holding)
{
  unsigned int i;

  if (FGModel::Run(Holding)) return true;
  if (Holding) return false;

  RunPreFunctions();

  vForces.InitMatrix();
  vMoments.InitMatrix();

  for (i=0; i<numEngines; i++) {
    Engines[i]->Calculate();
    ConsumeFuel(Engines[i]);
    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
    vMoments += Engines[i]->GetMoments();     // sum body frame moments
  }

  TotalFuelQuantity = 0.0;
  for (i=0; i<numTanks; i++) {
    Tanks[i]->Calculate( in.TotalDeltaT, in.TAT_c);
    if (Tanks[i]->GetType() == FGTank::ttFUEL) {
      TotalFuelQuantity += Tanks[i]->GetContents();
    }
  }

  if (refuel) DoRefuel( in.TotalDeltaT );
  if (dump) DumpFuel( in.TotalDeltaT );

  RunPostFunctions();

  return false;
}
コード例 #2
0
ファイル: FGFCS.cpp プロジェクト: agodemar/jsbsim
bool FGFCS::Run(bool Holding)
{
  unsigned int i;

  if (FGModel::Run(Holding)) return true; // fast exit if nothing to do
  if (Holding) return false;

  RunPreFunctions();

  for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
  for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
  for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
  for (i=0; i<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i];

  // Execute system channels in order
  for (i=0; i<SystemChannels.size(); i++) {
    if (debug_lvl & 4) cout << "    Executing System Channel: " << SystemChannels[i]->GetName() << endl;
    ChannelRate = SystemChannels[i]->GetRate();
    SystemChannels[i]->Execute();
  }
  ChannelRate = 1;

  RunPostFunctions();

  return false;
}
コード例 #3
0
ファイル: FGPropulsion.cpp プロジェクト: 8W9aG/jsbsim
bool FGPropulsion::Run(void)
{
  unsigned int i;

  if (FGModel::Run()) return true;
  if (FDMExec->Holding()) return false;

  RunPreFunctions();

  double dt = FDMExec->GetDeltaT();

  vForces.InitMatrix();
  vMoments.InitMatrix();

  for (i=0; i<numEngines; i++) {
    Engines[i]->Calculate();
    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
    vMoments += Engines[i]->GetMoments();     // sum body frame moments
  }

  TotalFuelQuantity = 0.0;
  for (i=0; i<numTanks; i++) {
    Tanks[i]->Calculate( dt * rate );
    if (Tanks[i]->GetType() == FGTank::ttFUEL) {
      TotalFuelQuantity += Tanks[i]->GetContents();
    }
  }

  if (refuel) DoRefuel( dt * rate );
  if (dump) DumpFuel( dt * rate );

  RunPostFunctions();

  return false;
}
コード例 #4
0
ファイル: FGRocket.cpp プロジェクト: adrcad/jsbsim
void FGRocket::Calculate(void)
{
  if (FDMExec->IntegrationSuspended()) return;

  RunPreFunctions();

  PropellantFlowRate = (FuelExpended + OxidizerExpended)/in.TotalDeltaT;
  TotalPropellantExpended += FuelExpended + OxidizerExpended;
  // If Isp has been specified as a function, override the value of Isp to that, otherwise
  // assume a constant value is given.
  if (isp_function) Isp = isp_function->GetValue();

  // If there is a thrust table, it is a function of propellant burned. The
  // engine is started when the throttle is advanced to 1.0. After that, it
  // burns without regard to throttle setting.

  if (ThrustTable != 0L) { // Thrust table given -> Solid fuel used

    if ((in.ThrottlePos[EngineNumber] == 1 || BurnTime > 0.0 ) && !Starved) {

      VacThrust = ThrustTable->GetValue(TotalPropellantExpended)
                * (ThrustVariation + 1)
                * (TotalIspVariation + 1);
      if (BurnTime <= BuildupTime && BuildupTime > 0.0) {
        VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0);
        // VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach
      }
      BurnTime += in.TotalDeltaT; // Increment burn time
    } else {
      VacThrust = 0.0;
    }

  } else { // liquid fueled rocket assumed

    if (in.ThrottlePos[EngineNumber] < MinThrottle || Starved) { // Combustion not supported

      PctPower = 0.0; // desired thrust
      Flameout = true;
      VacThrust = 0.0;

    } else { // Calculate thrust

      // PctPower = Throttle / MaxThrottle; // Min and MaxThrottle range from 0.0 to 1.0, normally.
      
      PctPower = in.ThrottlePos[EngineNumber];
      Flameout = false;
      VacThrust = Isp * PropellantFlowRate;

    }

  } // End thrust calculations

  LoadThrusterInputs();
  It += Thruster->Calculate(VacThrust) * in.TotalDeltaT;
  ItVac += VacThrust * in.TotalDeltaT;

  RunPostFunctions();
}
コード例 #5
0
bool FGOutput::Run(bool Holding)
{
  if (FGModel::Run(Holding)) return true;

  if (enabled && !FDMExec->IntegrationSuspended() && !Holding) {
    RunPreFunctions();
    Print();
    RunPostFunctions();
  }
  return false;
}
コード例 #6
0
ファイル: FGPiston.cpp プロジェクト: 8W9aG/jsbsim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPiston::Calculate(void)
{
  RunPreFunctions();

  if (FuelFlow_gph > 0.0) ConsumeFuel();

  Throttle = FCS->GetThrottlePos(EngineNumber);
  Mixture = FCS->GetMixturePos(EngineNumber);

  // Input values.

  p_amb = Atmosphere->GetPressure() * psftopa;
  double p = Auxiliary->GetTotalPressure() * psftopa;
  p_ram = (p - p_amb) * Ram_Air_Factor + p_amb;
  T_amb = RankineToKelvin(Atmosphere->GetTemperature());

  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
  MeanPistonSpeed_fps =  ( RPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS

  IAS = Auxiliary->GetVcalibratedKTS();

  doEngineStartup();
  if (Boosted) doBoostControl();
  doMAP();
  doAirFlow();
  doFuelFlow();

  //Now that the fuel flow is done check if the mixture is too lean to run the engine
  //Assume lean limit at 22 AFR for now - thats a thi of 0.668
  //This might be a bit generous, but since there's currently no audiable warning of impending
  //cutout in the form of misfiring and/or rough running its probably reasonable for now.

  //  if (equivalence_ratio < 0.668)
  //    Running = false;

  doEnginePower();
  if (IndicatedHorsePower < 0.1250) Running = false;

  doEGT();
  doCHT();
  doOilTemperature();
  doOilPressure();

  if (Thruster->GetType() == FGThruster::ttPropeller) {
    ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
    ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
  }

  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
  Thruster->Calculate(PowerAvailable);

  RunPostFunctions();
}
コード例 #7
0
ファイル: FGPiston.cpp プロジェクト: matthewzhenggong/jsbsim
void FGPiston::Calculate(void)
{
  // Input values.

  p_amb = in.Pressure * psftopa;
  double p = in.TotalPressure * psftopa;
  p_ram = (p - p_amb) * Ram_Air_Factor + p_amb;
  T_amb = RankineToKelvin(in.Temperature);

  RunPreFunctions();

  TotalDeltaT = ( in.TotalDeltaT < 1e-9 ) ? 1.0 : in.TotalDeltaT;

/* The thruster controls the engine RPM because it encapsulates the gear ratio and other transmission variables */
  RPM = Thruster->GetEngineRPM();

  MeanPistonSpeed_fps =  ( RPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS

  IAS = in.Vc;

  doEngineStartup();
  if (Boosted) doBoostControl();
  doMAP();
  doAirFlow();
  doFuelFlow();

  //Now that the fuel flow is done check if the mixture is too lean to run the engine
  //Assume lean limit at 22 AFR for now - thats a thi of 0.668
  //This might be a bit generous, but since there's currently no audiable warning of impending
  //cutout in the form of misfiring and/or rough running its probably reasonable for now.

  //  if (equivalence_ratio < 0.668)
  //    Running = false;

  doEnginePower();
  if (IndicatedHorsePower < 0.1250) Running = false;

  doEGT();
  doCHT();
  doOilTemperature();
  doOilPressure();

  if (Thruster->GetType() == FGThruster::ttPropeller) {
    ((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
    ((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
  }

  LoadThrusterInputs();
  Thruster->Calculate(HP * hptoftlbssec);

  RunPostFunctions();
}
コード例 #8
0
ファイル: FGInertial.cpp プロジェクト: 8W9aG/jsbsim
bool FGInertial::Run(void)
{
  // Fast return if we have nothing to do ...
  if (FGModel::Run()) return true;
  if (FDMExec->Holding()) return false;

  RunPreFunctions();

  // Gravitation accel
  double r = Propagate->GetRadius();
  gAccel = GetGAccel(r);
  earthPosAngle += FDMExec->GetDeltaT()*RotationRate;

  RunPostFunctions();

  return false;
}
コード例 #9
0
ファイル: FGElectric.cpp プロジェクト: agodemar/jsbsim
void FGElectric::Calculate(void)
{
  RunPreFunctions();

  if (Thruster->GetType() == FGThruster::ttPropeller) {
    ((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
    ((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
  } 

  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();

  HP = PowerWatts * in.ThrottlePos[EngineNumber] / hptowatts;
  
  LoadThrusterInputs();
  Thruster->Calculate(HP * hptoftlbssec);

  RunPostFunctions();
}
コード例 #10
0
bool FGBuoyantForces::Run(bool Holding)
{
  if (FGModel::Run(Holding)) return true;
  if (Holding) return false; // if paused don't execute
  if (NoneDefined) return true;

  RunPreFunctions();

  vTotalForces.InitMatrix();
  vTotalMoments.InitMatrix();

  for (unsigned int i=0; i<Cells.size(); i++) {
    Cells[i]->Calculate(FDMExec->GetDeltaT());
    vTotalForces  += Cells[i]->GetBodyForces();
    vTotalMoments += Cells[i]->GetMoments();
  }

  RunPostFunctions();

  return false;
}
コード例 #11
0
ファイル: FGAircraft.cpp プロジェクト: AEgisTG/jsbsim
bool FGAircraft::Run(bool Holding)
{
  if (FGModel::Run(Holding)) return true;
  if (Holding) return false;

  RunPreFunctions();

  vForces = in.AeroForce;
  vForces += in.PropForce;
  vForces += in.GroundForce;
  vForces += in.ExternalForce;
  vForces += in.BuoyantForce;

  vMoments = in.AeroMoment;
  vMoments += in.PropMoment;
  vMoments += in.GroundMoment;
  vMoments += in.ExternalMoment;
  vMoments += in.BuoyantMoment;

  RunPostFunctions();

  return false;
}
コード例 #12
0
ファイル: FGInput.cpp プロジェクト: andrewms/jsbsim
bool FGInput::Run(void)
{
  string line, token;
  size_t start=0, string_start=0, string_end=0;
  double value=0;
  FGPropertyManager* node=0;

  if (FGModel::Run()) return true; // fast exit if nothing to do
  if (port == 0) return false;      // Do nothing here if port not defined
                                    // return false if no error
  // This model DOES execute if "Exec->Holding"

  RunPreFunctions();

  data = socket->Receive(); // get socket transmission if present

  if (data.size() > 0) {
    // parse lines
    while (1) {
      string_start = data.find_first_not_of("\r\n", start);
      if (string_start == string::npos) break;
      string_end = data.find_first_of("\r\n", string_start);
      if (string_end == string::npos) break;
      line = data.substr(string_start, string_end-string_start);
      if (line.size() == 0) break;

      // now parse individual line
      vector <string> tokens = split(line,' ');
  
      string command="", argument="", str_value="";
      if (tokens.size() > 0) {
        command = to_lower(tokens[0]);
        if (tokens.size() > 1) {
          argument = trim(tokens[1]);
          if (tokens.size() > 2) {
            str_value = trim(tokens[2]);
          }
        }
      }

      if (command == "set") {                   // SET PROPERTY

        node = PropertyManager->GetNode(argument);
        if (node == 0)
          socket->Reply("Unknown property\n");
        else {
          value = atof(str_value.c_str());
          node->setDoubleValue(value);
        }
        socket->Reply("");

      } else if (command == "get") {             // GET PROPERTY

        if (argument.size() == 0) {
          socket->Reply("No property argument supplied.\n");
          break;
        }
        try {
          node = PropertyManager->GetNode(argument);
        } catch(...) {
          socket->Reply("Badly formed property query\n");
          break;
        }
        if (node == 0) {
          if (FDMExec->Holding()) { // if holding can query property list
            string query = FDMExec->QueryPropertyCatalog(argument);
            socket->Reply(query);
          } else {
            socket->Reply("Must be in HOLD to search properties\n");
          }
        } else if (node > 0) {
          ostringstream buf;
          buf << argument << " = " << setw(12) << setprecision(6) << node->getDoubleValue() << endl;
          socket->Reply(buf.str());
        }

      } else if (command == "hold") {                  // PAUSE

        FDMExec->Hold();
        socket->Reply("");

      } else if (command == "resume") {             // RESUME

        FDMExec->Resume();
        socket->Reply("");

      } else if (command == "quit") {                   // QUIT

        // close the socket connection
        socket->Reply("");
        socket->Close();

      } else if (command == "info") {                   // INFO

        // get info about the sim run and/or aircraft, etc.
        ostringstream info;
        info << "JSBSim version: " << JSBSim_version << endl;
        info << "Config File version: " << needed_cfg_version << endl;
        info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl;
        info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl;
        socket->Reply(info.str());

      } else if (command == "help") {                   // HELP

        socket->Reply(
        " JSBSim Server commands:\n\n"
        "   get {property name}\n"
        "   set {property name} {value}\n"
        "   hold\n"
        "   resume\n"
        "   help\n"
        "   quit\n"
        "   info\n\n");

      } else {
        socket->Reply(string("Unknown command: ") +  token + string("\n"));
      }

      start = string_end;
    }
  }

  RunPostFunctions();

  return false;
}
コード例 #13
0
ファイル: FGMassBalance.cpp プロジェクト: adrcad/jsbsim
bool FGMassBalance::Run(bool Holding)
{
  double denom, k1, k2, k3, k4, k5, k6;
  double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;

  if (FGModel::Run(Holding)) return true;
  if (Holding) return false;

  RunPreFunctions();

  double ChildFDMWeight = 0.0;
  for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
    if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
  }

  Weight = EmptyWeight + in.TanksWeight + GetTotalPointMassWeight()
    + in.GasMass*slugtolb + ChildFDMWeight;

  Mass = lbtoslug*Weight;

// Calculate new CG

  vXYZcg = (EmptyWeight*vbaseXYZcg
            + GetPointMassMoment()
            + in.TanksMoment
            + in.GasMoment) / Weight;

  // Track frame-by-frame delta CG, and move the EOM-tracked location
  // by this amount.
  if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg;
  vDeltaXYZcg = vXYZcg - vLastXYZcg;
  vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg);
  vLastXYZcg = vXYZcg;
  FDMExec->GetPropagate()->NudgeBodyLocation(vDeltaXYZcgBody);

// Calculate new total moments of inertia

  // At first it is the base configuration inertia matrix ...
  mJ = baseJ;
  // ... with the additional term originating from the parallel axis theorem.
  mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
  // Then add the contributions from the additional pointmasses.
  mJ += CalculatePMInertias();
  mJ += in.TankInertia;
  mJ += in.GasInertia;

  Ixx = mJ(1,1);
  Iyy = mJ(2,2);
  Izz = mJ(3,3);
  Ixy = -mJ(1,2);
  Ixz = -mJ(1,3);
  Iyz = -mJ(2,3);

// Calculate inertia matrix inverse (ref. Stevens and Lewis, "Flight Control & Simulation")

  k1 = (Iyy*Izz - Iyz*Iyz);
  k2 = (Iyz*Ixz + Ixy*Izz);
  k3 = (Ixy*Iyz + Iyy*Ixz);

  denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
  k1 = k1*denom;
  k2 = k2*denom;
  k3 = k3*denom;
  k4 = (Izz*Ixx - Ixz*Ixz)*denom;
  k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
  k6 = (Ixx*Iyy - Ixy*Ixy)*denom;

  mJinv.InitMatrix( k1, k2, k3,
                    k2, k4, k5,
                    k3, k5, k6 );

  RunPostFunctions();

  Debug(0);

  return false;
}
コード例 #14
0
ファイル: FGAerodynamics.cpp プロジェクト: adrcad/jsbsim
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;
}
コード例 #15
0
ファイル: FGTurbine.cpp プロジェクト: airware/jsbsim
void FGTurbine::Calculate(void)
{
  double thrust;

  RunPreFunctions();

  ThrottlePos = in.ThrottlePos[EngineNumber];

  if (ThrottlePos > 1.0) {
    AugmentCmd = ThrottlePos - 1.0;
    ThrottlePos -= AugmentCmd;
  } else {
    AugmentCmd = 0.0;
  }

  // When trimming is finished check if user wants engine OFF or RUNNING
  if ((phase == tpTrim) && (in.TotalDeltaT > 0)) {
    if (Running && !Starved) {
      phase = tpRun;
      N1_factor = MaxN1 - IdleN1;
      N2_factor = MaxN2 - IdleN2;      
      N2 = IdleN2 + ThrottlePos * N2_factor;
      N1 = IdleN1 + ThrottlePos * N1_factor;
      OilTemp_degK = 366.0;
      Cutoff = false;
    } else {
      phase = tpOff;
      Cutoff = true;
      EGT_degC = in.TAT_c;
    }
  }

  if (!Running && Cutoff && Starter) {
     if (phase == tpOff) phase = tpSpinUp;
  }

  // start
  if ((Starter == true) || (in.qbar > 30.0)) {
    if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart;
  }

  if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
  if (in.TotalDeltaT == 0) phase = tpTrim;
  if (Starved) phase = tpOff;
  if (Stalled) phase = tpStall;
  if (Seized) phase = tpSeize;

  switch (phase) {
    case tpOff:    thrust = Off(); break;
    case tpRun:    thrust = Run(); break;
    case tpSpinUp: thrust = SpinUp(); break;
    case tpStart:  thrust = Start(); break;
    case tpStall:  thrust = Stall(); break;
    case tpSeize:  thrust = Seize(); break;
    case tpTrim:   thrust = Trim(); break;
    default: thrust = Off();
  }

  Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)

  RunPostFunctions();
}
コード例 #16
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;
}
コード例 #17
0
ファイル: FGTurboProp.cpp プロジェクト: DolanP/jsbsim-dll
void FGTurboProp::Calculate(void)
{
  RunPreFunctions();

  TAT = in.TAT_c;

  ThrottlePos = in.ThrottlePos[EngineNumber];

/* The thruster controls the engine RPM because it encapsulates the gear ratio and other transmission variables */
  RPM = Thruster->GetEngineRPM();
  if (thrusterType == FGThruster::ttPropeller) {
    ((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
    ((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
    ((FGPropeller*)Thruster)->SetReverse(Reversed);
    if (Reversed) {
      ((FGPropeller*)Thruster)->SetReverseCoef(ThrottlePos);
    } else {
      ((FGPropeller*)Thruster)->SetReverseCoef(0.0);
    }

    if (Reversed) {
      if (ThrottlePos < BetaRangeThrottleEnd) {
          ThrottlePos = 0.0;  // idle when in Beta-range
      } else {
        // when reversed:
        ThrottlePos = (ThrottlePos-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
      }
    }
  }

  // When trimming is finished check if user wants engine OFF or RUNNING
  if ((phase == tpTrim) && (in.TotalDeltaT > 0)) {
    if (Running && !Starved) {
      phase = tpRun;
      N2 = IdleN2;
      N1 = IdleN1;
      OilTemp_degK = 366.0;
      Cutoff = false;
    } else {
      phase = tpOff;
      Cutoff = true;
      Eng_ITT_degC = TAT;
      Eng_Temperature = TAT;
      OilTemp_degK = TAT+273.15;
    }
  }

  if (!Running && Starter) {
    if (phase == tpOff) {
      phase = tpSpinUp;
      if (StartTime < 0) StartTime=0;
    }
  }
  if (!Running && !Cutoff && (N1 > 15.0)) {
    phase = tpStart;
    StartTime = -1;
  }
  if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
  if (in.TotalDeltaT == 0) phase = tpTrim;
  if (Starved) phase = tpOff;
  if (Condition >= 10) {
    phase = tpOff;
    StartTime=-1;
  }

  // limiter intervention wanted?
  if (Ielu_max_torque > 0.0) {
    double torque = 0.0;
    
    if (thrusterType == FGThruster::ttPropeller) {
      torque = ((FGPropeller*)(Thruster))->GetTorque();
    } else if (thrusterType == FGThruster::ttRotor) {
      torque = ((FGRotor*)(Thruster))->GetTorque();
    }

    if (Condition < 1) {
      if ( abs(torque) > Ielu_max_torque && ThrottlePos >= OldThrottle ) {
        ThrottlePos = OldThrottle - 0.1 * in.TotalDeltaT; //IELU down
        Ielu_intervent = true;
      } else if ( Ielu_intervent && ThrottlePos >= OldThrottle) {
        ThrottlePos = OldThrottle + 0.05 * in.TotalDeltaT; //IELU up
        Ielu_intervent = true;
      } else {
        Ielu_intervent = false;
      }
    } else {
      Ielu_intervent = false;
    }
    OldThrottle = ThrottlePos;
  }

  switch (phase) {
    case tpOff:    HP = Off(); break;
    case tpRun:    HP = Run(); break;
    case tpSpinUp: HP = SpinUp(); break;
    case tpStart:  HP = Start(); break;
    default: HP = 0;
  }
 
  LoadThrusterInputs();
  Thruster->Calculate(HP * hptoftlbssec);

  RunPostFunctions();
}