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