]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim.cxx
Sync with latest JSBSim CVS.
[flightgear.git] / src / FDM / JSBSim.cxx
index 4ec1faf70148900217d3ce28a0d13dc7818fa8cc..ee28d6a633c53033708ee134625f50f607541532 100644 (file)
@@ -49,7 +49,6 @@
 #include <FDM/JSBSim/FGState.h>
 #include <FDM/JSBSim/FGTranslation.h>
 #include <FDM/JSBSim/FGAuxiliary.h>
-#include <FDM/JSBSim/FGDefs.h>
 #include <FDM/JSBSim/FGInitialCondition.h>
 #include <FDM/JSBSim/FGTrim.h>
 #include <FDM/JSBSim/FGAtmosphere.h>
@@ -64,19 +63,21 @@ FGJSBsim::FGJSBsim( double dt )
 {
     bool result;
    
-    fdmex=new FGFDMExec;
+    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();
     
@@ -95,7 +96,6 @@ FGJSBsim::FGJSBsim( double dt )
                                engine_path.str(),
                                fgGetString("/sim/aircraft") );
     
-
     if (result) {
       SG_LOG( SG_FLIGHT, SG_INFO, "  loaded aircraft.");
     } else {
@@ -104,13 +104,28 @@ FGJSBsim::FGJSBsim( double dt )
       throw(-1);
     }
 
+    SG_LOG( SG_FLIGHT, SG_INFO, "" );
+    SG_LOG( SG_FLIGHT, SG_INFO, "" );
+    SG_LOG( SG_FLIGHT, SG_INFO, "After loading aircraft definition file ..." );
+
     int Neng = Propulsion->GetNumEngines();
-    SG_LOG(SG_FLIGHT,SG_INFO, "Neng: " << Neng );
-    
+    SG_LOG( SG_FLIGHT, SG_INFO, "num engines = " << Neng );
     for(int i=0;i<Neng;i++) {
         add_engine( FGEngInterface() );
     }  
     
+    if ( GroundReactions->GetNumGearUnits() <= 0 ) {
+        SG_LOG( SG_FLIGHT, SG_ALERT, "num gear units = "
+                << 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!");
+         exit(-1);
+    }
+        
+    
+    init_gear();
+    
     fgSetDouble("/fdm/trim/pitch-trim", FCS->GetPitchTrimCmd());
     fgSetDouble("/fdm/trim/throttle",   FCS->GetThrottleCmd(0));
     fgSetDouble("/fdm/trim/aileron",    FCS->GetDaCmd());
@@ -125,6 +140,10 @@ FGJSBsim::FGJSBsim( double dt )
     throttle_trim = fgGetNode("/fdm/trim/throttle", true );
     aileron_trim = fgGetNode("/fdm/trim/aileron", true );
     rudder_trim = fgGetNode("/fdm/trim/rudder", true );
+    
+    
+    stall_warning = fgGetNode("/sim/aircraft/alarms/stall-warning",true);
+    stall_warning->setDoubleValue(0);
 }
 
 /******************************************************************************/
