Em Seg, 2009-02-23 às 17:58 -0300, Diogo Kastrup escreveu:
> The carrier sailing out from underneath is strange, it looks like the
> groundcache can't finding a intersection with the ground for these
> aircrafts and it is using a fallback value. Can someone check if this
> happens without my patch also? I will try to find out why this is
> happening.

Yep, the groundcache can't find a intersection. I think this problem
occurs without my patch also. To fix it just change groundcache.cxx
around line 312 from this:

if (d*d < reference_vehicle_radius*dot(n, n)) {

to this:

if (d*d < reference_vehicle_radius*reference_vehicle_radius*dot(n, n)) {

I am sending the diff again with the fix for this and the (untested) fix
for the zero-speed problem, just in case someone want to play with it.

I am still trying to figure out why the s76c is shaking. This happens
with other helicopters also, like the R22.

Regards,

Diogo
Index: src/FDM/flight.cxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/flight.cxx,v
retrieving revision 1.35
diff -u -r1.35 flight.cxx
--- src/FDM/flight.cxx	9 Nov 2007 05:39:13 -0000	1.35
+++ src/FDM/flight.cxx	23 Feb 2009 23:14:47 -0000
@@ -705,6 +705,15 @@
   return dist*SG_METER_TO_FEET;
 }
 
+void 
+FGInterface::get_platform(double t, double pos[3], float *orient)
+{
+  SGVec3d _pos;
+  ground_cache.get_platform(t, _pos, orient);
+  if (pos)
+    assign(pos, _pos);
+}
+
 // Legacy interface just kept because of JSBSim
 bool
 FGInterface::get_agl_m(double t, const double pt[3],
Index: src/FDM/flight.hxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/flight.hxx,v
retrieving revision 1.18
diff -u -r1.18 flight.hxx
--- src/FDM/flight.hxx	27 Jul 2008 16:25:14 -0000	1.18
+++ src/FDM/flight.hxx	23 Feb 2009 23:14:48 -0000
@@ -629,6 +629,9 @@
                      double end[2][3], double vel[2][3]);
     double get_cat_ft(double t, const double pt[3],
                       double end[2][3], double vel[2][3]);
+
+    // Return the position and orientation of the platform
+    void get_platform(double t, double pos[3], float *orient);
   
 
     // Return the altitude above ground below the wgs84 point pt
@@ -642,8 +645,8 @@
                    int *type, double *loadCapacity,
                    double *frictionFactor, double *agl);
     bool get_agl_m(double t, const double pt[3],
-                       double contact[3], double normal[3], double vel[3],
-                       int *type, const SGMaterial **material,double *agl);
+                   double contact[3], double normal[3], double vel[3],
+                   int *type, const SGMaterial **material,double *agl);
     bool get_agl_ft(double t, const double pt[3],
                     double contact[3], double normal[3], double vel[3],
                     int *type, double *loadCapacity,
Index: src/FDM/groundcache.cxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/groundcache.cxx,v
retrieving revision 1.33
diff -u -r1.33 groundcache.cxx
--- src/FDM/groundcache.cxx	15 Feb 2009 00:56:22 -0000	1.33
+++ src/FDM/groundcache.cxx	23 Feb 2009 23:14:49 -0000
@@ -158,6 +158,7 @@
   _material(0),
   cache_ref_time(0.0),
   wire_id(0),
+  platform_id(0),
   reference_wgs84_point(SGVec3d(0, 0, 0)),
   reference_vehicle_radius(0.0),
   down(0.0, 0.0, 0.0),
@@ -198,6 +199,8 @@
     gp.vel = SGVec3d(0.0, 0.0, 0.0);
     gp.rot = SGVec3d(0.0, 0.0, 0.0);
     gp.pivot = SGVec3d(0.0, 0.0, 0.0);
+    gp.platform_id = 0;
+    gp.platform = NULL;
     gp.material = 0;
     backfaceCulling = false;
     // XXX state set might be higher up in scene graph
@@ -235,6 +238,8 @@
             break;
         default:
             gp.type = FGInterface::Solid;
+            gp.platform_id = ud->carrier->getID();
+            gp.platform = ud->carrier;
             break;
         }
         // Copy the velocity from the carrier class.
@@ -304,7 +309,7 @@
         // Only check if the triangle is in the cache sphere if the plane
         // containing the triangle is near enough
         double d = dot(n, v[0] - localCacheReference);
