Re: Patch for wheel spin velocity traction

David Savinkoff <[email protected]> Mon, 11 Apr 2016 01:11:08 -0600 (MDT)
Newsgroups gmane.games.torcs.general
Message-ID <1049927673.36595567.1460358668485.JavaMail.zimbra@mailid.telus.net>
(SimDeltaTime*car->DynGC.vel.az /*account for yaw induced wheel direction*/)
This is no small requirement for maneuverability. Expect correctness.
----- David Savinkoff wrote:
> car->carElt->_wheelSlipAccel(index) = slip_magnitude;
> in wheel.c seems to work best. Now you can feel real
> traction interaction of the tire with the road, right through
> the suspension and inertia of the vehicle.
> 
> ----- David Savinkoff wrote:
> > This patch has more suspension improvements lifted from
> > TORCS on Sourceforge, and further tweaks to my code.
> > 
> > ----- David Savinkoff wrote:
> > > Hi,
> > > torcs-1.3.6/src/modules/graphic/ssggraph/grskidmarks.cpp:
> > > 
> > > if (cur_clr[3] > 0.06f) {
> > > // 0.06 works better than 0.1 // something here improves traction ?!
> > > 
> > > ----- David Savinkoff wrote:
> > > Hi,
> > > 
> > > This patch applies the latest change to wheel.cpp in
> > > TORCS on Sourcforge:
> > > $Id: wheel.cpp,v 1.26.2.6 2016/03/06 20:59:31 berniw Exp $
> > > 
> > > This patch (see patch) also removes a discontinuity by tanh() in
> > > modules/graphic/ssggraph/grskidmarks.cpp
> > > (The Magic Formula in wheel.cpp should determine traction)
> > > 
> > > Good to see torqs-1.3.7 on the way.
> > > 
> > > ----- David Savinkoff wrote:
> > > Hi,
> > > 
> > > This patch removes an un-needed tanh() from
> > > modules/graphic/ssggraph/grskidmarks.cpp
> > > and re-arranges some of my changes in wheel.cpp
> > > ( the tanh() trick was used to range limit input: -1 to 1 )
> > > 
> > > This patch is the most physically correct,
> > > and the best performing one yet.
> > > 
> > > Please apply this patch.
> > > 
> > > ----- David Savinkoff wrote:
> > > Hi,
> > > 
> > > This patch fixes a performance issue without compromise.
> > > Smaller, Faster, and Better sound and driving performance.
> > > You can hear which tire is squealing as you drift past
> > > another car. Yahoo!
> > > 
> > ----- David Savinkoff wrote:
> > > OK,
> > > 
> > > This patch goes beyond traction; it includes 2 bug fixes
> > > from Speed Dreams.
> > > 
> > > Yes, two serious physics impacting bugs.
> > > 
> > > Now you can get twice the realism by driving to the
> > > track in one car, and racing at the track in another.
> > > 
> > > ----- David Savinkoff wrote:
> > > Hi,
> > > This patch implements rolling resistance correctly along
> > > with some small changes. (wheel.cpp car.cpp)
> > > 
> > > Massive improvement. The TORCS simuv2 reference
> > > measure 'is' about to show all car sims 'how it is done'.
> > >
> > > ----- David Savinkoff wrote:
> > > Hi,
> > > 
> > > Yet another small improvement. Note that if some of these
> > > improvements appear odd, they are indicating problems
> > > hidden elsewhere.
> > > 
> > > ----- David Savinkoff wrote:
> > > Hi,
> > > This patch will probably be the last I make for
> > > wheel.cpp because I've meticulously examined and
> > > tested the code here repeatedly with results that have
> > > converged to perfection.
> > > 
> > > Please apply this patch.
> > > 
> > > ----- David Savinkoff wrote:
> > > > 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.
> > >
> > > This problem seems to be diminished as TORCS is made more
> > > correct.
> > > 
> > > > Note that RELAXATION2 is a low-pass Infinite Impulse Response
> > > > filter of the form: f(s) = (1/as) / (b+1/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:
> > > > Hi,
> > > > 
> > > > In my last patch I had the following code:
> > > > slip_magnitude = 0.3f + 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.3f + 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.
>

------------------------------------------------------------------------------
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial! http://pubads.g.doubleclick.net/
gampad/clk?id=1444514301&iu=/ca-pub-7940484522588532

_______________________________________________
Torcs-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/torcs-users
torcs-1.3.6.2016apr11.diff (text/x-patch, 13.8 KB)
--- torcs-1.3.6/src/modules/graphic/ssggraph/CarSoundData.cpp	2014-02-10 03:16:18.000000000 -0800
+++ torcs-1.3.6/src/modules/graphic/ssggraph/CarSoundData.cpp	2016-03-05 17:29:31.000000000 -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-1.3.6/src/modules/graphic/ssggraph/grskidmarks.cpp	2014-02-10 03:09:36.000000000 -0800
+++ torcs-1.3.6/src/modules/graphic/ssggraph/grskidmarks.cpp	2016-03-22 14:24:34.000000000 -0700
@@ -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-1.3.6/src/modules/simu/simuv2/axle.cpp	2013-08-29 07:21:44.000000000 -0700
+++ torcs-1.3.6/src/modules/simu/simuv2/axle.cpp	2016-03-20 17:59:40.000000000 -0700
@@ -2,9 +2,9 @@
 
     file                 : axle.cpp
     created              : Sun Mar 19 00:05:09 CET 2000
-    copyright            : (C) 2000-2013 by Eric Espie, Bernhard Wymann
+    copyright            : (C) 2000-2016 by Eric Espie, Bernhard Wymann
     email                : [email protected]
-    version              : $Id: axle.cpp,v 1.8.2.5 2013/08/29 14:21:44 berniw Exp $
+    version              : $Id: axle.cpp,v 1.8.2.6 2016/03/19 13:28:35 berniw Exp $
 
  ***************************************************************************/
 
@@ -82,7 +82,7 @@
 	axle->thirdSusp.v = (vl + vr)/2.0f;
 	SimSuspUpdate(&axle->thirdSusp);
 	tdble fthird = 0.0f;
-	if (axle->thirdSusp.x < axle->thirdSusp.spring.xMax) {
+	if (axle->thirdSusp.x < axle->thirdSusp.spring.xMax && axle->thirdSusp.force > 0.0f) {
 		fthird = axle->thirdSusp.force/2.0f;
 	}
 
--- torcs-1.3.6/src/modules/simu/simuv2/car.cpp	2014-02-10 02:06:30.000000000 -0800
+++ torcs-1.3.6/src/modules/simu/simuv2/car.cpp	2016-02-19 17:53:01.000000000 -0800
@@ -146,7 +146,6 @@
 	tdble	m, w, minv;
 	tdble	SinTheta;
 	tdble	Cosz, Sinz;
-	tdble	v, R, Rv, Rm, Rx, Ry;
 	
 	Cosz = car->Cosz = cos(car->DynGCg.pos.az);
 	Sinz = car->Sinz = sin(car->DynGCg.pos.az);
@@ -199,41 +198,18 @@
 		F.M.y -= car->aero.lift[i] * (car->axle[i].xpos - car->statGC.x);
 	}
 	
-	/* Rolling Resistance */
-	v = sqrt(car->DynGCg.vel.x * car->DynGCg.vel.x + car->DynGCg.vel.y * car->DynGCg.vel.y);
-	R = 0;
-	for (i = 0; i < 4; i++) {
-		R += car->wheel[i].rollRes;
-	}
-	if (v > 0.00001) {
-		Rv = R / v;
-		if ((Rv * minv * SimDeltaTime) > v) {
-			Rv = v * m / SimDeltaTime;
-		}
-	} else {
-		Rv = 0;
-	}
-	Rx = Rv * car->DynGCg.vel.x;
-	Ry = Rv * car->DynGCg.vel.y;
-	
-	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 * minv;
 	car->DynGC.acc.y = F.F.y * minv;
 	car->DynGC.acc.z = F.F.z * minv;
 	
-	car->DynGCg.acc.x = (F.F.x * Cosz - F.F.y * Sinz - Rx) * minv;
-	car->DynGCg.acc.y = (F.F.x * Sinz + F.F.y * Cosz - Ry) * minv;
+	car->DynGCg.acc.x = (F.F.x * Cosz - F.F.y * Sinz) * minv;
+	car->DynGCg.acc.y = (F.F.x * Sinz + F.F.y * Cosz) * minv;
 	car->DynGCg.acc.z = car->DynGC.acc.z;
 	
 	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;
 }
 
 static void
--- torcs-1.3.6/src/modules/simu/simuv2/collide.cpp	2014-04-12 06:55:29.000000000 -0700
+++ torcs-1.3.6/src/modules/simu/simuv2/collide.cpp	2016-02-26 11:36:54.224354425 -0800
@@ -29,6 +29,7 @@
 	tdble dotProd;
 	tWheel *wheel;
 	const float CRASH_THRESHOLD = -5.0f;
+	tdble dz = 0.0f;
 
 	if (car->carElt->_state & RM_CAR_STATE_NO_SIMU) {
 		return;
@@ -36,8 +37,9 @@
 
 	for (i = 0; i < 4; i++) {
 		wheel = &(car->wheel[i]);
-		if (wheel->state & SIM_SUSP_COMP) {
-			car->DynGCg.pos.z += wheel->susp.spring.packers - wheel->rideHeight;
+		if ( (wheel->state & SIM_SUSP_COMP)&&(!(wheel->state & SIM_WH_ONAIR)) ) {
+			dz = MAX(dz, wheel->susp.spring.packers - wheel->rideHeight);
+			wheel->rideHeight = wheel->susp.spring.packers;
 			RtTrackSurfaceNormalL(&(wheel->trkPos), &normal);
 			dotProd = (car->DynGCg.vel.x * normal.x + car->DynGCg.vel.y * normal.y + car->DynGCg.vel.z * normal.z) * wheel->trkPos.seg->surface->kRebound;
 			if (dotProd < 0.0f) {
@@ -54,6 +56,7 @@
 			}
 		}
 	}
+	car->DynGCg.pos.z += dz; // elevate car when it has slightly impacted into ground. (SD r6312)
 }
 
 const tdble BorderFriction = 0.0f;
--- torcs-1.3.6/src/modules/simu/simuv2/susp.cpp	2014-02-09 23:53:35.000000000 -0800
+++ torcs-1.3.6/src/modules/simu/simuv2/susp.cpp	2016-03-20 18:49:32.000000000 -0700
@@ -2,9 +2,9 @@
 
     file                 : susp.cpp
     created              : Sun Mar 19 00:08:41 CET 2000
-    copyright            : (C) 2000 by Eric Espie
+    copyright            : (C) 2000-2016 by Eric Espie, Bernhard Wymann
     email                : [email protected]
-    version              : $Id: susp.cpp,v 1.10.2.7 2014/02/10 07:53:35 berniw Exp $
+    version              : $Id: susp.cpp,v 1.10.2.10 2016/03/19 14:47:05 berniw Exp $
 
  ***************************************************************************/
 
@@ -85,6 +85,7 @@
 	/* K is < 0 */
 	f = spring->K * (susp->x - spring->x0) + spring->F0;
 	if (f < 0.0f) {
+		// Compression spring, so the force can never change the sign.
 		f = 0.0f;
 	}
 	
@@ -98,13 +99,17 @@
 {
 	susp->state = 0;
 	if (susp->x < susp->spring.packers) {
+		// Packers are not scaled with susp->spring.bellcrank, because they are a hard
+		// rubber element or plate spring packs directly mounted on the piston of the
+		// damper.
 		susp->x = susp->spring.packers;
 		susp->state = SIM_SUSP_COMP;
 	}
+	
 	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
 	}
 }
 
@@ -113,7 +118,17 @@
 
 void SimSuspUpdate(tSuspension *susp)
 {
-	susp->force = (springForce(susp) + damperForce(susp)) * susp->spring.bellcrank;
+	tdble internalForce = springForce(susp) + damperForce(susp);
+	if (internalForce <= 0.0f) {
+		// The damping can at its best cancel out the spring force. Requred because
+		// of numerical integration artefacts with (if the velocity is 0 there is no
+		// damping, so the spring accelarates the system for one time step; if the
+		// damping is set very high this can result in a counterforce larger than the
+		// spring force in the next timestep)
+		susp->force = 0.0f;
+	} else {
+		susp->force = internalForce * susp->spring.bellcrank;
+	}
 }
 
 
--- 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-04-10 23:41:20.000000000 -0700
@@ -4,7 +4,7 @@
     created              : Sun Mar 19 00:09:06 CET 2000
     copyright            : (C) 2000-2013 by Eric Espie, Bernhard Wymann
     email                : [email protected]
-    version              : $Id: wheel.cpp,v 1.26.2.5 2013/08/29 13:01:32 berniw Exp $
+    version              : $Id: wheel.cpp,v 1.26.2.6 2016/03/06 20:59:31 berniw Exp $
 
  ***************************************************************************/
 
@@ -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;
-	tdble s, sa, sx, sy; // slip vector
-	tdble stmp, F, Bx;
+	double CosA, SinA;
+	tdble s, sx, sy; // slip vector
+	tdble F, Bx;
 	tdble mu;
 	wheel->state = 0;
 
@@ -193,8 +193,8 @@
 		wheel->forces.z = wheel->rel_vel/SimDeltaTime*wheel->mass;
 		wheel->rel_vel = 0.0;
 	} else {
-		wheel->rel_vel -= SimDeltaTime * wheel->susp.force / wheel->mass;
 		wheel->forces.z = axleFz + wheel->susp.force;
+		wheel->rel_vel -= SimDeltaTime * wheel->forces.z / wheel->mass;
 	}
 
 	// update wheel coord, center relative to GC
