Re: Patch for wheel spin velocity traction

David Savinkoff <[email protected]> Thu, 7 Jan 2016 17:58:49 -0700 (MST)
Newsgroups gmane.games.torcs.general
Message-ID <271731365.25264110.1452214729164.JavaMail.zimbra@mailid.telus.net>
This patch removes legacy duct tape which was used as a
work-around for a previously nonexistent friction circle.

There is another piece of duct tape which impedes the car
from accelerating forward while allowing unimpeded sideways
acceleration when drifting. I'll remove that when I find it.

Note that RELAXATION2 is a low-pass Infinite Impulse Response
filter of the form: f(s) = as/(b+as) where s is in the s-domain,
'a' is a spring-constant, and 'b' is a friction constant
mechanically acting on the rotation of the wheel. This will
certainly affect the physics of TORCS.

----- David Savinkoff wrote:
> Hi Everybody,
> 
> This patch makes TORCS the best simulator wherever
> 'The Rubber meets the Road' is concerned. Try it.
> 
> ----- David Savinkoff wrote:
> > ----- David Savinkoff wrote:
> > > Hi,
> > > 
> > > In my last patch I had the following code:
> > > slip_magnitude = 0.000001f + sqrt( MAX(MAX((vn*vn + vt*vt)
> > > 
> > > Where (v2) should be equal to (vn*vn + vt*vt) but is not,
> > > because of lack of precision of the float data type.
> > > 
> > > Here I use (v2) for velocity squared because the car drives
> > > noticeably better, and (v2) is obviously more accurate.
> > > 
> > > slip_magnitude = 0.000001f + sqrt( MAX(MAX((v2)
> > > 
> > > BTW is there somewhere I can find recent TORCS source code
> > > changes so that I can test and experiment?
> > > 
> > > Sincerely,
> > > David Savinkoff
> > 
> > Hi,
> > 
> > Here is another patch for floating point improvements.
> > 
> > I used sqrtf() where it seemed to make a speed improvement
> > on my slow computer.
> > 
> > I used (double) to get more accuracy for CosA and SinA
> > 
> > It is obvious that (float) is not sufficient in some
> > circumstances, and that (double) is slower in others.
> > 
> > I hope these improvements in wheel.cpp help with making
> > other problems more characterizable.
> > 
> > Sincerely,
> > David Savinkoff
> > 
> > ps.
> > 
> > Speed Dreams should incorporate this patch too.
> > Note that this patch will give you deja vu a few times
> > per lap (even if you do motocross).
>

------------------------------------------------------------------------------

_______________________________________________
Torcs-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/torcs-users
wheel.cpp.2016jan06.diff (text/x-patch, 3.6 KB)
--- torcs-1.3.6/src/modules/simu/simuv2/wheel.cpp	2013-08-29 06:01:32.000000000 -0700
+++ torcs-1.3.6/src/modules/simu/simuv2/wheel.cpp	2016-01-07 15:51:23.848132581 -0800
@@ -174,12 +174,12 @@
 {
 	tWheel *wheel = &(car->wheel[index]);
 	tdble axleFz = wheel->axleFz;
-	tdble vt, v, v2, wrl; // wheel related velocity
+	tdble vt, vn, v, v2, wrl, slip_magnitude; // wheel related velocity
 	tdble Fn, Ft;
 	tdble waz;
-	tdble CosA, SinA;
+	double CosA, SinA;
 	tdble s, sa, sx, sy; // slip vector
-	tdble stmp, F, Bx;
+	tdble F, Bx;
 	tdble mu;
 	wheel->state = 0;
 
@@ -215,46 +215,39 @@
 
 	// tangent velocity.
 	vt = wheel->bodyVel.x * CosA + wheel->bodyVel.y * SinA;
+	vn = wheel->bodyVel.y * CosA - wheel->bodyVel.x * SinA;
 	v2 = wheel->bodyVel.x * wheel->bodyVel.x + wheel->bodyVel.y * wheel->bodyVel.y;
-	v = sqrt(v2);
-
-	// slip angle
-	if (v < 0.000001f) {
-		sa = 0.0f;
-	} else {
-		sa = atan2(wheel->bodyVel.y, wheel->bodyVel.x) - waz;
-	}
-	NORM_PI_PI(sa);
+	v = sqrtf(v2);
 
 	wrl = wheel->spinVel * wheel->radius;
+
 	if ((wheel->state & SIM_WH_ONAIR) != 0) {
 		sx = sy = 0.0f;
-	} else if (v < 0.000001f) {
-		sx = wrl;
-		sy = 0.0f;
 	} else {
-		sx = (vt - wrl) / fabs(vt);
-		sy = sin(sa);
+		// Normalize the friction circle to get normalized vector components (sx, sy) while
+		// braking (vt), accelerating (wrl), or wheel counter spin (vt - wrl) for any angle.
+		// Softening factor 0.36 added to slip_magnitude affects low velocities and divide by zero.
+		slip_magnitude = 0.36f + sqrt( MAX(MAX((v2), (vn*vn + wrl*wrl)), (vn*vn + (vt - wrl)*(vt - wrl))) );
+		sx = (vt - wrl) / slip_magnitude;
+		sy = vn / slip_magnitude;
 	}
 
-	Ft = 0.0f;
-	Fn = 0.0f;
-	s = sqrt(sx*sx+sy*sy);
+	s = sqrtf(sx*sx+sy*sy);
 
 	{
 		// calculate _skid and _reaction for sound.
-		if (v < 2.0f) {
+		if ((v < 2.0f) || (zforce < 0.0002f)) {
 			car->carElt->_skid[index] = 0.0f;
 		} else {
-			car->carElt->_skid[index] =  MIN(1.0f, (s*zforce*0.0002f));
+			// skid energy :: F*d :: v*v :: s*s ... the empirical equation:
+			// n*(s*s + s) is represented in Damped Simple Harmonic Motion
+			car->carElt->_skid[index] = 0.63662f*(s*s+s); // 0.63662 = 2/pi
 		}
 	}
 
-	stmp = MIN(s, 1.5f);
-	
 	// MAGIC FORMULA
-	Bx = wheel->mfB * stmp;
-	F = sin(wheel->mfC * atan(Bx * (1.0f - wheel->mfE) + wheel->mfE * atan(Bx))) * (1.0f + stmp * simSkidFactor[car->carElt->_skillLevel]);
+	Bx = wheel->mfB * s;
+	F = sin(wheel->mfC * atan(Bx * (1.0f - wheel->mfE) + wheel->mfE * atan(Bx))) * (1.0f + s * simSkidFactor[car->carElt->_skillLevel]);
 
 	// load sensitivity
 	mu = wheel->mu * (wheel->lfMin + (wheel->lfMax - wheel->lfMin) * exp(wheel->lfK * zforce / wheel->opLoad));
@@ -264,21 +257,17 @@
 	wheel->rollRes = zforce * wheel->trkPos.seg->surface->kRollRes;
     car->carElt->priv.wheel[index].rollRes = wheel->rollRes;
 
-	if (s > 0.000001f) {
-		// wheel axis based
-		Ft -= F * sx / s;
-		Fn -= F * sy / s;
-	}
-
-	RELAXATION2(Fn, wheel->preFn, 50.0f);
-	RELAXATION2(Ft, wheel->preFt, 50.0f);
+	// wheel axis based
+	s = -0.000001f - s; // make Ft, Fn and s negative with stable divide by zero avoidance.
+	Ft = F * sx/s;
+	Fn = F * sy/s;
 
 	wheel->relPos.az = waz;
 
 	wheel->forces.x = Ft * CosA - Fn * SinA;
 	wheel->forces.y = Ft * SinA + Fn * CosA;
 	wheel->spinTq = Ft * wheel->radius;
-	wheel->sa = sa;
+	wheel->sa = asin(sy/-s);
 	wheel->sx = sx;
 
 	wheel->feedBack.spinVel = wheel->spinVel;
@@ -301,8 +290,6 @@
 		wheel = &(car->wheel[i]);
 		wheel->spinVel = wheel->in.spinVel;
 
-		RELAXATION2(wheel->spinVel, wheel->prespinVel, 50.0f);
-
 		wheel->relPos.ay += wheel->spinVel * SimDeltaTime;
 		NORM_PI_PI(wheel->relPos.ay);
 		car->carElt->_wheelSpinVel(i) = wheel->spinVel;