]> git.mxchange.org Git - flightgear.git/blob - src/Main/bfi.cxx
Moved sky code over to simgear.
[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 program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #if defined( FG_HAVE_NATIVE_SGI_COMPILERS )
29 #  include <iostream.h>
30 #else
31 #  include <iostream>
32 #endif
33
34 #include <simgear/constants.h>
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/math/fg_types.hxx>
37 #include <simgear/misc/props.hxx>
38
39 #include <Aircraft/aircraft.hxx>
40 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
41 #include <Controls/controls.hxx>
42 #include <Autopilot/newauto.hxx>
43 #include <Scenery/scenery.hxx>
44 #include <Time/fg_time.hxx>
45 #include <Time/light.hxx>
46 #include <Time/event.hxx>
47 #include <Time/sunpos.hxx>
48 #include <Cockpit/radiostack.hxx>
49 #include <Ephemeris/ephemeris.hxx>
50 #ifndef FG_OLD_WEATHER
51 #  include <WeatherCM/FGLocalWeatherDatabase.h>
52 #else
53 #  include <Weather/weather.hxx>
54 #endif
55
56 #include "options.hxx"
57 #include "save.hxx"
58 #include "fg_init.hxx"
59
60 FG_USING_NAMESPACE(std);
61
62
63 #include "bfi.hxx"
64
65
66 \f
67 ////////////////////////////////////////////////////////////////////////
68 // Static variables.
69 ////////////////////////////////////////////////////////////////////////
70
71 bool FGBFI::_needReinit = false;
72
73
74 \f
75 ////////////////////////////////////////////////////////////////////////
76 // Local functions
77 ////////////////////////////////////////////////////////////////////////
78
79
80 /**
81  * Initialize the BFI by binding its functions to properties.
82  *
83  * TODO: perhaps these should migrate into the individual modules
84  * (i.e. they should register themselves).
85  */
86 void
87 FGBFI::init ()
88 {
89   FG_LOG(FG_GENERAL, FG_INFO, "Starting BFI init");
90                                 // Simulation
91   current_properties.tieInt("/sim/flight-model",
92                             getFlightModel, setFlightModel);
93 //   current_properties.tieString("/sim/aircraft",
94 //                             getAircraft, setAircraft);
95   // TODO: timeGMT
96   current_properties.tieBool("/sim/hud/visibility",
97                              getHUDVisible, setHUDVisible);
98   current_properties.tieBool("/sim/panel/visibility",
99                              getPanelVisible, setPanelVisible);
100
101                                 // Position
102   current_properties.tieDouble("/position/latitude",
103                                 getLatitude, setLatitude);
104   current_properties.tieDouble("/position/longitude",
105                                getLongitude, setLongitude);
106   current_properties.tieDouble("/position/altitude",
107                                getAltitude, setAltitude);
108   current_properties.tieDouble("/position/altitude-agl",
109                                getAGL, 0);
110
111                                 // Orientation
112   current_properties.tieDouble("/orientation/heading",
113                                getHeading, setHeading);
114   current_properties.tieDouble("/orientation/heading-magnetic",
115                                getHeadingMag, 0);
116   current_properties.tieDouble("/orientation/pitch",
117                                getPitch, setPitch);
118   current_properties.tieDouble("/orientation/roll",
119                                getRoll, setRoll);
120
121                                 // Velocities
122   current_properties.tieDouble("/velocities/airspeed",
123                                getAirspeed, 0);
124   current_properties.tieDouble("/velocities/side-slip",
125                                getSideSlip, 0);
126   current_properties.tieDouble("/velocities/vertical-speed",
127                                getVerticalSpeed, 0);
128   current_properties.tieDouble("/velocities/speed-north",
129                                getSpeedNorth, setSpeedNorth);
130   current_properties.tieDouble("/velocities/speed-east",
131                                getSpeedEast, setSpeedEast);
132   current_properties.tieDouble("/velocities/speed-down",
133                                getSpeedDown, setSpeedDown);
134
135                                 // Controls
136   current_properties.tieDouble("/controls/throttle",
137                                getThrottle, setThrottle);
138   current_properties.tieDouble("/controls/flaps",
139                                getFlaps, setFlaps);
140   current_properties.tieDouble("/controls/aileron",
141                                getAileron, setAileron);
142   current_properties.tieDouble("/controls/rudder",
143                                getRudder, setRudder);
144   current_properties.tieDouble("/controls/elevator",
145                                getElevator, setElevator);
146   current_properties.tieDouble("/controls/elevator-trim",
147                                getElevatorTrim, setElevatorTrim);
148   current_properties.tieDouble("/controls/brake",
149                                getBrake, setBrake);
150
151                                 // Autopilot
152   current_properties.tieBool("/autopilot/locks/altitude",
153                              getAPAltitudeLock, setAPAltitudeLock);
154   current_properties.tieDouble("/autopilot/settings/altitude",
155                                getAPAltitude, setAPAltitude);
156   current_properties.tieBool("/autopilot/locks/heading",
157                              getAPHeadingLock, setAPHeadingLock);
158   current_properties.tieDouble("/autopilot/settings/heading-magnetic",
159                                getAPHeadingMag, setAPHeadingMag);
160   current_properties.tieBool("/autopilot/locks/nav1",
161                              getAPNAV1Lock, setAPNAV1Lock);
162
163                                 // Radio navigation
164   current_properties.tieDouble("/radios/nav1/frequencies/selected",
165                                getNAV1Freq, setNAV1Freq);
166   current_properties.tieDouble("/radios/nav1/frequencies/standby",
167                                getNAV1AltFreq, setNAV1AltFreq);
168   current_properties.tieDouble("/radios/nav1/radials/actual",
169                                getNAV1Radial, 0);
170   current_properties.tieDouble("/radios/nav1/radials/selected",
171                                getNAV1SelRadial, setNAV1SelRadial);
172   current_properties.tieDouble("/radios/nav1/dme/distance",
173                                getNAV1DistDME, 0);
174   current_properties.tieBool("/radios/nav1/in-range",
175                              getNAV1InRange, 0);
176   current_properties.tieBool("/radios/nav1/dme/in-range",
177                              getNAV1DMEInRange, 0);
178                                
179   current_properties.tieDouble("/radios/nav2/frequencies/selected",
180                                getNAV2Freq, setNAV2Freq);
181   current_properties.tieDouble("/radios/nav2/frequencies/standby",
182                                getNAV2AltFreq, setNAV2AltFreq);
183   current_properties.tieDouble("/radios/nav2/radials/actual",
184                                getNAV2Radial, 0);
185   current_properties.tieDouble("/radios/nav2/radials/selected",
186                                getNAV2SelRadial, setNAV2SelRadial);
187   current_properties.tieDouble("/radios/nav2/dme/distance",
188                                getNAV2DistDME, 0);
189   current_properties.tieBool("/radios/nav2/in-range",
190                              getNAV2InRange, 0);
191   current_properties.tieBool("/radios/nav2/dme/in-range",
192                              getNAV2DMEInRange, 0);
193
194   current_properties.tieDouble("/radios/adf/frequencies/selected",
195                                getADFFreq, setADFFreq);
196   current_properties.tieDouble("/radios/adf/frequencies/standby",
197                                getADFAltFreq, setADFAltFreq);
198   current_properties.tieDouble("/radios/adf/rotation",
199                                getADFRotation, setADFRotation);
200
201   FG_LOG(FG_GENERAL, FG_INFO, "Ending BFI init");
202 }
203
204
205 /**
206  * Reinitialize FGFS if required.
207  *
208  * Some changes (especially those in aircraft position) require that
209  * FGFS be reinitialized afterwards.  Rather than reinitialize after
210  * every change, the setter methods simply set a flag so that there
211  * can be a single reinit at the end of the frame.
212  */
213 void
214 FGBFI::update ()
215 {
216   if (_needReinit) {
217     reinit();
218   }
219 }
220
221
222 /**
223  * Reinitialize FGFS to use the new BFI settings.
224  */
225 void
226 FGBFI::reinit ()
227 {
228                                 // Save the state of everything
229                                 // that's going to get clobbered
230                                 // when we reinit the subsystems.
231
232   cout << "BFI: start reinit\n";
233
234   setHeading(getHeading());
235   setPitch(getPitch());
236   setRoll(getRoll());
237   setSpeedNorth(getSpeedNorth());
238   setSpeedEast(getSpeedEast());
239   setSpeedDown(getSpeedDown());
240   setLatitude(getLatitude());
241   setLongitude(getLongitude());
242   setAltitude(getAltitude());
243
244                                 // TODO: add more AP stuff
245   double elevator = getElevator();
246   double aileron = getAileron();
247   double rudder = getRudder();
248   double throttle = getThrottle();
249   double elevator_trim = getElevatorTrim();
250   double flaps = getFlaps();
251   double brake = getBrake();
252   bool apHeadingLock = getAPHeadingLock();
253   double apHeadingMag = getAPHeadingMag();
254   bool apAltitudeLock = getAPAltitudeLock();
255   double apAltitude = getAPAltitude();
256   const string &targetAirport = getTargetAirport();
257   bool gpsLock = getGPSLock();
258   double gpsLatitude = getGPSTargetLatitude();
259   double gpsLongitude = getGPSTargetLongitude();
260
261   setTargetAirport("");
262   cout << "Target airport is " << current_options.get_airport_id() << endl;
263
264   fgReInitSubsystems();
265
266                                 // FIXME: this is wrong.
267                                 // All of these are scheduled events,
268                                 // and it should be possible to force
269                                 // them all to run once.
270   fgUpdateSunPos();
271   fgUpdateMoonPos();
272   cur_light_params.Update();
273   FGTime::cur_time_params->updateLocal();
274   fgUpdateWeatherDatabase();
275   fgRadioSearch();
276
277                                 // Restore all of the old states.
278   setElevator(elevator);
279   setAileron(aileron);
280   setRudder(rudder);
281   setThrottle(throttle);
282   setElevatorTrim(elevator_trim);
283   setFlaps(flaps);
284   setBrake(brake);
285   setAPHeadingLock(apHeadingLock);
286   setAPHeadingMag(apHeadingMag);
287   setAPAltitudeLock(apAltitudeLock);
288   setAPAltitude(apAltitude);
289   setTargetAirport(targetAirport);
290   setGPSLock(gpsLock);
291   setGPSTargetLatitude(gpsLatitude);
292   setGPSTargetLongitude(gpsLongitude);
293
294   _needReinit = false;
295
296   cout << "BFI: end reinit\n";
297 }
298
299
300 \f
301 ////////////////////////////////////////////////////////////////////////
302 // Simulation.
303 ////////////////////////////////////////////////////////////////////////
304
305
306 /**
307  * Return the flight model as an integer.
308  *
309  * TODO: use a string instead.
310  */
311 int
312 FGBFI::getFlightModel ()
313 {
314   return current_options.get_flight_model();
315 }
316
317
318 /**
319  * Return the current aircraft as a string.
320  */
321 const string
322 FGBFI::getAircraft ()
323 {
324   return current_options.get_aircraft();
325 }
326
327
328 /**
329  * Return the current aircraft directory (UIUC) as a string.
330  */
331 const string
332 FGBFI::getAircraftDir ()
333 {
334   return aircraft_dir;
335 }
336
337
338 /**
339  * Set the flight model as an integer.
340  *
341  * TODO: use a string instead.
342  */
343 void
344 FGBFI::setFlightModel (int model)
345 {
346   current_options.set_flight_model(model);
347   needReinit();
348 }
349
350
351 /**
352  * Set the current aircraft.
353  */
354 void
355 FGBFI::setAircraft (const string &aircraft)
356 {
357   current_options.set_aircraft(aircraft);
358   needReinit();
359 }
360
361
362 /**
363  * Set the current aircraft directory (UIUC).
364  */
365 void
366 FGBFI::setAircraftDir (const string &dir)
367 {
368   aircraft_dir = dir;
369   needReinit();
370 }
371
372
373 /**
374  * Return the current Zulu time.
375  */
376 time_t
377 FGBFI::getTimeGMT ()
378 {
379   return FGTime::cur_time_params->get_cur_time();
380 }
381
382
383 /**
384  * Set the current Zulu time.
385  */
386 void
387 FGBFI::setTimeGMT (time_t time)
388 {
389                                 // FIXME: need to update lighting
390                                 // and solar system
391   current_options.set_time_offset(time);
392   current_options.set_time_offset_type(fgOPTIONS::FG_TIME_GMT_ABSOLUTE);
393   FGTime::cur_time_params->init( cur_fdm_state->get_Longitude(),
394                                  cur_fdm_state->get_Latitude() );
395   FGTime::cur_time_params->update( cur_fdm_state->get_Longitude(),
396                                    cur_fdm_state->get_Latitude(),
397                                    cur_fdm_state->get_Altitude()
398                                    * FEET_TO_METER );
399   needReinit();
400 }
401
402
403 /**
404  * Return true if the HUD is visible.
405  */
406 bool
407 FGBFI::getHUDVisible ()
408 {
409   return current_options.get_hud_status();
410 }
411
412
413 /**
414  * Ensure that the HUD is visible or hidden.
415  */
416 void
417 FGBFI::setHUDVisible (bool visible)
418 {
419   current_options.set_hud_status(visible);
420 }
421
422
423 /**
424  * Return true if the 2D panel is visible.
425  */
426 bool
427 FGBFI::getPanelVisible ()
428 {
429   return current_options.get_panel_status();
430 }
431
432
433 /**
434  * Ensure that the 2D panel is visible or hidden.
435  */
436 void
437 FGBFI::setPanelVisible (bool visible)
438 {
439   if (current_options.get_panel_status() != visible) {
440     current_options.toggle_panel();
441   }
442 }
443
444
445 \f
446 ////////////////////////////////////////////////////////////////////////
447 // Position
448 ////////////////////////////////////////////////////////////////////////
449
450
451 /**
452  * Return the current latitude in degrees (negative for south).
453  */
454 double
455 FGBFI::getLatitude ()
456 {
457   return current_aircraft.fdm_state->get_Latitude() * RAD_TO_DEG;
458 }
459
460
461 /**
462  * Set the current latitude in degrees (negative for south).
463  */
464 void
465 FGBFI::setLatitude (double latitude)
466 {
467   current_options.set_lat(latitude);
468   current_aircraft.fdm_state->set_Latitude(latitude * DEG_TO_RAD);
469   needReinit();
470 }
471
472
473 /**
474  * Return the current longitude in degrees (negative for west).
475  */
476 double
477 FGBFI::getLongitude ()
478 {
479   return current_aircraft.fdm_state->get_Longitude() * RAD_TO_DEG;
480 }
481
482
483 /**
484  * Set the current longitude in degrees (negative for west).
485  */
486 void
487 FGBFI::setLongitude (double longitude)
488 {
489   current_options.set_lon(longitude);
490   current_aircraft.fdm_state->set_Longitude(longitude * DEG_TO_RAD);
491   needReinit();
492 }
493
494
495 /**
496  * Return the current altitude in feet.
497  */
498 double
499 FGBFI::getAltitude ()
500 {
501   return current_aircraft.fdm_state->get_Altitude();
502 }
503
504
505
506 /**
507  * Return the current altitude in above the terrain.
508  */
509 double
510 FGBFI::getAGL ()
511 {
512   return current_aircraft.fdm_state->get_Altitude()
513          - scenery.cur_elev * METER_TO_FEET;
514 }
515
516
517 /**
518  * Set the current altitude in feet.
519  */
520 void
521 FGBFI::setAltitude (double altitude)
522 {
523   fgFDMForceAltitude(getFlightModel(), altitude * FEET_TO_METER);
524 //   current_options.set_altitude(altitude * FEET_TO_METER);
525 //   current_aircraft.fdm_state->set_Altitude(altitude);
526 //   needReinit();
527 }
528
529
530 \f
531 ////////////////////////////////////////////////////////////////////////
532 // Attitude
533 ////////////////////////////////////////////////////////////////////////
534
535
536 /**
537  * Return the current heading in degrees.
538  */
539 double
540 FGBFI::getHeading ()
541 {
542   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG;
543 }
544
545
546 /**
547  * Return the current heading in degrees.
548  */
549 double
550 FGBFI::getHeadingMag ()
551 {
552   return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG - getMagVar();
553 }
554
555
556 /**
557  * Set the current heading in degrees.
558  */
559 void
560 FGBFI::setHeading (double heading)
561 {
562   current_options.set_heading(heading);
563   current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
564                                                getPitch() * DEG_TO_RAD,
565                                                heading * DEG_TO_RAD);
566   needReinit();
567 }
568
569
570 /**
571  * Return the current pitch in degrees.
572  */
573 double
574 FGBFI::getPitch ()
575 {
576   return current_aircraft.fdm_state->get_Theta() * RAD_TO_DEG;
577 }
578
579
580 /**
581  * Set the current pitch in degrees.
582  */
583 void
584 FGBFI::setPitch (double pitch)
585 {
586
587   current_options.set_pitch(pitch);
588   current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
589                                                pitch * DEG_TO_RAD,
590                                                getHeading() * DEG_TO_RAD);
591   needReinit();
592 }
593
594
595 /**
596  * Return the current roll in degrees.
597  */
598 double
599 FGBFI::getRoll ()
600 {
601   return current_aircraft.fdm_state->get_Phi() * RAD_TO_DEG;
602 }
603
604
605 /**
606  * Set the current roll in degrees.
607  */
608 void
609 FGBFI::setRoll (double roll)
610 {
611   current_options.set_roll(roll);
612   current_aircraft.fdm_state->set_Euler_Angles(roll * DEG_TO_RAD,
613                                                getPitch() * DEG_TO_RAD,
614                                                getHeading() * DEG_TO_RAD);
615   needReinit();
616 }
617
618
619 \f
620 ////////////////////////////////////////////////////////////////////////
621 // Velocities
622 ////////////////////////////////////////////////////////////////////////
623
624
625 /**
626  * Return the current airspeed in knots.
627  */
628 double
629 FGBFI::getAirspeed ()
630 {
631                                 // FIXME: should we add speed-up?
632   return current_aircraft.fdm_state->get_V_calibrated_kts();
633 }
634
635
636 /**
637  * Return the current sideslip (FIXME: units unknown).
638  */
639 double
640 FGBFI::getSideSlip ()
641 {
642   return current_aircraft.fdm_state->get_Beta();
643 }
644
645
646 /**
647  * Return the current climb rate in feet/minute
648  */
649 double
650 FGBFI::getVerticalSpeed ()
651 {
652                                 // What about meters?
653   return current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
654 }
655
656
657 /**
658  * Get the current north velocity (units??).
659  */
660 double
661 FGBFI::getSpeedNorth ()
662 {
663   return current_aircraft.fdm_state->get_V_north();
664 }
665
666
667 /**
668  * Set the current north velocity (units??).
669  */
670 void
671 FGBFI::setSpeedNorth (double speed)
672 {
673   current_options.set_uBody(speed);
674   current_aircraft.fdm_state->set_Velocities_Local(speed,
675                                                    getSpeedEast(),
676                                                    getSpeedDown());
677   needReinit();
678 }
679
680
681 /**
682  * Get the current east velocity (units??).
683  */
684 double
685 FGBFI::getSpeedEast ()
686 {
687   return current_aircraft.fdm_state->get_V_east();
688 }
689
690
691 /**
692  * Set the current east velocity (units??).
693  */
694 void
695 FGBFI::setSpeedEast (double speed)
696 {
697   current_options.set_vBody(speed);
698   current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
699                                                    speed,
700                                                    getSpeedDown());
701   needReinit();
702 }
703
704
705 /**
706  * Get the current down velocity (units??).
707  */
708 double
709 FGBFI::getSpeedDown ()
710 {
711   return current_aircraft.fdm_state->get_V_down();
712 }
713
714
715 /**
716  * Set the current down velocity (units??).
717  */
718 void
719 FGBFI::setSpeedDown (double speed)
720 {
721   current_options.set_wBody(speed);
722   current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
723                                                    getSpeedEast(),
724                                                    speed);
725   needReinit();
726 }
727
728
729 \f
730 ////////////////////////////////////////////////////////////////////////
731 // Controls
732 ////////////////////////////////////////////////////////////////////////
733
734
735 /**
736  * Get the throttle setting, from 0.0 (none) to 1.0 (full).
737  */
738 double
739 FGBFI::getThrottle ()
740 {
741                                 // FIXME: add throttle selector
742   return controls.get_throttle(0);
743 }
744
745
746 /**
747  * Set the throttle, from 0.0 (none) to 1.0 (full).
748  */
749 void
750 FGBFI::setThrottle (double throttle)
751 {
752                                 // FIXME: allow throttle selection
753                                 // FIXME: clamp?
754   controls.set_throttle(0, throttle);
755 }
756
757
758 /**
759  * Get the flaps setting, from 0.0 (none) to 1.0 (full).
760  */
761 double
762 FGBFI::getFlaps ()
763 {
764   return controls.get_flaps();
765 }
766
767
768 /**
769  * Set the flaps, from 0.0 (none) to 1.0 (full).
770  */
771 void
772 FGBFI::setFlaps (double flaps)
773 {
774                                 // FIXME: clamp?
775   controls.set_flaps(flaps);
776 }
777
778
779 /**
780  * Get the aileron, from -1.0 (left) to 1.0 (right).
781  */
782 double
783 FGBFI::getAileron ()
784 {
785   return controls.get_aileron();
786 }
787
788
789 /**
790  * Set the aileron, from -1.0 (left) to 1.0 (right).
791  */
792 void
793 FGBFI::setAileron (double aileron)
794 {
795                                 // FIXME: clamp?
796   controls.set_aileron(aileron);
797 }
798
799
800 /**
801  * Get the rudder setting, from -1.0 (left) to 1.0 (right).
802  */
803 double
804 FGBFI::getRudder ()
805 {
806   return controls.get_rudder();
807 }
808
809
810 /**
811  * Set the rudder, from -1.0 (left) to 1.0 (right).
812  */
813 void
814 FGBFI::setRudder (double rudder)
815 {
816                                 // FIXME: clamp?
817   controls.set_rudder(rudder);
818 }
819
820
821 /**
822  * Get the elevator setting, from -1.0 (down) to 1.0 (up).
823  */
824 double
825 FGBFI::getElevator ()
826 {
827   return controls.get_elevator();
828 }
829
830
831 /**
832  * Set the elevator, from -1.0 (down) to 1.0 (up).
833  */
834 void
835 FGBFI::setElevator (double elevator)
836 {
837                                 // FIXME: clamp?
838   controls.set_elevator(elevator);
839 }
840
841
842 /**
843  * Get the elevator trim, from -1.0 (down) to 1.0 (up).
844  */
845 double
846 FGBFI::getElevatorTrim ()
847 {
848   return controls.get_elevator_trim();
849 }
850
851
852 /**
853  * Set the elevator trim, from -1.0 (down) to 1.0 (up).
854  */
855 void
856 FGBFI::setElevatorTrim (double trim)
857 {
858                                 // FIXME: clamp?
859   controls.set_elevator_trim(trim);
860 }
861
862
863 /**
864  * Get the brake setting, from 0.0 (none) to 1.0 (full).
865  */
866 double
867 FGBFI::getBrake ()
868 {
869                                 // FIXME: add brake selector
870   return controls.get_brake(0);
871 }
872
873
874 /**
875  * Set the brake, from 0.0 (none) to 1.0 (full).
876  */
877 void
878 FGBFI::setBrake (double brake)
879 {
880                                 // FIXME: clamp?
881                                 // FIXME: allow brake selection
882   controls.set_brake(0, brake);
883 }
884
885
886 \f
887 ////////////////////////////////////////////////////////////////////////
888 // Autopilot
889 ////////////////////////////////////////////////////////////////////////
890
891
892 /**
893  * Get the autopilot altitude lock (true=on).
894  */
895 bool
896 FGBFI::getAPAltitudeLock ()
897 {
898     return current_autopilot->get_AltitudeEnabled();
899 }
900
901
902 /**
903  * Set the autopilot altitude lock (true=on).
904  */
905 void
906 FGBFI::setAPAltitudeLock (bool lock)
907 {
908   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
909   current_autopilot->set_AltitudeEnabled(lock);
910 }
911
912
913 /**
914  * Get the autopilot target altitude in feet.
915  */
916 double
917 FGBFI::getAPAltitude ()
918 {
919   return current_autopilot->get_TargetAltitude() * METER_TO_FEET;
920 }
921
922
923 /**
924  * Set the autopilot target altitude in feet.
925  */
926 void
927 FGBFI::setAPAltitude (double altitude)
928 {
929     current_autopilot->set_TargetAltitude( altitude );
930 }
931
932
933 /**
934  * Get the autopilot heading lock (true=on).
935  */
936 bool
937 FGBFI::getAPHeadingLock ()
938 {
939     return
940       (current_autopilot->get_HeadingEnabled() &&
941        current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_LOCK);
942 }
943
944
945 /**
946  * Set the autopilot heading lock (true=on).
947  */
948 void
949 FGBFI::setAPHeadingLock (bool lock)
950 {
951   if (lock) {
952                                 // We need to do this so that
953                                 // it's possible to lock onto a
954                                 // heading other than the current
955                                 // heading.
956     double heading = getAPHeadingMag();
957     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_LOCK);
958     current_autopilot->set_HeadingEnabled(true);
959     setAPHeadingMag(heading);
960   } else if (current_autopilot->get_HeadingMode() ==
961              FGAutopilot::FG_HEADING_LOCK) {
962     current_autopilot->set_HeadingEnabled(false);
963   }
964 }
965
966
967 /**
968  * Get the autopilot target heading in degrees.
969  */
970 double
971 FGBFI::getAPHeadingMag ()
972 {
973   return current_autopilot->get_TargetHeading() - getMagVar();
974 }
975
976
977 /**
978  * Set the autopilot target heading in degrees.
979  */
980 void
981 FGBFI::setAPHeadingMag (double heading)
982 {
983   current_autopilot->set_TargetHeading( heading + getMagVar() );
984 }
985
986
987 /**
988  * Return true if the autopilot is locked to NAV1.
989  */
990 bool
991 FGBFI::getAPNAV1Lock ()
992 {
993   return
994     (current_autopilot->get_HeadingEnabled() &&
995      current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
996 }
997
998
999 /**
1000  * Set the autopilot NAV1 lock.
1001  */
1002 void
1003 FGBFI::setAPNAV1Lock (bool lock)
1004 {
1005   if (lock) {
1006     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
1007     current_autopilot->set_HeadingEnabled(true);
1008   } else if (current_autopilot->get_HeadingMode() ==
1009              FGAutopilot::FG_HEADING_NAV1) {
1010     current_autopilot->set_HeadingEnabled(false);
1011   }
1012 }
1013
1014
1015 \f
1016 ////////////////////////////////////////////////////////////////////////
1017 // Radio navigation.
1018 ////////////////////////////////////////////////////////////////////////
1019
1020 double
1021 FGBFI::getNAV1Freq ()
1022 {
1023   return current_radiostack->get_nav1_freq();
1024 }
1025
1026 double
1027 FGBFI::getNAV1AltFreq ()
1028 {
1029   return current_radiostack->get_nav1_alt_freq();
1030 }
1031
1032 double
1033 FGBFI::getNAV1Radial ()
1034 {
1035   return current_radiostack->get_nav1_radial();
1036 }
1037
1038 double
1039 FGBFI::getNAV1SelRadial ()
1040 {
1041   return current_radiostack->get_nav1_sel_radial();
1042 }
1043
1044 double
1045 FGBFI::getNAV1DistDME ()
1046 {
1047   return current_radiostack->get_nav1_dme_dist();
1048 }
1049
1050 bool
1051 FGBFI::getNAV1InRange ()
1052 {
1053   return current_radiostack->get_nav1_inrange();
1054 }
1055
1056 bool
1057 FGBFI::getNAV1DMEInRange ()
1058 {
1059   return (current_radiostack->get_nav1_inrange() &&
1060           current_radiostack->get_nav1_has_dme());
1061 }
1062
1063 double
1064 FGBFI::getNAV2Freq ()
1065 {
1066   return current_radiostack->get_nav2_freq();
1067 }
1068
1069 double
1070 FGBFI::getNAV2AltFreq ()
1071 {
1072   return current_radiostack->get_nav2_alt_freq();
1073 }
1074
1075 double
1076 FGBFI::getNAV2Radial ()
1077 {
1078   return current_radiostack->get_nav2_radial();
1079 }
1080
1081 double
1082 FGBFI::getNAV2SelRadial ()
1083 {
1084   return current_radiostack->get_nav2_sel_radial();
1085 }
1086
1087 double
1088 FGBFI::getNAV2DistDME ()
1089 {
1090   return current_radiostack->get_nav2_dme_dist();
1091 }
1092
1093 bool
1094 FGBFI::getNAV2InRange ()
1095 {
1096   return current_radiostack->get_nav2_inrange();
1097 }
1098
1099 bool
1100 FGBFI::getNAV2DMEInRange ()
1101 {
1102   return (current_radiostack->get_nav2_inrange() &&
1103           current_radiostack->get_nav2_has_dme());
1104 }
1105
1106 double
1107 FGBFI::getADFFreq ()
1108 {
1109   return current_radiostack->get_adf_freq();
1110 }
1111
1112 double
1113 FGBFI::getADFAltFreq ()
1114 {
1115   return current_radiostack->get_adf_alt_freq();
1116 }
1117
1118 double
1119 FGBFI::getADFRotation ()
1120 {
1121   return current_radiostack->get_adf_rotation();
1122 }
1123
1124 void
1125 FGBFI::setNAV1Freq (double freq)
1126 {
1127   current_radiostack->set_nav1_freq(freq);
1128 }
1129
1130 void
1131 FGBFI::setNAV1AltFreq (double freq)
1132 {
1133   current_radiostack->set_nav1_alt_freq(freq);
1134 }
1135
1136 void
1137 FGBFI::setNAV1SelRadial (double radial)
1138 {
1139   current_radiostack->set_nav1_sel_radial(radial);
1140 }
1141
1142 void
1143 FGBFI::setNAV2Freq (double freq)
1144 {
1145   current_radiostack->set_nav2_freq(freq);
1146 }
1147
1148 void
1149 FGBFI::setNAV2AltFreq (double freq)
1150 {
1151   current_radiostack->set_nav2_alt_freq(freq);
1152 }
1153
1154 void
1155 FGBFI::setNAV2SelRadial (double radial)
1156 {
1157   current_radiostack->set_nav2_sel_radial(radial);
1158 }
1159
1160 void
1161 FGBFI::setADFFreq (double freq)
1162 {
1163   current_radiostack->set_adf_freq(freq);
1164 }
1165
1166 void
1167 FGBFI::setADFAltFreq (double freq)
1168 {
1169   current_radiostack->set_adf_alt_freq(freq);
1170 }
1171
1172 void
1173 FGBFI::setADFRotation (double rot)
1174 {
1175   current_radiostack->set_adf_rotation(rot);
1176 }
1177
1178
1179 \f
1180 ////////////////////////////////////////////////////////////////////////
1181 // GPS
1182 ////////////////////////////////////////////////////////////////////////
1183
1184
1185 /**
1186  * Get the autopilot GPS lock (true=on).
1187  */
1188 bool
1189 FGBFI::getGPSLock ()
1190 {
1191   return (current_autopilot->get_HeadingEnabled() &&
1192           (current_autopilot->get_HeadingMode() ==
1193            FGAutopilot::FG_HEADING_WAYPOINT ));
1194 }
1195
1196
1197 /**
1198  * Set the autopilot GPS lock (true=on).
1199  */
1200 void
1201 FGBFI::setGPSLock (bool lock)
1202 {
1203   if (lock) {
1204     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_WAYPOINT);
1205     current_autopilot->set_HeadingEnabled(true);
1206   } else if (current_autopilot->get_HeadingMode() ==
1207              FGAutopilot::FG_HEADING_WAYPOINT) {
1208     current_autopilot->set_HeadingEnabled(false);
1209   }
1210 }
1211
1212
1213 /**
1214  * Get the GPS target airport code.
1215  */
1216 const string
1217 FGBFI::getTargetAirport ()
1218 {
1219   return current_options.get_airport_id();
1220 }
1221
1222
1223 /**
1224  * Set the GPS target airport code.
1225  */
1226 void
1227 FGBFI::setTargetAirport (const string &airportId)
1228 {
1229   current_options.set_airport_id(airportId);
1230 }
1231
1232
1233 /**
1234  * Get the GPS target latitude in degrees (negative for south).
1235  */
1236 double
1237 FGBFI::getGPSTargetLatitude ()
1238 {
1239     return current_autopilot->get_TargetLatitude();
1240 }
1241
1242
1243 /**
1244  * Set the GPS target latitude in degrees (negative for south).
1245  */
1246 void
1247 FGBFI::setGPSTargetLatitude (double latitude)
1248 {
1249   current_autopilot->set_TargetLatitude( latitude );
1250 }
1251
1252
1253 /**
1254  * Get the GPS target longitude in degrees (negative for west).
1255  */
1256 double
1257 FGBFI::getGPSTargetLongitude ()
1258 {
1259   return current_autopilot->get_TargetLongitude();
1260 }
1261
1262
1263 /**
1264  * Set the GPS target longitude in degrees (negative for west).
1265  */
1266 void
1267 FGBFI::setGPSTargetLongitude (double longitude)
1268 {
1269   current_autopilot->set_TargetLongitude( longitude );
1270 }
1271
1272
1273 \f
1274 ////////////////////////////////////////////////////////////////////////
1275 // Weather
1276 ////////////////////////////////////////////////////////////////////////
1277
1278
1279 /**
1280  * Get the current visible (units??).
1281  */
1282 double
1283 FGBFI::getVisibility ()
1284 {
1285 #ifndef FG_OLD_WEATHER
1286   return WeatherDatabase->getWeatherVisibility();
1287 #else
1288   return current_weather.get_visibility();
1289 #endif
1290 }
1291
1292
1293 /**
1294  * Check whether clouds are enabled.
1295  */
1296 bool
1297 FGBFI::getClouds ()
1298 {
1299   return current_options.get_clouds();
1300 }
1301
1302
1303 /**
1304  * Check the height of the clouds ASL (units?).
1305  */
1306 double
1307 FGBFI::getCloudsASL ()
1308 {
1309   return current_options.get_clouds_asl();
1310 }
1311
1312
1313 /**
1314  * Set the current visibility (units??).
1315  */
1316 void
1317 FGBFI::setVisibility (double visibility)
1318 {
1319 #ifndef FG_OLD_WEATHER
1320   WeatherDatabase->setWeatherVisibility(visibility);
1321 #else
1322   current_weather.set_visibility(visibility);
1323 #endif
1324 }
1325
1326
1327 /**
1328  * Switch clouds on or off.
1329  */
1330 void
1331 FGBFI::setClouds (bool clouds)
1332 {
1333   cout << "Set clouds to " << clouds << endl;
1334   current_options.set_clouds(clouds);
1335   needReinit();
1336 }
1337
1338
1339 /**
1340  * Set the cloud height.
1341  */
1342 void
1343 FGBFI::setCloudsASL (double cloudsASL)
1344 {
1345   current_options.set_clouds_asl(cloudsASL);
1346   needReinit();
1347 }
1348
1349
1350 \f
1351 ////////////////////////////////////////////////////////////////////////
1352 // Time
1353 ////////////////////////////////////////////////////////////////////////
1354
1355 /**
1356  * Return the magnetic variation
1357  */
1358 double
1359 FGBFI::getMagVar ()
1360 {
1361   return FGTime::cur_time_params->getMagVar() * RAD_TO_DEG;
1362 }
1363
1364
1365 /**
1366  * Return the magnetic variation
1367  */
1368 double
1369 FGBFI::getMagDip ()
1370 {
1371   return FGTime::cur_time_params->getMagDip() * RAD_TO_DEG;
1372 }
1373
1374
1375 // end of bfi.cxx
1376