Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/commaai/openpilot/llms.txt

Use this file to discover all available pages before exploring further.

openpilot is built as a collection of independent processes that communicate through a shared message bus. Each process owns a narrow responsibility — camera capture, neural network inference, planning, or actuation — and coordinates with others only through typed messages. This design makes the system easier to reason about, test in isolation, and extend without coupling unrelated subsystems.

Process overview

manager.py

The system supervisor. Starts, monitors, and restarts all other processes. Tracks ignition state and transitions processes between on-road and off-road modes.

selfdrived.py

The high-level state machine. Manages openpilot’s enabled/engaged states, evaluates safety events, and publishes alerts to the UI and other processes.

controlsd.py

The low-level control loop running at 100 Hz. Runs PID and torque-based lateral controllers alongside a longitudinal controller to produce actuator commands.

modeld.py

Neural network inference for the supercombo driving model. Consumes camera frames via VisionIPC and publishes trajectory predictions and model metadata.

dmonitoringmodeld.py

Driver monitoring inference. Runs a separate neural network on the driver-facing camera to detect distraction and drowsiness.

plannerd.py

Longitudinal planning. Consumes model outputs and radar data to produce a longitudinal plan, and monitors for lane departure warnings.

pandad

CAN bus communication. Reads vehicle state from the panda hardware device and sends actuator commands back to the car via CAN frames.

camerad

Camera capture. Reads raw frames from the road-facing, wide-angle, and driver-facing cameras and publishes them over VisionIPC for model consumers.

loggerd

Route and telemetry logging. Records all cereal messages to disk for review, debugging, and upload as training data.

Process startup sequence

manager.py is the entry point for the entire system. It handles registration, parameter initialization, and supervised process lifecycle management.
1

manager initializes

manager.py runs manager_init(): clears stale parameters, creates shared memory paths, registers the device, and prepares all managed processes for launch.
2

off-road processes start

Processes that run regardless of ignition — including athenad, uploader, and updated — are started immediately.
3

ignition detected

The manager polls pandaStates over the message bus. When ignition is detected, it transitions to on-road mode and clears the relevant parameter flags.
4

on-road processes start

camerad, modeld, dmonitoringmodeld, selfdrived, controlsd, plannerd, pandad, and loggerd are all started as on-road processes.
5

selfdrived waits for CarParams

selfdrived.py blocks on CarParams being written to the params store, which happens after pandad fingerprints the connected vehicle.
6

control loop runs

Once CarParams is available, controlsd.py and plannerd.py initialize their controllers and enter their real-time loops.

Inter-process communication

All processes communicate through cereal — comma’s messaging library built on Cap’n Proto schemas serialized over either ZMQ (socket-based) or msgq (shared-memory, lower latency). Each message type is defined in the cereal schema and has a single publisher. Subscribers declare which topics they consume at startup using SubMaster, and publishers use PubMaster. This pub/sub model means processes never call each other directly — they only read and write to the message bus.
Camera frames are too large for the cereal message bus and instead travel through VisionIPC, a separate shared-memory transport. modeld and dmonitoringmodeld subscribe to camera streams through a VisionIpcClient.
Key message topics and their publishers:
TopicPublisherConsumers
carStatepandadselfdrived, controlsd, plannerd
modelV2modeldplannerd, controlsd, selfdrived
selfdriveStateselfdrivedcontrolsd, UI
longitudinalPlanplannerdcontrolsd
carControlcontrolsdpandad, plannerd
driverMonitoringStatedmonitoringmodeldselfdrived
managerStatemanagerUI, logging

Data flow: cameras to car

The full pipeline from sensor input to actuator output follows this path:
  1. camerad captures frames from road-facing and wide-angle cameras and publishes them to VisionIPC streams.
  2. modeld reads camera frames, runs the supercombo model, and publishes modelV2 — which includes predicted trajectories, velocity, and desired curvature.
  3. plannerd subscribes to modelV2 and radarState to build a longitudinalPlan, resolving the desired acceleration profile.
  4. controlsd subscribes to longitudinalPlan, modelV2, and selfdriveState to compute lateral and longitudinal actuator commands, publishing carControl.
  5. pandad reads carControl and translates the actuator values into CAN frames sent to the vehicle over the panda hardware interface.
In parallel, dmonitoringmodeld processes the driver camera independently and publishes driverMonitoringState, which selfdrived uses to determine whether to issue distraction or drowsiness alerts.

Controller types

controlsd.py selects a lateral controller at startup based on the car’s CarParams:
  • LatControlTorque — torque-based control, used on most supported vehicles
  • LatControlPID — PID controller for lateral position
  • LatControlAngle — direct steering angle control for steer-by-wire vehicles
Longitudinal control is handled by LongControl, which computes the required acceleration and deceleration to follow the plan from plannerd.

System and selfdrive directories

The codebase is split between two top-level directories:
  • system/ — infrastructure: manager, camerad, loggerd, athena, hardware abstraction, and update management
  • selfdrive/ — driving logic: controls, modeld, selfdrived, locationd, monitoring, and car interfaces

Build docs developers (and LLMs) love