コード例 #1
0
ファイル: FGFCS.cpp プロジェクト: agodemar/jsbsim
void FGFCS::bindThrottle(unsigned int num)
{
  string tmp;

  tmp = CreateIndexedPropertyName("fcs/throttle-cmd-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottleCmd,
                                        &FGFCS::SetThrottleCmd);
  tmp = CreateIndexedPropertyName("fcs/throttle-pos-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottlePos,
                                        &FGFCS::SetThrottlePos);
  tmp = CreateIndexedPropertyName("fcs/mixture-cmd-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixtureCmd,
                                        &FGFCS::SetMixtureCmd);
  tmp = CreateIndexedPropertyName("fcs/mixture-pos-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixturePos,
                                        &FGFCS::SetMixturePos);
  tmp = CreateIndexedPropertyName("fcs/advance-cmd-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvanceCmd,
                                        &FGFCS::SetPropAdvanceCmd);
  tmp = CreateIndexedPropertyName("fcs/advance-pos-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvance,
                                        &FGFCS::SetPropAdvance);
  tmp = CreateIndexedPropertyName("fcs/feather-cmd-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetFeatherCmd,
                                        &FGFCS::SetFeatherCmd);
  tmp = CreateIndexedPropertyName("fcs/feather-pos-norm", num);
  PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropFeather,
                                        &FGFCS::SetPropFeather);
}
コード例 #2
0
ファイル: FGMassBalance.cpp プロジェクト: adrcad/jsbsim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// This function binds properties for each pointmass object created.
//
void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) {
  string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num);
  PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight,
                                       &PointMass::SetPointMassWeight);

  tmp = CreateIndexedPropertyName("inertia/pointmass-location-X-inches", num);
  PropertyManager->Tie( tmp.c_str(), this, eX, &PointMass::GetPointMassLocation,
                                           &PointMass::SetPointMassLocation);
  tmp = CreateIndexedPropertyName("inertia/pointmass-location-Y-inches", num);
  PropertyManager->Tie( tmp.c_str(), this, eY, &PointMass::GetPointMassLocation,
                                           &PointMass::SetPointMassLocation);
  tmp = CreateIndexedPropertyName("inertia/pointmass-location-Z-inches", num);
  PropertyManager->Tie( tmp.c_str(), this, eZ, &PointMass::GetPointMassLocation,
                                           &PointMass::SetPointMassLocation);
}
コード例 #3
0
ファイル: FGFDMExec.cpp プロジェクト: deutschlion/JSBSim.js
void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
{
  struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure;
  int node_idx = 0;

  for (int i=0; i<pcs->node->nChildren(); i++) {
    string access="";
    pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
    node_idx = pcs->node->getChild(i)->getIndex();
    if (node_idx != 0) {
      pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx);
    }
    if (pcs->node->getChild(i)->nChildren() == 0) {
      if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) {
        pcsNew->base_string = pcsNew->base_string.erase(0,12);
      }
      if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::READ)) access="R";
      if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::WRITE)) access+="W";
      PropertyCatalog.push_back(pcsNew->base_string+" ("+access+")");
    } else {
      pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i);
      BuildPropertyCatalog(pcsNew);
    }
  }
  delete pcsNew;
}
コード例 #4
0
ファイル: FGRocket.cpp プロジェクト: adrcad/jsbsim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This function should tie properties to rocket engine specific properties
// that are not bound in the base class (FGEngine) code.
//
void FGRocket::bindmodel()
{
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);

  property_name = base_property_name + "/total-impulse";
  PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse);
  property_name = base_property_name + "/vacuum-thrust_lbs";
  PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust);

  if (ThrustTable) { // Solid rocket motor
    property_name = base_property_name + "/thrust-variation_pct";
    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetThrustVariation,
                                                       &FGRocket::SetThrustVariation);
    property_name = base_property_name + "/total-isp-variation_pct";
    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalIspVariation,
                                                       &FGRocket::SetTotalIspVariation);
  } else { // Liquid rocket motor
    property_name = base_property_name + "/oxi-flow-rate-pps";
    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate);
    property_name = base_property_name + "/mixture-ratio";
    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetMixtureRatio,
                                                       &FGRocket::SetMixtureRatio);
    property_name = base_property_name + "/isp";
    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetIsp,
                                                       &FGRocket::SetIsp);
  }
}
コード例 #5
0
ファイル: FGRocket.cpp プロジェクト: Aero348/Matlab-Cularis
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This funciton should tie properties to rocket engine specific properties
// that are not bound in the base class (FGEngine) code.
//
void FGRocket::bindmodel()
{
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);

  property_name = base_property_name + "/total-impulse";
  PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse);
  property_name = base_property_name + "/oxi-flow-rate-pps";
  PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate);
  property_name = base_property_name + "/vacuum-thrust_lbs";
  PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust);
}
コード例 #6
0
ファイル: FGElectric.cpp プロジェクト: agodemar/jsbsim
FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number, struct FGEngine::Inputs& input)
  : FGEngine(engine_number, input)
{
  Load(exec,el);

  Type = etElectric;
  PowerWatts = 745.7;
  hptowatts = 745.7;

  if (el->FindElement("power"))
    PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS");

  string base_property_name = CreateIndexedPropertyName("propulsion/engine",
                                                        EngineNumber);
  exec->GetPropertyManager()->Tie(base_property_name + "/power-hp", &HP);

  Debug(0); // Call Debug() routine from constructor if needed
}
コード例 #7
0
ファイル: FGRotor.cpp プロジェクト: 8W9aG/jsbsim
bool FGRotor::bind(void) {

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);

  PropertyManager->Tie( base_property_name + "/rotor-rpm", this, &FGRotor::GetRPM );
  PropertyManager->Tie( base_property_name + "/thrust-mr-lbs", &mr.Thrust );
  PropertyManager->Tie( base_property_name + "/vi-mr-fps", &mr.v_induced );
  PropertyManager->Tie( base_property_name + "/a0-mr-rad", &mr.a0 );
  PropertyManager->Tie( base_property_name + "/a1-mr-rad", &mr.a1s ); // s means shaft axes
  PropertyManager->Tie( base_property_name + "/b1-mr-rad", &mr.b1s );
  PropertyManager->Tie( base_property_name + "/thrust-tr-lbs", &tr.Thrust );
  PropertyManager->Tie( base_property_name + "/vi-tr-fps", &tr.v_induced );

  // lambda
  PropertyManager->Tie( base_property_name + "/inflow-ratio", &prop_inflow_ratio_lambda );
  // mu
  PropertyManager->Tie( base_property_name + "/advance-ratio", &prop_advance_ratio_mu );
  // nu
  PropertyManager->Tie( base_property_name + "/induced-inflow-ratio", &prop_inflow_ratio_induced_nu );

  PropertyManager->Tie( base_property_name + "/torque-mr-lbsft", &prop_mr_torque );
  PropertyManager->Tie( base_property_name + "/thrust-coefficient", &prop_thrust_coefficient );
  PropertyManager->Tie( base_property_name + "/main-rotor-rpm", &mr.ActualRPM );
  PropertyManager->Tie( base_property_name + "/tail-rotor-rpm", &tr.ActualRPM );

  // position of the downwash
  PropertyManager->Tie( base_property_name + "/theta-downwash-rad", &prop_theta_downwash );
  PropertyManager->Tie( base_property_name + "/phi-downwash-rad", &prop_phi_downwash );  

  // nodes to use via get<xyz>Value
  prop_collective_ctrl = PropertyManager->GetNode(base_property_name + "/collective-ctrl-rad",true);
  prop_lateral_ctrl = PropertyManager->GetNode(base_property_name + "/lateral-ctrl-rad",true);
  prop_longitudinal_ctrl = PropertyManager->GetNode(base_property_name + "/longitudinal-ctrl-rad",true);
  prop_antitorque_ctrl =   PropertyManager->GetNode(base_property_name + "/antitorque-ctrl-rad",true);

  prop_rotorbrake =   PropertyManager->GetNode(base_property_name + "/rotorbrake-hp", true);
  prop_freewheel_factor =   PropertyManager->GetNode(base_property_name + "/freewheel-factor", true);

  PropertyManager->Tie( base_property_name + "/dump-flag", &prop_DumpFlag );

  return true;
}
コード例 #8
0
bool FGTransmission::BindModel(int num)
{
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", num);

  property_name = base_property_name + "/brake-ctrl-norm";
  PropertyManager->Tie( property_name.c_str(), this, 
      &FGTransmission::GetBrakeCtrlNorm, &FGTransmission::SetBrakeCtrlNorm);

  property_name = base_property_name + "/clutch-ctrl-norm";
  PropertyManager->Tie( property_name.c_str(), this, 
      &FGTransmission::GetClutchCtrlNorm, &FGTransmission::SetClutchCtrlNorm);

  property_name = base_property_name + "/free-wheel-transmission";
  PropertyManager->Tie( property_name.c_str(), this, 
      &FGTransmission::GetFreeWheelTransmission);

  return true;
}
コード例 #9
0
ファイル: FGTurboProp.cpp プロジェクト: DolanP/jsbsim-dll
void FGTurboProp::bindmodel()
{
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
  property_name = base_property_name + "/n1";
  PropertyManager->Tie( property_name.c_str(), &N1);
  // property_name = base_property_name + "/n2";
  // PropertyManager->Tie( property_name.c_str(), &N2);
  property_name = base_property_name + "/reverser";
  PropertyManager->Tie( property_name.c_str(), &Reversed);
  property_name = base_property_name + "/power-hp";
  PropertyManager->Tie( property_name.c_str(), &HP);
  property_name = base_property_name + "/itt-c";
  PropertyManager->Tie( property_name.c_str(), &Eng_ITT_degC);
  property_name = base_property_name + "/engtemp-c";
  PropertyManager->Tie( property_name.c_str(), &Eng_Temperature);
  property_name = base_property_name + "/ielu_intervent";
  PropertyManager->Tie( property_name.c_str(), &Ielu_intervent);
  property_name = base_property_name + "/combustion_efficiency";
  PropertyManager->Tie( property_name.c_str(), &CombustionEfficiency);
}
コード例 #10
0
ファイル: FGFDMExec.cpp プロジェクト: matthewzhenggong/jsbsim
bool FGFDMExec::SetOutputDirectives(const string& fname)
{
  bool result;

  FGOutput* Output = new FGOutput(this);
  Output->SetDirectivesFile(RootDir + fname);
  Output->InitModel();
  Schedule(Output);
  result = Output->Load(0);

  if (result) {
    Output->Run(holding);
    Outputs.push_back(Output);
    typedef double (FGOutput::*iOPMF)(void) const;
    string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1);
    instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
  }
  else
    delete Output;

  return result;
}
コード例 #11
0
ファイル: FGFDMExec.cpp プロジェクト: matthewzhenggong/jsbsim
void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
{
  struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure;
  int node_idx = 0;

  for (int i=0; i<pcs->node->nChildren(); i++) {
    pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
    node_idx = pcs->node->getChild(i)->getIndex();
    if (node_idx != 0) {
      pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx);
    }
    if (pcs->node->getChild(i)->nChildren() == 0) {
      if (pcsNew->base_string.substr(0,11) == string("/fdm/jsbsim")) {
        pcsNew->base_string = pcsNew->base_string.erase(0,12);
      }
      PropertyCatalog.push_back(pcsNew->base_string);
    } else {
      pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
      BuildPropertyCatalog(pcsNew);
    }
  }
  delete pcsNew;
}
コード例 #12
0
ファイル: FGTank.cpp プロジェクト: MCBama/jsbsim
void FGTank::bind(FGPropertyManager* PropertyManager)
{
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
  property_name = base_property_name + "/contents-lbs";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
                                       &FGTank::SetContents );
  property_name = base_property_name + "/pct-full";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);

  property_name = base_property_name + "/priority";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
                                       &FGTank::SetPriority );
  property_name = base_property_name + "/external-flow-rate-pps";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
                                       &FGTank::SetExternalFlow );
  property_name = base_property_name + "/local-ixx-slug_ft2";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIxx);
  property_name = base_property_name + "/local-iyy-slug_ft2";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIyy);
  property_name = base_property_name + "/local-izz-slug_ft2";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIzz);
}
コード例 #13
0
ファイル: FGTurbine.cpp プロジェクト: airware/jsbsim
void FGTurbine::bindmodel(FGPropertyManager* PropertyManager)
{
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
  property_name = base_property_name + "/n1";
  PropertyManager->Tie( property_name.c_str(), &N1);
  property_name = base_property_name + "/n2";
  PropertyManager->Tie( property_name.c_str(), &N2);
  property_name = base_property_name + "/injection_cmd";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, 
                        &FGTurbine::GetInjection, &FGTurbine::SetInjection);
  property_name = base_property_name + "/seized";
  PropertyManager->Tie( property_name.c_str(), &Seized);
  property_name = base_property_name + "/stalled";
  PropertyManager->Tie( property_name.c_str(), &Stalled);
  property_name = base_property_name + "/bleed-factor";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, &FGTurbine::GetBleedDemand, &FGTurbine::SetBleedDemand);
  property_name = base_property_name + "/MaxN1";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
                        &FGTurbine::GetMaxN1, &FGTurbine::SetMaxN1);
  property_name = base_property_name + "/MaxN2";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
                        &FGTurbine::GetMaxN2, &FGTurbine::SetMaxN2);
  property_name = base_property_name + "/InjectionTimer";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
                        &FGTurbine::GetInjectionTimer, &FGTurbine::SetInjectionTimer);
  property_name = base_property_name + "/InjWaterNorm";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
                        &FGTurbine::GetInjWaterNorm, &FGTurbine::SetInjWaterNorm);
  property_name = base_property_name + "/InjN1increment";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
                        &FGTurbine::GetInjN1increment, &FGTurbine::SetInjN1increment);
  property_name = base_property_name + "/InjN2increment";
  PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
                        &FGTurbine::GetInjN2increment, &FGTurbine::SetInjN2increment);
}
コード例 #14
0
ファイル: FGGasCell.cpp プロジェクト: MCBama/jsbsim
FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num,
                       FGGasCell* parent, const struct FGGasCell::Inputs& input)
  : in(input)
{
  string token;
  Element* element;

  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
  MassBalance = exec->GetMassBalance();

  ballonetJ = FGMatrix33();

  MaxVolume = MaxOverpressure = Temperature = Pressure =
    Contents = Volume = dVolumeIdeal = dU = 0.0;
  Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0;
  ValveCoefficient = ValveOpen = 0.0;
  BlowerInput = NULL;
  CellNum = num;
  Parent = parent;

  // NOTE: In the local system X points north, Y points east and Z points down.
  element = el->FindElement("location");
  if (element) {
    vXYZ = element->FindElementTripletConvertTo("IN");
  } else {
      std::stringstream error;
    error << "Fatal Error: No location found for this ballonet." << endl;
    throw std::runtime_error(error.str());
  }
  if ((el->FindElement("x_radius") || el->FindElement("x_width")) &&
      (el->FindElement("y_radius") || el->FindElement("y_width")) &&
      (el->FindElement("z_radius") || el->FindElement("z_width"))) {

    if (el->FindElement("x_radius")) {
      Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT");
    }
    if (el->FindElement("y_radius")) {
      Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT");
    }
    if (el->FindElement("z_radius")) {
      Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT");
    }

    if (el->FindElement("x_width")) {
      Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT");
    }
    if (el->FindElement("y_width")) {
      Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT");
    }
    if (el->FindElement("z_width")) {
      Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT");
    }

    // The volume is a (potentially) extruded ellipsoid.
    // FIXME: However, currently only a few combinations of radius and
    //        width are fully supported.
    if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
        (Xwidth  == 0.0) && (Ywidth  == 0.0) && (Zwidth  == 0.0)) {
      // Ellipsoid volume.
      MaxVolume = 4.0  * M_PI * Xradius * Yradius * Zradius / 3.0;
    } else if  ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
                (Xwidth  != 0.0) && (Ywidth  == 0.0) && (Zwidth  == 0.0)) {
      // Cylindrical volume.
      MaxVolume = M_PI * Yradius * Zradius * Xwidth;
    } else {
      cerr << "Warning: Unsupported ballonet shape." << endl;
      MaxVolume = 
        (4.0  * M_PI * Xradius * Yradius * Zradius / 3.0 +
         M_PI * Yradius * Zradius * Xwidth +
         M_PI * Xradius * Zradius * Ywidth +
         M_PI * Xradius * Yradius * Zwidth +
         2.0  * Xradius * Ywidth * Zwidth +
         2.0  * Yradius * Xwidth * Zwidth +
         2.0  * Zradius * Xwidth * Ywidth +
         Xwidth * Ywidth * Zwidth);
    }
  } else {
      std::stringstream error;
    error << "Fatal Error: Ballonet shape must be given." << endl;
    throw std::runtime_error(error.str());
  }
  if (el->FindElement("max_overpressure")) {
    MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure",
                                                            "LBS/FT2");
  }
  if (el->FindElement("fullness")) {
    const double Fullness = el->FindElementValueAsNumber("fullness");
    if (0 <= Fullness) { 
      Volume = Fullness * MaxVolume; 
    } else {
      cerr << "Warning: Invalid initial ballonet fullness value." << endl;
    }
  }  
  if (el->FindElement("valve_coefficient")) {
    ValveCoefficient =
      el->FindElementValueAsNumberConvertTo("valve_coefficient",
                                            "FT4*SEC/SLUG");
    ValveCoefficient = max(ValveCoefficient, 0.0);
  }

  // Initialize state
  if (Temperature == 0.0) {
    Temperature = Parent->GetTemperature();
  }
  if (Pressure == 0.0) {
    Pressure = Parent->GetPressure();
  }
  if (Volume != 0.0) {
    // Calculate initial air content.
    Contents = Pressure * Volume / (R * Temperature);
    
    // Clip to max allowed value.
    const double IdealPressure = Contents * R * Temperature / MaxVolume;
    if (IdealPressure > Pressure + MaxOverpressure) {
      Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature);
      Pressure = Pressure + MaxOverpressure;
    } else {
      Pressure = max(IdealPressure, Pressure);
    }
  } else {
    // Calculate initial air content.
    Contents = Pressure * MaxVolume / (R * Temperature);
  }

  Volume = Contents * R * Temperature / Pressure;

  // Bind relevant properties
  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", Parent->GetIndex());
  base_property_name = CreateIndexedPropertyName(base_property_name + "/ballonet", CellNum);

  property_name = base_property_name + "/max_volume-ft3";
  PropertyManager->Tie( property_name, &MaxVolume, false );
  PropertyManager->GetNode()->SetWritable( property_name, false );

  property_name = base_property_name + "/temp-R";
  PropertyManager->Tie( property_name, &Temperature, false );

  property_name = base_property_name + "/pressure-psf";
  PropertyManager->Tie( property_name, &Pressure, false );

  property_name = base_property_name + "/volume-ft3";
  PropertyManager->Tie( property_name, &Volume, false );

  property_name = base_property_name + "/contents-mol";
  PropertyManager->Tie( property_name, &Contents, false );

  property_name = base_property_name + "/valve_open";
  PropertyManager->Tie( property_name, &ValveOpen, false );

  Debug(0);

  // Read heat transfer coefficients
  if (Element* heat = el->FindElement("heat")) {
    Element* function_element = heat->FindElement("function");
    while (function_element) {
      HeatTransferCoeff.push_back(new FGFunction(PropertyManager,
                                                 function_element));
      function_element = heat->FindNextElement("function");
    }
  }
  // Read blower input function
  if (Element* blower = el->FindElement("blower_input")) {
    Element* function_element = blower->FindElement("function");
    BlowerInput = new FGFunction(PropertyManager,
                                 function_element);
  }
}
コード例 #15
0
ファイル: FGFDMExec.cpp プロジェクト: matthewzhenggong/jsbsim
bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
{
  string token;
  string aircraftCfgFileName;
  Element* element = 0L;
  bool result = false; // initialize result to false, indicating input file not yet read

  modelName = model; // Set the class modelName attribute

  if( AircraftPath.empty() || EnginePath.empty() || SystemsPath.empty()) {
    cerr << "Error: attempted to load aircraft with undefined ";
    cerr << "aircraft, engine, and system paths" << endl;
    return false;
  }

  FullAircraftPath = AircraftPath;
  if (addModelToPath) FullAircraftPath += "/" + model;
  aircraftCfgFileName = FullAircraftPath + "/" + model + ".xml";

  if (modelLoaded) {
    DeAllocate();
    Allocate();
  }

  int saved_debug_lvl = debug_lvl;

  document = LoadXMLDocument(aircraftCfgFileName); // "document" is a class member
  if (document) {
    if (IsChild) debug_lvl = 0;

    ReadPrologue(document);

    if (IsChild) debug_lvl = saved_debug_lvl;

    // Process the fileheader element in the aircraft config file. This element is OPTIONAL.
    element = document->FindElement("fileheader");
    if (element) {
      result = ReadFileHeader(element);
      if (!result) {
        cerr << endl << "Aircraft fileheader element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    if (IsChild) debug_lvl = 0;

    // Process the metrics element. This element is REQUIRED.
    element = document->FindElement("metrics");
    if (element) {
      result = ((FGAircraft*)Models[eAircraft])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft metrics element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    } else {
      cerr << endl << "No metrics element was found in the aircraft config file." << endl;
      return false;
    }

    // Process the mass_balance element. This element is REQUIRED.
    element = document->FindElement("mass_balance");
    if (element) {
      result = ((FGMassBalance*)Models[eMassBalance])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft mass_balance element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    } else {
      cerr << endl << "No mass_balance element was found in the aircraft config file." << endl;
      return false;
    }

    // Process the ground_reactions element. This element is REQUIRED.
    element = document->FindElement("ground_reactions");
    if (element) {
      result = ((FGGroundReactions*)Models[eGroundReactions])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft ground_reactions element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
      ((FGFCS*)Models[eSystems])->AddGear(((FGGroundReactions*)Models[eGroundReactions])->GetNumGearUnits());
    } else {
      cerr << endl << "No ground_reactions element was found in the aircraft config file." << endl;
      return false;
    }

    // Process the external_reactions element. This element is OPTIONAL.
    element = document->FindElement("external_reactions");
    if (element) {
      result = ((FGExternalReactions*)Models[eExternalReactions])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft external_reactions element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    // Process the buoyant_forces element. This element is OPTIONAL.
    element = document->FindElement("buoyant_forces");
    if (element) {
      result = ((FGBuoyantForces*)Models[eBuoyantForces])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft buoyant_forces element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    // Process the propulsion element. This element is OPTIONAL.
    element = document->FindElement("propulsion");
    if (element) {
      result = ((FGPropulsion*)Models[ePropulsion])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft propulsion element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
      for (unsigned int i=0; i<((FGPropulsion*)Models[ePropulsion])->GetNumEngines(); i++)
        ((FGFCS*)Models[eSystems])->AddThrottle();
    }

    // Process the system element[s]. This element is OPTIONAL, and there may be more than one.
    element = document->FindElement("system");
    while (element) {
      result = ((FGFCS*)Models[eSystems])->Load(element, FGFCS::stSystem);
      if (!result) {
        cerr << endl << "Aircraft system element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
      element = document->FindNextElement("system");
    }

    // Process the autopilot element. This element is OPTIONAL.
    element = document->FindElement("autopilot");
    if (element) {
      result = ((FGFCS*)Models[eSystems])->Load(element, FGFCS::stAutoPilot);
      if (!result) {
        cerr << endl << "Aircraft autopilot element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    // Process the flight_control element. This element is OPTIONAL.
    element = document->FindElement("flight_control");
    if (element) {
      result = ((FGFCS*)Models[eSystems])->Load(element, FGFCS::stFCS);
      if (!result) {
        cerr << endl << "Aircraft flight_control element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    // Process the aerodynamics element. This element is OPTIONAL, but almost always expected.
    element = document->FindElement("aerodynamics");
    if (element) {
      result = ((FGAerodynamics*)Models[eAerodynamics])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft aerodynamics element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    } else {
      cerr << endl << "No expected aerodynamics element was found in the aircraft config file." << endl;
    }

    // Process the input element. This element is OPTIONAL.
    element = document->FindElement("input");
    if (element) {
      result = ((FGInput*)Models[eInput])->Load(element);
      if (!result) {
        cerr << endl << "Aircraft input element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    // Process the output element[s]. This element is OPTIONAL, and there may be more than one.
    unsigned int idx=0;
    typedef double (FGOutput::*iOPMF)(void) const;
    typedef int (FGFDMExec::*iOPV)(void) const;
    element = document->FindElement("output");
    while (element) {
      if (debug_lvl > 0) cout << endl << "  Output data set: " << idx << "  ";
      FGOutput* Output = new FGOutput(this);
      Output->InitModel();
      Schedule(Output);
      result = Output->Load(element);
      if (!result) {
        cerr << endl << "Aircraft output element has problems in file " << aircraftCfgFileName << endl;
        return result;
      } else {
        Outputs.push_back(Output);
        string outputProp = CreateIndexedPropertyName("simulation/output",idx);
        instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
        instance->Tie("simulation/force-output", this, (iOPV)0, &FGFDMExec::ForceOutput, false);
        idx++;
      }
      element = document->FindNextElement("output");
    }

    // Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED.
    element = document->FindElement("child");
    if (element) {
      result = ReadChild(element);
      if (!result) {
        cerr << endl << "Aircraft child element has problems in file " << aircraftCfgFileName << endl;
        return result;
      }
    }

    // Since all vehicle characteristics have been loaded, place the values in the Inputs
    // structure for the FGModel-derived classes.
    LoadModelConstants();

    modelLoaded = true;

    if (debug_lvl > 0) {
      LoadInputs(eMassBalance); // Update all input mass properties for the report.
      Models[eMassBalance]->Run(false);  // Update all mass properties for the report.
      ((FGMassBalance*)Models[eMassBalance])->GetMassPropertiesReport();

      cout << endl << fgblue << highint
           << "End of vehicle configuration loading." << endl
           << "-------------------------------------------------------------------------------"
           << reset << endl;
    }

    if (IsChild) debug_lvl = saved_debug_lvl;

  } else {
    cerr << fgred
         << "  JSBSim failed to open the configuration file: " << aircraftCfgFileName
         << fgdef << endl;
  }

  for (unsigned int i=0; i< Models.size(); i++) LoadInputs(i);

  if (result) {
    struct PropertyCatalogStructure masterPCS;
    masterPCS.base_string = "";
    masterPCS.node = (FGPropertyManager*)Root;
    BuildPropertyCatalog(&masterPCS);
  }

  return result;
}
コード例 #16
0
ファイル: FGTurbine.cpp プロジェクト: airware/jsbsim
bool FGTurbine::Load(FGFDMExec* exec, Element *el)
{
  Element* function_element = el->FindElement("function");

  while(function_element) {
    string name = function_element->GetAttributeValue("name");
    if (name == "IdleThrust" || name == "MilThrust" || name == "AugThrust" || name == "Injection")
      function_element->SetAttributeValue("name", string("propulsion/engine[#]/") + name);

    function_element = el->FindNextElement("function");
  }

  FGEngine::Load(exec, el);

  ResetToIC();

  if (el->FindElement("milthrust"))
    MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS");
  if (el->FindElement("maxthrust"))
    MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS");
  if (el->FindElement("bypassratio"))
    BypassRatio = el->FindElementValueAsNumber("bypassratio");
  if (el->FindElement("bleed"))
    BleedDemand = el->FindElementValueAsNumber("bleed");
  if (el->FindElement("tsfc"))
    TSFC = el->FindElementValueAsNumber("tsfc");
  if (el->FindElement("atsfc"))
    ATSFC = el->FindElementValueAsNumber("atsfc");
  if (el->FindElement("idlen1"))
    IdleN1 = el->FindElementValueAsNumber("idlen1");
  if (el->FindElement("idlen2"))
    IdleN2 = el->FindElementValueAsNumber("idlen2");
  if (el->FindElement("maxn1"))
    MaxN1 = el->FindElementValueAsNumber("maxn1");
  if (el->FindElement("maxn2"))
    MaxN2 = el->FindElementValueAsNumber("maxn2");
  if (el->FindElement("n1spinup"))
    N1_spinup = el->FindElementValueAsNumber("n1spinup");
  if (el->FindElement("n2spinup"))
    N2_spinup = el->FindElementValueAsNumber("n2spinup");
  if (el->FindElement("augmented"))
    Augmented = (int)el->FindElementValueAsNumber("augmented");
  if (el->FindElement("augmethod"))
    AugMethod = (int)el->FindElementValueAsNumber("augmethod");
  if (el->FindElement("injected"))
    Injected = (int)el->FindElementValueAsNumber("injected");
  if (el->FindElement("injection-time")){
    InjectionTime = el->FindElementValueAsNumber("injection-time");
    InjWaterNorm =1.0;
  }
  if (el->FindElement("injection-N1-inc"))
    InjN1increment = el->FindElementValueAsNumber("injection-N1-inc");
  if (el->FindElement("injection-N2-inc"))
    InjN2increment = el->FindElementValueAsNumber("injection-N2-inc");

  string property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber);

  IdleThrustLookup = GetPreFunction(property_prefix+"/IdleThrust");
  MilThrustLookup = GetPreFunction(property_prefix+"/MilThrust");
  MaxThrustLookup = GetPreFunction(property_prefix+"/AugThrust");
  InjectionLookup = GetPreFunction(property_prefix+"/Injection");

  // Pre-calculations and initializations

  delay = 90.0 / (BypassRatio + 3.0);
  N1_factor = MaxN1 - IdleN1;
  N2_factor = MaxN2 - IdleN2;
  OilTemp_degK = in.TAT_c + 273.0;
  IdleFF = pow(MilThrust, 0.2) * 107.0;  // just an estimate

  bindmodel(exec->GetPropertyManager());
  return true;
}
コード例 #17
0
FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
                       : FGThruster(exec, prop_element, num)
{
  string token;
  Element *table_element, *local_element;
  string name="";
  FGPropertyManager* PropertyManager = exec->GetPropertyManager();

  MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0;
  Sense = 1; // default clockwise rotation
  ReversePitch = 0.0;
  Reversed = false;
  Feathered = false;
  Reverse_coef = 0.0;
  GearRatio = 1.0;
  CtFactor = CpFactor = 1.0;

  if (prop_element->FindElement("ixx"))
    Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
  if (prop_element->FindElement("diameter"))
    Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT");
  if (prop_element->FindElement("numblades"))
    numBlades = (int)prop_element->FindElementValueAsNumber("numblades");
  if (prop_element->FindElement("gearratio"))
    GearRatio = prop_element->FindElementValueAsNumber("gearratio");
  if (prop_element->FindElement("minpitch"))
    MinPitch = prop_element->FindElementValueAsNumber("minpitch");
  if (prop_element->FindElement("maxpitch"))
    MaxPitch = prop_element->FindElementValueAsNumber("maxpitch");
  if (prop_element->FindElement("minrpm"))
    MinRPM = prop_element->FindElementValueAsNumber("minrpm");
  if (prop_element->FindElement("maxrpm"))
    MaxRPM = prop_element->FindElementValueAsNumber("maxrpm");
  if (prop_element->FindElement("reversepitch"))
    ReversePitch = prop_element->FindElementValueAsNumber("reversepitch");
  for (int i=0; i<2; i++) {
    table_element = prop_element->FindNextElement("table");
    name = table_element->GetAttributeValue("name");
    if (name == "C_THRUST") {
      cThrust = new FGTable(PropertyManager, table_element);
    } else if (name == "C_POWER") {
      cPower = new FGTable(PropertyManager, table_element);
    } else {
      cerr << "Unknown table type: " << name << " in propeller definition." << endl;
    }
  }

  local_element = prop_element->GetParent()->FindElement("sense");
  if (local_element) {
    double Sense = local_element->GetDataAsNumber();
    SetSense(fabs(Sense)/Sense);
  }
  local_element = prop_element->GetParent()->FindElement("p_factor");
  if (local_element) {
    P_Factor = local_element->GetDataAsNumber();
  }
  if (P_Factor < 0) {
    cerr << "P-Factor value in config file must be greater than zero" << endl;
  }
  if (prop_element->FindElement("ct_factor"))
    SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") );
  if (prop_element->FindElement("cp_factor"))
    SetCpFactor( prop_element->FindElementValueAsNumber("cp_factor") );

  Type = ttPropeller;
  RPM = 0;
  vTorque.InitMatrix();
  D4 = Diameter*Diameter*Diameter*Diameter;
  D5 = D4*Diameter;

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);
  property_name = base_property_name + "/advance-ratio";
  PropertyManager->Tie( property_name.c_str(), &J );
  property_name = base_property_name + "/blade-angle";
  PropertyManager->Tie( property_name.c_str(), &Pitch );
  property_name = base_property_name + "/thrust-coefficient";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetThrustCoefficient );
  property_name = base_property_name + "/propeller-rpm";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetRPM );

  Debug(0);
}
コード例 #18
0
ファイル: FGPiston.cpp プロジェクト: matthewzhenggong/jsbsim
FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Inputs& input)
  : FGEngine(exec, el, engine_number, input),
  R_air(287.3),                  // Gas constant for air J/Kg/K
  rho_fuel(800),                 // estimate
  calorific_value_fuel(47.3e6),  // J/Kg
  Cp_air(1005),                  // Specific heat (constant pressure) J/Kg/K
  Cp_fuel(1700),
  standard_pressure(101320.73)
{
  Element *table_element;
  string token;
  string name="";

  // Defaults and initializations

  Type = etPiston;

  // These items are read from the configuration file
  // Defaults are from a Lycoming O-360, more or less

  Cycles = 4;
  IdleRPM = 600;
  MaxRPM = 2800;
  Displacement = 360;
  SparkFailDrop = 1.0;
  MaxHP = 200;
  MinManifoldPressure_inHg = 6.5;
  MaxManifoldPressure_inHg = 28.5;
  ManifoldPressureLag=1.0;
  ISFC = -1;
  volumetric_efficiency = 0.85;
  Bore = 5.125;
  Stroke = 4.375;
  Cylinders = 4;
  CylinderHeadMass = 2; //kg
  CompressionRatio = 8.5;
  Z_airbox = -999;
  Ram_Air_Factor = 1;
  PeakMeanPistonSpeed_fps = 100;
  FMEPDynamic= 18400;
  FMEPStatic = 46500;
  Cooling_Factor = 0.5144444;
  StaticFriction_HP = 1.5;
  StarterGain = 1.;
  StarterTorque = -1.;
  StarterRPM = -1.;

  // These are internal program variables

  Lookup_Combustion_Efficiency = 0;
  Mixture_Efficiency_Correlation = 0;
  crank_counter = 0;
  Magnetos = 0;
  minMAP = 21950;
  maxMAP = 96250;

  ResetToIC();

  // Supercharging
  BoostSpeeds = 0;  // Default to no supercharging
  BoostSpeed = 0;
  Boosted = false;
  BoostOverride = 0;
  BoostManual = 0;
  bBoostOverride = false;
  bTakeoffBoost = false;
  TakeoffBoost = 0.0;   // Default to no extra takeoff-boost
  int i;
  for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) {
    RatedBoost[i] = 0.0;
    RatedPower[i] = 0.0;
    RatedAltitude[i] = 0.0;
    BoostMul[i] = 1.0;
    RatedMAP[i] = 100000;
    RatedRPM[i] = 2500;
    TakeoffMAP[i] = 100000;
  }
  for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) {
    BoostSwitchAltitude[i] = 0.0;
    BoostSwitchPressure[i] = 0.0;
  }

  // Read inputs from engine data file where present.

  if (el->FindElement("minmp")) 
    MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG");
  if (el->FindElement("maxmp"))
    MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG");
  if (el->FindElement("man-press-lag"))
    ManifoldPressureLag = el->FindElementValueAsNumber("man-press-lag");
  if (el->FindElement("displacement"))
    Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3");
  if (el->FindElement("maxhp"))
    MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP");
  if (el->FindElement("static-friction"))
    StaticFriction_HP = el->FindElementValueAsNumberConvertTo("static-friction","HP");
  if (el->FindElement("sparkfaildrop"))
    SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1);
  if (el->FindElement("cycles"))
    Cycles = el->FindElementValueAsNumber("cycles");
  if (el->FindElement("idlerpm"))
    IdleRPM = el->FindElementValueAsNumber("idlerpm");
  if (el->FindElement("maxrpm"))
    MaxRPM = el->FindElementValueAsNumber("maxrpm");
  if (el->FindElement("maxthrottle"))
    MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
  if (el->FindElement("minthrottle"))
    MinThrottle = el->FindElementValueAsNumber("minthrottle");
  if (el->FindElement("bsfc"))
    ISFC = el->FindElementValueAsNumberConvertTo("bsfc", "LBS/HP*HR");
  if (el->FindElement("volumetric-efficiency"))
    volumetric_efficiency = el->FindElementValueAsNumber("volumetric-efficiency");
  if (el->FindElement("compression-ratio"))
    CompressionRatio = el->FindElementValueAsNumber("compression-ratio");
  if (el->FindElement("bore"))
    Bore = el->FindElementValueAsNumberConvertTo("bore","IN");
  if (el->FindElement("stroke"))
    Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN");
  if (el->FindElement("cylinders"))
    Cylinders = el->FindElementValueAsNumber("cylinders");
  if (el->FindElement("cylinder-head-mass"))
    CylinderHeadMass = el->FindElementValueAsNumberConvertTo("cylinder-head-mass","KG");
  if (el->FindElement("air-intake-impedance-factor"))
    Z_airbox = el->FindElementValueAsNumber("air-intake-impedance-factor");
  if (el->FindElement("ram-air-factor"))
    Ram_Air_Factor  = el->FindElementValueAsNumber("ram-air-factor");
  if (el->FindElement("cooling-factor"))
    Cooling_Factor  = el->FindElementValueAsNumber("cooling-factor");
  if (el->FindElement("starter-rpm"))
    StarterRPM  = el->FindElementValueAsNumber("starter-rpm");
  if (el->FindElement("starter-torque"))
    StarterTorque  = el->FindElementValueAsNumber("starter-torque");
  if (el->FindElement("dynamic-fmep"))
    FMEPDynamic= el->FindElementValueAsNumberConvertTo("dynamic-fmep","PA");
  if (el->FindElement("static-fmep"))
    FMEPStatic = el->FindElementValueAsNumberConvertTo("static-fmep","PA");
  if (el->FindElement("peak-piston-speed"))
    PeakMeanPistonSpeed_fps  = el->FindElementValueAsNumber("peak-piston-speed");
  if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
    BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");
    if (el->FindElement("boostoverride"))
      BoostOverride = (int)el->FindElementValueAsNumber("boostoverride");
    if (el->FindElement("boostmanual"))
      BoostManual = (int)el->FindElementValueAsNumber("boostmanual");
    if (el->FindElement("takeoffboost"))
      TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI");
    if (el->FindElement("ratedboost1"))
      RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI");
    if (el->FindElement("ratedboost2"))
      RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI");
    if (el->FindElement("ratedboost3"))
      RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI");
    if (el->FindElement("ratedpower1"))
      RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP");
    if (el->FindElement("ratedpower2"))
      RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP");
    if (el->FindElement("ratedpower3"))
      RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP");
    if (el->FindElement("ratedrpm1"))
      RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1");
    if (el->FindElement("ratedrpm2"))
      RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2");
    if (el->FindElement("ratedrpm3"))
      RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3");
    if (el->FindElement("ratedaltitude1"))
      RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT");
    if (el->FindElement("ratedaltitude2"))
      RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT");
    if (el->FindElement("ratedaltitude3"))
      RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT");
  }

  while((table_element = el->FindNextElement("table")) != 0) {
    name = table_element->GetAttributeValue("name");
    try {
      if (name == "COMBUSTION") {
        Lookup_Combustion_Efficiency = new FGTable(PropertyManager, table_element);
      } else if (name == "MIXTURE") {
        Mixture_Efficiency_Correlation = new FGTable(PropertyManager, table_element);
      } else {
        cerr << "Unknown table type: " << name << " in piston engine definition." << endl;
      }
    } catch (std::string str) {
      throw("Error loading piston engine table:" + name + ". " + str);
    }
  }


  volumetric_efficiency_reduced = volumetric_efficiency;

  if(StarterRPM < 0.) StarterRPM = 2*IdleRPM;
  if(StarterTorque < 0)
    StarterTorque = (MaxHP)*0.4; //just a wag.

  displacement_SI = Displacement * in3tom3;
  RatedMeanPistonSpeed_fps =  ( MaxRPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS

  // Create IFSC to match the engine if not provided
  if (ISFC < 0) {
      double pmep = 29.92 - MaxManifoldPressure_inHg;
      pmep *= inhgtopa  * volumetric_efficiency;
      double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic);
      double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371);
      ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss-StaticFriction_HP));
// cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl;
  }
  if ( MaxManifoldPressure_inHg > 29.9 ) {   // Don't allow boosting with a bogus number
      MaxManifoldPressure_inHg = 29.9;
  }
  minMAP = MinManifoldPressure_inHg * inhgtopa;  // inHg to Pa
  maxMAP = MaxManifoldPressure_inHg * inhgtopa;

