Exemplo n.º 1
0
void FGAtmosphere::Calculate(double altitude)
{
  FGPropertyNode* node = PropertyManager->GetNode();
  if (!PropertyManager->HasNode("atmosphere/override/temperature"))
    Temperature = GetTemperature(altitude);
  else
    Temperature = node->GetDouble("atmosphere/override/temperature");

  if (!PropertyManager->HasNode("atmosphere/override/pressure"))
    Pressure = GetPressure(altitude);
  else
    Pressure = node->GetDouble("atmosphere/override/pressure");

  if (!PropertyManager->HasNode("atmosphere/override/density"))
    Density = Pressure/(Reng*Temperature);
  else
    Density = node->GetDouble("atmosphere/override/density");

  Soundspeed  = sqrt(SHRatio*Reng*(Temperature));
  PressureAltitude = altitude;
  DensityAltitude = altitude;

  Viscosity = Beta * pow(Temperature, 1.5) / (SutherlandConstant + Temperature);
  KinematicViscosity = Viscosity / Density;
}
Exemplo n.º 2
0
FGSimplexTrim::FGSimplexTrim(FGFDMExec * fdm, TrimMode mode)
{
    std::clock_t time_start=clock(), time_trimDone;

    // variables
    FGTrimmer::Constraints constraints;

    if (fdm->GetDebugLevel() > 0) {
        std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
    }

    // defaults
    std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
    FGPropertyNode* node = fdm->GetPropertyManager()->GetNode();
    double rtol = node->GetDouble("trim/solver/rtol");
    double abstol = node->GetDouble("trim/solver/abstol");
    double speed = node->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
    double random = node->GetDouble("trim/solver/random");
    int iterMax = int(node->GetDouble("trim/solver/iterMax"));
    bool showConvergence = node->GetBool("trim/solver/showConvergence");
    bool pause = node->GetBool("trim/solver/pause");
    bool showSimplex = node->GetBool("trim/solver/showSimplex");

    // flight conditions
    double phi = fdm->GetIC()->GetPhiRadIC();
    double theta = fdm->GetIC()->GetThetaRadIC();
    double gd = fdm->GetInertial()->gravity();

    constraints.velocity = fdm->GetIC()->GetVtrueFpsIC();
    constraints.altitude = fdm->GetIC()->GetAltitudeASLFtIC();
    constraints.gamma = fdm->GetIC()->GetFlightPathAngleRadIC();
    constraints.rollRate = 0;
    constraints.pitchRate = 0;
    constraints.yawRate = tan(phi)*gd*cos(theta)/constraints.velocity;

    constraints.stabAxisRoll = true; // FIXME, make this an option

    // initial solver state
    int n = 6;
    std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);

    lowerBound[0] = node->GetDouble("trim/solver/throttleMin");
    lowerBound[1] = node->GetDouble("trim/solver/elevatorMin");
    lowerBound[2] = node->GetDouble("trim/solver/alphaMin");
    lowerBound[3] = node->GetDouble("trim/solver/aileronMin");
    lowerBound[4] = node->GetDouble("trim/solver/rudderMin");
    lowerBound[5] = node->GetDouble("trim/solver/betaMin");

    upperBound[0] = node->GetDouble("trim/solver/throttleMax");
    upperBound[1] = node->GetDouble("trim/solver/elevatorMax");
    upperBound[2] = node->GetDouble("trim/solver/alphaMax");
    upperBound[3] = node->GetDouble("trim/solver/aileronMax");
    upperBound[4] = node->GetDouble("trim/solver/rudderMax");
    upperBound[5] = node->GetDouble("trim/solver/betaMax");

    initialStepSize[0] = node->GetDouble("trim/solver/throttleStep");
    initialStepSize[1] = node->GetDouble("trim/solver/elevatorStep");
    initialStepSize[2] = node->GetDouble("trim/solver/alphaStep");
    initialStepSize[3] = node->GetDouble("trim/solver/aileronStep");
    initialStepSize[4] = node->GetDouble("trim/solver/rudderStep");
    initialStepSize[5] = node->GetDouble("trim/solver/betaStep");

    initialGuess[0] = node->GetDouble("trim/solver/throttleGuess");
    initialGuess[1] = node->GetDouble("trim/solver/elevatorGuess");
    initialGuess[2] = node->GetDouble("trim/solver/alphaGuess");
    initialGuess[3] = node->GetDouble("trim/solver/aileronGuess");
    initialGuess[4] = node->GetDouble("trim/solver/rudderGuess");
    initialGuess[5] = node->GetDouble("trim/solver/betaGuess");

    // solve
    FGTrimmer * trimmer = new FGTrimmer(fdm, &constraints);
    Callback callback(aircraftName, trimmer);
    FGNelderMead * solver = NULL;

    solver = new FGNelderMead(trimmer,initialGuess,
        lowerBound, upperBound, initialStepSize,iterMax,rtol,
        abstol,speed,random,showConvergence,showSimplex,pause,&callback);
    while(solver->status()==1) solver->update();
    time_trimDone = std::clock();

    // output
    if (fdm->GetDebugLevel() > 0) {
        trimmer->printSolution(std::cout,solver->getSolution());
        std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer->eval(solver->getSolution()) << std::endl;
        std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
    }

    delete solver;
    delete trimmer;
}
Exemplo n.º 3
0
FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root), FDMctr(fdmctr)
{
  Frame           = 0;
  Error           = 0;
  IC              = 0;
  Trim            = 0;
  Script          = 0;
  disperse        = 0;

  RootDir = "";

  modelLoaded = false;
  IsChild = false;
  holding = false;
  Terminate = false;
  StandAlone = false;
  ResetMode = 0;

  IncrementThenHolding = false;  // increment then hold is off by default
  TimeStepsUntilHold = -1;

  sim_time = 0.0;
  dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
                  // run in standalone mode with no initialization file.

  AircraftPath = "aircraft";
  EnginePath = "engine";
  SystemsPath = "systems";

  try {
    char* num = getenv("JSBSIM_DEBUG");
    if (num) debug_lvl = atoi(num); // set debug level
  } catch (...) {                   // if error set to 1
    debug_lvl = 1;
  }

  if (Root == 0) {                 // Then this is the root FDM
    Root = new FGPropertyManager;  // Create the property manager
    StandAlone = true;
  }

  if (FDMctr == 0) {
    FDMctr = new unsigned int;     // Create and initialize the child FDM counter
    (*FDMctr) = 0;
  }

  // Store this FDM's ID
  IdFDM = (*FDMctr); // The main (parent) JSBSim instance is always the "zeroth"

  // Prepare FDMctr for the next child FDM id
  (*FDMctr)++;       // instance. "child" instances are loaded last.

  FGPropertyNode* instanceRoot = Root->GetNode("/fdm/jsbsim",IdFDM,true);
  instance = new FGPropertyManager(instanceRoot);

  try {
    char* num = getenv("JSBSIM_DISPERSE");
    if (num) {
      if (atoi(num) != 0) disperse = 1;  // set dispersions on
    }
  } catch (...) {                        // if error set to false
    disperse = 0;
    std::cerr << "Could not process JSBSIM_DISPERSIONS environment variable: Assumed NO dispersions." << endl;
  }

  Debug(0);
  // this is to catch errors in binding member functions to the property tree.
  try {
    Allocate();
  } catch ( string msg ) {
    cout << "Caught error: " << msg << endl;
    exit(1);
  }

  trim_status = false;
  ta_mode     = 99;

  Constructing = true;
  typedef int (FGFDMExec::*iPMF)(void) const;
//  instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
  instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
  instance->Tie("simulation/do_simplex_trim", this, (iPMF)0, &FGFDMExec::DoSimplexTrim);
  instance->Tie("simulation/do_linearization", this, (iPMF)0, &FGFDMExec::DoLinearization);
  instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
  instance->Tie("simulation/disperse", this, &FGFDMExec::GetDisperse);
  instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false);
  instance->Tie("simulation/terminate", (int *)&Terminate);
  instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
  instance->Tie("simulation/dt", this, &FGFDMExec::GetDeltaT);
  instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
  instance->Tie("simulation/frame", (int *)&Frame, false);

  // simplex trim properties
  instanceRoot->SetDouble("trim/solver/rtol",0.0001);
  instanceRoot->SetDouble("trim/solver/speed",2);
  instanceRoot->SetDouble("trim/solver/abstol",0.001);
  instanceRoot->SetDouble("trim/solver/iterMax",2000);
  instanceRoot->SetInt("trim/solver/debugLevel",0);
  instanceRoot->SetDouble("trim/solver/random",0);
  instanceRoot->SetBool("trim/solver/showSimplex",false);
  instanceRoot->SetBool("trim/solver/showConvergence",false);
  instanceRoot->SetBool("trim/solver/pause",false);
  instanceRoot->SetBool("trim/solver/variablePropPitch",false);

  instanceRoot->SetDouble("trim/solver/throttleGuess",0.50);
  instanceRoot->SetDouble("trim/solver/throttleMin",0.0);
  instanceRoot->SetDouble("trim/solver/throttleMax",1.0);
  instanceRoot->SetDouble("trim/solver/throttleStep",0.1);

  instanceRoot->SetDouble("trim/solver/aileronGuess",0);
  instanceRoot->SetDouble("trim/solver/aileronMin",-1.00);
  instanceRoot->SetDouble("trim/solver/aileronMax",1.00);
  instanceRoot->SetDouble("trim/solver/aileronStep",0.1);

  instanceRoot->SetDouble("trim/solver/rudderGuess",0);
  instanceRoot->SetDouble("trim/solver/rudderMin",-1.00);
  instanceRoot->SetDouble("trim/solver/rudderMax",1.00);
  instanceRoot->SetDouble("trim/solver/rudderStep",0.1);

  instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1);
  instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0);
  instanceRoot->SetDouble("trim/solver/elevatorMax",1.0);
  instanceRoot->SetDouble("trim/solver/elevatorStep",0.1);

  instanceRoot->SetDouble("trim/solver/alphaGuess",0.05);
  instanceRoot->SetDouble("trim/solver/alphaMin",-0.1);
  instanceRoot->SetDouble("trim/solver/alphaMax",.18);
  instanceRoot->SetDouble("trim/solver/alphaStep",0.05);

  instanceRoot->SetDouble("trim/solver/betaGuess",0);
  instanceRoot->SetDouble("trim/solver/betaMin",-0.1);
  instanceRoot->SetDouble("trim/solver/betaMax",0.1);
  instanceRoot->SetDouble("trim/solver/betaStep",0.0001);

  Constructing = false;
}
Exemplo n.º 4
0
void FGScript::Debug(int from)
{
  if (debug_lvl <= 0) return;

  if (debug_lvl & 1) { // Standard console startup message output
    if (from == 0) { // Constructor
    } else if (from == 3) {
    } else if (from == 4)  { // print out script data
      cout << endl;
      cout << "Script: \"" << ScriptName << "\"" << endl;
      cout << "  begins at " << StartTime << " seconds and runs to " << EndTime
        << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" <<
        ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl;
      cout << endl;

      FGPropertyReader::const_iterator it;
      for (it = LocalProperties.begin(); it != LocalProperties.end(); ++it) {
        FGPropertyNode* node = *it;
        cout << "Local property: " << node->GetName()
             << " = " << node->getDoubleValue()
             << endl;
      }
      
      if (LocalProperties.empty()) cout << endl;

      for (unsigned i=0; i<Events.size(); i++) {
        cout << "Event " << i;
        if (!Events[i].Name.empty()) cout << " (" << Events[i].Name << ")";
        cout << ":" << endl;

        if (Events[i].Persistent)
          cout << "  " << "Whenever triggered, executes once";
        else if (Events[i].Continuous)
          cout << "  " << "While true, always executes";
        else
          cout << "  " << "When first triggered, executes once";

        Events[i].Condition->PrintCondition();

        cout << endl << "  Actions taken";
        if (Events[i].Delay > 0.0)
          cout << " (after a delay of " << Events[i].Delay << " secs)";
        cout << ":" << endl << "    {";
        for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
          if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
            if (Events[i].SetParam[j] == 0) {
              if (Events[i].SetParamName[j].size() == 0) {
                  std::stringstream error;
              error << fgred << highint << endl
                   << "  An attempt has been made to access a non-existent property" << endl
                   << "  in this event. Please check the property names used, spelling, etc."
                   << reset << endl;
              throw std::runtime_error(error.str());
              } else {
                cout << endl << "      set " << Events[i].SetParamName[j]
                     << " to function value (Late Bound)";
            }
            } else {
            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                 << " to function value";
            }
          } else {
            if (Events[i].SetParam[j] == 0) {
              if (Events[i].SetParamName[j].size() == 0) {
                  std::stringstream error;
              error << fgred << highint << endl
                   << "  An attempt has been made to access a non-existent property" << endl
                   << "  in this event. Please check the property names used, spelling, etc."
                   << reset << endl;
              throw std::runtime_error(error.str());
              } else {
                cout << endl << "      set " << Events[i].SetParamName[j]
                     << " to function value (Late Bound)";
            }
            } else {
            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                 << " to " << Events[i].SetValue[j];
          }
          }

          switch (Events[i].Type[j]) {
          case FG_VALUE:
          case FG_BOOL:
            cout << " (constant";
            break;
          case FG_DELTA:
            cout << " (delta";
            break;
          default:
            cout << " (unspecified type";
          }

          switch (Events[i].Action[j]) {
          case FG_RAMP:
            cout << " via ramp";
            break;
          case FG_STEP:
            cout << " via step)";
            break;
          case FG_EXP:
            cout << " via exponential approach";
            break;
          default:
            cout << " via unspecified action)";
          }

          if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP)
            cout << " with time constant " << Events[i].TC[j] << ")";
        }
        cout << endl << "    }" << endl;

        // Print notifications
        if (Events[i].Notify) {
          if (Events[i].NotifyProperties.size() > 0) {
            if (Events[i].NotifyKML) {
              cout << "  Notifications (KML Format):" << endl << "    {" << endl;
            } else {
              cout << "  Notifications:" << endl << "    {" << endl;
            }
            for (unsigned j=0; j<Events[i].NotifyPropertyNames.size();j++) {
              cout << "      "
                   << Events[i].NotifyPropertyNames[j]
                   << endl;
            }
            cout << "    }" << endl;
          }
        }
        cout << endl;
      }
    }
  }
  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
    if (from == 0) cout << "Instantiated: FGScript" << endl;
    if (from == 1) cout << "Destroyed:    FGScript" << endl;
  }
  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
  }
  if (debug_lvl & 8 ) { // Runtime state variables
  }
  if (debug_lvl & 16) { // Sanity checking
  }
  if (debug_lvl & 64) {
    if (from == 0) { // Constructor
      cout << IdSrc << endl;
      cout << IdHdr << endl;
    }
  }
}