]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/AIMultiplayer.cxx
Interim windows build fix
[flightgear.git] / src / AIModel / AIMultiplayer.cxx
index 0b73c9ba4d7eb1874fd1972d877a9d3acd6c27ca..a4176b3a6d7076fb0e0726a2051384a2dc827251 100644 (file)
 #endif
 
 #include <string>
+#include <stdio.h>
+
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
 
 #include "AIMultiplayer.hxx"
 
+using std::string;
 
 // #define SG_DEBUG SG_ALERT
 
 FGAIMultiplayer::FGAIMultiplayer() :
-   FGAIBase(otMultiplayer, false)
+   FGAIBase(otMultiplayer, fgGetBool("/sim/multiplay/hot", false))
 {
    no_roll = false;
 
@@ -42,6 +47,8 @@ FGAIMultiplayer::FGAIMultiplayer() :
    mLagAdjustSystemSpeed = 10;
    mLastTimestamp = 0;
    lastUpdateTime = 0;
+   playerLag = 0.03;
+   compensateLag = 1;
 
 } 
 
@@ -54,8 +61,8 @@ bool FGAIMultiplayer::init(bool search_in_AI_path) {
     isTanker = false; // do this until this property is
                       // passed over the net
 
-    string str1 = _getCallsign();
-    string str2 = "MOBIL";
+    const string& str1 = _getCallsign();
+    const string str2 = "MOBIL";
 
     string::size_type loc1= str1.find( str2, 0 );
     if ( (loc1 != string::npos && str2 != "") ){
@@ -79,7 +86,10 @@ void FGAIMultiplayer::bind() {
 
     tie("controls/invisible",
         SGRawValuePointer<bool>(&invisible));
-
+       _uBodyNode = props->getNode("velocities/uBody-fps", true);
+       _vBodyNode = props->getNode("velocities/vBody-fps", true);
+       _wBodyNode = props->getNode("velocities/wBody-fps", true);
+       
 #define AIMPROProp(type, name) \
 SGRawValueMethods<FGAIMultiplayer, type>(*this, &FGAIMultiplayer::get##name)
 
@@ -93,7 +103,10 @@ SGRawValueMethods<FGAIMultiplayer, type>(*this, \
         AIMPRWProp(bool, AllowExtrapolation));
     tie("controls/lag-adjust-system-speed",
         AIMPRWProp(double, LagAdjustSystemSpeed));
-
+    tie("controls/player-lag",
+        AIMPRWProp(double, playerLag));
+    tie("controls/compensate-lag",
+        AIMPRWProp(int, compensateLag));
 
 #undef AIMPROProp
 #undef AIMPRWProp
@@ -135,7 +148,18 @@ void FGAIMultiplayer::update(double dt)
     mTimeOffsetSet = true;
     mTimeOffset = curentPkgTime - curtime - lag;
   } else {
-    double offset = curentPkgTime - curtime - lag;
+         double offset = 0.0;
+
+               //spectator mode, more late to be in the interpolation zone
+    if (compensateLag == 3) { offset = curentPkgTime -curtime -lag + playerLag;
+
+                 // old behaviour
+    } else if (compensateLag == 1) { offset = curentPkgTime - curtime - lag;
+
+    // using the prediction mode to display the mpaircraft in the futur/past with given playerlag value
+    //currently compensatelag = 2
+    } else { offset = curentPkgTime - curtime + 0.48*lag + playerLag;
+    }
     if ((!mAllowExtrapolation && offset + lag < mTimeOffset)
         || (offset - 10 > mTimeOffset)) {
       mTimeOffset = offset;
@@ -149,14 +173,27 @@ void FGAIMultiplayer::update(double dt)
       // arriving packets will pessimize the overall lag much more than
       // early packets will shorten the overall lag
       double sysSpeed;
-      if (err < 0) {
-        // Ok, we have some very late packets and nothing newer increase the
-        // lag by the given speedadjust
-        sysSpeed = mLagAdjustSystemSpeed*err;
-      } else {
-        // We have a too pessimistic display delay shorten that a small bit
-        sysSpeed = SGMiscd::min(0.1*err*err, 0.5);
-      }
+
+  //trying to slow the rudderlag phenomenon thus using more the prediction system
+  //if we are off by less than 1.5s, do a little correction, and bigger step above 1.5s
+         if (fabs(err) < 1.5) {
+               if (err < 0) {
+                 sysSpeed = mLagAdjustSystemSpeed*err*0.01;
+           } else {
+               sysSpeed = SGMiscd::min(0.5*err*err, 0.05);
+               }
+         } else {
+               if (err < 0) {
+
+                       // Ok, we have some very late packets and nothing newer increase the
+                       // lag by the given speedadjust
+                       sysSpeed = mLagAdjustSystemSpeed*err;
+               } else {
+                       // We have a too pessimistic display delay shorten that a small bit
+                       sysSpeed = SGMiscd::min(0.1*err*err, 0.5);
+          }
+         }
+
 
       // simple euler integration for that first order system including some
       // overshooting guard to prevent to aggressive system speeds
@@ -180,6 +217,7 @@ void FGAIMultiplayer::update(double dt)
 
   SGVec3d ecPos;
   SGQuatf ecOrient;
+  SGVec3f ecLinearVel;
 
   if (tInterp <= curentPkgTime) {
     // Ok, we need a time prevous to the last available packet,
@@ -193,7 +231,8 @@ void FGAIMultiplayer::update(double dt)
       MotionInfo::iterator firstIt = mMotionInfo.begin();
       ecPos = firstIt->second.position;
       ecOrient = firstIt->second.orientation;
-      speed = norm(firstIt->second.linearVel) * SG_METER_TO_NM * 3600.0;
+      ecLinearVel = firstIt->second.linearVel;
+      speed = norm(ecLinearVel) * SG_METER_TO_NM * 3600.0;
 
       std::vector<FGPropertyData*>::const_iterator firstPropIt;
       std::vector<FGPropertyData*>::const_iterator firstPropItEnd;
@@ -256,8 +295,8 @@ void FGAIMultiplayer::update(double dt)
       ecPos = ((1-tau)*prevIt->second.position + tau*nextIt->second.position);
       ecOrient = interpolate((float)tau, prevIt->second.orientation,
                              nextIt->second.orientation);
-      speed = norm((1-tau)*prevIt->second.linearVel
-                   + tau*nextIt->second.linearVel) * SG_METER_TO_NM * 3600.0;
+      ecLinearVel = ((1-tau)*prevIt->second.linearVel + tau*nextIt->second.linearVel);
+      speed = norm(ecLinearVel) * SG_METER_TO_NM * 3600.0;
 
       if (prevIt->second.properties.size()
           == nextIt->second.properties.size()) {
@@ -331,37 +370,40 @@ void FGAIMultiplayer::update(double dt)
     // and do some eom computation to guess that for now.
     FGExternalMotionData& motionInfo = it->second;
 
-    // The time to predict, limit to 5 seconds
+    // The time to predict, limit to 3 seconds
     double t = tInterp - motionInfo.time;
-    t = SGMisc<double>::min(t, 5);
+    t = SGMisc<double>::min(t, 3);
 
     SG_LOG(SG_AI, SG_DEBUG, "Multiplayer vehicle extrapolation: "
            "extrapolation time = " << t);
 
-    // Do a few explicit euler steps with the constant acceleration's
-    // This must be sufficient ...
+    // using velocity and acceleration to guess a parabolic position...
     ecPos = motionInfo.position;
     ecOrient = motionInfo.orientation;
-    SGVec3f linearVel = motionInfo.linearVel;
+    ecLinearVel = motionInfo.linearVel;
+    SGVec3d ecVel = toVec3d(ecOrient.backTransform(ecLinearVel));
     SGVec3f angularVel = motionInfo.angularVel;
-    while (0 < t) {
-      double h = 1e-1;
-      if (t < h)
-        h = t;
+    SGVec3d ecAcc = toVec3d(ecOrient.backTransform(motionInfo.linearAccel));
 
-      SGVec3d ecVel = toVec3d(ecOrient.backTransform(linearVel));
-      ecPos += h*ecVel;
-      ecOrient += h*ecOrient.derivative(angularVel);
+       double normVel = norm(ecVel);
 
-      linearVel += h*(cross(linearVel, angularVel) + motionInfo.linearAccel);
-      angularVel += h*motionInfo.angularAccel;
-      
-      t -= h;
-    }
+       // not doing rotationnal prediction for small speed or rotation rate,
+       // to avoid agitated parked plane
+    if (( norm(angularVel) > 0.05 ) || ( normVel > 1.0 )) {
+               ecOrient += t*ecOrient.derivative(angularVel);
+       }
+
+       // not using acceleration for small speed, to have better parked planes
+       // note that anyway acceleration is not transmit yet by mp
+       if ( normVel > 1.0 ) {
+               ecPos += t*(ecVel + 0.5*t*ecAcc);
+       } else {
+               ecPos += t*(ecVel);
+       }
 
-    std::vector<FGPropertyData*>::const_iterator firstPropIt;
+       std::vector<FGPropertyData*>::const_iterator firstPropIt;
     std::vector<FGPropertyData*>::const_iterator firstPropItEnd;
-    speed = norm(linearVel) * SG_METER_TO_NM * 3600.0;
+    speed = norm(ecLinearVel) * SG_METER_TO_NM * 3600.0;
     firstPropIt = it->second.properties.begin();
     firstPropItEnd = it->second.properties.end();
     while (firstPropIt != firstPropItEnd) {
@@ -432,6 +474,11 @@ void FGAIMultiplayer::update(double dt)
   roll = rDeg;
   pitch = pDeg;
 
+  // expose velocities/u,v,wbody-fps in the mp tree
+  _uBodyNode->setValue(ecLinearVel[0] * SG_METER_TO_FEET);
+  _vBodyNode->setValue(ecLinearVel[1] * SG_METER_TO_FEET);
+  _wBodyNode->setValue(ecLinearVel[2] * SG_METER_TO_FEET);
+
   SG_LOG(SG_AI, SG_DEBUG, "Multiplayer position and orientation: "
          << ecPos << ", " << hlOr);