@@ -146,9 +165,14 @@ void FGJSBsim::init() {
    
     // Explicitly call the superclass's
     // init method first.
-    FGInterface::init();
+    common_init();
+
+    fdmex->GetState()->Initialize(fgic);
+    fdmex->RunIC(fgic); //loop JSBSim once w/o integrating
+    // fdmex->Run();       //loop JSBSim once
+    copy_from_JSBsim(); //update the bus
 
-    SG_LOG( SG_FLIGHT, SG_INFO, "  Initializing JSBSim with:" );
+    SG_LOG( SG_FLIGHT, SG_INFO, "  Initialized JSBSim with:" );
 
     switch(fgic->GetSpeedSet()) {
     case setned:
@@ -173,23 +197,29 @@ void FGJSBsim::init() {
                << Auxiliary->GetVcalibratedKTS() << " knots" );
     break;
     }
-
+    
+    stall_warning->setBoolValue(false);
+    
     SG_LOG( SG_FLIGHT, SG_INFO, "  Bank Angle: "
-            <<  Rotation->Getphi()*RADTODEG << " deg");
+            <<  Rotation->Getphi()*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Pitch Angle: "
-            << Rotation->Gettht()*RADTODEG << " deg"  );
+            << Rotation->Gettht()*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  True Heading: "
-            << Rotation->Getpsi()*RADTODEG << " deg"  );
+            << Rotation->Getpsi()*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Latitude: "
-            <<  Position->GetLatitude() << " deg" );
+            << Position->GetLatitude() << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Longitude: "
-            <<  Position->GetLongitude() << " deg"  );
-
+            << Position->GetLongitude() << " deg" );
+    SG_LOG( SG_FLIGHT, SG_INFO, "  Altitude: "
+           << Position->Geth() << " feet" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  loaded initial conditions" );
 
     SG_LOG( SG_FLIGHT, SG_INFO, "  set dt" );
 
     SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" );
+    
+
+   
 }
 
 /******************************************************************************/
@@ -206,45 +236,51 @@ bool FGJSBsim::update( int multiloop ) {
 
     trimmed->setBoolValue(false);
 
-    if ( needTrim && startup_trim->getBoolValue() ) {
-
-        //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;
+    if ( needTrim ) {
+      if ( startup_trim->getBoolValue() ) {
+        do_trim();
+      } else {
+        fdmex->RunIC(fgic);  //apply any changes made through the set_ functions
+      }
+      needTrim = false;  
+    }    
+    
+    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) );
+    }
 
-        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));
+    for ( i=0; i < multiloop; i++ ) {
+        fdmex->Run();
+    }
 
-        globals->get_controls()->set_aileron(FCS->GetDaCmd());
-        globals->get_controls()->set_rudder( FCS->GetDrCmd());
-    
-        SG_LOG( SG_FLIGHT, SG_INFO, "  Trim complete" );
+    struct FGJSBBase::Message* msg;
+    while (fdmex->ReadMessage()) {
+      msg = fdmex->ProcessMessage();
+      switch (msg->type) {
+      case FGJSBBase::Message::eText:
+        cout << msg->messageId << ": " << msg->text << endl;
+        break;
+      case FGJSBBase::Message::eBool:
+        cout << msg->messageId << ": " << msg->text << " " << msg->bVal << endl;
+        break;
+      case FGJSBBase::Message::eInteger:
+        cout << msg->messageId << ": " << msg->text << " " << msg->iVal << endl;
+        break;
+      case FGJSBBase::Message::eDouble:
+        cout << msg->messageId << ": " << msg->text << " " << msg->dVal << endl;
+        break;
+      default:
+        cerr << "Unrecognized message type." << endl;
+              break;
+      }
     }
-  
+
     for( i=0; i<get_num_engines(); i++ ) {
       FGEngInterface * e = get_engine(i);
       FGEngine * eng = Propulsion->GetEngine(i);
@@ -254,19 +290,17 @@ bool FGJSBsim::update( int multiloop ) {
       e->set_EGT( eng->getExhaustGasTemp_degF() );
       e->set_CHT( eng->getCylinderHeadTemp_degF() );
       e->set_Oil_Temp( eng->getOilTemp_degF() );
-      e->set_Throttle( globals->get_controls()->get_throttle(i) );
-    }
-
-    for ( i=0; i < multiloop; i++ ) {
-        fdmex->Run();
+      e->set_Running_Flag( eng->GetRunning() );
+      e->set_Cranking_Flag( eng->GetCranking() );
     }
 
-    // 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;
 }
@@ -294,7 +328,7 @@ bool FGJSBsim::copy_to_JSBsim() {
     }
 
     Position->SetSeaLevelRadius( get_Sea_level_radius() );
