]> git.mxchange.org Git - flightgear.git/blob - src/Main/bfi.cxx
8ab40e4e5db4aad28612b68719976cffc02f0af0
[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/fg_types.hxx>
38 #include <simgear/misc/props.hxx>
39 #include <simgear/timing/fg_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 #ifndef FG_OLD_WEATHER
52 #  include <WeatherCM/FGLocalWeatherDatabase.h>
53 #else
54 #  include <Weather/weather.hxx>
55 #endif
56
57 #include "options.hxx"
58 #include "save.hxx"
59 #include "fg_init.hxx"
60
61 FG_USING_NAMESPACE(std);
62
63
64 #include "bfi.hxx"
65
66
67 \f
68 ////////////////////////////////////////////////////////////////////////
69 // Static variables.
70 ////////////////////////////////////////////////////////////////////////
71
72 bool FGBFI::_needReinit = false;
73
74
75 \f
76 ////////////////////////////////////////////////////////////////////////
77 // Local functions
78 ////////////////////////////////////////////////////////////////////////
79
80
81 /**
82  * Initialize the BFI by binding its functions to properties.
83  *
84  * TODO: perhaps these should migrate into the individual modules
85  * (i.e. they should register themselves).
86  */
87 void
88 FGBFI::init ()
89 {
90   FG_LOG(FG_GENERAL, FG_INFO, "Starting BFI init");
91                                 // Simulation
92   current_properties.tieInt("/sim/flight-model",
93                             getFlightModel, setFlightModel);
94 //   current_properties.tieString("/sim/aircraft",
95 //                             getAircraft, setAircraft);
96   // TODO: timeGMT
97   current_properties.tieBool("/sim/hud/visibility",
98                              getHUDVisible, setHUDVisible);
99   current_properties.tieBool("/sim/panel/visibility",
100                              getPanelVisible, setPanelVisible);
101
102                                 // Position
103   current_properties.tieDouble("/position/latitude",
104                                 getLatitude, setLatitude);
105   current_properties.tieDouble("/position/longitude",
106                                getLongitude, setLongitude);
107   current_properties.tieDouble("/position/altitude",
108                                getAltitude, setAltitude);
109   current_properties.tieDouble("/position/altitude-agl",
110                                getAGL, 0);
111
112                                 // Orientation
113   current_properties.tieDouble("/orientation/heading",
114                                getHeading, setHeading);
115   current_properties.tieDouble("/orientation/heading-magnetic",
116                                getHeadingMag, 0);
117   current_properties.tieDouble("/orientation/pitch",
118                                getPitch, setPitch);
119   current_properties.tieDouble("/orientation/roll",
120                                getRoll, setRoll);
121
122                                 // Velocities
123   current_properties.tieDouble("/velocities/airspeed",
124                                getAirspeed, 0);
125   current_properties.tieDouble("/velocities/side-slip",
126                                getSideSlip, 0);
127   current_properties.tieDouble("/velocities/vertical-speed",
128                                getVerticalSpeed, 0);
129   current_properties.tieDouble("/velocities/speed-north",
130                                getSpeedNorth, setSpeedNorth);
131   current_properties.tieDouble("/velocities/speed-east",
132                                getSpeedEast, setSpeedEast);
133   current_properties.tieDouble("/velocities/speed-down",
134                                getSpeedDown, setSpeedDown);
135
136                                 // Controls
137   current_properties.tieDouble("/controls/throttle",
138                                getThrottle, setThrottle);
139   current_properties.tieDouble("/controls/flaps",
140                                getFlaps, setFlaps);
141   current_properties.tieDouble("/controls/aileron",
142                                getAileron, setAileron);
143   current_properties.tieDouble("/controls/rudder",
144                                getRudder, setRudder);
145   current_properties.tieDouble("/controls/elevator",
146                                getElevator, setElevator);
147   current_properties.tieDouble("/controls/elevator-trim",
148                                getElevatorTrim, setElevatorTrim);
149   current_properties.tieDouble("/controls/brake",
150                                getBrake, setBrake);
151
152                                 // Autopilot
153   current_properties.tieBool("/autopilot/locks/altitude",
154                              getAPAltitudeLock, setAPAltitudeLock);
155   current_properties.tieDouble("/autopilot/settings/altitude",
156                                getAPAltitude, setAPAltitude);
157   current_properties.tieBool("/autopilot/locks/heading",
158                              getAPHeadingLock, setAPHeadingLock);
159   current_properties.tieDouble("/autopilot/settings/heading-magnetic",
160                                getAPHeadingMag, setAPHeadingMag);
161   current_properties.tieBool("/autopilot/locks/nav1",
162                              getAPNAV1Lock, setAPNAV1Lock);
163
164                                 // Radio navigation
165   current_properties.tieDouble("/radios/nav1/frequencies/selected",
166                                getNAV1Freq, setNAV1Freq);
167   current_properties.tieDouble("/radios/nav1/frequencies/standby",
168                                getNAV1AltFreq, setNAV1AltFreq);
169   current_properties.tieDouble("/radios/nav1/radials/actual",
170                                getNAV1Radial, 0);
171   current_properties.tieDouble("/radios/nav1/radials/selected",
172                                getNAV1SelRadial, setNAV1SelRadial);
173   current_properties.tieDouble("/radios/nav1/dme/distance",
174                                getNAV1DistDME, 0);
175   current_properties.tieBool("/radios/nav1/in-range",
176                              getNAV1InRange, 0);
177   current_properties.tieBool("/radios/nav1/dme/in-range",
178                              getNAV1DMEInRange, 0);
179                                
180   current_properties.tieDouble("/radios/nav2/frequencies/selected",
181                                getNAV2Freq, setNAV2Freq);
182   current_properties.tieDouble("/radios/nav2/frequencies/standby",
183                                getNAV2AltFreq, setNAV2AltFreq);
184   current_properties.tieDouble("/radios/nav2/radials/actual",
185                                getNAV2Radial, 0);
186   current_properties.tieDouble("/radios/nav2/radials/selected",
187                                getNAV2SelRadial, setNAV2SelRadial);
188   current_properties.tieDouble("/radios/nav2/dme/distance",
189                                getNAV2DistDME, 0);
190   current_properties.tieBool("/radios/nav2/in-range",
191                              getNAV2InRange, 0);
192   current_properties.tieBool("/radios/nav2/dme/in-range",
193                              getNAV2DMEInRange, 0);
194
195   current_properties.tieDouble("/radios/adf/frequencies/selected",
196                                getADFFreq, setADFFreq);
197   current_properties.tieDouble("/radios/adf/frequencies/standby",
198                                getADFAltFreq, setADFAltFreq);
199   current_properties.tieDouble("/radios/adf/rotation",
200                                getADFRotation, setADFRotation);
201
202   FG_LOG(FG_GENERAL, FG_INFO, "Ending BFI init");
203 }
204
205
206 /**
207  * Reinitialize FGFS if required.
208  *
209  * Some changes (especially those in aircraft position) require that
210  * FGFS be reinitialized afterwards.  Rather than reinitialize after
211  * every change, the setter methods simply set a flag so that there
212  * can be a single reinit at the end of the frame.
213  */
214 void
215 FGBFI::update ()
216 {
217   if (_needReinit) {
218     reinit();
219   }
220 }
221
222
223 /**
224  * Reinitialize FGFS to use the new BFI settings.
225  */
226 void
227 FGBFI::reinit ()
228 {
229                                 // Save the state of everything
230                                 // that's going to get clobbered
231                                 // when we reinit the subsystems.
232
233   cout << "BFI: start reinit\n";
234
235   setHeading(getHeading());
236   setPitch(getPitch());
237   setRoll(getRoll());
238   setSpeedNorth(getSpeedNorth());
239   setSpeedEast(getSpeedEast());
240   setSpeedDown(getSpeedDown());
241   setLatitude(getLatitude());
242   setLongitude(getLongitude());
243   setAltitude(getAltitude());
244
245                                 // TODO: add more AP stuff
246   double elevator = getElevator();
247   double aileron = getAileron();
248   double rudder = getRudder();
249   double throttle = getThrottle();
250   double elevator_trim = getElevatorTrim();
251   double flaps = getFlaps();
252   double brake = getBrake();
253   bool apHeadingLock = getAPHeadingLock();
254   double apHeadingMag = getAPHeadingMag();
255   bool apAltitudeLock = getAPAltitudeLock();
256   double apAltitude = getAPAltitude();
257   const string &targetAirport = getTargetAirport();
258   bool gpsLock = getGPSLock();
259   double gpsLatitude = getGPSTargetLatitude();
260   double gpsLongitude = getGPSTargetLongitude();
261
262   setTargetAirport("");
263   cout << "Target airport is " << current_options.get_airport_id() << endl;
264
265   fgReInitSubsystems();
266
267                                 // FIXME: this is wrong.
268                                 // All of these are scheduled events,
269                                 // and it should be possible to force
270                                 // them all to run once.
271   fgUpdateSunPos();
272   fgUpdateMoonPos();
273   cur_light_params.Update();
274   fgUpdateLocalTime();
275   fgUpdateWeatherDatabase();
276   fgRadioSearch();
277
278                                 // Restore all of the old states.
279   setElevator(elevator);
280   setAileron(aileron);
281   setRudder(rudder);
282   setThrottle(throttle);
283   setElevatorTrim(elevator_trim);
284   setFlaps(flaps);
285   setBrake(brake);
286   setAPHeadingLock(apHeadingLock);
287   setAPHeadingMag(apHeadingMag);
288   setAPAltitudeLock(apAltitudeLock);
289   setAPAltitude(apAltitude);
290   setTargetAirport(targetAirport);
291   setGPSLock(gpsLock);
292   setGPSTargetLatitude(gpsLatitude);
293   setGPSTargetLongitude(gpsLongitude);
294
295   _needReinit = false;
296
297   cout << "BFI: end reinit\n";
298 }
299
300
301 \f
302 ////////////////////////////////////////////////////////////////////////
303 // Simulation.
304 ////////////////////////////////////////////////////////////////////////
305
306
307 /**
308  * Return the flight model as an integer.
309  *
310  * TODO: use a string instead.
311  */
312 int
313 FGBFI::getFlightModel ()
314 {
315   return current_options.get_flight_model();
316 }
317
318
319 /**
320  * Return the current aircraft as a string.
321  */
322 const string
323 FGBFI::getAircraft ()
324 {
325   return current_options.get_aircraft();
326 }
327
328
329 /**
330  * Return the current aircraft directory (UIUC) as a string.
331  */
332 const string
333 FGBFI::getAircraftDir ()
334 {
335   return aircraft_dir;
336 }
337
338
339 /**
340  * Set the flight model as an integer.
341  *
342  * TODO: use a string instead.
343  */
344 void
345 FGBFI::setFlightModel (int model)
346 {
347   current_options.set_flight_model(model);
348   needReinit();
349 }
350
351
352 /**
353  * Set the current aircraft.
354  */
355 void
356 FGBFI::setAircraft (const string &aircraft)
357 {
358   current_options.set_aircraft(aircraft);
359   needReinit();
360 }
361
362
363 /**
364  * Set the current aircraft directory (UIUC).
365  */
366 void
367 FGBFI::setAircraftDir (const string &dir)
368 {
369   aircraft_dir = dir;
370   needReinit();
371 }
372
373
374 /**
375  * Return the current Zulu time.
376  */
377 time_t
378 FGBFI::getTimeGMT ()
379 {
380   return FGTime::cur_time_params->get_cur_time();
381 }
382
383
384 /**
385  * Set the current Zulu time.
386  */
387 void
388 FGBFI::setTimeGMT (time_t time)
389 {
390                                 // FIXME: need to update lighting
391                                 // and solar system
392   current_options.set_time_offset(time);
393   current_options.set_time_offset_type(SG_TIME_GMT_ABSOLUTE);
394   FGTime::cur_time_params->init( cur_fdm_state->get_Longitude(),
395                                  cur_fdm_state->get_Latitude(),
396                                  current_options.get_fg_root(),
397                                  current_options.get_time_offset(),
398                                  current_options.get_time_offset_type() );
399   FGTime::cur_time_params->update( cur_fdm_state->get_Longitude(),
400                                    cur_fdm_state->get_Latitude(),
401                                    cur_fdm_state->get_Altitude()
402                                    * FEET_TO_METER );
403   needReinit();
404 }
405
406
407 /**
408  * Return true if the HUD is visible.
409  */
410 bool
411 FGBFI::getHUDVisible ()
412 {
413   return current_options.get_hud_status();
414 }
415
416
417 /**
418  * Ensure that the HUD is visible or hidden.
419  */
420 void
421 FGBFI::setHUDVisible (bool visible)
422 {
423   current_options.set_hud_status(visible);
424 }
425
426
427 /**
428  * Return true if the 2D panel is visible.
429  */
430 bool
431 FGBFI::getPanelVisible ()
432 {
433   return current_options.get_panel_status();
434 }
435
436
437 /**
438  * Ensure that the 2D panel is visible or hidden.
439  */
440 void
441 FGBFI::setPanelVisible (bool visible)
442 {
443   if (current_options.get_panel_status() != visible) {
444     current_options.toggle_panel();
445   }
446 }
447
448
449 \f
450 ////////////////////////////////////////////////////////////////////////
451 // Position
452 ////////////////////////////////////////////////////////////////////////
453
454
455 /**
456  * Return the current latitude in degrees (negative for south).
457  */
458 double
459 FGBFI::getLatitude ()
460 {
461   return current_aircraft.fdm_state->get_Latitude() * RAD_TO_DEG;
462 }
463
464
465 /**
466  * Set the current latitude in degrees (negative for south).
467  */
468 void
469 FGBFI::setLatitude (double latitude)
470 {
471   current_options.set_lat(latitude);
472   current_aircraft.fdm_state->set_Latitude(latitude * DEG_TO_RAD);
473   needReinit();
474 }
475
476
477 /**
478  * Return the current longitude in degrees (negative for west).
479  */
480 double
481 FGBFI::getLongitude ()
482 {
483   return current_aircraft.fdm_state->get_Longitude() * RAD_TO_DEG;
484 }
485
486
487 /**
488  * Set the current longitude in degrees (negative for west).
489  */
490 void
491 FGBFI::setLongitude (double longitude)
492 {
493   current_options.set_lon(longitude);
494   current_aircraft.fdm_state->set_Longitude(longitude * DEG_TO_RAD);
495   needReinit();
496 }
497
498
499 /**
500  * Return the current altitude in feet.
501  */
502 double
503 FGBFI::getAltitude ()
504 {
505   return current_aircraft.fdm_state->get_Altitude();
506 }
507
508
509
510 /**
511  * Return the current altitude in above the terrain.
512  */
513 double
514 FGBFI::getAGL ()
515 {
516   return current_aircraft.fdm_state->get_Altitude()
517          - scenery.cur_elev * METER_TO_FEET;
518 }
519
520
521 /**
522  * Set the current altitude in feet.
523  */
524 void
525 FGBFI::setAltitude (double altitude)
526 {
527   fgFDMForceAltitude(getFlightModel(), altitude * FEET_TO_METER);
528 //   current_options.set_altitude(altitude * FEET_TO_METER);
529 //   current_aircraft.fdm_state->set_Altitude(altitude);
530 //   needReinit();
531 }
532
533
534 \f
535 ////////////////////////////////////////////////////////////////////////
536 // Attitude
537 ////////////////////////////////////////////////////////////////////////
538
539
540 /**
541  * Return the current heading in degrees.
542  */
543 double
544 FGBFI::getHeading ()
545 {
546   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG;
547 }
548
549
550 /**
551  * Return the current heading in degrees.
552  */
553 double
554 FGBFI::getHeadingMag ()
555 {
556   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG - getMagVar();
557 }
558
559
560 /**
561  * Set the current heading in degrees.
562  */
563 void
564 FGBFI::setHeading (double heading)
565 {
566   current_options.set_heading(heading);
567   current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
568                                                getPitch() * DEG_TO_RAD,
569                                                heading * DEG_TO_RAD);
570   needReinit();
571 }
572
573
574 /**
575  * Return the current pitch in degrees.
576  */
577 double
578 FGBFI::getPitch ()
579 {
580   return current_aircraft.fdm_state->get_Theta() * RAD_TO_DEG;
581 }
582
583
584 /**
585  * Set the current pitch in degrees.
586  */
587 void
588 FGBFI::setPitch (double pitch)
589 {
590
591   current_options.set_pitch(pitch);
592   current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
593                                                pitch * DEG_TO_RAD,
594                                                getHeading() * DEG_TO_RAD);
595   needReinit();
596 }
597
598
599 /**
600  * Return the current roll in degrees.
601  */
602 double
603 FGBFI::getRoll ()
604 {
605   return current_aircraft.fdm_state->get_Phi() * RAD_TO_DEG;
606 }
607
608
609 /**
610  * Set the current roll in degrees.
611  */
612 void
613 FGBFI::setRoll (double roll)
614 {
615   current_options.set_roll(roll);
616   current_aircraft.fdm_state->set_Euler_Angles(roll * DEG_TO_RAD,
617                                                getPitch() * DEG_TO_RAD,
618                                                getHeading() * DEG_TO_RAD);
619   needReinit();
620 }
621
622
623 \f
624 ////////////////////////////////////////////////////////////////////////
625 // Velocities
626 ////////////////////////////////////////////////////////////////////////
627
628
629 /**
630  * Return the current airspeed in knots.
631  */
632 double
633 FGBFI::getAirspeed ()
634 {
635                                 // FIXME: should we add speed-up?
636   return current_aircraft.fdm_state->get_V_calibrated_kts();
637 }
638
639
640 /**
641  * Return the current sideslip (FIXME: units unknown).
642  */
643 double
644 FGBFI::getSideSlip ()
645 {
646   return current_aircraft.fdm_state->get_Beta();
647 }
648
649
650 /**
651  * Return the current climb rate in feet/minute
652  */
653 double
654 FGBFI::getVerticalSpeed ()
655 {
656                                 // What about meters?
657   return current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
658 }
659
660
661 /**
662  * Get the current north velocity (units??).
663  */
664 double
665 FGBFI::getSpeedNorth ()
666 {
667   return current_aircraft.fdm_state->get_V_north();
668 }
669
670
671 /**
672  * Set the current north velocity (units??).
673  */
674 void
675 FGBFI::setSpeedNorth (double speed)
676 {
677   current_options.set_uBody(speed);
678   current_aircraft.fdm_state->set_Velocities_Local(speed,
679                                                    getSpeedEast(),
680                                                    getSpeedDown());
681   needReinit();
682 }
683
684
685 /**
686  * Get the current east velocity (units??).
687  */
688 double
689 FGBFI::getSpeedEast ()
690 {
691   return current_aircraft.fdm_state->get_V_east();
692 }
693
694
695 /**
696  * Set the current east velocity (units??).
697  */
698 void
699 FGBFI::setSpeedEast (double speed)
700 {
701   current_options.set_vBody(speed);
702   current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
703                                                    speed,
704                                                    getSpeedDown());
705   needReinit();
706 }
707
708
709 /**
710  * Get the current down velocity (units??).
711  */
712 double
713 FGBFI::getSpeedDown ()
714 {
715   return current_aircraft.fdm_state->get_V_down();
716 }
717
718
719 /**
720  * Set the current down velocity (units??).
721  */
722 void
723 FGBFI::setSpeedDown (double speed)
724 {
725   current_options.set_wBody(speed);
726   current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
727                                                    getSpeedEast(),
728                                                    speed);
729   needReinit();
730 }
731
732
733 \f
734 ////////////////////////////////////////////////////////////////////////
735 // Controls
736 ////////////////////////////////////////////////////////////////////////
737
738
739 /**
740  * Get the throttle setting, from 0.0 (none) to 1.0 (full).
741  */
742 double
743 FGBFI::getThrottle ()
744 {
745                                 // FIXME: add throttle selector
746   return controls.get_throttle(0);
747 }
748
749
750 /**
751  * Set the throttle, from 0.0 (none) to 1.0 (full).
752  */
753 void
754 FGBFI::setThrottle (double throttle)
755 {
756                                 // FIXME: allow throttle selection
757                                 // FIXME: clamp?
758   controls.set_throttle(0, throttle);
759 }
760
761
762 /**
763  * Get the flaps setting, from 0.0 (none) to 1.0 (full).
764  */
765 double
766 FGBFI::getFlaps ()
767 {
768   return controls.get_flaps();
769 }
770
771
772 /**
773  * Set the flaps, from 0.0 (none) to 1.0 (full).
774  */
775 void
776 FGBFI::setFlaps (double flaps)
777 {
778                                 // FIXME: clamp?
779   controls.set_flaps(flaps);
780 }
781
782
783 /**
784  * Get the aileron, from -1.0 (left) to 1.0 (right).
785  */
786 double
787 FGBFI::getAileron ()
788 {
789   return controls.get_aileron();
790 }
791
792
793 /**
794  * Set the aileron, from -1.0 (left) to 1.0 (right).
795  */
796 void
797 FGBFI::setAileron (double aileron)
798 {
799                                 // FIXME: clamp?
800   controls.set_aileron(aileron);
801 }
802
803
804 /**
805  * Get the rudder setting, from -1.0 (left) to 1.0 (right).
806  */
807 double
808 FGBFI::getRudder ()
809 {
810   return controls.get_rudder();
811 }
812
813
814 /**
815  * Set the rudder, from -1.0 (left) to 1.0 (right).
816  */
817 void
818 FGBFI::setRudder (double rudder)
819 {
820                                 // FIXME: clamp?
821   controls.set_rudder(rudder);
822 }
823
824
825 /**
826  * Get the elevator setting, from -1.0 (down) to 1.0 (up).
827  */
828 double
829 FGBFI::getElevator ()
830 {
831   return controls.get_elevator();
832 }
833
834
835 /**
836  * Set the elevator, from -1.0 (down) to 1.0 (up).
837  */
838 void
839 FGBFI::setElevator (double elevator)
840 {
841                                 // FIXME: clamp?
842   controls.set_elevator(elevator);
843 }
844
845
846 /**
847  * Get the elevator trim, from -1.0 (down) to 1.0 (up).
848  */
849 double
850 FGBFI::getElevatorTrim ()
851 {
852   return controls.get_elevator_trim();
853 }
854
855
856 /**
857  * Set the elevator trim, from -1.0 (down) to 1.0 (up).
858  */
859 void
860 FGBFI::setElevatorTrim (double trim)
861 {
862                                 // FIXME: clamp?
863   controls.set_elevator_trim(trim);
864 }
865
866
867 /**
868  * Get the brake setting, from 0.0 (none) to 1.0 (full).
869  */
870 double
871 FGBFI::getBrake ()
872 {
873                                 // FIXME: add brake selector
874   return controls.get_brake(0);
875 }
876
877
878 /**
879  * Set the brake, from 0.0 (none) to 1.0 (full).
880  */
881 void
882 FGBFI::setBrake (double brake)
883 {
884                                 // FIXME: clamp?
885                                 // FIXME: allow brake selection
886   controls.set_brake(0, brake);
887 }
888
889
890 \f
891 ////////////////////////////////////////////////////////////////////////
892 // Autopilot
893 ////////////////////////////////////////////////////////////////////////
894
895
896 /**
897  * Get the autopilot altitude lock (true=on).
898  */
899 bool
900 FGBFI::getAPAltitudeLock ()
901 {
902     return current_autopilot->get_AltitudeEnabled();
903 }
904
905
906 /**
907  * Set the autopilot altitude lock (true=on).
908  */
909 void
910 FGBFI::setAPAltitudeLock (bool lock)
911 {
912   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
913   current_autopilot->set_AltitudeEnabled(lock);
914 }
915
916
917 /**
918  * Get the autopilot target altitude in feet.
919  */
920 double
921 FGBFI::getAPAltitude ()
922 {
923   return current_autopilot->get_TargetAltitude() * METER_TO_FEET;
924 }
925
926
927 /**
928  * Set the autopilot target altitude in feet.
929  */
930 void
931 FGBFI::setAPAltitude (double altitude)
932 {
933     current_autopilot->set_TargetAltitude( altitude );
934 }
935
936
937 /**
938  * Get the autopilot heading lock (true=on).
939  */
940 bool
941 FGBFI::getAPHeadingLock ()
942 {
943     return
944       (current_autopilot->get_HeadingEnabled() &&
945        current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_LOCK);
946 }
947
948
949 /**
950  * Set the autopilot heading lock (true=on).
951  */
952 void
953 FGBFI::setAPHeadingLock (bool lock)
954 {
955   if (lock) {
956                                 // We need to do this so that
957                                 // it's possible to lock onto a
958                                 // heading other than the current
959                                 // heading.
960     double heading = getAPHeadingMag();
961     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_LOCK);
962     current_autopilot->set_HeadingEnabled(true);
963     setAPHeadingMag(heading);
964   } else if (current_autopilot->get_HeadingMode() ==
965              FGAutopilot::FG_HEADING_LOCK) {
966     current_autopilot->set_HeadingEnabled(false);
967   }
968 }
969
970
971 /**
972  * Get the autopilot target heading in degrees.
973  */
974 double
975 FGBFI::getAPHeadingMag ()
976 {
977   return current_autopilot->get_TargetHeading() - getMagVar();
978 }
979
980
981 /**
982  * Set the autopilot target heading in degrees.
983  */
984 void
985 FGBFI::setAPHeadingMag (double heading)
986 {
987   current_autopilot->set_TargetHeading( heading + getMagVar() );
988 }
989
990
991 /**
992  * Return true if the autopilot is locked to NAV1.
993  */
994 bool
995 FGBFI::getAPNAV1Lock ()
996 {
997   return
998     (current_autopilot->get_HeadingEnabled() &&
999      current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
1000 }
1001
1002
1003 /**
1004  * Set the autopilot NAV1 lock.
1005  */
1006 void
1007 FGBFI::setAPNAV1Lock (bool lock)
1008 {
1009   if (lock) {
1010     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
1011     current_autopilot->set_HeadingEnabled(true);
1012   } else if (current_autopilot->get_HeadingMode() ==
1013              FGAutopilot::FG_HEADING_NAV1) {
1014     current_autopilot->set_HeadingEnabled(false);
1015   }
1016 }
1017
1018
1019 \f
1020 ////////////////////////////////////////////////////////////////////////
1021 // Radio navigation.
1022 ////////////////////////////////////////////////////////////////////////
1023
1024 double
1025 FGBFI::getNAV1Freq ()
1026 {
1027   return current_radiostack->get_nav1_freq();
1028 }
1029
1030 double
1031 FGBFI::getNAV1AltFreq ()
1032 {
1033   return current_radiostack->get_nav1_alt_freq();
1034 }
1035
1036 double
1037 FGBFI::getNAV1Radial ()
1038 {
1039   return current_radiostack->get_nav1_radial();
1040 }
1041
1042 double
1043 FGBFI::getNAV1SelRadial ()
1044 {
1045   return current_radiostack->get_nav1_sel_radial();
1046 }
1047
1048 double
1049 FGBFI::getNAV1DistDME ()
1050 {
1051   return current_radiostack->get_nav1_dme_dist();
1052 }
1053
1054 bool
1055 FGBFI::getNAV1InRange ()
1056 {
1057   return current_radiostack->get_nav1_inrange();
1058 }
1059
1060 bool
1061 FGBFI::getNAV1DMEInRange ()
1062 {
1063   return (current_radiostack->get_nav1_inrange() &&
1064           current_radiostack->get_nav1_has_dme());
1065 }
1066
1067 double
1068 FGBFI::getNAV2Freq ()
1069 {
1070   return current_radiostack->get_nav2_freq();
1071 }
1072
1073 double
1074 FGBFI::getNAV2AltFreq ()
1075 {
1076   return current_radiostack->get_nav2_alt_freq();
1077 }
1078
1079 double
1080 FGBFI::getNAV2Radial ()
1081 {
1082   return current_radiostack->get_nav2_radial();
1083 }
1084
1085 double
1086 FGBFI::getNAV2SelRadial ()
1087 {
1088   return current_radiostack->get_nav2_sel_radial();
1089 }
1090
1091 double
1092 FGBFI::getNAV2DistDME ()
1093 {
1094   return current_radiostack->get_nav2_dme_dist();
1095 }
1096
1097 bool
1098 FGBFI::getNAV2InRange ()
1099 {
1100   return current_radiostack->get_nav2_inrange();
1101 }
1102
1103 bool
1104 FGBFI::getNAV2DMEInRange ()
1105 {
1106   return (current_radiostack->get_nav2_inrange() &&
1107           current_radiostack->get_nav2_has_dme());
1108 }
1109
1110 double
1111 FGBFI::getADFFreq ()
1112 {
1113   return current_radiostack->get_adf_freq();
1114 }
1115
1116 double
1117 FGBFI::getADFAltFreq ()
1118 {
1119   return current_radiostack->get_adf_alt_freq();
1120 }
1121
1122 double
1123 FGBFI::getADFRotation ()
1124 {
1125   return current_radiostack->get_adf_rotation();
1126 }
1127
1128 void
1129 FGBFI::setNAV1Freq (double freq)
1130 {
1131   current_radiostack->set_nav1_freq(freq);
1132 }
1133
1134 void
1135 FGBFI::setNAV1AltFreq (double freq)
1136 {
1137   current_radiostack->set_nav1_alt_freq(freq);
1138 }
1139
1140 void
1141 FGBFI::setNAV1SelRadial (double radial)
1142 {
1143   current_radiostack->set_nav1_sel_radial(radial);
1144 }
1145
1146 void
1147 FGBFI::setNAV2Freq (double freq)
1148 {
1149   current_radiostack->set_nav2_freq(freq);
1150 }
1151
1152 void
1153 FGBFI::setNAV2AltFreq (double freq)
1154 {
1155   current_radiostack->set_nav2_alt_freq(freq);
1156 }
1157
1158 void
1159 FGBFI::setNAV2SelRadial (double radial)
1160 {
1161   current_radiostack->set_nav2_sel_radial(radial);
1162 }
1163
1164 void
1165 FGBFI::setADFFreq (double freq)
1166 {
1167   current_radiostack->set_adf_freq(freq);
1168 }
1169
1170 void
1171 FGBFI::setADFAltFreq (double freq)
1172 {
1173   current_radiostack->set_adf_alt_freq(freq);
1174 }
1175
1176 void
1177 FGBFI::setADFRotation (double rot)
1178 {
1179   current_radiostack->set_adf_rotation(rot);
1180 }
1181
1182
1183 \f
1184 ////////////////////////////////////////////////////////////////////////
1185 // GPS
1186 ////////////////////////////////////////////////////////////////////////
1187
1188
1189 /**
1190  * Get the autopilot GPS lock (true=on).
1191  */
1192 bool
1193 FGBFI::getGPSLock ()
1194 {
1195   return (current_autopilot->get_HeadingEnabled() &&
1196           (current_autopilot->get_HeadingMode() ==
1197            FGAutopilot::FG_HEADING_WAYPOINT ));
1198 }
1199
1200
1201 /**
1202  * Set the autopilot GPS lock (true=on).
1203  */
1204 void
1205 FGBFI::setGPSLock (bool lock)
1206 {
1207   if (lock) {
1208     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_WAYPOINT);
1209     current_autopilot->set_HeadingEnabled(true);
1210   } else if (current_autopilot->get_HeadingMode() ==
1211              FGAutopilot::FG_HEADING_WAYPOINT) {
1212     current_autopilot->set_HeadingEnabled(false);
1213   }
1214 }
1215
1216
1217 /**
1218  * Get the GPS target airport code.
1219  */
1220 const string
1221 FGBFI::getTargetAirport ()
1222 {
1223   return current_options.get_airport_id();
1224 }
1225
1226
1227 /**
1228  * Set the GPS target airport code.
1229  */
1230 void
1231 FGBFI::setTargetAirport (const string &airportId)
1232 {
1233   current_options.set_airport_id(airportId);
1234 }
1235
1236
1237 /**
1238  * Get the GPS target latitude in degrees (negative for south).
1239  */
1240 double
1241 FGBFI::getGPSTargetLatitude ()
1242 {
1243     return current_autopilot->get_TargetLatitude();
1244 }
1245
1246
1247 /**
1248  * Set the GPS target latitude in degrees (negative for south).
1249  */
1250 void
1251 FGBFI::setGPSTargetLatitude (double latitude)
1252 {
1253   current_autopilot->set_TargetLatitude( latitude );
1254 }
1255
1256
1257 /**
1258  * Get the GPS target longitude in degrees (negative for west).
1259  */
1260 double
1261 FGBFI::getGPSTargetLongitude ()
1262 {
1263   return current_autopilot->get_TargetLongitude();
1264 }
1265
1266
1267 /**
1268  * Set the GPS target longitude in degrees (negative for west).
1269  */
1270 void
1271 FGBFI::setGPSTargetLongitude (double longitude)
1272 {
1273   current_autopilot->set_TargetLongitude( longitude );
1274 }
1275
1276
1277 \f
1278 ////////////////////////////////////////////////////////////////////////
1279 // Weather
1280 ////////////////////////////////////////////////////////////////////////
1281
1282
1283 /**
1284  * Get the current visible (units??).
1285  */
1286 double
1287 FGBFI::getVisibility ()
1288 {
1289 #ifndef FG_OLD_WEATHER
1290   return WeatherDatabase->getWeatherVisibility();
1291 #else
1292   return current_weather.get_visibility();
1293 #endif
1294 }
1295
1296
1297 /**
1298  * Check whether clouds are enabled.
1299  */
1300 bool
1301 FGBFI::getClouds ()
1302 {
1303   return current_options.get_clouds();
1304 }
1305
1306
1307 /**
1308  * Check the height of the clouds ASL (units?).
1309  */
1310 double
1311 FGBFI::getCloudsASL ()
1312 {
1313   return current_options.get_clouds_asl();
1314 }
1315
1316
1317 /**
1318  * Set the current visibility (units??).
1319  */
1320 void
1321 FGBFI::setVisibility (double visibility)
1322 {
1323 #ifndef FG_OLD_WEATHER
1324   WeatherDatabase->setWeatherVisibility(visibility);
1325 #else
1326   current_weather.set_visibility(visibility);
1327 #endif
1328 }
1329
1330
1331 /**
1332  * Switch clouds on or off.
1333  */
1334 void
1335 FGBFI::setClouds (bool clouds)
1336 {
1337   cout << "Set clouds to " << clouds << endl;
1338   current_options.set_clouds(clouds);
1339   needReinit();
1340 }
1341
1342
1343 /**
1344  * Set the cloud height.
1345  */
1346 void
1347 FGBFI::setCloudsASL (double cloudsASL)
1348 {
1349   current_options.set_clouds_asl(cloudsASL);
1350   needReinit();
1351 }
1352
1353
1354 \f
1355 ////////////////////////////////////////////////////////////////////////
1356 // Time
1357 ////////////////////////////////////////////////////////////////////////
1358
1359 /**
1360  * Return the magnetic variation
1361  */
1362 double
1363 FGBFI::getMagVar ()
1364 {
1365   return cur_magvar.get_magvar() * RAD_TO_DEG;
1366 }
1367
1368
1369 /**
1370  * Return the magnetic variation
1371  */
1372 double
1373 FGBFI::getMagDip ()
1374 {
1375   return cur_magvar.get_magdip() * RAD_TO_DEG;
1376 }
1377
1378
1379 // end of bfi.cxx
1380