With the PD controllers on angular speed and the P controller on linear speed, I proceeded to perform the first parameter tuning to increase the maximum linear speed and reduce the lap time.
I progressively assigned values and experimented with the parameters to observe their effects:
These adjustments demonstrate how balancing KP and KD for angular speed, along with proper KP tuning for linear speed, is key to achieving efficient, stable line tracking without excessive oscillations.
Despite tuning the parameters and achieving substantial improvement in the simulation car (completing the lap in 90 seconds on the Simple Circuit), when switching to the Ackermann car, the oscillations reappeared, and the P controller for linear speed seemed insufficient.
Therefore, the next step was to integrate a derivative (D) controller into linear speed control. This allows anticipation of abrupt error changes, smoothing the transition between acceleration and braking, and avoiding excessive speed fluctuations.
Additionally, I decided to implement the integral (I) controller, which takes into account the accumulated error over time. This is not the case in the Simple Circuit, but other circuits contain longer and smoother curves that could significantly benefit from this type of controller.
Proper parameter tuning for all three controllers is necessary to observe real results and analyze their effects.
In the current code, the error has no maximum limit, meaning it can sometimes reach very high values, such as 300 or more. This results in excessively large output values from the P, I, and D terms, exceeding the optimal speed and steering values, leading to a zigzagging effect.
To solve this, I decided to scale the error to a fixed range (-100 to 100) using the image dimensions. This way, the correction remains proportional and stable regardless of image size, preventing excessive error growth.
When tuning parameters for the Ackermann car, I quickly noticed that the settings that work well for curves do not perform as effectively on straight sections, where oscillations become more evident.
I considered dynamically adjusting the P and D constants for angular speed control depending on whether the car was on a straight path or a curve.
I tested two different approaches for detecting curves:
The best performance was achieved using the first method, so I ultimately chose it.
🚩 UPDATE: Later, I noticed that when the car approached the line in curves, the parameter changes caused more oscillations. I tried other techniques to detect curves and straights (such as using the contours of the calculated mask), but none were robust enough to provide substantial improvements. Therefore, I ultimately disabled this feature in the final code.
After extensive testing with various controller parameters, I realized that the first version of my integral controller had significant issues. It lacked a limitation on the accumulated error, which led to excessive error buildup. To fix this, I set a limit of 100 for the accumulated error.
I experimented with different values, but this limit proved to be the most stable, preventing large error accumulations from causing drastic steering changes.
Additionally, I implemented logic to reset the error history when the error approaches zero. This ensures that once a correction has been made, the integral controller does not continue influencing the steering unnecessarily.
Another key observation was that the integral controller was not very useful for this task, especially for controlling linear speed. Initially, I disabled it for linear speed control, leaving it only for angular speed control.