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