-    Position->SetRunwayRadius( scenery.cur_elev*SG_METER_TO_FEET
+    Position->SetRunwayRadius( scenery.get_cur_elev()*SG_METER_TO_FEET
                                + get_Sea_level_radius() );
 
     Atmosphere->SetExTemperature(get_Static_temperature());
@@ -328,25 +362,25 @@ bool FGJSBsim::copy_from_JSBsim() {
                       MassBalance->GetXYZcg(2),
                       MassBalance->GetXYZcg(3) );
 
-    _set_Accels_Body( Translation->GetUVWdot(1),
-                      Translation->GetUVWdot(2),
-                      Translation->GetUVWdot(3) );
+    _set_Accels_Body( Aircraft->GetBodyAccel()(1),
+                      Aircraft->GetBodyAccel()(2),
+                      Aircraft->GetBodyAccel()(3) );
 
-    _set_Accels_CG_Body( Translation->GetUVWdot(1),
-                         Translation->GetUVWdot(2),
-                         Translation->GetUVWdot(3) );
-
-    //_set_Accels_CG_Body_N ( Translation->GetNcg(1),
-    //                       Translation->GetNcg(2),
-    //                       Translation->GetNcg(3) );
+    //_set_Accels_CG_Body( Aircraft->GetBodyAccel()(1),
+    //                     Aircraft->GetBodyAccel()(2),
+    //                     Aircraft->GetBodyAccel()(3) );
     //
-    _set_Accels_Pilot_Body( Auxiliary->GetPilotAccel(1),
-                            Auxiliary->GetPilotAccel(2),
-                            Auxiliary->GetPilotAccel(3) );
+    _set_Accels_CG_Body_N ( Aircraft->GetNcg()(1),
+                            Aircraft->GetNcg()(2),
+                            Aircraft->GetNcg()(3) );
+    
+    _set_Accels_Pilot_Body( 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() );
 
@@ -415,19 +449,6 @@ bool FGJSBsim::copy_from_JSBsim() {
     return true;
 }
 
-void FGJSBsim::snap_shot(void) {
-    fgic->SetLatitudeRadIC(get_Lat_geocentric() );
-    fgic->SetLongitudeRadIC( get_Longitude() );
-    fgic->SetAltitudeFtIC( get_Altitude() );
-    fgic->SetTerrainAltitudeFtIC( get_Runway_altitude() );
-    fgic->SetVtrueFpsIC( get_V_rel_wind() );
-    fgic->SetPitchAngleRadIC( get_Theta() );
-    fgic->SetRollAngleRadIC( get_Phi() );
-    fgic->SetTrueHeadingRadIC( get_Psi() );
-    fgic->SetClimbRateFpsIC( get_Climb_Rate() );
-}
-
-
 bool FGJSBsim::ToggleDataLogging(void) {
     return fdmex->GetOutput()->Toggle();
 }
@@ -446,17 +467,26 @@ bool FGJSBsim::ToggleDataLogging(bool state) {
 
 //Positions
 void FGJSBsim::set_Latitude(double lat) {
-    double sea_level_radius_meters,lat_geoc;
+    static const SGPropertyNode *altitude
+       = fgGetNode("/position/altitude-ft");
+    double alt;
+    if ( altitude->getDoubleValue() > -9990 ) {
+       alt = altitude->getDoubleValue();
+    } else {
+       alt = 0.0;
+    }
+
+    double sea_level_radius_meters, lat_geoc;
 
     SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::set_Latitude: " << lat );
+    SG_LOG(SG_FLIGHT,SG_INFO," cur alt (ft) =  " << alt );
 
-    snap_shot();
-    sgGeodToGeoc( lat, get_Altitude() , &sea_level_radius_meters, &lat_geoc);
+    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 );
-    fdmex->RunIC(fgic); //loop JSBSim once
-    copy_from_JSBsim(); //update the bus
     needTrim=true;
 }
 
@@ -464,46 +494,39 @@ void FGJSBsim::set_Longitude(double lon) {
 
     SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::set_Longitude: " << lon );
 
-    snap_shot();
-    fgic->SetLongitudeRadIC(lon);
-    fdmex->RunIC(fgic); //loop JSBSim once
-    copy_from_JSBsim(); //update the bus
+    fgic->SetLongitudeRadIC( lon );
     needTrim=true;
 }
 
 void FGJSBsim::set_Altitude(double alt) {
+    static const SGPropertyNode *latitude
+       = fgGetNode("/position/latitude-deg");
+
     double sea_level_radius_meters,lat_geoc;
 
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Altitude: " << alt );
+    SG_LOG(SG_FLIGHT,SG_INFO, "  lat (deg) = " << latitude->getDoubleValue() );
 
-    snap_shot();
-    sgGeodToGeoc( get_Latitude(), alt , &sea_level_radius_meters, &lat_geoc);
+    sgGeodToGeoc( latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS, 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::set_V_calibrated_kts(double vc) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_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::set_Mach_number(double mach) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Mach_number: " <<  mach );
 
-    snap_shot();
     fgic->SetMachIC(mach);
-    fdmex->RunIC(fgic); //loop JSBSim once
-    copy_from_JSBsim(); //update the bus
     needTrim=true;
 }
 
@@ -511,12 +534,9 @@ void FGJSBsim::set_Velocities_Local( double north, double east, double down ){
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_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;
 }
 
@@ -524,12 +544,9 @@ void FGJSBsim::set_Velocities_Wind_Body( double u, double v, double w){
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_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;
 }
 
@@ -538,12 +555,9 @@ void FGJSBsim::set_Euler_Angles( double phi, double theta, double psi ) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_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;
 }
 
@@ -551,20 +565,14 @@ void FGJSBsim::set_Euler_Angles( double phi, double theta, double psi ) {
 void FGJSBsim::set_Climb_Rate( double roc) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Climb_Rate: " << roc );
 
-    snap_shot();
     fgic->SetClimbRateFpsIC(roc);
-    fdmex->RunIC(fgic); //loop JSBSim once
-    copy_from_JSBsim(); //update the bus
     needTrim=true;
 }
 
 void FGJSBsim::set_Gamma_vert_rad( double gamma) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Gamma_vert_rad: " << gamma );
 
-    snap_shot();
     fgic->SetFlightPathAngleRadIC(gamma);
-    fdmex->RunIC(fgic); //loop JSBSim once
-    copy_from_JSBsim(); //update the bus
     needTrim=true;
 }
 
