Patching latest TORCS changes in CVS

David Savinkoff <[email protected]> Sat, 25 Feb 2017 01:52:16 -0700 (MST)
Newsgroups gmane.games.torcs.general
Message-ID <316074698.53138712.1488012736232.JavaMail.zimbra@mailid.telus.net>
Here is a patch to play with.
Correctly combined longitudinal, lateral, and yaw tire friction forces.
(realistic and predictable vehicular response where the rubber meets the road)

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

_______________________________________________
Torcs-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/torcs-users
torcs-1.3.8.contact.patch (text/x-patch, 12.6 KB)
--- torcs/src/modules/graphic/ssggraph/CarSoundData.cpp	2014-02-10 03:16:18.000000000 -0800
+++ torcs/src/modules/graphic/ssggraph/CarSoundData.cpp	2017-02-24 20:37:21.212075558 -0800
@@ -315,29 +315,30 @@
 
     }
 
+// Calculate road-tire contact noise positions with an efficient formula.
+// note that sin(az) is nearly equal to az [in radians].
+// note that cos(az) is close to 1.0 for moderate yaw angles.
+// note that the contact patch is beneath GC (approx -0.3 metres).
+    tdble az = car->_yaw;
     for (i = 0; i<4; i++) {
-        tdble az = car->_yaw;
-        tdble Sinz = sin(az);
-        tdble Cosz = cos(az);
-                
         tdble x = car->priv.wheel[i].relPos.x;
         tdble y = car->priv.wheel[i].relPos.y;
                 
-        tdble dx = x * Cosz - y * Sinz;
-        tdble dy = x * Sinz + y * Cosz;
+        tdble dx = x - y*az; // x*cos(az) - y*sin(az)
+        tdble dy = x*az + y;
                 
         tdble dux = -car->_yaw_rate * y;
         tdble duy = car->_yaw_rate * x;
                 
-        dux = dux * Cosz - duy * Sinz;
-        duy = dux * Sinz + duy * Cosz;
+        dux = dux - duy*az;
+        duy = dux*az + duy;
                 
         wheel[i].u[0] = car->pub.DynGCg.vel.x + dux;
         wheel[i].u[1] = car->pub.DynGCg.vel.y + duy;
         wheel[i].u[2] = car->pub.DynGCg.vel.z;
         wheel[i].p[0] = car->pub.DynGCg.pos.x + dx;
         wheel[i].p[1] = car->pub.DynGCg.pos.y + dy;
-        wheel[i].p[2] = car->pub.DynGCg.pos.z;
+        wheel[i].p[2] = car->pub.DynGCg.pos.z - 0.3f;
     }
 }
 
--- torcs/src/modules/graphic/ssggraph/grskidmarks.cpp	2014-02-10 03:09:36.000000000 -0800
+++ torcs/src/modules/graphic/ssggraph/grskidmarks.cpp	2017-02-24 20:37:21.213075570 -0800
@@ -199,11 +199,7 @@
 			}
 		}
 
