Implementation:CARLA simulator Carla VehiclePIDController Run Step
| Knowledge Sources | |
|---|---|
| Domains | Control Theory, PID Control, Autonomous Driving |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
Concrete tool for generating vehicle control commands via dual PID controllers provided by the CARLA simulator agents library. The VehiclePIDController.run_step() method takes a target speed and a target waypoint, computes separate longitudinal (throttle/brake) and lateral (steering) PID outputs, and returns a combined carla.VehicleControl object.
Description
The run_step() method orchestrates the dual PID control loop at each simulation tick:
- Calls the longitudinal controller (
PIDLongitudinalController.run_step(target_speed)) which:- Computes the speed error between target_speed and current vehicle speed
- Applies the PID formula with longitudinal gains (K_P, K_I, K_D)
- Returns a throttle value (positive output) or brake value (negative output)
- Calls the lateral controller (
PIDLateralController.run_step(waypoint)) which:- Computes the angular error between the vehicle's forward vector and the direction to the target waypoint
- Applies the PID formula with lateral gains (K_P, K_I, K_D)
- Returns a steering value in [-1, 1]
- Assembles a
carla.VehicleControlwith:throttleclamped to [0, max_throttle]brakeclamped to [0, max_brake]steeringclamped to [-max_steering, max_steering]hand_brake = Falsemanual_gear_shift = False
Usage
Use run_step() as the low-level actuator interface in the navigation agent loop. It is called by LocalPlanner.run_step() which provides the next target waypoint and desired speed from the global route plan. It can also be used directly for custom control loops.
Code Reference
Source Location
- Repository: CARLA
- File:
PythonAPI/carla/agents/navigation/controller.py - Lines: L54-92
Signature
class VehiclePIDController(object):
def run_step(self, target_speed, waypoint):
"""
Execute one step of control invoking both lateral and longitudinal
PID controllers to reach a target waypoint at a given target_speed.
:param target_speed: desired vehicle speed in km/h
:param waypoint: target carla.Waypoint
:return: carla.VehicleControl
"""
throttle = self._lon_controller.run_step(target_speed)
steering = self._lat_controller.run_step(waypoint)
control = carla.VehicleControl()
control.steer = steering
control.throttle = throttle
control.brake = 0.0
control.hand_brake = False
control.manual_gear_shift = False
return control
Import
from agents.navigation.controller import VehiclePIDController
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| target_speed | float |
Yes | Desired vehicle speed in km/h. The longitudinal PID controller will compute throttle/brake to reach this speed. |
| waypoint | carla.Waypoint |
Yes | Target waypoint to steer toward. The lateral PID controller will compute steering to minimize the angular error between the vehicle heading and the direction to this waypoint. |
Outputs
| Name | Type | Description |
|---|---|---|
| control | carla.VehicleControl |
Complete vehicle control command with throttle [0, max_throttle], brake [0, max_brake], steer [-max_steering, max_steering], hand_brake=False, manual_gear_shift=False.
|
Usage Examples
Basic Example
import carla
from agents.navigation.controller import VehiclePIDController
client = carla.Client('localhost', 2000)
world = client.get_world()
# Spawn vehicle
bp = world.get_blueprint_library().find('vehicle.tesla.model3')
spawn_point = world.get_map().get_spawn_points()[0]
vehicle = world.spawn_actor(bp, spawn_point)
# Create PID controller with custom gains
args_lateral = {
'K_P': 1.95,
'K_I': 0.05,
'K_D': 0.2,
'dt': 0.03
}
args_longitudinal = {
'K_P': 1.0,
'K_I': 0.05,
'K_D': 0.0,
'dt': 0.03
}
pid_controller = VehiclePIDController(
vehicle,
args_lateral=args_lateral,
args_longitudinal=args_longitudinal
)
# Get a target waypoint ahead of the vehicle
target_waypoint = world.get_map().get_waypoint(vehicle.get_location()).next(10.0)[0]
# Generate control at each tick
for _ in range(500):
control = pid_controller.run_step(
target_speed=30.0, # 30 km/h
waypoint=target_waypoint
)
vehicle.apply_control(control)
world.tick()
# Update target waypoint to the next one ahead
target_waypoint = world.get_map().get_waypoint(vehicle.get_location()).next(10.0)[0]
Custom Gain Tuning for High-Speed Driving
# Tighter lateral control for highway speeds
highway_lateral = {'K_P': 0.8, 'K_I': 0.02, 'K_D': 0.3, 'dt': 0.03}
highway_longitudinal = {'K_P': 0.5, 'K_I': 0.1, 'K_D': 0.0, 'dt': 0.03}
pid = VehiclePIDController(
vehicle,
args_lateral=highway_lateral,
args_longitudinal=highway_longitudinal,
max_throttle=0.75,
max_brake=0.5,
max_steering=0.6
)
control = pid.run_step(target_speed=80.0, waypoint=highway_waypoint)
vehicle.apply_control(control)