-        if (d*d < reference_vehicle_radius*dot(n, n)) {
+        if (d*d < reference_vehicle_radius*reference_vehicle_radius*dot(n, n)) {
             // Check if the sphere around the vehicle intersects the sphere
             // around that triangle. If so, put that triangle into the cache.
             double r2 = boundRadius + reference_vehicle_radius;
@@ -323,6 +328,10 @@
                 t.sphere.setRadius(boundRadius);
                 t.gp = gp;
                 triangles.push_back(t);
+                if (gp.platform_id
+                    && (platforms.empty() 
+                        || dynamic_cast<class FGAIBase*>(platforms.back())->getID() != gp.platform_id))
+                    platforms.push_back(gp.platform);
             }
         }
         // In case the cache is empty, we still provide agl computations.
@@ -414,6 +423,7 @@
   triangles.resize(0);
   catapults.resize(0);
   wires.resize(0);
+  platforms.resize(0);
 
   // Store the parameters we used to build up that cache.
   reference_wgs84_point = pt;
@@ -460,6 +470,7 @@
          << ", # triangles = " << triangles.size()
          << ", # wires = " << wires.size()
          << ", # catapults = " << catapults.size()
+         << ", # platforms = " << platforms.size()
          << ", ground_radius = " << ground_radius );
 
   // If the ground radius is still below 5e6 meters, then we do not yet have
@@ -520,6 +531,58 @@
   return sqrt(dist);
 }
 
+void
+FGGroundCache::get_platform(double t, SGVec3d& pos, float *orient)
+{
+  size_t sz = platforms.size();
+  if (sz == 0)
+  {
+    pos = SGVec3d(0,0,0);
+    for (int y = 0; y < 3; y++)
+      for (int x = 0; x < 3; x++)
+        orient[y*3+x] = x == y ? 1.0 : 0.0;
+    return;
+  }
+
+  for (size_t i = 0; i < sz; ++i) {
+    FGAIBase* platform = dynamic_cast<class FGAIBase*>(platforms[i]);
+    if (platform->getID() == platform_id)
+    {
+      SGMatrixf orient4;
+      double hdg, pitch, roll, speed, lat, lon;
+      hdg = platform->_getHeading();
+      pitch = platform->_getPitch();
+      roll = platform->_getRoll();
+      speed = platform->_getSpeed();
+      lat = platform->_getLatitude();
+      lon = platform->_getLongitude();
+
+      // Copied from AICarrier.cxx
+      // Transform that one to the horizontal local coordinate system.
+      SGQuatd ec2hl = SGQuatd::fromLonLatDeg(lon, lat);
+      // The orientation of the platform wrt the horizontal local frame
+      SGQuatd hl2body = SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll);
+      // and postrotate the orientation of the AIModel wrt the horizontal
+      // local frame
+      SGQuatd ec2body = ec2hl*hl2body;
+      // Compute the velocity in m/s in the earth centered coordinate system axis
+      double v_north = 0.51444444*speed*cos(hdg * SGD_DEGREES_TO_RADIANS);
+      double v_east  = 0.51444444*speed*sin(hdg * SGD_DEGREES_TO_RADIANS);
+      SGVec3d vel_wrt_earth = ec2hl.backTransform(SGVec3d(v_north, v_east, 0));
+
+      orient4.set(hl2body);
+      for (int y = 0; y < 3; y++)
+        for (int x = 0; x < 3; x++)
+          orient[y*3+x] = orient4[y*4+x];
+
+      // Time difference to the reference time.
+      t -= cache_ref_time;
+
+      pos = platform->getCartPos() + t * vel_wrt_earth;
+    }
+  }
+}
+
 bool
 FGGroundCache::get_agl(double t, const SGVec3d& dpt, double max_altoff,
                        SGVec3d& contact, SGVec3d& normal, SGVec3d& vel,
@@ -535,7 +598,7 @@
   contact = SGVec3d(0, 0, 0);
   normal = SGVec3d(0, 0, 0);
 
-  // Time difference to th reference time.
+  // Time difference to the reference time.
   t -= cache_ref_time;
 
   // The double valued point we start to search for intersection.
@@ -578,6 +641,7 @@
         *agl = dot(down, contact - dpt);
         if (material)
           *material = triangles[i].gp.material;
+        platform_id = triangles[i].gp.platform_id;
       }
     }
   }
Index: src/FDM/groundcache.hxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/groundcache.hxx,v
retrieving revision 1.11
diff -u -r1.11 groundcache.hxx
--- src/FDM/groundcache.hxx	13 Feb 2009 09:21:35 -0000	1.11
+++ src/FDM/groundcache.hxx	23 Feb 2009 23:14:49 -0000
@@ -62,6 +62,9 @@
     // pt in wgs84 coordinates.
     double get_cat(double t, const SGVec3d& pt,
                    SGVec3d end[2], SGVec3d vel[2]);
