Implementing VNAV support in FlightGear: Difference between revisions

Jump to navigation Jump to search
m
Line 484: Line 484:


=== Parent & Child FDMs ===
=== Parent & Child FDMs ===
The whole VNAV effort would be simplified if we could directly run and query the FDM for some future point in time. This isn't directly supported by JSBSim. However, as a workaround, we could run a "simulation inside the simulation" by instantiating the JSBSim FDM recursively:


As in, run an independent instance of the FDM as part of the FCS, to solve for specific pitch/thrust settings.
The whole VNAV effort would be greatly simplified if we could directly run and query the FDM for some future point in time. This isn't directly supported by JSBSim. However, as a workaround, we could run a "simulation inside the simulation" by instantiating the JSBSim FDM recursively:


And as it turns out, this is another long-standing idea/feature request, i.e. supporting recursion in FDMs and having multiple instances per process.
Instantiating a JSBSim FDM instance is straightforward, thanks to the FGFDMExec class, which manages a single JSBSim instance:
<syntaxhighlight lang="cpp">
FGFDMExec* fdmex = new FGFDMExec(); // (1) Instantiation
bool result = fdmex->LoadModel("737"); // (2) Model loading
fdmex->Run();
</syntaxhighlight>


Meanwhile, since around ~2009, this has been partially implemented in JSBSim, which now contains support for a '''<child>''' FDM element that is mated/coupled to the main FDM. The feature is still considered experimental and unsupported by JSBSim developers, it is also currently disabled by default - especially in FlightGear, where it's causing problems/segfaults. However, we can look at the corresponding code in order to learn how to instantiate an '''FGFDMExec''' instance as part of '''FCS''' system/channel in order to run an identical FDM instance in look-ahead mode, see $JSBSIM_SRC/FGFDMExec.cpp: '''bool FGFDMExec::ReadChild(Element* el)'''
As in, run an independent instance of the FDM as part of the FCS, to solve for certain VNAV constraints (altitude, speed, time) via specific pitch/thrust settings.
 
And as it turns out, this is another long-standing idea/feature request, i.e. supporting recursion in JSBSim FDMs and having multiple instances per process (single-threaded).
 
Meanwhile, since around ~2009, this has been partially implemented in JSBSim, which now contains support for a slaved '''<child>''' FDM element that is mated/coupled to the main FDM. The feature is still considered experimental and unsupported by JSBSim developers, it is also currently disabled by default - especially in FlightGear, where it's causing problems/segfaults.  
 
However, we can look at the corresponding code in order to learn how to instantiate an '''FGFDMExec''' instance as part of '''FCS''' system/channel in order to run an identical FDM instance in look-ahead mode, see $JSBSIM_SRC/FGFDMExec.cpp: '''bool FGFDMExec::ReadChild(Element* el)'''
 
Instantiating a JSBSim FDM instance is straightforward, thanks to the FGFDMExec class, which manages a single JSBSim instance:
<syntaxhighlight lang="cpp">
bool FGFDMExec::ReadChild(Element* el)
{
  // Add a new childData object to the child FDM list
  // Populate that childData element with a new FDMExec object
  // Set the IsChild flag for that FDMExec object
  // Get the aircraft name
  // set debug level to print out no additional data for child objects
  // Load the model given the aircraft name
  // reset debug level to prior setting
 
  string token;
 
  struct childData* child = new childData;
 
  child->exec = new FGFDMExec(Root, FDMctr);
  child->exec->SetChild(true);
 
  string childAircraft = el->GetAttributeValue("name");
  string sMated = el->GetAttributeValue("mated");
  if (sMated == "false") child->mated = false; // child objects are mated by default.
  string sInternal = el->GetAttributeValue("internal");
  if (sInternal == "true") child->internal = true; // child objects are external by default.
 
  child->exec->SetAircraftPath( AircraftPath );
  child->exec->SetEnginePath( EnginePath );
  child->exec->SetSystemsPath( SystemsPath );
  child->exec->LoadModel(childAircraft);
 
  Element* location = el->FindElement("location");
  if (location) {
    child->Loc = location->FindElementTripletConvertTo("IN");
  } else {
    cerr << endl << highint << fgred << "  No location was found for this child object!" << reset << endl;
    exit(-1);
  }
 
  Element* orientation = el->FindElement("orient");
  if (orientation) {
    child->Orient = orientation->FindElementTripletConvertTo("RAD");
  } else if (debug_lvl > 0) {
    cerr << endl << highint << "  No orientation was found for this child object! Assuming 0,0,0." << reset << endl;
  }
 
  ChildFDMList.push_back(child);
 
  return true;
}
 
</syntaxhighlight>


{{cquote|One feature in JSBSim that I began and have not yet finished (pending other things) is a parent/child capability. You can (for instance) load a Mk82 on
{{cquote|One feature in JSBSim that I began and have not yet finished (pending other things) is a parent/child capability. You can (for instance) load a Mk82 on

Navigation menu