User:Callahanp/Flightgear and Simgear Code/From Command Line to Holding Short

From FlightGear wiki
Jump to navigation Jump to search

Recently I began the effort to fully understand the skills needed to contribute to the Flightgear project's codebase. I know c++ from a course in the early 90's. I'm looking at Kdevelop and QTquick as development tools.

Flightgear Codebase

My area of interest is in Flightgear's code includes:

  • telnet
  • phi
  • reset & re-initialize
  • any method to set or get a property
  • the property tree itself
  • configuration files
  • command line parameters

I'm beginning to look through various parts of the Flightgear code-base to understand how the parts fit together and how supporting libraries are used in the project. I'd like to learn how aircraft data and graphics are integrated into the working program, and how, why and where Nasal scripting is used. To this end, I have

* Built a full debug version of the next branch
* Installed 
** gdbgui
** atom for basic code exploration.

Later I'll try QtCreator


I start by stepping through bootstrap and other modules until flightgear is up and running. I'm making some notes. There are three sections:

  • Path will trace the path through modules that provide significant functionality to the Simulator until the aircraft is shown holding short or parked somewhere. only the module's source path and a brief explanation or list of why it's on the "path".
  • Modules lists all the classes and methods or functions executed on the "path" as well as those that are not executed in the path.
  • Utility Calls will contain notes on various library calls, noting what the call looks like, where the library comes from, what the call does and where else it might be used. These will be functions with a purpose that is not limited to flight simulation.

From Command Line to Holding Short

When you start flight gear, several activities take place

* logging is set up
* command line arguments are checked, read and saved
* a global object is created to hold state and references to managing functions of several types
* a tree of properties is built on the global object
* various static objects are created and initialized
* scenery data is downloaded using terrasync
* airport and aircraft data is scanned and made available
* scenery data is read and made available
* an interpreter is started
* connections to multiplayer servers are made
* a scene is established as a "view" with scenery, Airport data and the Aircraft
* an event loop is started to adjust the view based on changes in controls, weather, aircraft position and attitude
Module Description & Steps
src/Main/bootstrap Main Bootstrap provides the top level of the stack for executing either fgviewerMain or fgMainInit.
  • Enable Floating Point features with InitFPE
  • Set locale settings specific to using C or C++
  • Uninstall if requested
  • Initialize logging
  • Initialize some static objects in OSG to prevent crashes on exit
  • set the std:: terminate function
  • set the atexit function
  • pass control to the viewer with fgViewerMain or initialize using fgMainInit
  • catch throwables and other fatal error conditions, providing appropriate error messages
src/Main/Main fgMainInit( int argc, char **argv )
  • set logging level and enable logging
  • setup globals as an instance of FGGlobals.
    • see src/Main/globals.cxx constructor FGGlobals::FGGlobals()
  • make sure there's a valid FG_HOME directory and set up logging there
  • set the version & log the version, build type and Jenkins or Hudson build id
  • seed the random number generator
  • set up a few things in globals
  • decide if we're using a launcher
    • see below src/Main/Main.cxx Launcher for details
  • set read-only mode when more than one flightgear instance is found
  • load configuration data
    • see src/Main/Main.cxxfgInitConfig
  • initalize aircraft paths
    • see: src/Main/fg_init.cxx fgInitAircraftPaths and fgInitAircraft
  • create an instance of the addon manager
    • see below src/Add-ons/AddonManager.cxx
  • check that the paths are allowed when they come from an untrusted source
  • create an instance of an embedded resource manager
    • see below simgear::EmbeddedResourceManager createInstance
    • and initFlightGearEmbeddedResources
  • get the preferred language and set the locale
  • initialize the windows/graphics environment
    • see viewer/fg_os_osgviewer.cxx fgosinit(int* argc, char** argv)
  • register fgIdleFunction
    • see fgRegisterIdleHandler in Main/fg_os_common.cxx and fgIdleFUnction in Main/main.cxx
  • Initialize sockets
    • simgear::Socket::initSockets()
  • setup alpha channel for Clouds3D
    • fgOSOpenWindow(true /* request stencil buffer */);
    • fgOSResetProperties();
  • fntInit();
  • globals->get_renderer()->preinit();
  • ATIScreenSizeHack
  • fgOutputSettings();
  • disable the screensaver
  • pass control off to the master event handler
    • See viewer/fg_os_osgviewer.cxx fgOSMainLoop() (next)
  • cleanup
    • frame_signal.clear();
    • fgOSCloseWindow();
    • simgear::clearEffectCache();
    • delete globals;
    • globals = NULL;
  • delete the NavCache here. This will cause the destruction of many cached objects (eg, airports, navaids, runways).
    • delete flightgear::NavDataCache::instance();
  • return to bootstrap.cxx Main return result;
