1
0
Fork 0
flightgear/src/Main/fg_init.cxx

1927 lines
63 KiB
C++
Raw Normal View History

2001-07-02 22:14:09 +00:00
// fg_init.cxx -- Flight Gear top level initialization routines
//
// Written by Curtis Olson, started August 1997.
//
// Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//
// $Id$
1997-08-23 01:46:20 +00:00
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
// For BC 5.01 this must be included before OpenGL includes.
2001-03-23 22:42:49 +00:00
#ifdef SG_MATH_EXCEPTION_CLASH
# include <math.h>
#endif
1997-08-23 01:46:20 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strcmp()
#if defined( unix ) || defined( __CYGWIN__ )
# include <unistd.h> // for gethostname()
#endif
// work around a stdc++ lib bug in some versions of linux, but doesn't
// seem to hurt to have this here for all versions of Linux.
#ifdef linux
# define _G_NO_EXTERN_TEMPLATES
#endif
2000-02-15 03:30:01 +00:00
#include <simgear/compiler.h>
#include STL_STRING
1997-08-23 01:46:20 +00:00
2000-02-15 03:30:01 +00:00
#include <simgear/constants.h>
2000-02-16 23:01:03 +00:00
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/structure/event_mgr.hxx>
2000-02-16 23:01:03 +00:00
#include <simgear/math/point3d.hxx>
#include <simgear/math/polar3d.hxx>
2000-09-27 20:16:22 +00:00
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/interpolator.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/timing/lowleveltime.h>
2000-02-15 03:30:01 +00:00
1998-10-17 01:33:52 +00:00
#include <Aircraft/aircraft.hxx>
#include <Aircraft/replay.hxx>
#include <Airports/apt_loader.hxx>
#include <Airports/runways.hxx>
1998-08-25 16:59:08 +00:00
#include <Airports/simple.hxx>
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
#include <AIModel/AIManager.hxx>
#include <ATC/ATCdisplay.hxx>
#include <ATC/ATCmgr.hxx>
#include <ATC/AIMgr.hxx>
#include <Autopilot/auto_gui.hxx>
2004-01-31 19:47:45 +00:00
#include <Autopilot/route_mgr.hxx>
#include <Autopilot/xmlauto.hxx>
#include <Cockpit/cockpit.hxx>
#include <Cockpit/panel.hxx>
#include <Cockpit/panel_io.hxx>
#ifdef ENABLE_SP_FMDS
#include <FDM/SP/ADA.hxx>
#include <FDM/SP/ACMS.hxx>
#endif
1999-10-15 22:21:09 +00:00
#include <FDM/Balloon.h>
#include <FDM/ExternalNet/ExternalNet.hxx>
2003-03-03 04:34:27 +00:00
#include <FDM/ExternalPipe/ExternalPipe.hxx>
2002-02-25 03:22:03 +00:00
#include <FDM/JSBSim/JSBSim.hxx>
#include <FDM/LaRCsim/LaRCsim.hxx>
1999-10-14 01:53:43 +00:00
#include <FDM/MagicCarpet.hxx>
#include <FDM/UFO.hxx>
#include <FDM/NullFDM.hxx>
#include <FDM/YASim/YASim.hxx>
#include <GUI/new_gui.hxx>
#include <Include/general.hxx>
#include <Input/input.hxx>
#include <Instrumentation/instrument_mgr.hxx>
#include <Model/acmodel.hxx>
#include <AIModel/submodel.hxx>
#include <AIModel/AIManager.hxx>
#include <Navaids/navdb.hxx>
#include <Navaids/navlist.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include <Scripting/NasalSys.hxx>
#include <Sound/fg_fx.hxx>
#include <Sound/beacon.hxx>
#include <Sound/morse.hxx>
#include <Systems/system_mgr.hxx>
#include <Time/light.hxx>
#include <Time/sunsolver.hxx>
#include <Time/tmp.hxx>
#include <Traffic/TrafficMgr.hxx>
#ifdef FG_MPLAYER_AS
#include <MultiPlayer/multiplaymgr.hxx>
#endif
2004-03-16 20:19:07 +00:00
#include <Environment/environment_mgr.hxx>
1997-08-23 01:46:20 +00:00
#include "fg_init.hxx"
1999-11-19 02:10:24 +00:00
#include "fg_io.hxx"
#include "fg_commands.hxx"
#include "fg_props.hxx"
#include "options.hxx"
2000-07-08 06:29:19 +00:00
#include "globals.hxx"
2002-03-12 16:29:00 +00:00
#include "logger.hxx"
#include "viewmgr.hxx"
#if defined(FX) && defined(XMESA)
#include <GL/xmesa.h>
#endif
2001-03-23 22:59:18 +00:00
SG_USING_STD(string);
class Sound;
extern const char *default_root;
float init_volume;
// Scan the command line options for the specified option and return
// the value.
static string fgScanForOption( const string& option, int argc, char **argv ) {
int i = 1;
SG_LOG(SG_GENERAL, SG_INFO, "Scanning command line for: " << option );
int len = option.length();
while ( i < argc ) {
SG_LOG( SG_GENERAL, SG_DEBUG, "argv[" << i << "] = " << argv[i] );
string arg = argv[i];
if ( arg.find( option ) == 0 ) {
return arg.substr( len );
}
i++;
}
return "";
}
// Scan the user config files for the specified option and return
// the value.
static string fgScanForOption( const string& option, const string& path ) {
sg_gzifstream in( path );
if ( !in.is_open() ) {
return "";
}
SG_LOG( SG_GENERAL, SG_INFO, "Scanning " << path << " for: " << option );
int len = option.length();
in >> skipcomment;
#ifndef __MWERKS__
while ( ! in.eof() ) {
#else
char c = '\0';
while ( in.get(c) && c != '\0' ) {
in.putback(c);
#endif
string line;
#if defined( macintosh )
getline( in, line, '\r' );
#else
getline( in, line, '\n' );
#endif
// catch extraneous (DOS) line ending character
if ( line[line.length() - 1] < 32 ) {
line = line.substr( 0, line.length()-1 );
}
if ( line.find( option ) == 0 ) {
return line.substr( len );
}
in >> skipcomment;
}
return "";
}
// Read in configuration (files and command line options) but only set
// fg_root
bool fgInitFGRoot ( int argc, char **argv ) {
string root;
char* envp;
// First parse command line options looking for --fg-root=, this
// will override anything specified in a config file
root = fgScanForOption( "--fg-root=", argc, argv);
#if defined( unix ) || defined( __CYGWIN__ )
// Next check home directory for .fgfsrc.hostname file
if ( root.empty() ) {
envp = ::getenv( "HOME" );
if ( envp != NULL ) {
SGPath config( envp );
config.append( ".fgfsrc" );
char name[256];
gethostname( name, 256 );
config.concat( "." );
config.concat( name );
root = fgScanForOption( "--fg-root=", config.str() );
}
}
#endif
// Next check home directory for .fgfsrc file
if ( root.empty() ) {
envp = ::getenv( "HOME" );
if ( envp != NULL ) {
SGPath config( envp );
config.append( ".fgfsrc" );
root = fgScanForOption( "--fg-root=", config.str() );
}
}
// Next check if fg-root is set as an env variable
if ( root.empty() ) {
envp = ::getenv( "FG_ROOT" );
if ( envp != NULL ) {
root = envp;
}
}
// Otherwise, default to a random compiled-in location if we can't
// find fg-root any other way.
if ( root.empty() ) {
#if defined( __CYGWIN__ )
root = "/FlightGear";
#elif defined( WIN32 )
root = "\\FlightGear";
#elif defined(OSX_BUNDLE)
/* the following code looks for the base package directly inside
the application bundle. This can be changed fairly easily by
fiddling with the code below. And yes, I know it's ugly and verbose.
*/
CFBundleRef appBundle = CFBundleGetMainBundle();
CFURLRef appUrl = CFBundleCopyBundleURL(appBundle);
CFRelease(appBundle);
// look for a 'data' subdir directly inside the bundle : is there
// a better place? maybe in Resources? I don't know ...
CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent(NULL, appUrl, CFSTR("data"), true);
// now convert down to a path, and the a c-string
CFStringRef path = CFURLCopyFileSystemPath(dataDir, kCFURLPOSIXPathStyle);
root = CFStringGetCStringPtr(path, CFStringGetSystemEncoding());
// tidy up.
CFRelease(appBundle);
CFRelease(dataDir);
CFRelease(path);
#else
root = PKGLIBDIR;
#endif
}
2001-03-24 06:03:11 +00:00
SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root );
globals->set_fg_root(root);
return true;
}
// Read in configuration (files and command line options) but only set
// aircraft
bool fgInitFGAircraft ( int argc, char **argv ) {
string aircraft;
char* envp;
// First parse command line options looking for --aircraft=, this
// will override anything specified in a config file
aircraft = fgScanForOption( "--aircraft=", argc, argv );
#if defined( unix ) || defined( __CYGWIN__ )
// Next check home directory for .fgfsrc.hostname file
if ( aircraft.empty() ) {
envp = ::getenv( "HOME" );
if ( envp != NULL ) {
SGPath config( envp );
config.append( ".fgfsrc" );
char name[256];
gethostname( name, 256 );
config.concat( "." );
config.concat( name );
aircraft = fgScanForOption( "--aircraft=", config.str() );
}
}
#endif
// Next check home directory for .fgfsrc file
if ( aircraft.empty() ) {
envp = ::getenv( "HOME" );
if ( envp != NULL ) {
SGPath config( envp );
config.append( ".fgfsrc" );
aircraft = fgScanForOption( "--aircraft=", config.str() );
}
}
2005-01-29 13:12:34 +00:00
if ( aircraft.empty() ) {
// Check for $fg_root/system.fgfsrc
SGPath sysconf( globals->get_fg_root() );
sysconf.append( "system.fgfsrc" );
aircraft = fgScanForOption( "--aircraft=", sysconf.str() );
}
// if an aircraft was specified, set the property name
if ( !aircraft.empty() ) {
SG_LOG(SG_INPUT, SG_INFO, "aircraft = " << aircraft );
fgSetString("/sim/aircraft", aircraft.c_str() );
} else {
SG_LOG(SG_INPUT, SG_INFO, "No user specified aircraft, using default" );
}
return true;
}
// Return the current base package version
string fgBasePackageVersion() {
SGPath base_path( globals->get_fg_root() );
base_path.append("version");
sg_gzifstream in( base_path.str() );
if ( !in.is_open() ) {
SGPath old_path( globals->get_fg_root() );
old_path.append( "Thanks" );
sg_gzifstream old( old_path.str() );
if ( !old.is_open() ) {
return "[none]";
} else {
return "[old version]";
}
}
string version;
in >> version;
return version;
}
// Initialize the localization
SGPropertyNode *fgInitLocale(const char *language) {
SGPropertyNode *c_node = NULL, *d_node = NULL;
SGPropertyNode *intl = fgGetNode("/sim/intl");
SG_LOG(SG_GENERAL, SG_INFO, "Selecting language: " << language );
// localization not defined
if (!intl)
return NULL;
//
// Select the proper language from the list
//
vector<SGPropertyNode_ptr> locale = intl->getChildren("locale");
for (unsigned int i = 0; i < locale.size(); i++) {
vector<SGPropertyNode_ptr> lang = locale[i]->getChildren("lang");
for (unsigned int j = 0; j < lang.size(); j++) {
if (!strcmp(lang[j]->getStringValue(), language)) {
c_node = locale[i];
break;
}
}
}
// Get the defaults
d_node = intl->getChild("locale");
if (!c_node)
c_node = d_node;
// Check for localized font
SGPropertyNode *font_n = c_node->getNode("font", true);
if ( !strcmp(font_n->getStringValue(), "") )
font_n->setStringValue(d_node->getStringValue("font", "typewriter.txf"));
//
// Load the default strings
//
SGPath d_path( globals->get_fg_root() );
const char *d_path_str = d_node->getStringValue("strings");
if (!d_path_str) {
SG_LOG(SG_GENERAL, SG_ALERT, "Incorrect path in configuration file.");
return NULL;
}
d_path.append(d_path_str);
SG_LOG(SG_GENERAL, SG_INFO, "Reading localized strings from "
<< d_path.str());
SGPropertyNode *strings = c_node->getNode("strings");
try {
readProperties(d_path.str(), strings);
} catch (const sg_exception &e) {
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to read the localized strings");
return NULL;
}
//
// Load the language specific strings
//
if (c_node != d_node) {
SGPath c_path( globals->get_fg_root() );
const char *c_path_str = c_node->getStringValue("strings");
if (!c_path_str) {
SG_LOG(SG_GENERAL, SG_ALERT, "Incorrect path in configuration file.");
return NULL;
}
c_path.append(c_path_str);
SG_LOG(SG_GENERAL, SG_INFO, "Reading localized strings from "
<< c_path.str());
try {
readProperties(c_path.str(), strings);
} catch (const sg_exception &e) {
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to read the localized strings");
return NULL;
}
}
return c_node;
}
// Initialize the localization routines
bool fgDetectLanguage() {
char *language = ::getenv("LANG");
if (language == NULL) {
SG_LOG(SG_GENERAL, SG_INFO, "Unable to detect the language" );
language = "C";
}
SGPropertyNode *locale = fgInitLocale(language);
if (!locale) {
SG_LOG(SG_GENERAL, SG_ALERT,
"No internationalization settings specified in preferences.xml" );
return false;
}
globals->set_locale( locale );
return true;
}
// Attempt to locate and parse the various non-XML config files in order
// from least precidence to greatest precidence
static void
do_options (int argc, char ** argv)
{
// Check for $fg_root/system.fgfsrc
SGPath config( globals->get_fg_root() );
config.append( "system.fgfsrc" );
fgParseOptions(config.str());
#if defined( unix ) || defined( __CYGWIN__ )
char name[256];
// Check for $fg_root/system.fgfsrc.hostname
gethostname( name, 256 );
config.concat( "." );
config.concat( name );
fgParseOptions(config.str());
#endif
// Check for ~/.fgfsrc
char* envp = ::getenv( "HOME" );
if ( envp != NULL ) {
config.set( envp );
config.append( ".fgfsrc" );
fgParseOptions(config.str());
}
#if defined( unix ) || defined( __CYGWIN__ )
// Check for ~/.fgfsrc.hostname
gethostname( name, 256 );
config.concat( "." );
config.concat( name );
fgParseOptions(config.str());
#endif
// Parse remaining command line options
// These will override anything specified in a config file
fgParseArgs(argc, argv);
}
static string fgFindAircraftPath( const SGPath &path, const string &aircraft ) {
ulDirEnt* dire;
ulDir *dirp = ulOpenDir(path.str().c_str());
if (dirp == NULL) {
cerr << "Unable to open aircraft directory '" << path.str() << '\'' << endl;
exit(-1);
}
while ((dire = ulReadDir(dirp)) != NULL) {
if (dire->d_isdir) {
if ( strcmp("CVS", dire->d_name) && strcmp(".", dire->d_name)
&& strcmp("..", dire->d_name) )
{
SGPath next = path;
next.append(dire->d_name);
string result = fgFindAircraftPath( next, aircraft );
if ( ! result.empty() ) {
return result;
}
}
} else if ( !strcmp(dire->d_name, aircraft.c_str()) ) {
return path.str();
}
}
ulCloseDir(dirp);
return "";
}
// Read in configuration (file and command line)
bool fgInitConfig ( int argc, char **argv ) {
// First, set some sane default values
fgSetDefaults();
// Read global preferences from $FG_ROOT/preferences.xml
SG_LOG(SG_INPUT, SG_INFO, "Reading global preferences");
fgLoadProps("preferences.xml", globals->get_props());
SG_LOG(SG_INPUT, SG_INFO, "Finished Reading global preferences");
// Detect the required language as early as possible
if ( !fgDetectLanguage() ) {
return false;
}
// Scan user config files and command line for a specified aircraft.
fgInitFGAircraft(argc, argv);
string aircraft = fgGetString( "/sim/aircraft", "" );
if ( aircraft.size() > 0 ) {
SGPath aircraft_search( globals->get_fg_root() );
aircraft_search.append( "Aircraft" );
string aircraft_set = aircraft + "-set.xml";
string result = fgFindAircraftPath( aircraft_search, aircraft_set );
if ( !result.empty() ) {
fgSetString( "/sim/aircraft-dir", result.c_str() );
SGPath full_name( result );
full_name.append( aircraft_set );
SG_LOG(SG_INPUT, SG_INFO, "Reading default aircraft: " << aircraft
<< " from " << full_name.str());
try {
readProperties( full_name.str(), globals->get_props() );
} catch ( const sg_exception &e ) {
string message = "Error reading default aircraft: ";
message += e.getFormattedMessage();
SG_LOG(SG_INPUT, SG_ALERT, message);
exit(2);
}
} else {
SG_LOG( SG_INPUT, SG_ALERT, "Cannot find specified aircraft: "
<< aircraft );
return false;
}
} else {
SG_LOG( SG_INPUT, SG_ALERT, "No default aircraft specified" );
}
// parse options after loading aircraft to ensure any user
// overrides of defaults are honored.
do_options(argc, argv);
return true;
}
// find basic airport location info from airport database
bool fgFindAirportID( const string& id, FGAirport *a ) {
David Luff: Attached is a patch to the airport data storage that I would like committed after review if acceptable. Currently the storage of airports mapped by ID is by locally created objects - about 12 Meg or so created on the stack if I am not mistaken. I've changed this to creating the airports on the heap, and storing pointers to them - see FGAirportList.add(...) in src/Airports/simple.cxx. I believe that this is probably better practice, and it's certainly cured some strange problems I was seeing when accessing the airport data with some gps unit code. Changes resulting from this have cascaded through a few files which access the data - 11 files are modified in all. Melchior and Durk - you might want to test this and shout if there are problems since the metar and traffic code are probably the biggest users of the airport data. I've also added a fuzzy search function that returns the next matching airport code in ASCII sequence in order to support gps units that have autocompletion of partially entered codes. More generally, the simple airport class seems to have grown a lot with the fairly recent addition of the parking, runway preference and schedule time code. It is no longer just an encapsulation of the global airport data file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!). My personal opinion is that we should look to just store the basic data in apt.dat for all global airports in a simple airport class, plus globally needed data (metar available?), and then have the traffic, AI and ATC subsystems create more advanced airports for themselves as needed in the area of interest. Once a significant number of airports worldwide have ground networks and parking defined, it will be impractical and unnecessary to store them all in memory. That's just a thought for the future though.
2005-09-20 20:26:57 +00:00
const FGAirport* result;
if ( id.length() ) {
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
2003-08-28 20:53:08 +00:00
result = globals->get_airports()->search( id );
David Luff: Attached is a patch to the airport data storage that I would like committed after review if acceptable. Currently the storage of airports mapped by ID is by locally created objects - about 12 Meg or so created on the stack if I am not mistaken. I've changed this to creating the airports on the heap, and storing pointers to them - see FGAirportList.add(...) in src/Airports/simple.cxx. I believe that this is probably better practice, and it's certainly cured some strange problems I was seeing when accessing the airport data with some gps unit code. Changes resulting from this have cascaded through a few files which access the data - 11 files are modified in all. Melchior and Durk - you might want to test this and shout if there are problems since the metar and traffic code are probably the biggest users of the airport data. I've also added a fuzzy search function that returns the next matching airport code in ASCII sequence in order to support gps units that have autocompletion of partially entered codes. More generally, the simple airport class seems to have grown a lot with the fairly recent addition of the parking, runway preference and schedule time code. It is no longer just an encapsulation of the global airport data file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!). My personal opinion is that we should look to just store the basic data in apt.dat for all global airports in a simple airport class, plus globally needed data (metar available?), and then have the traffic, AI and ATC subsystems create more advanced airports for themselves as needed in the area of interest. Once a significant number of airports worldwide have ground networks and parking defined, it will be impractical and unnecessary to store them all in memory. That's just a thought for the future though.
2005-09-20 20:26:57 +00:00
if ( result == NULL ) {
SG_LOG( SG_GENERAL, SG_ALERT,
David Luff: Attached is a patch to the airport data storage that I would like committed after review if acceptable. Currently the storage of airports mapped by ID is by locally created objects - about 12 Meg or so created on the stack if I am not mistaken. I've changed this to creating the airports on the heap, and storing pointers to them - see FGAirportList.add(...) in src/Airports/simple.cxx. I believe that this is probably better practice, and it's certainly cured some strange problems I was seeing when accessing the airport data with some gps unit code. Changes resulting from this have cascaded through a few files which access the data - 11 files are modified in all. Melchior and Durk - you might want to test this and shout if there are problems since the metar and traffic code are probably the biggest users of the airport data. I've also added a fuzzy search function that returns the next matching airport code in ASCII sequence in order to support gps units that have autocompletion of partially entered codes. More generally, the simple airport class seems to have grown a lot with the fairly recent addition of the parking, runway preference and schedule time code. It is no longer just an encapsulation of the global airport data file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!). My personal opinion is that we should look to just store the basic data in apt.dat for all global airports in a simple airport class, plus globally needed data (metar available?), and then have the traffic, AI and ATC subsystems create more advanced airports for themselves as needed in the area of interest. Once a significant number of airports worldwide have ground networks and parking defined, it will be impractical and unnecessary to store them all in memory. That's just a thought for the future though.
2005-09-20 20:26:57 +00:00
"Failed to find " << id << " in apt.dat.gz" );
return false;
}
} else {
return false;
}
David Luff: Attached is a patch to the airport data storage that I would like committed after review if acceptable. Currently the storage of airports mapped by ID is by locally created objects - about 12 Meg or so created on the stack if I am not mistaken. I've changed this to creating the airports on the heap, and storing pointers to them - see FGAirportList.add(...) in src/Airports/simple.cxx. I believe that this is probably better practice, and it's certainly cured some strange problems I was seeing when accessing the airport data with some gps unit code. Changes resulting from this have cascaded through a few files which access the data - 11 files are modified in all. Melchior and Durk - you might want to test this and shout if there are problems since the metar and traffic code are probably the biggest users of the airport data. I've also added a fuzzy search function that returns the next matching airport code in ASCII sequence in order to support gps units that have autocompletion of partially entered codes. More generally, the simple airport class seems to have grown a lot with the fairly recent addition of the parking, runway preference and schedule time code. It is no longer just an encapsulation of the global airport data file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!). My personal opinion is that we should look to just store the basic data in apt.dat for all global airports in a simple airport class, plus globally needed data (metar available?), and then have the traffic, AI and ATC subsystems create more advanced airports for themselves as needed in the area of interest. Once a significant number of airports worldwide have ground networks and parking defined, it will be impractical and unnecessary to store them all in memory. That's just a thought for the future though.
2005-09-20 20:26:57 +00:00
*a = *result;
2003-08-28 20:53:08 +00:00
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("
<< a->getLongitude() << ", "
<< a->getLatitude() << ")" );
return true;
}
// get airport elevation
static double fgGetAirportElev( const string& id ) {
FGAirport a;
// double lon, lat;
SG_LOG( SG_GENERAL, SG_INFO,
"Finding elevation for airport: " << id );
if ( fgFindAirportID( id, &a ) ) {
return a.getElevation();
} else {
return -9999.0;
}
}
#if 0
//
// This function is never used, but maybe useful in the future ???
//
// Preset lon/lat given an airport id
static bool fgSetPosFromAirportID( const string& id ) {
FGAirport a;
// double lon, lat;
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO,
"Attempting to set starting position from airport code " << id );
if ( fgFindAirportID( id, &a ) ) {
// presets
fgSetDouble("/sim/presets/longitude-deg", a.longitude );
fgSetDouble("/sim/presets/latitude-deg", a.latitude );
// other code depends on the actual postition being set so set
// that as well
fgSetDouble("/position/longitude-deg", a.longitude );
fgSetDouble("/position/latitude-deg", a.latitude );
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is (" << a.longitude
<< ", " << a.latitude << ")" );
return true;
} else {
return false;
}
}
#endif
// Set current tower position lon/lat given an airport id
static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) {
FGAirport a;
// tower height hard coded for now...
float towerheight=50.0f;
// make a little off the heading for 1 runway airports...
float fudge_lon = fabs(sin(hdg)) * .003f;
float fudge_lat = .003f - fudge_lon;
if ( fgFindAirportID( id, &a ) ) {
fgSetDouble("/sim/tower/longitude-deg", a.getLongitude() + fudge_lon);
fgSetDouble("/sim/tower/latitude-deg", a.getLatitude() + fudge_lat);
fgSetDouble("/sim/tower/altitude-ft", a.getElevation() + towerheight);
return true;
} else {
return false;
}
}
struct FGTowerLocationListener : SGPropertyChangeListener {
void valueChanged(SGPropertyNode* node) {
const double hdg = fgGetDouble( "/orientation/heading-deg", 0);
const string id(node->getStringValue());
fgSetTowerPosFromAirportID(id, hdg);
}
};
static void fgInitTowerLocationListener() {
fgGetNode("/sim/tower/airport-id", true)
->addChangeListener( new FGTowerLocationListener() );
}
// Set current_options lon/lat given an airport id and heading (degrees)
static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
FGRunway r;
if ( id.length() ) {
// set initial position from runway and heading
SG_LOG( SG_GENERAL, SG_INFO,
"Attempting to set starting position from airport code "
<< id << " heading " << tgt_hdg );
if ( ! globals->get_runways()->search( id, (int)tgt_hdg, &r ) ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Failed to find a good runway for " << id << '\n' );
return false;
}
} else {
return false;
}
double lat2, lon2, az2;
double heading = r._heading;
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO,
"runway = " << r._lon << ", " << r._lat
<< " length = " << r._length * SG_FEET_TO_METER
<< " heading = " << azimuth );
geo_direct_wgs_84 ( 0, r._lat, r._lon, azimuth,
r._length * SG_FEET_TO_METER * 0.5 - 5.0,
&lat2, &lon2, &az2 );
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) {
double olat, olon;
double odist = fgGetDouble("/sim/presets/offset-distance");
odist *= SG_NM_TO_METER;
double oaz = azimuth;
if ( fabs(fgGetDouble("/sim/presets/offset-azimuth")) > SG_EPSILON ) {
oaz = fgGetDouble("/sim/presets/offset-azimuth") + 180;
heading = tgt_hdg;
}
while ( oaz >= 360.0 ) { oaz -= 360.0; }
geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 );
lat2=olat;
lon2=olon;
}
// presets
fgSetDouble("/sim/presets/longitude-deg", lon2 );
fgSetDouble("/sim/presets/latitude-deg", lat2 );
fgSetDouble("/sim/presets/heading-deg", heading );
// other code depends on the actual values being set ...
** Properties Renamed - /autopilot/locks/nav1 => /autopilot/locks/nav[0] - /autopilot/settings/altitude += "-ft" - /autopilot/settings/climb-rate += "-fpm" - /autopilot/settings/heading-bug += "-deg" - /consumables/fuel/tank1/level => /consumables/fuel/tank[0]/level-gal_us - /consumables/fuel/tank2/level => /consumables/fuel/tank[1]/level-gal_us - /engines/engine0/cht => /engines/engine[0]/cht-degf - /engines/engine0/egt => /engines/engine[0]/egt-degf - /engines/engine0/fuel-flow => /engines/engine[0]/fuel-flow-gph - /engines/engine0/mp => /engines/engine[0]/mp-osi - /engines/engine0/rpm => /engines/engine[0]/rpm - /environment/clouds/altitude += "-ft" - /environment/magnetic-dip += "-deg" - /environment/magnetic-varation += "-deg" - /environment/visibility += "-m" - /environment/wind-down += "-fps" - /environment/wind-east += "-fps" - /environment/wind-north += "-fps" - /orientation/heading += "-deg" - /orientation/heading-magnetic += "-deg" - /orientation/pitch += "-deg" - /orientation/roll += "-deg" - /position/altitude += "-ft" - /position/altitude-agl += "-ft" - /position/latitude += "-deg" - /position/longitude += "-deg" - /radios/adf/frequencies/selected += "-khz" - /radios/adf/frequencies/standby += "-khz" - /radios/adf/rotation += "-deg" - /radios/nav1/* => /radios/nav[0]/* - /radios/nav2/* => /radios/nav[1]/* - /radios/nav[*]/dme/distance += "-nm" - /radios/nav[*]/frequencies/selected += "-mhz" - /radios/nav[*]/frequencies/standby += "-mhz" - /radios/nav[*]/radials/actual += "-deg" - /radios/nav[*]/radials/selected += "-deg" - /sim/view/goal-offset += "-deg" - /sim/view/offset += "-deg" - /steam/adf += "-deg" - /steam/airspeed += "-kt" - /steam/altitude += "-ft" - /steam/gyro-compass += "-deg" - /steam/gyro-compass-error += "-deg" - /steam/mag-compass += "-deg" - /steam/vertical-speed += "-fpm" - /velocities/airspeed += "-kt" - /velocities/side-slip += "-rad" - /velocities/speed-down += "-fps" - /velocities/speed-east += "-fps" - /velocities/speed-north += "-fps" - /velocities/uBody += "-fps" - /velocities/vBody += "-fps" - /velocities/wBody += "-fps" - /velocities/vertical-speed += "-fps"
2001-07-02 22:27:24 +00:00
fgSetDouble("/position/longitude-deg", lon2 );
fgSetDouble("/position/latitude-deg", lat2 );
fgSetDouble("/orientation/heading-deg", heading );
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("
<< lon2 << ", "
<< lat2 << ") new heading is "
<< heading );
return true;
}
// Set current_options lon/lat given an airport id and runway number
static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
FGRunway r;
if ( id.length() ) {
// set initial position from airport and runway number
SG_LOG( SG_GENERAL, SG_INFO,
"Attempting to set starting position for "
2003-03-20 22:31:25 +00:00
<< id << ":" << rwy );
if ( ! globals->get_runways()->search( id, rwy, &r ) ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Failed to find runway " << rwy <<
" at airport " << id );
return false;
}
} else {
return false;
}
double lat2, lon2, az2;
double heading = r._heading;
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
SG_LOG( SG_GENERAL, SG_INFO,
"runway = " << r._lon << ", " << r._lat
<< " length = " << r._length * SG_FEET_TO_METER
<< " heading = " << azimuth );
geo_direct_wgs_84 ( 0, r._lat, r._lon,
azimuth,
r._length * SG_FEET_TO_METER * 0.5 - 5.0,
&lat2, &lon2, &az2 );
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON )
{
double olat, olon;
double odist = fgGetDouble("/sim/presets/offset-distance");
odist *= SG_NM_TO_METER;
double oaz = azimuth;
if ( fabs(fgGetDouble("/sim/presets/offset-azimuth")) > SG_EPSILON )
{
oaz = fgGetDouble("/sim/presets/offset-azimuth") + 180;
heading = fgGetDouble("/sim/presets/heading-deg");
}
while ( oaz >= 360.0 ) { oaz -= 360.0; }
geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 );
lat2=olat;
lon2=olon;
}
// presets
fgSetDouble("/sim/presets/longitude-deg", lon2 );
fgSetDouble("/sim/presets/latitude-deg", lat2 );
fgSetDouble("/sim/presets/heading-deg", heading );
// other code depends on the actual values being set ...
fgSetDouble("/position/longitude-deg", lon2 );
fgSetDouble("/position/latitude-deg", lat2 );
fgSetDouble("/orientation/heading-deg", heading );
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("
<< lon2 << ", "
<< lat2 << ") new heading is "
<< heading );
return true;
}
static void fgSetDistOrAltFromGlideSlope() {
// cout << "fgSetDistOrAltFromGlideSlope()" << endl;
string apt_id = fgGetString("/sim/presets/airport-id");
2002-11-18 21:31:33 +00:00
double gs = fgGetDouble("/sim/presets/glideslope-deg")
* SG_DEGREES_TO_RADIANS ;
double od = fgGetDouble("/sim/presets/offset-distance");
double alt = fgGetDouble("/sim/presets/altitude-ft");
double apt_elev = 0.0;
if ( ! apt_id.empty() ) {
apt_elev = fgGetAirportElev( apt_id );
if ( apt_elev < -9990.0 ) {
apt_elev = 0.0;
}
} else {
apt_elev = 0.0;
}
if( fabs(gs) > 0.01 && fabs(od) > 0.1 && alt < -9990 ) {
// set altitude from glideslope and offset-distance
od *= SG_NM_TO_METER * SG_METER_TO_FEET;
alt = fabs(od*tan(gs)) + apt_elev;
fgSetDouble("/sim/presets/altitude-ft", alt);
fgSetBool("/sim/presets/onground", false);
SG_LOG( SG_GENERAL, SG_INFO, "Calculated altitude as: "
<< alt << " ft" );
} else if( fabs(gs) > 0.01 && alt > 0 && fabs(od) < 0.1) {
// set offset-distance from glideslope and altitude
od = (alt - apt_elev) / tan(gs);
od *= -1*SG_FEET_TO_METER * SG_METER_TO_NM;
fgSetDouble("/sim/presets/offset-distance", od);
fgSetBool("/sim/presets/onground", false);
SG_LOG( SG_GENERAL, SG_INFO, "Calculated offset distance as: "
<< od << " nm" );
} else if( fabs(gs) > 0.01 ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Glideslope given but not altitude or offset-distance." );
SG_LOG( SG_GENERAL, SG_ALERT, "Resetting glideslope to zero" );
2002-11-18 21:31:33 +00:00
fgSetDouble("/sim/presets/glideslope-deg", 0);
fgSetBool("/sim/presets/onground", true);
}
}
// Set current_options lon/lat given an airport id and heading (degrees)
static bool fgSetPosFromNAV( const string& id, const double& freq ) {
FGNavRecord *nav
= globals->get_navlist()->findByIdentAndFreq( id.c_str(), freq );
// set initial position from runway and heading
if ( nav != NULL ) {
SG_LOG( SG_GENERAL, SG_INFO, "Attempting to set starting position for "
<< id << ":" << freq );
double lon = nav->get_lon();
double lat = nav->get_lat();
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON )
{
double odist = fgGetDouble("/sim/presets/offset-distance")
* SG_NM_TO_METER;
double oaz = fabs(fgGetDouble("/sim/presets/offset-azimuth"))
+ 180.0;
while ( oaz >= 360.0 ) { oaz -= 360.0; }
double olat, olon, az2;
geo_direct_wgs_84 ( 0, lat, lon, oaz, odist, &olat, &olon, &az2 );
lat = olat;
lon = olon;
}
// presets
fgSetDouble("/sim/presets/longitude-deg", lon );
fgSetDouble("/sim/presets/latitude-deg", lat );
// other code depends on the actual values being set ...
fgSetDouble("/position/longitude-deg", lon );
fgSetDouble("/position/latitude-deg", lat );
fgSetDouble("/orientation/heading-deg",
fgGetDouble("/sim/presets/heading-deg") );
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << ":" << freq << " is ("
<< lon << ", "<< lat << ")" );
return true;
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = "
<< id << ":" << freq );
return false;
}
}
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
// Set current_options lon/lat given an aircraft carrier id
static bool fgSetPosFromCarrier( const string& carrier, const string& posid ) {
// set initial position from runway and heading
Point3D geodPos;
double heading;
sgdVec3 uvw;
if (FGAIManager::getStartPosition(carrier, posid, geodPos, heading, uvw)) {
double lon = geodPos.lon() * SGD_RADIANS_TO_DEGREES;
double lat = geodPos.lat() * SGD_RADIANS_TO_DEGREES;
double alt = geodPos.elev() * SG_METER_TO_FEET;
SG_LOG( SG_GENERAL, SG_INFO, "Attempting to set starting position for "
<< carrier << " at lat = " << lat << ", lon = " << lon
<< ", alt = " << alt << ", heading = " << heading);
fgSetDouble("/sim/presets/longitude-deg", lon);
fgSetDouble("/sim/presets/latitude-deg", lat);
fgSetDouble("/sim/presets/altitude-ft", alt);
fgSetDouble("/sim/presets/heading-deg", heading);
fgSetDouble("/position/longitude-deg", lon);
fgSetDouble("/position/latitude-deg", lat);
fgSetDouble("/position/altitude-ft", alt);
fgSetDouble("/orientation/heading-deg", heading);
fgSetString("/sim/presets/speed-set", "UVW");
fgSetDouble("/velocities/uBody-fps", uvw[0]);
fgSetDouble("/velocities/vBody-fps", uvw[1]);
fgSetDouble("/velocities/wBody-fps", uvw[2]);
fgSetDouble("/sim/presets/uBody-fps", uvw[0]);
fgSetDouble("/sim/presets/vBody-fps", uvw[1]);
fgSetDouble("/sim/presets/wBody-fps", uvw[2]);
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
fgSetBool("/sim/presets/onground", true);
return true;
} else {
2005-10-04 20:36:38 +00:00
SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate aircraft carrier = "
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
<< carrier );
return false;
}
}
// Set current_options lon/lat given an airport id and heading (degrees)
static bool fgSetPosFromFix( const string& id ) {
FGFix fix;
// set initial position from runway and heading
if ( globals->get_fixlist()->query( id.c_str(), &fix ) ) {
SG_LOG( SG_GENERAL, SG_INFO, "Attempting to set starting position for "
<< id );
double lon = fix.get_lon();
double lat = fix.get_lat();
if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON )
{
double odist = fgGetDouble("/sim/presets/offset-distance")
* SG_NM_TO_METER;
double oaz = fabs(fgGetDouble("/sim/presets/offset-azimuth"))
+ 180.0;
while ( oaz >= 360.0 ) { oaz -= 360.0; }
double olat, olon, az2;
geo_direct_wgs_84 ( 0, lat, lon, oaz, odist, &olat, &olon, &az2 );
lat = olat;
lon = olon;
}
// presets
fgSetDouble("/sim/presets/longitude-deg", lon );
fgSetDouble("/sim/presets/latitude-deg", lat );
// other code depends on the actual values being set ...
fgSetDouble("/position/longitude-deg", lon );
fgSetDouble("/position/latitude-deg", lat );
fgSetDouble("/orientation/heading-deg",
fgGetDouble("/sim/presets/heading-deg") );
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("
<< lon << ", "<< lat << ")" );
return true;
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = "
<< id );
return false;
}
}
2004-04-19 02:24:22 +00:00
static void parseWaypoints() {
string_list *waypoints = globals->get_initial_waypoints();
2004-04-19 02:24:22 +00:00
if (waypoints) {
vector<string>::iterator i;
for (i = waypoints->begin();
i != waypoints->end();
i++)
2004-04-19 02:24:22 +00:00
{
NewWaypoint(*i);
}
// Now were done using the way points we can deallocate the
// memory they used
2004-04-19 02:24:22 +00:00
while (waypoints->begin() != waypoints->end()) {
waypoints->pop_back();
}
delete waypoints;
globals->set_initial_waypoints(0);
2004-04-19 02:24:22 +00:00
}
}
/**
2003-08-28 20:53:08 +00:00
* Initialize vor/ndb/ils/fix list management and query systems (as
* well as simple airport db list)
*/
bool
fgInitNav ()
{
SG_LOG(SG_GENERAL, SG_INFO, "Loading Airport Database ...");
SGPath aptdb( globals->get_fg_root() );
aptdb.append( "Airports/apt.dat" );
SGPath p_metar( globals->get_fg_root() );
p_metar.append( "Airports/metar.dat" );
2003-08-28 20:53:08 +00:00
FGAirportList *airports = new FGAirportList();
globals->set_airports( airports );
FGRunwayList *runways = new FGRunwayList();
globals->set_runways( runways );
fgAirportDBLoad( airports, runways, aptdb.str(), p_metar.str() );
FGNavList *navlist = new FGNavList;
FGNavList *loclist = new FGNavList;
FGNavList *gslist = new FGNavList;
FGNavList *dmelist = new FGNavList;
FGNavList *mkrlist = new FGNavList;
FGNavList *tacanlist = new FGNavList;
FGNavList *carrierlist = new FGNavList;
FGTACANList *channellist = new FGTACANList;
globals->set_navlist( navlist );
globals->set_loclist( loclist );
globals->set_gslist( gslist );
globals->set_dmelist( dmelist );
globals->set_mkrlist( mkrlist );
globals->set_tacanlist( tacanlist );
globals->set_carrierlist( carrierlist );
globals->set_channellist( channellist );
if ( !fgNavDBInit(airports, navlist, loclist, gslist, dmelist, mkrlist, tacanlist, carrierlist, channellist) ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Problems loading one or more navigational database" );
}
if ( fgGetBool("/sim/navdb/localizers/auto-align", true) ) {
// align all the localizers with their corresponding runways
// since data sources are good for cockpit navigation
// purposes, but not always to the error tolerances needed to
// exactly place these items.
double threshold
= fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg",
5.0 );
fgNavDBAlignLOCwithRunway( runways, loclist, threshold );
}
SG_LOG(SG_GENERAL, SG_INFO, " Fixes");
SGPath p_fix( globals->get_fg_root() );
p_fix.append( "Navaids/fix.dat" );
FGFixList *fixlist = new FGFixList;
fixlist->init( p_fix );
globals->set_fixlist( fixlist );
2003-03-03 04:34:27 +00:00
return true;
}
// Set the initial position based on presets (or defaults)
bool fgInitPosition() {
// cout << "fgInitPosition()" << endl;
double gs = fgGetDouble("/sim/presets/glideslope-deg")
* SG_DEGREES_TO_RADIANS ;
double od = fgGetDouble("/sim/presets/offset-distance");
double alt = fgGetDouble("/sim/presets/altitude-ft");
bool set_pos = false;
// If glideslope is specified, then calculate offset-distance or
// altitude relative to glide slope if either of those was not
// specified.
if ( fabs( gs ) > 0.01 ) {
fgSetDistOrAltFromGlideSlope();
}
// If we have an explicit, in-range lon/lat, don't change it, just use it.
// If not, check for an airport-id and use that.
// If not, default to the middle of the KSFO field.
// The default values for lon/lat are deliberately out of range
// so that the airport-id can take effect; valid lon/lat will
// override airport-id, however.
double lon_deg = fgGetDouble("/sim/presets/longitude-deg");
double lat_deg = fgGetDouble("/sim/presets/latitude-deg");
if ( lon_deg >= -180.0 && lon_deg <= 180.0
&& lat_deg >= -90.0 && lat_deg <= 90.0 )
{
set_pos = true;
}
string apt = fgGetString("/sim/presets/airport-id");
string rwy_no = fgGetString("/sim/presets/runway");
double hdg = fgGetDouble("/sim/presets/heading-deg");
string vor = fgGetString("/sim/presets/vor-id");
double vor_freq = fgGetDouble("/sim/presets/vor-freq");
string ndb = fgGetString("/sim/presets/ndb-id");
double ndb_freq = fgGetDouble("/sim/presets/ndb-freq");
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
string carrier = fgGetString("/sim/presets/carrier");
string parkpos = fgGetString("/sim/presets/parkpos");
string fix = fgGetString("/sim/presets/fix");
2003-07-02 16:24:50 +00:00
fgSetDouble( "/orientation/heading-deg", hdg );
fgInitTowerLocationListener();
if ( !set_pos && !apt.empty() && !rwy_no.empty() ) {
// An airport + runway is requested
if ( fgSetPosFromAirportIDandRwy( apt, rwy_no ) ) {
2003-07-02 16:24:50 +00:00
// set tower position (a little off the heading for single
// runway airports)
fgSetString("/sim/tower/airport-id", apt.c_str());
set_pos = true;
}
}
2003-07-02 16:24:50 +00:00
if ( !set_pos && !apt.empty() ) {
// An airport is requested (find runway closest to hdg)
2003-07-02 16:24:50 +00:00
if ( fgSetPosFromAirportIDandHdg( apt, hdg ) ) {
// set tower position (a little off the heading for single
// runway airports)
fgSetString("/sim/tower/airport-id", apt.c_str());
set_pos = true;
}
}
2003-07-02 16:24:50 +00:00
if ( !set_pos && !vor.empty() ) {
// a VOR is requested
if ( fgSetPosFromNAV( vor, vor_freq ) ) {
set_pos = true;
}
}
2003-07-02 16:24:50 +00:00
if ( !set_pos && !ndb.empty() ) {
// an NDB is requested
if ( fgSetPosFromNAV( ndb, ndb_freq ) ) {
set_pos = true;
}
}
2003-07-02 16:24:50 +00:00
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
if ( !set_pos && !carrier.empty() ) {
// an aircraft carrier is requested
if ( fgSetPosFromCarrier( carrier, parkpos ) ) {
set_pos = true;
}
}
if ( !set_pos && !fix.empty() ) {
// a Fix is requested
if ( fgSetPosFromFix( fix ) ) {
set_pos = true;
}
}
if ( !set_pos ) {
// No lon/lat specified, no airport specified, default to
// middle of KSFO field.
fgSetDouble("/sim/presets/longitude-deg", -122.374843);
fgSetDouble("/sim/presets/latitude-deg", 37.619002);
}
fgSetDouble( "/position/longitude-deg",
fgGetDouble("/sim/presets/longitude-deg") );
fgSetDouble( "/position/latitude-deg",
fgGetDouble("/sim/presets/latitude-deg") );
// determine if this should be an on-ground or in-air start
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
if ((fabs(gs) > 0.01 || fabs(od) > 0.1 || alt > 0.1) && carrier.empty()) {
fgSetBool("/sim/presets/onground", false);
} else {
fgSetBool("/sim/presets/onground", true);
}
return true;
}
// General house keeping initializations
bool fgInitGeneral() {
string root;
1999-11-19 02:10:24 +00:00
#if defined(FX) && defined(XMESA)
char *mesa_win_state;
1999-11-19 02:10:24 +00:00
#endif
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO, "General Initialization" );
SG_LOG( SG_GENERAL, SG_INFO, "======= ==============" );
root = globals->get_fg_root();
1998-09-08 21:40:08 +00:00
if ( ! root.length() ) {
// No root path set? Then bail ...
SG_LOG( SG_GENERAL, SG_ALERT,
"Cannot continue without a path to the base package "
<< "being defined." );
exit(-1);
}
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO, "FG_ROOT = " << '"' << root << '"' << endl );
#if defined(FX) && defined(XMESA)
// initialize full screen flag
globals->set_fullscreen(false);
if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
// Test for the MESA_GLX_FX env variable
if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
// test if we are fullscreen mesa/glide
if ( (mesa_win_state[0] == 'f') ||
(mesa_win_state[0] == 'F') ) {
globals->set_fullscreen(true);
}
}
}
#endif
return true;
}
// Initialize the flight model subsystem. This just creates the
// object. The actual fdm initialization is delayed until we get a
// proper scenery elevation hit. This is checked for in main.cxx
void fgInitFDM() {
if ( cur_fdm_state ) {
delete cur_fdm_state;
cur_fdm_state = 0;
}
double dt = 1.0 / fgGetInt("/sim/model-hz");
string model = fgGetString("/sim/flight-model");
try {
if ( model == "larcsim" ) {
cur_fdm_state = new FGLaRCsim( dt );
} else if ( model == "jsb" ) {
cur_fdm_state = new FGJSBsim( dt );
#ifdef ENABLE_SP_FMDS
} else if ( model == "ada" ) {
cur_fdm_state = new FGADA( dt );
} else if ( model == "acms" ) {
cur_fdm_state = new FGACMS( dt );
#endif
} else if ( model == "balloon" ) {
cur_fdm_state = new FGBalloonSim( dt );
} else if ( model == "magic" ) {
cur_fdm_state = new FGMagicCarpet( dt );
} else if ( model == "ufo" ) {
cur_fdm_state = new FGUFO( dt );
} else if ( model == "external" ) {
// external is a synonym for "--fdm=null" and is
// maintained here for backwards compatibility
cur_fdm_state = new FGNullFDM( dt );
} else if ( model.find("network") == 0 ) {
string host = "localhost";
int port1 = 5501;
int port2 = 5502;
int port3 = 5503;
string net_options = model.substr(8);
string::size_type begin, end;
begin = 0;
// host
end = net_options.find( ",", begin );
if ( end != string::npos ) {
host = net_options.substr(begin, end - begin);
begin = end + 1;
}
// port1
end = net_options.find( ",", begin );
if ( end != string::npos ) {
port1 = atoi( net_options.substr(begin, end - begin).c_str() );
begin = end + 1;
}
// port2
end = net_options.find( ",", begin );
if ( end != string::npos ) {
port2 = atoi( net_options.substr(begin, end - begin).c_str() );
begin = end + 1;
}
// port3
end = net_options.find( ",", begin );
if ( end != string::npos ) {
port3 = atoi( net_options.substr(begin, end - begin).c_str() );
begin = end + 1;
}
cur_fdm_state = new FGExternalNet( dt, host, port1, port2, port3 );
2003-03-03 04:34:27 +00:00
} else if ( model.find("pipe") == 0 ) {
// /* old */ string pipe_path = model.substr(5);
// /* old */ cur_fdm_state = new FGExternalPipe( dt, pipe_path );
string pipe_path = "";
string pipe_protocol = "";
string pipe_options = model.substr(5);
string::size_type begin, end;
begin = 0;
// pipe file path
end = pipe_options.find( ",", begin );
if ( end != string::npos ) {
pipe_path = pipe_options.substr(begin, end - begin);
begin = end + 1;
}
// protocol (last option)
pipe_protocol = pipe_options.substr(begin);
cur_fdm_state = new FGExternalPipe( dt, pipe_path, pipe_protocol );
} else if ( model == "null" ) {
cur_fdm_state = new FGNullFDM( dt );
} else if ( model == "yasim" ) {
cur_fdm_state = new YASim( dt );
} else {
SG_LOG(SG_GENERAL, SG_ALERT,
"Unrecognized flight model '" << model
<< "', cannot init flight dynamics model.");
exit(-1);
}
} catch ( ... ) {
SG_LOG(SG_GENERAL, SG_ALERT, "FlightGear aborting\n\n");
exit(-1);
}
}
static void printMat(const sgVec4 *mat, char *name="")
{
int i;
SG_LOG(SG_GENERAL, SG_BULK, name );
for(i=0; i<4; i++) {
SG_LOG(SG_GENERAL, SG_BULK, " " << mat[i][0] << " " << mat[i][1]
<< " " << mat[i][2] << " " << mat[i][3] );
}
}
// Initialize view parameters
void fgInitView() {
// force update of model so that viewer can get some data...
globals->get_aircraft_model()->update(0);
// run update for current view so that data is current...
globals->get_viewmgr()->update(0);
printMat(globals->get_current_view()->get_VIEW(),"VIEW");
printMat(globals->get_current_view()->get_UP(),"UP");
// printMat(globals->get_current_view()->get_LOCAL(),"LOCAL");
}
SGTime *fgInitTime() {
// Initialize time
static const SGPropertyNode *longitude
= fgGetNode("/position/longitude-deg");
static const SGPropertyNode *latitude
= fgGetNode("/position/latitude-deg");
static const SGPropertyNode *cur_time_override
= fgGetNode("/sim/time/cur-time-override", true);
SGPath zone( globals->get_fg_root() );
zone.append( "Timezone" );
SGTime *t = new SGTime( longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
zone.str(),
cur_time_override->getLongValue() );
globals->set_warp_delta( 0 );
t->update( 0.0, 0.0,
cur_time_override->getLongValue(),
globals->get_warp() );
return t;
}
// set up a time offset (aka warp) if one is specified
void fgInitTimeOffset() {
static const SGPropertyNode *longitude
= fgGetNode("/position/longitude-deg");
static const SGPropertyNode *latitude
= fgGetNode("/position/latitude-deg");
static const SGPropertyNode *cur_time_override
= fgGetNode("/sim/time/cur-time-override", true);
// Handle potential user specified time offsets
int orig_warp = globals->get_warp();
SGTime *t = globals->get_time_params();
time_t cur_time = t->get_cur_time();
time_t currGMT = sgTimeGetGMT( gmtime(&cur_time) );
time_t systemLocalTime = sgTimeGetGMT( localtime(&cur_time) );
time_t aircraftLocalTime =
sgTimeGetGMT( fgLocaltime(&cur_time, t->get_zonename() ) );
// Okay, we now have several possible scenarios
int offset = fgGetInt("/sim/startup/time-offset");
string offset_type = fgGetString("/sim/startup/time-offset-type");
int warp = 0;
if ( offset_type == "real" ) {
warp = 0;
} else if ( offset_type == "dawn" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
90.0, true );
} else if ( offset_type == "morning" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
75.0, true );
} else if ( offset_type == "noon" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
0.0, true );
} else if ( offset_type == "afternoon" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
60.0, false );
} else if ( offset_type == "dusk" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
90.0, false );
} else if ( offset_type == "evening" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
100.0, false );
} else if ( offset_type == "midnight" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
180.0, false );
} else if ( offset_type == "system-offset" ) {
warp = offset;
} else if ( offset_type == "gmt-offset" ) {
warp = offset - (currGMT - systemLocalTime);
} else if ( offset_type == "latitude-offset" ) {
warp = offset - (aircraftLocalTime - systemLocalTime);
} else if ( offset_type == "system" ) {
warp = offset - cur_time;
} else if ( offset_type == "gmt" ) {
warp = offset - currGMT;
} else if ( offset_type == "latitude" ) {
warp = offset - (aircraftLocalTime - systemLocalTime) - cur_time;
} else {
SG_LOG( SG_GENERAL, SG_ALERT,
"FG_TIME::Unsupported offset type " << offset_type );
exit( -1 );
}
globals->set_warp( orig_warp + warp );
t->update( longitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
cur_time_override->getLongValue(),
globals->get_warp() );
SG_LOG( SG_GENERAL, SG_INFO, "After fgInitTimeOffset(): warp = "
<< globals->get_warp() );
}
2004-11-18 05:00:44 +00:00
// This is the top level init routine which calls all the other
// initialization routines. If you are adding a subsystem to flight
// gear, its initialization call should located in this routine.
// Returns non-zero if a problem encountered.
2002-11-18 21:31:33 +00:00
bool fgInitSubsystems() {
// static const SGPropertyNode *longitude
// = fgGetNode("/sim/presets/longitude-deg");
// static const SGPropertyNode *latitude
// = fgGetNode("/sim/presets/latitude-deg");
// static const SGPropertyNode *altitude
// = fgGetNode("/sim/presets/altitude-ft");
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO, "Initialize Subsystems");
SG_LOG( SG_GENERAL, SG_INFO, "========== ==========");
////////////////////////////////////////////////////////////////////
// Initialize the event manager subsystem.
////////////////////////////////////////////////////////////////////
2004-11-18 05:00:44 +00:00
globals->get_event_mgr()->init();
globals->get_event_mgr()->setRealtimeProperty(fgGetNode("/sim/time/delta-realtime-sec", true));
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the property interpolator subsystem
////////////////////////////////////////////////////////////////////
globals->add_subsystem("interpolator", new SGInterpolator);
////////////////////////////////////////////////////////////////////
// Add the FlightGear property utilities.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("properties", new FGProperties);
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the material property subsystem.
////////////////////////////////////////////////////////////////////
SGPath mpath( globals->get_fg_root() );
mpath.append( "materials.xml" );
string season = fgGetString("/sim/startup/season", "summer");
if ( ! globals->get_matlib()->load(globals->get_fg_root(), mpath.str(), season.c_str()) ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Error loading material lib!" );
exit(-1);
}
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the scenery management subsystem.
////////////////////////////////////////////////////////////////////
if ( globals->get_tile_mgr()->init() ) {
// Load the local scenery data
double visibility_meters = fgGetDouble("/environment/visibility-m");
globals->get_tile_mgr()->update( visibility_meters );
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Error in Tile Manager initialization!" );
exit(-1);
}
From: "Jim Wilson" <jimw@kelcomaine.com> This is a new improved patch for the previous tile manager fixes. Rather than building dependencies between FGlocation or the viewer or fdm with tilemgr what I ended up doing was linking the pieces together in the Mainloop in main.cxx. You'll see what I mean...it's been commented fairly well. More than likely we should move that chunk somewhere...just not sure where yet. The changes seem clean now. As I get more ideas there could be some further improvement in organizing the update in tilemgr. You'll note that I left an override in there for the tilemgr::update() function to preserve earlier functionality if someone needs it (e.g. usage independent of an fdm or viewer), not to mention there are a few places in flightgear that call it directly that have not been changed to the new interface (and may not need to be). The code has been optimized to avoid duplicate traversals and seems to run generally quite well. Note that there can be a short delay reloading tiles that have been dropped from static views. We could call the tile scheduler on a view switch, but it's not a big deal and at the moment I'd like to get this in so people can try it and comment on it as it is. Everything has been resycned with CVS tonight and I've included the description submitted earlier (below). Best, Jim Changes synced with CVS approx 20:30EDT 2002-05-09 (after this evenings updates). Files: http://www.spiderbark.com/fgfs/viewer-update-20020516.tar.gz or http://www.spiderbark.com/fgfs/viewer-update-20020516.diffs.gz Description: In a nutshell, these patches begin to take what was one value for ground elevation and calculate ground elevation values seperately for the FDM and the viewer (eye position). Several outstanding view related bugs have been fixed. With the introduction of the new viewer code a lot of that Flight Gear code broke related to use of a global variable called "scenery.cur_elev". Therefore the ground_elevation and other associated items (like the current tile bucket) is maintained per FDM instance and per View. Each of these has a "point" or location that can be identified. See changes to FGLocation class and main.cxx. Most of the problems related to the new viewer in terms of sky, ground and runway lights, and tower views are fixed. There are four minor problems remaining. 1) The sun/moon spins when you pan the "lookat" tower view only (view #3). 2) Under stress (esp. magic carpet full speed with max visibility), there is a memory leak in the tile caching that was not introduced with these changes. 3) I have not tested these changes or made corrections to the ADA or External FDM interfaces. 4) The change view function doesn't call the time/light update (not a problem unless a tower is very far away). Details: FDM/flight.cxx, flight.hxx - FGInterface ties to FGAircraftModel so that it's location data can be accessed for runway (ground elevation under aircraft) elevation. FDM/larsim.cxx, larcsim.hxx - gets runway elevation from FGInterface now. Commented out function that is causing a namespace conflict, hasn't been called with recent code anyway. FDM/JSBSim/JSBSim.cxx, YASim/YASim.cxx - gets runway elevation from FGInterface now. Scenery/newcache.cxx, newcache.hxx - changed caching scheme to time based (oldest tiles discard). Scenery/tileentry.cxx, tileentry.hxx - added place to record time, changed rendering to reference viewer altitude in order to fix a problem with ground and runway lights. Scenery/tilemgr.cxx, tilemgr.hxx - Modified update() to accept values for multiple locations. Refresh function added in order to periodically make the tiles current for a non-moving view (like a tower). Main/fg_init.cxx - register event for making tiles current in a non-moving view (like a tower). Main/location.hxx - added support for current ground elevation data. Main/main.cxx - added second tilemgr call for fdm, fixed places where viewer position data was required for correct sky rendering. Main/options.cxx - fixed segfault reported by Curtis when using --view-offset command line parameter. Main/viewer.cxx, viewer.hxx - removed fudging of view position. Fixed numerous bugs that were causing eye and target values to get mixed up.
2002-05-17 17:25:28 +00:00
// cause refresh of viewer scenery timestamps every 15 seconds...
globals->get_event_mgr()->addTask( "FGTileMgr::refresh_view_timestamps()",
globals->get_tile_mgr(),
&FGTileMgr::refresh_view_timestamps,
15 );
From: "Jim Wilson" <jimw@kelcomaine.com> This is a new improved patch for the previous tile manager fixes. Rather than building dependencies between FGlocation or the viewer or fdm with tilemgr what I ended up doing was linking the pieces together in the Mainloop in main.cxx. You'll see what I mean...it's been commented fairly well. More than likely we should move that chunk somewhere...just not sure where yet. The changes seem clean now. As I get more ideas there could be some further improvement in organizing the update in tilemgr. You'll note that I left an override in there for the tilemgr::update() function to preserve earlier functionality if someone needs it (e.g. usage independent of an fdm or viewer), not to mention there are a few places in flightgear that call it directly that have not been changed to the new interface (and may not need to be). The code has been optimized to avoid duplicate traversals and seems to run generally quite well. Note that there can be a short delay reloading tiles that have been dropped from static views. We could call the tile scheduler on a view switch, but it's not a big deal and at the moment I'd like to get this in so people can try it and comment on it as it is. Everything has been resycned with CVS tonight and I've included the description submitted earlier (below). Best, Jim Changes synced with CVS approx 20:30EDT 2002-05-09 (after this evenings updates). Files: http://www.spiderbark.com/fgfs/viewer-update-20020516.tar.gz or http://www.spiderbark.com/fgfs/viewer-update-20020516.diffs.gz Description: In a nutshell, these patches begin to take what was one value for ground elevation and calculate ground elevation values seperately for the FDM and the viewer (eye position). Several outstanding view related bugs have been fixed. With the introduction of the new viewer code a lot of that Flight Gear code broke related to use of a global variable called "scenery.cur_elev". Therefore the ground_elevation and other associated items (like the current tile bucket) is maintained per FDM instance and per View. Each of these has a "point" or location that can be identified. See changes to FGLocation class and main.cxx. Most of the problems related to the new viewer in terms of sky, ground and runway lights, and tower views are fixed. There are four minor problems remaining. 1) The sun/moon spins when you pan the "lookat" tower view only (view #3). 2) Under stress (esp. magic carpet full speed with max visibility), there is a memory leak in the tile caching that was not introduced with these changes. 3) I have not tested these changes or made corrections to the ADA or External FDM interfaces. 4) The change view function doesn't call the time/light update (not a problem unless a tower is very far away). Details: FDM/flight.cxx, flight.hxx - FGInterface ties to FGAircraftModel so that it's location data can be accessed for runway (ground elevation under aircraft) elevation. FDM/larsim.cxx, larcsim.hxx - gets runway elevation from FGInterface now. Commented out function that is causing a namespace conflict, hasn't been called with recent code anyway. FDM/JSBSim/JSBSim.cxx, YASim/YASim.cxx - gets runway elevation from FGInterface now. Scenery/newcache.cxx, newcache.hxx - changed caching scheme to time based (oldest tiles discard). Scenery/tileentry.cxx, tileentry.hxx - added place to record time, changed rendering to reference viewer altitude in order to fix a problem with ground and runway lights. Scenery/tilemgr.cxx, tilemgr.hxx - Modified update() to accept values for multiple locations. Refresh function added in order to periodically make the tiles current for a non-moving view (like a tower). Main/fg_init.cxx - register event for making tiles current in a non-moving view (like a tower). Main/location.hxx - added support for current ground elevation data. Main/main.cxx - added second tilemgr call for fdm, fixed places where viewer position data was required for correct sky rendering. Main/options.cxx - fixed segfault reported by Curtis when using --view-offset command line parameter. Main/viewer.cxx, viewer.hxx - removed fudging of view position. Fixed numerous bugs that were causing eye and target values to get mixed up.
2002-05-17 17:25:28 +00:00
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the flight model subsystem.
////////////////////////////////////////////////////////////////////
fgInitFDM();
// allocates structures so must happen before any of the flight
// model or control parameters are set
fgAircraftInit(); // In the future this might not be the case.
2004-01-31 19:47:45 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the XML Autopilot subsystem.
////////////////////////////////////////////////////////////////////
globals->add_subsystem( "xml-autopilot", new FGXMLAutopilot );
globals->add_subsystem( "route-manager", new FGRouteMgr );
////////////////////////////////////////////////////////////////////
// Initialize the view manager subsystem.
////////////////////////////////////////////////////////////////////
fgInitView();
2002-03-12 16:29:00 +00:00
////////////////////////////////////////////////////////////////////
// Create and register the logger.
2002-03-12 16:29:00 +00:00
////////////////////////////////////////////////////////////////////
globals->add_subsystem("logger", new FGLogger);
2002-03-12 16:29:00 +00:00
////////////////////////////////////////////////////////////////////
// Create and register the XML GUI.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("gui", new NewGUI, SGSubsystemMgr::INIT);
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the local time subsystem.
////////////////////////////////////////////////////////////////////
// update the current timezone each 30 minutes
globals->get_event_mgr()->addTask( "fgUpdateLocalTime()",
&fgUpdateLocalTime, 30*60 );
fgInitTimeOffset(); // the environment subsystem needs this
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the weather subsystem.
////////////////////////////////////////////////////////////////////
// Initialize the weather modeling subsystem
globals->add_subsystem("environment", new FGEnvironmentMgr);
1997-08-23 01:46:20 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the lighting subsystem.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("lighting", new FGLight);
//////////////////////////////////////////////////////////////////////
// Initialize the 2D cloud subsystem.
////////////////////////////////////////////////////////////////////
fgGetBool("/sim/rendering/bump-mapping", false);
#ifdef ENABLE_AUDIO_SUPPORT
////////////////////////////////////////////////////////////////////
// Initialize the sound subsystem.
////////////////////////////////////////////////////////////////////
init_volume = fgGetFloat("/sim/sound/volume");
fgSetFloat("/sim/sound/volume", 0.0f);
globals->set_soundmgr(new SGSoundMgr);
globals->get_soundmgr()->init();
globals->get_soundmgr()->bind();
////////////////////////////////////////////////////////////////////
// Initialize the sound-effects subsystem.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("fx", new FGFX);
#endif
////////////////////////////////////////////////////////////////////
// Initialise ATC display system
////////////////////////////////////////////////////////////////////
SG_LOG(SG_GENERAL, SG_INFO, " ATC Display");
globals->set_ATC_display(new FGATCDisplay);
globals->get_ATC_display()->init();
////////////////////////////////////////////////////////////////////
// Initialise the ATC Manager
////////////////////////////////////////////////////////////////////
SG_LOG(SG_GENERAL, SG_INFO, " ATC Manager");
globals->set_ATC_mgr(new FGATCMgr);
globals->get_ATC_mgr()->init();
////////////////////////////////////////////////////////////////////
// Initialise the AI Manager
////////////////////////////////////////////////////////////////////
SG_LOG(SG_GENERAL, SG_INFO, " AI Manager");
globals->set_AI_mgr(new FGAIMgr);
globals->get_AI_mgr()->init();
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialise the AI Model Manager
////////////////////////////////////////////////////////////////////
SG_LOG(SG_GENERAL, SG_INFO, " AI Model Manager");
globals->add_subsystem("ai_model", new FGAIManager);
globals->add_subsystem("submodel_mgr", new FGSubmodelMgr);
// It's probably a good idea to initialize the top level traffic manager
// After the AI and ATC systems have been initialized properly.
// AI Traffic manager
globals->add_subsystem("Traffic Manager", new FGTrafficManager);
FGTrafficManager *dispatcher =
(FGTrafficManager*) globals->get_subsystem("Traffic Manager");
SGPath path = globals->get_fg_root();
path.append("/Traffic/fgtraffic.xml");
readXML(path.str(),
*dispatcher);
//globals->get_subsystem("Traffic Manager")->init();
globals->add_subsystem("instrumentation", new FGInstrumentMgr);
globals->add_subsystem("systems", new FGSystemMgr);
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the cockpit subsystem
////////////////////////////////////////////////////////////////////
if( fgCockpitInit( &current_aircraft )) {
// Cockpit initialized ok.
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Error in Cockpit initialization!" );
exit(-1);
1997-09-04 02:17:18 +00:00
}
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the autopilot subsystem.
////////////////////////////////////////////////////////////////////
// FIXME: these should go in the
// GUI initialization code, not here.
2004-01-31 19:47:45 +00:00
// fgAPAdjustInit();
NewTgtAirportInit();
NewHeadingInit();
NewAltitudeInit();
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize I/O subsystem.
////////////////////////////////////////////////////////////////////
globals->get_io()->init();
globals->get_io()->bind();
2003-03-30 12:46:08 +00:00
////////////////////////////////////////////////////////////////////
// Add a new 2D panel.
////////////////////////////////////////////////////////////////////
string panel_path = fgGetString("/sim/panel/path",
"Panels/Default/default.xml");
2003-03-30 12:46:08 +00:00
globals->set_current_panel( fgReadPanel(panel_path) );
if (globals->get_current_panel() == 0) {
SG_LOG( SG_INPUT, SG_ALERT,
"Error reading new panel from " << panel_path );
} else {
SG_LOG( SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path );
2003-03-30 12:46:08 +00:00
globals->get_current_panel()->init();
globals->get_current_panel()->bind();
}
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the controls subsystem.
////////////////////////////////////////////////////////////////////
globals->get_controls()->init();
globals->get_controls()->bind();
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////
// Initialize the input subsystem.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("input", new FGInput);
////////////////////////////////////////////////////////////////////
// Initialize the replay subsystem
////////////////////////////////////////////////////////////////////
globals->add_subsystem("replay", new FGReplay);
////////////////////////////////////////////////////////////////////
// Bind and initialize subsystems.
////////////////////////////////////////////////////////////////////
globals->get_subsystem_mgr()->bind();
globals->get_subsystem_mgr()->init();
#ifdef FG_MPLAYER_AS
////////////////////////////////////////////////////////////////////
// Initialize multiplayer subsystem
////////////////////////////////////////////////////////////////////
globals->set_multiplayer_mgr(new FGMultiplayMgr);
globals->get_multiplayer_mgr()->init();
#endif
////////////////////////////////////////////////////////////////////////
// Initialize the Nasal interpreter.
// Do this last, so that the loaded scripts see initialized state
////////////////////////////////////////////////////////////////////////
FGNasalSys* nasal = new FGNasalSys();
globals->add_subsystem("nasal", nasal);
nasal->init();
////////////////////////////////////////////////////////////////////
// At this point we could try and parse the waypoint options
///////////////////////////////////////////////////////////////////
parseWaypoints();
// initialize methods that depend on other subsystems.
globals->get_subsystem_mgr()->postinit();
From David Megginson: The files in the attached tarball make the following changes to FlightGear: - rename the existing FGInterface::init() method to FGInterface::_setup to get it out of the way - move *all* FDM initialization code out of src/Main/fg_init.cxx and into FGInterface::init(), and clean up fg_init.cxx a little (especially by removing the zillions of attempts to place the plane on the ground at various locations in the code) - modify FGInterface::bind() so that no values are picked up automatically at bind time (they are set previously by init() instead) - modify the init() methods of the classes derived from FGInterface (i.e. larcsim, jsbsim, balloon, magic, and ada) to invoke FGInterface::init() explicitly before doing their own setup I don't claim that the code in FGInterface::init() is optimal (or even correct), but it seems to work for on-ground starts with both LaRCSim and JSBSim on runways pointing various directions from near sea level to about 700' ASL (the range I happened to test). I expect that Jon and Tony will want to look at the code and refactor and correct it now that they can see what's going on in one place. Here's a quick outline of what is invoked: cur_fdm_state = new <whatever>(dt); cur_fdm_state->init(); cur_fdm_state->bind(); The constructor allocates memory and sets default values only (with the help of the FGInterface::_setup() method). The init() method pull any required properties out of the property tree and sets up the initial state of the FDM. The bind() method takes ownership of FDM-related properties so that the FDM can publish them to the rest of the sim. Note that bind() and init() are virtual, so any implementation in a subclass will hide the implementation in FGInterface; that's why subclass implementations of init() and bind() have to invoke FGInterface::init() and FGInterface::bind() explicitly, probably at the start, so that they get the basic initialization.
2001-04-05 20:20:44 +00:00
////////////////////////////////////////////////////////////////////////
// End of subsystem initialization.
////////////////////////////////////////////////////////////////////
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO, endl);
// Save the initial state for future
// reference.
globals->saveInitialState();
return true;
1997-08-23 01:46:20 +00:00
}
2002-11-18 21:31:33 +00:00
void fgReInitSubsystems()
{
// static const SGPropertyNode *longitude
// = fgGetNode("/sim/presets/longitude-deg");
// static const SGPropertyNode *latitude
// = fgGetNode("/sim/presets/latitude-deg");
static const SGPropertyNode *altitude
= fgGetNode("/sim/presets/altitude-ft");
static const SGPropertyNode *master_freeze
= fgGetNode("/sim/freeze/master");
2001-03-24 06:03:11 +00:00
SG_LOG( SG_GENERAL, SG_INFO,
"fgReInitSubsystems(): /position/altitude = "
2002-07-02 20:45:02 +00:00
<< altitude->getDoubleValue() );
2001-01-17 23:30:35 +00:00
bool freeze = master_freeze->getBoolValue();
if ( !freeze ) {
fgSetBool("/sim/freeze/master", true);
}
2003-12-29 10:10:35 +00:00
fgSetBool("/sim/crashed", false);
// Force reupdating the positions of the ai 3d models. They are used for
// initializing ground level for the FDM.
globals->get_subsystem("ai_model")->reinit();
2002-11-18 21:31:33 +00:00
// Initialize the FDM
fgInitFDM();
// allocates structures so must happen before any of the flight
// model or control parameters are set
fgAircraftInit(); // In the future this might not be the case.
// reload offsets from config defaults
globals->get_viewmgr()->reinit();
fgInitView();
globals->get_controls()->reset_all();
fgUpdateLocalTime();
// re-init to proper time of day setting
fgInitTimeOffset();
if ( !freeze ) {
fgSetBool("/sim/freeze/master", false);
}
fgSetBool("/sim/sceneryloaded",false);
}