]> git.mxchange.org Git - flightgear.git/blob - src/Main/bfi.cxx
Updates to time parsing and setting by David Megginson.
[flightgear.git] / src / Main / bfi.cxx
1 // bfi.cxx - Big Friendly Interface implementation
2 //
3 // Written by David Megginson, started February, 2000.
4 //
5 // Copyright (C) 2000  David Megginson - david@megginson.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 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #if defined( FG_HAVE_NATIVE_SGI_COMPILERS )
29 #  include <iostream.h>
30 #else
31 #  include <iostream>
32 #endif
33
34 #include <simgear/constants.h>
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/ephemeris/ephemeris.hxx>
37 #include <simgear/math/sg_types.hxx>
38 #include <simgear/misc/props.hxx>
39 #include <simgear/timing/sg_time.hxx>
40
41 #include <Aircraft/aircraft.hxx>
42 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
43 #include <Controls/controls.hxx>
44 #include <Autopilot/newauto.hxx>
45 #include <Scenery/scenery.hxx>
46 #include <Time/light.hxx>
47 #include <Time/event.hxx>
48 #include <Time/sunpos.hxx>
49 #include <Time/tmp.hxx>
50 #include <Cockpit/radiostack.hxx>
51 #include <Cockpit/panel.hxx>
52 #ifndef FG_OLD_WEATHER
53 #  include <WeatherCM/FGLocalWeatherDatabase.h>
54 #else
55 #  include <Weather/weather.hxx>
56 #endif
57
58 #include "globals.hxx"
59 #include "save.hxx"
60 #include "fg_init.hxx"
61 #include <simgear/misc/props.hxx>
62
63 FG_USING_NAMESPACE(std);
64
65
66 #include "bfi.hxx"
67
68
69 \f
70 ////////////////////////////////////////////////////////////////////////
71 // Static variables.
72 ////////////////////////////////////////////////////////////////////////
73
74                                 // Yech -- not thread-safe, etc. etc.
75 static bool _needReinit = false;
76 static string _temp;
77
78 static inline void needReinit ()
79 {
80   _needReinit = true;
81 }
82
83
84 /**
85  * Reinitialize FGFS to use the new BFI settings.
86  */
87 static inline void
88 reinit ()
89 {
90                                 // Save the state of everything
91                                 // that's going to get clobbered
92                                 // when we reinit the subsystems.
93
94   cout << "BFI: start reinit\n";
95
96                                 // TODO: add more AP stuff
97   double elevator = FGBFI::getElevator();
98   double aileron = FGBFI::getAileron();
99   double rudder = FGBFI::getRudder();
100   double throttle = FGBFI::getThrottle();
101   double elevator_trim = FGBFI::getElevatorTrim();
102   double flaps = FGBFI::getFlaps();
103   double brake = FGBFI::getBrakes();
104   bool apHeadingLock = FGBFI::getAPHeadingLock();
105   double apHeadingMag = FGBFI::getAPHeadingMag();
106   bool apAltitudeLock = FGBFI::getAPAltitudeLock();
107   double apAltitude = FGBFI::getAPAltitude();
108   const string &targetAirport = FGBFI::getTargetAirport();
109   bool gpsLock = FGBFI::getGPSLock();
110   // double gpsLatitude = FGBFI::getGPSTargetLatitude();
111   // double gpsLongitude = FGBFI::getGPSTargetLongitude();
112
113   FGBFI::setTargetAirport("");
114   cout << "Target airport is " << globals->get_options()->get_airport_id() << endl;
115
116   fgReInitSubsystems();
117
118                                 // FIXME: this is wrong.
119                                 // All of these are scheduled events,
120                                 // and it should be possible to force
121                                 // them all to run once.
122   fgUpdateSunPos();
123   fgUpdateMoonPos();
124   cur_light_params.Update();
125   fgUpdateLocalTime();
126   fgUpdateWeatherDatabase();
127   fgRadioSearch();
128
129                                 // Restore all of the old states.
130   FGBFI::setElevator(elevator);
131   FGBFI::setAileron(aileron);
132   FGBFI::setRudder(rudder);
133   FGBFI::setThrottle(throttle);
134   FGBFI::setElevatorTrim(elevator_trim);
135   FGBFI::setFlaps(flaps);
136   FGBFI::setBrakes(brake);
137   FGBFI::setAPHeadingLock(apHeadingLock);
138   FGBFI::setAPHeadingMag(apHeadingMag);
139   FGBFI::setAPAltitudeLock(apAltitudeLock);
140   FGBFI::setAPAltitude(apAltitude);
141   FGBFI::setTargetAirport(targetAirport);
142   FGBFI::setGPSLock(gpsLock);
143
144   _needReinit = false;
145
146   cout << "BFI: end reinit\n";
147 }
148
149
150 \f
151 ////////////////////////////////////////////////////////////////////////
152 // Local functions
153 ////////////////////////////////////////////////////////////////////////
154
155
156 /**
157  * Initialize the BFI by binding its functions to properties.
158  *
159  * TODO: perhaps these should migrate into the individual modules
160  * (i.e. they should register themselves).
161  */
162 void
163 FGBFI::init ()
164 {
165   FG_LOG(FG_GENERAL, FG_INFO, "Starting BFI init");
166                                 // Simulation
167   current_properties.tieInt("/sim/flight-model",
168                             getFlightModel, setFlightModel);
169   current_properties.tieString("/sim/aircraft",
170                                getAircraft, setAircraft);
171   current_properties.tieString("/sim/aircraft-dir",
172                                getAircraftDir, setAircraftDir);
173   // TODO: timeGMT
174   current_properties.tieString("/sim/time/gmt",
175                                getDateString, setDateString);
176   current_properties.tieString("/sim/time/gmt-string",
177                                getGMTString, 0);
178   current_properties.tieBool("/sim/hud/visibility",
179                              getHUDVisible, setHUDVisible);
180   current_properties.tieBool("/sim/panel/visibility",
181                              getPanelVisible, setPanelVisible);
182   current_properties.tieInt("/sim/panel/x-offset",
183                             getPanelXOffset, setPanelXOffset);
184   current_properties.tieInt("/sim/panel/y-offset",
185                             getPanelYOffset, setPanelYOffset);
186
187                                 // Position
188   current_properties.tieString("/position/airport-id",
189                                 getTargetAirport, setTargetAirport);
190   current_properties.tieDouble("/position/latitude",
191                                 getLatitude, setLatitude);
192   current_properties.tieDouble("/position/longitude",
193                                getLongitude, setLongitude);
194   current_properties.tieDouble("/position/altitude",
195                                getAltitude, setAltitude);
196 //                             getAltitude, setAltitude, false);
197   current_properties.tieDouble("/position/altitude-agl",
198                                getAGL, 0);
199
200                                 // Orientation
201   current_properties.tieDouble("/orientation/heading",
202                                getHeading, setHeading);
203   current_properties.tieDouble("/orientation/heading-magnetic",
204                                getHeadingMag, 0);
205   current_properties.tieDouble("/orientation/pitch",
206                                getPitch, setPitch);
207   current_properties.tieDouble("/orientation/roll",
208                                getRoll, setRoll);
209
210                                 // Engine
211   current_properties.tieDouble("/engines/engine0/rpm",
212                                getRPM, 0);
213   current_properties.tieDouble("/engines/engine0/egt",
214                                getEGT, 0);
215   current_properties.tieDouble("/engines/engine0/cht",
216                                getCHT, 0);
217   current_properties.tieDouble("/engines/engine0/mp",
218                                getMP, 0);
219
220                                 // Velocities
221   current_properties.tieDouble("/velocities/airspeed",
222                                getAirspeed, setAirspeed);
223   current_properties.tieDouble("/velocities/side-slip",
224                                getSideSlip, 0);
225   current_properties.tieDouble("/velocities/vertical-speed",
226                                getVerticalSpeed, 0);
227   current_properties.tieDouble("/velocities/speed-north",
228                                getSpeedNorth, 0);
229   current_properties.tieDouble("/velocities/speed-east",
230                                getSpeedEast, 0);
231   current_properties.tieDouble("/velocities/speed-down",
232                                getSpeedDown, 0);
233
234                                 // Controls
235   current_properties.tieDouble("/controls/throttle",
236                                getThrottle, setThrottle);
237   current_properties.tieDouble("/controls/mixture",
238                                getMixture, setMixture);
239   current_properties.tieDouble("/controls/propellor-pitch",
240                                getPropAdvance, setPropAdvance);
241   current_properties.tieDouble("/controls/flaps",
242                                getFlaps, setFlaps);
243   current_properties.tieDouble("/controls/aileron",
244                                getAileron, setAileron);
245   current_properties.tieDouble("/controls/rudder",
246                                getRudder, setRudder);
247   current_properties.tieDouble("/controls/elevator",
248                                getElevator, setElevator);
249   current_properties.tieDouble("/controls/elevator-trim",
250                                getElevatorTrim, setElevatorTrim);
251   current_properties.tieDouble("/controls/brakes/all",
252                                getBrakes, setBrakes);
253   current_properties.tieDouble("/controls/brakes/left",
254                                getLeftBrake, setLeftBrake);
255   current_properties.tieDouble("/controls/brakes/right",
256                                getRightBrake, setRightBrake);
257   current_properties.tieDouble("/controls/brakes/center",
258                                getRightBrake, setCenterBrake);
259
260                                 // Autopilot
261   current_properties.tieBool("/autopilot/locks/altitude",
262                              getAPAltitudeLock, setAPAltitudeLock);
263   current_properties.tieDouble("/autopilot/settings/altitude",
264                                getAPAltitude, setAPAltitude);
265   current_properties.tieBool("/autopilot/locks/heading",
266                              getAPHeadingLock, setAPHeadingLock);
267   current_properties.tieDouble("/autopilot/settings/heading",
268                                getAPHeading, setAPHeading);
269   current_properties.tieDouble("/autopilot/settings/heading-magnetic",
270                                getAPHeadingMag, setAPHeadingMag);
271   current_properties.tieBool("/autopilot/locks/nav1",
272                              getAPNAV1Lock, setAPNAV1Lock);
273
274                                 // Radio navigation
275   current_properties.tieDouble("/radios/nav1/frequencies/selected",
276                                getNAV1Freq, setNAV1Freq);
277   current_properties.tieDouble("/radios/nav1/frequencies/standby",
278                                getNAV1AltFreq, setNAV1AltFreq);
279   current_properties.tieDouble("/radios/nav1/radials/actual",
280                                getNAV1Radial, 0);
281   current_properties.tieDouble("/radios/nav1/radials/selected",
282                                getNAV1SelRadial, setNAV1SelRadial);
283   current_properties.tieDouble("/radios/nav1/dme/distance",
284                                getNAV1DistDME, 0);
285   current_properties.tieBool("/radios/nav1/to-flag",
286                              getNAV1TO, 0);
287   current_properties.tieBool("/radios/nav1/from-flag",
288                              getNAV1FROM, 0);
289   current_properties.tieBool("/radios/nav1/in-range",
290                              getNAV1InRange, 0);
291   current_properties.tieBool("/radios/nav1/dme/in-range",
292                              getNAV1DMEInRange, 0);
293                                
294   current_properties.tieDouble("/radios/nav2/frequencies/selected",
295                                getNAV2Freq, setNAV2Freq);
296   current_properties.tieDouble("/radios/nav2/frequencies/standby",
297                                getNAV2AltFreq, setNAV2AltFreq);
298   current_properties.tieDouble("/radios/nav2/radials/actual",
299                                getNAV2Radial, 0);
300   current_properties.tieDouble("/radios/nav2/radials/selected",
301                                getNAV2SelRadial, setNAV2SelRadial);
302   current_properties.tieDouble("/radios/nav2/dme/distance",
303                                getNAV2DistDME, 0);
304   current_properties.tieBool("/radios/nav2/to-flag",
305                              getNAV2TO, 0);
306   current_properties.tieBool("/radios/nav2/from-flag",
307                              getNAV2FROM, 0);
308   current_properties.tieBool("/radios/nav2/in-range",
309                              getNAV2InRange, 0);
310   current_properties.tieBool("/radios/nav2/dme/in-range",
311                              getNAV2DMEInRange, 0);
312
313   current_properties.tieDouble("/radios/adf/frequencies/selected",
314                                getADFFreq, setADFFreq);
315   current_properties.tieDouble("/radios/adf/frequencies/standby",
316                                getADFAltFreq, setADFAltFreq);
317   current_properties.tieDouble("/radios/adf/rotation",
318                                getADFRotation, setADFRotation);
319
320   current_properties.tieDouble("/environment/visibility",
321                                getVisibility, setVisibility);
322
323   _needReinit = false;
324
325   FG_LOG(FG_GENERAL, FG_INFO, "Ending BFI init");
326 }
327
328
329 /**
330  * Reinitialize FGFS if required.
331  *
332  * Some changes (especially those in aircraft position) require that
333  * FGFS be reinitialized afterwards.  Rather than reinitialize after
334  * every change, the setter methods simply set a flag so that there
335  * can be a single reinit at the end of the frame.
336  */
337 void
338 FGBFI::update ()
339 {
340   if (_needReinit) {
341     reinit();
342   }
343 }
344
345
346 \f
347 ////////////////////////////////////////////////////////////////////////
348 // Simulation.
349 ////////////////////////////////////////////////////////////////////////
350
351
352 /**
353  * Return the flight model as an integer.
354  *
355  * TODO: use a string instead.
356  */
357 int
358 FGBFI::getFlightModel ()
359 {
360   return globals->get_options()->get_flight_model();
361 }
362
363
364 /**
365  * Return the current aircraft as a string.
366  */
367 const string &
368 FGBFI::getAircraft ()
369 {
370   _temp = globals->get_options()->get_aircraft();
371   return _temp;
372 }
373
374
375 /**
376  * Return the current aircraft directory (UIUC) as a string.
377  */
378 const string &
379 FGBFI::getAircraftDir ()
380 {
381   _temp = aircraft_dir;
382   return _temp;
383 }
384
385
386 /**
387  * Set the flight model as an integer.
388  *
389  * TODO: use a string instead.
390  */
391 void
392 FGBFI::setFlightModel (int model)
393 {
394   if (getFlightModel() != model) {
395     globals->get_options()->set_flight_model(model);
396     needReinit();
397   }
398 }
399
400
401 /**
402  * Set the current aircraft.
403  */
404 void
405 FGBFI::setAircraft (const string &aircraft)
406 {
407   if (getAircraft() != aircraft) {
408     globals->get_options()->set_aircraft(aircraft);
409     needReinit();
410   }
411 }
412
413
414 /**
415  * Set the current aircraft directory (UIUC).
416  */
417 void
418 FGBFI::setAircraftDir (const string &dir)
419 {
420   if (getAircraftDir() != dir) {
421     aircraft_dir = dir;
422     needReinit();
423   }
424 }
425
426
427 /**
428  * Return the current Zulu time.
429  */
430 const string &
431 FGBFI::getDateString ()
432 {
433   static string out;            // FIXME: not thread-safe
434   char buf[64];
435   struct tm * t = globals->get_time_params()->getGmt();
436   sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
437           t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
438           t->tm_hour, t->tm_min, t->tm_sec);
439   out = buf;
440   return out;
441 }
442
443
444 /**
445  * Set the current Zulu time.
446  */
447 void
448 FGBFI::setDateString (const string &date_string)
449 // FGBFI::setTimeGMT (time_t time)
450 {
451   SGTime * st = globals->get_time_params();
452   struct tm * current_time = st->getGmt();
453   struct tm new_time;
454
455                                 // Scan for basic ISO format
456                                 // YYYY-MM-DDTHH:MM:SS
457   int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
458                    &(new_time.tm_year), &(new_time.tm_mon),
459                    &(new_time.tm_mday), &(new_time.tm_hour),
460                    &(new_time.tm_min), &(new_time.tm_sec));
461
462                                 // Be pretty picky about this, so
463                                 // that strange things don't happen
464                                 // if the save file has been edited
465                                 // by hand.
466   if (ret != 6) {
467     FG_LOG(FG_INPUT, FG_ALERT, "Date/time string " << date_string
468            << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
469     return;
470   }
471
472                                 // OK, it looks like we got six
473                                 // values, one way or another.
474   new_time.tm_year -= 1900;
475   new_time.tm_mon -= 1;
476
477                                 // Now, tell flight gear to use
478                                 // the new time.  This was far
479                                 // too difficult, by the way.
480   long int warp =
481     mktime(&new_time) - mktime(current_time) + globals->get_warp();
482   double lon = current_aircraft.fdm_state->get_Longitude();
483   double lat = current_aircraft.fdm_state->get_Latitude();
484   double alt = current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER;
485   globals->set_warp(warp);
486   st->update(lon, lat, warp);
487   fgUpdateSkyAndLightingParams();
488 }
489
490
491 /**
492  * Return the GMT as a string.
493  */
494 const string &
495 FGBFI::getGMTString ()
496 {
497   static string out;            // FIXME: not thread-safe
498   char buf[16];
499   struct tm * t = globals->get_time_params()->getGmt();
500   sprintf(buf, " %.2d:%.2d:%.2d",
501           t->tm_hour, t->tm_min, t->tm_sec);
502   out = buf;
503   return out;
504 }
505
506
507 /**
508  * Return true if the HUD is visible.
509  */
510 bool
511 FGBFI::getHUDVisible ()
512 {
513   return globals->get_options()->get_hud_status();
514 }
515
516
517 /**
518  * Ensure that the HUD is visible or hidden.
519  */
520 void
521 FGBFI::setHUDVisible (bool visible)
522 {
523   globals->get_options()->set_hud_status(visible);
524 }
525
526
527 /**
528  * Return true if the 2D panel is visible.
529  */
530 bool
531 FGBFI::getPanelVisible ()
532 {
533   return globals->get_options()->get_panel_status();
534 }
535
536
537 /**
538  * Ensure that the 2D panel is visible or hidden.
539  */
540 void
541 FGBFI::setPanelVisible (bool visible)
542 {
543   if (globals->get_options()->get_panel_status() != visible) {
544     globals->get_options()->toggle_panel();
545   }
546 }
547
548
549 /**
550  * Get the panel's current x-shift.
551  */
552 int
553 FGBFI::getPanelXOffset ()
554 {
555   if (current_panel != 0)
556     return current_panel->getXOffset();
557   else
558     return 0;
559 }
560
561
562 /**
563  * Set the panel's current x-shift.
564  */
565 void
566 FGBFI::setPanelXOffset (int offset)
567 {
568   if (current_panel != 0)
569     current_panel->setXOffset(offset);
570 }
571
572
573 /**
574  * Get the panel's current y-shift.
575  */
576 int
577 FGBFI::getPanelYOffset ()
578 {
579   if (current_panel != 0)
580     return current_panel->getYOffset();
581   else
582     return 0;
583 }
584
585
586 /**
587  * Set the panel's current y-shift.
588  */
589 void
590 FGBFI::setPanelYOffset (int offset)
591 {
592   if (current_panel != 0)
593     current_panel->setYOffset(offset);
594 }
595
596
597
598
599 \f
600 ////////////////////////////////////////////////////////////////////////
601 // Position
602 ////////////////////////////////////////////////////////////////////////
603
604
605 /**
606  * Return the current latitude in degrees (negative for south).
607  */
608 double
609 FGBFI::getLatitude ()
610 {
611   return current_aircraft.fdm_state->get_Latitude() * RAD_TO_DEG;
612 }
613
614
615 /**
616  * Set the current latitude in degrees (negative for south).
617  */
618 void
619 FGBFI::setLatitude (double latitude)
620 {
621   current_aircraft.fdm_state->set_Latitude(latitude * DEG_TO_RAD);
622   fgUpdateSkyAndLightingParams();
623 }
624
625
626 /**
627  * Return the current longitude in degrees (negative for west).
628  */
629 double
630 FGBFI::getLongitude ()
631 {
632   return current_aircraft.fdm_state->get_Longitude() * RAD_TO_DEG;
633 }
634
635
636 /**
637  * Set the current longitude in degrees (negative for west).
638  */
639 void
640 FGBFI::setLongitude (double longitude)
641 {
642   current_aircraft.fdm_state->set_Longitude(longitude * DEG_TO_RAD);
643   fgUpdateSkyAndLightingParams();
644 }
645
646
647 /**
648  * Return the current altitude in feet.
649  */
650 double
651 FGBFI::getAltitude ()
652 {
653   return current_aircraft.fdm_state->get_Altitude();
654 }
655
656
657
658 /**
659  * Return the current altitude in above the terrain.
660  */
661 double
662 FGBFI::getAGL ()
663 {
664   return current_aircraft.fdm_state->get_Altitude()
665          - (scenery.cur_elev * METER_TO_FEET);
666 }
667
668
669 /**
670  * Set the current altitude in feet.
671  */
672 void
673 FGBFI::setAltitude (double altitude)
674 {
675   current_aircraft.fdm_state->set_Altitude(altitude);
676   fgUpdateSkyAndLightingParams();
677 }
678
679
680 \f
681 ////////////////////////////////////////////////////////////////////////
682 // Attitude
683 ////////////////////////////////////////////////////////////////////////
684
685
686 /**
687  * Return the current heading in degrees.
688  */
689 double
690 FGBFI::getHeading ()
691 {
692   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG;
693 }
694
695
696 /**
697  * Return the current heading in degrees.
698  */
699 double
700 FGBFI::getHeadingMag ()
701 {
702   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG - getMagVar();
703 }
704
705
706 /**
707  * Set the current heading in degrees.
708  */
709 void
710 FGBFI::setHeading (double heading)
711 {
712   FGInterface * fdm = current_aircraft.fdm_state;
713   fdm->set_Euler_Angles(fdm->get_Phi(), fdm->get_Theta(),
714                         heading * DEG_TO_RAD);
715 }
716
717
718 /**
719  * Return the current pitch in degrees.
720  */
721 double
722 FGBFI::getPitch ()
723 {
724   return current_aircraft.fdm_state->get_Theta() * RAD_TO_DEG;
725 }
726
727
728 /**
729  * Set the current pitch in degrees.
730  */
731 void
732 FGBFI::setPitch (double pitch)
733 {
734   FGInterface * fdm = current_aircraft.fdm_state;
735   fdm->set_Euler_Angles(fdm->get_Phi(), pitch * DEG_TO_RAD, fdm->get_Psi());
736 }
737
738
739 /**
740  * Return the current roll in degrees.
741  */
742 double
743 FGBFI::getRoll ()
744 {
745   return current_aircraft.fdm_state->get_Phi() * RAD_TO_DEG;
746 }
747
748
749 /**
750  * Set the current roll in degrees.
751  */
752 void
753 FGBFI::setRoll (double roll)
754 {
755   FGInterface * fdm = current_aircraft.fdm_state;
756   fdm->set_Euler_Angles(roll * DEG_TO_RAD, fdm->get_Theta(), fdm->get_Psi());
757 }
758
759
760 /**
761  * Return the current engine0 rpm
762  */
763 double
764 FGBFI::getRPM ()
765 {
766   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
767       return current_aircraft.fdm_state->get_engine(0)->get_RPM();
768   } else {
769       return 0.0;
770   }
771 }
772
773
774 /**
775  * Set the current engine0 rpm
776  */
777 void
778 FGBFI::setRPM (double rpm)
779 {
780     if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
781         if (getRPM() != rpm) {
782             current_aircraft.fdm_state->get_engine(0)->set_RPM( rpm );
783         }
784     }
785 }
786
787
788 /**
789  * Return the current engine0 EGT.
790  */
791 double
792 FGBFI::getEGT ()
793 {
794   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
795       return current_aircraft.fdm_state->get_engine(0)->get_EGT();
796   } else {
797       return 0.0;
798   }
799 }
800
801
802 /**
803  * Return the current engine0 CHT.
804  */
805 double
806 FGBFI::getCHT ()
807 {
808   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
809       return current_aircraft.fdm_state->get_engine(0)->get_CHT();
810   } else {
811       return 0.0;
812   }
813 }
814
815
816 /**
817  * Return the current engine0 CHT.
818  */
819 double
820 FGBFI::getMP ()
821 {
822   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
823       return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
824   } else {
825       return 0.0;
826   }
827 }
828
829
830 \f
831 ////////////////////////////////////////////////////////////////////////
832 // Velocities
833 ////////////////////////////////////////////////////////////////////////
834
835
836 /**
837  * Return the current airspeed in knots.
838  */
839 double
840 FGBFI::getAirspeed ()
841 {
842                                 // FIXME: should we add speed-up?
843   return current_aircraft.fdm_state->get_V_calibrated_kts();
844 }
845
846
847 /**
848  * Set the calibrated airspeed in knots.
849  */
850 void
851 FGBFI::setAirspeed (double speed)
852 {
853   current_aircraft.fdm_state->set_V_calibrated_kts(speed);
854 }
855
856
857 /**
858  * Return the current sideslip (FIXME: units unknown).
859  */
860 double
861 FGBFI::getSideSlip ()
862 {
863   return current_aircraft.fdm_state->get_Beta();
864 }
865
866
867 /**
868  * Return the current climb rate in feet/minute
869  */
870 double
871 FGBFI::getVerticalSpeed ()
872 {
873                                 // What about meters?
874   return current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
875 }
876
877
878 /**
879  * Get the current north velocity (units??).
880  */
881 double
882 FGBFI::getSpeedNorth ()
883 {
884   return current_aircraft.fdm_state->get_V_north();
885 }
886
887
888 // /**
889 //  * Set the current north velocity (units??).
890 //  */
891 // void
892 // FGBFI::setSpeedNorth (double speed)
893 // {
894 //   FGInterface * fdm = current_aircraft.fdm_state;
895 // //   fdm->set_Velocities_Local(speed, fdm->get_V_east(), fdm->get_V_down());
896 // }
897
898
899 /**
900  * Get the current east velocity (units??).
901  */
902 double
903 FGBFI::getSpeedEast ()
904 {
905   return current_aircraft.fdm_state->get_V_east();
906 }
907
908
909 // /**
910 //  * Set the current east velocity (units??).
911 //  */
912 // void
913 // FGBFI::setSpeedEast (double speed)
914 // {
915 //   FGInterface * fdm = current_aircraft.fdm_state;
916 // //   fdm->set_Velocities_Local(fdm->get_V_north(), speed, fdm->get_V_down());
917 // }
918
919
920 /**
921  * Get the current down velocity (units??).
922  */
923 double
924 FGBFI::getSpeedDown ()
925 {
926   return current_aircraft.fdm_state->get_V_down();
927 }
928
929
930 // /**
931 //  * Set the current down velocity (units??).
932 //  */
933 // void
934 // FGBFI::setSpeedDown (double speed)
935 // {
936 //   FGInterface * fdm = current_aircraft.fdm_state;
937 // //   fdm->set_Velocities_Local(fdm->get_V_north(), fdm->get_V_east(), speed);
938 // }
939
940
941 \f
942 ////////////////////////////////////////////////////////////////////////
943 // Controls
944 ////////////////////////////////////////////////////////////////////////
945
946
947 /**
948  * Get the throttle setting, from 0.0 (none) to 1.0 (full).
949  */
950 double
951 FGBFI::getThrottle ()
952 {
953                                 // FIXME: add engine selector
954   return controls.get_throttle(0);
955 }
956
957
958 /**
959  * Set the throttle, from 0.0 (none) to 1.0 (full).
960  */
961 void
962 FGBFI::setThrottle (double throttle)
963 {
964                                 // FIXME: allow engine selection
965   controls.set_throttle(0, throttle);
966 }
967
968
969 /**
970  * Get the fuel mixture setting, from 0.0 (none) to 1.0 (full).
971  */
972 double
973 FGBFI::getMixture ()
974 {
975                                 // FIXME: add engine selector
976   return controls.get_mixture(0);
977 }
978
979
980 /**
981  * Set the fuel mixture, from 0.0 (none) to 1.0 (full).
982  */
983 void
984 FGBFI::setMixture (double mixture)
985 {
986                                 // FIXME: allow engine selection
987   controls.set_mixture(0, mixture);
988 }
989
990
991 /**
992  * Get the propellor pitch setting, from 0.0 (none) to 1.0 (full).
993  */
994 double
995 FGBFI::getPropAdvance ()
996 {
997                                 // FIXME: add engine selector
998   return controls.get_prop_advance(0);
999 }
1000
1001
1002 /**
1003  * Set the propellor pitch, from 0.0 (none) to 1.0 (full).
1004  */
1005 void
1006 FGBFI::setPropAdvance (double pitch)
1007 {
1008                                 // FIXME: allow engine selection
1009   controls.set_prop_advance(0, pitch);
1010 }
1011
1012
1013 /**
1014  * Get the flaps setting, from 0.0 (none) to 1.0 (full).
1015  */
1016 double
1017 FGBFI::getFlaps ()
1018 {
1019   return controls.get_flaps();
1020 }
1021
1022
1023 /**
1024  * Set the flaps, from 0.0 (none) to 1.0 (full).
1025  */
1026 void
1027 FGBFI::setFlaps (double flaps)
1028 {
1029                                 // FIXME: clamp?
1030   controls.set_flaps(flaps);
1031 }
1032
1033
1034 /**
1035  * Get the aileron, from -1.0 (left) to 1.0 (right).
1036  */
1037 double
1038 FGBFI::getAileron ()
1039 {
1040   return controls.get_aileron();
1041 }
1042
1043
1044 /**
1045  * Set the aileron, from -1.0 (left) to 1.0 (right).
1046  */
1047 void
1048 FGBFI::setAileron (double aileron)
1049 {
1050                                 // FIXME: clamp?
1051   controls.set_aileron(aileron);
1052 }
1053
1054
1055 /**
1056  * Get the rudder setting, from -1.0 (left) to 1.0 (right).
1057  */
1058 double
1059 FGBFI::getRudder ()
1060 {
1061   return controls.get_rudder();
1062 }
1063
1064
1065 /**
1066  * Set the rudder, from -1.0 (left) to 1.0 (right).
1067  */
1068 void
1069 FGBFI::setRudder (double rudder)
1070 {
1071                                 // FIXME: clamp?
1072   controls.set_rudder(rudder);
1073 }
1074
1075
1076 /**
1077  * Get the elevator setting, from -1.0 (down) to 1.0 (up).
1078  */
1079 double
1080 FGBFI::getElevator ()
1081 {
1082   return controls.get_elevator();
1083 }
1084
1085
1086 /**
1087  * Set the elevator, from -1.0 (down) to 1.0 (up).
1088  */
1089 void
1090 FGBFI::setElevator (double elevator)
1091 {
1092                                 // FIXME: clamp?
1093   controls.set_elevator(elevator);
1094 }
1095
1096
1097 /**
1098  * Get the elevator trim, from -1.0 (down) to 1.0 (up).
1099  */
1100 double
1101 FGBFI::getElevatorTrim ()
1102 {
1103   return controls.get_elevator_trim();
1104 }
1105
1106
1107 /**
1108  * Set the elevator trim, from -1.0 (down) to 1.0 (up).
1109  */
1110 void
1111 FGBFI::setElevatorTrim (double trim)
1112 {
1113                                 // FIXME: clamp?
1114   controls.set_elevator_trim(trim);
1115 }
1116
1117
1118 /**
1119  * Get the highest brake setting, from 0.0 (none) to 1.0 (full).
1120  */
1121 double
1122 FGBFI::getBrakes ()
1123 {
1124   double b1 = getCenterBrake();
1125   double b2 = getLeftBrake();
1126   double b3 = getRightBrake();
1127   return (b1 > b2 ? (b1 > b3 ? b1 : b3) : (b2 > b3 ? b2 : b3));
1128 }
1129
1130
1131 /**
1132  * Set all brakes, from 0.0 (none) to 1.0 (full).
1133  */
1134 void
1135 FGBFI::setBrakes (double brake)
1136 {
1137   setCenterBrake(brake);
1138   setLeftBrake(brake);
1139   setRightBrake(brake);
1140 }
1141
1142
1143 /**
1144  * Get the center brake, from 0.0 (none) to 1.0 (full).
1145  */
1146 double
1147 FGBFI::getCenterBrake ()
1148 {
1149   return controls.get_brake(2);
1150 }
1151
1152
1153 /**
1154  * Set the center brake, from 0.0 (none) to 1.0 (full).
1155  */
1156 void
1157 FGBFI::setCenterBrake (double brake)
1158 {
1159   controls.set_brake(2, brake);
1160 }
1161
1162
1163 /**
1164  * Get the left brake, from 0.0 (none) to 1.0 (full).
1165  */
1166 double
1167 FGBFI::getLeftBrake ()
1168 {
1169   return controls.get_brake(0);
1170 }
1171
1172
1173 /**
1174  * Set the left brake, from 0.0 (none) to 1.0 (full).
1175  */
1176 void
1177 FGBFI::setLeftBrake (double brake)
1178 {
1179   controls.set_brake(0, brake);
1180 }
1181
1182
1183 /**
1184  * Get the right brake, from 0.0 (none) to 1.0 (full).
1185  */
1186 double
1187 FGBFI::getRightBrake ()
1188 {
1189   return controls.get_brake(1);
1190 }
1191
1192
1193 /**
1194  * Set the right brake, from 0.0 (none) to 1.0 (full).
1195  */
1196 void
1197 FGBFI::setRightBrake (double brake)
1198 {
1199   controls.set_brake(1, brake);
1200 }
1201
1202
1203
1204
1205 \f
1206 ////////////////////////////////////////////////////////////////////////
1207 // Autopilot
1208 ////////////////////////////////////////////////////////////////////////
1209
1210
1211 /**
1212  * Get the autopilot altitude lock (true=on).
1213  */
1214 bool
1215 FGBFI::getAPAltitudeLock ()
1216 {
1217     return current_autopilot->get_AltitudeEnabled();
1218 }
1219
1220
1221 /**
1222  * Set the autopilot altitude lock (true=on).
1223  */
1224 void
1225 FGBFI::setAPAltitudeLock (bool lock)
1226 {
1227   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
1228   current_autopilot->set_AltitudeEnabled(lock);
1229 }
1230
1231
1232 /**
1233  * Get the autopilot target altitude in feet.
1234  */
1235 double
1236 FGBFI::getAPAltitude ()
1237 {
1238   return current_autopilot->get_TargetAltitude() * METER_TO_FEET;
1239 }
1240
1241
1242 /**
1243  * Set the autopilot target altitude in feet.
1244  */
1245 void
1246 FGBFI::setAPAltitude (double altitude)
1247 {
1248     current_autopilot->set_TargetAltitude( altitude );
1249 }
1250
1251
1252 /**
1253  * Get the autopilot heading lock (true=on).
1254  */
1255 bool
1256 FGBFI::getAPHeadingLock ()
1257 {
1258     return
1259       (current_autopilot->get_HeadingEnabled() &&
1260        current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_LOCK);
1261 }
1262
1263
1264 /**
1265  * Set the autopilot heading lock (true=on).
1266  */
1267 void
1268 FGBFI::setAPHeadingLock (bool lock)
1269 {
1270   if (lock) {
1271                                 // We need to do this so that
1272                                 // it's possible to lock onto a
1273                                 // heading other than the current
1274                                 // heading.
1275     double heading = getAPHeadingMag();
1276     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_LOCK);
1277     current_autopilot->set_HeadingEnabled(true);
1278     setAPHeadingMag(heading);
1279   } else if (current_autopilot->get_HeadingMode() ==
1280              FGAutopilot::FG_HEADING_LOCK) {
1281     current_autopilot->set_HeadingEnabled(false);
1282   }
1283 }
1284
1285
1286 /**
1287  * Get the autopilot target heading in degrees.
1288  */
1289 double
1290 FGBFI::getAPHeading ()
1291 {
1292   return current_autopilot->get_TargetHeading();
1293 }
1294
1295
1296 /**
1297  * Set the autopilot target heading in degrees.
1298  */
1299 void
1300 FGBFI::setAPHeading (double heading)
1301 {
1302   current_autopilot->set_TargetHeading( heading );
1303 }
1304
1305
1306 /**
1307  * Get the autopilot target heading in degrees.
1308  */
1309 double
1310 FGBFI::getAPHeadingMag ()
1311 {
1312   return current_autopilot->get_TargetHeading() - getMagVar();
1313 }
1314
1315
1316 /**
1317  * Set the autopilot target heading in degrees.
1318  */
1319 void
1320 FGBFI::setAPHeadingMag (double heading)
1321 {
1322   current_autopilot->set_TargetHeading( heading + getMagVar() );
1323 }
1324
1325
1326 /**
1327  * Return true if the autopilot is locked to NAV1.
1328  */
1329 bool
1330 FGBFI::getAPNAV1Lock ()
1331 {
1332   return
1333     (current_autopilot->get_HeadingEnabled() &&
1334      current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
1335 }
1336
1337
1338 /**
1339  * Set the autopilot NAV1 lock.
1340  */
1341 void
1342 FGBFI::setAPNAV1Lock (bool lock)
1343 {
1344   if (lock) {
1345     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
1346     current_autopilot->set_HeadingEnabled(true);
1347   } else if (current_autopilot->get_HeadingMode() ==
1348              FGAutopilot::FG_HEADING_NAV1) {
1349     current_autopilot->set_HeadingEnabled(false);
1350   }
1351 }
1352
1353
1354 \f
1355 ////////////////////////////////////////////////////////////////////////
1356 // Radio navigation.
1357 ////////////////////////////////////////////////////////////////////////
1358
1359 double
1360 FGBFI::getNAV1Freq ()
1361 {
1362   return current_radiostack->get_nav1_freq();
1363 }
1364
1365 double
1366 FGBFI::getNAV1AltFreq ()
1367 {
1368   return current_radiostack->get_nav1_alt_freq();
1369 }
1370
1371 double
1372 FGBFI::getNAV1Radial ()
1373 {
1374   return current_radiostack->get_nav1_radial();
1375 }
1376
1377 double
1378 FGBFI::getNAV1SelRadial ()
1379 {
1380   return current_radiostack->get_nav1_sel_radial();
1381 }
1382
1383 double
1384 FGBFI::getNAV1DistDME ()
1385 {
1386   return current_radiostack->get_nav1_dme_dist();
1387 }
1388
1389 bool 
1390 FGBFI::getNAV1TO ()
1391 {
1392   if (current_radiostack->get_nav1_inrange()) {
1393     double heading = current_radiostack->get_nav1_heading();
1394     double radial = current_radiostack->get_nav1_radial();
1395     double var = FGBFI::getMagVar();
1396     if (current_radiostack->get_nav1_loc()) {
1397       double offset = fabs(heading - radial);
1398       return (offset<= 8.0 || offset >= 352.0);
1399     } else {
1400       double offset =
1401         fabs(heading - var - radial);
1402       return (offset <= 20.0 || offset >= 340.0);
1403     }
1404   } else {
1405     return false;
1406   }
1407 }
1408
1409 bool
1410 FGBFI::getNAV1FROM ()
1411 {
1412   if (current_radiostack->get_nav1_inrange()) {
1413     double heading = current_radiostack->get_nav1_heading();
1414     double radial = current_radiostack->get_nav1_radial();
1415     double var = FGBFI::getMagVar();
1416     if (current_radiostack->get_nav1_loc()) {
1417       double offset = fabs(heading - radial);
1418       return (offset >= 172.0 && offset<= 188.0);
1419     } else {
1420       double offset =
1421         fabs(heading - var - radial);
1422       return (offset >= 160.0 && offset <= 200.0);
1423     }
1424   } else {
1425     return false;
1426   }
1427 }
1428
1429 bool
1430 FGBFI::getNAV1InRange ()
1431 {
1432   return current_radiostack->get_nav1_inrange();
1433 }
1434
1435 bool
1436 FGBFI::getNAV1DMEInRange ()
1437 {
1438   return (current_radiostack->get_nav1_inrange() &&
1439           current_radiostack->get_nav1_has_dme());
1440 }
1441
1442 double
1443 FGBFI::getNAV2Freq ()
1444 {
1445   return current_radiostack->get_nav2_freq();
1446 }
1447
1448 double
1449 FGBFI::getNAV2AltFreq ()
1450 {
1451   return current_radiostack->get_nav2_alt_freq();
1452 }
1453
1454 double
1455 FGBFI::getNAV2Radial ()
1456 {
1457   return current_radiostack->get_nav2_radial();
1458 }
1459
1460 double
1461 FGBFI::getNAV2SelRadial ()
1462 {
1463   return current_radiostack->get_nav2_sel_radial();
1464 }
1465
1466 double
1467 FGBFI::getNAV2DistDME ()
1468 {
1469   return current_radiostack->get_nav2_dme_dist();
1470 }
1471
1472 bool 
1473 FGBFI::getNAV2TO ()
1474 {
1475   if (current_radiostack->get_nav2_inrange()) {
1476     double heading = current_radiostack->get_nav2_heading();
1477     double radial = current_radiostack->get_nav2_radial();
1478     double var = FGBFI::getMagVar();
1479     if (current_radiostack->get_nav2_loc()) {
1480       double offset = fabs(heading - radial);
1481       return (offset<= 8.0 || offset >= 352.0);
1482     } else {
1483       double offset =
1484         fabs(heading - var - radial);
1485       return (offset <= 20.0 || offset >= 340.0);
1486     }
1487   } else {
1488     return false;
1489   }
1490 }
1491
1492 bool 
1493 FGBFI::getNAV2FROM ()
1494 {
1495   if (current_radiostack->get_nav2_inrange()) {
1496     double heading = current_radiostack->get_nav2_heading();
1497     double radial = current_radiostack->get_nav2_radial();
1498     double var = FGBFI::getMagVar();
1499     if (current_radiostack->get_nav2_loc()) {
1500       double offset = fabs(heading - radial);
1501       return (offset >= 172.0 && offset<= 188.0);
1502     } else {
1503       double offset =
1504         fabs(heading - var - radial);
1505       return (offset >= 160.0 && offset <= 200.0);
1506     }
1507   } else {
1508     return false;
1509   }
1510 }
1511
1512
1513 bool
1514 FGBFI::getNAV2InRange ()
1515 {
1516   return current_radiostack->get_nav2_inrange();
1517 }
1518
1519 bool
1520 FGBFI::getNAV2DMEInRange ()
1521 {
1522   return (current_radiostack->get_nav2_inrange() &&
1523           current_radiostack->get_nav2_has_dme());
1524 }
1525
1526 double
1527 FGBFI::getADFFreq ()
1528 {
1529   return current_radiostack->get_adf_freq();
1530 }
1531
1532 double
1533 FGBFI::getADFAltFreq ()
1534 {
1535   return current_radiostack->get_adf_alt_freq();
1536 }
1537
1538 double
1539 FGBFI::getADFRotation ()
1540 {
1541   return current_radiostack->get_adf_rotation();
1542 }
1543
1544 void
1545 FGBFI::setNAV1Freq (double freq)
1546 {
1547   current_radiostack->set_nav1_freq(freq);
1548 }
1549
1550 void
1551 FGBFI::setNAV1AltFreq (double freq)
1552 {
1553   current_radiostack->set_nav1_alt_freq(freq);
1554 }
1555
1556 void
1557 FGBFI::setNAV1SelRadial (double radial)
1558 {
1559   current_radiostack->set_nav1_sel_radial(radial);
1560 }
1561
1562 void
1563 FGBFI::setNAV2Freq (double freq)
1564 {
1565   current_radiostack->set_nav2_freq(freq);
1566 }
1567
1568 void
1569 FGBFI::setNAV2AltFreq (double freq)
1570 {
1571   current_radiostack->set_nav2_alt_freq(freq);
1572 }
1573
1574 void
1575 FGBFI::setNAV2SelRadial (double radial)
1576 {
1577   current_radiostack->set_nav2_sel_radial(radial);
1578 }
1579
1580 void
1581 FGBFI::setADFFreq (double freq)
1582 {
1583   current_radiostack->set_adf_freq(freq);
1584 }
1585
1586 void
1587 FGBFI::setADFAltFreq (double freq)
1588 {
1589   current_radiostack->set_adf_alt_freq(freq);
1590 }
1591
1592 void
1593 FGBFI::setADFRotation (double rot)
1594 {
1595   current_radiostack->set_adf_rotation(rot);
1596 }
1597
1598
1599 \f
1600 ////////////////////////////////////////////////////////////////////////
1601 // GPS
1602 ////////////////////////////////////////////////////////////////////////
1603
1604
1605 /**
1606  * Get the autopilot GPS lock (true=on).
1607  */
1608 bool
1609 FGBFI::getGPSLock ()
1610 {
1611   return (current_autopilot->get_HeadingEnabled() &&
1612           (current_autopilot->get_HeadingMode() ==
1613            FGAutopilot::FG_HEADING_WAYPOINT ));
1614 }
1615
1616
1617 /**
1618  * Set the autopilot GPS lock (true=on).
1619  */
1620 void
1621 FGBFI::setGPSLock (bool lock)
1622 {
1623   if (lock) {
1624     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_WAYPOINT);
1625     current_autopilot->set_HeadingEnabled(true);
1626   } else if (current_autopilot->get_HeadingMode() ==
1627              FGAutopilot::FG_HEADING_WAYPOINT) {
1628     current_autopilot->set_HeadingEnabled(false);
1629   }
1630 }
1631
1632
1633 /**
1634  * Get the GPS target airport code.
1635  */
1636 const string &
1637 FGBFI::getTargetAirport ()
1638 {
1639   // FIXME: not thread-safe
1640   static string out;
1641   out = globals->get_options()->get_airport_id();
1642
1643   return out;
1644 }
1645
1646
1647 /**
1648  * Set the GPS target airport code.
1649  */
1650 void
1651 FGBFI::setTargetAirport (const string &airportId)
1652 {
1653   // cout << "setting target airport id = " << airportId << endl;
1654   globals->get_options()->set_airport_id(airportId);
1655 }
1656
1657
1658 /**
1659  * Get the GPS target latitude in degrees (negative for south).
1660  */
1661 double
1662 FGBFI::getGPSTargetLatitude ()
1663 {
1664     return current_autopilot->get_TargetLatitude();
1665 }
1666
1667
1668 /**
1669  * Get the GPS target longitude in degrees (negative for west).
1670  */
1671 double
1672 FGBFI::getGPSTargetLongitude ()
1673 {
1674   return current_autopilot->get_TargetLongitude();
1675 }
1676
1677 #if 0
1678 /**
1679  * Set the GPS target longitude in degrees (negative for west).
1680  */
1681 void
1682 FGBFI::setGPSTargetLongitude (double longitude)
1683 {
1684   current_autopilot->set_TargetLongitude( longitude );
1685 }
1686 #endif
1687
1688
1689 \f
1690 ////////////////////////////////////////////////////////////////////////
1691 // Weather
1692 ////////////////////////////////////////////////////////////////////////
1693
1694
1695 /**
1696  * Get the current visible (units??).
1697  */
1698 double
1699 FGBFI::getVisibility ()
1700 {
1701 #ifndef FG_OLD_WEATHER
1702   return WeatherDatabase->getWeatherVisibility();
1703 #else
1704   return current_weather.get_visibility();
1705 #endif
1706 }
1707
1708
1709 /**
1710  * Set the current visibility (units??).
1711  */
1712 void
1713 FGBFI::setVisibility (double visibility)
1714 {
1715 #ifndef FG_OLD_WEATHER
1716   WeatherDatabase->setWeatherVisibility(visibility);
1717 #else
1718   current_weather.set_visibility(visibility);
1719 #endif
1720 }
1721
1722
1723 \f
1724 ////////////////////////////////////////////////////////////////////////
1725 // Time
1726 ////////////////////////////////////////////////////////////////////////
1727
1728 /**
1729  * Return the magnetic variation
1730  */
1731 double
1732 FGBFI::getMagVar ()
1733 {
1734   return globals->get_mag()->get_magvar() * RAD_TO_DEG;
1735 }
1736
1737
1738 /**
1739  * Return the magnetic variation
1740  */
1741 double
1742 FGBFI::getMagDip ()
1743 {
1744   return globals->get_mag()->get_magdip() * RAD_TO_DEG;
1745 }
1746
1747
1748 // end of bfi.cxx
1749