@@ -572,28 +580,21 @@ void FGJSBsim::set_Gamma_vert_rad( double gamma) {
 void FGJSBsim::set_Sea_level_radius(double slr) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_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::set_Runway_altitude(double ralt) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_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::set_Static_pressure(double p) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Static_pressure: " << p );
 
-    snap_shot();
     Atmosphere->SetExPressure(p);
     if(Atmosphere->External() == true)
     needTrim=true;
@@ -602,7 +603,6 @@ void FGJSBsim::set_Static_pressure(double p) {
 void FGJSBsim::set_Static_temperature(double T) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Static_temperature: " << T );
     
-    snap_shot();
     Atmosphere->SetExTemperature(T);
     if(Atmosphere->External() == true)
     needTrim=true;
@@ -612,13 +612,11 @@ void FGJSBsim::set_Static_temperature(double T) {
 void FGJSBsim::set_Density(double rho) {
     SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Density: " << rho );
     
-    snap_shot();
     Atmosphere->SetExDensity(rho);
     if(Atmosphere->External() == true)
     needTrim=true;
 }
   
-
 void FGJSBsim::set_Velocities_Local_Airmass (double wnorth, 
                          double weast, 
                          double wdown ) {
@@ -626,9 +624,75 @@ void FGJSBsim::set_Velocities_Local_Airmass (double wnorth,
        << wnorth << ", " << weast << ", " << wdown );
     
     _set_Velocities_Local_Airmass( wnorth, weast, wdown );
-    snap_shot();
     Atmosphere->SetWindNED(wnorth, weast, wdown );
     if(Atmosphere->External() == true)
         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_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::do_trim(void) {
+
+        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() );
+
+        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" );
+}