1
0
Fork 0

Updates to JSBSim and FDM interface.

This commit is contained in:
curt 2001-11-06 22:33:05 +00:00
parent bc20e9b490
commit 5fe0f04702
22 changed files with 420 additions and 491 deletions

View file

@ -168,9 +168,10 @@ FGADA::~FGADA() {
// for each subsequent iteration through the EOM
void FGADA::init() {
// explicitly call the superclass's
// init() method first.
FGInterface::init();
//do init common to all FDM"s
common_init();
//now do ADA-specific init.
// cout << "FGADA::init()" << endl;

View file

@ -75,9 +75,11 @@ FGBalloonSim::~FGBalloonSim() {
// Initialize the BalloonSim flight model, dt is the time increment for
// each subsequent iteration through the EOM
void FGBalloonSim::init() {
// explicitly call the superclass's
// init method first.
FGInterface::init();
//do init common to all the FDM's
common_init();
//now do init specific to the Balloon
sgVec3 temp;

View file

@ -77,6 +77,8 @@ FGJSBsim::FGJSBsim( double dt )
Position = fdmex->GetPosition();
Auxiliary = fdmex->GetAuxiliary();
Aerodynamics = fdmex->GetAerodynamics();
GroundReactions = fdmex->GetGroundReactions();
Atmosphere->UseInternal();
@ -113,9 +115,9 @@ FGJSBsim::FGJSBsim( double dt )
add_engine( FGEngInterface() );
}
if ( fdmex->GetGroundReactions()->GetNumGearUnits() <= 0 ) {
if ( GroundReactions->GetNumGearUnits() <= 0 ) {
SG_LOG( SG_FLIGHT, SG_ALERT, "num gear units = "
<< fdmex->GetGroundReactions()->GetNumGearUnits() );
<< GroundReactions->GetNumGearUnits() );
SG_LOG( SG_FLIGHT, SG_ALERT, "This is a very bad thing because with 0 gear units, the ground trimming");
SG_LOG( SG_FLIGHT, SG_ALERT, "routine (coming up later in the code) will core dump.");
SG_LOG( SG_FLIGHT, SG_ALERT, "Halting the sim now, and hoping a solution will present itself soon!");
@ -123,6 +125,8 @@ FGJSBsim::FGJSBsim( double dt )
}
init_gear();
fgSetDouble("/fdm/trim/pitch-trim", FCS->GetPitchTrimCmd());
fgSetDouble("/fdm/trim/throttle", FCS->GetThrottleCmd(0));
fgSetDouble("/fdm/trim/aileron", FCS->GetDaCmd());
@ -137,6 +141,10 @@ FGJSBsim::FGJSBsim( double dt )
throttle_trim = fgGetNode("/fdm/trim/throttle", true );
aileron_trim = fgGetNode("/fdm/trim/aileron", true );
rudder_trim = fgGetNode("/fdm/trim/rudder", true );
stall_warning = fgGetNode("/sim/aircraft/alarms/stall-warning",true);
stall_warning->setDoubleValue(0);
}
/******************************************************************************/
@ -158,7 +166,7 @@ void FGJSBsim::init() {
// Explicitly call the superclass's
// init method first.
FGInterface::init();
common_init();
fdmex->GetState()->Initialize(fgic);
fdmex->RunIC(fgic); //loop JSBSim once w/o integrating
@ -191,6 +199,8 @@ void FGJSBsim::init() {
break;
}
stall_warning->setBoolValue(false);
SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: "
<< Rotation->Getphi()*RADTODEG << " deg" );
SG_LOG( SG_FLIGHT, SG_INFO, " Pitch Angle: "
@ -208,6 +218,9 @@ void FGJSBsim::init() {
SG_LOG( SG_FLIGHT, SG_INFO, " set dt" );
SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" );
}
/******************************************************************************/
@ -224,43 +237,13 @@ bool FGJSBsim::update( int multiloop ) {
trimmed->setBoolValue(false);
if ( needTrim && startup_trim->getBoolValue() ) {
cout << "num gear units = " << fdmex->GetGroundReactions()->GetNumGearUnits() << endl;
//fgic->SetSeaLevelRadiusFtIC( get_Sea_level_radius() );
//fgic->SetTerrainAltitudeFtIC( scenery.cur_elev * SG_METER_TO_FEET );
FGTrim *fgtrim;
if(fgic->GetVcalibratedKtsIC() < 10 ) {
fgic->SetVcalibratedKtsIC(0.0);
fgtrim=new FGTrim(fdmex,fgic,tGround);
if ( needTrim ) {
if ( startup_trim->getBoolValue() ) {
do_trim();
} else {
fgtrim=new FGTrim(fdmex,fgic,tLongitudinal);
fdmex->RunIC(fgic); //apply any changes made through the set_ functions
}
if(!fgtrim->DoTrim()) {
fgtrim->Report();
fgtrim->TrimStats();
} else {
trimmed->setBoolValue(true);
}
fgtrim->ReportState();
delete fgtrim;
needTrim = false;
pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() );
throttle_trim->setDoubleValue( FCS->GetThrottleCmd(0) );
aileron_trim->setDoubleValue( FCS->GetDaCmd() );
rudder_trim->setDoubleValue( FCS->GetDrCmd() );
globals->get_controls()->set_elevator_trim(FCS->GetPitchTrimCmd());
globals->get_controls()->set_elevator(FCS->GetDeCmd());
globals->get_controls()->set_throttle(FGControls::ALL_ENGINES,
FCS->GetThrottleCmd(0));
globals->get_controls()->set_aileron(FCS->GetDaCmd());
globals->get_controls()->set_rudder( FCS->GetDrCmd());
SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
}
for( i=0; i<get_num_engines(); i++ ) {
@ -269,6 +252,18 @@ bool FGJSBsim::update( int multiloop ) {
FGThruster * thrust = Propulsion->GetThruster(i);
eng->SetMagnetos( globals->get_controls()->get_magnetos(i) );
eng->SetStarter( globals->get_controls()->get_starter(i) );
e->set_Throttle( globals->get_controls()->get_throttle(i) );
}
for ( i=0; i < multiloop; i++ ) {
fdmex->Run();
}
for( i=0; i<get_num_engines(); i++ ) {
FGEngInterface * e = get_engine(i);
FGEngine * eng = Propulsion->GetEngine(i);
FGThruster * thrust = Propulsion->GetThruster(i);
e->set_Manifold_Pressure( eng->getManifoldPressure_inHg() );
e->set_RPM( thrust->GetRPM() );
e->set_EGT( eng->getExhaustGasTemp_degF() );
@ -276,19 +271,15 @@ bool FGJSBsim::update( int multiloop ) {
e->set_Oil_Temp( eng->getOilTemp_degF() );
e->set_Running_Flag( eng->GetRunning() );
e->set_Cranking_Flag( eng->GetCranking() );
e->set_Throttle( globals->get_controls()->get_throttle(i) );
}
for ( i=0; i < multiloop; i++ ) {
fdmex->Run();
}
// printf("%d FG_Altitude = %.2f\n", i, FG_Altitude * 0.3048);
// printf("%d Altitude = %.2f\n", i, Altitude * 0.3048);
update_gear();
stall_warning->setDoubleValue( Aircraft->GetStallWarn() );
// translate JSBsim back to FG structure so that the
// autopilot (and the rest of the sim can use the updated values
copy_from_JSBsim();
return true;
}
@ -350,25 +341,25 @@ bool FGJSBsim::copy_from_JSBsim() {
MassBalance->GetXYZcg(2),
MassBalance->GetXYZcg(3) );
_set_Accels_Body( Translation->GetUVWdot(1),
Translation->GetUVWdot(2),
Translation->GetUVWdot(3) );
_set_Accels_Body( Aircraft->GetBodyAccel()(1),
Aircraft->GetBodyAccel()(2),
Aircraft->GetBodyAccel()(3) );
_set_Accels_CG_Body( Translation->GetUVWdot(1),
Translation->GetUVWdot(2),
Translation->GetUVWdot(3) );
//_set_Accels_CG_Body_N ( Translation->GetNcg(1),
// Translation->GetNcg(2),
// Translation->GetNcg(3) );
//_set_Accels_CG_Body( Aircraft->GetBodyAccel()(1),
// Aircraft->GetBodyAccel()(2),
// Aircraft->GetBodyAccel()(3) );
//
_set_Accels_Pilot_Body( Auxiliary->GetPilotAccel(1),
Auxiliary->GetPilotAccel(2),
Auxiliary->GetPilotAccel(3) );
_set_Accels_CG_Body_N ( Aircraft->GetNcg()(1),
Aircraft->GetNcg()(2),
Aircraft->GetNcg()(3) );
//_set_Accels_Pilot_Body_N( Auxiliary->GetNpilot(1),
// Auxiliary->GetNpilot(2),
// Auxiliary->GetNpilot(3) );
_set_Accels_Pilot_Body( Auxiliary->GetPilotAccel()(1),
Auxiliary->GetPilotAccel()(2),
Auxiliary->GetPilotAccel()(3) );
// _set_Accels_Pilot_Body_N( Auxiliary->GetPilotAccel()(1)/32.1739,
// Auxiliary->GetNpilot(2)/32.1739,
// Auxiliary->GetNpilot(3)/32.1739 );
_set_Nlf( Aerodynamics->GetNlf() );
@ -437,19 +428,6 @@ bool FGJSBsim::copy_from_JSBsim() {
return true;
}
void FGJSBsim::snap_shot(void) {
fgic->SetLatitudeRadIC(get_Lat_geocentric() );
fgic->SetLongitudeRadIC( get_Longitude() );
fgic->SetAltitudeFtIC( get_Altitude() );
fgic->SetTerrainAltitudeFtIC( get_Runway_altitude() );
fgic->SetVtrueFpsIC( get_V_rel_wind() );
fgic->SetPitchAngleRadIC( get_Theta() );
fgic->SetRollAngleRadIC( get_Phi() );
fgic->SetTrueHeadingRadIC( get_Psi() );
fgic->SetClimbRateFpsIC( get_Climb_Rate() );
}
bool FGJSBsim::ToggleDataLogging(void) {
return fdmex->GetOutput()->Toggle();
}
@ -484,6 +462,7 @@ void FGJSBsim::set_Latitude(double lat) {
sgGeodToGeoc( lat, alt * SG_FEET_TO_METER,
&sea_level_radius_meters, &lat_geoc );
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc );
@ -617,7 +596,6 @@ void FGJSBsim::set_Density(double rho) {
needTrim=true;
}
void FGJSBsim::set_Velocities_Local_Airmass (double wnorth,
double weast,
double wdown ) {
@ -630,194 +608,70 @@ void FGJSBsim::set_Velocities_Local_Airmass (double wnorth,
needTrim=true;
}
void FGJSBsim::init_gear(void ) {
//Positions
void FGJSBsim::update_Latitude(double lat) {
double sea_level_radius_meters, lat_geoc;
SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::update_Latitude: " << lat );
SG_LOG(SG_FLIGHT,SG_INFO," cur alt = " << get_Altitude() );
snap_shot();
sgGeodToGeoc( lat, get_Altitude(), &sea_level_radius_meters, &lat_geoc);
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc );
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
FGGearInterface *gear;
FGGroundReactions* gr=fdmex->GetGroundReactions();
int Ngear=GroundReactions->GetNumGearUnits();
for (int i=0;i<Ngear;i++) {
add_gear_unit( FGGearInterface() );
gear=get_gear_unit(i);
gear->SetX( gr->GetGearUnit(i)->GetBodyLocation()(1) );
gear->SetY( gr->GetGearUnit(i)->GetBodyLocation()(2) );
gear->SetZ( gr->GetGearUnit(i)->GetBodyLocation()(3) );
gear->SetWoW( gr->GetGearUnit(i)->GetWOW() );
if ( gr->GetGearUnit(i)->GetBrakeGroup() > 0 ) {
gear->SetBrake(true);
}
if ( gr->GetGearUp() ) {
gear->SetPosition( 0.0 );
}
}
}
void FGJSBsim::update_Longitude(double lon) {
void FGJSBsim::update_gear(void) {
SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::update_Longitude: " << lon );
SG_LOG(SG_FLIGHT,SG_INFO," cur alt = " << get_Altitude() );
snap_shot();
fgic->SetLongitudeRadIC(lon);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
FGGearInterface* gear;
FGGroundReactions* gr=fdmex->GetGroundReactions();
int Ngear=GroundReactions->GetNumGearUnits();
for (int i=0;i<Ngear;i++) {
gear=get_gear_unit(i);
gear->SetWoW( gr->GetGearUnit(i)->GetWOW() );
if ( gr->GetGearUp() ) {
gear->SetPosition( 0.0 );
}
}
}
void FGJSBsim::update_Altitude(double alt) {
double sea_level_radius_meters,lat_geoc;
void FGJSBsim::do_trim(void) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Altitude: " << alt );
snap_shot();
sgGeodToGeoc( get_Latitude(), alt , &sea_level_radius_meters, &lat_geoc);
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc );
fgic->SetAltitudeFtIC(alt);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
FGTrim *fgtrim;
if(fgic->GetVcalibratedKtsIC() < 10 ) {
fgic->SetVcalibratedKtsIC(0.0);
fgtrim=new FGTrim(fdmex,fgic,tGround);
} else {
fgtrim=new FGTrim(fdmex,fgic,tLongitudinal);
}
void FGJSBsim::update_V_calibrated_kts(double vc) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_V_calibrated_kts: " << vc );
snap_shot();
fgic->SetVcalibratedKtsIC(vc);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
if( !fgtrim->DoTrim() ) {
fgtrim->Report();
fgtrim->TrimStats();
} else {
trimmed->setBoolValue(true);
}
State->ReportState();
delete fgtrim;
pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() );
throttle_trim->setDoubleValue( FCS->GetThrottleCmd(0) );
aileron_trim->setDoubleValue( FCS->GetDaCmd() );
rudder_trim->setDoubleValue( FCS->GetDrCmd() );
void FGJSBsim::update_Mach_number(double mach) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Mach_number: " << mach );
globals->get_controls()->set_elevator_trim(FCS->GetPitchTrimCmd());
globals->get_controls()->set_elevator(FCS->GetDeCmd());
globals->get_controls()->set_throttle(FGControls::ALL_ENGINES,
FCS->GetThrottleCmd(0));
snap_shot();
fgic->SetMachIC(mach);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
globals->get_controls()->set_aileron(FCS->GetDaCmd());
globals->get_controls()->set_rudder( FCS->GetDrCmd());
SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
}
void FGJSBsim::update_Velocities_Local( double north, double east, double down ){
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Velocities_Local: "
<< north << ", " << east << ", " << down );
snap_shot();
fgic->SetVnorthFpsIC(north);
fgic->SetVeastFpsIC(east);
fgic->SetVdownFpsIC(down);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
void FGJSBsim::update_Velocities_Wind_Body( double u, double v, double w){
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Velocities_Wind_Body: "
<< u << ", " << v << ", " << w );
snap_shot();
fgic->SetUBodyFpsIC(u);
fgic->SetVBodyFpsIC(v);
fgic->SetWBodyFpsIC(w);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
//Euler angles
void FGJSBsim::update_Euler_Angles( double phi, double theta, double psi ) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Euler_Angles: "
<< phi << ", " << theta << ", " << psi );
snap_shot();
fgic->SetPitchAngleRadIC(theta);
fgic->SetRollAngleRadIC(phi);
fgic->SetTrueHeadingRadIC(psi);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
//Flight Path
void FGJSBsim::update_Climb_Rate( double roc) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Climb_Rate: " << roc );
snap_shot();
fgic->SetClimbRateFpsIC(roc);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
void FGJSBsim::update_Gamma_vert_rad( double gamma) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Gamma_vert_rad: " << gamma );
snap_shot();
fgic->SetFlightPathAngleRadIC(gamma);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
//Earth
void FGJSBsim::update_Sea_level_radius(double slr) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Sea_level_radius: " << slr );
snap_shot();
fgic->SetSeaLevelRadiusFtIC(slr);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
void FGJSBsim::update_Runway_altitude(double ralt) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Runway_altitude: " << ralt );
snap_shot();
_set_Runway_altitude( ralt );
fgic->SetTerrainAltitudeFtIC( ralt );
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
}
void FGJSBsim::update_Static_pressure(double p) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Static_pressure: " << p );
snap_shot();
Atmosphere->SetExPressure(p);
if(Atmosphere->External() == true)
needTrim=true;
}
void FGJSBsim::update_Static_temperature(double T) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Static_temperature: " << T );
snap_shot();
Atmosphere->SetExTemperature(T);
if(Atmosphere->External() == true)
needTrim=true;
}
void FGJSBsim::update_Density(double rho) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Density: " << rho );
snap_shot();
Atmosphere->SetExDensity(rho);
if(Atmosphere->External() == true)
needTrim=true;
}
void FGJSBsim::update_Velocities_Local_Airmass (double wnorth,
double weast,
double wdown ) {
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Velocities_Local_Airmass: "
<< wnorth << ", " << weast << ", " << wdown );
_set_Velocities_Local_Airmass( wnorth, weast, wdown );
snap_shot();
Atmosphere->SetWindNED(wnorth, weast, wdown );
if(Atmosphere->External() == true)
needTrim=true;
}

