// 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;
// 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;
fdmex = new FGFDMExec;
- State = fdmex->GetState();
- Atmosphere = fdmex->GetAtmosphere();
- FCS = fdmex->GetFCS();
- MassBalance = fdmex->GetMassBalance();
- Propulsion = fdmex->GetPropulsion();
- Aircraft = fdmex->GetAircraft();
- Translation = fdmex->GetTranslation();
- Rotation = fdmex->GetRotation();
- Position = fdmex->GetPosition();
- Auxiliary = fdmex->GetAuxiliary();
- Aerodynamics = fdmex->GetAerodynamics();
+ State = fdmex->GetState();
+ Atmosphere = fdmex->GetAtmosphere();
+ FCS = fdmex->GetFCS();
+ MassBalance = fdmex->GetMassBalance();
+ Propulsion = fdmex->GetPropulsion();
+ Aircraft = fdmex->GetAircraft();
+ Translation = fdmex->GetTranslation();
+ Rotation = fdmex->GetRotation();
+ Position = fdmex->GetPosition();
+ Auxiliary = fdmex->GetAuxiliary();
+ Aerodynamics = fdmex->GetAerodynamics();
+ GroundReactions = fdmex->GetGroundReactions();
+
Atmosphere->UseInternal();
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!");
}
+ init_gear();
+
fgSetDouble("/fdm/trim/pitch-trim", FCS->GetPitchTrimCmd());
fgSetDouble("/fdm/trim/throttle", FCS->GetThrottleCmd(0));
fgSetDouble("/fdm/trim/aileron", FCS->GetDaCmd());
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);
}
/******************************************************************************/
// 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
<< Auxiliary->GetVcalibratedKTS() << " knots" );
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: "
SG_LOG( SG_FLIGHT, SG_INFO, " set dt" );
SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" );
+
+
+
}
/******************************************************************************/
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);
- } else {
- fgtrim=new FGTrim(fdmex,fgic,tLongitudinal);
- }
- 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());
+ if ( needTrim ) {
+ if ( startup_trim->getBoolValue() ) {
+ do_trim();
+ } else {
+ fdmex->RunIC(fgic); //apply any changes made through the set_ functions
+ }
+ needTrim = false;
+ }
- SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
- }
-
for( i=0; i<get_num_engines(); i++ ) {
FGEngInterface * e = get_engine(i);
FGEngine * eng = Propulsion->GetEngine(i);
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() );
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;
}
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( Auxiliary->GetPilotAccel()(1),
+ Auxiliary->GetPilotAccel()(2),
+ Auxiliary->GetPilotAccel()(3) );
- //_set_Accels_Pilot_Body_N( Auxiliary->GetNpilot(1),
- // Auxiliary->GetNpilot(2),
- // Auxiliary->GetNpilot(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() );
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();
}
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 );
needTrim=true;
}
-
void FGJSBsim::set_Velocities_Local_Airmass (double wnorth,
double weast,
double wdown ) {
needTrim=true;
}
-
-//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;
-}
-
-void FGJSBsim::update_Longitude(double lon) {
-
- 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;
-}
-
-void FGJSBsim::update_Altitude(double alt) {
- double sea_level_radius_meters,lat_geoc;
-
- 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;
-}
-
-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;
-}
-
-void FGJSBsim::update_Mach_number(double mach) {
- SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Mach_number: " << mach );
-
- snap_shot();
- fgic->SetMachIC(mach);
- fdmex->RunIC(fgic); //loop JSBSim once
- copy_from_JSBsim(); //update the bus
- needTrim=true;
-}
-
-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::init_gear(void ) {
+
+ 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_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_gear(void) {
+
+ 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_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::do_trim(void) {
-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;
-}
-
+ FGTrim *fgtrim;
+ if(fgic->GetVcalibratedKtsIC() < 10 ) {
+ fgic->SetVcalibratedKtsIC(0.0);
+ fgtrim=new FGTrim(fdmex,fgic,tGround);
+ } else {
+ fgtrim=new FGTrim(fdmex,fgic,tLongitudinal);
+ }
+ 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_Density(double rho) {
- SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Density: " << rho );
-
- snap_shot();
- Atmosphere->SetExDensity(rho);
- if(Atmosphere->External() == true)
- needTrim=true;
-}
-
+ 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));
-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 );
+ globals->get_controls()->set_aileron(FCS->GetDaCmd());
+ globals->get_controls()->set_rudder( FCS->GetDrCmd());
- _set_Velocities_Local_Airmass( wnorth, weast, wdown );
- snap_shot();
- Atmosphere->SetWindNED(wnorth, weast, wdown );
- if(Atmosphere->External() == true)
- needTrim=true;
-}
-
+ SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
+}
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
bool update( int multiloop );
bool ToggleDataLogging(bool state);
bool ToggleDataLogging(void);
+ void do_trim(void);
private:
FGFDMExec *fdmex;
FGPosition* Position;
FGAuxiliary* Auxiliary;
FGAerodynamics* Aerodynamics;
+ FGGroundReactions *GroundReactions;
int runcount;
float trim_elev;
SGPropertyNode *throttle_trim;
SGPropertyNode *aileron_trim;
SGPropertyNode *rudder_trim;
+ SGPropertyNode *stall_warning;
+
+ void init_gear(void);
+ void update_gear(void);
- void snap_shot(void);
};
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;
}
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;
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); }
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 {
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;
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);
vXYZn(3),
vDXYZ(3),
mT(3,3),
+ vH(3),
vSense(3),
ttype(tNone)
{
- mT(1,1)=1; //identity matrix
- mT(2,2)=1;
- mT(3,3)=1;
+ mT(1,1) = 1; //identity matrix
+ mT(2,2) = 1;
+ mT(3,3) = 1;
vSense.InitMatrix(1);
if (debug_lvl & 2) cout << "Instantiated: FGForce" << endl;
}
FGColumnVector3& FGForce::GetBodyForces(void) {
- vFb=Transform()*(vFn.multElementWise(vSense));
+ vFb = Transform()*(vFn.multElementWise(vSense));
//find the distance from this vector's location to the cg
//needs to be done like this to convert from structural to body coords
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;
}
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; }
protected:
FGColumnVector3 vFn;
FGColumnVector3 vMn;
+ FGColumnVector3 vH;
FGFDMExec *fdmex;
virtual void Debug(void);
inline bool GetReport(void) { return ReportEnable; }
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;
string token;
int rows, cols;
- MaxPitch = MinPitch = 0.0;
+ MaxPitch = MinPitch = P_Factor = Sense = 0.0;
Name = Prop_cfg->GetValue("NAME");
Prop_cfg->GetNextConfigLine();
*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);
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;
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);
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;
float Diameter;
float MaxPitch;
float MinPitch;
+ float P_Factor;
+ float Sense;
float Pitch;
float Torque;
FGTable *Efficiency;
float PowerAvailable;
float currentThrust = 0, lastThrust=-1;
dt = State->Getdt();
+ int steady_count,j=0;
+ bool steady=false;
Forces->InitMatrix();
Moments->InitMatrix();
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
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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;
/** 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);
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",
FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex),
vUVW(3),
vUVWdot(3),
- vNcg(3),
vlastUVWdot(3),
mVel(3,3),
vAero(3)
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();
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); }
private:
FGColumnVector3 vUVW;
FGColumnVector3 vUVWdot;
- FGColumnVector3 vNcg;
FGColumnVector3 vlastUVWdot;
FGMatrix33 mVel;
FGColumnVector3 vAero;
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;
tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin();
tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax();
//cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value;
- fdmex -> GetFCS() -> SetThrottleCmd(i,tMin+control_value*(tMax-tMin));
+ 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();
}
}
// 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
}
// 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();
}
FGEngInterface::~FGEngInterface(void) {
}
+FGGearInterface::FGGearInterface(void) {
+ x=y=z=0.0;
+ brake=rolls=WoW=false;
+ position=1.0;
+}
+
+FGGearInterface::~FGGearInterface() {
+}
// Constructor
FGInterface::FGInterface() {
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");
-
- 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;
- double ground_elev_ft = ground_elev_m * METERS_TO_FEET;
- 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);
-
- // 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")
- << " alt = " << fgGetDouble("/position/altitude-ft") );
- double sea_level_radius_meters;
- double lat_geoc;
- 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);
-
- // Set initial velocities
- SG_LOG(SG_FLIGHT, SG_INFO, "...initializing velocities...");
- if (!fgHasNode("/sim/startup/speed-set")) {
- set_V_calibrated_kts(0.0);
- } else {
- const string speedset = fgGetString("/sim/startup/speed-set");
- if (speedset == "knots" || speedset == "KNOTS") {
- set_V_calibrated_kts(fgGetDouble("/velocities/airspeed-kt"));
- } 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"),
- fgGetDouble("/velocities/vBody-fps"),
- fgGetDouble("/velocities/wBody-fps"));
- } else if (speedset == "NED" || speedset == "ned") {
- set_Velocities_Local(fgGetDouble("/velocities/speed-north-fps"),
- fgGetDouble("/velocities/speed-east-fps"),
- fgGetDouble("/velocities/speed-down-fps"));
+ SG_LOG( SG_FLIGHT, SG_INFO, "Start common FDM init" );
+
+ 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();
+ double ground_elev_ft = ground_elev_m * METERS_TO_FEET;
+ 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..." );
+ 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")
+ << " alt = " << fgGetDouble("/position/altitude-ft") );
+ double sea_level_radius_meters;
+ double lat_geoc;
+ 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 );
+
+ // Set initial velocities
+ SG_LOG( SG_FLIGHT, SG_INFO, "...initializing velocities..." );
+ if ( !fgHasNode("/sim/startup/speed-set") ) {
+ set_V_calibrated_kts(0.0);
} else {
- SG_LOG(SG_FLIGHT, SG_ALERT,
- "Unrecognized value for /sim/startup/speed-set: " << speedset);
- set_V_calibrated_kts(0.0);
+ const string speedset = fgGetString("/sim/startup/speed-set");
+ if ( speedset == "knots" || speedset == "KNOTS" ) {
+ set_V_calibrated_kts( fgGetDouble("/velocities/airspeed-kt") );
+ } 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"),
+ fgGetDouble("/velocities/vBody-fps"),
+ fgGetDouble("/velocities/wBody-fps") );
+ } else if ( speedset == "NED" || speedset == "ned" ) {
+ 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);
+ 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 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 );
- SG_LOG(SG_FLIGHT, SG_INFO, "End initializing FGInterface");
+ SG_LOG( SG_FLIGHT, SG_INFO, "End common FDM init" );
}
}
-// 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;
void fgToggleFDMdataLogging(void) {
cur_fdm_state->ToggleDataLogging();
}
-
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 {
// 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
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; }
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 );
+ }
};
// 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);