]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_init.cxx
313776de7cb9550a3afa1a4907d6d6b9cc9dbfb6
[flightgear.git] / src / Main / fg_init.cxx
1 // fg_init.cxx -- Flight Gear top level initialization routines
2 //
3 // Written by Curtis Olson, started August 1997.
4 //
5 // Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 //
22 // $Id$
23
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 // For BC 5.01 this must be included before OpenGL includes.
30 #ifdef FG_MATH_EXCEPTION_CLASH
31 #  include <math.h>
32 #endif
33
34 #include <GL/glut.h>
35 #include <simgear/xgl/xgl.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39
40 // work around a stdc++ lib bug in some versions of linux, but doesn't
41 // seem to hurt to have this here for all versions of Linux.
42 #ifdef linux
43 #  define _G_NO_EXTERN_TEMPLATES
44 #endif
45
46 #include <simgear/compiler.h>
47
48 #include STL_STRING
49
50 #include <simgear/constants.h>
51 #include <simgear/debug/logstream.hxx>
52 #include <simgear/math/fg_geodesy.hxx>
53 #include <simgear/math/point3d.hxx>
54 #include <simgear/math/polar3d.hxx>
55 #include <simgear/misc/fgpath.hxx>
56 #include <simgear/timing/sg_time.hxx>
57
58 #include <Aircraft/aircraft.hxx>
59 #include <Airports/simple.hxx>
60 #include <Autopilot/auto_gui.hxx>
61 #include <Autopilot/newauto.hxx>
62 #include <Cockpit/cockpit.hxx>
63 #include <Cockpit/radiostack.hxx>
64 #include <Cockpit/panel.hxx>
65 #include <Cockpit/sp_panel.hxx>
66 #include <FDM/Balloon.h>
67 #include <FDM/External.hxx>
68 #include <FDM/JSBsim.hxx>
69 #include <FDM/LaRCsim.hxx>
70 #include <FDM/MagicCarpet.hxx>
71 #include <Include/general.hxx>
72 #include <Joystick/joystick.hxx>
73 #include <Objects/matlib.hxx>
74 #include <Navaids/fixlist.hxx>
75 #include <Navaids/ilslist.hxx>
76 #include <Navaids/navlist.hxx>
77 #include <Scenery/scenery.hxx>
78 #include <Scenery/tilemgr.hxx>
79 #include <Time/event.hxx>
80 #include <Time/light.hxx>
81 #include <Time/sunpos.hxx>
82 #include <Time/moonpos.hxx>
83 #include <Time/tmp.hxx>
84
85 #ifndef FG_OLD_WEATHER
86 #  include <WeatherCM/FGLocalWeatherDatabase.h>
87 #else
88 #  include <Weather/weather.hxx>
89 #endif
90
91 #include "fg_init.hxx"
92 #include "fg_io.hxx"
93 #include "globals.hxx"
94 #include "options.hxx"
95 #include "views.hxx"
96 #include "bfi.hxx"
97
98 #if defined(FX) && defined(XMESA)
99 #include <GL/xmesa.h>
100 #endif
101
102 FG_USING_STD(string);
103
104 extern const char *default_root;
105
106
107 // Read in configuration (file and command line)
108 bool fgInitConfig ( int argc, char **argv ) {
109     // Attempt to locate and parse a config file
110     // First check fg_root
111     FGPath config( current_options.get_fg_root() );
112     config.append( "system.fgfsrc" );
113     current_options.parse_config_file( config.str() );
114
115     // Next check home directory
116     char* envp = ::getenv( "HOME" );
117     if ( envp != NULL ) {
118         config.set( envp );
119         config.append( ".fgfsrc" );
120         current_options.parse_config_file( config.str() );
121     }
122
123     // Parse remaining command line options
124     // These will override anything specified in a config file
125     if ( current_options.parse_command_line(argc, argv) !=
126          fgOPTIONS::FG_OPTIONS_OK )
127     {
128         // Something must have gone horribly wrong with the command
129         // line parsing or maybe the user just requested help ... :-)
130         current_options.usage();
131         FG_LOG( FG_GENERAL, FG_ALERT, "\nExiting ...");
132         return false;
133     }
134
135    return true;
136 }
137
138
139 // Set current_options lon/lat given an airport id
140 bool fgSetPosFromAirportID( const string& id ) {
141     FGAirport a;
142     double lon, lat;
143
144     if ( id.length() ) {
145         // set initial position from airport id
146
147         FGPath path( current_options.get_fg_root() );
148         path.append( "Airports" );
149         path.append( "simple.mk4" );
150         FGAirports airports( path.c_str() );
151
152         FG_LOG( FG_GENERAL, FG_INFO,
153                 "Attempting to set starting position from airport code "
154                 << id );
155
156         // FGPath inpath( current_options.get_fg_root() );
157         // inpath.append( "Airports" );
158         // inpath.append( "apt_simple" );
159         // airports.load( inpath.c_str() );
160
161         // FGPath outpath( current_options.get_fg_root() );
162         // outpath.append( "Airports" );
163         // outpath.append( "simple.gdbm" );
164         // airports.dump_gdbm( outpath.c_str() );
165
166         if ( ! airports.search( id, &a ) ) {
167             FG_LOG( FG_GENERAL, FG_ALERT,
168                     "Failed to find " << id << " in database." );
169             return false;
170         } else {
171             current_options.set_lon( a.longitude );
172             current_options.set_lat( a.latitude );
173         }
174     } else {
175         return false;
176     }
177
178     FG_LOG( FG_GENERAL, FG_INFO,
179             "Position for " << id << " is ("
180             << a.longitude << ", "
181             << a.latitude << ")" );
182
183     return true;
184 }
185
186 // Set initial position and orientation
187 bool fgInitPosition( void ) {
188     FGInterface *f = current_aircraft.fdm_state;
189     string id = current_options.get_airport_id();
190
191     // set initial position from default or command line coordinates
192     f->set_Longitude( current_options.get_lon() * DEG_TO_RAD );
193     f->set_Latitude( current_options.get_lat() * DEG_TO_RAD );
194
195     if ( scenery.cur_elev > current_options.get_altitude() - 2 ) {
196         current_options.set_altitude( scenery.cur_elev + 2 );
197     }
198
199     FG_LOG( FG_GENERAL, FG_INFO,
200             "starting altitude is = " << current_options.get_altitude() );
201
202     f->set_Altitude( current_options.get_altitude() * METER_TO_FEET );
203     fgFDMSetGroundElevation( current_options.get_flight_model(),
204                              (f->get_Altitude() - 3.758099) * FEET_TO_METER );
205
206     FG_LOG( FG_GENERAL, FG_INFO,
207             "Initial position is: ("
208             << (f->get_Longitude() * RAD_TO_DEG) << ", "
209             << (f->get_Latitude() * RAD_TO_DEG) << ", "
210             << (f->get_Altitude() * FEET_TO_METER) << ")" );
211
212     return true;
213 }
214
215
216 // General house keeping initializations
217 bool fgInitGeneral( void ) {
218     string root;
219
220 #if defined(FX) && defined(XMESA)
221     char *mesa_win_state;
222 #endif
223
224     FG_LOG( FG_GENERAL, FG_INFO, "General Initialization" );
225     FG_LOG( FG_GENERAL, FG_INFO, "======= ==============" );
226
227     root = current_options.get_fg_root();
228     if ( ! root.length() ) {
229         // No root path set? Then bail ...
230         FG_LOG( FG_GENERAL, FG_ALERT,
231                 "Cannot continue without environment variable FG_ROOT"
232                 << "being defined." );
233         exit(-1);
234     }
235     FG_LOG( FG_GENERAL, FG_INFO, "FG_ROOT = " << '"' << root << '"' << endl );
236
237 #if defined(FX) && defined(XMESA)
238     // initialize full screen flag
239     global_fullscreen = false;
240     if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
241         // Test for the MESA_GLX_FX env variable
242         if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
243             // test if we are fullscreen mesa/glide
244             if ( (mesa_win_state[0] == 'f') ||
245                  (mesa_win_state[0] == 'F') ) {
246                 global_fullscreen = true;
247             }
248         }
249     }
250 #endif
251
252     return true;
253 }
254
255
256 // This is the top level init routine which calls all the other
257 // initialization routines.  If you are adding a subsystem to flight
258 // gear, its initialization call should located in this routine.
259 // Returns non-zero if a problem encountered.
260 bool fgInitSubsystems( void ) {
261     fgLIGHT *l = &cur_light_params;
262
263     FG_LOG( FG_GENERAL, FG_INFO, "Initialize Subsystems");
264     FG_LOG( FG_GENERAL, FG_INFO, "========== ==========");
265
266     // Initialize the material property lib
267     FGPath mpath( current_options.get_fg_root() );
268     mpath.append( "materials" );
269     if ( material_lib.load( mpath.str() ) ) {
270     } else {
271         FG_LOG( FG_GENERAL, FG_ALERT, "Error loading material lib!" );
272         exit(-1);
273     }
274
275     // Initialize the Scenery Management subsystem
276     if ( fgSceneryInit() ) {
277         // Material lib initialized ok.
278     } else {
279         FG_LOG( FG_GENERAL, FG_ALERT, "Error in Scenery initialization!" );
280         exit(-1);
281     }
282
283     if ( global_tile_mgr.init() ) {
284         // Load the local scenery data
285         global_tile_mgr.update( current_options.get_lon(),
286                                 current_options.get_lat() );
287     } else {
288         FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" );
289         exit(-1);
290     }
291
292     FG_LOG( FG_GENERAL, FG_DEBUG,
293             "Current terrain elevation after tile mgr init " <<
294             scenery.cur_elev );
295
296     if ( current_options.get_flight_model() == FGInterface::FG_LARCSIM ) {
297         cur_fdm_state = new FGLaRCsim;
298     } else if ( current_options.get_flight_model() == FGInterface::FG_JSBSIM ) {
299         cur_fdm_state = new FGJSBsim;
300     } else if ( current_options.get_flight_model() == 
301                 FGInterface::FG_BALLOONSIM ) {
302         cur_fdm_state = new FGBalloonSim;
303     } else if ( current_options.get_flight_model() == 
304                 FGInterface::FG_MAGICCARPET ) {
305         cur_fdm_state = new FGMagicCarpet;
306     } else if ( current_options.get_flight_model() == 
307                 FGInterface::FG_EXTERNAL ) {
308         cur_fdm_state = new FGExternal;
309     } else {
310         FG_LOG( FG_GENERAL, FG_ALERT,
311                 "No flight model, can't init aircraft" );
312         exit(-1);
313     }
314
315     // allocates structures so must happen before any of the flight
316     // model or control parameters are set
317     fgAircraftInit();   // In the future this might not be the case.
318
319     // set the initial position
320     fgInitPosition();
321
322     // Calculate ground elevation at starting point (we didn't have
323     // tmp_abs_view_pos calculated when fgTileMgrUpdate() was called above
324     //
325     // calculalate a cartesian point somewhere along the line between
326     // the center of the earth and our view position.  Doesn't have to
327     // be the exact elevation (this is good because we don't know it
328     // yet :-)
329
330     // now handled inside of the fgTileMgrUpdate()
331
332     /*
333     geod_pos = Point3D( cur_fdm_state->get_Longitude(), cur_fdm_state->get_Latitude(), 0.0);
334     tmp_abs_view_pos = fgGeodToCart(geod_pos);
335
336     FG_LOG( FG_GENERAL, FG_DEBUG,
337             "Initial abs_view_pos = " << tmp_abs_view_pos );
338     scenery.cur_elev =
339         fgTileMgrCurElev( cur_fdm_state->get_Longitude(), cur_fdm_state->get_Latitude(),
340                           tmp_abs_view_pos );
341     FG_LOG( FG_GENERAL, FG_DEBUG,
342             "Altitude after update " << scenery.cur_elev );
343     */
344
345     fgFDMSetGroundElevation( current_options.get_flight_model(),
346                              scenery.cur_elev );
347
348     // Reset our altitude if we are below ground
349     FG_LOG( FG_GENERAL, FG_DEBUG, "Current altitude = " << cur_fdm_state->get_Altitude() );
350     FG_LOG( FG_GENERAL, FG_DEBUG, "Current runway altitude = " <<
351             cur_fdm_state->get_Runway_altitude() );
352
353     if ( cur_fdm_state->get_Altitude() < cur_fdm_state->get_Runway_altitude() + 3.758099) {
354         cur_fdm_state->set_Altitude( cur_fdm_state->get_Runway_altitude() + 3.758099 );
355     }
356
357     FG_LOG( FG_GENERAL, FG_INFO,
358             "Updated position (after elevation adj): ("
359             << (cur_fdm_state->get_Latitude() * RAD_TO_DEG) << ", "
360             << (cur_fdm_state->get_Longitude() * RAD_TO_DEG) << ", "
361             << (cur_fdm_state->get_Altitude() * FEET_TO_METER) << ")" );
362
363     // We need to calculate a few more values here that would normally
364     // be calculated by the FDM so that the current_view.UpdateViewMath()
365     // routine doesn't get hosed.
366
367     double sea_level_radius_meters;
368     double lat_geoc;
369     // Set the FG variables first
370     fgGeodToGeoc( cur_fdm_state->get_Latitude(), cur_fdm_state->get_Altitude(),
371                   &sea_level_radius_meters, &lat_geoc);
372     cur_fdm_state->set_Geocentric_Position( lat_geoc, cur_fdm_state->get_Longitude(),
373                                 cur_fdm_state->get_Altitude() +
374                                 (sea_level_radius_meters * METER_TO_FEET) );
375     cur_fdm_state->set_Sea_level_radius( sea_level_radius_meters * METER_TO_FEET );
376
377     cur_fdm_state->set_sin_cos_longitude(cur_fdm_state->get_Longitude());
378     cur_fdm_state->set_sin_cos_latitude(cur_fdm_state->get_Latitude());
379         
380     cur_fdm_state->set_sin_lat_geocentric(sin(lat_geoc));
381     cur_fdm_state->set_cos_lat_geocentric(cos(lat_geoc));
382
383     // The following section sets up the flight model EOM parameters
384     // and should really be read in from one or more files.
385
386     // Initial Velocity
387     cur_fdm_state->set_Velocities_Local( current_options.get_uBody(),
388                              current_options.get_vBody(),
389                              current_options.get_wBody());
390
391     // Initial Orientation
392     cur_fdm_state->set_Euler_Angles( current_options.get_roll() * DEG_TO_RAD,
393                          current_options.get_pitch() * DEG_TO_RAD,
394                          current_options.get_heading() * DEG_TO_RAD );
395
396     // Initial Angular Body rates
397     cur_fdm_state->set_Omega_Body( 7.206685E-05, 0.0, 9.492658E-05 );
398
399     cur_fdm_state->set_Earth_position_angle( 0.0 );
400
401     // Mass properties and geometry values
402     cur_fdm_state->set_Inertias( 8.547270E+01,
403                      1.048000E+03, 3.000000E+03, 3.530000E+03, 0.000000E+00 );
404
405     // CG position w.r.t. ref. point
406     cur_fdm_state->set_CG_Position( 0.0, 0.0, 0.0 );
407
408     // Initialize the event manager
409     global_events.Init();
410
411     // Output event stats every 60 seconds
412     global_events.Register( "fgEVENT_MGR::PrintStats()",
413                             fgMethodCallback<fgEVENT_MGR>( &global_events,
414                                                    &fgEVENT_MGR::PrintStats),
415                             fgEVENT::FG_EVENT_READY, 60000 );
416
417     // Initialize view parameters
418     FG_LOG( FG_GENERAL, FG_DEBUG, "Before current_view.init()");
419     current_view.Init();
420     pilot_view.Init();
421     FG_LOG( FG_GENERAL, FG_DEBUG, "After current_view.init()");
422     current_view.UpdateViewMath(*cur_fdm_state);
423     pilot_view.UpdateViewMath(*cur_fdm_state);
424     FG_LOG( FG_GENERAL, FG_DEBUG, "  abs_view_pos = " << current_view.get_abs_view_pos());
425     // current_view.UpdateWorldToEye(f);
426
427     // Initialize the planetary subsystem
428     // global_events.Register( "fgPlanetsInit()", fgPlanetsInit,
429     //                      fgEVENT::FG_EVENT_READY, 600000);
430
431     // Initialize the sun's position
432     // global_events.Register( "fgSunInit()", fgSunInit,
433     //                      fgEVENT::FG_EVENT_READY, 30000 );
434
435     // Intialize the moon's position
436     // global_events.Register( "fgMoonInit()", fgMoonInit,
437     //                      fgEVENT::FG_EVENT_READY, 600000 );
438
439     // fgUpdateSunPos() needs a few position and view parameters set
440     // so it can calculate local relative sun angle and a few other
441     // things for correctly orienting the sky.
442     fgUpdateSunPos();
443     fgUpdateMoonPos();
444     global_events.Register( "fgUpdateSunPos()", fgUpdateSunPos,
445                             fgEVENT::FG_EVENT_READY, 60000);
446     global_events.Register( "fgUpdateMoonPos()", fgUpdateMoonPos,
447                             fgEVENT::FG_EVENT_READY, 60000);
448
449     // Initialize Lighting interpolation tables
450     l->Init();
451
452     // update the lighting parameters (based on sun angle)
453     global_events.Register( "fgLight::Update()",
454                             fgMethodCallback<fgLIGHT>( &cur_light_params,
455                                                        &fgLIGHT::Update),
456                             fgEVENT::FG_EVENT_READY, 30000 );
457     // update the current timezone each 30 minutes
458     global_events.Register( "fgUpdateLocalTime()", fgUpdateLocalTime,
459                             fgEVENT::FG_EVENT_READY, 1800000);
460
461     // Initialize the weather modeling subsystem
462 #ifndef FG_OLD_WEATHER
463     // Initialize the WeatherDatabase
464     FG_LOG(FG_GENERAL, FG_INFO, "Creating LocalWeatherDatabase");
465     sgVec3 position;
466     sgSetVec3( position, current_aircraft.fdm_state->get_Latitude(),
467                current_aircraft.fdm_state->get_Longitude(),
468                current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER );
469     FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 
470         new FGLocalWeatherDatabase( position, current_options.get_fg_root() );
471     // cout << theFGLocalWeatherDatabase << endl;
472     // cout << "visibility = " 
473     //      << theFGLocalWeatherDatabase->getWeatherVisibility() << endl;
474
475     WeatherDatabase = FGLocalWeatherDatabase::theFGLocalWeatherDatabase;
476      
477     // register the periodic update of the weather
478     global_events.Register( "weather update", fgUpdateWeatherDatabase,
479                             fgEVENT::FG_EVENT_READY, 30000);
480 #else
481     current_weather.Init();
482 #endif
483
484     // Initialize vor/ndb/ils/fix list management and query systems
485     FG_LOG(FG_GENERAL, FG_INFO, "Loading Navaids");
486
487     FG_LOG(FG_GENERAL, FG_INFO, "  VOR/NDB");
488     current_navlist = new FGNavList;
489     FGPath p_nav( current_options.get_fg_root() );
490     p_nav.append( "Navaids/default.nav" );
491     current_navlist->init( p_nav );
492
493     FG_LOG(FG_GENERAL, FG_INFO, "  ILS");
494     current_ilslist = new FGILSList;
495     FGPath p_ils( current_options.get_fg_root() );
496     p_ils.append( "Navaids/default.ils" );
497     current_ilslist->init( p_ils );
498
499     FG_LOG(FG_GENERAL, FG_INFO, "  Fixes");
500     current_fixlist = new FGFixList;
501     FGPath p_fix( current_options.get_fg_root() );
502     p_fix.append( "Navaids/default.fix" );
503     current_fixlist->init( p_fix );
504
505     // Initialize the underlying radio stack model
506     current_radiostack = new FGRadioStack;
507
508     current_radiostack->set_nav1_freq( 117.30 );
509     current_radiostack->set_nav1_alt_freq( 110.30 );
510     current_radiostack->set_nav1_sel_radial( 119.0 );
511
512     current_radiostack->set_nav2_freq( 111.80 );
513     current_radiostack->set_nav2_alt_freq( 115.70 );
514     current_radiostack->set_nav2_sel_radial( 029.0 );
515
516     current_radiostack->set_adf_freq( 266.0 );
517
518 #if 0
519     // This block of settings are Alex's defaults for San Diego
520     current_radiostack->set_nav1_freq( 111.70 );
521     current_radiostack->set_nav1_alt_freq( 115.30 );
522     current_radiostack->set_nav1_sel_radial( 280.0 );
523     current_radiostack->set_nav2_freq( 117.80 );
524     current_radiostack->set_nav2_alt_freq( 114.00 );
525     current_radiostack->set_nav2_sel_radial( 68.0 );
526     current_radiostack->set_adf_freq( 210.0 );
527     // End of Alex's custom settings
528 #endif
529
530     current_radiostack->search( cur_fdm_state->get_Longitude(),
531                                 cur_fdm_state->get_Latitude(),
532                                 cur_fdm_state->get_Altitude() * FEET_TO_METER );
533
534     current_radiostack->update( cur_fdm_state->get_Longitude(),
535                                 cur_fdm_state->get_Latitude(),
536                                 cur_fdm_state->get_Altitude() * FEET_TO_METER );
537
538     // Search radio database once per second
539     global_events.Register( "fgRadioSearch()", fgRadioSearch,
540                             fgEVENT::FG_EVENT_READY, 1000);
541
542
543     // Initialize the Cockpit subsystem
544     if( fgCockpitInit( &current_aircraft )) {
545         // Cockpit initialized ok.
546     } else {
547         FG_LOG( FG_GENERAL, FG_ALERT, "Error in Cockpit initialization!" );
548         exit(-1);
549     }
550
551     // Initialize the flight model subsystem data structures base on
552     // above values
553
554     // fgFDMInit( current_options.get_flight_model(), cur_fdm_state,
555     //            1.0 / current_options.get_model_hz() );
556     cur_fdm_state->init( 1.0 / current_options.get_model_hz() );
557
558     // I'm just sticking this here for now, it should probably move
559     // eventually
560     scenery.cur_elev = cur_fdm_state->get_Runway_altitude() * FEET_TO_METER;
561
562     if ( cur_fdm_state->get_Altitude() < cur_fdm_state->get_Runway_altitude() + 3.758099) {
563         cur_fdm_state->set_Altitude( cur_fdm_state->get_Runway_altitude() + 3.758099 );
564     }
565
566     FG_LOG( FG_GENERAL, FG_INFO,
567             "Updated position (after elevation adj): ("
568             << (cur_fdm_state->get_Latitude() * RAD_TO_DEG) << ", "
569             << (cur_fdm_state->get_Longitude() * RAD_TO_DEG) << ", "
570             << (cur_fdm_state->get_Altitude() * FEET_TO_METER) << ")" );
571     // end of thing that I just stuck in that I should probably move
572
573     // Joystick support
574     if ( fgJoystickInit() ) {
575         // Joystick initialized ok.
576     } else {
577         FG_LOG( FG_GENERAL, FG_ALERT, "Error in Joystick initialization!" );
578     }
579
580     // Autopilot init
581     current_autopilot = new FGAutopilot;
582     current_autopilot->init();
583
584     // initialize the gui parts of the autopilot
585     NewTgtAirportInit();
586     fgAPAdjustInit() ;
587     NewHeadingInit();
588     NewAltitudeInit();
589
590     // Initialize I/O channels
591 #if ! defined( MACOS )
592     fgIOInit();
593 #endif
594
595     // Initialize the 2D panel.
596     current_panel = fgCreateSmallSinglePropPanel(0, 0, 1024, 768);
597
598     // Initialize the BFI
599     FGBFI::init();
600
601     FG_LOG( FG_GENERAL, FG_INFO, endl);
602
603     return true;
604 }
605
606
607 void fgReInitSubsystems( void )
608 {
609     bool freeze = globals->get_freeze();
610     if( !freeze )
611         globals->set_freeze( true );
612     
613     if( global_tile_mgr.init() ) {
614         // Load the local scenery data
615         global_tile_mgr.update( current_options.get_lon(),
616                                 current_options.get_lat() );
617     } else {
618         FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" );
619                 exit(-1);
620     }
621
622     // cout << "current scenery elev = " << scenery.cur_elev << endl;
623
624     fgInitPosition();
625     fgFDMSetGroundElevation( current_options.get_flight_model(), 
626                              scenery.cur_elev );
627
628     // Reset our altitude if we are below ground
629     FG_LOG( FG_GENERAL, FG_DEBUG, "Current altitude = " << cur_fdm_state->get_Altitude() );
630     FG_LOG( FG_GENERAL, FG_DEBUG, "Current runway altitude = " << 
631             cur_fdm_state->get_Runway_altitude() );
632
633     if ( cur_fdm_state->get_Altitude() < cur_fdm_state->get_Runway_altitude() + 3.758099) {
634         cur_fdm_state->set_Altitude( cur_fdm_state->get_Runway_altitude() + 3.758099 );
635     }
636     double sea_level_radius_meters;
637     double lat_geoc;
638     // Set the FG variables first
639     fgGeodToGeoc( cur_fdm_state->get_Latitude(), cur_fdm_state->get_Altitude(), 
640                   &sea_level_radius_meters, &lat_geoc);
641     cur_fdm_state->set_Geocentric_Position( lat_geoc, cur_fdm_state->get_Longitude(), 
642                                 cur_fdm_state->get_Altitude() + 
643                                 (sea_level_radius_meters * METER_TO_FEET) );
644     cur_fdm_state->set_Sea_level_radius( sea_level_radius_meters * METER_TO_FEET );
645         
646     cur_fdm_state->set_sin_cos_longitude(cur_fdm_state->get_Longitude());
647     cur_fdm_state->set_sin_cos_latitude(cur_fdm_state->get_Latitude());
648         
649     cur_fdm_state->set_sin_lat_geocentric(sin(lat_geoc));
650     cur_fdm_state->set_cos_lat_geocentric(cos(lat_geoc));
651
652     // The following section sets up the flight model EOM parameters
653     // and should really be read in from one or more files.
654
655     // Initial Velocity
656     cur_fdm_state->set_Velocities_Local( current_options.get_uBody(),
657                              current_options.get_vBody(),
658                              current_options.get_wBody());
659
660     // Initial Orientation
661     cur_fdm_state->set_Euler_Angles( current_options.get_roll() * DEG_TO_RAD,
662                          current_options.get_pitch() * DEG_TO_RAD,
663                          current_options.get_heading() * DEG_TO_RAD );
664
665     // Initial Angular Body rates
666     cur_fdm_state->set_Omega_Body( 7.206685E-05, 0.0, 9.492658E-05 );
667
668     cur_fdm_state->set_Earth_position_angle( 0.0 );
669
670     // Mass properties and geometry values
671     cur_fdm_state->set_Inertias( 8.547270E+01, 
672                      1.048000E+03, 3.000000E+03, 3.530000E+03, 0.000000E+00 );
673
674     // CG position w.r.t. ref. point
675     cur_fdm_state->set_CG_Position( 0.0, 0.0, 0.0 );
676
677     // Initialize view parameters
678     current_view.set_view_offset( 0.0 );
679     current_view.set_goal_view_offset( 0.0 );
680     pilot_view.set_view_offset( 0.0 );
681     pilot_view.set_goal_view_offset( 0.0 );
682
683     FG_LOG( FG_GENERAL, FG_DEBUG, "After current_view.init()");
684     current_view.UpdateViewMath(*cur_fdm_state);
685     pilot_view.UpdateViewMath(*cur_fdm_state);
686     FG_LOG( FG_GENERAL, FG_DEBUG, "  abs_view_pos = " << current_view.get_abs_view_pos());
687
688     // fgFDMInit( current_options.get_flight_model(), cur_fdm_state, 
689     //            1.0 / current_options.get_model_hz() );
690     cur_fdm_state->init( 1.0 / current_options.get_model_hz() );
691
692     scenery.cur_elev = cur_fdm_state->get_Runway_altitude() * FEET_TO_METER;
693
694     if ( cur_fdm_state->get_Altitude() < cur_fdm_state->get_Runway_altitude() + 3.758099) {
695         cur_fdm_state->set_Altitude( cur_fdm_state->get_Runway_altitude() + 3.758099 );
696     }
697
698     controls.reset_all();
699     current_autopilot->reset();
700
701     if( !freeze )
702         globals->set_freeze( false );
703 }