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 // for each subsequent iteration through the EOM
void FGADA::init() { void FGADA::init() {
// explicitly call the superclass's //do init common to all FDM"s
// init() method first. common_init();
FGInterface::init();
//now do ADA-specific init.
// cout << "FGADA::init()" << endl; // cout << "FGADA::init()" << endl;

View file

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

View file

@ -77,6 +77,8 @@ FGJSBsim::FGJSBsim( double dt )
Position = fdmex->GetPosition(); Position = fdmex->GetPosition();
Auxiliary = fdmex->GetAuxiliary(); Auxiliary = fdmex->GetAuxiliary();
Aerodynamics = fdmex->GetAerodynamics(); Aerodynamics = fdmex->GetAerodynamics();
GroundReactions = fdmex->GetGroundReactions();
Atmosphere->UseInternal(); Atmosphere->UseInternal();
@ -113,9 +115,9 @@ FGJSBsim::FGJSBsim( double dt )
add_engine( FGEngInterface() ); add_engine( FGEngInterface() );
} }
if ( fdmex->GetGroundReactions()->GetNumGearUnits() <= 0 ) { if ( GroundReactions->GetNumGearUnits() <= 0 ) {
SG_LOG( SG_FLIGHT, SG_ALERT, "num gear units = " 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, "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, "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!"); 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/pitch-trim", FCS->GetPitchTrimCmd());
fgSetDouble("/fdm/trim/throttle", FCS->GetThrottleCmd(0)); fgSetDouble("/fdm/trim/throttle", FCS->GetThrottleCmd(0));
fgSetDouble("/fdm/trim/aileron", FCS->GetDaCmd()); fgSetDouble("/fdm/trim/aileron", FCS->GetDaCmd());
@ -137,6 +141,10 @@ FGJSBsim::FGJSBsim( double dt )
throttle_trim = fgGetNode("/fdm/trim/throttle", true ); throttle_trim = fgGetNode("/fdm/trim/throttle", true );
aileron_trim = fgGetNode("/fdm/trim/aileron", true ); aileron_trim = fgGetNode("/fdm/trim/aileron", true );
rudder_trim = fgGetNode("/fdm/trim/rudder", 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 // Explicitly call the superclass's
// init method first. // init method first.
FGInterface::init(); common_init();
fdmex->GetState()->Initialize(fgic); fdmex->GetState()->Initialize(fgic);
fdmex->RunIC(fgic); //loop JSBSim once w/o integrating fdmex->RunIC(fgic); //loop JSBSim once w/o integrating
@ -191,6 +199,8 @@ void FGJSBsim::init() {
break; break;
} }
stall_warning->setBoolValue(false);
SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: " SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: "
<< Rotation->Getphi()*RADTODEG << " deg" ); << Rotation->Getphi()*RADTODEG << " deg" );
SG_LOG( SG_FLIGHT, SG_INFO, " Pitch Angle: " 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, " set dt" );
SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" ); SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" );
} }
/******************************************************************************/ /******************************************************************************/
@ -224,43 +237,13 @@ bool FGJSBsim::update( int multiloop ) {
trimmed->setBoolValue(false); trimmed->setBoolValue(false);
if ( needTrim && startup_trim->getBoolValue() ) { if ( needTrim ) {
cout << "num gear units = " << fdmex->GetGroundReactions()->GetNumGearUnits() << endl; if ( startup_trim->getBoolValue() ) {
//fgic->SetSeaLevelRadiusFtIC( get_Sea_level_radius() ); do_trim();
//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 { } 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; 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++ ) { for( i=0; i<get_num_engines(); i++ ) {
@ -269,6 +252,18 @@ bool FGJSBsim::update( int multiloop ) {
FGThruster * thrust = Propulsion->GetThruster(i); FGThruster * thrust = Propulsion->GetThruster(i);
eng->SetMagnetos( globals->get_controls()->get_magnetos(i) ); eng->SetMagnetos( globals->get_controls()->get_magnetos(i) );
eng->SetStarter( globals->get_controls()->get_starter(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_Manifold_Pressure( eng->getManifoldPressure_inHg() );
e->set_RPM( thrust->GetRPM() ); e->set_RPM( thrust->GetRPM() );
e->set_EGT( eng->getExhaustGasTemp_degF() ); e->set_EGT( eng->getExhaustGasTemp_degF() );
@ -276,19 +271,15 @@ bool FGJSBsim::update( int multiloop ) {
e->set_Oil_Temp( eng->getOilTemp_degF() ); e->set_Oil_Temp( eng->getOilTemp_degF() );
e->set_Running_Flag( eng->GetRunning() ); e->set_Running_Flag( eng->GetRunning() );
e->set_Cranking_Flag( eng->GetCranking() ); 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); update_gear();
// printf("%d Altitude = %.2f\n", i, Altitude * 0.3048);
stall_warning->setDoubleValue( Aircraft->GetStallWarn() );
// translate JSBsim back to FG structure so that the // translate JSBsim back to FG structure so that the
// autopilot (and the rest of the sim can use the updated values // autopilot (and the rest of the sim can use the updated values
copy_from_JSBsim(); copy_from_JSBsim();
return true; return true;
} }
@ -350,25 +341,25 @@ bool FGJSBsim::copy_from_JSBsim() {
MassBalance->GetXYZcg(2), MassBalance->GetXYZcg(2),
MassBalance->GetXYZcg(3) ); MassBalance->GetXYZcg(3) );
_set_Accels_Body( Translation->GetUVWdot(1), _set_Accels_Body( Aircraft->GetBodyAccel()(1),
Translation->GetUVWdot(2), Aircraft->GetBodyAccel()(2),
Translation->GetUVWdot(3) ); Aircraft->GetBodyAccel()(3) );
_set_Accels_CG_Body( Translation->GetUVWdot(1), //_set_Accels_CG_Body( Aircraft->GetBodyAccel()(1),
Translation->GetUVWdot(2), // Aircraft->GetBodyAccel()(2),
Translation->GetUVWdot(3) ); // Aircraft->GetBodyAccel()(3) );
//_set_Accels_CG_Body_N ( Translation->GetNcg(1),
// Translation->GetNcg(2),
// Translation->GetNcg(3) );
// //
_set_Accels_Pilot_Body( Auxiliary->GetPilotAccel(1), _set_Accels_CG_Body_N ( Aircraft->GetNcg()(1),
Auxiliary->GetPilotAccel(2), Aircraft->GetNcg()(2),
Auxiliary->GetPilotAccel(3) ); Aircraft->GetNcg()(3) );
//_set_Accels_Pilot_Body_N( Auxiliary->GetNpilot(1), _set_Accels_Pilot_Body( Auxiliary->GetPilotAccel()(1),
// Auxiliary->GetNpilot(2), Auxiliary->GetPilotAccel()(2),
// Auxiliary->GetNpilot(3) ); 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() ); _set_Nlf( Aerodynamics->GetNlf() );
@ -437,19 +428,6 @@ bool FGJSBsim::copy_from_JSBsim() {
return true; 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) { bool FGJSBsim::ToggleDataLogging(void) {
return fdmex->GetOutput()->Toggle(); return fdmex->GetOutput()->Toggle();
} }
@ -484,6 +462,7 @@ void FGJSBsim::set_Latitude(double lat) {
sgGeodToGeoc( lat, alt * SG_FEET_TO_METER, sgGeodToGeoc( lat, alt * SG_FEET_TO_METER,
&sea_level_radius_meters, &lat_geoc ); &sea_level_radius_meters, &lat_geoc );
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); _set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc ); fgic->SetLatitudeRadIC( lat_geoc );
@ -617,7 +596,6 @@ void FGJSBsim::set_Density(double rho) {
needTrim=true; needTrim=true;
} }
void FGJSBsim::set_Velocities_Local_Airmass (double wnorth, void FGJSBsim::set_Velocities_Local_Airmass (double wnorth,
double weast, double weast,
double wdown ) { double wdown ) {
@ -630,194 +608,70 @@ void FGJSBsim::set_Velocities_Local_Airmass (double wnorth,
needTrim=true; needTrim=true;
} }
void FGJSBsim::init_gear(void ) {
//Positions FGGearInterface *gear;
void FGJSBsim::update_Latitude(double lat) { FGGroundReactions* gr=fdmex->GetGroundReactions();
double sea_level_radius_meters, lat_geoc; int Ngear=GroundReactions->GetNumGearUnits();
for (int i=0;i<Ngear;i++) {
SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::update_Latitude: " << lat ); add_gear_unit( FGGearInterface() );
SG_LOG(SG_FLIGHT,SG_INFO," cur alt = " << get_Altitude() ); gear=get_gear_unit(i);
gear->SetX( gr->GetGearUnit(i)->GetBodyLocation()(1) );
snap_shot(); gear->SetY( gr->GetGearUnit(i)->GetBodyLocation()(2) );
sgGeodToGeoc( lat, get_Altitude(), &sea_level_radius_meters, &lat_geoc); gear->SetZ( gr->GetGearUnit(i)->GetBodyLocation()(3) );
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); gear->SetWoW( gr->GetGearUnit(i)->GetWOW() );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); if ( gr->GetGearUnit(i)->GetBrakeGroup() > 0 ) {
fgic->SetLatitudeRadIC( lat_geoc ); gear->SetBrake(true);
fdmex->RunIC(fgic); //loop JSBSim once }
copy_from_JSBsim(); //update the bus if ( gr->GetGearUp() ) {
needTrim=true; 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 ); FGGearInterface* gear;
SG_LOG(SG_FLIGHT,SG_INFO," cur alt = " << get_Altitude() ); FGGroundReactions* gr=fdmex->GetGroundReactions();
int Ngear=GroundReactions->GetNumGearUnits();
snap_shot(); for (int i=0;i<Ngear;i++) {
fgic->SetLongitudeRadIC(lon); gear=get_gear_unit(i);
fdmex->RunIC(fgic); //loop JSBSim once gear->SetWoW( gr->GetGearUnit(i)->GetWOW() );
copy_from_JSBsim(); //update the bus if ( gr->GetGearUp() ) {
needTrim=true; gear->SetPosition( 0.0 );
}
}
} }
void FGJSBsim::update_Altitude(double alt) { void FGJSBsim::do_trim(void) {
double sea_level_radius_meters,lat_geoc;
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Altitude: " << alt ); FGTrim *fgtrim;
if(fgic->GetVcalibratedKtsIC() < 10 ) {
snap_shot(); fgic->SetVcalibratedKtsIC(0.0);
sgGeodToGeoc( get_Latitude(), alt , &sea_level_radius_meters, &lat_geoc); fgtrim=new FGTrim(fdmex,fgic,tGround);
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); } else {
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); fgtrim=new FGTrim(fdmex,fgic,tLongitudinal);
fgic->SetLatitudeRadIC( lat_geoc );
fgic->SetAltitudeFtIC(alt);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=true;
} }
if( !fgtrim->DoTrim() ) {
void FGJSBsim::update_V_calibrated_kts(double vc) { fgtrim->Report();
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_V_calibrated_kts: " << vc ); fgtrim->TrimStats();
} else {
snap_shot(); trimmed->setBoolValue(true);
fgic->SetVcalibratedKtsIC(vc);
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus
needTrim=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) { globals->get_controls()->set_elevator_trim(FCS->GetPitchTrimCmd());
SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::update_Mach_number: " << mach ); globals->get_controls()->set_elevator(FCS->GetDeCmd());
globals->get_controls()->set_throttle(FGControls::ALL_ENGINES,
FCS->GetThrottleCmd(0));
snap_shot(); globals->get_controls()->set_aileron(FCS->GetDaCmd());
fgic->SetMachIC(mach); globals->get_controls()->set_rudder( FCS->GetDrCmd());
fdmex->RunIC(fgic); //loop JSBSim once
copy_from_JSBsim(); //update the bus SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
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::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 ); double wdown );
/// @name Position Parameter Update /// @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. /** Update the position based on inputs, positions, velocities, etc.
@param multiloop number of times to loop through the FDM @param multiloop number of times to loop through the FDM
@ -309,6 +215,7 @@ public:
bool update( int multiloop ); bool update( int multiloop );
bool ToggleDataLogging(bool state); bool ToggleDataLogging(bool state);
bool ToggleDataLogging(void); bool ToggleDataLogging(void);
void do_trim(void);
private: private:
FGFDMExec *fdmex; FGFDMExec *fdmex;
@ -326,6 +233,7 @@ private:
FGPosition* Position; FGPosition* Position;
FGAuxiliary* Auxiliary; FGAuxiliary* Auxiliary;
FGAerodynamics* Aerodynamics; FGAerodynamics* Aerodynamics;
FGGroundReactions *GroundReactions;
int runcount; int runcount;
float trim_elev; float trim_elev;
@ -337,8 +245,11 @@ private:
SGPropertyNode *throttle_trim; SGPropertyNode *throttle_trim;
SGPropertyNode *aileron_trim; SGPropertyNode *aileron_trim;
SGPropertyNode *rudder_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), vXYZrp(3),
vXYZep(3), vXYZep(3),
vDXYZcg(3), vDXYZcg(3),
vBodyAccel(3) vBodyAccel(3),
vNcg(3)
{ {
Name = "FGAircraft"; Name = "FGAircraft";
alphaclmin = alphaclmax = 0; alphaclmin = alphaclmax = 0;
HTailArea = VTailArea = HTailArm = VTailArm = 0.0; HTailArea = VTailArea = HTailArm = VTailArm = 0.0;
lbarh = lbarv = vbarh = vbarv = 0.0; lbarh = lbarv = vbarh = vbarv = 0.0;
WingIncidence=0; WingIncidence=0;
impending_stall = 0;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} }
@ -176,6 +178,16 @@ bool FGAircraft::Run(void)
vBodyAccel = vForces/MassBalance->GetMass(); 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; return false;
} else { // skip Run() execution this time } else { // skip Run() execution this time
return true; return true;

View file

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

View file

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

View file

@ -63,6 +63,7 @@ FGForce::FGForce(FGFDMExec *FDMExec) :
vXYZn(3), vXYZn(3),
vDXYZ(3), vDXYZ(3),
mT(3,3), mT(3,3),
vH(3),
vSense(3), vSense(3),
ttype(tNone) 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(2) = (vXYZn(2) - fdmex->GetMassBalance()->GetXYZcg(2))*INCHTOFT; //cg and rp values are in inches
vDXYZ(3) = -(vXYZn(3) - fdmex->GetMassBalance()->GetXYZcg(3))*INCHTOFT; 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; return vFb;
} }