+
+    // Get the platform position and orientation
+    void get_platform(double t, SGVec3d& pos, float *orient);
   
 
     // Return the altitude above ground below the wgs84 point pt
@@ -101,6 +104,9 @@
       SGVec3d vel;
       SGVec3d rot;
       SGVec3d pivot;
+      // the platform owning the triangle
+      int platform_id;
+      osg::Referenced* platform;
       // the simgear material reference, contains friction coeficients ...
       const SGMaterial* material;
     };
@@ -134,11 +140,14 @@
     double cache_ref_time;
     // The wire identifier to track.
     int wire_id;
+    // The platform represented by the groundcache
+    int platform_id;
 
     // Containers which hold all the essential information about this cache.
     std::vector<Triangle> triangles;
     std::vector<Catapult> catapults;
     std::vector<Wire> wires;
+    std::vector<osg::Referenced*> platforms;
 
     // The point and radius where the cache is built around.
     // That are the arguments that were given to prepare_ground_cache.
Index: src/FDM/YASim/BodyEnvironment.hpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/BodyEnvironment.hpp,v
retrieving revision 1.4
diff -u -r1.4 BodyEnvironment.hpp
--- src/FDM/YASim/BodyEnvironment.hpp	27 Dec 2008 16:08:21 -0000	1.4
+++ src/FDM/YASim/BodyEnvironment.hpp	23 Feb 2009 23:14:49 -0000
@@ -19,6 +19,7 @@
     float  rot[3];    // rotational velocity
     float  acc[3];    // acceleration
     float  racc[3];   // rotational acceleration
+    float  dt;        // Time offset
 
     // Simple initialization
     State() {
@@ -29,6 +30,7 @@
             for(j=0; j<3; j++)
                 orient[3*i+j] = i==j ? 1.0f : 0.0f;
         }
+	dt = 0.0;
     }
 
     void posLocalToGlobal(float* lpos, double *gpos) {
Index: src/FDM/YASim/FGGround.cpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/FGGround.cpp,v
retrieving revision 1.3
diff -u -r1.3 FGGround.cpp
--- src/FDM/YASim/FGGround.cpp	17 Jan 2007 20:42:39 -0000	1.3
+++ src/FDM/YASim/FGGround.cpp	23 Feb 2009 23:14:49 -0000
@@ -83,6 +83,11 @@
     return dist;
 }
 
+void FGGround::getPlatform(float dt, double pos[3], float *orient)
+{
+    _iface->get_platform(_toff + dt, pos, orient);
+}
+
 void FGGround::setTimeOffset(double toff)
 {
     _toff = toff;
Index: src/FDM/YASim/FGGround.hpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/FGGround.hpp,v
retrieving revision 1.2
diff -u -r1.2 FGGround.hpp
--- src/FDM/YASim/FGGround.hpp	17 Jan 2007 20:42:39 -0000	1.2
+++ src/FDM/YASim/FGGround.hpp	23 Feb 2009 23:14:49 -0000
@@ -38,6 +38,8 @@
     virtual float getCatapult(const double pos[3],
                               double end[2][3], float vel[2][3]);
 
+    virtual void getPlatform(float dt, double pos[3], float *orient);
+
     void setTimeOffset(double toff);
 
 private:
Index: src/FDM/YASim/Gear.cpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Gear.cpp,v
retrieving revision 1.9
diff -u -r1.9 Gear.cpp
--- src/FDM/YASim/Gear.cpp	13 May 2007 11:58:36 -0000	1.9
+++ src/FDM/YASim/Gear.cpp	23 Feb 2009 23:14:50 -0000
@@ -1,5 +1,6 @@
 #include "Math.hpp"
 #include "BodyEnvironment.hpp"
+#include "Ground.hpp"
 #include "RigidBody.hpp"
 
 #include <simgear/scene/material/mat.hxx>
@@ -7,6 +8,7 @@
 #include "Gear.hpp"
 namespace yasim {
 static const float YASIM_PI = 3.14159265358979323846;
+static const float DEG2RAD = YASIM_PI / 180.0;
 static const float maxGroundBumpAmplitude=0.4;
         //Amplitude can be positive and negative
 
@@ -14,11 +16,12 @@
 {
     int i;
     for(i=0; i<3; i++)
-	_pos[i] = _cmpr[i] = 0;
+       _pos[i] = _cmpr[i] = _stuck[i] = 0;
     _spring = 1;
     _damp = 0;
     _sfric = 0.8f;
     _dfric = 0.7f;
+    _fric_spring = 0.005f; // Spring length = 0.5 cm
     _brake = 0;
     _rot = 0;
     _initialLoad = 0;
@@ -46,6 +49,13 @@
 	_global_ground[i] = _global_vel[i] = 0;
     _global_ground[2] = 1;
     _global_ground[3] = -1e3;
+
+    for(int y=0; y<3; y++)
+    {
+        _ground_pivot[y] = 0.0;
+        for(int x=0; x<3; x++)
+            _ground_orient[y*3+x] = x == y ? 1.0 : 0.0;
+    }
 }
 
 void Gear::setPosition(float* position)
@@ -191,8 +201,7 @@
     _ground_isSolid = isSolid;
     _global_x = globalX;
     _global_y = globalY;
-
-    }
+}
 
 void Gear::getPosition(float* out)
 {
@@ -293,7 +302,7 @@
     return h*(1/8.)*_ground_bumpiness*maxGroundBumpAmplitude;
 }
 