viewer/fg_os_osgviewer.cxx fgOSMainLoop()
  • Release the viewer's context at end of frame hint
    • viewer->setReleaseContextAtEndOfFrameHint(false)
  • If the viewer is not realized yet, realize it. We still see nothing in the window
    • viewer->realize()
here's the loop:
  • get the idle handler
    • fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler();
  • run the idle handler It's not clear what this is. It's either fgMainLoop or fgIdleFunction
    • (*idleFunc)()
  • update the screen
    • globals->get_renderer()->update();
  • timestamp the frame
    • viewer->frame( globals->get_sim_time_sec() );
Main/main.cxx fgIdleFunc
  • normal startup has states 0, 2, 3, 4, 5, 7, 8, 9, 10, 900 1000
  • reset startup has 2000, 2005, 2007, 8, 9, 10, 900, 1000
  • state 1000 sets fgMainLoop as the idle function. a reset sets it back to fgIdleFunc
  • state 0 checks the openGL version and sets video options
    • see checkOpenGLVersion() and fgSetVideoOptions()
  • state 2 sets /sim/rendering/initialized true and initializes terrasync with initTerrasync()
  • state 3 loads nav data
    • fgInitNav()
  • state 4 initalizes scenery, but there's not call here
  • state 5
    • initializes some general items with fgInitGeneral()
    • adds the TimeManager
      • globals->add_new_subsystem<TimeManager>(SGSubsystemMgr::INIT)
    • initializes property based commands
      • fgInitCommands(); and fgInitSceneCommands();
    • registers Subsystem Commands
      • flightgear::registerSubsystemCommands(globals->get_commands());
    • initializes the material manager
      • globals->set_matlib( new SGMaterialLib )
      • simgear::SGModelLib::setPanelFunc(FGPanelNode::load)
  • state 7
    • Initializes Position
      • flightgear::initPosition(); and flightgear::initTowerLocationListener();
    • Initializes somethingin SGModelLib
      • simgear::SGModelLib::init(globals->get_fg_root().local8BitStr(), globals->get_props());
    • initializes the time manager instantiated in state 5
      • auto timeManager = globals->get_subsystem<TimeManager>(); timeManager->init();
  • state 8
  • Create subsystems
    • fgCreateSubsystems(isReset)
  • log the time spent creating subsystems
  • state 9
    • bind subsystems
    • globals->get_subsystem_mgr()->bind();
  • state 10
    • initialize subsystems
      • SGSubsystem::InitStatus status = globals->get_subsystem_mgr()->incrementalInit();
    • remains in state 10 until SGSubsystem::INIT_DONE
  • state 900
    • do what needs doing after systems are initialized
      • fgPostInitSubsystems();
  • state 1000
    • setup OpenGl view Parameters
      • globals->get_renderer()->setupView();
    • resize the window to startup size
      • globals->get_renderer()->resize(x,y)
    • unsure what this does
      • WindowSystemAdapter::getWSA()->windows[0]->gc->add(new simgear::canvas::VGInitOperation() )
  • increment /sim/session
  • State 1000 takes a break and continues with the next call
    • sglog().setStartupLoggingEnabled(false)
  • turns off logging for startup
  • sets sim/scenery loaded to false
  • changes the idle function
    • registerMainLoop();
  • state 2000
    • Reset the application
      • fgStartNewReset();
  • state 2005 same as state 5
  • state 2007 same as state 7