View file

@ -256,6 +256,9 @@ public:
vXYZn(2) = y; vXYZn(2) = y;
vXYZn(3) = z; 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; } inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; }
FGColumnVector3& GetLocation(void) { return vXYZn; } FGColumnVector3& GetLocation(void) { return vXYZn; }
@ -282,6 +285,7 @@ public:
protected: protected:
FGColumnVector3 vFn; FGColumnVector3 vFn;
FGColumnVector3 vMn; FGColumnVector3 vMn;
FGColumnVector3 vH;
FGFDMExec *fdmex; FGFDMExec *fdmex;
virtual void Debug(void); virtual void Debug(void);

View file

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

View file

@ -50,7 +50,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
string token; string token;
int rows, cols; int rows, cols;
MaxPitch = MinPitch = 0.0; MaxPitch = MinPitch = P_Factor = Sense = 0.0;
Name = Prop_cfg->GetValue("NAME"); Name = Prop_cfg->GetValue("NAME");
Prop_cfg->GetNextConfigLine(); Prop_cfg->GetNextConfigLine();
@ -67,6 +67,10 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
*Prop_cfg >> MinPitch; *Prop_cfg >> MinPitch;
} else if (token == "MAXPITCH") { } else if (token == "MAXPITCH") {
*Prop_cfg >> MaxPitch; *Prop_cfg >> MaxPitch;
} else if (token == "P_FACTOR") {
*Prop_cfg >> P_Factor;
} else if (token == "SENSE") {
*Prop_cfg >> Sense;
} else if (token == "EFFICIENCY") { } else if (token == "EFFICIENCY") {
*Prop_cfg >> rows >> cols; *Prop_cfg >> rows >> cols;
if (cols == 1) Efficiency = new FGTable(rows); 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 << " Number of Blades = " << numBlades << endl;
cout << " Minimum Pitch = " << MinPitch << endl; cout << " Minimum Pitch = " << MinPitch << endl;
cout << " Maximum Pitch = " << MaxPitch << 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; cout << " Efficiency: " << endl;
Efficiency->Print(); Efficiency->Print();
cout << " Thrust Coefficient: " << endl; cout << " Thrust Coefficient: " << endl;
@ -141,6 +153,7 @@ float FGPropeller::Calculate(float PowerAvailable)
float Vel = (fdmex->GetTranslation()->GetvAero())(1); float Vel = (fdmex->GetTranslation()->GetvAero())(1);
float rho = fdmex->GetAtmosphere()->GetDensity(); float rho = fdmex->GetAtmosphere()->GetDensity();
float RPS = RPM/60.0; float RPS = RPM/60.0;
float alpha, beta;
if (RPM > 0.10) { if (RPM > 0.10) {
J = Vel / (Diameter * RPM / 60.0); J = Vel / (Diameter * RPM / 60.0);
@ -154,10 +167,25 @@ float FGPropeller::Calculate(float PowerAvailable)
C_Thrust = cThrust->GetValue(J, Pitch); 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; Thrust = C_Thrust*RPS*RPS*Diameter*Diameter*Diameter*Diameter*rho;
vFn(1) = Thrust; vFn(1) = Thrust;
omega = RPS*2.0*M_PI; 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; if (omega <= 5) omega = 1.0;
Torque = PowerAvailable / omega; Torque = PowerAvailable / omega;

View file

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

View file

@ -115,6 +115,8 @@ bool FGPropulsion::GetSteadyState(void) {
float PowerAvailable; float PowerAvailable;
float currentThrust = 0, lastThrust=-1; float currentThrust = 0, lastThrust=-1;
dt = State->Getdt(); dt = State->Getdt();
int steady_count,j=0;
bool steady=false;
Forces->InitMatrix(); Forces->InitMatrix();
Moments->InitMatrix(); Moments->InitMatrix();
@ -123,10 +125,18 @@ bool FGPropulsion::GetSteadyState(void) {
for (unsigned int i=0; i<numEngines; i++) { for (unsigned int i=0; i<numEngines; i++) {
Engines[i]->SetTrimMode(true); Engines[i]->SetTrimMode(true);
Thrusters[i]->SetdeltaT(dt*rate); 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()); PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
lastThrust = currentThrust; lastThrust = currentThrust;
currentThrust = Thrusters[i]->Calculate(PowerAvailable); 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 *Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces
*Moments += Thrusters[i]->GetMoments(); // sum body frame moments *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) bool FGPropulsion::Load(FGConfigFile* AC_cfg)
{ {
string token, fullpath; string token, fullpath;

View file

@ -158,8 +158,13 @@ public:
/** Returns the number of oxidizer tanks currently actively supplying oxidizer */ /** Returns the number of oxidizer tanks currently actively supplying oxidizer */
inline int GetnumSelectedOxiTanks(void) {return numSelectedOxiTanks;} inline int GetnumSelectedOxiTanks(void) {return numSelectedOxiTanks;}
/** Loops the engines/thrusters until thrust output steady (used for trimming) */
bool GetSteadyState(void); 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 GetPropulsionStrings(void);
string GetPropulsionValues(void); string GetPropulsionValues(void);

View file

@ -739,7 +739,7 @@ void FGState::ReportState(void) {
GetParameter(FG_RUDDER_POS)*RADTODEG ); GetParameter(FG_RUDDER_POS)*RADTODEG );
cout << out; cout << out;
snprintf(out,80, " Throttle: %5.2f%c\n", snprintf(out,80, " Throttle: %5.2f%c\n",
FCS->GetThrottlePos(0),'%' ); FCS->GetThrottlePos(0)*100,'%' );
cout << out; cout << out;
snprintf(out,80, " Wind Components: %5.2f kts head wind, %5.2f kts cross wind\n", 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), FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex),
vUVW(3), vUVW(3),
vUVWdot(3), vUVWdot(3),
vNcg(3),
vlastUVWdot(3), vlastUVWdot(3),
mVel(3,3), mVel(3,3),
vAero(3) vAero(3)
@ -120,9 +119,7 @@ bool FGTranslation::Run(void)
mVel(3,2) = vUVW(eU); mVel(3,2) = vUVW(eU);
mVel(3,3) = 0.0; mVel(3,3) = 0.0;
vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetForces()/MassBalance->GetMass(); vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetBodyAccel();
vNcg = vUVWdot*INVGRAVITY;
vUVW += Tc * (vlastUVWdot + vUVWdot); vUVW += Tc * (vlastUVWdot + vUVWdot);
vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED(); vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED();

View file

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

View file

@ -150,9 +150,9 @@ FGTrimAxis::~FGTrimAxis()
void FGTrimAxis::getState(void) { void FGTrimAxis::getState(void) {
switch(state) { switch(state) {
case tUdot: state_value=fdmex->GetTranslation()->GetUVWdot(1); break; case tUdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(1); break;
case tVdot: state_value=fdmex->GetTranslation()->GetUVWdot(2); break; case tVdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(2); break;
case tWdot: state_value=fdmex->GetTranslation()->GetUVWdot(3); break; case tWdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(3); break;
case tQdot: state_value=fdmex->GetRotation()->GetPQRdot(2);break; case tQdot: state_value=fdmex->GetRotation()->GetPQRdot(2);break;
case tPdot: state_value=fdmex->GetRotation()->GetPQRdot(1); break; case tPdot: state_value=fdmex->GetRotation()->GetPQRdot(1); break;
case tRdot: state_value=fdmex->GetRotation()->GetPQRdot(3); break; case tRdot: state_value=fdmex->GetRotation()->GetPQRdot(3); break;
@ -398,6 +398,9 @@ void FGTrimAxis::setThrottlesPct(void) {
tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax();
//cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; //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();
} }
} }

View file

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

View file

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

View file

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

View file

@ -177,6 +177,43 @@ public:
typedef vector < FGEngInterface > engine_list; 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 // This is based heavily on LaRCsim/ls_generic.h
class FGInterface : public FGSubsystem { class FGInterface : public FGSubsystem {
@ -303,6 +340,9 @@ private:
// Engine list // Engine list
engine_list engines; engine_list engines;
//gear list
gear_list gear;
// SGTimeStamp valid_stamp; // time this record is valid // SGTimeStamp valid_stamp; // time this record is valid
// SGTimeStamp next_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; } inline bool get_bound() const { return bound; }
//perform initializion that is common to all FDM's
void common_init();
// time and update management values // time and update management values
inline double get_delta_t() const { return delta_t; } inline double get_delta_t() const { return delta_t; }
inline void set_delta_t( double dt ) { delta_t = dt; } inline void set_delta_t( double dt ) { delta_t = dt; }
@ -1179,6 +1222,19 @@ public:
inline void add_engine( FGEngInterface e ) { inline void add_engine( FGEngInterface e ) {
engines.push_back( 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) // Set the altitude (force)
void fgFDMForceAltitude(const string &model, double alt_meters); 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 // Toggle data logging on/off
void fgToggleFDMdataLogging(void); void fgToggleFDMdataLogging(void);