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