-void Gear::calcForce(RigidBody* body, State *s, float* v, float* rot)
+void Gear::calcForce(Ground *g_cb, RigidBody* body, State *s, float* v, float* rot)
 {
     // Init the return values
     int i;
@@ -451,56 +460,247 @@
         _rollSpeed = vsteer;
         _casterAngle = _rot;
     }
-    float fsteer,fskid;
+
+    float ffric[3];
     if(_ground_isSolid)
     {
-        fsteer = (_brake * _ground_frictionFactor
-                    +(1-_brake)*_ground_rollingFriction
-                 )*calcFriction(wgt, vsteer);
-        fskid  = calcFriction(wgt, vskid)*(_ground_frictionFactor);
-    }
-    else
-    {
-        fsteer = calcFrictionFluid(wgt, vsteer)*_ground_frictionFactor;
-        fskid  = 10*calcFrictionFluid(wgt, vskid)*_ground_frictionFactor;
-        //factor 10: floats have different drag in x and y.
+        float stuckf[3];
+        double stuckd[3];
+        g_cb->getPlatform(s->dt, _ground_pivot, _ground_orient);
+
+        // Convert platform coordinates to global
+        Math::tmul33(_ground_orient, _stuck, stuckd);
+        stuckd[0] += _ground_pivot[0];
+        stuckd[1] += _ground_pivot[1];
+        stuckd[2] += _ground_pivot[2];
+        s->posGlobalToLocal(stuckd, stuckf);
+        calcFriction(stuckf, cv, steer, skid, wgt, ffric);
     }
-    if(vsteer > 0) fsteer = -fsteer;
-    if(vskid > 0) fskid = -fskid;
-    
-    //reduce friction if wanted by _reduceFrictionByExtension
-    float factor = (1-_frac)*(1-_reduceFrictionByExtension)+_frac*1;
-    factor = Math::clamp(factor,0,1);
-    fsteer *= factor;
-    fskid *= factor;
+    else calcFrictionFluid(cv, steer, skid, wgt, ffric);
 
     // Phoo!  All done.  Add it up and get out of here.
-    Math::mul3(fsteer, steer, tmp);
-    Math::add3(tmp, _force, _force);
-
-    Math::mul3(fskid, skid, tmp);
-    Math::add3(tmp, _force, _force);
+    Math::add3(ffric, _force, _force);
 }
 