View file

@ -207,101 +207,7 @@ public:
double wdown );
/// @name Position Parameter Update
//@{
/** Update geocentric latitude
@param lat latitude in radians measured from the 0 meridian where
the westerly direction is positive and east is negative */
void update_Latitude(double lat); // geocentric
/** Update longitude
@param lon longitude in radians measured from the equator where
the northerly direction is positive and south is negative */
void update_Longitude(double lon);
/** Update altitude
Note: this triggers a recalculation of AGL altitude
@param alt altitude in feet */
void update_Altitude(double alt); // triggers re-calc of AGL altitude
//@}
//void update_AltitudeAGL(double altagl); // and vice-versa
/// @name Velocity Parameter Update
//@{
/** Updates calibrated airspeed
Updateting this will trigger a recalc of the other velocity terms.
@param vc Calibrated airspeed in ft/sec */
void update_V_calibrated_kts(double vc);
/** Updates Mach number.
Updateting this will trigger a recalc of the other velocity terms.
@param mach Mach number */
void update_Mach_number(double mach);
/** Updates velocity in N-E-D coordinates.
Updateting this will trigger a recalc of the other velocity terms.
@param north velocity northward in ft/sec
@param east velocity eastward in ft/sec
@param down velocity downward in ft/sec */
void update_Velocities_Local( double north, double east, double down );
/** Updates aircraft velocity in stability frame.
Updateting this will trigger a recalc of the other velocity terms.
@param u X velocity in ft/sec
@param v Y velocity in ft/sec
@param w Z velocity in ft/sec */
void update_Velocities_Wind_Body( double u, double v, double w);
//@}
/** Euler Angle Parameter Update
@param phi roll angle in radians
@param theta pitch angle in radians
@param psi heading angle in radians */
void update_Euler_Angles( double phi, double theta, double psi );
/// @name Flight Path Parameter Update
//@{
/** Updates rate of climb
@param roc Rate of climb in ft/sec */
void update_Climb_Rate( double roc);
/** Updates the flight path angle in radians
@param gamma flight path angle in radians. */
void update_Gamma_vert_rad( double gamma);
//@}
/// @name Earth Parameter Update
//@{
/** Updates the sea level radius in feet.
@param slr Sea Level Radius in feet */
void update_Sea_level_radius(double slr);
/** Updates the runway altitude in feet above sea level.
@param ralt Runway altitude in feet above sea level. */
void update_Runway_altitude(double ralt);
//@}
/// @name Atmospheric Parameter Update
//@{
/** Updates the atmospheric static pressure
@param p pressure in psf */
void update_Static_pressure(double p);
/** Updates the atmospheric temperature
@param T temperature in degrees rankine */
void update_Static_temperature(double T);
/** Updates the atmospheric density.
@param rho air density slugs/cubic foot */
void update_Density(double rho);
/** Updates the velocity of the local airmass for wind modeling.
@param wnorth velocity north in fps
@param weast velocity east in fps
@param wdown velocity down in fps*/
void update_Velocities_Local_Airmass (double wnorth,
double weast,
double wdown );
//@}
/** Update the position based on inputs, positions, velocities, etc.
@param multiloop number of times to loop through the FDM
@ -309,6 +215,7 @@ public:
bool update( int multiloop );
bool ToggleDataLogging(bool state);
bool ToggleDataLogging(void);
void do_trim(void);
private:
FGFDMExec *fdmex;
@ -326,6 +233,7 @@ private:
FGPosition* Position;
FGAuxiliary* Auxiliary;
FGAerodynamics* Aerodynamics;
FGGroundReactions *GroundReactions;
int runcount;
float trim_elev;
@ -337,8 +245,11 @@ private:
SGPropertyNode *throttle_trim;
SGPropertyNode *aileron_trim;
SGPropertyNode *rudder_trim;
SGPropertyNode *stall_warning;
void init_gear(void);
void update_gear(void);
void snap_shot(void);
};

View file

@ -104,13 +104,15 @@ FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex),
vXYZrp(3),
vXYZep(3),
vDXYZcg(3),
vBodyAccel(3)
vBodyAccel(3),
vNcg(3)
{
Name = "FGAircraft";
alphaclmin = alphaclmax = 0;
HTailArea = VTailArea = HTailArm = VTailArm = 0.0;
lbarh = lbarv = vbarh = vbarv = 0.0;
WingIncidence=0;
impending_stall = 0;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
}
@ -176,6 +178,16 @@ bool FGAircraft::Run(void)
vBodyAccel = vForces/MassBalance->GetMass();
vNcg = vBodyAccel*INVGRAVITY;
if (alphaclmax != 0) {
if (Translation->Getalpha() > 0.85*alphaclmax) {
impending_stall = 10*(Translation->Getalpha()/alphaclmax - 0.85);
} else {
impending_stall = 0;
}
}
return false;
} else { // skip Run() execution this time
return true;

View file

@ -189,6 +189,7 @@ public:
inline FGColumnVector3& GetMoments(void) { return vMoments; }
inline FGColumnVector3& GetForces(void) { return vForces; }
inline FGColumnVector3& GetBodyAccel(void) { return vBodyAccel; }
inline FGColumnVector3& GetNcg (void) { return vNcg; }
inline FGColumnVector3& GetXYZrp(void) { return vXYZrp; }
inline FGColumnVector3& GetXYZep(void) { return vXYZep; }
inline float GetXYZrp(int idx) { return vXYZrp(idx); }
@ -199,6 +200,8 @@ public:
inline void SetAlphaCLMax(float tt) { alphaclmax=tt; }
inline void SetAlphaCLMin(float tt) { alphaclmin=tt; }
inline bool GetStallWarn(void) { return impending_stall; }
/// Subsystem types for specifying which will be output in the FDM data logging
enum SubSystems {
/** Subsystem: Simulation (= 1) */ ssSimulation = 1,
@ -224,10 +227,13 @@ private:
FGColumnVector3 vEuler;
FGColumnVector3 vDXYZcg;
FGColumnVector3 vBodyAccel;
FGColumnVector3 vNcg;
float WingArea, WingSpan, cbar, WingIncidence;
float HTailArea, VTailArea, HTailArm, VTailArm;
float lbarh,lbarv,vbarh,vbarv;
float alphaclmax,alphaclmin;
float impending_stall;
string CFGVersion;
string AircraftName;

