<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Macklee Gitonga</title>
    <description>The latest articles on DEV Community by Macklee Gitonga (@mackleegitonga).</description>
    <link>https://dev.to/mackleegitonga</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4176883%2F9de8e4a6-11b1-4937-b5c2-9280c1734a11.png</url>
      <title>DEV Community: Macklee Gitonga</title>
      <link>https://dev.to/mackleegitonga</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mackleegitonga"/>
    <language>en</language>
    <item>
      <title>From DNF to Sub-2:00 — How I Used IBM Bob to Fix My AI Racing Car</title>
      <dc:creator>Macklee Gitonga</dc:creator>
      <pubDate>Sun, 11 Oct 2026 11:18:43 +0000</pubDate>
      <link>https://dev.to/mackleegitonga/from-dnf-to-sub-200-how-i-used-ibm-bob-to-fix-my-ai-racing-car-513</link>
      <guid>https://dev.to/mackleegitonga/from-dnf-to-sub-200-how-i-used-ibm-bob-to-fix-my-ai-racing-car-513</guid>
      <description>&lt;p&gt;I spent 1.5 days getting TORCS installed, named my AI driver &lt;strong&gt;Max Verstoppin'&lt;/strong&gt;,&lt;br&gt;
and watched him immediately drive full speed into a wall. This is the story of how&lt;br&gt;
IBM Bob and I turned him into Max Verstappen.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://skills.yourlearning.ibm.com/activity/PLAN-6FA860C53B3A" rel="noopener noreferrer"&gt;IBM Bob TORCS University Challenge&lt;/a&gt;&lt;br&gt;
gives you a base Python script — &lt;code&gt;snakeoil3_gym.py&lt;/code&gt; — that controls an AI car in&lt;br&gt;
&lt;a href="https://ibm.box.com/v/TORCSdownloadzip" rel="noopener noreferrer"&gt;TORCS&lt;/a&gt;, an open-source racing simulator.&lt;br&gt;
The goal: use IBM Bob as your crew, improve the script, and post the fastest clean&lt;br&gt;
lap on the &lt;strong&gt;Corkscrew&lt;/strong&gt; track from a standing start with zero damage.&lt;/p&gt;

&lt;p&gt;Simple brief. Brutal execution.&lt;/p&gt;


&lt;h2&gt;
  
  
  Alpha — The Baseline (DNF, 1,863 Damage)
&lt;/h2&gt;

&lt;p&gt;The baseline &lt;code&gt;drive_example()&lt;/code&gt; function looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;target_speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;

&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;steer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;angle&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;PI&lt;/span&gt;
&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;steer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trackPos&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;speedX&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;target_speed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;steer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No brakes. No corner awareness. A steering multiplier of 15 that caused the wheel&lt;br&gt;
to thrash violently. A target speed of 300 km/h regardless of what's ahead.&lt;/p&gt;

&lt;p&gt;Max hit &lt;strong&gt;237 km/h&lt;/strong&gt;, missed the first corner entirely, and sat pinned against the&lt;br&gt;
barrier wall until the server hit the 100,000 step limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Laps: 0. Damage: 1,863. Top speed: 237 km/h.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Bringing in IBM Bob
&lt;/h2&gt;

&lt;p&gt;I pointed IBM Bob at the script and asked it to analyse what was wrong. It broke&lt;br&gt;
down &lt;code&gt;drive_example()&lt;/code&gt; and flagged three core issues immediately:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No braking system&lt;/strong&gt; — the &lt;code&gt;brake&lt;/code&gt; key in the action dictionary was never touched&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering multiplier too aggressive&lt;/strong&gt; — &lt;code&gt;* 15&lt;/code&gt; caused severe oscillation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blind target speed&lt;/strong&gt; — 300 km/h with zero awareness of what's ahead&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once I understood the problems, the approach was straightforward: fix one or two&lt;br&gt;
things at a time, run a lap, read the telemetry, feed it back to Bob, identify the&lt;br&gt;
next bottleneck. Eight iterations. Alpha through Iota.&lt;/p&gt;


&lt;h2&gt;
  
  
  Beta — First Clean Lap (02:24.17, 0 Damage)
&lt;/h2&gt;