// For throttle
/*
 * Pm = ( Ze / ( Ze + Zi + Zt ) ) * Pa
 * Where:
 * Pm = Manifold Pressure
 * Pa = Ambient Pressre
 * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed
 * Zi = airbox impedance
 * Zt = throttle impedance
 *
 * For the calculation below throttle is fully open or Zt = 0
 *
 *
 *
 */
  if(Z_airbox < 0.0){
    double Ze=PeakMeanPistonSpeed_fps/RatedMeanPistonSpeed_fps; // engine impedence
    Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox
  }
  // Constant for Throttle impedence
  Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; 
  //  Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence

// Default tables if not provided in the configuration file
  if(Lookup_Combustion_Efficiency == 0) {
    // First column is thi, second is neta (combustion efficiency)
    Lookup_Combustion_Efficiency = new FGTable(12);
    *Lookup_Combustion_Efficiency << 0.00 << 0.980;
    *Lookup_Combustion_Efficiency << 0.90 << 0.980;
    *Lookup_Combustion_Efficiency << 1.00 << 0.970;
    *Lookup_Combustion_Efficiency << 1.05 << 0.950;
    *Lookup_Combustion_Efficiency << 1.10 << 0.900;
    *Lookup_Combustion_Efficiency << 1.15 << 0.850;
    *Lookup_Combustion_Efficiency << 1.20 << 0.790;
    *Lookup_Combustion_Efficiency << 1.30 << 0.700;
    *Lookup_Combustion_Efficiency << 1.40 << 0.630;
    *Lookup_Combustion_Efficiency << 1.50 << 0.570;
    *Lookup_Combustion_Efficiency << 1.60 << 0.525;
    *Lookup_Combustion_Efficiency << 2.00 << 0.345;
  }

    // First column is Fuel/Air Ratio, second is neta (mixture efficiency)
  if( Mixture_Efficiency_Correlation == 0) {
    Mixture_Efficiency_Correlation = new FGTable(15);
    *Mixture_Efficiency_Correlation << 0.05000 << 0.00000;
    *Mixture_Efficiency_Correlation << 0.05137 << 0.00862;
    *Mixture_Efficiency_Correlation << 0.05179 << 0.21552;
    *Mixture_Efficiency_Correlation << 0.05430 << 0.48276;
    *Mixture_Efficiency_Correlation << 0.05842 << 0.70690;
    *Mixture_Efficiency_Correlation << 0.06312 << 0.83621;
    *Mixture_Efficiency_Correlation << 0.06942 << 0.93103;
    *Mixture_Efficiency_Correlation << 0.07786 << 1.00000;
    *Mixture_Efficiency_Correlation << 0.08845 << 1.00000;
    *Mixture_Efficiency_Correlation << 0.09270 << 0.98276;
    *Mixture_Efficiency_Correlation << 0.10120 << 0.93103;
    *Mixture_Efficiency_Correlation << 0.11455 << 0.72414;
    *Mixture_Efficiency_Correlation << 0.12158 << 0.45690;
    *Mixture_Efficiency_Correlation << 0.12435 << 0.23276;
    *Mixture_Efficiency_Correlation << 0.12500 << 0.00000;
  }

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
  property_name = base_property_name + "/power-hp";
  PropertyManager->Tie(property_name, &HP);
  property_name = base_property_name + "/bsfc-lbs_hphr";
  PropertyManager->Tie(property_name, &ISFC);
  property_name = base_property_name + "/starter-norm";
  PropertyManager->Tie(property_name, &StarterGain);
  property_name = base_property_name + "/volumetric-efficiency";
  PropertyManager->Tie(property_name, &volumetric_efficiency);
  property_name = base_property_name + "/map-pa";
  PropertyManager->Tie(property_name, &MAP);
  property_name = base_property_name + "/map-inhg";
  PropertyManager->Tie(property_name, &ManifoldPressure_inHg);
  property_name = base_property_name + "/air-intake-impedance-factor";
  PropertyManager->Tie(property_name, &Z_airbox);
  property_name = base_property_name + "/ram-air-factor";
  PropertyManager->Tie(property_name, &Ram_Air_Factor);
  property_name = base_property_name + "/cooling-factor";
  PropertyManager->Tie(property_name, &Cooling_Factor);
  property_name = base_property_name + "/boost-speed";
  PropertyManager->Tie(property_name, &BoostSpeed);
  property_name = base_property_name + "/cht-degF";
  PropertyManager->Tie(property_name, this, &FGPiston::getCylinderHeadTemp_degF);
  property_name = base_property_name + "/oil-temperature-degF";
  PropertyManager->Tie(property_name, this, &FGPiston::getOilTemp_degF);
  property_name = base_property_name + "/oil-pressure-psi";
  PropertyManager->Tie(property_name, this, &FGPiston::getOilPressure_psi);
  property_name = base_property_name + "/egt-degF";
  PropertyManager->Tie(property_name, this, &FGPiston::getExhaustGasTemp_degF);

  // Set up and sanity-check the turbo/supercharging configuration based on the input values.
  if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true;
  for (i=0; i<BoostSpeeds; ++i) {
    bool bad = false;
    if (RatedBoost[i] <= 0.0) bad = true;
    if (RatedPower[i] <= 0.0) bad = true;
    if (RatedAltitude[i] < 0.0) bad = true;  // 0.0 is deliberately allowed - this corresponds to unregulated supercharging.
    if (i > 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true;
    if (bad) {
      // We can't recover from the above - don't use this supercharger speed.
      BoostSpeeds--;
      // TODO - put out a massive error message!
      break;
    }
    // Now sanity-check stuff that is recoverable.
    if (i < BoostSpeeds - 1) {
      if (BoostSwitchAltitude[i] < RatedAltitude[i]) {
        // TODO - put out an error message
        // But we can also make a reasonable estimate, as below.
        BoostSwitchAltitude[i] = RatedAltitude[i] + 1000;
      }
      BoostSwitchPressure[i] = GetStdPressure100K(BoostSwitchAltitude[i]) * psftopa;
      //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n';
      // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now
      BoostSwitchHysteresis = 1000;
    }
    // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude.
    RatedMAP[i] = standard_pressure + RatedBoost[i] * 6895;  // psi*6895 = Pa.
    // Sometimes a separate BCV setting for takeoff or extra power is fitted.
    if (TakeoffBoost > RatedBoost[0]) {
      // Assume that the effect on the BCV is the same whichever speed is in use.
      TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895);
      bTakeoffBoost = true;
    } else {
      TakeoffMAP[i] = RatedMAP[i];
      bTakeoffBoost = false;
    }
    BoostMul[i] = RatedMAP[i] / (GetStdPressure100K(RatedAltitude[i]) * psftopa);

  }

  if (BoostSpeeds > 0) {
    Boosted = true;
    BoostSpeed = 0;
  }
  bBoostOverride = (BoostOverride == 1 ? true : false);
  bBoostManual   = (BoostManual   == 1 ? true : false);
  Debug(0); // Call Debug() routine from constructor if needed
}
コード例 #19
0
ファイル: FGPropeller.cpp プロジェクト: ToninoTarsi/jsbsim
FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
                       : FGThruster(exec, prop_element, num)
{
  string token;
  Element *table_element, *local_element;
  string name="";
  FGPropertyManager* PropertyManager = exec->GetPropertyManager();

  MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0;
  Sense = 1; // default clockwise rotation
  ReversePitch = 0.0;
  Reversed = false;
  Feathered = false;
  Reverse_coef = 0.0;
  GearRatio = 1.0;
  CtFactor = CpFactor = 1.0;
  ConstantSpeed = 0;
  cThrust = cPower = CtMach = CpMach = 0;
  Vinduced = 0.0;

  if (prop_element->FindElement("ixx"))
    Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
  if (prop_element->FindElement("diameter"))
    Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT");
  if (prop_element->FindElement("numblades"))
    numBlades = (int)prop_element->FindElementValueAsNumber("numblades");
  if (prop_element->FindElement("gearratio"))
    GearRatio = prop_element->FindElementValueAsNumber("gearratio");
  if (prop_element->FindElement("minpitch"))
    MinPitch = prop_element->FindElementValueAsNumber("minpitch");
  if (prop_element->FindElement("maxpitch"))
    MaxPitch = prop_element->FindElementValueAsNumber("maxpitch");
  if (prop_element->FindElement("minrpm"))
    MinRPM = prop_element->FindElementValueAsNumber("minrpm");
  if (prop_element->FindElement("maxrpm")) {
    MaxRPM = prop_element->FindElementValueAsNumber("maxrpm");
    ConstantSpeed = 1;
    }
  if (prop_element->FindElement("constspeed"))
    ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed");
  if (prop_element->FindElement("reversepitch"))
    ReversePitch = prop_element->FindElementValueAsNumber("reversepitch");
  while((table_element = prop_element->FindNextElement("table")) != 0) {
    name = table_element->GetAttributeValue("name");
    try {
      if (name == "C_THRUST") {
        cThrust = new FGTable(PropertyManager, table_element);
      } else if (name == "C_POWER") {
        cPower = new FGTable(PropertyManager, table_element);
      } else if (name == "CT_MACH") {
        CtMach = new FGTable(PropertyManager, table_element);
      } else if (name == "CP_MACH") {
        CpMach = new FGTable(PropertyManager, table_element);
      } else {
        cerr << "Unknown table type: " << name << " in propeller definition." << endl;
      }
    } catch (std::string str) {
      throw("Error loading propeller table:" + name + ". " + str);
    }
  }
  if( (cPower == 0) || (cThrust == 0)){
      cerr << "Propeller configuration must contain C_THRUST and C_POWER tables!" << endl;
  }

  local_element = prop_element->GetParent()->FindElement("sense");
  if (local_element) {
    double Sense = local_element->GetDataAsNumber();
    SetSense(Sense >= 0.0 ? 1.0 : -1.0);
  }
  local_element = prop_element->GetParent()->FindElement("p_factor");
  if (local_element) {
    P_Factor = local_element->GetDataAsNumber();
  }
  if (P_Factor < 0) {
    cerr << "P-Factor value in propeller configuration file must be greater than zero" << endl;
  }
  if (prop_element->FindElement("ct_factor"))
    SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") );
  if (prop_element->FindElement("cp_factor"))
    SetCpFactor( prop_element->FindElementValueAsNumber("cp_factor") );

  Type = ttPropeller;
  RPM = 0;
  vTorque.InitMatrix();
  D4 = Diameter*Diameter*Diameter*Diameter;
  D5 = D4*Diameter;
  Pitch = MinPitch;

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);
  property_name = base_property_name + "/engine-rpm";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetEngineRPM );
  property_name = base_property_name + "/advance-ratio";
  PropertyManager->Tie( property_name.c_str(), &J );
  property_name = base_property_name + "/blade-angle";
  PropertyManager->Tie( property_name.c_str(), &Pitch );
  property_name = base_property_name + "/thrust-coefficient";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetThrustCoefficient );
  property_name = base_property_name + "/propeller-rpm";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetRPM );
  property_name = base_property_name + "/helical-tip-Mach";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetHelicalTipMach );
  property_name = base_property_name + "/constant-speed-mode";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetConstantSpeed,
                      &FGPropeller::SetConstantSpeed );
  property_name = base_property_name + "/prop-induced-velocity_fps";
  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetInducedVelocity,
                      &FGPropeller::SetInducedVelocity );

  Debug(0);
}
コード例 #20
0
ファイル: FGThruster.cpp プロジェクト: adrcad/jsbsim
FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMExec)
{
  Element* thruster_element = el->GetParent();
  Element* element;
  FGColumnVector3 location, orientation, pointing;

  Type = ttDirect;
  SetTransformType(FGForce::tCustom);

  Name = el->GetAttributeValue("name");

  GearRatio = 1.0;
  ReverserAngle = 0.0;
  Thrust = 0.0;
  EngineNum = num;
  PropertyManager = FDMExec->GetPropertyManager();

// Determine the initial location and orientation of this thruster and load the
// thruster with this information.

  element = thruster_element->FindElement("location");
  if (element)  location = element->FindElementTripletConvertTo("IN");
  else          cerr << fgred << "      No thruster location found." << reset << endl;

  SetLocation(location);

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);

  element = thruster_element->FindElement("pointing");
  if (element)  {

    // This defines a fixed nozzle that has no public interface property to gimbal or reverse it.
    pointing = element->FindElementTripletConvertTo("RAD"); // The specification of RAD here is superfluous,
                                                            // and simply precludes a conversion.
    mT.InitMatrix();
    mT(1,1) = pointing(1);
    mT(2,1) = pointing(2);
    mT(3,1) = pointing(3);

  } else {

  element = thruster_element->FindElement("orient");
  if (element)  orientation = element->FindElementTripletConvertTo("RAD");

  SetAnglesToBody(orientation);
  property_name = base_property_name + "/pitch-angle-rad";
  PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetPitch, &FGForce::SetPitch);
  property_name = base_property_name + "/yaw-angle-rad";
  PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw);

  if (el->GetName() == "direct") // this is a direct thruster. At this time
                                 // only a direct thruster can be reversed.
  {
    property_name = base_property_name + "/reverser-angle-rad";
    PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetReverserAngle,
                                                          &FGThruster::SetReverserAngle);
  }

  }


  Debug(0);
}
コード例 #21
0
ファイル: FGTank.cpp プロジェクト: adrcad/jsbsim
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
                  : TankNumber(tank_number), Exec(exec)
{
  string token, strFuelName;
  Element* element;
  Element* element_Grain;
  Area = 1.0;
  Density = 6.6;
  InitialTemperature = Temperature = -9999.0;
  Ixx = Iyy = Izz = 0.0;
  InertiaFactor = 1.0;
  Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
  PreviousUsed = 0.0;
  ExternalFlow = 0.0;
  InitialStandpipe = 0.0;
  Capacity = 0.00001;
  Priority = InitialPriority = 1;
  PropertyManager = Exec->GetPropertyManager();
  vXYZ.InitMatrix();
  vXYZ_drain.InitMatrix();

  type = el->GetAttributeValue("type");
  if      (type == "FUEL")     Type = ttFUEL;
  else if (type == "OXIDIZER") Type = ttOXIDIZER;
  else                         Type = ttUNKNOWN;

  element = el->FindElement("location");
  if (element)  vXYZ = element->FindElementTripletConvertTo("IN");
  else          cerr << "No location found for this tank." << endl;

  vXYZ_drain = vXYZ; // Set initial drain location to initial tank CG

  element = el->FindElement("drain_location");
  if (element)  {
    vXYZ_drain = element->FindElementTripletConvertTo("IN");
  }

  if (el->FindElement("radius"))
    Radius = el->FindElementValueAsNumberConvertTo("radius", "IN");
  if (el->FindElement("inertia_factor"))
    InertiaFactor = el->FindElementValueAsNumber("inertia_factor");
  if (el->FindElement("capacity"))
    Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS");
  if (el->FindElement("contents"))
    InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS");
  if (el->FindElement("temperature"))
    InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature");
  if (el->FindElement("standpipe"))
    InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS");
  if (el->FindElement("priority"))
    InitialPriority = Priority = (int)el->FindElementValueAsNumber("priority");
  if (el->FindElement("density"))
    Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
  if (el->FindElement("type"))
    strFuelName = el->FindElementValue("type");


  SetPriority( InitialPriority );     // this will also set the Selected flag

  if (Capacity == 0) {
    cerr << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl;
    Capacity = 0.00001;
    Contents = 0.0;
  }
  if (Contents > Capacity) {
    cerr << "Tank content (" << Contents << " lbs) is greater than tank capacity ("
         << Capacity << " lbs) for tank " << tank_number
         << "! Did you accidentally swap contents and capacity?" << endl;
    throw("tank definition error");
  }

  PctFull = 100.0*Contents/Capacity;            // percent full; 0 to 100.0

  // Check whether this is a solid propellant "tank". Initialize it if true.

  grainType = gtUNKNOWN; // This is the default
  
  element_Grain = el->FindElement("grain_config");
  if (element_Grain) {

    strGType = element_Grain->GetAttributeValue("type");
    if (strGType == "CYLINDRICAL")     grainType = gtCYLINDRICAL;
    else if (strGType == "ENDBURNING") grainType = gtENDBURNING;
    else                               cerr << "Unknown propellant grain type specified" << endl;

    if (element_Grain->FindElement("length"))
      Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN");
    if (element_Grain->FindElement("bore_diameter"))
      InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0;

    // Initialize solid propellant values for debug and runtime use.

    switch (grainType) {
      case gtCYLINDRICAL:
        if (Radius <= InnerRadius) {
          cerr << "The bore diameter should be smaller than the total grain diameter!" << endl;
          exit(-1);
        }
        Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches
        break;
      case gtENDBURNING:
        Volume = M_PI * Length * Radius * Radius; // cubic inches
        break;
      case gtUNKNOWN:
        cerr << "Unknown grain type found in this rocket engine definition." << endl;
        exit(-1);
    }
    Density = (Contents*lbtoslug)/Volume; // slugs/in^3
  }

    CalculateInertias();

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
  property_name = base_property_name + "/contents-lbs";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
                                       &FGTank::SetContents );
  property_name = base_property_name + "/pct-full";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);

  property_name = base_property_name + "/priority";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
                                       &FGTank::SetPriority );
  property_name = base_property_name + "/external-flow-rate-pps";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
                                       &FGTank::SetExternalFlow );

  if (Temperature != -9999.0)  InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
  Area = 40.0 * pow(Capacity/1975, 0.666666667);

  // A named fuel type will override a previous density value
  if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); 

  Debug(0);
}
コード例 #22
0
ファイル: FGRocket.cpp プロジェクト: adrcad/jsbsim
FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input)
  : FGEngine(exec, el, engine_number, input), isp_function(0L)
{
  Type = etRocket;
  Element* thrust_table_element = 0;
  ThrustTable = 0L;
  BurnTime = 0.0;
  previousFuelNeedPerTank = 0.0;
  previousOxiNeedPerTank = 0.0;
  PropellantFlowRate = 0.0;
  TotalPropellantExpended = 0.0;
  FuelFlowRate = FuelExpended = 0.0;
  OxidizerFlowRate = OxidizerExpended = 0.0;
  SLOxiFlowMax = SLFuelFlowMax = PropFlowMax = 0.0;
  MxR = 0.0;
  BuildupTime = 0.0;
  It = ItVac = 0.0;
  ThrustVariation = 0.0;
  TotalIspVariation = 0.0;
  VacThrust = 0.0;
  Flameout = false;

  // Defaults
   MinThrottle = 0.0;
   MaxThrottle = 1.0;

  string base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);

  std::stringstream strEngineNumber;
  strEngineNumber << EngineNumber;

  Element* isp_el = el->FindElement("isp");
  Element* isp_func_el=0;

  bindmodel(); // Bind model properties first, since they might be needed in functions.

  // Specific impulse may be specified as a constant value or as a function - perhaps as a function of mixture ratio.
  if (isp_el) {
    isp_func_el = isp_el->FindElement("function");
    if (isp_func_el) {
      isp_function = new FGFunction(exec->GetPropertyManager(),isp_func_el, strEngineNumber.str());
    } else {
    Isp = el->FindElementValueAsNumber("isp");
    }
  } else {
    throw("Specific Impulse <isp> must be specified for a rocket engine");
  }
  
  if (el->FindElement("builduptime"))
    BuildupTime = el->FindElementValueAsNumber("builduptime");
  if (el->FindElement("maxthrottle"))
    MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
  if (el->FindElement("minthrottle"))
    MinThrottle = el->FindElementValueAsNumber("minthrottle");

  if (el->FindElement("slfuelflowmax")) {
    SLFuelFlowMax = el->FindElementValueAsNumberConvertTo("slfuelflowmax", "LBS/SEC");
    if (el->FindElement("sloxiflowmax")) {
    SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC");
    }
    PropFlowMax = SLOxiFlowMax + SLFuelFlowMax;
    MxR = SLOxiFlowMax/SLFuelFlowMax;
  } else if (el->FindElement("propflowmax")) {
    PropFlowMax = el->FindElementValueAsNumberConvertTo("propflowmax", "LBS/SEC");
    // Mixture ratio may be specified here, but it can also be specified as a function or via property
    if (el->FindElement("mixtureratio")) {
      MxR = el->FindElementValueAsNumber("mixtureratio");
    }
  }

  if (isp_function) Isp = isp_function->GetValue(); // cause Isp function to be executed if present.
  // If there is a thrust table element, this is a solid propellant engine.
  thrust_table_element = el->FindElement("thrust_table");
  if (thrust_table_element) {
    ThrustTable = new FGTable(PropertyManager, thrust_table_element);
    Element* variation_element = el->FindElement("variation");
    if (variation_element) {
      if (variation_element->FindElement("thrust")) {
        ThrustVariation = variation_element->FindElementValueAsNumber("thrust");
      }
      if (variation_element->FindElement("total_isp")) {
        TotalIspVariation = variation_element->FindElementValueAsNumber("total_isp");
      }
    }
  }


  Debug(0);
}
コード例 #23
0
ファイル: FGGasCell.cpp プロジェクト: MCBama/jsbsim
FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num,
                     const struct Inputs& input)
  : FGForce(exec), in(input)
{
  string token;
  Element* element;

  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
  MassBalance = exec->GetMassBalance();

  gasCellJ = FGMatrix33();
  gasCellM = FGColumnVector3();

  Buoyancy = MaxVolume = MaxOverpressure = Temperature = Pressure =
    Contents = Volume = dVolumeIdeal = 0.0;
  Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0;
  ValveCoefficient = ValveOpen = 0.0;
  CellNum = num;

  // NOTE: In the local system X points north, Y points east and Z points down.
  SetTransformType(FGForce::tLocalBody);

  type = el->GetAttributeValue("type");
  if      (type == "HYDROGEN") Type = ttHYDROGEN;
  else if (type == "HELIUM")   Type = ttHELIUM;
  else if (type == "AIR")      Type = ttAIR;
  else                         Type = ttUNKNOWN;

  element = el->FindElement("location");
  if (element) {
    vXYZ = element->FindElementTripletConvertTo("IN");
  } else {
      std::stringstream error;
    error << "Fatal Error: No location found for this gas cell." << endl;
    throw std::runtime_error(error.str());
  }
  if ((el->FindElement("x_radius") || el->FindElement("x_width")) &&
      (el->FindElement("y_radius") || el->FindElement("y_width")) &&
      (el->FindElement("z_radius") || el->FindElement("z_width"))) {

    if (el->FindElement("x_radius")) {
      Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT");
    }
    if (el->FindElement("y_radius")) {
      Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT");
    }
    if (el->FindElement("z_radius")) {
      Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT");
    }

    if (el->FindElement("x_width")) {
      Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT");
    }
    if (el->FindElement("y_width")) {
      Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT");
    }
    if (el->FindElement("z_width")) {
      Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT");
    }

    // The volume is a (potentially) extruded ellipsoid.
    // However, currently only a few combinations of radius and width are
    // fully supported.
    if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
        (Xwidth  == 0.0) && (Ywidth  == 0.0) && (Zwidth  == 0.0)) {
      // Ellipsoid volume.
      MaxVolume = 4.0  * M_PI * Xradius * Yradius * Zradius / 3.0;
    } else if  ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
                (Xwidth  != 0.0) && (Ywidth  == 0.0) && (Zwidth  == 0.0)) {
      // Cylindrical volume.
      MaxVolume = M_PI * Yradius * Zradius * Xwidth;
    } else {
      cerr << "Warning: Unsupported gas cell shape." << endl;
      MaxVolume = 
        (4.0  * M_PI * Xradius * Yradius * Zradius / 3.0 +
         M_PI * Yradius * Zradius * Xwidth +
         M_PI * Xradius * Zradius * Ywidth +
         M_PI * Xradius * Yradius * Zwidth +
         2.0  * Xradius * Ywidth * Zwidth +
         2.0  * Yradius * Xwidth * Zwidth +
         2.0  * Zradius * Xwidth * Ywidth +
         Xwidth * Ywidth * Zwidth);
    }
  } else {
      std::stringstream error;
    error << "Fatal Error: Gas cell shape must be given." << endl;
    throw std::runtime_error(error.str());
  }
  if (el->FindElement("max_overpressure")) {
    MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure",
                                                            "LBS/FT2");
  }
  if (el->FindElement("fullness")) {
    const double Fullness = el->FindElementValueAsNumber("fullness");
    if (0 <= Fullness) { 
      Volume = Fullness * MaxVolume; 
    } else {
      cerr << "Warning: Invalid initial gas cell fullness value." << endl;
    }
  }  
  if (el->FindElement("valve_coefficient")) {
    ValveCoefficient =
      el->FindElementValueAsNumberConvertTo("valve_coefficient",
                                            "FT4*SEC/SLUG");
    ValveCoefficient = max(ValveCoefficient, 0.0);
  }

  // Initialize state
  SetLocation(vXYZ);

  if (Temperature == 0.0) {
    Temperature = in.Temperature;
  }
  if (Pressure == 0.0) {
    Pressure = in.Pressure;
  }
  if (Volume != 0.0) {
    // Calculate initial gas content.
    Contents = Pressure * Volume / (R * Temperature);
    
    // Clip to max allowed value.
    const double IdealPressure = Contents * R * Temperature / MaxVolume;
    if (IdealPressure > Pressure + MaxOverpressure) {
      Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature);
      Pressure = Pressure + MaxOverpressure;
    } else {
      Pressure = max(IdealPressure, Pressure);
    }
  } else {
    // Calculate initial gas content.
    Contents = Pressure * MaxVolume / (R * Temperature);
  }

  Volume = Contents * R * Temperature / Pressure;
  Mass = Contents * M_gas();

  // Bind relevant properties
  string property_name, base_property_name;

  base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", CellNum);

  property_name = base_property_name + "/max_volume-ft3";
  PropertyManager->Tie( property_name.c_str(), &MaxVolume, false );
  PropertyManager->GetNode()->SetWritable( property_name, false );
  property_name = base_property_name + "/temp-R";
  PropertyManager->Tie( property_name.c_str(), &Temperature, false );
  property_name = base_property_name + "/pressure-psf";
  PropertyManager->Tie( property_name.c_str(), &Pressure, false );
  property_name = base_property_name + "/volume-ft3";
  PropertyManager->Tie( property_name.c_str(), &Volume, false );
  property_name = base_property_name + "/buoyancy-lbs";
  PropertyManager->Tie( property_name.c_str(), &Buoyancy, false );
  property_name = base_property_name + "/contents-mol";
  PropertyManager->Tie( property_name.c_str(), &Contents, false );
  property_name = base_property_name + "/valve_open";
  PropertyManager->Tie( property_name.c_str(), &ValveOpen, false );

  Debug(0);

  // Read heat transfer coefficients
  if (Element* heat = el->FindElement("heat")) {
    Element* function_element = heat->FindElement("function");
    while (function_element) {
      HeatTransferCoeff.push_back(new FGFunction(PropertyManager,
                                                 function_element));
      function_element = heat->FindNextElement("function");
    }
  }

  // Load ballonets if there are any
  if (Element* ballonet_element = el->FindElement("ballonet")) {
    while (ballonet_element) {
      Ballonet.push_back(new FGBallonet(exec,
                                        ballonet_element,
                                        Ballonet.size(),
                                        this, in));
      ballonet_element = el->FindNextElement("ballonet");
    }
  }

}
コード例 #24
0
ファイル: FGEngine.cpp プロジェクト: AnandBiradar/jsbsim
FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number, struct Inputs& input)
                      : in(input), EngineNumber(engine_number)
{
  Element* local_element;
  FGColumnVector3 location, orientation;

  Name = "";
  Type = etUnknown;
  X = Y = Z = 0.0;
  EnginePitch = EngineYaw = 0.0;
  SLFuelFlowMax = 0.0;
  FuelExpended = 0.0;
  MaxThrottle = 1.0;
  MinThrottle = 0.0;

  ResetToIC(); // initialize dynamic terms

  FDMExec = exec;

  PropertyManager = FDMExec->GetPropertyManager();

  Name = engine_element->GetAttributeValue("name");

  Load(engine_element, PropertyManager, to_string(EngineNumber)); // Call ModelFunctions loader

// Find and set engine location

  local_element = engine_element->GetParent()->FindElement("location");
  if (local_element)  location = local_element->FindElementTripletConvertTo("IN");
  else      cerr << "No engine location found for this engine." << endl;

  local_element = engine_element->GetParent()->FindElement("orient");
  if (local_element)  orientation = local_element->FindElementTripletConvertTo("RAD");
//  else          cerr << "No engine orientation found for this engine." << endl;
// Jon: The engine orientation has a default and is not normally used.

  SetPlacement(location, orientation);

  // Load thruster
  local_element = engine_element->GetParent()->FindElement("thruster");
  if (local_element) {
    try {
      if (!LoadThruster(local_element)) exit(-1);
    } catch (std::string str) {
      throw("Error loading engine " + Name + ". " + str);
    }
  } else {
    cerr << "No thruster definition supplied with engine definition." << endl;
  }

  // Load feed tank[s] references
  local_element = engine_element->GetParent()->FindElement("feed");
  while (local_element) {
    int tankID = (int)local_element->GetDataAsNumber();
    SourceTanks.push_back(tankID);
    local_element = engine_element->GetParent()->FindNextElement("feed");
  }

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);

  property_name = base_property_name + "/set-running";
  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning );
  property_name = base_property_name + "/thrust-lbs";
  PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust);
  property_name = base_property_name + "/fuel-flow-rate-pps";
  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
  property_name = base_property_name + "/fuel-flow-rate-gph";
  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRateGPH);
  property_name = base_property_name + "/fuel-used-lbs";
  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs);

  PostLoad(engine_element, PropertyManager, to_string(EngineNumber));

  Debug(0);
}