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