]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_init.cxx
90c2edd194df841c80189c22ae616a5f4e8f3ed5
[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 SG_MATH_EXCEPTION_CLASH
31 #  include <math.h>
32 #endif
33
34 #ifdef HAVE_WINDOWS_H
35 #  include <windows.h>
36 #endif
37
38 #include <GL/glut.h>
39
40 #include <stdio.h>
41 #include <stdlib.h>
42
43
44 #if defined( unix ) || defined( __CYGWIN__ )
45 #  include <unistd.h>           // for gethostname()
46 #endif
47
48 // work around a stdc++ lib bug in some versions of linux, but doesn't
49 // seem to hurt to have this here for all versions of Linux.
50 #ifdef linux
51 #  define _G_NO_EXTERN_TEMPLATES
52 #endif
53
54 #include <simgear/compiler.h>
55 #include <simgear/misc/exception.hxx>
56
57 #include STL_STRING
58
59 #include <simgear/constants.h>
60 #include <simgear/debug/logstream.hxx>
61 #include <simgear/math/point3d.hxx>
62 #include <simgear/math/polar3d.hxx>
63 #include <simgear/math/sg_geodesy.hxx>
64 #include <simgear/misc/sg_path.hxx>
65 #include <simgear/timing/sg_time.hxx>
66
67 #include <Aircraft/aircraft.hxx>
68 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
69 #include <Airports/runways.hxx>
70 #include <Airports/simple.hxx>
71 #include <Autopilot/auto_gui.hxx>
72 #include <Autopilot/newauto.hxx>
73 #include <Cockpit/cockpit.hxx>
74 #include <Cockpit/radiostack.hxx>
75 #include <Cockpit/panel.hxx>
76 #include <Cockpit/panel_io.hxx>
77 #include <FDM/ADA.hxx>
78 #include <FDM/Balloon.h>
79 #include <FDM/External.hxx>
80 #include <FDM/JSBSim.hxx>
81 #include <FDM/LaRCsim.hxx>
82 #include <FDM/MagicCarpet.hxx>
83 #include <Include/general.hxx>
84 #include <Input/input.hxx>
85 // #include <Joystick/joystick.hxx>
86 #include <Objects/matlib.hxx>
87 #include <Navaids/fixlist.hxx>
88 #include <Navaids/ilslist.hxx>
89 #include <Navaids/mkrbeacons.hxx>
90 #include <Navaids/navlist.hxx>
91 #include <Scenery/scenery.hxx>
92 #include <Scenery/tilemgr.hxx>
93 #include <Time/event.hxx>
94 #include <Time/light.hxx>
95 #include <Time/sunpos.hxx>
96 #include <Time/moonpos.hxx>
97 #include <Time/tmp.hxx>
98
99 #ifndef FG_OLD_WEATHER
100 #  include <WeatherCM/FGLocalWeatherDatabase.h>
101 #else
102 #  include <Weather/weather.hxx>
103 #endif
104
105 #include "fg_init.hxx"
106 #include "fg_io.hxx"
107 #include "fg_commands.hxx"
108 #include "fg_props.hxx"
109 #include "options.hxx"
110 #include "globals.hxx"
111
112 #if defined(FX) && defined(XMESA)
113 #include <GL/xmesa.h>
114 #endif
115
116 SG_USING_STD(string);
117
118 extern const char *default_root;
119
120
121 // Read in configuration (file and command line) and just set fg_root
122 bool fgInitFGRoot ( int argc, char **argv ) {
123     string root;
124     char* envp;
125
126     // First parse command line options looking for fg-root, this will
127     // override anything specified in a config file
128     root = fgScanForRoot(argc, argv);
129
130 #if defined( unix ) || defined( __CYGWIN__ )
131     // Next check home directory for .fgfsrc.hostname file
132     if ( root == "" ) {
133         envp = ::getenv( "HOME" );
134         if ( envp != NULL ) {
135             SGPath config( envp );
136             config.append( ".fgfsrc" );
137             char name[256];
138             gethostname( name, 256 );
139             config.concat( "." );
140             config.concat( name );
141             root = fgScanForRoot(config.str());
142         }
143     }
144 #endif
145
146     // Next check home directory for .fgfsrc file
147     if ( root == "" ) {
148         envp = ::getenv( "HOME" );
149         if ( envp != NULL ) {
150             SGPath config( envp );
151             config.append( ".fgfsrc" );
152             root = fgScanForRoot(config.str());
153         }
154     }
155     
156     // Next check if fg-root is set as an env variable
157     if ( root == "" ) {
158         envp = ::getenv( "FG_ROOT" );
159         if ( envp != NULL ) {
160             root = envp;
161         }
162     }
163
164     // Otherwise, default to a random compiled-in location if we can't
165     // find fg-root any other way.
166     if ( root == "" ) {
167 #if defined( __CYGWIN__ )
168         root = "/FlightGear";
169 #elif defined( WIN32 )
170         root = "\\FlightGear";
171 #elif defined( macintosh )
172         root = "";
173 #else
174         root = PKGLIBDIR;
175 #endif
176     }
177
178     SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root );
179     globals->set_fg_root(root);
180
181     return true;
182 }
183
184
185 // Return the current base package version
186 string fgBasePackageVersion() {
187     SGPath base_path( globals->get_fg_root() );
188     base_path.append("version");
189
190     sg_gzifstream in( base_path.str() );
191     if ( !in.is_open() ) {
192         SGPath old_path( globals->get_fg_root() );
193         old_path.append( "Thanks" );
194         sg_gzifstream old( old_path.str() );
195         if ( !old.is_open() ) {
196             return "[none]";
197         } else {
198             return "[old version]";
199         }
200     }
201
202     string version;
203     in >> version;
204
205     return version;
206 }
207
208
209 // Read in configuration (file and command line)
210 bool fgInitConfig ( int argc, char **argv ) {
211
212                                 // First, set some sane default values
213     fgSetDefaults();
214
215     // Read global preferences from $FG_ROOT/preferences.xml
216     SGPath props_path(globals->get_fg_root());
217     props_path.append("preferences.xml");
218     SG_LOG(SG_INPUT, SG_INFO, "Reading global preferences");
219     try {
220       readProperties(props_path.str(), globals->get_props());
221     } catch (const sg_io_exception &e) {
222       string message = "Error reading global preferences: ";
223       message += e.getMessage();
224       message += "\n at ";
225       message += e.getLocation().asString();
226       SG_LOG(SG_INPUT, SG_ALERT, message);
227       exit(2);
228     }
229     SG_LOG(SG_INPUT, SG_INFO, "Finished Reading global preferences");
230
231     // Attempt to locate and parse the various config files in order
232     // from least precidence to greatest precidence
233
234     // Check for $fg_root/system.fgfsrc
235     SGPath config( globals->get_fg_root() );
236     config.append( "system.fgfsrc" );
237     fgParseOptions(config.str());
238
239     char name[256];
240 #if defined( unix ) || defined( __CYGWIN__ )
241     // Check for $fg_root/system.fgfsrc.hostname
242     gethostname( name, 256 );
243     config.concat( "." );
244     config.concat( name );
245     fgParseOptions(config.str());
246 #endif
247
248     // Check for ~/.fgfsrc
249     char* envp = ::getenv( "HOME" );
250     if ( envp != NULL ) {
251         config.set( envp );
252         config.append( ".fgfsrc" );
253         fgParseOptions(config.str());
254     }
255
256 #if defined( unix ) || defined( __CYGWIN__ )
257     // Check for ~/.fgfsrc.hostname
258     gethostname( name, 256 );
259     config.concat( "." );
260     config.concat( name );
261     fgParseOptions(config.str());
262 #endif
263
264     // Parse remaining command line options
265     // These will override anything specified in a config file
266     fgParseOptions(argc, argv);
267
268     return true;
269 }
270
271
272 // find basic airport location info from airport database
273 bool fgFindAirportID( const string& id, FGAirport *a ) {
274     if ( id.length() ) {
275         SGPath path( globals->get_fg_root() );
276         path.append( "Airports" );
277         path.append( "simple.mk4" );
278         FGAirports airports( path.c_str() );
279
280         SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
281
282         if ( ! airports.search( id, a ) ) {
283             SG_LOG( SG_GENERAL, SG_ALERT,
284                     "Failed to find " << id << " in " << path.str() );
285             return false;
286         }
287     } else {
288         return false;
289     }
290
291     SG_LOG( SG_GENERAL, SG_INFO,
292             "Position for " << id << " is ("
293             << a->longitude << ", "
294             << a->latitude << ")" );
295
296     return true;
297 }
298
299
300 // Set current_options lon/lat given an airport id
301 bool fgSetPosFromAirportID( const string& id ) {
302     FGAirport a;
303     // double lon, lat;
304
305     SG_LOG( SG_GENERAL, SG_INFO,
306             "Attempting to set starting position from airport code " << id );
307
308     if ( fgFindAirportID( id, &a ) ) {
309         fgSetDouble("/position/longitude-deg",  a.longitude );
310         fgSetDouble("/position/latitude-deg",  a.latitude );
311         SG_LOG( SG_GENERAL, SG_INFO,
312                 "Position for " << id << " is ("
313                 << a.longitude << ", "
314                 << a.latitude << ")" );
315
316         return true;
317     } else {
318         return false;
319     }
320
321 }
322
323
324 // Set current_options lon/lat given an airport id and heading (degrees)
325 bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
326     FGRunway r;
327     FGRunway found_r;
328     double found_dir = 0.0;
329
330     if ( id.length() ) {
331         // set initial position from runway and heading
332
333         SGPath path( globals->get_fg_root() );
334         path.append( "Airports" );
335         path.append( "runways.mk4" );
336         FGRunways runways( path.c_str() );
337
338         SG_LOG( SG_GENERAL, SG_INFO,
339                 "Attempting to set starting position from runway code "
340                 << id << " heading " << tgt_hdg );
341
342         // SGPath inpath( globals->get_fg_root() );
343         // inpath.append( "Airports" );
344         // inpath.append( "apt_simple" );
345         // airports.load( inpath.c_str() );
346
347         // SGPath outpath( globals->get_fg_root() );
348         // outpath.append( "Airports" );
349         // outpath.append( "simple.gdbm" );
350         // airports.dump_gdbm( outpath.c_str() );
351
352         if ( ! runways.search( id, &r ) ) {
353             SG_LOG( SG_GENERAL, SG_ALERT,
354                     "Failed to find " << id << " in database." );
355             return false;
356         }
357
358         double diff;
359         double min_diff = 360.0;
360
361         while ( r.id == id ) {
362             // forward direction
363             diff = tgt_hdg - r.heading;
364             while ( diff < -180.0 ) { diff += 360.0; }
365             while ( diff >  180.0 ) { diff -= 360.0; }
366             diff = fabs(diff);
367             SG_LOG( SG_GENERAL, SG_INFO,
368                     "Runway " << r.rwy_no << " heading = " << r.heading <<
369                     " diff = " << diff );
370             if ( diff < min_diff ) {
371                 min_diff = diff;
372                 found_r = r;
373                 found_dir = 0;
374             }
375
376             // reverse direction
377             diff = tgt_hdg - r.heading - 180.0;
378             while ( diff < -180.0 ) { diff += 360.0; }
379             while ( diff >  180.0 ) { diff -= 360.0; }
380             diff = fabs(diff);
381             SG_LOG( SG_GENERAL, SG_INFO,
382                     "Runway -" << r.rwy_no << " heading = " <<
383                     r.heading + 180.0 <<
384                     " diff = " << diff );
385             if ( diff < min_diff ) {
386                 min_diff = diff;
387                 found_r = r;
388                 found_dir = 180.0;
389             }
390
391             runways.next( &r );
392         }
393
394         SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << found_r.rwy_no
395                 << " + " << found_dir );
396
397     } else {
398         return false;
399     }
400
401     double heading = found_r.heading + found_dir;
402     while ( heading >= 360.0 ) { heading -= 360.0; }
403
404     double lat2, lon2, az2;
405     double azimuth = found_r.heading + found_dir + 180.0;
406     while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
407
408     SG_LOG( SG_GENERAL, SG_INFO,
409             "runway =  " << found_r.lon << ", " << found_r.lat
410             << " length = " << found_r.length * SG_FEET_TO_METER * 0.5 
411             << " heading = " << azimuth );
412     
413     geo_direct_wgs_84 ( 0, found_r.lat, found_r.lon, 
414                         azimuth, found_r.length * SG_FEET_TO_METER * 0.5 - 5.0,
415                         &lat2, &lon2, &az2 );
416
417     if ( fabs( fgGetDouble("/sim/startup/offset-distance") ) > SG_EPSILON ) {
418         double olat, olon;
419         double odist = fgGetDouble("/sim/startup/offset-distance");
420         odist *= SG_NM_TO_METER;
421         double oaz = azimuth;
422         if ( fabs(fgGetDouble("/sim/startup/offset-azimuth")) > SG_EPSILON ) {
423             oaz = fgGetDouble("/sim/startup/offset-azimuth") + 180;
424         }
425         while ( oaz >= 360.0 ) { oaz -= 360.0; }
426         geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 );
427         lat2=olat;
428         lon2=olon;
429     }
430     fgSetDouble("/position/longitude-deg",  lon2 );
431     fgSetDouble("/position/latitude-deg",  lat2 );
432     fgSetDouble("/orientation/heading-deg", heading );
433
434     SG_LOG( SG_GENERAL, SG_INFO,
435             "Position for " << id << " is ("
436             << lon2 << ", "
437             << lat2 << ") new heading is "
438             << heading );
439
440     return true;
441 }
442
443
444 // General house keeping initializations
445 bool fgInitGeneral( void ) {
446     string root;
447
448 #if defined(FX) && defined(XMESA)
449     char *mesa_win_state;
450 #endif
451
452     SG_LOG( SG_GENERAL, SG_INFO, "General Initialization" );
453     SG_LOG( SG_GENERAL, SG_INFO, "======= ==============" );
454
455     root = globals->get_fg_root();
456     if ( ! root.length() ) {
457         // No root path set? Then bail ...
458         SG_LOG( SG_GENERAL, SG_ALERT,
459                 "Cannot continue without environment variable FG_ROOT"
460                 << "being defined." );
461         exit(-1);
462     }
463     SG_LOG( SG_GENERAL, SG_INFO, "FG_ROOT = " << '"' << root << '"' << endl );
464
465 #if defined(FX) && defined(XMESA)
466     // initialize full screen flag
467     global_fullscreen = false;
468     if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
469         // Test for the MESA_GLX_FX env variable
470         if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
471             // test if we are fullscreen mesa/glide
472             if ( (mesa_win_state[0] == 'f') ||
473                  (mesa_win_state[0] == 'F') ) {
474                 global_fullscreen = true;
475             }
476         }
477     }
478 #endif
479
480     return true;
481 }
482
483
484 // This is the top level init routine which calls all the other
485 // initialization routines.  If you are adding a subsystem to flight
486 // gear, its initialization call should located in this routine.
487 // Returns non-zero if a problem encountered.
488 bool fgInitSubsystems( void ) {
489     fgLIGHT *l = &cur_light_params;
490
491     SG_LOG( SG_GENERAL, SG_INFO, "Initialize Subsystems");
492     SG_LOG( SG_GENERAL, SG_INFO, "========== ==========");
493
494
495     ////////////////////////////////////////////////////////////////////
496     // Initialize the material property subsystem.
497     ////////////////////////////////////////////////////////////////////
498
499     SGPath mpath( globals->get_fg_root() );
500     mpath.append( "materials" );
501     if ( material_lib.load( mpath.str() ) ) {
502     } else {
503         SG_LOG( SG_GENERAL, SG_ALERT, "Error loading material lib!" );
504         exit(-1);
505     }
506
507
508     ////////////////////////////////////////////////////////////////////
509     // Initialize the scenery management subsystem.
510     ////////////////////////////////////////////////////////////////////
511
512     if ( fgSceneryInit() ) {
513         // Material lib initialized ok.
514     } else {
515         SG_LOG( SG_GENERAL, SG_ALERT, "Error in Scenery initialization!" );
516         exit(-1);
517     }
518
519     if ( global_tile_mgr.init() ) {
520         // Load the local scenery data
521         global_tile_mgr.update( fgGetDouble("/position/longitude-deg"),
522                                 fgGetDouble("/position/latitude-deg") );
523     } else {
524         SG_LOG( SG_GENERAL, SG_ALERT, "Error in Tile Manager initialization!" );
525         exit(-1);
526     }
527
528     SG_LOG( SG_GENERAL, SG_DEBUG,
529             "Current terrain elevation after tile mgr init " <<
530             scenery.cur_elev );
531
532
533     ////////////////////////////////////////////////////////////////////
534     // Initialize the flight model subsystem.
535     ////////////////////////////////////////////////////////////////////
536
537     double dt = 1.0 / fgGetInt("/sim/model-hz");
538     // cout << "dt = " << dt << endl;
539
540     aircraft_dir = fgGetString("/sim/aircraft-dir");
541     const string &model = fgGetString("/sim/flight-model");
542     try {
543         if (model == "larcsim") {
544             cur_fdm_state = new FGLaRCsim( dt );
545         } else if (model == "jsb") {
546             cur_fdm_state = new FGJSBsim( dt );
547         } else if (model == "ada") {
548             cur_fdm_state = new FGADA( dt );
549         } else if (model == "balloon") {
550             cur_fdm_state = new FGBalloonSim( dt );
551         } else if (model == "magic") {
552             cur_fdm_state = new FGMagicCarpet( dt );
553         } else if (model == "external") {
554             cur_fdm_state = new FGExternal( dt );
555         } else {
556             SG_LOG(SG_GENERAL, SG_ALERT,
557                    "Unrecognized flight model '" << model
558                    << ", can't init aircraft");
559             exit(-1);
560         }
561     } catch ( ... ) {
562         SG_LOG(SG_GENERAL, SG_ALERT, "FlightGear aborting\n\n");
563         exit(-1);
564     }
565
566     cur_fdm_state->init();
567     cur_fdm_state->bind();
568     
569     // allocates structures so must happen before any of the flight
570     // model or control parameters are set
571     fgAircraftInit();   // In the future this might not be the case.
572
573
574     ////////////////////////////////////////////////////////////////////
575     // Initialize the event manager subsystem.
576     ////////////////////////////////////////////////////////////////////
577
578     global_events.Init();
579
580     // Output event stats every 60 seconds
581     global_events.Register( "fgEVENT_MGR::PrintStats()",
582                             fgMethodCallback<fgEVENT_MGR>( &global_events,
583                                                    &fgEVENT_MGR::PrintStats),
584                             fgEVENT::FG_EVENT_READY, 60000 );
585
586
587     ////////////////////////////////////////////////////////////////////
588     // Initialize the view manager subsystem.
589     ////////////////////////////////////////////////////////////////////
590
591     // Initialize win_ratio parameters
592     for ( int i = 0; i < globals->get_viewmgr()->size(); ++i ) {
593         globals->get_viewmgr()->get_view(i)->
594             set_win_ratio( fgGetInt("/sim/startup/xsize") /
595                            fgGetInt("/sim/startup/ysize") );
596     }
597
598     // Initialize pilot view
599     FGViewerRPH *pilot_view =
600         (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
601
602     pilot_view->set_geod_view_pos( cur_fdm_state->get_Longitude(), 
603                                    cur_fdm_state->get_Lat_geocentric(), 
604                                    cur_fdm_state->get_Altitude() *
605                                    SG_FEET_TO_METER );
606     pilot_view->set_sea_level_radius( cur_fdm_state->get_Sea_level_radius() *
607                                       SG_FEET_TO_METER ); 
608     pilot_view->set_rph( cur_fdm_state->get_Phi(),
609                          cur_fdm_state->get_Theta(),
610                          cur_fdm_state->get_Psi() );
611
612     // set current view to 0 (first) which is our main pilot view
613     globals->set_current_view( pilot_view );
614
615     SG_LOG( SG_GENERAL, SG_DEBUG, "  abs_view_pos = "
616             << globals->get_current_view()->get_abs_view_pos());
617
618
619     ////////////////////////////////////////////////////////////////////
620     // Initialize the lighting subsystem.
621     ////////////////////////////////////////////////////////////////////
622
623     // fgUpdateSunPos() needs a few position and view parameters set
624     // so it can calculate local relative sun angle and a few other
625     // things for correctly orienting the sky.
626     fgUpdateSunPos();
627     fgUpdateMoonPos();
628     global_events.Register( "fgUpdateSunPos()", fgUpdateSunPos,
629                             fgEVENT::FG_EVENT_READY, 60000);
630     global_events.Register( "fgUpdateMoonPos()", fgUpdateMoonPos,
631                             fgEVENT::FG_EVENT_READY, 60000);
632
633     // Initialize Lighting interpolation tables
634     l->Init();
635
636     // update the lighting parameters (based on sun angle)
637     global_events.Register( "fgLight::Update()",
638                             fgMethodCallback<fgLIGHT>( &cur_light_params,
639                                                        &fgLIGHT::Update),
640                             fgEVENT::FG_EVENT_READY, 30000 );
641
642
643     ////////////////////////////////////////////////////////////////////
644     // Initialize the local time subsystem.
645     ////////////////////////////////////////////////////////////////////
646
647     // update the current timezone each 30 minutes
648     global_events.Register( "fgUpdateLocalTime()", fgUpdateLocalTime,
649                             fgEVENT::FG_EVENT_READY, 1800000);
650
651
652     ////////////////////////////////////////////////////////////////////
653     // Initialize the weather subsystem.
654     ////////////////////////////////////////////////////////////////////
655
656     // Initialize the weather modeling subsystem
657 #ifndef FG_OLD_WEATHER
658     // Initialize the WeatherDatabase
659     SG_LOG(SG_GENERAL, SG_INFO, "Creating LocalWeatherDatabase");
660     sgVec3 position;
661     sgSetVec3( position, current_aircraft.fdm_state->get_Latitude(),
662                current_aircraft.fdm_state->get_Longitude(),
663                current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER );
664     double init_vis = fgGetDouble("/environment/visibility-m");
665
666     FGLocalWeatherDatabase::DatabaseWorkingType working_type;
667
668     if (fgGetString("/environment/weather/working-type") == "internet")
669     {
670       working_type = FGLocalWeatherDatabase::use_internet;
671     } else {
672       working_type = FGLocalWeatherDatabase::default_mode;
673     }
674     
675     if ( init_vis > 0 ) {
676       FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 
677         new FGLocalWeatherDatabase( position,
678                                     globals->get_fg_root(),
679                                     working_type,
680                                     init_vis );
681     } else {
682       FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 
683         new FGLocalWeatherDatabase( position,
684                                     globals->get_fg_root(),
685                                     working_type );
686     }
687
688     // cout << theFGLocalWeatherDatabase << endl;
689     // cout << "visibility = " 
690     //      << theFGLocalWeatherDatabase->getWeatherVisibility() << endl;
691
692     WeatherDatabase = FGLocalWeatherDatabase::theFGLocalWeatherDatabase;
693
694     // register the periodic update of the weather
695     global_events.Register( "weather update", fgUpdateWeatherDatabase,
696                             fgEVENT::FG_EVENT_READY, 30000);
697 #else
698     current_weather.Init();
699 #endif
700
701     ////////////////////////////////////////////////////////////////////
702     // Initialize vor/ndb/ils/fix list management and query systems
703     ////////////////////////////////////////////////////////////////////
704
705     SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaids");
706
707     SG_LOG(SG_GENERAL, SG_INFO, "  VOR/NDB");
708     current_navlist = new FGNavList;
709     SGPath p_nav( globals->get_fg_root() );
710     p_nav.append( "Navaids/default.nav" );
711     current_navlist->init( p_nav );
712
713     SG_LOG(SG_GENERAL, SG_INFO, "  ILS and Marker Beacons");
714     current_beacons = new FGMarkerBeacons;
715     current_beacons->init();
716     current_ilslist = new FGILSList;
717     SGPath p_ils( globals->get_fg_root() );
718     p_ils.append( "Navaids/default.ils" );
719     current_ilslist->init( p_ils );
720
721     SG_LOG(SG_GENERAL, SG_INFO, "  Fixes");
722     current_fixlist = new FGFixList;
723     SGPath p_fix( globals->get_fg_root() );
724     p_fix.append( "Navaids/default.fix" );
725     current_fixlist->init( p_fix );
726
727
728     ////////////////////////////////////////////////////////////////////
729     // Initialize the built-in commands.
730     ////////////////////////////////////////////////////////////////////
731     fgInitCommands();
732
733
734     ////////////////////////////////////////////////////////////////////
735     // Initialize the radio stack subsystem.
736     ////////////////////////////////////////////////////////////////////
737
738                                 // A textbook example of how FGSubsystem
739                                 // should work...
740     current_radiostack = new FGRadioStack;
741     current_radiostack->init();
742     current_radiostack->bind();
743
744
745     ////////////////////////////////////////////////////////////////////
746     // Initialize the cockpit subsystem
747     ////////////////////////////////////////////////////////////////////
748
749     if( fgCockpitInit( &current_aircraft )) {
750         // Cockpit initialized ok.
751     } else {
752         SG_LOG( SG_GENERAL, SG_ALERT, "Error in Cockpit initialization!" );
753         exit(-1);
754     }
755
756
757     ////////////////////////////////////////////////////////////////////
758     // Initialize the joystick subsystem.
759     ////////////////////////////////////////////////////////////////////
760
761     // if ( ! fgJoystickInit() ) {
762     //   SG_LOG( SG_GENERAL, SG_ALERT, "Error in Joystick initialization!" );
763     // }
764
765
766     ////////////////////////////////////////////////////////////////////
767     // Initialize the autopilot subsystem.
768     ////////////////////////////////////////////////////////////////////
769
770     current_autopilot = new FGAutopilot;
771     current_autopilot->init();
772
773     // initialize the gui parts of the autopilot
774     NewTgtAirportInit();
775     fgAPAdjustInit() ;
776     NewHeadingInit();
777     NewAltitudeInit();
778
779     
780     ////////////////////////////////////////////////////////////////////
781     // Initialize I/O subsystem.
782     ////////////////////////////////////////////////////////////////////
783
784 #if ! defined( macintosh )
785     fgIOInit();
786 #endif
787
788     // Initialize the 2D panel.
789     string panel_path = fgGetString("/sim/panel/path",
790                                     "Panels/Default/default.xml");
791     current_panel = fgReadPanel(panel_path);
792     if (current_panel == 0) {
793         SG_LOG( SG_INPUT, SG_ALERT, 
794                 "Error reading new panel from " << panel_path );
795     } else {
796         SG_LOG( SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path );
797         current_panel->init();
798         current_panel->bind();
799     }
800
801     
802     ////////////////////////////////////////////////////////////////////
803     // Initialize the default (kludged) properties.
804     ////////////////////////////////////////////////////////////////////
805
806     fgInitProps();
807
808
809     ////////////////////////////////////////////////////////////////////
810     // Initialize the controls subsystem.
811     ////////////////////////////////////////////////////////////////////
812
813     controls.init();
814     controls.bind();
815
816
817     ////////////////////////////////////////////////////////////////////
818     // Initialize the input subsystem.
819     ////////////////////////////////////////////////////////////////////
820
821     current_input.init();
822     current_input.bind();
823
824
825     ////////////////////////////////////////////////////////////////////////
826     // End of subsystem initialization.
827     ////////////////////////////////////////////////////////////////////
828
829     SG_LOG( SG_GENERAL, SG_INFO, endl);
830
831                                 // Save the initial state for future
832                                 // reference.
833     globals->saveInitialState();
834
835     return true;
836 }
837
838
839 void fgReInitSubsystems( void )
840 {
841     SG_LOG( SG_GENERAL, SG_INFO,
842             "/position/altitude = " << fgGetDouble("/position/altitude-ft") );
843
844     bool freeze = globals->get_freeze();
845     if( !freeze )
846         globals->set_freeze( true );
847     
848     // Initialize the Scenery Management subsystem
849     if ( ! fgSceneryInit() ) {
850         SG_LOG( SG_GENERAL, SG_ALERT, "Error in Scenery initialization!" );
851         exit(-1);
852     }
853
854     if( global_tile_mgr.init() ) {
855         // Load the local scenery data
856         global_tile_mgr.update( fgGetDouble("/position/longitude-deg"),
857                                 fgGetDouble("/position/latitude-deg") );
858     } else {
859         SG_LOG( SG_GENERAL, SG_ALERT, "Error in Tile Manager initialization!" );
860                 exit(-1);
861     }
862
863     // Initialize view parameters
864     FGViewerRPH *pilot_view =
865         (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
866
867     pilot_view->set_view_offset( 0.0 );
868     pilot_view->set_goal_view_offset( 0.0 );
869
870     pilot_view->set_geod_view_pos( cur_fdm_state->get_Longitude(), 
871                                    cur_fdm_state->get_Lat_geocentric(), 
872                                    cur_fdm_state->get_Altitude() *
873                                    SG_FEET_TO_METER );
874     pilot_view->set_sea_level_radius( cur_fdm_state->get_Sea_level_radius() *
875                                       SG_FEET_TO_METER ); 
876     pilot_view->set_rph( cur_fdm_state->get_Phi(),
877                          cur_fdm_state->get_Theta(),
878                          cur_fdm_state->get_Psi() );
879
880     // set current view to 0 (first) which is our main pilot view
881     globals->set_current_view( pilot_view );
882
883     SG_LOG( SG_GENERAL, SG_DEBUG, "  abs_view_pos = "
884             << globals->get_current_view()->get_abs_view_pos());
885
886     cur_fdm_state->init();
887
888     controls.reset_all();
889     current_autopilot->reset();
890
891     fgUpdateSunPos();
892     fgUpdateMoonPos();
893     cur_light_params.Update();
894     fgUpdateLocalTime();
895
896     if( !freeze )
897         globals->set_freeze( false );
898 }