Exemplo n.º 1
0
bool FGModel::Load(Element* el, bool preLoad)
{
  FGModelLoader ModelLoader(this);
  Element* document = ModelLoader.Open(el);

  if (!document) return false;

  if (document->GetName() != el->GetName()) {
    cerr << el->ReadFrom()
         << " Read model '" << document->GetName()
         << "' while expecting model '" << el->GetName() << "'" << endl;
    return false;
  }

  bool result = true;

  if (preLoad)
    result = FGModelFunctions::Load(document, PropertyManager);

  if (document != el) {
    el->MergeAttributes(document);

    if (preLoad) {
      // After reading interface properties in a file, read properties in the
      // local model element. This allows general-purpose models to be defined
      // in a file, with overrides or initial loaded constants supplied in the
      // relevant element of the aircraft configuration file.
      LocalProperties.Load(el, PropertyManager, true);
    }

    Element* element = document->FindElement();
    while (element) {
      el->AddChildElement(element);
      element->SetParent(el);
      element = document->FindNextElement();
    }
  }

  return result;
}
Exemplo n.º 2
0
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;
  FGXMLFileRead XMLFileRead;
  Element *document = XMLFileRead.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, and there may be more than one.
    element = document->FindElement("input");
    while (element) {
      if (!static_cast<FGInput*>(Models[eInput])->Load(element))
        return false;

      element = document->FindNextElement("input");
    }

    // Process the output element[s]. This element is OPTIONAL, and there may be
    // more than one.
    element = document->FindElement("output");
    while (element) {
      if (!static_cast<FGOutput*>(Models[eOutput])->Load(element))
        return false;

      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.
      LoadInputs(ePropulsion); // Update propulsion properties for the report.
      Models[ePropulsion]->Run(false);  // Update propulsion properties for the report.
      LoadInputs(eMassBalance); // Update all (one more time) input mass properties for the report.
      Models[eMassBalance]->Run(false);  // Update all (one more time) mass properties for the report.
      ((FGMassBalance*)Models[eMassBalance])->GetMassPropertiesReport(0);

      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 = Root->GetNode();
    BuildPropertyCatalog(&masterPCS);
  }

  return result;
}
Exemplo n.º 3
0
bool FGScript::LoadScript(const string& script, double default_dT,
                          const string& initfile)
{
  string aircraft="", initialize="", prop_name="";
  string notifyPropertyName="";
  Element *element=0, *run_element=0, *event_element=0;
  Element *set_element=0;
  Element *notify_element = 0L, *notify_property_element = 0L;
  double dt = 0.0, value = 0.0;
  FGCondition *newCondition;

  FGXMLFileRead XMLFileRead;
  Element* document = XMLFileRead.LoadXMLDocument(script);

  if (!document) {
    cerr << "File: " << script << " could not be loaded." << endl;
    return false;
  }

  if (document->GetName() != string("runscript")) {
    cerr << "File: " << script << " is not a script file" << endl;
    return false;
  }

  ScriptName = document->GetAttributeValue("name");

 // First, find "run" element and set delta T

  run_element = document->FindElement("run");

  if (!run_element) {
    cerr << "No \"run\" element found in script." << endl;
    return false;
  }

  // Set sim timing

  if (run_element->HasAttribute("start"))
    StartTime = run_element->GetAttributeValueAsNumber("start");
  else
    StartTime = 0.0;
  FDMExec->Setsim_time(StartTime);
  if (run_element->HasAttribute("end")) {
    EndTime   = run_element->GetAttributeValueAsNumber("end");
  } else {
    cerr << "An end time (duration) for the script must be specified in the script <run> element." << endl;
    return false;
  }

  // Make sure that the desired time is reached and executed.
  EndTime += 0.99*FDMExec->GetDeltaT();

  if (default_dT == 0.0)
    dt = run_element->GetAttributeValueAsNumber("dt");
  else {
    dt = default_dT;
    cout << endl << "Overriding simulation step size from the command line. New step size is: "
         << default_dT << " seconds (" << 1/default_dT << " Hz)" << endl << endl;
  }

  FDMExec->Setdt(dt);
  
  // read aircraft and initialization files

  element = document->FindElement("use");
  if (element) {
    aircraft = element->GetAttributeValue("aircraft");
    if (!aircraft.empty()) {
      if (!FDMExec->LoadModel(aircraft))
        return false;
    } else {
      cerr << "Aircraft must be specified in use element." << endl;
      return false;
    }

    if (initfile.empty()) {
      initialize = element->GetAttributeValue("initialize");
      if (initialize.empty()) {
        cerr << "Initialization file must be specified in use element." << endl;
        return false;
      }
    } else {
      cout << endl << "The initialization file specified in the script file (" << initialize
                   << ") has been overridden with a specified file (" << initfile << ")." << endl;
      initialize = initfile;
    }

  } else {
    cerr << "No \"use\" directives in the script file." << endl;
    return false;
  }

  FGInitialCondition *IC=FDMExec->GetIC();
  if ( ! IC->Load( initialize )) {
    cerr << "Initialization unsuccessful" << endl;
    return false;
  }

  // Now, read input spec if given.
  element = document->FindElement("input");
  while (element) {
    if (!FDMExec->GetInput()->Load(element))
      return false;
 
    element = document->FindNextElement("input");
  }

  // Now, read output spec if given.
  element = document->FindElement("output");
  while (element) {
    if (!FDMExec->GetOutput()->Load(element))
      return false;
 
    element = document->FindNextElement("output");
  }

  // Read local property/value declarations
  int saved_debug_lvl = debug_lvl;
  debug_lvl = 0; // Disable messages
  LocalProperties.Load(run_element, PropertyManager, true);
  debug_lvl = saved_debug_lvl;

  // Read "events" from script

  event_element = run_element->FindElement("event");
  while (event_element) { // event processing

    // Create the event structure
    struct event *newEvent = new struct event();

    // Retrieve the event name if given
    newEvent->Name = event_element->GetAttributeValue("name");

    // Is this event persistent? That is, does it execute every time the
    // condition triggers to true, or does it execute as a one-shot event, only?
    if (event_element->GetAttributeValue("persistent") == string("true")) {
      newEvent->Persistent = true;
    }

    // Does this event execute continuously when triggered to true?
    if (event_element->GetAttributeValue("continuous") == string("true")) {
      newEvent->Continuous = true;
    }

    // Process the conditions
    Element* condition_element = event_element->FindElement("condition");
    if (condition_element != 0) {
      try {
        newCondition = new FGCondition(condition_element, PropertyManager);
      } catch(string& str) {
        cout << endl << fgred << str << reset << endl << endl;
        delete newEvent;
        return false;
      }
      newEvent->Condition = newCondition;
    } else {
      cerr << "No condition specified in script event " << newEvent->Name << endl;
      delete newEvent;
      return false;
    }

    // Is there a delay between the time this event is triggered, and when the event
    // actions are executed?

    Element* delay_element = event_element->FindElement("delay");
    if (delay_element)
      newEvent->Delay = event_element->FindElementValueAsNumber("delay");
    else
      newEvent->Delay = 0.0;

    // Notify about when this event is triggered?
    if ((notify_element = event_element->FindElement("notify")) != 0) {
      if (notify_element->HasAttribute("format")) {
        if (notify_element->GetAttributeValue("format") == "kml") newEvent->NotifyKML = true;
      }
      newEvent->Notify = true;
      // Check here for new <description> tag that gets echoed
      string notify_description = notify_element->FindElementValue("description");
      if (!notify_description.empty()) {
        newEvent->Description = notify_description;
      }
      notify_property_element = notify_element->FindElement("property");
      while (notify_property_element) {
        notifyPropertyName = notify_property_element->GetDataLine();

        newEvent->NotifyPropertyNames.push_back(notifyPropertyName);
        newEvent->NotifyProperties.push_back(0);
          string caption_attribute = notify_property_element->GetAttributeValue("caption");
          if (caption_attribute.empty()) {
            newEvent->DisplayString.push_back(notifyPropertyName);
          } else {
            newEvent->DisplayString.push_back(caption_attribute);
          }

        notify_property_element = notify_element->FindNextElement("property");
      }
    }

    // Read set definitions (these define the actions to be taken when the event is triggered).
    set_element = event_element->FindElement("set");
    while (set_element) {
      prop_name = set_element->GetAttributeValue("name");
      if (PropertyManager->HasNode(prop_name)) {
        newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
      } else {
        newEvent->SetParam.push_back( 0L );
      }
      newEvent->SetParamName.push_back( prop_name );

      //Todo - should probably do some safety checking here to make sure one or the other
      //of value or function is specified.
      if (!set_element->GetAttributeValue("value").empty()) {
        value = set_element->GetAttributeValueAsNumber("value");
        newEvent->Functions.push_back((FGFunction*)0L);
      } else if (set_element->FindElement("function")) {
        value = 0.0;
        newEvent->Functions.push_back(new FGFunction(PropertyManager, set_element->FindElement("function")));
      }
      newEvent->SetValue.push_back(value);
      newEvent->OriginalValue.push_back(0.0);
      newEvent->newValue.push_back(0.0);
      newEvent->ValueSpan.push_back(0.0);
      string tempCompare = set_element->GetAttributeValue("type");
      if      (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA);
      else if (to_lower(tempCompare).find("bool") != string::npos)  newEvent->Type.push_back(FG_BOOL);
      else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE);
      else                                newEvent->Type.push_back(FG_VALUE); // DEFAULT
      tempCompare = set_element->GetAttributeValue("action");
      if      (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP);
      else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP);
      else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP);
      else                               newEvent->Action.push_back(FG_STEP); // DEFAULT

      if (!set_element->GetAttributeValue("tc").empty())
        newEvent->TC.push_back(set_element->GetAttributeValueAsNumber("tc"));
      else
        newEvent->TC.push_back(1.0); // DEFAULT

      newEvent->Transiting.push_back(false);

      set_element = event_element->FindNextElement("set");
    }
    Events.push_back(*newEvent);
    delete newEvent;

    event_element = run_element->FindNextElement("event");
  }

  Debug(4);

  return true;
}