1 // bfi.cxx - Big Friendly Interface implementation
3 // Written by David Megginson, started February, 2000.
5 // Copyright (C) 2000 David Megginson - david@megginson.com
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.
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.
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.
28 #if defined( FG_HAVE_NATIVE_SGI_COMPILERS )
29 # include <iostream.h>
34 #include <simgear/constants.h>
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/math/fg_types.hxx>
38 #include <Aircraft/aircraft.hxx>
39 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
40 #include <Controls/controls.hxx>
41 #include <Autopilot/newauto.hxx>
42 #include <Scenery/scenery.hxx>
43 #include <Time/fg_time.hxx>
44 #include <Time/light.hxx>
45 #include <Time/event.hxx>
46 #include <Time/sunpos.hxx>
47 #include <Cockpit/radiostack.hxx>
48 #include <Ephemeris/ephemeris.hxx>
49 #ifndef FG_OLD_WEATHER
50 # include <WeatherCM/FGLocalWeatherDatabase.h>
52 # include <Weather/weather.hxx>
55 #include "options.hxx"
57 #include "fg_init.hxx"
59 FG_USING_NAMESPACE(std);
66 ////////////////////////////////////////////////////////////////////////
68 ////////////////////////////////////////////////////////////////////////
70 bool FGBFI::_needReinit = false;
74 ////////////////////////////////////////////////////////////////////////
76 ////////////////////////////////////////////////////////////////////////
80 * Reinitialize FGFS if required.
82 * Some changes (especially those in aircraft position) require that
83 * FGFS be reinitialized afterwards. Rather than reinitialize after
84 * every change, the setter methods simply set a flag so that there
85 * can be a single reinit at the end of the frame.
97 * Reinitialize FGFS to use the new BFI settings.
102 // Save the state of everything
103 // that's going to get clobbered
104 // when we reinit the subsystems.
106 cout << "BFI: start reinit\n";
108 setHeading(getHeading());
109 setPitch(getPitch());
111 setSpeedNorth(getSpeedNorth());
112 setSpeedEast(getSpeedEast());
113 setSpeedDown(getSpeedDown());
114 setLatitude(getLatitude());
115 setLongitude(getLongitude());
116 setAltitude(getAltitude());
118 // TODO: add more AP stuff
119 double elevator = getElevator();
120 double aileron = getAileron();
121 double rudder = getRudder();
122 double throttle = getThrottle();
123 double elevator_trim = getElevatorTrim();
124 double flaps = getFlaps();
125 double brake = getBrake();
126 bool apHeadingLock = getAPHeadingLock();
127 double apHeadingMag = getAPHeadingMag();
128 bool apAltitudeLock = getAPAltitudeLock();
129 double apAltitude = getAPAltitude();
130 const string &targetAirport = getTargetAirport();
131 bool gpsLock = getGPSLock();
132 double gpsLatitude = getGPSTargetLatitude();
133 double gpsLongitude = getGPSTargetLongitude();
135 setTargetAirport("");
136 cout << "Target airport is " << current_options.get_airport_id() << endl;
137 fgReInitSubsystems();
139 // FIXME: this is wrong.
140 // All of these are scheduled events,
141 // and it should be possible to force
142 // them all to run once.
145 cur_light_params.Update();
146 FGTime::cur_time_params->updateLocal();
147 fgUpdateWeatherDatabase();
150 // Restore all of the old states.
151 setElevator(elevator);
154 setThrottle(throttle);
155 setElevatorTrim(elevator_trim);
158 setAPHeadingLock(apHeadingLock);
159 setAPHeadingMag(apHeadingMag);
160 setAPAltitudeLock(apAltitudeLock);
161 setAPAltitude(apAltitude);
162 setTargetAirport(targetAirport);
164 setGPSTargetLatitude(gpsLatitude);
165 setGPSTargetLongitude(gpsLongitude);
169 cout << "BFI: end reinit\n";
174 ////////////////////////////////////////////////////////////////////////
176 ////////////////////////////////////////////////////////////////////////
180 * Return the flight model as an integer.
182 * TODO: use a string instead.
185 FGBFI::getFlightModel ()
187 return current_options.get_flight_model();
192 * Return the current aircraft as a string.
195 FGBFI::getAircraft ()
197 return current_options.get_aircraft();
202 * Return the current aircraft directory (UIUC) as a string.
205 FGBFI::getAircraftDir ()
212 * Set the flight model as an integer.
214 * TODO: use a string instead.
217 FGBFI::setFlightModel (int model)
219 current_options.set_flight_model(model);
225 * Set the current aircraft.
228 FGBFI::setAircraft (const string &aircraft)
230 current_options.set_aircraft(aircraft);
236 * Set the current aircraft directory (UIUC).
239 FGBFI::setAircraftDir (const string &dir)
247 * Return the current Zulu time.
252 // FIXME: inefficient
253 return mktime(FGTime::cur_time_params->getGmt());
258 * Set the current Zulu time.
261 FGBFI::setTimeGMT (time_t time)
263 // FIXME: need to update lighting
265 current_options.set_time_offset(time);
266 current_options.set_time_offset_type(fgOPTIONS::FG_TIME_GMT_ABSOLUTE);
267 FGTime::cur_time_params->init( cur_fdm_state->get_Longitude(),
268 cur_fdm_state->get_Latitude() );
269 FGTime::cur_time_params->update( cur_fdm_state->get_Longitude(),
270 cur_fdm_state->get_Latitude(),
271 cur_fdm_state->get_Altitude()
278 * Return true if the HUD is visible.
281 FGBFI::getHUDVisible ()
283 return current_options.get_hud_status();
288 * Ensure that the HUD is visible or hidden.
291 FGBFI::setHUDVisible (bool visible)
293 current_options.set_hud_status(visible);
298 * Return true if the 2D panel is visible.
301 FGBFI::getPanelVisible ()
303 return current_options.get_panel_status();
308 * Ensure that the 2D panel is visible or hidden.
311 FGBFI::setPanelVisible (bool visible)
313 if (current_options.get_panel_status() != visible) {
314 current_options.toggle_panel();
320 ////////////////////////////////////////////////////////////////////////
322 ////////////////////////////////////////////////////////////////////////
326 * Return the current latitude in degrees (negative for south).
329 FGBFI::getLatitude ()
331 return current_aircraft.fdm_state->get_Latitude() * RAD_TO_DEG;
336 * Set the current latitude in degrees (negative for south).
339 FGBFI::setLatitude (double latitude)
341 current_options.set_lat(latitude);
342 current_aircraft.fdm_state->set_Latitude(latitude * DEG_TO_RAD);
348 * Return the current longitude in degrees (negative for west).
351 FGBFI::getLongitude ()
353 return current_aircraft.fdm_state->get_Longitude() * RAD_TO_DEG;
358 * Set the current longitude in degrees (negative for west).
361 FGBFI::setLongitude (double longitude)
363 current_options.set_lon(longitude);
364 current_aircraft.fdm_state->set_Longitude(longitude * DEG_TO_RAD);
370 * Return the current altitude in feet.
373 FGBFI::getAltitude ()
375 return current_aircraft.fdm_state->get_Altitude();
381 * Return the current altitude in above the terrain.
386 return current_aircraft.fdm_state->get_Altitude()
387 - scenery.cur_elev * METER_TO_FEET;
392 * Set the current altitude in feet.
395 FGBFI::setAltitude (double altitude)
397 current_options.set_altitude(altitude * FEET_TO_METER);
398 current_aircraft.fdm_state->set_Altitude(altitude);
404 ////////////////////////////////////////////////////////////////////////
406 ////////////////////////////////////////////////////////////////////////
410 * Return the current heading in degrees.
415 return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG;
420 * Return the current heading in degrees.
423 FGBFI::getHeadingMag ()
425 return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG - getMagVar();
430 * Set the current heading in degrees.
433 FGBFI::setHeading (double heading)
435 current_options.set_heading(heading);
436 current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
437 getPitch() * DEG_TO_RAD,
438 heading * DEG_TO_RAD);
444 * Return the current pitch in degrees.
449 return current_aircraft.fdm_state->get_Theta() * RAD_TO_DEG;
454 * Set the current pitch in degrees.
457 FGBFI::setPitch (double pitch)
460 current_options.set_pitch(pitch);
461 current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
463 getHeading() * DEG_TO_RAD);
469 * Return the current roll in degrees.
474 return current_aircraft.fdm_state->get_Phi() * RAD_TO_DEG;
479 * Set the current roll in degrees.
482 FGBFI::setRoll (double roll)
484 current_options.set_roll(roll);
485 current_aircraft.fdm_state->set_Euler_Angles(roll * DEG_TO_RAD,
486 getPitch() * DEG_TO_RAD,
487 getHeading() * DEG_TO_RAD);
493 ////////////////////////////////////////////////////////////////////////
495 ////////////////////////////////////////////////////////////////////////
499 * Return the current airspeed in knots.
502 FGBFI::getAirspeed ()
504 // FIXME: should we add speed-up?
505 return current_aircraft.fdm_state->get_V_calibrated_kts();
510 * Return the current sideslip (FIXME: units unknown).
513 FGBFI::getSideSlip ()
515 return current_aircraft.fdm_state->get_Beta();
520 * Return the current climb rate in feet/minute
523 FGBFI::getVerticalSpeed ()
525 // What about meters?
526 return current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
531 * Get the current north velocity (units??).
534 FGBFI::getSpeedNorth ()
536 return current_aircraft.fdm_state->get_V_north();
541 * Set the current north velocity (units??).
544 FGBFI::setSpeedNorth (double speed)
546 current_options.set_uBody(speed);
547 current_aircraft.fdm_state->set_Velocities_Local(speed,
555 * Get the current east velocity (units??).
558 FGBFI::getSpeedEast ()
560 return current_aircraft.fdm_state->get_V_east();
565 * Set the current east velocity (units??).
568 FGBFI::setSpeedEast (double speed)
570 current_options.set_vBody(speed);
571 current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
579 * Get the current down velocity (units??).
582 FGBFI::getSpeedDown ()
584 return current_aircraft.fdm_state->get_V_down();
589 * Set the current down velocity (units??).
592 FGBFI::setSpeedDown (double speed)
594 current_options.set_wBody(speed);
595 current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
603 ////////////////////////////////////////////////////////////////////////
605 ////////////////////////////////////////////////////////////////////////
609 * Get the throttle setting, from 0.0 (none) to 1.0 (full).
612 FGBFI::getThrottle ()
614 // FIXME: add throttle selector
615 return controls.get_throttle(0);
620 * Set the throttle, from 0.0 (none) to 1.0 (full).
623 FGBFI::setThrottle (double throttle)
625 // FIXME: allow throttle selection
627 controls.set_throttle(0, throttle);
632 * Get the flaps setting, from 0.0 (none) to 1.0 (full).
637 return controls.get_flaps();
642 * Set the flaps, from 0.0 (none) to 1.0 (full).
645 FGBFI::setFlaps (double flaps)
648 controls.set_flaps(flaps);
653 * Get the aileron, from -1.0 (left) to 1.0 (right).
658 return controls.get_aileron();
663 * Set the aileron, from -1.0 (left) to 1.0 (right).
666 FGBFI::setAileron (double aileron)
669 controls.set_aileron(aileron);
674 * Get the rudder setting, from -1.0 (left) to 1.0 (right).
679 return controls.get_rudder();
684 * Set the rudder, from -1.0 (left) to 1.0 (right).
687 FGBFI::setRudder (double rudder)
690 controls.set_rudder(rudder);
695 * Get the elevator setting, from -1.0 (down) to 1.0 (up).
698 FGBFI::getElevator ()
700 return controls.get_elevator();
705 * Set the elevator, from -1.0 (down) to 1.0 (up).
708 FGBFI::setElevator (double elevator)
711 controls.set_elevator(elevator);
716 * Get the elevator trim, from -1.0 (down) to 1.0 (up).
719 FGBFI::getElevatorTrim ()
721 return controls.get_elevator_trim();
726 * Set the elevator trim, from -1.0 (down) to 1.0 (up).
729 FGBFI::setElevatorTrim (double trim)
732 controls.set_elevator_trim(trim);
737 * Get the brake setting, from 0.0 (none) to 1.0 (full).
742 // FIXME: add brake selector
743 return controls.get_brake(0);
748 * Set the brake, from 0.0 (none) to 1.0 (full).
751 FGBFI::setBrake (double brake)
754 // FIXME: allow brake selection
755 controls.set_brake(0, brake);
760 ////////////////////////////////////////////////////////////////////////
762 ////////////////////////////////////////////////////////////////////////
766 * Get the autopilot altitude lock (true=on).
769 FGBFI::getAPAltitudeLock ()
771 return current_autopilot->get_AltitudeEnabled();
776 * Set the autopilot altitude lock (true=on).
779 FGBFI::setAPAltitudeLock (bool lock)
781 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
782 current_autopilot->set_AltitudeEnabled(lock);
787 * Get the autopilot target altitude in feet.
790 FGBFI::getAPAltitude ()
792 return current_autopilot->get_TargetAltitude() * METER_TO_FEET;
797 * Set the autopilot target altitude in feet.
800 FGBFI::setAPAltitude (double altitude)
802 current_autopilot->set_TargetAltitude( altitude );
807 * Get the autopilot heading lock (true=on).
810 FGBFI::getAPHeadingLock ()
813 (current_autopilot->get_HeadingEnabled() &&
814 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_LOCK);
819 * Set the autopilot heading lock (true=on).
822 FGBFI::setAPHeadingLock (bool lock)
825 // We need to do this so that
826 // it's possible to lock onto a
827 // heading other than the current
829 double heading = getAPHeadingMag();
830 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_LOCK);
831 current_autopilot->set_HeadingEnabled(true);
832 setAPHeadingMag(heading);
833 } else if (current_autopilot->get_HeadingMode() ==
834 FGAutopilot::FG_HEADING_LOCK) {
835 current_autopilot->set_HeadingEnabled(false);
841 * Get the autopilot target heading in degrees.
844 FGBFI::getAPHeadingMag ()
846 return current_autopilot->get_TargetHeading() - getMagVar();
851 * Set the autopilot target heading in degrees.
854 FGBFI::setAPHeadingMag (double heading)
856 current_autopilot->set_TargetHeading( heading + getMagVar() );
861 * Return true if the autopilot is locked to NAV1.
864 FGBFI::getAPNAV1Lock ()
867 (current_autopilot->get_HeadingEnabled() &&
868 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
873 * Set the autopilot NAV1 lock.
876 FGBFI::setAPNAV1Lock (bool lock)
879 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
880 current_autopilot->set_HeadingEnabled(true);
881 } else if (current_autopilot->get_HeadingMode() ==
882 FGAutopilot::FG_HEADING_NAV1) {
883 current_autopilot->set_HeadingEnabled(false);
889 ////////////////////////////////////////////////////////////////////////
891 ////////////////////////////////////////////////////////////////////////
894 FGBFI::getNAV1Freq ()
896 return current_radiostack->get_nav1_freq();
900 FGBFI::getNAV1AltFreq ()
902 return current_radiostack->get_nav1_alt_freq();
906 FGBFI::getNAV1Radial ()
908 return current_radiostack->get_nav1_radial();
912 FGBFI::getNAV1SelRadial ()
914 return current_radiostack->get_nav1_sel_radial();
918 FGBFI::getNAV1DistDME ()
920 return current_radiostack->get_nav1_dme_dist();
924 FGBFI::getNAV1InRange ()
926 return current_radiostack->get_nav1_inrange();
930 FGBFI::getNAV1DMEInRange ()
932 return (current_radiostack->get_nav1_inrange() &&
933 current_radiostack->get_nav1_has_dme());
937 FGBFI::getNAV2Freq ()
939 return current_radiostack->get_nav2_freq();
943 FGBFI::getNAV2AltFreq ()
945 return current_radiostack->get_nav2_alt_freq();
949 FGBFI::getNAV2Radial ()
951 return current_radiostack->get_nav2_radial();
955 FGBFI::getNAV2SelRadial ()
957 return current_radiostack->get_nav2_sel_radial();
961 FGBFI::getNAV2DistDME ()
963 return current_radiostack->get_nav2_dme_dist();
967 FGBFI::getNAV2InRange ()
969 return current_radiostack->get_nav2_inrange();
973 FGBFI::getNAV2DMEInRange ()
975 return (current_radiostack->get_nav2_inrange() &&
976 current_radiostack->get_nav2_has_dme());
982 return current_radiostack->get_adf_freq();
986 FGBFI::getADFAltFreq ()
988 return current_radiostack->get_adf_alt_freq();
992 FGBFI::getADFRotation ()
994 return current_radiostack->get_adf_rotation();
998 FGBFI::setNAV1Freq (double freq)
1000 current_radiostack->set_nav1_freq(freq);
1004 FGBFI::setNAV1AltFreq (double freq)
1006 current_radiostack->set_nav1_alt_freq(freq);
1010 FGBFI::setNAV1SelRadial (double radial)
1012 current_radiostack->set_nav1_sel_radial(radial);
1016 FGBFI::setNAV2Freq (double freq)
1018 current_radiostack->set_nav2_freq(freq);
1022 FGBFI::setNAV2AltFreq (double freq)
1024 current_radiostack->set_nav2_alt_freq(freq);
1028 FGBFI::setNAV2SelRadial (double radial)
1030 current_radiostack->set_nav2_sel_radial(radial);
1034 FGBFI::setADFFreq (double freq)
1036 current_radiostack->set_adf_freq(freq);
1040 FGBFI::setADFAltFreq (double freq)
1042 current_radiostack->set_adf_alt_freq(freq);
1046 FGBFI::setADFRotation (double rot)
1048 current_radiostack->set_adf_rotation(rot);
1053 ////////////////////////////////////////////////////////////////////////
1055 ////////////////////////////////////////////////////////////////////////
1059 * Get the autopilot GPS lock (true=on).
1062 FGBFI::getGPSLock ()
1064 return (current_autopilot->get_HeadingEnabled() &&
1065 (current_autopilot->get_HeadingMode() ==
1066 FGAutopilot::FG_HEADING_WAYPOINT ));
1071 * Set the autopilot GPS lock (true=on).
1074 FGBFI::setGPSLock (bool lock)
1077 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_WAYPOINT);
1078 current_autopilot->set_HeadingEnabled(true);
1079 } else if (current_autopilot->get_HeadingMode() ==
1080 FGAutopilot::FG_HEADING_WAYPOINT) {
1081 current_autopilot->set_HeadingEnabled(false);
1087 * Get the GPS target airport code.
1090 FGBFI::getTargetAirport ()
1092 return current_options.get_airport_id();
1097 * Set the GPS target airport code.
1100 FGBFI::setTargetAirport (const string &airportId)
1102 current_options.set_airport_id(airportId);
1107 * Get the GPS target latitude in degrees (negative for south).
1110 FGBFI::getGPSTargetLatitude ()
1112 return current_autopilot->get_TargetLatitude();
1117 * Set the GPS target latitude in degrees (negative for south).
1120 FGBFI::setGPSTargetLatitude (double latitude)
1122 current_autopilot->set_TargetLatitude( latitude );
1127 * Get the GPS target longitude in degrees (negative for west).
1130 FGBFI::getGPSTargetLongitude ()
1132 return current_autopilot->get_TargetLongitude();
1137 * Set the GPS target longitude in degrees (negative for west).
1140 FGBFI::setGPSTargetLongitude (double longitude)
1142 current_autopilot->set_TargetLongitude( longitude );
1147 ////////////////////////////////////////////////////////////////////////
1149 ////////////////////////////////////////////////////////////////////////
1153 * Get the current visible (units??).
1156 FGBFI::getVisibility ()
1158 #ifndef FG_OLD_WEATHER
1159 return WeatherDatabase->getWeatherVisibility();
1161 return current_weather.get_visibility();
1167 * Check whether clouds are enabled.
1172 return current_options.get_clouds();
1177 * Check the height of the clouds ASL (units?).
1180 FGBFI::getCloudsASL ()
1182 return current_options.get_clouds_asl();
1187 * Set the current visibility (units??).
1190 FGBFI::setVisibility (double visibility)
1192 #ifndef FG_OLD_WEATHER
1193 WeatherDatabase->setWeatherVisibility(visibility);
1195 current_weather.set_visibility(visibility);
1201 * Switch clouds on or off.
1204 FGBFI::setClouds (bool clouds)
1206 cout << "Set clouds to " << clouds << endl;
1207 current_options.set_clouds(clouds);
1213 * Set the cloud height.
1216 FGBFI::setCloudsASL (double cloudsASL)
1218 current_options.set_clouds_asl(cloudsASL);
1224 ////////////////////////////////////////////////////////////////////////
1226 ////////////////////////////////////////////////////////////////////////
1229 * Return the magnetic variation
1234 return FGTime::cur_time_params->getMagVar() * RAD_TO_DEG;
1239 * Return the magnetic variation
1244 return FGTime::cur_time_params->getMagDip() * RAD_TO_DEG;