&lt;p&gt;The first set of changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added proportional braking using the forward track sensors to detect corners&lt;/li&gt;
&lt;li&gt;Reduced steering multiplier from &lt;code&gt;15&lt;/code&gt; to &lt;code&gt;10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;track[8], track[9], track[10]&lt;/code&gt; (the forward-facing sensors) to calculate a
corner-aware target speed instead of a hardcoded 300
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;forward_dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;target_speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_dist&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;speed_excess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;speedX&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;target_speed&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;speed_excess&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;brake&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed_excess&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Max finished his first ever clean lap. &lt;strong&gt;02:24.17. Zero damage.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;He was slow — the &lt;code&gt;1.1&lt;/code&gt; multiplier meant a 100m straight-line sensor reading only&lt;br&gt;
set a target of 110 km/h — but he was clean. Foundation laid.&lt;/p&gt;


&lt;h2&gt;
  
  
  Gamma → Epsilon — Extracting More Pace (02:15 → 02:06)
&lt;/h2&gt;

&lt;p&gt;Over the next three runs, the multiplier was progressively tuned upward:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Multiplier&lt;/th&gt;
&lt;th&gt;Lap Time&lt;/th&gt;
&lt;th&gt;Top Speed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gamma&lt;/td&gt;
&lt;td&gt;&lt;code&gt;× 2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;02:15.40&lt;/td&gt;
&lt;td&gt;217 km/h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Epsilon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;× 2.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;02:06.71&lt;/td&gt;
&lt;td&gt;225 km/h&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each step brought more straight-line speed while the braking system kept damage&lt;br&gt;
at zero. The brake ramp divisor was also tightened to make the car scrub speed&lt;br&gt;
faster when approaching corners at higher speeds.&lt;/p&gt;


&lt;h2&gt;
  
  
  Zeta — The Key Architectural Insight (02:04.90)
&lt;/h2&gt;

&lt;p&gt;This was the most important change of the whole project.&lt;/p&gt;

&lt;p&gt;The sensor logic was using &lt;code&gt;min()&lt;/code&gt; across a five-sensor forward cone to set target&lt;br&gt;
speed. The problem: when Max drifted toward the track edge, the diagonal sensors&lt;br&gt;
in that cone were pointing at the boundary wall and returning short readings —&lt;br&gt;
sometimes 20–30m — on a completely open straight. The car thought a corner was&lt;br&gt;
coming and backed off the throttle for no reason.&lt;/p&gt;

&lt;p&gt;The fix was to split the sensor reading into two separate signals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# MAX of the cone → straight-line pace (one clear sensor is enough)
&lt;/span&gt;&lt;span class="n"&gt;straight_dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# MIN of the tightest 3 → corner guard (only fires when road ahead closes in)
&lt;/span&gt;&lt;span class="n"&gt;corner_dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;target_speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;straight_dist&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;corner_dist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;corner_cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;corner_dist&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;target_speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_speed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;corner_cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As long as &lt;em&gt;any&lt;/em&gt; forward sensor sees clear road, Max pushes. Corner braking only&lt;br&gt;
triggers when the road directly ahead is genuinely closing in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;02:04.90. 228 km/h. 0 damage.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Eta — A Lesson in Calibration (02:11.21 — Regression)
&lt;/h2&gt;

&lt;p&gt;Not every run went forward. Lowering the corner detection threshold to &lt;code&gt;&amp;lt; 45m&lt;/code&gt;&lt;br&gt;
(from &lt;code&gt;&amp;lt; 60m&lt;/code&gt;) delayed braking too long into the final tight turn. Max ran wide&lt;br&gt;
onto the grass, lost grip, and the lap time went &lt;em&gt;up&lt;/em&gt; by 6 seconds despite zero&lt;br&gt;
damage.&lt;/p&gt;

&lt;p&gt;The off-track excursion didn't register as damage in TORCS — grass just kills&lt;br&gt;
speed. A good reminder that the metrics don't always tell the full story.&lt;/p&gt;




&lt;h2&gt;
  
  
  Theta → Iota — Breaking Sub-2:00 (02:02 → &lt;strong&gt;01:58.15&lt;/strong&gt;)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Theta&lt;/strong&gt; split the difference: threshold &lt;code&gt;&amp;lt; 55m&lt;/code&gt;, multiplier &lt;code&gt;2.8&lt;/code&gt;. New PB at&lt;br&gt;