Note fgResetIdleState() sets the state to 2000 and re-registers fgIdleFunction as the idle handler.

Main/main.cxx We seem to have arrived. We're at the hold short point.

Minor functions on the Path to Holding Short

sglog().setLogLevels( SG_ALL, SG_INFO )
sglog().setStartupLoggingEnabled(true); || /simgear/debug/logstream.cxx || Pretty obvious what this does. || What does sglog() actually return?
Module Description Steps
src/Main/globals Provides a global object to contain references to objects and data needed in initializing, running and terminating flightgear
  • Provides global access to
    • the property tree
    • subsystem, event, command and resource manager objects and methods
    • position, current view and aircraft orientation data
    • FG_ROOT and FG_HOME directory paths
    • time, comm channel, waypoint, and user settings data
  • uses foreach from the boost library
<boost/foreach.h> Example
<algorithm> Example Example
std::string version(FLIGHTGEAR_VERSION)
sg_srandom_time();
src/Main/Main.cxxfgInitConfig
src/Main/Main.cxx Launcher
src/Add-ons/AddonManager.cxx addons::AddonManager::createInstance()
initFlightGearEmbeddedResources see file build/flightgear/src/EmbeddedResources/FlightGear-resources.cxx,automatically generated by fgrcc
viewer/fg_os_osgviewer.cxx fgosinit(int* argc, char** argv)
Main/fg_os_common.cxx fgRegisterIdleHandler( & fgIdleFunction
detectSIMD() bootstrap.cxx returns true if the cpu supports sse2.
gethostname(_hostname, 256) unistd.h glibc returns the hostname of your computer
signal(SIGPIPE, SIG_IGN) signal.h directs SIGPIPE to the SIG_IGN signal handler - Portability: use sigaction() instead
signal(SIGSEGV, segfault_handler) signal.h Flightgear formats the message with a backtrace and exits with std:abort()
segfault_handler (int signo) bootstrap.cxx
initFPE(flightgear::Options::checkForArg(argc, argv, "enable-fpe")) main/options.cxx
bootstrap.cxx
checks the command line arguments for the enable-fpe option. Calls InitFPE with the result.
see bootstrap.cxx for more details
signal(SIGFPE, handleFPE) signal.h
bootstrap.cxx
We handle Floating Point Exceptions
setlocale(LC_ALL, "")
setlocale(LC_NUMERIC, "C")
setlocale(LC_COLLATE, "C")
return fgUninstall() fg_init.cxx Command line options are checked to determine if uninstall should be called.
sglog() /simgear/debug/logstream.cxx This initializes the log. see logstream.cxx for details
std::set_terminate(fg_terminate); <exception>
bootstrap.cxx
sets the standard template library terminate routine
atexit(fgExitCleanup) stdlib.h
bootstrap.cxx
registers the given function to be called at normal process termination, either via exit(3) or via return from the program's main(). Functions so registered are called in the reverse order of their registration; no arguments are passed
fgviewerMain(argc, argv) flightgear/Viewer/fgviewer.cxx see viewer topics for details. This is called in bootstrap.cxx if the command line arguments include --viewer
fgMainInit(argc, argv) Main/main.cxx Starts to initialize flightgear. This is called in bootstrap.cxx if command line arguments do not contain --viewer
catch block various termination for most or all errors. Read the end of bootstrap.cxx for more information
flightgear::shutdownQtApp() bootstrap
Qt
Done separately from atexit. see bootstrap.cxx for more information
crInstall(&info)
crUninstall()
CrashRpt.h #if defined(HAVE_CRASHRPT). This only happens on windows.