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