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