-float Gear::calcFriction(float wgt, float v) //used on solid ground
+void Gear::updateStuckPoint(State* s)
 {
-    // How slow is stopped?  10 cm/second?
-    const float STOP = 0.1f;
-    const float iSTOP = 1.0f/STOP;
-    v = Math::abs(v);
-    if(v < STOP) return v*iSTOP * wgt * _sfric;
-    else         return wgt * _dfric;
+    // Some values must be recalculated here because the
+    // integrator takes averaged values from the iterations
+    float stuck[3];
+    double stuckd[3];
+    // Convert platform coordinates to global
+    Math::tmul33(_ground_orient, _stuck, stuckd);
+    stuckd[0] += _ground_pivot[0];
+    stuckd[1] += _ground_pivot[1];
+    stuckd[2] += _ground_pivot[2];
+    // Global to aircraft coordinates
+    s->posGlobalToLocal(stuckd, stuck);
+    // The ground plane transformed to the local frame.
+    float ground[4];
+    s->planeGlobalToLocal(_global_ground, ground);
+    float gup[3]; // "up" unit vector from the ground
+    Math::set3(ground, gup);
+    Math::mul3(-1, gup, gup);
+
+    float xhat[] = {1,0,0};
+    float skid[3], steer[3];
+    Math::cross3(gup, xhat, skid);  // up cross xhat =~ skid
+    Math::unit3(skid, skid);        //               == skid
+    Math::cross3(skid, gup, steer); // skid cross up == steer
+
+    if(_rot != 0) {
+        // Correct for a rotation
+        float srot = Math::sin(_rot);
+        float crot = Math::cos(_rot);
+        float tx = steer[0];
+        float ty = steer[1];
+        steer[0] =  crot*tx + srot*ty;
+        steer[1] = -srot*tx + crot*ty;
+
+        tx = skid[0];
+        ty = skid[1];
+
+        skid[0] =  crot*tx + srot*ty;
+        skid[1] = -srot*tx + crot*ty;
+    }
+
+    if (_rolling)
+    {
+        // Calculate the gear's movement
+        float tmp[3];
+        Math::sub3(_contact, stuck, tmp);
+        // Get the movement in the skid and steer directions
+        float dskid, dsteer;
+        dskid  = Math::dot3(tmp, skid);
+        dsteer = Math::dot3(tmp, steer);
+        // The movement is not always exactly on the steer axis
+        // so we should allow some empirical "slip" because of 
+        // the wheel flexibility (max 5 degrees)
+        // FIXME: This angle should depend on the tire type/condition
+        //        Is 5 degrees a good value?
+        float rad = (dskid / _fric_spring) * 5.0 * DEG2RAD;
+        dskid -= Math::abs(dsteer) * Math::tan(rad);
+
+        Math::mul3(dskid, skid, tmp);
+        Math::sub3(_contact, tmp, stuck);
+    }
+    else if (_slipping) Math::set3(_contact, stuck);
+
+    if (_rolling || _slipping)
+    {
+        s->posLocalToGlobal(stuck, stuckd);
+        // Convert back to platform coordinates
+        stuckd[0] -= _ground_pivot[0];
+        stuckd[1] -= _ground_pivot[1];
+        stuckd[2] -= _ground_pivot[2];
+        Math::vmul33(_ground_orient, stuckd, _stuck);
+    }
+}
+
+//used on solid ground
+void Gear::calcFriction(float *stuck, float *cv,float *steer, float *skid
+                        , float wgt, float *force)
+{
+    // Calculate the gear's movement
+    float dgear[3];
+    Math::sub3(_contact, stuck, dgear);
+
+    // Get the movement in the steer and skid directions
+    float dsteer, dskid;
+    dsteer = Math::dot3(dgear, steer);
+    dskid  = Math::dot3(dgear, skid);
+
+    // Get the velocities in the steer and skid directions
+    float vsteer, vskid;
+    vsteer = Math::dot3(cv, steer);
+    vskid  = Math::dot3(cv, skid);
+
+    // If rolling and slipping are false, the gear is stopped
+    _rolling  = false;
+    _slipping = false;
+    // Here we detect if it is slipping
+    if (Math::sqrt(dskid*dskid + dsteer*dsteer*(_brake/_sfric)) > _fric_spring)
+    {
+/*
+        // Turn on our ABS ;)
+        // FIXME: This is off because we don't want ABS on helicopters
+        // as their "wheels" should be locked all the time
+        if (Math::abs(dskid) < _fric_spring)
+        {
+            float bl;
+            bl = _sfric - _sfric * (Math::abs(dskid) / _fric_spring);
+            if (_brake > bl) _brake = bl;
+        }
+        else
+*/
+            _slipping = true;
+    }
+
+
+    float fric, fspring, fdamper, brake, tmp[3];
+    if (!_slipping)
+    {
+        // Calculate the steer force.
+        // Brake is limited between 0 and 1, wheel lock on 1.
+        brake = _brake > _sfric ? 1 : _brake/_sfric;
+        fspring = Math::abs((dsteer / _fric_spring) * wgt * _sfric);
+        // Set _rolling so the stuck point is updated
+        if ((Math::abs(dsteer) > _fric_spring) || (fspring > brake * wgt * _sfric))
+        {
+            _rolling = true;
+            fric  = _ground_rollingFriction * wgt * _sfric; // Rolling
+            fric += _brake * wgt * _sfric * _ground_frictionFactor; // Brake
+            if (vsteer > 0) fric = -fric;
+        }
+        else // Stopped
+        {
+            fdamper  = Math::abs(vsteer * wgt * _sfric);
+            fdamper *= ((dsteer * vsteer) > 0) ? 1 : -1;
+            fric  = fspring + fdamper;
+            fric *= brake * _ground_frictionFactor
+                    + (1 - brake) * _ground_rollingFriction;
+            if (dsteer > 0) fric = -fric;
+        }
+        Math::mul3(fric, steer, force);
+
+        // Calculate the skid force.
+        fspring = Math::abs((dskid / _fric_spring) * wgt * _sfric);
+        fdamper  = Math::abs(vskid * wgt * _sfric);
+        fdamper *= ((dskid * vskid) > 0) ? 1 : -1;
+        fric = _ground_frictionFactor * (fspring + fdamper);
+        if (dskid > 0) fric = -fric;
+
+        Math::mul3(fric, skid, tmp);
+        Math::add3(force, tmp, force);
+
+        // The damper can add a lot of force,
+        // if it is to big, then it will slip
+        if (Math::mag3(force) > wgt * _sfric * _ground_frictionFactor)
+        {
+            _slipping = true;
+            _rolling = false;
+        }
+    }
+    if (_slipping)
+    {
+        // Get the direction of movement
+        float dir[3];
+        Math::unit3(cv, dir);
+
+        // Calculate the steer force.
+        // brake is limited between 0 and 1, wheel lock on 1
+        brake = _brake > _dfric ? 1 : _brake/_dfric;
+        fric  = wgt * _dfric * Math::abs(Math::dot3(dir, steer));
+        fric *= _ground_rollingFriction * (1 - brake)
+                + _ground_frictionFactor * brake;
+        if (vsteer > 0) fric = -fric;
+        Math::mul3(fric, steer, force);
+
+        // Calculate the skid force.
+        fric  = wgt * _dfric * _ground_frictionFactor;
+        // Multiply by 1 when no brake, else reduce the turning component
+        fric *= (1 - brake) + Math::abs(Math::dot3(dir, skid)) * brake;
+        if (vskid > 0) fric = -fric;
+
+        Math::mul3(fric, skid, tmp);
+        Math::add3(force, tmp, force);
+    }
+
+    //reduce friction if wanted by _reduceFrictionByExtension
+    float factor = (1-_frac)*(1-_reduceFrictionByExtension)+_frac*1;
+    factor = Math::clamp(factor,0,1);
+    Math::mul3(factor, force, force);
 }
 
