Minimize steering error with a PID controller

Source: Habrador

About the concept

Why do you need to minimize a steering error?

We can determine if the car should steer left or right to reach a waypoint. However, in real-life scenarios, the car gradually steers towards its intended heading and then drives in a mear to perfect straight path. If the gradual steering is not implemented, the wheels will rapidly switch to the left or right when the car is driving straight towards the waypoint. To minimize this behavior, an approach is to take the rolling average of the steering angles, with the addition of a PID controller.

Cross Tracking Error (CTE)

CTE is the distance between the car’s actual position and the intended position, which is the position closest to the car on a line between the waypoints.

  Vector a = Vector carPosition - Vector FromWaypoint
  Vector b = Vector ToWaypoint - Vector FromWaypoint
  proj_a_to_b = (a.b / |b|^2) * b
  progress = (a.x * b.x + a.y * b.y + a.z * b.z) / (b.x * b.x + b.y * b.y + b.z * b.z)
  Vector errorPerpendicular = FromWaypoint + progress * b;
  error = |(errorPerpendicular - carPosition)|;

This is the CTE. But we still do not know if we have to steer left or right to minimize this error.

  Vector rightDirection = carPosition.right;
  Vector waypointDirection = ToWaypoint - carPosition;
  dotProduct = DotProduct(rightDirection,waypointDirection)
  if (dotProduct > 0)
      steerDirection = 1
  else
      steerDirection = -1

Once we know the direction, the total error is given by:

  error = steerDirection*error

Now we apply PID controller to minimize this CTE.

PID

The input to the controller is the CTE error along with the P,I,D gains. The output is the steering angle at that particular instant of time.

  steeringAngle = 0
  steeringAngle += P * error

  error_sum +=  error * dt
  steeringAngle += I * error_sum

  float d_dt_error = (error - error_old) / dt
  steeringAngle += D * d_dt_error

  error_old = error
  return steeringAngle

We average this steering angle to simulate the time it takes to turn the steering wheel for realism.

averageSteeringAngle = averageSteeringAngle + ((steeringAngle - averageSteeringAngle) / averageAmount)

Result