@@ -209,52 +209,43 @@
 	}
 
 	// 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);
-
-	// 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.32 added to slip_magnitude affects low velocities and divide by zero.
+		slip_magnitude = sqrt( MAX(MAX((v2), (vn*vn + wrl*wrl)), (vn*vn + (vt - wrl)*(vt - wrl))) );
+		sx = (vt - wrl) / (0.32f + slip_magnitude);
+		sy = vn / (0.000001f + slip_magnitude);
 	}
 
-	Ft = 0.0f;
-	Fn = 0.0f;
-	s = sqrt(sx*sx+sy*sy);
+	s = sqrtf(sx*sx+sy*sy) + 0.000001f; // add 0.000001 to avoid divide by zero later.
 
 	{
-		// calculate _skid and _reaction for sound.
-		if (v < 2.0f) {
-			car->carElt->_skid[index] = 0.0f;
+		// calculate _skid and _reaction for sound (importantly; affects traction also).
+		if ((v < 0.01f) || (zforce < 0.002f)) {
+			car->carElt->_skid[index] = 0.000001f;
 		} else {
-			car->carElt->_skid[index] =  MIN(1.0f, (s*zforce*0.0002f));
+			car->carElt->_skid[index] = s; // linear (tanh removed in grskidmarks.cpp)
 		}
 	}
 
-	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));
@@ -262,31 +253,28 @@
 	F *= zforce * mu * wheel->trkPos.seg->surface->kFriction * (1.0f + 0.05f * sin(-wheel->staticPos.ax * 18.0f));	/* coeff */
 
 	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;
-	}
+	// wheel axis based
+	Ft = -(F - wheel->rollRes) * sx/s; // rolling resistance is the rolling vector component only.
+	Fn = -F * sy/s;
 
-	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
 
 	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(sy, sx);
 	wheel->sx = sx;
 
 	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) = slip_magnitude;
 	car->carElt->_reaction[index] = zforce;
 }
 
@@ -301,8 +289,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;