]> git.mxchange.org Git - flightgear.git/blob - src/Main/bfi.cxx
Added support for managing fov via the property manager so the --fov= option
[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 CLASS IS DEPRECATED; USE THE PROPERTY MANAGER INSTEAD.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License as
11 // published by the Free Software Foundation; either version 2 of the
12 // License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 // General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 //
23 // $Id$
24
25 #include "fgfs.hxx"
26
27 #include <simgear/constants.h>
28 #include <simgear/debug/logstream.hxx>
29 #include <simgear/ephemeris/ephemeris.hxx>
30 #include <simgear/math/sg_types.hxx>
31 #include <simgear/misc/props.hxx>
32 #include <simgear/timing/sg_time.hxx>
33
34 #include <Aircraft/aircraft.hxx>
35 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
36 #include <Controls/controls.hxx>
37 #include <Autopilot/newauto.hxx>
38 #include <Scenery/scenery.hxx>
39 #include <Time/light.hxx>
40 #include <Time/event.hxx>
41 #include <Time/sunpos.hxx>
42 #include <Time/tmp.hxx>
43 #include <Cockpit/radiostack.hxx>
44 #include <Cockpit/panel.hxx>
45 #ifndef FG_OLD_WEATHER
46 #  include <WeatherCM/FGLocalWeatherDatabase.h>
47 #else
48 #  include <Weather/weather.hxx>
49 #endif
50
51 #include "globals.hxx"
52 #include "fg_init.hxx"
53 #include "fg_props.hxx"
54
55 FG_USING_NAMESPACE(std);
56
57
58 #include "bfi.hxx"
59
60
61 \f
62 ////////////////////////////////////////////////////////////////////////
63 // Static variables.
64 ////////////////////////////////////////////////////////////////////////
65
66                                 // Yech -- not thread-safe, etc. etc.
67 static bool _needReinit = false;
68 static string _temp;
69
70 static inline void needReinit ()
71 {
72   _needReinit = true;
73 }
74
75
76 /**
77  * Reinitialize FGFS to use the new BFI settings.
78  */
79 static inline void
80 reinit ()
81 {
82                                 // Save the state of everything
83                                 // that's going to get clobbered
84                                 // when we reinit the subsystems.
85
86   FG_LOG(FG_GENERAL, FG_INFO, "Starting BFI reinit");
87
88                                 // TODO: add more AP stuff
89   bool apHeadingLock = FGBFI::getAPHeadingLock();
90   double apHeadingMag = FGBFI::getAPHeadingMag();
91   bool apAltitudeLock = FGBFI::getAPAltitudeLock();
92   double apAltitude = FGBFI::getAPAltitude();
93   bool gpsLock = FGBFI::getGPSLock();
94   // double gpsLatitude = FGBFI::getGPSTargetLatitude();
95   // double gpsLongitude = FGBFI::getGPSTargetLongitude();
96
97   fgReInitSubsystems();
98
99                                 // FIXME: this is wrong.
100                                 // All of these are scheduled events,
101                                 // and it should be possible to force
102                                 // them all to run once.
103   fgUpdateSunPos();
104   fgUpdateMoonPos();
105   cur_light_params.Update();
106   fgUpdateLocalTime();
107   fgUpdateWeatherDatabase();
108   current_radiostack->search();
109
110                                 // Restore all of the old states.
111   FGBFI::setAPHeadingLock(apHeadingLock);
112   FGBFI::setAPHeadingMag(apHeadingMag);
113   FGBFI::setAPAltitudeLock(apAltitudeLock);
114   FGBFI::setAPAltitude(apAltitude);
115   FGBFI::setGPSLock(gpsLock);
116
117   _needReinit = false;
118
119   FG_LOG(FG_GENERAL, FG_INFO, "Ending BFI reinit");
120 }
121
122 // BEGIN: kludge
123 // Allow the view to be set from two axes (i.e. a joystick hat)
124 // This needs to be in FGViewer itself, somehow.
125 static double axisLong = 0.0;
126 static double axisLat = 0.0;
127
128 static inline void
129 _set_view_from_axes ()
130 {
131                                 // Take no action when hat is centered
132   if (axisLong == 0 && axisLat == 0)
133     return;
134
135   double viewDir = 0;
136
137   if (axisLong < 0) {           // Longitudinal axis forward
138     if (axisLat < 0)
139       viewDir = 45;
140     else if (axisLat > 0)
141       viewDir = 315;
142     else
143       viewDir = 0;
144   } else if (axisLong > 0) {    // Longitudinal axis backward
145     if (axisLat < 0)
146       viewDir = 135;
147     else if (axisLat > 0)
148       viewDir = 225;
149     else
150       viewDir = 180;
151   } else {                      // Longitudinal axis neutral
152     if (axisLat < 0)
153       viewDir = 90;
154     else
155       viewDir = 270;
156   }
157
158   globals->get_current_view()->set_goal_view_offset(viewDir*DEG_TO_RAD);
159 //   globals->get_current_view()->set_view_offset(viewDir*DEG_TO_RAD);
160 }
161
162 // END: kludge
163
164
165 \f
166 ////////////////////////////////////////////////////////////////////////
167 // Local functions
168 ////////////////////////////////////////////////////////////////////////
169
170 /**
171  * Initialize the BFI by binding its functions to properties.
172  *
173  * TODO: perhaps these should migrate into the individual modules
174  * (i.e. they should register themselves).
175  */
176 void
177 FGBFI::init ()
178 {
179   FG_LOG(FG_GENERAL, FG_INFO, "Starting BFI init");
180
181                                 // Simulation
182   fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
183   fgTie("/sim/time/gmt", getDateString, setDateString);
184   fgTie("/sim/time/gmt-string", getGMTString);
185
186                                 // Orientation
187   fgTie("/orientation/heading-magnetic", getHeadingMag);
188
189                                 // Engine
190   fgTie("/engines/engine0/rpm", getRPM);
191   fgTie("/engines/engine0/egt", getEGT);
192   fgTie("/engines/engine0/cht", getCHT);
193   fgTie("/engines/engine0/mp", getMP);
194
195                                 // Autopilot
196   fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
197   fgTie("/autopilot/settings/altitude", getAPAltitude, setAPAltitude);
198   fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
199   fgTie("/autopilot/settings/heading", getAPHeading, setAPHeading);
200   fgTie("/autopilot/settings/heading-dg", getAPHeadingDG, setAPHeadingDG);
201   fgTie("/autopilot/settings/heading-magnetic",
202              getAPHeadingMag, setAPHeadingMag);
203   fgTie("/autopilot/locks/nav1", getAPNAV1Lock, setAPNAV1Lock);
204
205                                 // Weather
206   fgTie("/environment/visibility", getVisibility, setVisibility);
207   fgTie("/environment/wind-north", getWindNorth, setWindNorth);
208   fgTie("/environment/wind-east", getWindEast, setWindEast);
209   fgTie("/environment/wind-down", getWindDown, setWindDown);
210
211                                 // View
212   fgTie("/sim/field-of-view", getFOV, setFOV);
213   fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
214   fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
215
216   _needReinit = false;
217
218   FG_LOG(FG_GENERAL, FG_INFO, "Ending BFI init");
219 }
220
221
222 /**
223  * Reinitialize FGFS if required.
224  *
225  * Some changes (especially those in aircraft position) require that
226  * FGFS be reinitialized afterwards.  Rather than reinitialize after
227  * every change, the setter methods simply set a flag so that there
228  * can be a single reinit at the end of the frame.
229  */
230 void
231 FGBFI::update ()
232 {
233   _set_view_from_axes();
234   if (_needReinit) {
235     reinit();
236   }
237 }
238
239
240 \f
241 ////////////////////////////////////////////////////////////////////////
242 // Simulation.
243 ////////////////////////////////////////////////////////////////////////
244
245
246 /**
247  * Return the current aircraft directory (UIUC) as a string.
248  */
249 string 
250 FGBFI::getAircraftDir ()
251 {
252   return aircraft_dir;
253 }
254
255
256 /**
257  * Set the current aircraft directory (UIUC).
258  */
259 void
260 FGBFI::setAircraftDir (string dir)
261 {
262   if (getAircraftDir() != dir) {
263     aircraft_dir = dir;
264     needReinit();
265   }
266 }
267
268
269 /**
270  * Return the current Zulu time.
271  */
272 string 
273 FGBFI::getDateString ()
274 {
275   string out;
276   char buf[64];
277   struct tm * t = globals->get_time_params()->getGmt();
278   sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
279           t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
280           t->tm_hour, t->tm_min, t->tm_sec);
281   out = buf;
282   return out;
283 }
284
285
286 /**
287  * Set the current Zulu time.
288  */
289 void
290 FGBFI::setDateString (string date_string)
291 // FGBFI::setTimeGMT (time_t time)
292 {
293   SGTime * st = globals->get_time_params();
294   struct tm * current_time = st->getGmt();
295   struct tm new_time;
296
297                                 // Scan for basic ISO format
298                                 // YYYY-MM-DDTHH:MM:SS
299   int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
300                    &(new_time.tm_year), &(new_time.tm_mon),
301                    &(new_time.tm_mday), &(new_time.tm_hour),
302                    &(new_time.tm_min), &(new_time.tm_sec));
303
304                                 // Be pretty picky about this, so
305                                 // that strange things don't happen
306                                 // if the save file has been edited
307                                 // by hand.
308   if (ret != 6) {
309     FG_LOG(FG_INPUT, FG_ALERT, "Date/time string " << date_string
310            << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
311     return;
312   }
313
314                                 // OK, it looks like we got six
315                                 // values, one way or another.
316   new_time.tm_year -= 1900;
317   new_time.tm_mon -= 1;
318
319                                 // Now, tell flight gear to use
320                                 // the new time.  This was far
321                                 // too difficult, by the way.
322   long int warp =
323     mktime(&new_time) - mktime(current_time) + globals->get_warp();
324   double lon = current_aircraft.fdm_state->get_Longitude();
325   double lat = current_aircraft.fdm_state->get_Latitude();
326   double alt = current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER;
327   globals->set_warp(warp);
328   st->update(lon, lat, warp);
329   fgUpdateSkyAndLightingParams();
330 }
331
332
333 /**
334  * Return the GMT as a string.
335  */
336 string 
337 FGBFI::getGMTString ()
338 {
339   string out;
340   char buf[16];
341   struct tm * t = globals->get_time_params()->getGmt();
342   sprintf(buf, " %.2d:%.2d:%.2d",
343           t->tm_hour, t->tm_min, t->tm_sec);
344   out = buf;
345   return out;
346 }
347
348
349 \f
350 ////////////////////////////////////////////////////////////////////////
351 // Position
352 ////////////////////////////////////////////////////////////////////////
353
354
355 /**
356  * Return the current latitude in degrees (negative for south).
357  */
358 double
359 FGBFI::getLatitude ()
360 {
361   return current_aircraft.fdm_state->get_Latitude() * RAD_TO_DEG;
362 }
363
364
365 /**
366  * Set the current latitude in degrees (negative for south).
367  */
368 void
369 FGBFI::setLatitude (double latitude)
370 {
371   current_aircraft.fdm_state->set_Latitude(latitude * DEG_TO_RAD);
372 }
373
374
375 /**
376  * Return the current longitude in degrees (negative for west).
377  */
378 double
379 FGBFI::getLongitude ()
380 {
381   return current_aircraft.fdm_state->get_Longitude() * RAD_TO_DEG;
382 }
383
384
385 /**
386  * Set the current longitude in degrees (negative for west).
387  */
388 void
389 FGBFI::setLongitude (double longitude)
390 {
391   current_aircraft.fdm_state->set_Longitude(longitude * DEG_TO_RAD);
392 }
393
394
395 /**
396  * Return the current altitude in feet.
397  */
398 double
399 FGBFI::getAltitude ()
400 {
401   return current_aircraft.fdm_state->get_Altitude();
402 }
403
404
405
406 /**
407  * Return the current altitude in above the terrain.
408  */
409 double
410 FGBFI::getAGL ()
411 {
412   return current_aircraft.fdm_state->get_Altitude()
413          - (scenery.cur_elev * METER_TO_FEET);
414 }
415
416
417 /**
418  * Set the current altitude in feet.
419  */
420 void
421 FGBFI::setAltitude (double altitude)
422 {
423   current_aircraft.fdm_state->set_Altitude(altitude);
424 }
425
426
427 \f
428 ////////////////////////////////////////////////////////////////////////
429 // Attitude
430 ////////////////////////////////////////////////////////////////////////
431
432
433 /**
434  * Return the current heading in degrees.
435  */
436 double
437 FGBFI::getHeading ()
438 {
439   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG;
440 }
441
442
443 /**
444  * Return the current heading in degrees.
445  */
446 double
447 FGBFI::getHeadingMag ()
448 {
449   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG - getMagVar();
450 }
451
452
453 /**
454  * Set the current heading in degrees.
455  */
456 void
457 FGBFI::setHeading (double heading)
458 {
459   FGInterface * fdm = current_aircraft.fdm_state;
460   fdm->set_Euler_Angles(fdm->get_Phi(), fdm->get_Theta(),
461                         heading * DEG_TO_RAD);
462 }
463
464
465 /**
466  * Return the current pitch in degrees.
467  */
468 double
469 FGBFI::getPitch ()
470 {
471   return current_aircraft.fdm_state->get_Theta() * RAD_TO_DEG;
472 }
473
474
475 /**
476  * Set the current pitch in degrees.
477  */
478 void
479 FGBFI::setPitch (double pitch)
480 {
481   FGInterface * fdm = current_aircraft.fdm_state;
482   fdm->set_Euler_Angles(fdm->get_Phi(), pitch * DEG_TO_RAD, fdm->get_Psi());
483 }
484
485
486 /**
487  * Return the current roll in degrees.
488  */
489 double
490 FGBFI::getRoll ()
491 {
492   return current_aircraft.fdm_state->get_Phi() * RAD_TO_DEG;
493 }
494
495
496 /**
497  * Set the current roll in degrees.
498  */
499 void
500 FGBFI::setRoll (double roll)
501 {
502   FGInterface * fdm = current_aircraft.fdm_state;
503   fdm->set_Euler_Angles(roll * DEG_TO_RAD, fdm->get_Theta(), fdm->get_Psi());
504 }
505
506
507 /**
508  * Return the current engine0 rpm
509  */
510 double
511 FGBFI::getRPM ()
512 {
513   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
514       return current_aircraft.fdm_state->get_engine(0)->get_RPM();
515   } else {
516       return 0.0;
517   }
518 }
519
520
521 /**
522  * Set the current engine0 rpm
523  */
524 void
525 FGBFI::setRPM (double rpm)
526 {
527     if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
528         if (getRPM() != rpm) {
529             current_aircraft.fdm_state->get_engine(0)->set_RPM( rpm );
530         }
531     }
532 }
533
534
535 /**
536  * Return the current engine0 EGT.
537  */
538 double
539 FGBFI::getEGT ()
540 {
541   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
542       return current_aircraft.fdm_state->get_engine(0)->get_EGT();
543   } else {
544       return 0.0;
545   }
546 }
547
548
549 /**
550  * Return the current engine0 CHT.
551  */
552 double
553 FGBFI::getCHT ()
554 {
555   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
556       return current_aircraft.fdm_state->get_engine(0)->get_CHT();
557   } else {
558       return 0.0;
559   }
560 }
561
562
563 /**
564  * Return the current engine0 CHT.
565  */
566 double
567 FGBFI::getMP ()
568 {
569   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
570       return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
571   } else {
572       return 0.0;
573   }
574 }
575
576
577 \f
578 ////////////////////////////////////////////////////////////////////////
579 // Velocities
580 ////////////////////////////////////////////////////////////////////////
581
582
583 /**
584  * Return the current airspeed in knots.
585  */
586 double
587 FGBFI::getAirspeed ()
588 {
589                                 // FIXME: should we add speed-up?
590   return current_aircraft.fdm_state->get_V_calibrated_kts();
591 }
592
593
594 /**
595  * Set the calibrated airspeed in knots.
596  */
597 void
598 FGBFI::setAirspeed (double speed)
599 {
600   current_aircraft.fdm_state->set_V_calibrated_kts(speed);
601 }
602
603
604 /**
605  * Return the current sideslip (FIXME: units unknown).
606  */
607 double
608 FGBFI::getSideSlip ()
609 {
610   return current_aircraft.fdm_state->get_Beta();
611 }
612
613
614 /**
615  * Return the current climb rate in feet/minute
616  */
617 double
618 FGBFI::getVerticalSpeed ()
619 {
620                                 // What about meters?
621   return current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
622 }
623
624
625 /**
626  * Get the current north velocity (units??).
627  */
628 double
629 FGBFI::getSpeedNorth ()
630 {
631   return current_aircraft.fdm_state->get_V_north();
632 }
633
634
635 // /**
636 //  * Set the current north velocity (units??).
637 //  */
638 // void
639 // FGBFI::setSpeedNorth (double speed)
640 // {
641 //   FGInterface * fdm = current_aircraft.fdm_state;
642 // //   fdm->set_Velocities_Local(speed, fdm->get_V_east(), fdm->get_V_down());
643 // }
644
645
646 /**
647  * Get the current east velocity (units??).
648  */
649 double
650 FGBFI::getSpeedEast ()
651 {
652   return current_aircraft.fdm_state->get_V_east();
653 }
654
655
656 // /**
657 //  * Set the current east velocity (units??).
658 //  */
659 // void
660 // FGBFI::setSpeedEast (double speed)
661 // {
662 //   FGInterface * fdm = current_aircraft.fdm_state;
663 // //   fdm->set_Velocities_Local(fdm->get_V_north(), speed, fdm->get_V_down());
664 // }
665
666
667 /**
668  * Get the current down velocity (units??).
669  */
670 double
671 FGBFI::getSpeedDown ()
672 {
673   return current_aircraft.fdm_state->get_V_down();
674 }
675
676
677 // /**
678 //  * Set the current down velocity (units??).
679 //  */
680 // void
681 // FGBFI::setSpeedDown (double speed)
682 // {
683 //   FGInterface * fdm = current_aircraft.fdm_state;
684 // //   fdm->set_Velocities_Local(fdm->get_V_north(), fdm->get_V_east(), speed);
685 // }
686
687
688 \f
689 ////////////////////////////////////////////////////////////////////////
690 // Controls
691 ////////////////////////////////////////////////////////////////////////
692
693 #if 0
694
695 /**
696  * Get the throttle setting, from 0.0 (none) to 1.0 (full).
697  */
698 double
699 FGBFI::getThrottle ()
700 {
701                                 // FIXME: add engine selector
702   return controls.get_throttle(0);
703 }
704
705
706 /**
707  * Set the throttle, from 0.0 (none) to 1.0 (full).
708  */
709 void
710 FGBFI::setThrottle (double throttle)
711 {
712                                 // FIXME: allow engine selection
713   controls.set_throttle(0, throttle);
714 }
715
716
717 /**
718  * Get the fuel mixture setting, from 0.0 (none) to 1.0 (full).
719  */
720 double
721 FGBFI::getMixture ()
722 {
723                                 // FIXME: add engine selector
724   return controls.get_mixture(0);
725 }
726
727
728 /**
729  * Set the fuel mixture, from 0.0 (none) to 1.0 (full).
730  */
731 void
732 FGBFI::setMixture (double mixture)
733 {
734                                 // FIXME: allow engine selection
735   controls.set_mixture(0, mixture);
736 }
737
738
739 /**
740  * Get the propellor pitch setting, from 0.0 (none) to 1.0 (full).
741  */
742 double
743 FGBFI::getPropAdvance ()
744 {
745                                 // FIXME: add engine selector
746   return controls.get_prop_advance(0);
747 }
748
749
750 /**
751  * Set the propellor pitch, from 0.0 (none) to 1.0 (full).
752  */
753 void
754 FGBFI::setPropAdvance (double pitch)
755 {
756                                 // FIXME: allow engine selection
757   controls.set_prop_advance(0, pitch);
758 }
759
760
761 /**
762  * Get the flaps setting, from 0.0 (none) to 1.0 (full).
763  */
764 double
765 FGBFI::getFlaps ()
766 {
767   return controls.get_flaps();
768 }
769
770
771 /**
772  * Set the flaps, from 0.0 (none) to 1.0 (full).
773  */
774 void
775 FGBFI::setFlaps (double flaps)
776 {
777                                 // FIXME: clamp?
778   controls.set_flaps(flaps);
779 }
780
781
782 /**
783  * Get the aileron, from -1.0 (left) to 1.0 (right).
784  */
785 double
786 FGBFI::getAileron ()
787 {
788   return controls.get_aileron();
789 }
790
791
792 /**
793  * Set the aileron, from -1.0 (left) to 1.0 (right).
794  */
795 void
796 FGBFI::setAileron (double aileron)
797 {
798                                 // FIXME: clamp?
799   controls.set_aileron(aileron);
800 }
801
802
803 /**
804  * Get the rudder setting, from -1.0 (left) to 1.0 (right).
805  */
806 double
807 FGBFI::getRudder ()
808 {
809   return controls.get_rudder();
810 }
811
812
813 /**
814  * Set the rudder, from -1.0 (left) to 1.0 (right).
815  */
816 void
817 FGBFI::setRudder (double rudder)
818 {
819                                 // FIXME: clamp?
820   controls.set_rudder(rudder);
821 }
822
823
824 /**
825  * Get the elevator setting, from -1.0 (down) to 1.0 (up).
826  */
827 double
828 FGBFI::getElevator ()
829 {
830   return controls.get_elevator();
831 }
832
833
834 /**
835  * Set the elevator, from -1.0 (down) to 1.0 (up).
836  */
837 void
838 FGBFI::setElevator (double elevator)
839 {
840                                 // FIXME: clamp?
841   controls.set_elevator(elevator);
842 }
843
844
845 /**
846  * Get the elevator trim, from -1.0 (down) to 1.0 (up).
847  */
848 double
849 FGBFI::getElevatorTrim ()
850 {
851   return controls.get_elevator_trim();
852 }
853
854
855 /**
856  * Set the elevator trim, from -1.0 (down) to 1.0 (up).
857  */
858 void
859 FGBFI::setElevatorTrim (double trim)
860 {
861                                 // FIXME: clamp?
862   controls.set_elevator_trim(trim);
863 }
864
865
866 /**
867  * Get the highest brake setting, from 0.0 (none) to 1.0 (full).
868  */
869 double
870 FGBFI::getBrakes ()
871 {
872   double b1 = getCenterBrake();
873   double b2 = getLeftBrake();
874   double b3 = getRightBrake();
875   return (b1 > b2 ? (b1 > b3 ? b1 : b3) : (b2 > b3 ? b2 : b3));
876 }
877
878
879 /**
880  * Set all brakes, from 0.0 (none) to 1.0 (full).
881  */
882 void
883 FGBFI::setBrakes (double brake)
884 {
885   setCenterBrake(brake);
886   setLeftBrake(brake);
887   setRightBrake(brake);
888 }
889
890
891 /**
892  * Get the center brake, from 0.0 (none) to 1.0 (full).
893  */
894 double
895 FGBFI::getCenterBrake ()
896 {
897   return controls.get_brake(2);
898 }
899
900
901 /**
902  * Set the center brake, from 0.0 (none) to 1.0 (full).
903  */
904 void
905 FGBFI::setCenterBrake (double brake)
906 {
907   controls.set_brake(2, brake);
908 }
909
910
911 /**
912  * Get the left brake, from 0.0 (none) to 1.0 (full).
913  */
914 double
915 FGBFI::getLeftBrake ()
916 {
917   return controls.get_brake(0);
918 }
919
920
921 /**
922  * Set the left brake, from 0.0 (none) to 1.0 (full).
923  */
924 void
925 FGBFI::setLeftBrake (double brake)
926 {
927   controls.set_brake(0, brake);
928 }
929
930
931 /**
932  * Get the right brake, from 0.0 (none) to 1.0 (full).
933  */
934 double
935 FGBFI::getRightBrake ()
936 {
937   return controls.get_brake(1);
938 }
939
940
941 /**
942  * Set the right brake, from 0.0 (none) to 1.0 (full).
943  */
944 void
945 FGBFI::setRightBrake (double brake)
946 {
947   controls.set_brake(1, brake);
948 }
949
950
951 #endif
952
953 \f
954 ////////////////////////////////////////////////////////////////////////
955 // Autopilot
956 ////////////////////////////////////////////////////////////////////////
957
958
959 /**
960  * Get the autopilot altitude lock (true=on).
961  */
962 bool
963 FGBFI::getAPAltitudeLock ()
964 {
965     return current_autopilot->get_AltitudeEnabled();
966 }
967
968
969 /**
970  * Set the autopilot altitude lock (true=on).
971  */
972 void
973 FGBFI::setAPAltitudeLock (bool lock)
974 {
975   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
976   current_autopilot->set_AltitudeEnabled(lock);
977 }
978
979
980 /**
981  * Get the autopilot target altitude in feet.
982  */
983 double
984 FGBFI::getAPAltitude ()
985 {
986   return current_autopilot->get_TargetAltitude() * METER_TO_FEET;
987 }
988
989
990 /**
991  * Set the autopilot target altitude in feet.
992  */
993 void
994 FGBFI::setAPAltitude (double altitude)
995 {
996     current_autopilot->set_TargetAltitude( altitude );
997 }
998
999
1000 /**
1001  * Get the autopilot heading lock (true=on).
1002  */
1003 bool
1004 FGBFI::getAPHeadingLock ()
1005 {
1006     return
1007       (current_autopilot->get_HeadingEnabled() &&
1008        current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_LOCK);
1009 }
1010
1011
1012 /**
1013  * Set the autopilot heading lock (true=on).
1014  */
1015 void
1016 FGBFI::setAPHeadingLock (bool lock)
1017 {
1018   if (lock) {
1019                                 // We need to do this so that
1020                                 // it's possible to lock onto a
1021                                 // heading other than the current
1022                                 // heading.
1023     double heading = getAPHeadingMag();
1024     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_LOCK);
1025     current_autopilot->set_HeadingEnabled(true);
1026     setAPHeadingMag(heading);
1027   } else if (current_autopilot->get_HeadingMode() ==
1028              FGAutopilot::FG_HEADING_LOCK) {
1029     current_autopilot->set_HeadingEnabled(false);
1030   }
1031 }
1032
1033
1034 /**
1035  * Get the autopilot target heading in degrees.
1036  */
1037 double
1038 FGBFI::getAPHeading ()
1039 {
1040   return current_autopilot->get_TargetHeading();
1041 }
1042
1043
1044 /**
1045  * Set the autopilot target heading in degrees.
1046  */
1047 void
1048 FGBFI::setAPHeading (double heading)
1049 {
1050   current_autopilot->set_TargetHeading( heading );
1051 }
1052
1053
1054 /**
1055  * Get the autopilot DG target heading in degrees.
1056  */
1057 double
1058 FGBFI::getAPHeadingDG ()
1059 {
1060   return current_autopilot->get_DGTargetHeading();
1061 }
1062
1063
1064 /**
1065  * Set the autopilot DG target heading in degrees.
1066  */
1067 void
1068 FGBFI::setAPHeadingDG (double heading)
1069 {
1070   current_autopilot->set_DGTargetHeading( heading );
1071 }
1072
1073
1074 /**
1075  * Get the autopilot target heading in degrees.
1076  */
1077 double
1078 FGBFI::getAPHeadingMag ()
1079 {
1080   return current_autopilot->get_TargetHeading() - getMagVar();
1081 }
1082
1083
1084 /**
1085  * Set the autopilot target heading in degrees.
1086  */
1087 void
1088 FGBFI::setAPHeadingMag (double heading)
1089 {
1090   current_autopilot->set_TargetHeading( heading + getMagVar() );
1091 }
1092
1093
1094 /**
1095  * Return true if the autopilot is locked to NAV1.
1096  */
1097 bool
1098 FGBFI::getAPNAV1Lock ()
1099 {
1100   return
1101     (current_autopilot->get_HeadingEnabled() &&
1102      current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
1103 }
1104
1105
1106 /**
1107  * Set the autopilot NAV1 lock.
1108  */
1109 void
1110 FGBFI::setAPNAV1Lock (bool lock)
1111 {
1112   if (lock) {
1113     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
1114     current_autopilot->set_HeadingEnabled(true);
1115   } else if (current_autopilot->get_HeadingMode() ==
1116              FGAutopilot::FG_HEADING_NAV1) {
1117     current_autopilot->set_HeadingEnabled(false);
1118   }
1119 }
1120
1121
1122 \f
1123 ////////////////////////////////////////////////////////////////////////
1124 // GPS
1125 ////////////////////////////////////////////////////////////////////////
1126
1127
1128 /**
1129  * Get the autopilot GPS lock (true=on).
1130  */
1131 bool
1132 FGBFI::getGPSLock ()
1133 {
1134   return (current_autopilot->get_HeadingEnabled() &&
1135           (current_autopilot->get_HeadingMode() ==
1136            FGAutopilot::FG_HEADING_WAYPOINT ));
1137 }
1138
1139
1140 /**
1141  * Set the autopilot GPS lock (true=on).
1142  */
1143 void
1144 FGBFI::setGPSLock (bool lock)
1145 {
1146   if (lock) {
1147     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_WAYPOINT);
1148     current_autopilot->set_HeadingEnabled(true);
1149   } else if (current_autopilot->get_HeadingMode() ==
1150              FGAutopilot::FG_HEADING_WAYPOINT) {
1151     current_autopilot->set_HeadingEnabled(false);
1152   }
1153 }
1154
1155
1156 /**
1157  * Get the GPS target latitude in degrees (negative for south).
1158  */
1159 double
1160 FGBFI::getGPSTargetLatitude ()
1161 {
1162     return current_autopilot->get_TargetLatitude();
1163 }
1164
1165
1166 /**
1167  * Get the GPS target longitude in degrees (negative for west).
1168  */
1169 double
1170 FGBFI::getGPSTargetLongitude ()
1171 {
1172   return current_autopilot->get_TargetLongitude();
1173 }
1174
1175 #if 0
1176 /**
1177  * Set the GPS target longitude in degrees (negative for west).
1178  */
1179 void
1180 FGBFI::setGPSTargetLongitude (double longitude)
1181 {
1182   current_autopilot->set_TargetLongitude( longitude );
1183 }
1184 #endif
1185
1186
1187 \f
1188 ////////////////////////////////////////////////////////////////////////
1189 // Weather
1190 ////////////////////////////////////////////////////////////////////////
1191
1192
1193 /**
1194  * Get the current visibility (meters).
1195  */
1196 double
1197 FGBFI::getVisibility ()
1198 {
1199 #ifndef FG_OLD_WEATHER
1200   return WeatherDatabase->getWeatherVisibility();
1201 #else
1202   return current_weather.get_visibility();
1203 #endif
1204 }
1205
1206
1207 /**
1208  * Set the current visibility (meters).
1209  */
1210 void
1211 FGBFI::setVisibility (double visibility)
1212 {
1213 #ifndef FG_OLD_WEATHER
1214   WeatherDatabase->setWeatherVisibility(visibility);
1215 #else
1216   current_weather.set_visibility(visibility);
1217 #endif
1218 }
1219
1220
1221 /**
1222  * Get the current wind north velocity (feet/second).
1223  */
1224 double
1225 FGBFI::getWindNorth ()
1226 {
1227   return current_aircraft.fdm_state->get_V_north_airmass();
1228 }
1229
1230
1231 /**
1232  * Set the current wind north velocity (feet/second).
1233  */
1234 void
1235 FGBFI::setWindNorth (double speed)
1236 {
1237   current_aircraft.fdm_state->set_Velocities_Local_Airmass(speed,
1238                                                            getWindEast(),
1239                                                            getWindDown());
1240 }
1241
1242
1243 /**
1244  * Get the current wind east velocity (feet/second).
1245  */
1246 double
1247 FGBFI::getWindEast ()
1248 {
1249   return current_aircraft.fdm_state->get_V_east_airmass();
1250 }
1251
1252
1253 /**
1254  * Set the current wind east velocity (feet/second).
1255  */
1256 void
1257 FGBFI::setWindEast (double speed)
1258 {
1259   cout << "Set wind-east to " << speed << endl;
1260   current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
1261                                                            speed,
1262                                                            getWindDown());
1263 }
1264
1265
1266 /**
1267  * Get the current wind down velocity (feet/second).
1268  */
1269 double
1270 FGBFI::getWindDown ()
1271 {
1272   return current_aircraft.fdm_state->get_V_down_airmass();
1273 }
1274
1275
1276 /**
1277  * Set the current wind down velocity (feet/second).
1278  */
1279 void
1280 FGBFI::setWindDown (double speed)
1281 {
1282   current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
1283                                                            getWindEast(),
1284                                                            speed);
1285 }
1286
1287
1288 \f
1289 ////////////////////////////////////////////////////////////////////////
1290 // View.
1291 ////////////////////////////////////////////////////////////////////////
1292
1293 double
1294 FGBFI::getFOV ()
1295 {
1296   globals->get_current_view()->get_fov();
1297 }
1298
1299 void
1300 FGBFI::setFOV (double fov)
1301 {
1302   globals->get_current_view()->set_fov( fov );
1303 }
1304
1305 void
1306 FGBFI::setViewAxisLong (double axis)
1307 {
1308   axisLong = axis;
1309 }
1310
1311 void
1312 FGBFI::setViewAxisLat (double axis)
1313 {
1314   axisLat = axis;
1315 }
1316
1317 \f
1318 ////////////////////////////////////////////////////////////////////////
1319 // Time
1320 ////////////////////////////////////////////////////////////////////////
1321
1322 /**
1323  * Return the magnetic variation
1324  */
1325 double
1326 FGBFI::getMagVar ()
1327 {
1328   return globals->get_mag()->get_magvar() * RAD_TO_DEG;
1329 }
1330
1331
1332 /**
1333  * Return the magnetic variation
1334  */
1335 double
1336 FGBFI::getMagDip ()
1337 {
1338   return globals->get_mag()->get_magdip() * RAD_TO_DEG;
1339 }
1340
1341
1342 // end of bfi.cxx
1343