7cc98ad15f
LaRCsim c172 on-ground and in-air starts, reset: all work UIUC Cessna172 on-ground and in-air starts work as expected, reset results in an aircraft that is upside down but does not crash FG. I don't know what it was like before, so it may well be no change. JSBSim c172 and X15 in-air starts work fine, resets now work (and are trimmed), on-ground starts do not -- the c172 ends up on its back. I suspect this is no worse than before. I did not test: Balloon (the weather code returns nan's for the atmosphere data --this is in the weather module and apparently is a linux only bug) ADA (don't know how) MagicCarpet (needs work yet) External (don't know how) known to be broken: LaRCsim c172 on-ground starts with a negative terrain altitude (this happens at KPAO when the scenery is not present). The FDM inits to about 50 feet AGL and the model falls to the ground. It does stay upright, however, and seems to be fine once it settles out, FWIW. To do: --implement set_Model on the bus --bring Christian's weather data into JSBSim -- add default method to bus for updating things like the sin and cos of latitude (for Balloon, MagicCarpet) -- lots of cleanup The files: src/FDM/flight.cxx src/FDM/flight.hxx -- all data members now declared protected instead of private. -- eliminated all but a small set of 'setters', no change to getters. -- that small set is declared virtual, the default implementation provided preserves the old behavior -- all of the vector data members are now initialized. -- added busdump() method -- FG_LOG's all the bus data when called, useful for diagnostics. src/FDM/ADA.cxx -- bus data members now directly assigned to src/FDM/Balloon.cxx -- bus data members now directly assigned to -- changed V_equiv_kts to V_calibrated_kts src/FDM/JSBSim.cxx src/FDM/JSBSim.hxx -- bus data members now directly assigned to -- implemented the FGInterface virtual setters with JSBSim specific logic -- changed the static FDMExec to a dynamic fdmex (needed so that the JSBSim object can be deleted when a model change is called for) -- implemented constructor and destructor, moved some of the logic formerly in init() to constructor -- added logic to bring up FGEngInterface objects and set the RPM and throttle values. src/FDM/LaRCsim.cxx src/FDM/LaRCsim.hxx -- bus data members now directly assigned to -- implemented the FGInterface virtual setters with LaRCsim specific logic, uses LaRCsimIC -- implemented constructor and destructor, moved some of the logic formerly in init() to constructor -- moved default inertias to here from fg_init.cxx -- eliminated the climb rate calculation. The equivalent, climb_rate = -1*vdown, is now in copy_from_LaRCsim(). src/FDM/LaRCsimIC.cxx src/FDM/LaRCsimIC.hxx -- similar to FGInitialCondition, this class has all the logic needed to turn data like Vc and Mach into the more fundamental quantities LaRCsim needs to initialize. -- put it in src/FDM since it is a class src/FDM/MagicCarpet.cxx -- bus data members now directly assigned to src/FDM/Makefile.am -- adds LaRCsimIC.hxx and cxx src/FDM/JSBSim/FGAtmosphere.h src/FDM/JSBSim/FGDefs.h src/FDM/JSBSim/FGInitialCondition.cpp src/FDM/JSBSim/FGInitialCondition.h src/FDM/JSBSim/JSBSim.cpp -- changes to accomodate the new bus src/FDM/LaRCsim/atmos_62.h src/FDM/LaRCsim/ls_geodesy.h -- surrounded prototypes with #ifdef __cplusplus ... #endif , functions here are needed in LaRCsimIC src/FDM/LaRCsim/c172_main.c src/FDM/LaRCsim/cherokee_aero.c src/FDM/LaRCsim/ls_aux.c src/FDM/LaRCsim/ls_constants.h src/FDM/LaRCsim/ls_geodesy.c src/FDM/LaRCsim/ls_geodesy.h src/FDM/LaRCsim/ls_step.c src/FDM/UIUCModel/uiuc_betaprobe.cpp -- changed PI to LS_PI, eliminates preprocessor naming conflict with weather module src/FDM/LaRCsim/ls_interface.c src/FDM/LaRCsim/ls_interface.h -- added function ls_set_model_dt() src/Main/bfi.cxx -- eliminated calls that set the NED speeds to body components. They are no longer needed and confuse the new bus. src/Main/fg_init.cxx -- eliminated calls that just brought the bus data up-to-date (e.g. set_sin_cos_latitude). or set default values. The bus now handles the defaults and updates itself when the setters are called (for LaRCsim and JSBSim). A default method for doing this needs to be added to the bus. -- added fgVelocityInit() to set the speed the user asked for. Both JSBSim and LaRCsim can now be initialized using any of: vc,mach, NED components, UVW components. src/Main/main.cxx --eliminated call to fgFDMSetGroundElevation, this data is now 'pulled' onto the bus every update() src/Main/options.cxx src/Main/options.hxx -- added enum to keep track of the speed requested by the user -- eliminated calls to set NED velocity properties to body speeds, they are no longer needed. -- added options for the NED components. src/Network/garmin.cxx src/Network/nmea.cxx --eliminated calls that just brought the bus data up-to-date (e.g. set_sin_cos_latitude). The bus now updates itself when the setters are called (for LaRCsim and JSBSim). A default method for doing this needs to be added to the bus. -- changed set_V_equiv_kts to set_V_calibrated_kts. set_V_equiv_kts no longer exists ( get_V_equiv_kts still does, though) src/WeatherCM/FGLocalWeatherDatabase.cpp -- commented out the code to put the weather data on the bus, a different scheme for this is needed.
1684 lines
34 KiB
C++
1684 lines
34 KiB
C++
// bfi.cxx - Big Friendly Interface implementation
|
||
//
|
||
// Written by David Megginson, started February, 2000.
|
||
//
|
||
// Copyright (C) 2000 David Megginson - david@megginson.com
|
||
//
|
||
// This program is free software; you can redistribute it and/or
|
||
// modify it under the terms of the GNU General Public License as
|
||
// published by the Free Software Foundation; either version 2 of the
|
||
// License, or (at your option) any later version.
|
||
//
|
||
// This program is distributed in the hope that it will be useful, but
|
||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
// General Public License for more details.
|
||
//
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program; if not, write to the Free Software
|
||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
//
|
||
// $Id$
|
||
|
||
|
||
#ifdef HAVE_CONFIG_H
|
||
# include <config.h>
|
||
#endif
|
||
|
||
#if defined( FG_HAVE_NATIVE_SGI_COMPILERS )
|
||
# include <iostream.h>
|
||
#else
|
||
# include <iostream>
|
||
#endif
|
||
|
||
#include <simgear/constants.h>
|
||
#include <simgear/debug/logstream.hxx>
|
||
#include <simgear/ephemeris/ephemeris.hxx>
|
||
#include <simgear/math/sg_types.hxx>
|
||
#include <simgear/misc/props.hxx>
|
||
#include <simgear/timing/sg_time.hxx>
|
||
|
||
#include <Aircraft/aircraft.hxx>
|
||
#include <FDM/UIUCModel/uiuc_aircraftdir.h>
|
||
#include <Controls/controls.hxx>
|
||
#include <Autopilot/newauto.hxx>
|
||
#include <Scenery/scenery.hxx>
|
||
#include <Time/light.hxx>
|
||
#include <Time/event.hxx>
|
||
#include <Time/sunpos.hxx>
|
||
#include <Time/tmp.hxx>
|
||
#include <Cockpit/radiostack.hxx>
|
||
#ifndef FG_OLD_WEATHER
|
||
# include <WeatherCM/FGLocalWeatherDatabase.h>
|
||
#else
|
||
# include <Weather/weather.hxx>
|
||
#endif
|
||
|
||
#include "globals.hxx"
|
||
#include "save.hxx"
|
||
#include "fg_init.hxx"
|
||
#include <simgear/misc/props.hxx>
|
||
|
||
FG_USING_NAMESPACE(std);
|
||
|
||
|
||
#include "bfi.hxx"
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Static variables.
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
bool FGBFI::_needReinit = false;
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Local functions
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Initialize the BFI by binding its functions to properties.
|
||
*
|
||
* TODO: perhaps these should migrate into the individual modules
|
||
* (i.e. they should register themselves).
|
||
*/
|
||
void
|
||
FGBFI::init ()
|
||
{
|
||
FG_LOG(FG_GENERAL, FG_INFO, "Starting BFI init");
|
||
// Simulation
|
||
current_properties.tieInt("/sim/flight-model",
|
||
getFlightModel, setFlightModel);
|
||
// current_properties.tieString("/sim/aircraft",
|
||
// getAircraft, setAircraft);
|
||
// TODO: timeGMT
|
||
current_properties.tieString("/sim/time/gmt-string",
|
||
getGMTString, 0);
|
||
current_properties.tieBool("/sim/hud/visibility",
|
||
getHUDVisible, setHUDVisible);
|
||
current_properties.tieBool("/sim/panel/visibility",
|
||
getPanelVisible, setPanelVisible);
|
||
|
||
// Position
|
||
current_properties.tieString("/position/airport-id",
|
||
getTargetAirport, setTargetAirport);
|
||
current_properties.tieDouble("/position/latitude",
|
||
getLatitude, setLatitude);
|
||
current_properties.tieDouble("/position/longitude",
|
||
getLongitude, setLongitude);
|
||
current_properties.tieDouble("/position/altitude",
|
||
// getAltitude, setAltitude);
|
||
getAltitude, setAltitude, false);
|
||
current_properties.tieDouble("/position/altitude-agl",
|
||
getAGL, 0);
|
||
|
||
// Orientation
|
||
current_properties.tieDouble("/orientation/heading",
|
||
getHeading, setHeading);
|
||
current_properties.tieDouble("/orientation/heading-magnetic",
|
||
getHeadingMag, 0);
|
||
current_properties.tieDouble("/orientation/pitch",
|
||
getPitch, setPitch);
|
||
current_properties.tieDouble("/orientation/roll",
|
||
getRoll, setRoll);
|
||
|
||
// Engine
|
||
current_properties.tieDouble("/engines/engine0/rpm",
|
||
getRPM, 0);
|
||
current_properties.tieDouble("/engines/engine0/egt",
|
||
getEGT, 0);
|
||
|
||
// Velocities
|
||
current_properties.tieDouble("/velocities/airspeed",
|
||
getAirspeed, 0);
|
||
current_properties.tieDouble("/velocities/side-slip",
|
||
getSideSlip, 0);
|
||
current_properties.tieDouble("/velocities/vertical-speed",
|
||
getVerticalSpeed, 0);
|
||
current_properties.tieDouble("/velocities/speed-north",
|
||
getSpeedNorth, setSpeedNorth);
|
||
current_properties.tieDouble("/velocities/speed-east",
|
||
getSpeedEast, setSpeedEast);
|
||
current_properties.tieDouble("/velocities/speed-down",
|
||
getSpeedDown, setSpeedDown);
|
||
|
||
// Controls
|
||
current_properties.tieDouble("/controls/throttle",
|
||
getThrottle, setThrottle);
|
||
current_properties.tieDouble("/controls/mixture",
|
||
getMixture, setMixture);
|
||
current_properties.tieDouble("/controls/propellor-pitch",
|
||
getPropAdvance, setPropAdvance);
|
||
current_properties.tieDouble("/controls/flaps",
|
||
getFlaps, setFlaps);
|
||
current_properties.tieDouble("/controls/aileron",
|
||
getAileron, setAileron);
|
||
current_properties.tieDouble("/controls/rudder",
|
||
getRudder, setRudder);
|
||
current_properties.tieDouble("/controls/elevator",
|
||
getElevator, setElevator);
|
||
current_properties.tieDouble("/controls/elevator-trim",
|
||
getElevatorTrim, setElevatorTrim);
|
||
current_properties.tieDouble("/controls/brakes/all",
|
||
getBrakes, setBrakes);
|
||
current_properties.tieDouble("/controls/brakes/left",
|
||
getLeftBrake, setLeftBrake);
|
||
current_properties.tieDouble("/controls/brakes/right",
|
||
getRightBrake, setRightBrake);
|
||
current_properties.tieDouble("/controls/brakes/center",
|
||
getRightBrake, setCenterBrake);
|
||
|
||
// Autopilot
|
||
current_properties.tieBool("/autopilot/locks/altitude",
|
||
getAPAltitudeLock, setAPAltitudeLock);
|
||
current_properties.tieDouble("/autopilot/settings/altitude",
|
||
getAPAltitude, setAPAltitude);
|
||
current_properties.tieBool("/autopilot/locks/heading",
|
||
getAPHeadingLock, setAPHeadingLock);
|
||
current_properties.tieDouble("/autopilot/settings/heading",
|
||
getAPHeading, setAPHeading);
|
||
current_properties.tieDouble("/autopilot/settings/heading-magnetic",
|
||
getAPHeadingMag, setAPHeadingMag);
|
||
current_properties.tieBool("/autopilot/locks/nav1",
|
||
getAPNAV1Lock, setAPNAV1Lock);
|
||
|
||
// Radio navigation
|
||
current_properties.tieDouble("/radios/nav1/frequencies/selected",
|
||
getNAV1Freq, setNAV1Freq);
|
||
current_properties.tieDouble("/radios/nav1/frequencies/standby",
|
||
getNAV1AltFreq, setNAV1AltFreq);
|
||
current_properties.tieDouble("/radios/nav1/radials/actual",
|
||
getNAV1Radial, 0);
|
||
current_properties.tieDouble("/radios/nav1/radials/selected",
|
||
getNAV1SelRadial, setNAV1SelRadial);
|
||
current_properties.tieDouble("/radios/nav1/dme/distance",
|
||
getNAV1DistDME, 0);
|
||
current_properties.tieBool("/radios/nav1/to-flag",
|
||
getNAV1TO, 0);
|
||
current_properties.tieBool("/radios/nav1/from-flag",
|
||
getNAV1FROM, 0);
|
||
current_properties.tieBool("/radios/nav1/in-range",
|
||
getNAV1InRange, 0);
|
||
current_properties.tieBool("/radios/nav1/dme/in-range",
|
||
getNAV1DMEInRange, 0);
|
||
|
||
current_properties.tieDouble("/radios/nav2/frequencies/selected",
|
||
getNAV2Freq, setNAV2Freq);
|
||
current_properties.tieDouble("/radios/nav2/frequencies/standby",
|
||
getNAV2AltFreq, setNAV2AltFreq);
|
||
current_properties.tieDouble("/radios/nav2/radials/actual",
|
||
getNAV2Radial, 0);
|
||
current_properties.tieDouble("/radios/nav2/radials/selected",
|
||
getNAV2SelRadial, setNAV2SelRadial);
|
||
current_properties.tieDouble("/radios/nav2/dme/distance",
|
||
getNAV2DistDME, 0);
|
||
current_properties.tieBool("/radios/nav2/to-flag",
|
||
getNAV2TO, 0);
|
||
current_properties.tieBool("/radios/nav2/from-flag",
|
||
getNAV2FROM, 0);
|
||
current_properties.tieBool("/radios/nav2/in-range",
|
||
getNAV2InRange, 0);
|
||
current_properties.tieBool("/radios/nav2/dme/in-range",
|
||
getNAV2DMEInRange, 0);
|
||
|
||
current_properties.tieDouble("/radios/adf/frequencies/selected",
|
||
getADFFreq, setADFFreq);
|
||
current_properties.tieDouble("/radios/adf/frequencies/standby",
|
||
getADFAltFreq, setADFAltFreq);
|
||
current_properties.tieDouble("/radios/adf/rotation",
|
||
getADFRotation, setADFRotation);
|
||
|
||
current_properties.tieDouble("/environment/visibility",
|
||
getVisibility, setVisibility);
|
||
|
||
_needReinit = false;
|
||
|
||
FG_LOG(FG_GENERAL, FG_INFO, "Ending BFI init");
|
||
}
|
||
|
||
|
||
/**
|
||
* Reinitialize FGFS if required.
|
||
*
|
||
* Some changes (especially those in aircraft position) require that
|
||
* FGFS be reinitialized afterwards. Rather than reinitialize after
|
||
* every change, the setter methods simply set a flag so that there
|
||
* can be a single reinit at the end of the frame.
|
||
*/
|
||
void
|
||
FGBFI::update ()
|
||
{
|
||
if (_needReinit) {
|
||
reinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Reinitialize FGFS to use the new BFI settings.
|
||
*/
|
||
void
|
||
FGBFI::reinit ()
|
||
{
|
||
// Save the state of everything
|
||
// that's going to get clobbered
|
||
// when we reinit the subsystems.
|
||
|
||
cout << "BFI: start reinit\n";
|
||
|
||
// TODO: add more AP stuff
|
||
double elevator = getElevator();
|
||
double aileron = getAileron();
|
||
double rudder = getRudder();
|
||
double throttle = getThrottle();
|
||
double elevator_trim = getElevatorTrim();
|
||
double flaps = getFlaps();
|
||
double brake = getBrakes();
|
||
bool apHeadingLock = getAPHeadingLock();
|
||
double apHeadingMag = getAPHeadingMag();
|
||
bool apAltitudeLock = getAPAltitudeLock();
|
||
double apAltitude = getAPAltitude();
|
||
const string &targetAirport = getTargetAirport();
|
||
bool gpsLock = getGPSLock();
|
||
double gpsLatitude = getGPSTargetLatitude();
|
||
double gpsLongitude = getGPSTargetLongitude();
|
||
|
||
setTargetAirport("");
|
||
cout << "Target airport is " << globals->get_options()->get_airport_id() << endl;
|
||
|
||
fgReInitSubsystems();
|
||
|
||
// FIXME: this is wrong.
|
||
// All of these are scheduled events,
|
||
// and it should be possible to force
|
||
// them all to run once.
|
||
fgUpdateSunPos();
|
||
fgUpdateMoonPos();
|
||
cur_light_params.Update();
|
||
fgUpdateLocalTime();
|
||
fgUpdateWeatherDatabase();
|
||
fgRadioSearch();
|
||
|
||
// Restore all of the old states.
|
||
setElevator(elevator);
|
||
setAileron(aileron);
|
||
setRudder(rudder);
|
||
setThrottle(throttle);
|
||
setElevatorTrim(elevator_trim);
|
||
setFlaps(flaps);
|
||
setBrakes(brake);
|
||
setAPHeadingLock(apHeadingLock);
|
||
setAPHeadingMag(apHeadingMag);
|
||
setAPAltitudeLock(apAltitudeLock);
|
||
setAPAltitude(apAltitude);
|
||
setTargetAirport(targetAirport);
|
||
setGPSLock(gpsLock);
|
||
|
||
_needReinit = false;
|
||
|
||
cout << "BFI: end reinit\n";
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Simulation.
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Return the flight model as an integer.
|
||
*
|
||
* TODO: use a string instead.
|
||
*/
|
||
int
|
||
FGBFI::getFlightModel ()
|
||
{
|
||
return globals->get_options()->get_flight_model();
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current aircraft as a string.
|
||
*/
|
||
const string
|
||
FGBFI::getAircraft ()
|
||
{
|
||
return globals->get_options()->get_aircraft();
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current aircraft directory (UIUC) as a string.
|
||
*/
|
||
const string
|
||
FGBFI::getAircraftDir ()
|
||
{
|
||
return aircraft_dir;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the flight model as an integer.
|
||
*
|
||
* TODO: use a string instead.
|
||
*/
|
||
void
|
||
FGBFI::setFlightModel (int model)
|
||
{
|
||
if (getFlightModel() != model) {
|
||
globals->get_options()->set_flight_model(model);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current aircraft.
|
||
*/
|
||
void
|
||
FGBFI::setAircraft (const string &aircraft)
|
||
{
|
||
if (getAircraft() != aircraft) {
|
||
globals->get_options()->set_aircraft(aircraft);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current aircraft directory (UIUC).
|
||
*/
|
||
void
|
||
FGBFI::setAircraftDir (const string &dir)
|
||
{
|
||
if (getAircraftDir() != dir) {
|
||
aircraft_dir = dir;
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current Zulu time.
|
||
*/
|
||
time_t
|
||
FGBFI::getTimeGMT ()
|
||
{
|
||
return globals->get_time_params()->get_cur_time();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current Zulu time.
|
||
*/
|
||
void
|
||
FGBFI::setTimeGMT (time_t time)
|
||
{
|
||
if (getTimeGMT() != time) {
|
||
// FIXME: need to update lighting
|
||
// and solar system
|
||
globals->get_options()->set_time_offset(time);
|
||
globals->get_options()->set_time_offset_type(FGOptions::FG_TIME_GMT_ABSOLUTE);
|
||
globals->get_time_params()->update( cur_fdm_state->get_Longitude(),
|
||
cur_fdm_state->get_Latitude(),
|
||
globals->get_warp() );
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the GMT as a string.
|
||
*/
|
||
const string &
|
||
FGBFI::getGMTString ()
|
||
{
|
||
static string out; // FIXME: not thread-safe
|
||
char buf[16];
|
||
struct tm * t = globals->get_time_params()->getGmt();
|
||
sprintf(buf, " %.2d:%.2d:%.2d",
|
||
t->tm_hour, t->tm_min, t->tm_sec);
|
||
out = buf;
|
||
return out;
|
||
}
|
||
|
||
|
||
/**
|
||
* Return true if the HUD is visible.
|
||
*/
|
||
bool
|
||
FGBFI::getHUDVisible ()
|
||
{
|
||
return globals->get_options()->get_hud_status();
|
||
}
|
||
|
||
|
||
/**
|
||
* Ensure that the HUD is visible or hidden.
|
||
*/
|
||
void
|
||
FGBFI::setHUDVisible (bool visible)
|
||
{
|
||
globals->get_options()->set_hud_status(visible);
|
||
}
|
||
|
||
|
||
/**
|
||
* Return true if the 2D panel is visible.
|
||
*/
|
||
bool
|
||
FGBFI::getPanelVisible ()
|
||
{
|
||
return globals->get_options()->get_panel_status();
|
||
}
|
||
|
||
|
||
/**
|
||
* Ensure that the 2D panel is visible or hidden.
|
||
*/
|
||
void
|
||
FGBFI::setPanelVisible (bool visible)
|
||
{
|
||
if (globals->get_options()->get_panel_status() != visible) {
|
||
globals->get_options()->toggle_panel();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Position
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Return the current latitude in degrees (negative for south).
|
||
*/
|
||
double
|
||
FGBFI::getLatitude ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Latitude() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current latitude in degrees (negative for south).
|
||
*/
|
||
void
|
||
FGBFI::setLatitude (double latitude)
|
||
{
|
||
if (getLatitude() != latitude) {
|
||
globals->get_options()->set_lat(latitude);
|
||
current_aircraft.fdm_state->set_Latitude(latitude * DEG_TO_RAD);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current longitude in degrees (negative for west).
|
||
*/
|
||
double
|
||
FGBFI::getLongitude ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Longitude() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current longitude in degrees (negative for west).
|
||
*/
|
||
void
|
||
FGBFI::setLongitude (double longitude)
|
||
{
|
||
if (getLongitude() != longitude) {
|
||
globals->get_options()->set_lon(longitude);
|
||
current_aircraft.fdm_state->set_Longitude(longitude * DEG_TO_RAD);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current altitude in feet.
|
||
*/
|
||
double
|
||
FGBFI::getAltitude ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Altitude();
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* Return the current altitude in above the terrain.
|
||
*/
|
||
double
|
||
FGBFI::getAGL ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Altitude()
|
||
- (scenery.cur_elev * METER_TO_FEET);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current altitude in feet.
|
||
*/
|
||
void
|
||
FGBFI::setAltitude (double altitude)
|
||
{
|
||
if (getAltitude() != altitude) {
|
||
fgFDMForceAltitude(getFlightModel(), altitude);
|
||
globals->get_options()->set_altitude(altitude);
|
||
current_aircraft.fdm_state->set_Altitude(altitude);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Attitude
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Return the current heading in degrees.
|
||
*/
|
||
double
|
||
FGBFI::getHeading ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current heading in degrees.
|
||
*/
|
||
double
|
||
FGBFI::getHeadingMag ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Psi() * RAD_TO_DEG - getMagVar();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current heading in degrees.
|
||
*/
|
||
void
|
||
FGBFI::setHeading (double heading)
|
||
{
|
||
if (getHeading() != heading) {
|
||
globals->get_options()->set_heading(heading);
|
||
current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
|
||
getPitch() * DEG_TO_RAD,
|
||
heading * DEG_TO_RAD);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current pitch in degrees.
|
||
*/
|
||
double
|
||
FGBFI::getPitch ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Theta() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current pitch in degrees.
|
||
*/
|
||
void
|
||
FGBFI::setPitch (double pitch)
|
||
{
|
||
if (getPitch() != pitch) {
|
||
globals->get_options()->set_pitch(pitch);
|
||
current_aircraft.fdm_state->set_Euler_Angles(getRoll() * DEG_TO_RAD,
|
||
pitch * DEG_TO_RAD,
|
||
getHeading() * DEG_TO_RAD);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current roll in degrees.
|
||
*/
|
||
double
|
||
FGBFI::getRoll ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Phi() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current roll in degrees.
|
||
*/
|
||
void
|
||
FGBFI::setRoll (double roll)
|
||
{
|
||
if (getRoll() != roll) {
|
||
globals->get_options()->set_roll(roll);
|
||
current_aircraft.fdm_state->set_Euler_Angles(roll * DEG_TO_RAD,
|
||
getPitch() * DEG_TO_RAD,
|
||
getHeading() * DEG_TO_RAD);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current engine0 rpm
|
||
*/
|
||
double
|
||
FGBFI::getRPM ()
|
||
{
|
||
if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
|
||
return current_aircraft.fdm_state->get_engine(0)->get_RPM();
|
||
} else {
|
||
return 0.0;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current engine0 rpm
|
||
*/
|
||
void
|
||
FGBFI::setRPM (double rpm)
|
||
{
|
||
if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
|
||
if (getRPM() != rpm) {
|
||
current_aircraft.fdm_state->get_engine(0)->set_RPM( rpm );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current engine0 EGT.
|
||
*/
|
||
double
|
||
FGBFI::getEGT ()
|
||
{
|
||
if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
|
||
return current_aircraft.fdm_state->get_engine(0)->get_EGT();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Velocities
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Return the current airspeed in knots.
|
||
*/
|
||
double
|
||
FGBFI::getAirspeed ()
|
||
{
|
||
// FIXME: should we add speed-up?
|
||
return current_aircraft.fdm_state->get_V_calibrated_kts();
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current sideslip (FIXME: units unknown).
|
||
*/
|
||
double
|
||
FGBFI::getSideSlip ()
|
||
{
|
||
return current_aircraft.fdm_state->get_Beta();
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the current climb rate in feet/minute
|
||
*/
|
||
double
|
||
FGBFI::getVerticalSpeed ()
|
||
{
|
||
// What about meters?
|
||
return current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the current north velocity (units??).
|
||
*/
|
||
double
|
||
FGBFI::getSpeedNorth ()
|
||
{
|
||
return current_aircraft.fdm_state->get_V_north();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current north velocity (units??).
|
||
*/
|
||
void
|
||
FGBFI::setSpeedNorth (double speed)
|
||
{
|
||
if (getSpeedNorth() != speed) {
|
||
current_aircraft.fdm_state->set_Velocities_Local(speed,
|
||
getSpeedEast(),
|
||
getSpeedDown());
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the current east velocity (units??).
|
||
*/
|
||
double
|
||
FGBFI::getSpeedEast ()
|
||
{
|
||
return current_aircraft.fdm_state->get_V_east();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current east velocity (units??).
|
||
*/
|
||
void
|
||
FGBFI::setSpeedEast (double speed)
|
||
{
|
||
if (getSpeedEast() != speed) {
|
||
current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
|
||
speed,
|
||
getSpeedDown());
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the current down velocity (units??).
|
||
*/
|
||
double
|
||
FGBFI::getSpeedDown ()
|
||
{
|
||
return current_aircraft.fdm_state->get_V_down();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current down velocity (units??).
|
||
*/
|
||
void
|
||
FGBFI::setSpeedDown (double speed)
|
||
{
|
||
if (getSpeedDown() != speed) {
|
||
current_aircraft.fdm_state->set_Velocities_Local(getSpeedNorth(),
|
||
getSpeedEast(),
|
||
speed);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Controls
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Get the throttle setting, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getThrottle ()
|
||
{
|
||
// FIXME: add engine selector
|
||
return controls.get_throttle(0);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the throttle, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setThrottle (double throttle)
|
||
{
|
||
// FIXME: allow engine selection
|
||
controls.set_throttle(0, throttle);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the fuel mixture setting, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getMixture ()
|
||
{
|
||
// FIXME: add engine selector
|
||
return controls.get_mixture(0);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the fuel mixture, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setMixture (double mixture)
|
||
{
|
||
// FIXME: allow engine selection
|
||
controls.set_mixture(0, mixture);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the propellor pitch setting, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getPropAdvance ()
|
||
{
|
||
// FIXME: add engine selector
|
||
return controls.get_prop_advance(0);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the propellor pitch, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setPropAdvance (double pitch)
|
||
{
|
||
// FIXME: allow engine selection
|
||
controls.set_prop_advance(0, pitch);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the flaps setting, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getFlaps ()
|
||
{
|
||
return controls.get_flaps();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the flaps, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setFlaps (double flaps)
|
||
{
|
||
// FIXME: clamp?
|
||
controls.set_flaps(flaps);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the aileron, from -1.0 (left) to 1.0 (right).
|
||
*/
|
||
double
|
||
FGBFI::getAileron ()
|
||
{
|
||
return controls.get_aileron();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the aileron, from -1.0 (left) to 1.0 (right).
|
||
*/
|
||
void
|
||
FGBFI::setAileron (double aileron)
|
||
{
|
||
// FIXME: clamp?
|
||
controls.set_aileron(aileron);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the rudder setting, from -1.0 (left) to 1.0 (right).
|
||
*/
|
||
double
|
||
FGBFI::getRudder ()
|
||
{
|
||
return controls.get_rudder();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the rudder, from -1.0 (left) to 1.0 (right).
|
||
*/
|
||
void
|
||
FGBFI::setRudder (double rudder)
|
||
{
|
||
// FIXME: clamp?
|
||
controls.set_rudder(rudder);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the elevator setting, from -1.0 (down) to 1.0 (up).
|
||
*/
|
||
double
|
||
FGBFI::getElevator ()
|
||
{
|
||
return controls.get_elevator();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the elevator, from -1.0 (down) to 1.0 (up).
|
||
*/
|
||
void
|
||
FGBFI::setElevator (double elevator)
|
||
{
|
||
// FIXME: clamp?
|
||
controls.set_elevator(elevator);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the elevator trim, from -1.0 (down) to 1.0 (up).
|
||
*/
|
||
double
|
||
FGBFI::getElevatorTrim ()
|
||
{
|
||
return controls.get_elevator_trim();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the elevator trim, from -1.0 (down) to 1.0 (up).
|
||
*/
|
||
void
|
||
FGBFI::setElevatorTrim (double trim)
|
||
{
|
||
// FIXME: clamp?
|
||
controls.set_elevator_trim(trim);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the highest brake setting, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getBrakes ()
|
||
{
|
||
double b1 = getCenterBrake();
|
||
double b2 = getLeftBrake();
|
||
double b3 = getRightBrake();
|
||
return (b1 > b2 ? (b1 > b3 ? b1 : b3) : (b2 > b3 ? b2 : b3));
|
||
}
|
||
|
||
|
||
/**
|
||
* Set all brakes, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setBrakes (double brake)
|
||
{
|
||
setCenterBrake(brake);
|
||
setLeftBrake(brake);
|
||
setRightBrake(brake);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the center brake, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getCenterBrake ()
|
||
{
|
||
return controls.get_brake(2);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the center brake, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setCenterBrake (double brake)
|
||
{
|
||
controls.set_brake(2, brake);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the left brake, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getLeftBrake ()
|
||
{
|
||
return controls.get_brake(0);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the left brake, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setLeftBrake (double brake)
|
||
{
|
||
controls.set_brake(0, brake);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the right brake, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
double
|
||
FGBFI::getRightBrake ()
|
||
{
|
||
return controls.get_brake(1);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the right brake, from 0.0 (none) to 1.0 (full).
|
||
*/
|
||
void
|
||
FGBFI::setRightBrake (double brake)
|
||
{
|
||
controls.set_brake(1, brake);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Autopilot
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Get the autopilot altitude lock (true=on).
|
||
*/
|
||
bool
|
||
FGBFI::getAPAltitudeLock ()
|
||
{
|
||
return current_autopilot->get_AltitudeEnabled();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot altitude lock (true=on).
|
||
*/
|
||
void
|
||
FGBFI::setAPAltitudeLock (bool lock)
|
||
{
|
||
current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
|
||
current_autopilot->set_AltitudeEnabled(lock);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the autopilot target altitude in feet.
|
||
*/
|
||
double
|
||
FGBFI::getAPAltitude ()
|
||
{
|
||
return current_autopilot->get_TargetAltitude() * METER_TO_FEET;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot target altitude in feet.
|
||
*/
|
||
void
|
||
FGBFI::setAPAltitude (double altitude)
|
||
{
|
||
current_autopilot->set_TargetAltitude( altitude );
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the autopilot heading lock (true=on).
|
||
*/
|
||
bool
|
||
FGBFI::getAPHeadingLock ()
|
||
{
|
||
return
|
||
(current_autopilot->get_HeadingEnabled() &&
|
||
current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_LOCK);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot heading lock (true=on).
|
||
*/
|
||
void
|
||
FGBFI::setAPHeadingLock (bool lock)
|
||
{
|
||
if (lock) {
|
||
// We need to do this so that
|
||
// it's possible to lock onto a
|
||
// heading other than the current
|
||
// heading.
|
||
double heading = getAPHeadingMag();
|
||
current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_LOCK);
|
||
current_autopilot->set_HeadingEnabled(true);
|
||
setAPHeadingMag(heading);
|
||
} else if (current_autopilot->get_HeadingMode() ==
|
||
FGAutopilot::FG_HEADING_LOCK) {
|
||
current_autopilot->set_HeadingEnabled(false);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the autopilot target heading in degrees.
|
||
*/
|
||
double
|
||
FGBFI::getAPHeading ()
|
||
{
|
||
return current_autopilot->get_TargetHeading();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot target heading in degrees.
|
||
*/
|
||
void
|
||
FGBFI::setAPHeading (double heading)
|
||
{
|
||
current_autopilot->set_TargetHeading( heading );
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the autopilot target heading in degrees.
|
||
*/
|
||
double
|
||
FGBFI::getAPHeadingMag ()
|
||
{
|
||
return current_autopilot->get_TargetHeading() - getMagVar();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot target heading in degrees.
|
||
*/
|
||
void
|
||
FGBFI::setAPHeadingMag (double heading)
|
||
{
|
||
current_autopilot->set_TargetHeading( heading + getMagVar() );
|
||
}
|
||
|
||
|
||
/**
|
||
* Return true if the autopilot is locked to NAV1.
|
||
*/
|
||
bool
|
||
FGBFI::getAPNAV1Lock ()
|
||
{
|
||
return
|
||
(current_autopilot->get_HeadingEnabled() &&
|
||
current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot NAV1 lock.
|
||
*/
|
||
void
|
||
FGBFI::setAPNAV1Lock (bool lock)
|
||
{
|
||
if (lock) {
|
||
current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
|
||
current_autopilot->set_HeadingEnabled(true);
|
||
} else if (current_autopilot->get_HeadingMode() ==
|
||
FGAutopilot::FG_HEADING_NAV1) {
|
||
current_autopilot->set_HeadingEnabled(false);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Radio navigation.
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
double
|
||
FGBFI::getNAV1Freq ()
|
||
{
|
||
return current_radiostack->get_nav1_freq();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV1AltFreq ()
|
||
{
|
||
return current_radiostack->get_nav1_alt_freq();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV1Radial ()
|
||
{
|
||
return current_radiostack->get_nav1_radial();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV1SelRadial ()
|
||
{
|
||
return current_radiostack->get_nav1_sel_radial();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV1DistDME ()
|
||
{
|
||
return current_radiostack->get_nav1_dme_dist();
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV1TO ()
|
||
{
|
||
if (current_radiostack->get_nav1_inrange()) {
|
||
double heading = current_radiostack->get_nav1_heading();
|
||
double radial = current_radiostack->get_nav1_radial();
|
||
double var = FGBFI::getMagVar();
|
||
if (current_radiostack->get_nav1_loc()) {
|
||
double offset = fabs(heading - radial);
|
||
return (offset<= 8.0 || offset >= 352.0);
|
||
} else {
|
||
double offset =
|
||
fabs(heading - var - radial);
|
||
return (offset <= 20.0 || offset >= 340.0);
|
||
}
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV1FROM ()
|
||
{
|
||
if (current_radiostack->get_nav1_inrange()) {
|
||
double heading = current_radiostack->get_nav1_heading();
|
||
double radial = current_radiostack->get_nav1_radial();
|
||
double var = FGBFI::getMagVar();
|
||
if (current_radiostack->get_nav1_loc()) {
|
||
double offset = fabs(heading - radial);
|
||
return (offset >= 172.0 && offset<= 188.0);
|
||
} else {
|
||
double offset =
|
||
fabs(heading - var - radial);
|
||
return (offset >= 160.0 && offset <= 200.0);
|
||
}
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV1InRange ()
|
||
{
|
||
return current_radiostack->get_nav1_inrange();
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV1DMEInRange ()
|
||
{
|
||
return (current_radiostack->get_nav1_inrange() &&
|
||
current_radiostack->get_nav1_has_dme());
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV2Freq ()
|
||
{
|
||
return current_radiostack->get_nav2_freq();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV2AltFreq ()
|
||
{
|
||
return current_radiostack->get_nav2_alt_freq();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV2Radial ()
|
||
{
|
||
return current_radiostack->get_nav2_radial();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV2SelRadial ()
|
||
{
|
||
return current_radiostack->get_nav2_sel_radial();
|
||
}
|
||
|
||
double
|
||
FGBFI::getNAV2DistDME ()
|
||
{
|
||
return current_radiostack->get_nav2_dme_dist();
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV2TO ()
|
||
{
|
||
if (current_radiostack->get_nav2_inrange()) {
|
||
double heading = current_radiostack->get_nav2_heading();
|
||
double radial = current_radiostack->get_nav2_radial();
|
||
double var = FGBFI::getMagVar();
|
||
if (current_radiostack->get_nav2_loc()) {
|
||
double offset = fabs(heading - radial);
|
||
return (offset<= 8.0 || offset >= 352.0);
|
||
} else {
|
||
double offset =
|
||
fabs(heading - var - radial);
|
||
return (offset <= 20.0 || offset >= 340.0);
|
||
}
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV2FROM ()
|
||
{
|
||
if (current_radiostack->get_nav2_inrange()) {
|
||
double heading = current_radiostack->get_nav2_heading();
|
||
double radial = current_radiostack->get_nav2_radial();
|
||
double var = FGBFI::getMagVar();
|
||
if (current_radiostack->get_nav2_loc()) {
|
||
double offset = fabs(heading - radial);
|
||
return (offset >= 172.0 && offset<= 188.0);
|
||
} else {
|
||
double offset =
|
||
fabs(heading - var - radial);
|
||
return (offset >= 160.0 && offset <= 200.0);
|
||
}
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
bool
|
||
FGBFI::getNAV2InRange ()
|
||
{
|
||
return current_radiostack->get_nav2_inrange();
|
||
}
|
||
|
||
bool
|
||
FGBFI::getNAV2DMEInRange ()
|
||
{
|
||
return (current_radiostack->get_nav2_inrange() &&
|
||
current_radiostack->get_nav2_has_dme());
|
||
}
|
||
|
||
double
|
||
FGBFI::getADFFreq ()
|
||
{
|
||
return current_radiostack->get_adf_freq();
|
||
}
|
||
|
||
double
|
||
FGBFI::getADFAltFreq ()
|
||
{
|
||
return current_radiostack->get_adf_alt_freq();
|
||
}
|
||
|
||
double
|
||
FGBFI::getADFRotation ()
|
||
{
|
||
return current_radiostack->get_adf_rotation();
|
||
}
|
||
|
||
void
|
||
FGBFI::setNAV1Freq (double freq)
|
||
{
|
||
current_radiostack->set_nav1_freq(freq);
|
||
}
|
||
|
||
void
|
||
FGBFI::setNAV1AltFreq (double freq)
|
||
{
|
||
current_radiostack->set_nav1_alt_freq(freq);
|
||
}
|
||
|
||
void
|
||
FGBFI::setNAV1SelRadial (double radial)
|
||
{
|
||
current_radiostack->set_nav1_sel_radial(radial);
|
||
}
|
||
|
||
void
|
||
FGBFI::setNAV2Freq (double freq)
|
||
{
|
||
current_radiostack->set_nav2_freq(freq);
|
||
}
|
||
|
||
void
|
||
FGBFI::setNAV2AltFreq (double freq)
|
||
{
|
||
current_radiostack->set_nav2_alt_freq(freq);
|
||
}
|
||
|
||
void
|
||
FGBFI::setNAV2SelRadial (double radial)
|
||
{
|
||
current_radiostack->set_nav2_sel_radial(radial);
|
||
}
|
||
|
||
void
|
||
FGBFI::setADFFreq (double freq)
|
||
{
|
||
current_radiostack->set_adf_freq(freq);
|
||
}
|
||
|
||
void
|
||
FGBFI::setADFAltFreq (double freq)
|
||
{
|
||
current_radiostack->set_adf_alt_freq(freq);
|
||
}
|
||
|
||
void
|
||
FGBFI::setADFRotation (double rot)
|
||
{
|
||
current_radiostack->set_adf_rotation(rot);
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// GPS
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Get the autopilot GPS lock (true=on).
|
||
*/
|
||
bool
|
||
FGBFI::getGPSLock ()
|
||
{
|
||
return (current_autopilot->get_HeadingEnabled() &&
|
||
(current_autopilot->get_HeadingMode() ==
|
||
FGAutopilot::FG_HEADING_WAYPOINT ));
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the autopilot GPS lock (true=on).
|
||
*/
|
||
void
|
||
FGBFI::setGPSLock (bool lock)
|
||
{
|
||
if (lock) {
|
||
current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_WAYPOINT);
|
||
current_autopilot->set_HeadingEnabled(true);
|
||
} else if (current_autopilot->get_HeadingMode() ==
|
||
FGAutopilot::FG_HEADING_WAYPOINT) {
|
||
current_autopilot->set_HeadingEnabled(false);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the GPS target airport code.
|
||
*/
|
||
const string &
|
||
FGBFI::getTargetAirport ()
|
||
{
|
||
// FIXME: not thread-safe
|
||
static string out;
|
||
out = globals->get_options()->get_airport_id();
|
||
|
||
return out;
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the GPS target airport code.
|
||
*/
|
||
void
|
||
FGBFI::setTargetAirport (const string &airportId)
|
||
{
|
||
// cout << "setting target airport id = " << airportId << endl;
|
||
globals->get_options()->set_airport_id(airportId);
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the GPS target latitude in degrees (negative for south).
|
||
*/
|
||
double
|
||
FGBFI::getGPSTargetLatitude ()
|
||
{
|
||
return current_autopilot->get_TargetLatitude();
|
||
}
|
||
|
||
|
||
/**
|
||
* Get the GPS target longitude in degrees (negative for west).
|
||
*/
|
||
double
|
||
FGBFI::getGPSTargetLongitude ()
|
||
{
|
||
return current_autopilot->get_TargetLongitude();
|
||
}
|
||
|
||
#if 0
|
||
/**
|
||
* Set the GPS target longitude in degrees (negative for west).
|
||
*/
|
||
void
|
||
FGBFI::setGPSTargetLongitude (double longitude)
|
||
{
|
||
current_autopilot->set_TargetLongitude( longitude );
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Weather
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
* Get the current visible (units??).
|
||
*/
|
||
double
|
||
FGBFI::getVisibility ()
|
||
{
|
||
#ifndef FG_OLD_WEATHER
|
||
return WeatherDatabase->getWeatherVisibility();
|
||
#else
|
||
return current_weather.get_visibility();
|
||
#endif
|
||
}
|
||
|
||
|
||
/**
|
||
* Check whether clouds are enabled.
|
||
*/
|
||
bool
|
||
FGBFI::getClouds ()
|
||
{
|
||
return globals->get_options()->get_clouds();
|
||
}
|
||
|
||
|
||
/**
|
||
* Check the height of the clouds ASL (units?).
|
||
*/
|
||
double
|
||
FGBFI::getCloudsASL ()
|
||
{
|
||
return globals->get_options()->get_clouds_asl();
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the current visibility (units??).
|
||
*/
|
||
void
|
||
FGBFI::setVisibility (double visibility)
|
||
{
|
||
#ifndef FG_OLD_WEATHER
|
||
WeatherDatabase->setWeatherVisibility(visibility);
|
||
#else
|
||
current_weather.set_visibility(visibility);
|
||
#endif
|
||
}
|
||
|
||
|
||
/**
|
||
* Switch clouds on or off.
|
||
*/
|
||
void
|
||
FGBFI::setClouds (bool clouds)
|
||
{
|
||
if (getClouds() != clouds) {
|
||
cout << "Set clouds to " << clouds << endl;
|
||
globals->get_options()->set_clouds(clouds);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Set the cloud height.
|
||
*/
|
||
void
|
||
FGBFI::setCloudsASL (double cloudsASL)
|
||
{
|
||
if (getCloudsASL() != cloudsASL) {
|
||
globals->get_options()->set_clouds_asl(cloudsASL);
|
||
needReinit();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
// Time
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
/**
|
||
* Return the magnetic variation
|
||
*/
|
||
double
|
||
FGBFI::getMagVar ()
|
||
{
|
||
return globals->get_mag()->get_magvar() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
/**
|
||
* Return the magnetic variation
|
||
*/
|
||
double
|
||
FGBFI::getMagDip ()
|
||
{
|
||
return globals->get_mag()->get_magdip() * RAD_TO_DEG;
|
||
}
|
||
|
||
|
||
// end of bfi.cxx
|
||
|