&lt;strong&gt;02:02.42&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Iota&lt;/strong&gt; fixed the last remaining issue — Max was loitering along the track edge&lt;br&gt;
after corner exits, not punching the throttle onto the straight. Two causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When off-centre, diagonal sensors still saw the wall and suppressed
&lt;code&gt;straight_dist&lt;/code&gt;. Fix: fall back to dead-ahead sensor only when &lt;code&gt;|trackPos| &amp;gt; 0.5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The apex throttle boost required &lt;code&gt;|steer| &amp;lt; 0.1&lt;/code&gt; — too tight. The shallow
correction Max held while returning to centre never qualified. Relaxed to &lt;code&gt;0.2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Centering gain doubled when near the edge (&lt;code&gt;0.15&lt;/code&gt; → &lt;code&gt;0.30&lt;/code&gt;) so he snapped back
to the racing line faster.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;track_pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trackPos&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track_pos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;straight_dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# dead-ahead only — ignore lying diagonal sensors
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;straight_dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;centering_gain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track_pos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt;
&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;steer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;track_pos&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;centering_gain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;01:58.15. 235 km/h. 0 damage. Sub-2:00.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Progression
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Lap Time&lt;/th&gt;
&lt;th&gt;Top Speed&lt;/th&gt;
&lt;th&gt;Damage&lt;/th&gt;
&lt;th&gt;Key Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Alpha&lt;/td&gt;
&lt;td&gt;DNF&lt;/td&gt;
&lt;td&gt;237 km/h&lt;/td&gt;
&lt;td&gt;1,863&lt;/td&gt;
&lt;td&gt;Baseline — blind throttle, no brakes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beta&lt;/td&gt;
&lt;td&gt;02:24.17&lt;/td&gt;
&lt;td&gt;196 km/h&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Braking, corner-aware speed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gamma&lt;/td&gt;
&lt;td&gt;02:15.40&lt;/td&gt;
&lt;td&gt;217 km/h&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;dist × 2.0&lt;/code&gt; multiplier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Epsilon&lt;/td&gt;
&lt;td&gt;02:06.71&lt;/td&gt;
&lt;td&gt;225 km/h&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;dist × 2.5&lt;/code&gt;, tighter brake ramp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zeta&lt;/td&gt;
&lt;td&gt;02:04.90&lt;/td&gt;
&lt;td&gt;228 km/h&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Dual &lt;code&gt;max&lt;/code&gt;/&lt;code&gt;min&lt;/code&gt; sensor logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eta&lt;/td&gt;
&lt;td&gt;02:11.21&lt;/td&gt;
&lt;td&gt;228 km/h&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;⚠️ Regression — threshold &lt;code&gt;&amp;lt; 45&lt;/code&gt; too aggressive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Theta&lt;/td&gt;
&lt;td&gt;02:02.42&lt;/td&gt;
&lt;td&gt;229 km/h&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Threshold &lt;code&gt;&amp;lt; 55&lt;/code&gt;, multiplier &lt;code&gt;2.8&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Iota&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;01:58.15&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;235 km/h&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Edge sensor fix, adaptive centering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;The most useful thing IBM Bob did wasn't writing code — it was helping me&lt;br&gt;
&lt;strong&gt;understand what the code was actually doing&lt;/strong&gt; before I changed anything. Once I&lt;br&gt;
could see exactly why Max was crashing (no brakes, blind speed) or slowing down&lt;br&gt;
(sensor reading the wall on a straight), each fix became obvious.&lt;/p&gt;

&lt;p&gt;The iterative loop — run, observe, diagnose, fix — is also just good engineering.&lt;br&gt;
Every regression (Eta) taught something. Every metric mattered: lap time, damage,&lt;br&gt;
&lt;em&gt;and&lt;/em&gt; top speed together told a more complete story than any one number alone.&lt;/p&gt;

&lt;p&gt;I also completed the &lt;strong&gt;IBM Granite Models for Software Development&lt;/strong&gt; course on&lt;br&gt;
IBM SkillsBuild during this project and earned the official badge, which gave me&lt;br&gt;
solid context for how these models reason about code — useful when you're having&lt;br&gt;
technical back-and-forth with Bob about sensor arrays and braking logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📁 &lt;a href="https://github.com/MackleeGit/torcs-max-verstappen" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://drive.google.com/file/d/1VNxA5rrRlRGEEFmQQdKzo-SRzj9neCHD/view?usp=drive_link" rel="noopener noreferrer"&gt;Race Video (Corkscrew - 01:58.15)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://drive.google.com/file/d/1xVAomg6QD-L-Xag5BktWxFtWJSxa9SlP/view?usp=drive_link" rel="noopener noreferrer"&gt;Team Video&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ibm</category>
      <category>ai</category>
      <category>python</category>
    </item>
  </channel>
</rss>
