bool FGOutput::SetDirectivesFile(const std::string& fname) { FGXMLFileRead XMLFile; Element* document = XMLFile.LoadXMLDocument(fname); bool result = Load(document); if (!result) cerr << endl << "Aircraft output element has problems in file " << fname << endl; return result; }
Element_ptr FGModelLoader::Open(Element *el) { Element_ptr document = el; string fname = el->GetAttributeValue("file"); if (!fname.empty()) { FGXMLFileRead XMLFileRead; string file; try { file = model->FindFullPathName(fname); } catch(string& e) { cerr << endl << el->ReadFrom() << "Could not open file: " << e << endl; return NULL; } if (CachedFiles.find(file) != CachedFiles.end()) document = CachedFiles[file]; else { document = XMLFileRead.LoadXMLDocument(file); if (document == 0L) { cerr << endl << el->ReadFrom() << "Could not open file: " << file << endl; return NULL; } CachedFiles[file] = document; } if (document->GetName() != el->GetName()) { document->SetParent(el); el->AddChildElement(document); } } return document; }
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; }
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; }