View file

@ -141,19 +141,19 @@ public:
inline float GetWindPsi(void) { return psiw; }
private:
float rho;
double rho;
int lastIndex;
float h;
float htab[8];
float SLtemperature,SLdensity,SLpressure,SLsoundspeed;
float rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
float temperature,density,pressure,soundspeed;
double h;
double htab[8];
double SLtemperature,SLdensity,SLpressure,SLsoundspeed;
double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
double temperature,density,pressure,soundspeed;
bool useExternal;
float exTemperature,exDensity,exPressure;
double exTemperature,exDensity,exPressure;
FGColumnVector3 vWindNED;
float psiw;
double psiw;
void Calculate(float altitude);
void Debug(void);

View file

@ -63,6 +63,7 @@ FGForce::FGForce(FGFDMExec *FDMExec) :
vXYZn(3),
vDXYZ(3),
mT(3,3),
vH(3),
vSense(3),
ttype(tNone)
{
@ -92,7 +93,9 @@ FGColumnVector3& FGForce::GetBodyForces(void) {
vDXYZ(2) = (vXYZn(2) - fdmex->GetMassBalance()->GetXYZcg(2))*INCHTOFT; //cg and rp values are in inches
vDXYZ(3) = -(vXYZn(3) - fdmex->GetMassBalance()->GetXYZcg(3))*INCHTOFT;
vM=vMn +vDXYZ*vFb;
// include rotational effects. vH will be set in descendent class such as
// FGPropeller, and in most other cases will be zero.
vM = vMn + vDXYZ*vFb + fdmex->GetRotation()->GetPQR()*vH;
return vFb;
}

View file

@ -256,6 +256,9 @@ public:
vXYZn(2) = y;
vXYZn(3) = z;
}
inline void SetLocationX(float x) {vXYZn(1) = x;}
inline void SetLocationY(float y) {vXYZn(2) = y;}
inline void SetLocationZ(float z) {vXYZn(3) = z;}
inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; }
FGColumnVector3& GetLocation(void) { return vXYZn; }
@ -282,6 +285,7 @@ public:
protected:
FGColumnVector3 vFn;
FGColumnVector3 vMn;
FGColumnVector3 vH;
FGFDMExec *fdmex;
virtual void Debug(void);