-float Gear::calcFrictionFluid(float wgt, float v) //used on fluid ground
+//used on fluid ground
+void Gear::calcFrictionFluid(float *cv, float *steer, float *skid, float wgt, float *force)
 {
     // How slow is stopped?  1 cm/second?
     const float STOP = 0.01f;
     const float iSTOP = 1.0f/STOP;
-    v = Math::abs(v);
-    if(v < STOP) return v*iSTOP * wgt * _sfric;
-    else return wgt * _dfric*v*v*0.01;
+    float vsteer, vskid;
+    vsteer = Math::dot3(cv, steer);
+    vskid  = Math::dot3(cv, skid);
+
+    float tmp[3];
+    float fric;
+    // Calculate the steer force
+    float v = Math::abs(vsteer);
+    if(v < STOP) fric = v*iSTOP * wgt * _sfric;
+    else fric = wgt * _dfric*v*v*0.01;
+    //*0.01: to get _dfric of the same size than _dfric on solid
+    if (v > 0) fric = -fric;
+    Math::mul3(_ground_frictionFactor * fric, steer, force);
+
+    // Calculate the skid force
+    v = Math::abs(vskid);
+    if(v < STOP) fric = v*iSTOP * wgt * _sfric;
+    else fric = wgt * _dfric*v*v*0.01;
     //*0.01: to get _dfric of the same size than _dfric on solid
+    if (v > 0) fric = -fric;
+    Math::mul3(10 * _ground_frictionFactor * fric, skid, tmp);
+    Math::add3(force, tmp, force);
+    //factor 10: floats have different drag in x and y.
 }
 }; // namespace yasim
 
Index: src/FDM/YASim/Gear.hpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Gear.hpp,v
retrieving revision 1.7
diff -u -r1.7 Gear.hpp
--- src/FDM/YASim/Gear.hpp	18 Jan 2007 21:46:28 -0000	1.7
+++ src/FDM/YASim/Gear.hpp	23 Feb 2009 23:14:50 -0000
@@ -5,6 +5,7 @@
 
 namespace yasim {
 
+class Ground;
 class RigidBody;
 struct State;
 
@@ -73,7 +74,7 @@
     // vector, and a ground plane (all specified in local coordinates)
     // and make a force and point of application (i.e. ground contact)
     // available via getForce().
-    void calcForce(RigidBody* body, State* s, float* v, float* rot);
+    void calcForce(Ground *g_cb, RigidBody* body, State* s, float* v, float* rot);
 
     // Computed values: total force, weight-on-wheels (force normal to
     // ground) and compression fraction.
@@ -85,12 +86,19 @@
     bool getIgnoreWhileSolving() {return _ignoreWhileSolving; }
     void setContactPoint(bool c);
 
+    // Update the stuck point after all integrator's iterations
+    void updateStuckPoint(State* s);
+
 private:
-    float calcFriction(float wgt, float v);
-    float calcFrictionFluid(float wgt, float v);
+    void calcFriction(float *gpos, float *cv, float *steer, float *skid, float wgt, float *force);
+    void calcFrictionFluid(float *cv, float *steer, float *skid, float wgt, float *force);
 
+    float _fric_spring;
     bool _castering;
+    bool _rolling;
+    bool _slipping;
     float _pos[3];
+    double _stuck[3];
     float _cmpr[3];
     float _spring;
     float _damp;
@@ -126,6 +134,8 @@
     bool _ground_isSolid;
     double _global_x;
     double _global_y;
+    float _ground_orient[9];
+    double _ground_pivot[3];
 };
 
 }; // namespace yasim
