]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/flight.cxx
Use bool where the source and destination variable is bool.
[flightgear.git] / src / FDM / flight.cxx
index 43b5aa03b62d6b21084263e2717e0c9c82e92403..fd09210b70446807fcd318c4ac1680dd1a51a93e 100644 (file)
 //
 // You should have received a copy of the GNU General Public License
 // along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 // $Id$
 
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
 
 #include <stdio.h>
 
@@ -29,6 +32,7 @@
 #include <simgear/debug/logstream.hxx>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/scene/model/placement.hxx>
+#include <simgear/scene/material/mat.hxx>
 #include <simgear/timing/timestamp.hxx>
 
 #include <Scenery/scenery.hxx>
@@ -83,6 +87,18 @@ FGInterface::_calc_multiloop (double dt)
   // ... ok, two times the roundoff to have enough room.
   int multiloop = int(floor(ml * (1.0 + 2.0*DBL_EPSILON)));
   remainder = (ml - multiloop) / hz;
+
+  // If we artificially inflate ml above by a tiny amount to get the
+  // closest integer, then subtract the integer from the original
+  // slightly smaller value, we can get a negative remainder.
+  // Logically this should never happen, and we definitely don't want
+  // to carry a negative remainder over to the next iteration, so
+  // never let the remainder go below zero.
+  // 
+  // Note: this fixes a problem where we run 1, 3, 1, 3, 1, 3... loops
+  // of the FDM when in fact we want to run 2, 2, 2, 2, 2...
+  if ( remainder < 0 ) { remainder = 0; }
+
   return (multiloop * speedup);
 }
 
@@ -196,6 +212,10 @@ FGInterface::common_init ()
     double alt_m = alt_ft * SG_FEET_TO_METER;
     set_Longitude( lon );
     set_Latitude( lat );
+    SG_LOG( SG_FLIGHT, SG_INFO, "Checking for lon = "
+            << lon*SGD_RADIANS_TO_DEGREES << "deg, lat = "
+            << lat*SGD_RADIANS_TO_DEGREES << "deg, alt = "
+            << alt_ft << "ft");
 
     double ground_elev_m = get_groundlevel_m(lat, lon, alt_m);
     double ground_elev_ft = ground_elev_m * SG_METER_TO_FEET;
@@ -829,16 +849,28 @@ FGInterface::get_cat_ft(double t, const double pt[3],
   return dist*SG_METER_TO_FEET;
 }
 
+// Legacy interface just kept because of JSBSim
 bool
 FGInterface::get_agl_m(double t, const double pt[3],
                        double contact[3], double normal[3], double vel[3],
                        int *type, double *loadCapacity,
                        double *frictionFactor, double *agl)
 {
-  return ground_cache.get_agl(t, pt, 2.0, contact, normal, vel, type,
-                              loadCapacity, frictionFactor, agl);
+  const SGMaterial* material;
+  bool ret = ground_cache.get_agl(t, pt, 2.0, contact, normal, vel, type,
+                                  &material, agl);
+  if (material) {
+    *loadCapacity = material->get_load_resistence();
+    *frictionFactor = material->get_friction_factor();
+
+  } else {
+    *loadCapacity = DBL_MAX;
+    *frictionFactor = 1.0;
+  }
+  return ret;
 }
 
+// Legacy interface just kept because of JSBSim
 bool
 FGInterface::get_agl_ft(double t, const double pt[3],
                         double contact[3], double normal[3], double vel[3],
@@ -848,45 +880,51 @@ FGInterface::get_agl_ft(double t, const double pt[3],
   // Convert units and do the real work.
   sgdVec3 pt_m;
   sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER );
+
+  const SGMaterial* material;
   bool ret = ground_cache.get_agl(t, pt_m, 2.0, contact, normal, vel,
-                                  type, loadCapacity, frictionFactor, agl);
+                                  type, &material, agl);
   // Convert units back ...
   sgdScaleVec3( contact, SG_METER_TO_FEET );
   sgdScaleVec3( vel, SG_METER_TO_FEET );
   *agl *= SG_METER_TO_FEET;
