#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx>
+#include <simgear/structure/commands.hxx>
#include <FDM/flight.hxx>
#include <Aircraft/aircraft.hxx>
-#include <Controls/controls.hxx>
+#include <Aircraft/controls.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <FDM/JSBSim/FGPropertyManager.h>
#include <FDM/JSBSim/FGEngine.h>
#include <FDM/JSBSim/FGPiston.h>
+#include <FDM/JSBSim/FGGroundCallback.h>
#include <FDM/JSBSim/FGTurbine.h>
#include <FDM/JSBSim/FGRocket.h>
#include <FDM/JSBSim/FGElectric.h>
return a > b ? a : b;
}
+class FGFSGroundCallback : public FGGroundCallback {
+public:
+ FGFSGroundCallback(FGInterface* ifc) : mInterface(ifc) {}
+ virtual ~FGFSGroundCallback() {}
+
+ /** Get the altitude above sea level depenent on the location. */
+ virtual double GetAltitude(const FGLocation& l) const {
+ double pt[3] = { SG_FEET_TO_METER*l(eX),
+ SG_FEET_TO_METER*l(eY),
+ SG_FEET_TO_METER*l(eZ) };
+ double lat, lon, alt;
+ sgCartToGeod( pt, &lat, &lon, &alt);
+ return alt * SG_METER_TO_FEET;
+ }
+
+ /** Compute the altitude above ground. */
+ virtual double GetAGLevel(double t, const FGLocation& l,
+ FGLocation& cont,
+ FGColumnVector3& n, FGColumnVector3& v) const {
+ double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+ double contact[3], normal[3], vel[3], lc, ff, agl;
+ int groundtype;
+ mInterface->get_agl_ft(t, loc_cart, contact, normal, vel,
+ &groundtype, &lc, &ff, &agl);
+ n = l.GetTec2l()*FGColumnVector3( normal[0], normal[1], normal[2] );
+ v = l.GetTec2l()*FGColumnVector3( vel[0], vel[1], vel[2] );
+ cont = FGColumnVector3( contact[0], contact[1], contact[2] );
+ return agl;
+ }
+private:
+ FGInterface* mInterface;
+};
/******************************************************************************/
: FGInterface(dt)
{
bool result;
-
// Set up the debugging level
// FIXME: this will not respond to
// runtime changes
}
}
+ reset_on_crash = fgGetBool("/sim/reset-on-crash", false);
+ crashed = false;
+ fgSetBool("/sim/crashed", false);
+
fdmex = new FGFDMExec( (FGPropertyManager*)globals->get_props() );
+ // Register ground callback.
+ fdmex->SetGroundCallback( new FGFSGroundCallback(this) );
+
State = fdmex->GetState();
Atmosphere = fdmex->GetAtmosphere();
FCS = fdmex->GetFCS();
}
}
Propulsion->SetFuelFreeze((fgGetNode("/sim/freeze/fuel",true))->getBoolValue());
-
+
fgSetDouble("/fdm/trim/pitch-trim", FCS->GetPitchTrimCmd());
fgSetDouble("/fdm/trim/throttle", FCS->GetThrottleCmd(0));
fgSetDouble("/fdm/trim/aileron", FCS->GetDaCmd());
<< ", " << fdmex->GetAtmosphere()->GetPressure()
<< ", " << fdmex->GetAtmosphere()->GetDensity() );
+ if (fgGetBool("/sim/presets/running")) {
+ for (int i=0; i < Propulsion->GetNumEngines(); i++) {
+ SGPropertyNode * node = fgGetNode("engines/engine", i, true);
+ node->setBoolValue("running", true);
+ Propulsion->GetEngine(i)->SetRunning(true);
+ }
+ }
+
common_init();
copy_to_JSBsim();
int i;
- // double save_alt = 0.0;
+ // Compute the radius of the aircraft. That is the radius of a ball
+ // where all gear units are in. At the moment it is at least 10ft ...
+ double acrad = 10.0;
+ int n_gears = GroundReactions->GetNumGearUnits();
+ for (i=0; i<n_gears; ++i) {
+ FGColumnVector3 bl = GroundReactions->GetGearUnit(i)->GetBodyLocation();
+ double r = bl.Magnitude();
+ if (acrad < r)
+ acrad = r;
+ }
+
+ // Compute the potential movement of this aircraft and query for the
+ // ground in this area.
+ double groundCacheRadius = acrad + 2*dt*Propagate->GetUVW().Magnitude();
+ double alt, slr, lat, lon;
+ FGColumnVector3 cart = Auxiliary->GetLocationVRP();
+ if ( needTrim && startup_trim->getBoolValue() ) {
+ alt = fgic->GetAltitudeFtIC();
+ slr = fgic->GetSeaLevelRadiusFtIC();
+ lat = fgic->GetLatitudeDegIC() * SGD_DEGREES_TO_RADIANS;
+ lon = fgic->GetLongitudeDegIC() * SGD_DEGREES_TO_RADIANS;
+ cart = FGLocation(lon, lat, alt+slr);
+ }
+ double cart_pos[3] = { cart(1), cart(2), cart(3) };
+ bool cache_ok = prepare_ground_cache_ft( State->Getsim_time(), cart_pos,
+ groundCacheRadius );
+ if (!cache_ok) {
+ SG_LOG(SG_FLIGHT, SG_WARN,
+ "FGInterface is being called without scenery below the aircraft!");
+ cout << "altitude = " << alt << endl;
+ cout << "sea level radius = " << slr << endl;
+ cout << "latitude = " << lat << endl;
+ cout << "longitude = " << lon << endl;
+ //return;
+ }
copy_to_JSBsim();
if ( needTrim ) {
if ( startup_trim->getBoolValue() ) {
+ double contact[3], dummy[3], lc, ff, agl;
+ int groundtype;
+ get_agl_ft(State->Getsim_time(), cart_pos, contact,
+ dummy, dummy, &groundtype, &lc, &ff, &agl);
+ double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1]
+ + contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC();
+
SG_LOG(SG_FLIGHT, SG_INFO,
"Ready to trim, terrain altitude is: "
- << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET );
- fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() );
+ << terrain_alt * SG_METER_TO_FEET );
+
+ fgic->SetTerrainAltitudeFtIC( terrain_alt );
do_trim();
} else {
fdmex->RunIC(); //apply any changes made through the set_ functions
// translate JSBsim back to FG structure so that the
// autopilot (and the rest of the sim can use the updated values
copy_from_JSBsim();
+
+ // crashed (altitude AGL < 0)
+ if (get_Altitude_AGL() < 0.0) {
+ crash_message = "Attempted to fly under ground.";
+ crash_handler();
+ }
}
/******************************************************************************/
} // end FGEngine code block
}
-
- _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() );
+
Propagate->SetSeaLevelRadius( get_Sea_level_radius() );
- Propagate->SetRunwayRadius( get_Runway_altitude()
- + get_Sea_level_radius() );
Atmosphere->SetExTemperature(
9.0/5.0*(temperature->getDoubleValue()+273.15) );
SGPropertyNode* node = fgGetNode("/systems/refuel", true);
Propulsion->SetRefuel(node->getDoubleValue("contact"));
Propulsion->SetFuelFreeze((fgGetNode("/sim/freeze/fuel",true))->getBoolValue());
-
+
return true;
}
_set_Mach_number( Auxiliary->GetMach() );
// Positions of Visual Reference Point
- _updateGeocentricPosition( Auxiliary->GetLocationVRP().GetLatitude(),
- Auxiliary->GetLocationVRP().GetLongitude(),
- Auxiliary->GethVRP() );
+ FGLocation l = Auxiliary->GetLocationVRP();
+ _updateGeocentricPosition( l.GetLatitude(), l.GetLongitude(),
+ l.GetRadius() - get_Sea_level_radius() );
_set_Altitude_AGL( Propagate->GetDistanceAGL() );
+ {
+ double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+ double contact[3], d[3], sd, t;
+ int id;
+ is_valid_m(&t, d, &sd);
+ get_agl_ft(t, loc_cart, contact, d, d, &id, &sd, &sd, &sd);
+ double rwrad
+ = FGColumnVector3( contact[0], contact[1], contact[2] ).Magnitude();
+ _set_Runway_altitude( rwrad - get_Sea_level_radius() );
+ }
_set_Euler_Angles( Propagate->GetEuler(ePhi),
Propagate->GetEuler(eTht),
&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 );
- _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() );
- fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() );
fgic->SetLatitudeRadIC( lat_geoc );
needTrim=true;
}
update_ic();
fgic->SetLongitudeRadIC( lon );
- _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() );
- fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() );
needTrim=true;
}
&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 );
- _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() );
- fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() );
SG_LOG(SG_FLIGHT, SG_INFO,
"Terrain altitude: " << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc );
node->setBoolValue("has-brake", gear->GetBrakeGroup() > 0);
node->setDoubleValue("position-norm", FCS->GetGearPos());
node->setDoubleValue("tire-pressure-norm", gear->GetTirePressure());
+ node->setDoubleValue("compression-norm", gear->GetCompLen());
if ( gear->GetSteerable() )
node->setDoubleValue("steering-norm", gear->GetSteerNorm());
}
node->getChild("wow", 0, true)->setBoolValue( gear->GetWOW());
node->getChild("position-norm", 0, true)->setDoubleValue(FCS->GetGearPos());
gear->SetTirePressure(node->getDoubleValue("tire-pressure-norm"));
+ node->setDoubleValue("compression-norm", gear->GetCompLen());
if ( gear->GetSteerable() )
node->setDoubleValue("steering-norm", gear->GetSteerNorm());
}
}
}
+void FGJSBsim::crash_handler(void)
+{
+ if (crashed) return; // we already crashed
+ crashed = true;
+ fgSetBool("/sim/crashed", true);
+ SG_LOG( SG_FLIGHT, SG_WARN, " Crash: " << crash_message );
+ if (reset_on_crash) {
+ SGPropertyNode* node = fgGetNode("/sim/presets", true);
+ globals->get_commands()->execute("old-reinit-dialog", node);
+ } else {
+ fgSetBool("/sim/freeze/master", true);
+ fgSetBool("/sim/freeze/clock", true);
+ }
+}