Index: src/FDM/YASim/Ground.cpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Ground.cpp,v
retrieving revision 1.2
diff -u -r1.2 Ground.cpp
--- src/FDM/YASim/Ground.cpp	17 Jan 2007 20:42:39 -0000	1.2
+++ src/FDM/YASim/Ground.cpp	23 Feb 2009 23:14:50 -0000
@@ -30,8 +30,8 @@
 }
 
 void Ground::getGroundPlane(const double pos[3],
-                              double plane[4], float vel[3],
-                              int *type, const SGMaterial **material)
+                            double plane[4], float vel[3],
+                            int *type, const SGMaterial **material)
 {
     getGroundPlane(pos,plane,vel);
 }
@@ -56,5 +56,15 @@
     return 1e10;
 }
 
+void Ground::getPlatform(float dt, double pos[3], float *orient)
+{
+    for (int y = 0; y < 3; y++)
+    {
+        pos[y] = 0.0;
+        for (int x = 0; x < 3; x++)
+            orient[y*3+x] = x == y ? 1.0 : 0.0;
+    }
+}
+
 }; // namespace yasim
 
Index: src/FDM/YASim/Ground.hpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Ground.hpp,v
retrieving revision 1.2
diff -u -r1.2 Ground.hpp
--- src/FDM/YASim/Ground.hpp	17 Jan 2007 20:42:39 -0000	1.2
+++ src/FDM/YASim/Ground.hpp	23 Feb 2009 23:14:50 -0000
@@ -13,8 +13,8 @@
                                 double plane[4], float vel[3]);
 
     virtual void getGroundPlane(const double pos[3],
-                              double plane[4], float vel[3],
-                              int *type, const SGMaterial **material);
+                                double plane[4], float vel[3],
+                                int *type, const SGMaterial **material);
 
     virtual bool caughtWire(const double pos[4][3]);
 
@@ -24,6 +24,8 @@
 
     virtual float getCatapult(const double pos[3],
                               double end[2][3], float vel[2][3]);
+
+    virtual void getPlatform(float dt, double pos[3], float *orient);
 };
 
 }; // namespace yasim
Index: src/FDM/YASim/Integrator.cpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Integrator.cpp,v
retrieving revision 1.2
diff -u -r1.2 Integrator.cpp
--- src/FDM/YASim/Integrator.cpp	7 Oct 2004 20:34:56 -0000	1.2
+++ src/FDM/YASim/Integrator.cpp	23 Feb 2009 23:14:50 -0000
@@ -173,12 +173,13 @@
         }
         for(j=0; j<9; j++)
             stmp.orient[j] = ori[i][j];
-	_env->calcForces(&stmp);
+        stmp.dt = dt;
+        _env->calcForces(&stmp);
 
-	_body->getAccel(acc[i]);
-	_body->getAngularAccel(rac[i]);
- 	l2gVector(_s.orient, acc[i], acc[i]);
- 	l2gVector(_s.orient, rac[i], rac[i]);
+        _body->getAccel(acc[i]);
+        _body->getAngularAccel(rac[i]);
+        l2gVector(_s.orient, acc[i], acc[i]);
+        l2gVector(_s.orient, rac[i], rac[i]);
 
 	//
 	// Save the resulting derivatives for the next iteration
Index: src/FDM/YASim/Math.cpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Math.cpp,v
retrieving revision 1.5
diff -u -r1.5 Math.cpp
--- src/FDM/YASim/Math.cpp	14 Sep 2006 18:18:33 -0000	1.5
+++ src/FDM/YASim/Math.cpp	23 Feb 2009 23:14:50 -0000
@@ -163,6 +163,12 @@
     out[2] = ax*by - bx*ay;
 }
 