-		if (car->_skid[i] > 0.1f) {
-			cur_clr[3] = tanh(skid_sensitivity*car->_skid[i]);
-		} else {
-			cur_clr[3] = 0.0f;
-		}
+		cur_clr[3] = skid_sensitivity*car->_skid[i]; // linear (tanh removed, see wheel.cpp)
 
 		for (int c = 0; c < 3; c++) {
 			tdble tmp = grCarInfo[car->index].skidmarks->strips[i].smooth_colour[c];
@@ -216,7 +212,7 @@
 		}
 
 		if (car->pub.speed > 1.0f) {
-	    	if (cur_clr[3] > 0.1f) {
+	    	if (cur_clr[3] > 0.1f) { // 0.06 works better than 0.1 // something here improves traction ?!
                 
 				basevtx = new ssgVertexArray(4 * 2 + 1);
 				tdble sling_left = 0.0f;
--- torcs/src/modules/simu/simuv2/car.cpp	2017-02-12 09:45:57.000000000 -0800
+++ torcs/src/modules/simu/simuv2/car.cpp	2017-02-24 20:37:21.214075587 -0800
@@ -64,7 +64,7 @@
 	}
 	k = k * k;
 	car->Iinv.x = 12.0 / (car->mass * (car->dimension.y * car->dimension.y + car->dimension.z * car->dimension.z));
-	car->Iinv.y = 12.0 / (car->mass * (car->dimension.x * car->dimension.x + car->dimension.z * car->dimension.z));
+	car->Iinv.y = 12.0 / (car->mass * (k * car->dimension.x * car->dimension.x + car->dimension.z * car->dimension.z));
 	car->Iinv.z = 12.0 / (car->mass * (car->dimension.y * car->dimension.y + k * car->dimension.x * car->dimension.x));
 	
 	/* configure components */
@@ -145,10 +145,7 @@
 	tForces	F;
 	int		i;
 	tdble	m, w, minv;
-	tdble	v, R, Rv, Rm, Rx, Ry, Rz;
 
-	car->preDynGC = car->DynGCg;
-	
 	/* total mass */
 	m = car->mass + car->fuel;
 	minv = 1.0 / m;
@@ -200,34 +197,10 @@
 		F.M.y -= car->aero.lift[i] * (car->axle[i].xpos - car->statGC.x);
 	}
 		
-	/* Rolling Resistance */
-	v = car->speed;
-	R = 0.0f;
-	for (i = 0; i < 4; i++) {
-		R += car->wheel[i].rollRes;
-	}
-	if (v > 0.00001f) {
-		Rv = R / v;
-		if ((Rv * minv * SimDeltaTime) > v) {
-			Rv = v * m / SimDeltaTime;
-		}
-	} else {
-		Rv = 0.0f;
-	}
-	Rx = Rv * car->DynGC.vel.x;
-	Ry = Rv * car->DynGC.vel.y;
-	Rz = Rv * car->DynGC.vel.z;
-	
-	if ((R * car->wheelbase / 2.0 * car->Iinv.z) > fabs(car->DynGCg.vel.az)) {
-		Rm = car->DynGCg.vel.az / car->Iinv.z;
-	} else {
-		Rm = SIGN(car->DynGCg.vel.az) * R * car->wheelbase / 2.0;
-	}
-	
 	/* compute accelerations */
-	car->DynGC.acc.x = (F.F.x - Rx) * minv;
-	car->DynGC.acc.y = (F.F.y - Ry) * minv;
-	car->DynGC.acc.z = (F.F.z - Rz) * minv;
+	car->DynGC.acc.x = F.F.x * minv;
+	car->DynGC.acc.y = F.F.y * minv;
+	car->DynGC.acc.z = F.F.z * minv;
 	
 	sgVec3 accel = {car->DynGC.acc.x, car->DynGC.acc.y, car->DynGC.acc.z};
 	sgXformVec3(accel, dst);
@@ -238,7 +211,7 @@
 
 	car->DynGCg.acc.ax = car->DynGC.acc.ax = F.M.x * car->Iinv.x;
 	car->DynGCg.acc.ay = car->DynGC.acc.ay = F.M.y * car->Iinv.y;
-	car->DynGCg.acc.az = car->DynGC.acc.az = (F.M.z - Rm) * car->Iinv.z;
+	car->DynGCg.acc.az = car->DynGC.acc.az += F.M.z * car->Iinv.z; // += see torcs/src/modules/simu/simuv2/simu.cpp :: SimUpdate()
 }
 
 static void
@@ -256,7 +229,15 @@
 	if (fabs(car->DynGCg.vel.az) > 9.0) {
 		car->DynGCg.vel.az = SIGN(car->DynGCg.vel.az) * 9.0;
 	}
-		
+
+	/* FIXME: Hack to stop stationary car from rotating */
+	if ((	car->DynGCg.vel.x*car->DynGCg.vel.x +
+		car->DynGCg.vel.y*car->DynGCg.vel.y +
+		car->DynGCg.vel.z*car->DynGCg.vel.z) < 0.01f )
+	{
+		car->DynGCg.vel.ax = car->DynGCg.vel.ay = car->DynGCg.vel.az = 0.0f;
+	}
+
 	car->DynGC.vel.ax = car->DynGCg.vel.ax;
 	car->DynGC.vel.ay = car->DynGCg.vel.ay;
 	car->DynGC.vel.az = car->DynGCg.vel.az;
--- torcs/src/modules/simu/simuv2/simu.cpp	2017-02-19 05:09:00.000000000 -0800
+++ torcs/src/modules/simu/simuv2/simu.cpp	2017-02-24 20:37:21.215075600 -0800
@@ -385,6 +385,7 @@
 				SimAxleUpdate(car, i);
 			}
 			CHECK(car);
