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