-  // FIXME: scale the load limit to something in the english unit system.
-  // Be careful with the DBL_MAX which is returned by default.
+
+  // return material properties if available
+  if (material) {
+    // FIXME: convert units?? now pascal to lbf/ft^2
+    *loadCapacity = 0.020885434*material->get_load_resistence();
+    *frictionFactor = material->get_friction_factor();
+  } else {
+    *loadCapacity = DBL_MAX;
+    *frictionFactor = 1.0;
+  }
   return ret;
 }
 
 bool
 FGInterface::get_agl_m(double t, const double pt[3], double max_altoff,
                        double contact[3], double normal[3], double vel[3],
-                       int *type, double *loadCapacity,
-                       double *frictionFactor, double *agl)
+                       int *type, const SGMaterial** material, double *agl)
 {
   return ground_cache.get_agl(t, pt, max_altoff, contact, normal, vel, type,
-                              loadCapacity, frictionFactor, agl);
+                              material, agl);
 }
 
 bool
 FGInterface::get_agl_ft(double t, const double pt[3], double max_altoff,
                         double contact[3], double normal[3], double vel[3],
-                        int *type, double *loadCapacity,
-                        double *frictionFactor, double *agl)
+                        int *type, const SGMaterial** material, double *agl)
 {
   // Convert units and do the real work.
   sgdVec3 pt_m;
   sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER );
   bool ret = ground_cache.get_agl(t, pt_m, SG_FEET_TO_METER * max_altoff,
                                   contact, normal, vel,
-                                  type, loadCapacity, frictionFactor, agl);
+                                  type, material, agl);
   // Convert units back ...
   sgdScaleVec3( contact, SG_METER_TO_FEET );
   sgdScaleVec3( vel, SG_METER_TO_FEET );
   *agl *= SG_METER_TO_FEET;
-  // FIXME: scale the load limit to something in the english unit system.
-  // Be careful with the DBL_MAX which is returned by default.
   return ret;
 }
 
@@ -894,26 +932,50 @@ FGInterface::get_agl_ft(double t, const double pt[3], double max_altoff,
 double
 FGInterface::get_groundlevel_m(double lat, double lon, double alt)
 {
-  // First compute the sea level radius,
   sgdVec3 pos, cpos;
-  sgGeodToCart(lat, lon, 0, pos);
-  double slr = sgdLengthVec3(pos);
-  // .. then the cartesian position of the given lat/lon/alt.
+  // Compute the cartesian position of the given lat/lon/alt.
   sgGeodToCart(lat, lon, alt, pos);
 
   // FIXME: how to handle t - ref_time differences ???
   double ref_time, radius;
   // Prepare the ground cache for that position.
-  if (!is_valid_m(&ref_time, cpos, &radius))
-    prepare_ground_cache_m(ref_time, pos, 10);
-  else if (radius*radius <= sgdDistanceSquaredVec3(pos, cpos))
-    prepare_ground_cache_m(ref_time, pos, radius);
+  if (!is_valid_m(&ref_time, cpos, &radius)) {
+    bool ok = prepare_ground_cache_m(ref_time, pos, 10);
+    /// This is most likely the case when the given altitude is
+    /// too low, try with a new altitude of 10000m, that should be
+    /// sufficient to find a ground level below everywhere on our planet
+    if (!ok) {
+      sgGeodToCart(lat, lon, 10000, pos);
+      /// If there is still no ground, return sea level radius
+      if (!prepare_ground_cache_m(ref_time, pos, 10))
+        return 0;
+    }
+  } else if (radius*radius <= sgdDistanceSquaredVec3(pos, cpos)) {
+    /// We reuse the old radius value, but only if it is at least 10 Meters ..
+    if (!(10 < radius)) // Well this strange compare is nan safe
+      radius = 10;
+
+    bool ok = prepare_ground_cache_m(ref_time, pos, radius);
+    /// This is most likely the case when the given altitude is
+    /// too low, try with a new altitude of 10000m, that should be
+    /// sufficient to find a ground level below everywhere on our planet
+    if (!ok) {
+      sgGeodToCart(lat, lon, 10000, pos);
+      /// If there is still no ground, return sea level radius
+      if (!prepare_ground_cache_m(ref_time, pos, radius))
+        return 0;
+    }
+  }
   
-  double contact[3], normal[3], vel[3], lc, ff, agl;
+  double contact[3], normal[3], vel[3], agl;
   int type;
-  get_agl_m(ref_time, pos, 2.0, contact, normal, vel, &type, &lc, &ff, &agl);
-
-  return sgdLengthVec3(contact) - slr;
+  // Ignore the return value here, since it just tells us if
+  // the returns stem from the groundcache or from the coarse
+  // computations below the groundcache. The contact point is still something
+  // valid, the normals and the other returns just contain some defaults.
+  get_agl_m(ref_time, pos, 2.0, contact, normal, vel, &type, 0, &agl);
+  Point3D geodPos = sgCartToGeod(Point3D(contact[0], contact[1], contact[2]));
+  return geodPos.elev();
 }
   
 bool