+			car->DynGC.acc.az = 0.0f; // see torcs/src/modules/simu/simuv2/wheel.cpp :: SimWheelUpdateForce()
 			for (i = 0; i < 4; i++){
 				SimWheelUpdateForce(car, i);
 				SimWheelUpdateTire(car, i);
--- torcs/src/modules/simu/simuv2/susp.cpp	2017-01-15 04:52:16.000000000 -0800
+++ torcs/src/modules/simu/simuv2/susp.cpp	2017-02-24 20:37:21.216075618 -0800
@@ -107,9 +107,9 @@
 	}
 	
 	susp->x *= susp->spring.bellcrank;
-	if (susp->x > susp->spring.xMax) {
+	if (susp->x >= susp->spring.xMax) { // Tested OK with '>=' (SD r6020)
 		susp->x = susp->spring.xMax;
-		susp->state = SIM_SUSP_EXT;
+		susp->state = SIM_SUSP_EXT; // susp->state updated also
 	}
 }
 
--- torcs/src/modules/simu/simuv2/wheel.cpp	2017-02-13 15:51:07.000000000 -0800
+++ torcs/src/modules/simu/simuv2/wheel.cpp	2017-02-24 20:37:21.217075619 -0800
@@ -47,9 +47,9 @@
 	Ca                    = GfParmGetNum(hdle, WheelSect[index], PRM_CA, (char*)NULL, 30.0f);
 	RFactor               = GfParmGetNum(hdle, WheelSect[index], PRM_RFACTOR, (char*)NULL, 0.8f);
 	EFactor               = GfParmGetNum(hdle, WheelSect[index], PRM_EFACTOR, (char*)NULL, 0.7f);
-	wheel->lfMax          = GfParmGetNum(hdle, WheelSect[index], PRM_LOADFMAX, (char*)NULL, 1.6f);
-	wheel->lfMin          = GfParmGetNum(hdle, WheelSect[index], PRM_LOADFMIN, (char*)NULL, 0.8f);
-	wheel->opLoad         = GfParmGetNum(hdle, WheelSect[index], PRM_OPLOAD, (char*)NULL, wheel->weight0 * 1.2f);
+	wheel->lfMax          = GfParmGetNum(hdle, WheelSect[index], PRM_LOADFMAX, (char*)NULL, 1.4f);
+	wheel->lfMin          = GfParmGetNum(hdle, WheelSect[index], PRM_LOADFMIN, (char*)NULL, 1.0f);
+	wheel->opLoad         = GfParmGetNum(hdle, WheelSect[index], PRM_OPLOAD, (char*)NULL, wheel->weight0 * 1.618f);
 	wheel->mass           = GfParmGetNum(hdle, WheelSect[index], PRM_MASS, (char*)NULL, 20.0f);
 	
 	wheel->lfMin = MIN(0.8f, wheel->lfMin);
@@ -213,12 +213,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 = 0.000000f; // wheel related velocity
 	tdble Fn, Ft;
 	tdble waz;
-	tdble CosA, SinA;
-	tdble s, sa, sx, sy; // slip vector
-	tdble stmp, F, Bx;
+	double CosA, SinA;
+	tdble s, sx, sy, saz; // slip vector
+	tdble F, Bx;
 	tdble mu;
 	wheel->state = 0;
 
@@ -248,44 +248,45 @@
 	}
 
 	// HORIZONTAL FORCES
-	waz = wheel->steer + wheel->staticPos.az;
+	waz = wheel->steer + wheel->staticPos.az - (SimDeltaTime*car->DynGC.vel.az /* account for yaw induced wheel direction */);
 	CosA = cos(waz);
 	SinA = sin(waz);
 
 	// 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);
+	v = sqrtf(v2);
 