View file

@ -229,6 +229,9 @@ public:
inline float GetSteerAngle(void) { return SteerAngle;}
inline float GetstaticFCoeff(void) { return staticFCoeff;}
inline int GetBrakeGroup(void) { return (int)eBrakeGrp; }
inline int GetSteerType(void) { return (int)eSteerType; }
private:
FGColumnVector3 vXYZ;
FGColumnVector3 vMoment;

View file

@ -50,7 +50,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
string token;
int rows, cols;
MaxPitch = MinPitch = 0.0;
MaxPitch = MinPitch = P_Factor = Sense = 0.0;
Name = Prop_cfg->GetValue("NAME");
Prop_cfg->GetNextConfigLine();
@ -67,6 +67,10 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
*Prop_cfg >> MinPitch;
} else if (token == "MAXPITCH") {
*Prop_cfg >> MaxPitch;
} else if (token == "P_FACTOR") {
*Prop_cfg >> P_Factor;
} else if (token == "SENSE") {
*Prop_cfg >> Sense;
} else if (token == "EFFICIENCY") {
*Prop_cfg >> rows >> cols;
if (cols == 1) Efficiency = new FGTable(rows);
@ -97,6 +101,14 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
cout << " Number of Blades = " << numBlades << endl;
cout << " Minimum Pitch = " << MinPitch << endl;
cout << " Maximum Pitch = " << MaxPitch << endl;
if (P_Factor > 0.0) cout << " P-Factor = " << P_Factor << endl;
if (Sense > 0.0) {
cout << " Rotation Sense = CW (viewed from pilot looking forward)" << endl;
} else if (Sense < 0.0) {
cout << " Rotation Sense = CCW (viewed from pilot looking forward)" << endl;
} else {
cout << " Rotation Sense = indeterminate" << endl;
}
cout << " Efficiency: " << endl;
Efficiency->Print();
cout << " Thrust Coefficient: " << endl;
@ -141,6 +153,7 @@ float FGPropeller::Calculate(float PowerAvailable)
float Vel = (fdmex->GetTranslation()->GetvAero())(1);
float rho = fdmex->GetAtmosphere()->GetDensity();
float RPS = RPM/60.0;
float alpha, beta;
if (RPM > 0.10) {
J = Vel / (Diameter * RPM / 60.0);
@ -154,10 +167,25 @@ float FGPropeller::Calculate(float PowerAvailable)
C_Thrust = cThrust->GetValue(J, Pitch);
}
if (P_Factor > 0.0001) {
alpha = fdmex->GetTranslation()->Getalpha();
beta = fdmex->GetTranslation()->Getbeta();
SetLocationY(P_Factor*alpha*fabs(Sense)/Sense);
SetLocationZ(P_Factor*beta*fabs(Sense)/Sense);
} else if (P_Factor < 0.000) {
cerr << "P-Factor value in config file must be greater than zero" << endl;
}
Thrust = C_Thrust*RPS*RPS*Diameter*Diameter*Diameter*Diameter*rho;
vFn(1) = Thrust;
omega = RPS*2.0*M_PI;
// Must consider rotated axis for propeller (V-22, helicopter case)
// FIX THIS !!
vH(eX) = Ixx*omega*fabs(Sense)/Sense;
vH(eY) = 0.0;
vH(eZ) = 0.0;
if (omega <= 5) omega = 1.0;
Torque = PowerAvailable / omega;

View file

@ -150,6 +150,8 @@ private:
float Diameter;
float MaxPitch;
float MinPitch;
float P_Factor;
float Sense;
float Pitch;
float Torque;
FGTable *Efficiency;

View file

@ -115,6 +115,8 @@ bool FGPropulsion::GetSteadyState(void) {
float PowerAvailable;
float currentThrust = 0, lastThrust=-1;
dt = State->Getdt();
int steady_count,j=0;
bool steady=false;
Forces->InitMatrix();
Moments->InitMatrix();
@ -123,10 +125,18 @@ bool FGPropulsion::GetSteadyState(void) {
for (unsigned int i=0; i<numEngines; i++) {
Engines[i]->SetTrimMode(true);
Thrusters[i]->SetdeltaT(dt*rate);
while (pow(currentThrust - lastThrust, 2.0) > currentThrust*0.00010) {
steady=false;
while (!steady && j < 6000) {
PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
lastThrust = currentThrust;
currentThrust = Thrusters[i]->Calculate(PowerAvailable);
if(fabs(lastThrust-currentThrust) < 0.0001) {
steady_count++;
if(steady_count > 120) { steady=true; }
} else {
steady_count=0;
}
j++;
}
*Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces
*Moments += Thrusters[i]->GetMoments(); // sum body frame moments
@ -141,6 +151,33 @@ bool FGPropulsion::GetSteadyState(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropulsion::ICEngineStart(void) {
float PowerAvailable;
int j;
dt = State->Getdt();
Forces->InitMatrix();
Moments->InitMatrix();
for (unsigned int i=0; i<numEngines; i++) {
Engines[i]->SetTrimMode(true);
Thrusters[i]->SetdeltaT(dt*rate);
j=0;
while (!Engines[i]->GetRunning() && j < 2000) {
PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
Thrusters[i]->Calculate(PowerAvailable);
j++;
}
*Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces
*Moments += Thrusters[i]->GetMoments(); // sum body frame moments
Engines[i]->SetTrimMode(false);
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropulsion::Load(FGConfigFile* AC_cfg)
{
string token, fullpath;

View file

@ -158,8 +158,13 @@ public:
/** Returns the number of oxidizer tanks currently actively supplying oxidizer */
inline int GetnumSelectedOxiTanks(void) {return numSelectedOxiTanks;}
/** Loops the engines/thrusters until thrust output steady (used for trimming) */
bool GetSteadyState(void);
/** starts the engines in IC mode (dt=0). All engine-specific setup must
be done before calling this (i.e. magnetos, starter engage, etc.) */
bool ICEngineStart(void);
string GetPropulsionStrings(void);
string GetPropulsionValues(void);

View file

@ -739,7 +739,7 @@ void FGState::ReportState(void) {
GetParameter(FG_RUDDER_POS)*RADTODEG );
cout << out;
snprintf(out,80, " Throttle: %5.2f%c\n",
FCS->GetThrottlePos(0),'%' );
FCS->GetThrottlePos(0)*100,'%' );
cout << out;
snprintf(out,80, " Wind Components: %5.2f kts head wind, %5.2f kts cross wind\n",

View file

@ -80,7 +80,6 @@ CLASS IMPLEMENTATION
FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex),
vUVW(3),
vUVWdot(3),
vNcg(3),
vlastUVWdot(3),
mVel(3,3),
vAero(3)
@ -120,9 +119,7 @@ bool FGTranslation::Run(void)
mVel(3,2) = vUVW(eU);
mVel(3,3) = 0.0;
vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetForces()/MassBalance->GetMass();
vNcg = vUVWdot*INVGRAVITY;
vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetBodyAccel();
vUVW += Tc * (vlastUVWdot + vUVWdot);
vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED();

View file

@ -91,8 +91,6 @@ public:
inline float GetUVW (int idx) { return vUVW(idx); }
inline FGColumnVector3& GetUVWdot(void) { return vUVWdot; }
inline float GetUVWdot(int idx) { return vUVWdot(idx); }
inline FGColumnVector3& GetNcg (void) { return vNcg; }
inline float GetNcg (int idx) { return vNcg(idx); }
inline FGColumnVector3& GetvAero (void) { return vAero; }
inline float GetvAero (int idx) { return vAero(idx); }
@ -121,7 +119,6 @@ public:
private:
FGColumnVector3 vUVW;
FGColumnVector3 vUVWdot;
FGColumnVector3 vNcg;
FGColumnVector3 vlastUVWdot;
FGMatrix33 mVel;
FGColumnVector3 vAero;

View file

@ -150,9 +150,9 @@ FGTrimAxis::~FGTrimAxis()
void FGTrimAxis::getState(void) {
switch(state) {
case tUdot: state_value=fdmex->GetTranslation()->GetUVWdot(1); break;
case tVdot: state_value=fdmex->GetTranslation()->GetUVWdot(2); break;
case tWdot: state_value=fdmex->GetTranslation()->GetUVWdot(3); break;
case tUdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(1); break;
case tVdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(2); break;
case tWdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(3); break;
case tQdot: state_value=fdmex->GetRotation()->GetPQRdot(2);break;
case tPdot: state_value=fdmex->GetRotation()->GetPQRdot(1); break;
case tRdot: state_value=fdmex->GetRotation()->GetPQRdot(3); break;
@ -398,6 +398,9 @@ void FGTrimAxis::setThrottlesPct(void) {
tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax();
//cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value;
fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin));
//cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl;
fdmex->RunIC(fgic); //apply throttle change
fdmex->GetPropulsion()->GetSteadyState();
}
}

View file

@ -88,10 +88,10 @@ FGLaRCsim::~FGLaRCsim(void) {
// Initialize the LaRCsim flight model, dt is the time increment for
// each subsequent iteration through the EOM
void FGLaRCsim::init() {
//do init common to all FDM's
common_init();
// Explicitly call the superclass's
// init method first.
FGInterface::init();
//now do any specific to LaRCsim
}

View file

@ -44,9 +44,7 @@ FGMagicCarpet::~FGMagicCarpet() {
// Initialize the Magic Carpet flight model, dt is the time increment
// for each subsequent iteration through the EOM
void FGMagicCarpet::init() {
// explicitly call the superclass's
// init method first
FGInterface::init();
common_init();
}

View file

@ -71,6 +71,14 @@ FGEngInterface::FGEngInterface() {
FGEngInterface::~FGEngInterface(void) {
}
FGGearInterface::FGGearInterface(void) {
x=y=z=0.0;
brake=rolls=WoW=false;
position=1.0;
}
FGGearInterface::~FGGearInterface() {
}
// Constructor
FGInterface::FGInterface() {
@ -167,49 +175,59 @@ FGInterface::_setup ()
altitude_agl=0;
}
void
FGInterface::init () {}
/**
* Initialize the state of the FDM.
*
* Subclasses of FGInterface may do their own, additional initialization,
* but normally they should invoke this method explicitly first as
* FGInterface::init() to make sure the basic structures are set up
* properly.
* but there is some that is common to all. Normally, they should call
* this before they begin their own init to make sure the basic structures
* are set up properly.
*/
void
FGInterface::init ()
FGInterface::common_init ()
{
SG_LOG(SG_FLIGHT, SG_INFO, "Start initializing FGInterface");
SG_LOG( SG_FLIGHT, SG_INFO, "Start common FDM init" );
inited = true;
set_inited( true );
stamp();
set_remainder( 0 );
// Set initial position
SG_LOG( SG_FLIGHT, SG_INFO, "...initializing position..." );
set_Longitude(fgGetDouble("/position/longitude-deg") * SGD_DEGREES_TO_RADIANS);
set_Latitude(fgGetDouble("/position/latitude-deg") * SGD_DEGREES_TO_RADIANS);
double ground_elev_m = scenery.get_cur_elev() + 1;
set_Longitude( fgGetDouble("/position/longitude-deg")
* SGD_DEGREES_TO_RADIANS );
set_Latitude( fgGetDouble("/position/latitude-deg")
* SGD_DEGREES_TO_RADIANS );
double ground_elev_m = scenery.get_cur_elev();
double ground_elev_ft = ground_elev_m * METERS_TO_FEET;
if (fgGetBool("/sim/startup/onground") ||
fgGetDouble("/position/altitude-ft") < ground_elev_ft)
if ( fgGetBool("/sim/startup/onground")
|| fgGetDouble("/position/altitude-ft") < ground_elev_ft ) {
fgSetDouble("/position/altitude-ft", ground_elev_ft);
}
set_Altitude( fgGetDouble("/position/altitude-ft") );
// Set ground elevation
SG_LOG( SG_FLIGHT, SG_INFO,
"...initializing ground elevation to "
<< ground_elev_ft << "ft...");
fgFDMSetGroundElevation("jsb", ground_elev_m);
"...initializing ground elevation to " << ground_elev_ft
<< "ft..." );
SG_LOG( SG_FLIGHT, SG_INFO, "common_init(): set ground elevation "
<< ground_elev_ft );
base_fdm_state.set_Runway_altitude( ground_elev_ft );
set_Runway_altitude( ground_elev_ft );
// Set sea-level radius
SG_LOG( SG_FLIGHT, SG_INFO, "...initializing sea-level radius..." );
SG_LOG(SG_FLIGHT, SG_INFO, " lat = " << fgGetDouble("/position/latitude-deg")
SG_LOG( SG_FLIGHT, SG_INFO, " lat = "
<< fgGetDouble("/position/latitude-deg")
<< " alt = " << fgGetDouble("/position/altitude-ft") );
double sea_level_radius_meters;
double lat_geoc;
sgGeodToGeoc(fgGetDouble("/position/latitude-deg") * SGD_DEGREES_TO_RADIANS,
sgGeodToGeoc( fgGetDouble("/position/latitude-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/position/altitude-ft") * SG_FEET_TO_METER,
&sea_level_radius_meters, &lat_geoc );
set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
@ -225,28 +243,33 @@ FGInterface::init ()
} else if ( speedset == "mach" || speedset == "MACH" ) {
set_Mach_number( fgGetDouble("/velocities/mach") );
} else if ( speedset == "UVW" || speedset == "uvw" ) {
set_Velocities_Wind_Body(fgGetDouble("/velocities/uBody-fps"),
set_Velocities_Wind_Body(
fgGetDouble("/velocities/uBody-fps"),
fgGetDouble("/velocities/vBody-fps"),
fgGetDouble("/velocities/wBody-fps") );
} else if ( speedset == "NED" || speedset == "ned" ) {
set_Velocities_Local(fgGetDouble("/velocities/speed-north-fps"),
set_Velocities_Local(
fgGetDouble("/velocities/speed-north-fps"),
fgGetDouble("/velocities/speed-east-fps"),
fgGetDouble("/velocities/speed-down-fps") );
} else {
SG_LOG( SG_FLIGHT, SG_ALERT,
"Unrecognized value for /sim/startup/speed-set: " << speedset);
"Unrecognized value for /sim/startup/speed-set: "
<< speedset);
set_V_calibrated_kts( 0.0 );
}
}
// Set initial Euler angles
SG_LOG( SG_FLIGHT, SG_INFO, "...initializing Euler angles..." );
set_Euler_Angles
(fgGetDouble("/orientation/roll-deg") * SGD_DEGREES_TO_RADIANS,
fgGetDouble("/orientation/pitch-deg") * SGD_DEGREES_TO_RADIANS,
fgGetDouble("/orientation/heading-deg") * SGD_DEGREES_TO_RADIANS);
set_Euler_Angles( fgGetDouble("/orientation/roll-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/orientation/pitch-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/orientation/heading-deg")
* SGD_DEGREES_TO_RADIANS );
SG_LOG(SG_FLIGHT, SG_INFO, "End initializing FGInterface");
SG_LOG( SG_FLIGHT, SG_INFO, "End common FDM init" );
}
@ -524,15 +547,6 @@ void fgFDMForceAltitude(const string &model, double alt_meters) {
}
// Set the local ground elevation
void fgFDMSetGroundElevation(const string &model, double ground_meters) {
SG_LOG( SG_FLIGHT,SG_INFO, "fgFDMSetGroundElevation: "
<< ground_meters*SG_METER_TO_FEET );
base_fdm_state.set_Runway_altitude( ground_meters * SG_METER_TO_FEET );
cur_fdm_state->set_Runway_altitude( ground_meters * SG_METER_TO_FEET );
}
// Positions
void FGInterface::set_Latitude(double lat) {
geodetic_position_v[0] = lat;
@ -723,4 +737,3 @@ void FGInterface::_busdump(void) {
void fgToggleFDMdataLogging(void) {
cur_fdm_state->ToggleDataLogging();
}

View file

@ -177,6 +177,43 @@ public:
typedef vector < FGEngInterface > engine_list;
class FGGearInterface {
private:
string name;
float x,y,z; // >0 forward of cg, >0 right, >0 down
bool brake; // true if this gear unit has a brake mechanism
bool rolls; // true if this gear unit has a wheel
bool WoW; // true if this gear unit is touching the ground
float position; // 0 if retracted, 1 if extended
public:
FGGearInterface(void);
~FGGearInterface(void);
inline string GetName(void) { return name; }
inline void SetName(string nm) { name=nm; }
inline float GetX(void) { return x; }
inline void SetX(float xloc) { x=xloc; }
inline float GetY(void) { return y; }
inline void SetY(float yloc) { y=yloc; }
inline float GetZ(void) { return z; }
inline void SetZ(float zloc) { z=zloc; }
inline bool GetBrake(void) { return brake; }
inline void SetBrake(bool brk) { brake=brk; }
// no good way to implement these right now
//inline bool GetRolls(void) { return rolls; }
//inline SetRolls(bool rl) { rolls=rl; }
inline bool GetWoW(void) { return WoW; }
inline void SetWoW(bool wow) { WoW=wow; }
inline float GetPosition(void) { return position; }
inline void SetPosition(float pos) { position=pos; }
};
typedef vector < FGGearInterface > gear_list;
// This is based heavily on LaRCsim/ls_generic.h
class FGInterface : public FGSubsystem {
@ -303,6 +340,9 @@ private:
// Engine list
engine_list engines;
//gear list
gear_list gear;
// SGTimeStamp valid_stamp; // time this record is valid
// SGTimeStamp next_stamp; // time this record is valid
@ -521,6 +561,9 @@ public:
inline bool get_bound() const { return bound; }
//perform initializion that is common to all FDM's
void common_init();
// time and update management values
inline double get_delta_t() const { return delta_t; }
inline void set_delta_t( double dt ) { delta_t = dt; }
@ -1179,6 +1222,19 @@ public:
inline void add_engine( FGEngInterface e ) {
engines.push_back( e );
}
//gear
inline int get_num_gear() const {
return gear.size();
}
inline FGGearInterface* get_gear_unit( int i ) {
return &gear[i];
}
inline void add_gear_unit( FGGearInterface fgi ) {
gear.push_back( fgi );
}
};
@ -1195,9 +1251,6 @@ extern FGInterface * cur_fdm_state;
// Set the altitude (force)
void fgFDMForceAltitude(const string &model, double alt_meters);
// Set the local ground elevation
void fgFDMSetGroundElevation(const string &model, double alt_meters);
// Toggle data logging on/off
void fgToggleFDMdataLogging(void);