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