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