267 lines
9.9 KiB
HTML
267 lines
9.9 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<!--
|
|
copyright : (C) 2003-2004 Bernhard Wymann
|
|
email : berniw@bluewin.ch
|
|
version : $Id$
|
|
|
|
Permission is granted to copy, distribute and/or modify this document
|
|
under the terms of the GNU Free Documentation License, Version 1.2
|
|
or any later version published by the Free Software Foundation;
|
|
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
|
|
Texts. A copy of the license is included in the section entitled "GNU
|
|
Free Documentation License".
|
|
|
|
-->
|
|
<head>
|
|
<title>ABS and TCL</title>
|
|
<link rel="stylesheet" type="text/css" href="../../../css/format.css"/>
|
|
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
|
|
<meta name="description" content="ABS and TCL"/>
|
|
<meta name="author" content="Bernhard Wymann"/>
|
|
<meta name="keywords" content="torcs, berniw, bernhard wymann, robot, braking, traction, ABS, TCL"/>
|
|
<script src="../../../js/utilities.js" type="text/javascript"></script>
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<table class="maincontent">
|
|
<tr>
|
|
<td class="maincontent">
|
|
|
|
<h1>3.6 Antilock Brake System and Traction Control</h1>
|
|
|
|
<h3>Introduction</h3>
|
|
<p>
|
|
During the test runs you have seen the rear wheels skidding or some wheels
|
|
locking. It's because we accelerate or brake too hard, so the friction of the
|
|
tire on the road is smaller than the force we apply. When the speed of the tire
|
|
surface relative to the track (with no slip we would have perfect rolling, so
|
|
the tire contact point would have zero relative speed to the track) becomes too
|
|
big we loose the static friction. Because of that we can transport even less
|
|
force... so we need a system that tries to avoid that. We will implement a
|
|
simple wheel antilock brake system (ABS) and a simple traction control (TCL).
|
|
</p>
|
|
|
|
<h3>Anti Wheel Locking</h3>
|
|
<p>
|
|
I show you a simple implementation which considers the average slip of all
|
|
wheels. You could also take a weighted sum according to the situation or just
|
|
the wheel with the minimum slip. Feel free to improve it.
|
|
</p>
|
|
<p><pre class="lcolor">/* Antilocking filter for brakes */
|
|
float Driver::filterABS(float brake)
|
|
{
|
|
if (car->_speed_x < ABS_MINSPEED) return brake;</pre>
|
|
</p>
|
|
<p>
|
|
If we are too slow don't consider ABS (division by zero).
|
|
</p>
|
|
<p><pre class="lcolor"> int i;
|
|
float slip = 0.0;
|
|
for (i = 0; i < 4; i++) {
|
|
slip += car->_wheelSpinVel(i) * car->_wheelRadius(i) / car->_speed_x;
|
|
}
|
|
slip = slip/4.0;</pre>
|
|
</p>
|
|
<p>
|
|
Compute the average slip of the four wheels.
|
|
</p>
|
|
<p><pre class="lcolor"> if (slip < ABS_SLIP) brake = brake*slip;
|
|
return brake;
|
|
}</pre></p>
|
|
<p>
|
|
If the slip variable is below a certain threshold reduce the brake value by multiplying
|
|
it with the slip. Put this code into driver.cpp. You need also to insert the
|
|
call into the drive method and to define the new constants. Change
|
|
</p>
|
|
<p><pre class="lbcolor"> car->ctrl.brakeCmd = getBrake();</pre>
|
|
</p>
|
|
<p>
|
|
to
|
|
</p>
|
|
<p><pre class="lcolor"> car->ctrl.brakeCmd = filterABS(getBrake());</pre>
|
|
</p>
|
|
<p>
|
|
and add the constants
|
|
</p>
|
|
<p><pre class="lcolor"> const float Driver::ABS_SLIP = 0.9; /* [-] range [0.95..0.3] */
|
|
const float Driver::ABS_MINSPEED = 3.0; /* [m/s] */</pre>
|
|
</p>
|
|
<p>
|
|
driver.h needs also an update:
|
|
</p>
|
|
<p><pre class="lcolor"> float filterABS(float brake);</pre>
|
|
</p>
|
|
<p><pre class="lcolor"> static const float ABS_SLIP;
|
|
static const float ABS_MINSPEED;</pre>
|
|
</p>
|
|
|
|
<h3>Traction Control</h3>
|
|
<p>
|
|
The approach I show you for TCL is almost the same like for ABS. But there is a
|
|
difference, which will lead to more "administrative" stuff. Because we can have
|
|
rear, front or all wheel driven cars, we have depending on the type to check
|
|
the appropriate wheels. Just for fun we will implement that with a pointer to a
|
|
method (the right way would be the delegation pattern with an abstract class and
|
|
three subclasses). Let's implement top down, change the call in the drive
|
|
method from
|
|
</p>
|
|
|
|
<p><pre class="lbcolor"> car->ctrl.accelCmd = getAccel();</pre>
|
|
</p>
|
|
<p>
|
|
to
|
|
</p>
|
|
<p><pre class="lcolor"> car->ctrl.accelCmd = filterTCL(getAccel());</pre>
|
|
</p>
|
|
<p>
|
|
Now we implement filterTCL in driver.cpp. Have a look on the funny call.
|
|
</p>
|
|
<p><pre class="lcolor">/* TCL filter for accelerator pedal */
|
|
float Driver::filterTCL(float accel)
|
|
{
|
|
if (car->_speed_x < TCL_MINSPEED) return accel;
|
|
float slip = car->_speed_x/(this->*GET_DRIVEN_WHEEL_SPEED)();</pre>
|
|
</p>
|
|
<p>
|
|
Like with the ABS we have a minimal speed to consider TCL. We compute the slip
|
|
with a function that we plug in the GET_DRIVEN_WHEEL_SPEED variable during
|
|
initialization.
|
|
</p>
|
|
<p><pre class="lcolor"> if (slip < TCL_SLIP) {
|
|
accel = 0.0;
|
|
}
|
|
return accel;
|
|
}</pre>
|
|
</p>
|
|
<p>
|
|
Then we check the slip variable, and if it's too small we set the accelerator pedal
|
|
to 0.
|
|
Next I show you the initialization of the "plugin". This approach has the
|
|
advantage that we don't need to check the car type during runtime. The following
|
|
method checks the car type (from the XML file) and plugs in the fitting method.
|
|
</p>
|
|
|
|
<p><pre class="lcolor">/* Traction Control (TCL) setup */
|
|
void Driver::initTCLfilter()
|
|
{
|
|
char *traintype = GfParmGetStr(car->_carHandle,
|
|
SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD);
|
|
if (strcmp(traintype, VAL_TRANS_RWD) == 0) {
|
|
GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD;
|
|
} else if (strcmp(traintype, VAL_TRANS_FWD) == 0) {
|
|
GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD;
|
|
} else if (strcmp(traintype, VAL_TRANS_4WD) == 0) {
|
|
GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD;
|
|
}
|
|
}</pre></p>
|
|
<p>
|
|
Here follow the car type specific methods.
|
|
</p>
|
|
<p><pre class="lcolor">/* TCL filter plugin for rear wheel driven cars */
|
|
float Driver::filterTCL_RWD()
|
|
{
|
|
return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) *
|
|
car->_wheelRadius(REAR_LFT) / 2.0;
|
|
}
|
|
|
|
|
|
/* TCL filter plugin for front wheel driven cars */
|
|
float Driver::filterTCL_FWD()
|
|
{
|
|
return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) *
|
|
car->_wheelRadius(FRNT_LFT) / 2.0;
|
|
}
|
|
|
|
|
|
/* TCL filter plugin for all wheel driven cars */
|
|
float Driver::filterTCL_4WD()
|
|
{
|
|
return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) *
|
|
car->_wheelRadius(FRNT_LFT) / 4.0 +
|
|
(car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) *
|
|
car->_wheelRadius(REAR_LFT) / 4.0;
|
|
}</pre></p>
|
|
<p>
|
|
Put the initialization call into newRace(...).
|
|
</p>
|
|
<p><pre class="lcolor"> initTCLfilter();</pre>
|
|
</p>
|
|
<p>
|
|
Define the constants in driver.cpp
|
|
</p>
|
|
<p><pre class="lcolor"> const float Driver::TCL_SLIP = 0.9; /* [-] range [0.95..0.3] */
|
|
const float Driver::TCL_MINSPEED = 3.0; /* [m/s] */</pre>
|
|
</p>
|
|
<p>
|
|
and add the following to driver.h.
|
|
</p>
|
|
<p><pre class="lcolor"> float filterTCL(float accel);
|
|
float filterTCL_RWD();
|
|
float filterTCL_FWD();
|
|
float filterTCL_4WD();</pre></p>
|
|
<p><pre class="lcolor"> void initTCLfilter();</pre>
|
|
</p>
|
|
<p><pre class="lcolor"> float (Driver::*GET_DRIVEN_WHEEL_SPEED)();
|
|
static const float TCL_SLIP;
|
|
static const float TCL_MINSPEED;</pre></p>
|
|
|
|
<h3>Final Remarks</h3>
|
|
<p>
|
|
If you compare the lap times of the "gear" section with the current ones, then
|
|
you can see that we have won a lot. On e-track-4 we won ~15s, on e-track-2 ~3s
|
|
and on mixed-2 ~7s. That's very nice. The next thing we need to improve is the
|
|
way we take on the track. Ah, the measurements:
|
|
</p>
|
|
<ul style="list-style-type:disk; color:black;">
|
|
<li>mixed-2: 1:35:44, 831 damage.</li>
|
|
<li>e-track-2: 1:42:96, 0 damage.</li>
|
|
<li>e-track-4: 1:59:69, 4 damage.</li>
|
|
</ul>
|
|
|
|
|
|
<h3>Downloads</h3>
|
|
<p>
|
|
In case you got lost, you can <a href="../download/bt36.tar.gz">download</a> my robot for TORCS 1.2.0 or later.
|
|
</p>
|
|
|
|
<h3>Feedback</h3>
|
|
<p>
|
|
<a href="mailto:berni4you@gmx.ch">Let me know</a>
|
|
if you read this chapter and your thoughts about it. Please
|
|
<a href="mailto:berni4you@gmx.ch">send me</a>
|
|
also spelling, grammar, math and code corrections. Thank you for the feedback.
|
|
</p>
|
|
|
|
<h3>Summary</h3>
|
|
<ul style="list-style-type:disk; color:black;">
|
|
<li>You know how ABS works.</li>
|
|
<li>You know how TCL works.</li>
|
|
<li>You have implemented it.</li>
|
|
<li>Your brain is full of ideas and you are keen to implement it.</li>
|
|
</ul>
|
|
|
|
<br/>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
|
|
<table class="navigation_foot">
|
|
<tr>
|
|
<td class="navigation_foot">
|
|
<a href="./braking2.html">
|
|
<p style="text-align:left;">Back</p>
|
|
</a>
|
|
</td>
|
|
<td class="navigation_foot">
|
|
<a href="javascript:changetwoframes('../navigation/navigation.html','navigation','../robot.html','content')">
|
|
<p style="text-align:right;">Up</p>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
</body>
|
|
</html>
|