-	// slip angle
-	if (v < 0.000001f) {
-		sa = 0.0f;
-	} else {
-		sa = atan2(wheel->bodyVel.y, wheel->bodyVel.x) - waz;
+	wrl = wheel->spinVel * wheel->radius;
+
+	if (fabsf(vt - wrl) <= 0.1f) { // Adds numerical stability by catching adhesion
+		vt = wrl;
 	}
-	NORM_PI_PI(sa);
 
-	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;
+		sx = sy = saz = 0.0f;
 	} else {
-		sx = (vt - wrl) / fabs(vt);
-		sy = sin(sa);
+		// COMBINED LONGITUDINAL, LATERAL, and YAWING TIRE SLIP FORCES:
+		// 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.
+		// saz slip speed accounts for rotating the contact patch (yaw). * add steering speed and self aligning torque.
+		saz = (1.1f*3.1416f) * car->DynGC.vel.az * car->carElt->_tireWidth(index); // yaw slip speed.
+		slip_magnitude = 0.000001f + /* Softening factor 0.000001 prevents divide by zero */
+				sqrt( MAX(MAX((v2 + saz*saz), (vn*vn + wrl*wrl + saz*saz)), (vn*vn + (vt - wrl)*(vt - wrl) + saz*saz)) );
+		sx = (vt - wrl) / slip_magnitude;
+		sy = vn / slip_magnitude;
+		saz /= slip_magnitude;
 	}
-	
-	Ft = 0.0f;
-	Fn = 0.0f;
-	s = sqrt(sx*sx+sy*sy);
+
+	s = sqrtf(sx*sx+sy*sy+saz*saz);
 
 	{
-		// calculate _skid and _reaction for sound.
-		if (v < 2.0f) {
+		// calculate _skid and _reaction for sound (suspiciously; affects traction also).
+		if ((v < 0.01f) || (zforce < 0.002f)) {
 			car->carElt->_skid[index] = 0.0f;
 		} else {
-			car->carElt->_skid[index] =  MIN(1.0f, (s*zforce*0.0002f));
+			car->carElt->_skid[index] = s; // linear (tanh removed in grskidmarks.cpp)
 		}
 	}
 
@@ -299,47 +300,48 @@
 		camberDelta = casterCamber;
 	}
 
-	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]);
+	// MAGIC FORMULA // Note: F = sin(...) below returns normalized force!
+	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));
 
 	F *= zforce * mu * wheel->trkPos.seg->surface->kFriction * (1.0f + 0.05f * sin((-wheel->staticPos.ax + camberDelta) * 18.0f));	/* coeff */
 	F *= wheel->currentGripFactor;
-	
+
 	wheel->rollRes = zforce * wheel->trkPos.seg->surface->kRollRes;
-    car->carElt->priv.wheel[index].rollRes = wheel->rollRes;
+	// wheel axis based
+	s += 0.000001f; // add 0.000001 to avoid divide by zero later.
+	Ft = -(F - wheel->rollRes) * sx/s; // rolling resistance is the rolling vector component only.
+	Fn = -F * sy/s;
 
-	if (s > 0.000001f) {
-		// wheel axis based
-		Ft -= F * sx / s;
-		Fn -= F * sy / s;
-	}
+	car->DynGC.acc.az += -F * saz/s * SimDeltaTime * car->Iinv.z; // see torcs/src/modules/simu/simuv2/simu.cpp :: SimUpdate()
 
-	RELAXATION2(Fn, wheel->preFn, 50.0f);
-	RELAXATION2(Ft, wheel->preFt, 50.0f);
+	wheel->rollRes *= fabsf(sx/s); // not used (removed from /src/modules/simu/simuv2/car.cpp)
+	car->carElt->priv.wheel[index].rollRes = wheel->rollRes; // not used in /src/modules/graphic/ssggraph/CarSoundData.cpp
+
+	waz = wheel->steer + wheel->staticPos.az; /* don't include yaw induced wheel direction here */
+	CosA = cos(waz);
+	SinA = sin(waz);
 
 	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 = atan2(wheel->bodyVel.y, wheel->bodyVel.x) - waz;
 	wheel->sx = sx;
 
 	wheel->tireZForce = zforce;
-	wheel->tireSlip = stmp;
+	wheel->tireSlip = s;
 
 	wheel->feedBack.spinVel = wheel->spinVel;
 	wheel->feedBack.Tq = wheel->spinTq;
 	wheel->feedBack.brkTq = wheel->brake.Tq;
 
-	car->carElt->_wheelSlipSide(index) = sy*v;
-	car->carElt->_wheelSlipAccel(index) = sx*v;
+	car->carElt->_wheelSlipSide(index) = vn;
+	car->carElt->_wheelSlipAccel(index) = vt*(1.0f-sx); // Is wheelSlipAccel the wheel tangent velocity times adhesion ?
 	car->carElt->_reaction[index] = zforce;
 }
 
@@ -354,8 +356,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;