speed-dreams/doc/tutorials/robot/torcs/robot/ch3/advanced.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 &lt; 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 &lt; 4; i++) {
slip += car-&gt;_wheelSpinVel(i) * car-&gt;_wheelRadius(i) / car-&gt;_speed_x;
}
slip = slip/4.0;</pre>
</p>
<p>
Compute the average slip of the four wheels.
</p>
<p><pre class="lcolor"> if (slip &lt; 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-&gt;ctrl.brakeCmd = getBrake();</pre>
</p>
<p>
to
</p>
<p><pre class="lcolor"> car-&gt;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-&gt;ctrl.accelCmd = getAccel();</pre>
</p>
<p>
to
</p>
<p><pre class="lcolor"> car-&gt;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-&gt;_speed_x &lt; TCL_MINSPEED) return accel;
float slip = car-&gt;_speed_x/(this-&gt;*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 &lt; 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-&gt;_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-&gt;_wheelSpinVel(REAR_RGT) + car-&gt;_wheelSpinVel(REAR_LFT)) *
car-&gt;_wheelRadius(REAR_LFT) / 2.0;
}
/* TCL filter plugin for front wheel driven cars */
float Driver::filterTCL_FWD()
{
return (car-&gt;_wheelSpinVel(FRNT_RGT) + car-&gt;_wheelSpinVel(FRNT_LFT)) *
car-&gt;_wheelRadius(FRNT_LFT) / 2.0;
}
/* TCL filter plugin for all wheel driven cars */
float Driver::filterTCL_4WD()
{
return (car-&gt;_wheelSpinVel(FRNT_RGT) + car-&gt;_wheelSpinVel(FRNT_LFT)) *
car-&gt;_wheelRadius(FRNT_LFT) / 4.0 +
(car-&gt;_wheelSpinVel(REAR_RGT) + car-&gt;_wheelSpinVel(REAR_LFT)) *
car-&gt;_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>