+void Math::set33(float* a, float* b)
+{
+    for (int i=0; i < 9; i++)
+        a[i] = b[i];
+}
+
 void Math::mmul33(float* a, float* b, float* out)
 {
     float tmp[9];
@@ -191,6 +197,14 @@
     out[2] = x*m[6] + y*m[7] + z*m[8];
 }
 
+void Math::vmul33(float* m, double* v, double* out)
+{
+    double x = v[0], y = v[1], z = v[2];
+    out[0] = x*m[0] + y*m[1] + z*m[2];
+    out[1] = x*m[3] + y*m[4] + z*m[5];
+    out[2] = x*m[6] + y*m[7] + z*m[8];
+}
+
 void Math::tmul33(float* m, float* v, float* out)
 {
     float x = v[0], y = v[1], z = v[2];
@@ -199,6 +213,14 @@
     out[2] = x*m[2] + y*m[5] + z*m[8];
 }
 
+void Math::tmul33(float* m, double* v, double* out)
+{
+    double x = v[0], y = v[1], z = v[2];
+    out[0] = x*m[0] + y*m[3] + z*m[6];
+    out[1] = x*m[1] + y*m[4] + z*m[7];
+    out[2] = x*m[2] + y*m[5] + z*m[8];
+}
+
 void Math::invert33(float* m, float* out)
 {
     // Compute the inverse as the adjoint matrix times 1/(det M).
Index: src/FDM/YASim/Math.hpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Math.hpp,v
retrieving revision 1.5
diff -u -r1.5 Math.hpp
--- src/FDM/YASim/Math.hpp	14 Sep 2006 18:18:33 -0000	1.5
+++ src/FDM/YASim/Math.hpp	23 Feb 2009 23:14:50 -0000
@@ -51,15 +51,19 @@
     //                          3 4 5
     //                          6 7 8
 
+    // Copy matrix
+    static void set33(float* a, float* b);
     // Multiply two matrices
     static void mmul33(float* a, float* b, float* out);
 
     // Multiply by vector
     static void vmul33(float* m, float* v, float* out);
+    static void vmul33(float* m, double* v, double* out);
 
     // Multiply the vector by the matrix transpose.  Or pre-multiply the
     // matrix by v as a row vector.  Same thing.
     static void tmul33(float* m, float* v, float* out);
+    static void tmul33(float* m, double* v, double* out);
 
     // Invert matrix
     static void invert33(float* m, float* out);
Index: src/FDM/YASim/Model.cpp
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/FDM/YASim/Model.cpp,v
retrieving revision 1.14
diff -u -r1.14 Model.cpp
--- src/FDM/YASim/Model.cpp	17 Jan 2007 20:42:39 -0000	1.14
+++ src/FDM/YASim/Model.cpp	23 Feb 2009 23:14:51 -0000
@@ -324,10 +324,10 @@
         int type;
         const SGMaterial* material;
         _ground_cb->getGroundPlane(pt, global_ground, global_vel,
-                              &type,&material);
+                                   &type, &material);
         static int h=0;
         g->setGlobalGround(global_ground, global_vel, pt[0], pt[1],
-            type,material);
+                           type, material);
     }
 
     for(i=0; i<_hitches.size(); i++) {
@@ -486,7 +486,7 @@
 	float force[3], contact[3];
 	Gear* g = (Gear*)_gears.get(i);
 
-	g->calcForce(&_body, s, lv, lrot);
+	g->calcForce(_ground_cb, &_body, s, lv, lrot);
 	g->getForce(force, contact);
 	_body.addForce(contact, force);
     }
@@ -529,24 +529,25 @@
 
         if (!g->getSubmergable())
         {
-	    // Get the point of ground contact
+            // Get the point of ground contact
             float pos[3], cmpr[3];
-	    g->getPosition(pos);
-	    g->getCompression(cmpr);
-	    Math::mul3(g->getCompressFraction(), cmpr, cmpr);
-	    Math::add3(cmpr, pos, pos);
+            g->getPosition(pos);
+            g->getCompression(cmpr);
+            Math::mul3(g->getCompressFraction(), cmpr, cmpr);
+            Math::add3(cmpr, pos, pos);
 
             // The plane transformed to local coordinates.
             double global_ground[4];
             g->getGlobalGround(global_ground);
             float ground[4];
             s->planeGlobalToLocal(global_ground, ground);
-	    float dist = ground[3] - Math::dot3(pos, ground);
+            float dist = ground[3] - Math::dot3(pos, ground);
 
-	    // Find the lowest one
-	    if(dist < min)
-	        min = dist;
+            // Find the lowest one
+            if(dist < min)
+                min = dist;
         }
+	g->updateStuckPoint(s);
     }
     _agl = min;
     if(_agl < -1) // Allow for some integration slop
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to