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