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