1
0
Fork 0
flightgear/src/Main/bfi.cxx
curt 7cc98ad15f I tested:
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.
2000-10-24 00:34:50 +00:00

1684 lines
34 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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