+#include <FDM/JSBSim/FGFDMExec.h>
+#include <FDM/JSBSim/FGJSBBase.h>
+#include <FDM/JSBSim/initialization/FGInitialCondition.h>
+#include <FDM/JSBSim/initialization/FGTrim.h>
+#include <FDM/JSBSim/models/FGModel.h>
+#include <FDM/JSBSim/models/FGAircraft.h>
+#include <FDM/JSBSim/models/FGFCS.h>
+#include <FDM/JSBSim/models/FGPropagate.h>
+#include <FDM/JSBSim/models/FGAuxiliary.h>
+#include <FDM/JSBSim/models/FGInertial.h>
+#include <FDM/JSBSim/models/FGAtmosphere.h>
+#include <FDM/JSBSim/models/FGMassBalance.h>
+#include <FDM/JSBSim/models/FGAerodynamics.h>
+#include <FDM/JSBSim/models/FGLGear.h>
+#include <FDM/JSBSim/models/FGGroundReactions.h>
+#include <FDM/JSBSim/models/FGPropulsion.h>
+#include <FDM/JSBSim/models/FGAccelerations.h>
+#include <FDM/JSBSim/models/atmosphere/FGWinds.h>
+#include <FDM/JSBSim/models/propulsion/FGEngine.h>
+#include <FDM/JSBSim/models/propulsion/FGPiston.h>
+#include <FDM/JSBSim/models/propulsion/FGTurbine.h>
+#include <FDM/JSBSim/models/propulsion/FGTurboProp.h>
+#include <FDM/JSBSim/models/propulsion/FGRocket.h>
+#include <FDM/JSBSim/models/propulsion/FGElectric.h>
+#include <FDM/JSBSim/models/propulsion/FGNozzle.h>
+#include <FDM/JSBSim/models/propulsion/FGPropeller.h>
+#include <FDM/JSBSim/models/propulsion/FGRotor.h>
+#include <FDM/JSBSim/models/propulsion/FGTank.h>
+#include <FDM/JSBSim/input_output/FGPropertyManager.h>
+#include <FDM/JSBSim/input_output/FGGroundCallback.h>
+
+using namespace JSBSim;
+
+static inline double
+FMAX (double a, double b)
+{
+ return a > b ? a : b;
+}
+
+class FGFSGroundCallback : public FGGroundCallback {
+public:
+ FGFSGroundCallback(FGJSBsim* ifc) : mInterface(ifc) {}
+ virtual ~FGFSGroundCallback() {}
+
+ /** Get the altitude above sea level dependent 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, FGColumnVector3& w) const {
+ double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+ double contact[3], normal[3], vel[3], angularVel[3], agl = 0;
+ mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
+ vel, angularVel, &agl);
+ n = FGColumnVector3( normal[0], normal[1], normal[2] );
+ v = FGColumnVector3( vel[0], vel[1], vel[2] );
+ w = FGColumnVector3( angularVel[0], angularVel[1], angularVel[2] );
+ cont = FGColumnVector3( contact[0], contact[1], contact[2] );
+ return agl;
+ }
+
+ virtual double GetTerrainGeoCentRadius(double t, const FGLocation& l) const {
+ double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+ double contact[3], normal[3], vel[3], angularVel[3], agl = 0;
+ mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
+ vel, angularVel, &agl);
+ return sqrt(contact[0]*contact[0]+contact[1]*contact[1]+contact[2]*contact[2]);
+ }
+
+ virtual double GetSeaLevelRadius(const FGLocation& l) const {
+ double seaLevelRadius, latGeoc;
+
+ sgGeodToGeoc(l.GetGeodLatitudeRad(), l.GetGeodAltitude(),
+ &seaLevelRadius, &latGeoc);
+
+ return seaLevelRadius * SG_METER_TO_FEET;
+ }
+
+ virtual void SetTerrainGeoCentRadius(double radius) {}
+ virtual void SetSeaLevelRadius(double radius) {}
+private:
+ FGJSBsim* mInterface;
+};
+
+// FG uses a squared normalized magnitude for turbulence
+// this lookup table maps fg's severity levels
+// none(0), light(1/3), moderate(2/3) and severe(3/3)
+// to the POE table indexes 0, 3, 4 and 7
+class FGTurbulenceSeverityTable : public FGTable {
+public:
+ FGTurbulenceSeverityTable() : FGTable(4) {
+ *this << (0.0/9.0) << 0.0;
+ *this << (1.0/9.0) << 3.0;
+ *this << (4.0/9.0) << 4.0;
+ *this << (9.0/9.0) << 7.0;
+ }
+};