Ever had the autopilot brake too late on the highway, or mistake a pedestrian for a tree? We solve these problems with custom neural networks on embedded controllers. Over the last 7 years we've delivered 15+ ADAS functions—from AEB to blind spot monitoring—that work in real conditions: rain, snow, poor lane markings. Below is the concrete stack and architecture.
Each function is a separate computer vision problem with tight latency and accuracy requirements. For AEB, the delay must not exceed 30 ms—at 100 km/h, the car covers an extra 2.8 meters every 30 ms.
We use proven models: YOLOv8n for detection, CLRNet for lanes, Depth Anything for monocular depth. All wrapped into TensorRT or ONNX Runtime for inference on NVIDIA Orin and Qualcomm Snapdragon.
The main challenge is balancing accuracy and speed, especially when running 4–5 functions concurrently. On one project we cut AEB latency from 45 ms to 22 ms by replacing the backbone with EfficientNet-lite and switching to TensorRT INT8.
Key Functions and Implementation
import cv2
import numpy as np
from ultralytics import YOLO
import torch
class ADASSystem:
def __init__(self, config: dict):
self.lane_detector = self._load_lane_model(config)
self.object_detector = YOLO(config['object_model']) # YOLOv8n для скорости
self.depth_estimator = self._load_depth_model(config)
self.camera_matrix = np.array(config['camera_intrinsics'])
self.focal_length = self.camera_matrix[0, 0]
self.baseline = config.get('stereo_baseline', None)
# Пороги для предупреждений
self.ttc_warning = 2.5 # секунды — предупреждение
self.ttc_critical = 1.5 # секунды — AEB
self.lane_offset_threshold = 0.3 # метра
def lane_departure_warning(self, frame: np.ndarray,
vehicle_speed: float) -> dict:
"""
Детекция полосы: классика — UFLD (Ultra-Fast Lane Detection)
или CLRNet для сложных условий (пересечения, плохая разметка).
"""
lanes = self.lane_detector(frame)
if len(lanes) < 2:
return {'warning': False, 'reason': 'no_lanes'}
# Центр автомобиля относительно полосы
frame_center = frame.shape[1] // 2
lane_center = (lanes[0][-1][0] + lanes[1][-1][0]) // 2
offset_px = frame_center - lane_center
# Перевод пикселей в метры через гомографию
offset_m = offset_px * (3.5 / abs(lanes[1][-1][0] - lanes[0][-1][0]))
warning = abs(offset_m) > self.lane_offset_threshold
return {
'warning': warning,
'offset_meters': offset_m,
'lane_width': abs(lanes[1][-1][0] - lanes[0][-1][0])
}
def collision_warning(self, frame: np.ndarray,
ego_speed: float) -> dict:
detections = self.object_detector(frame, conf=0.5,
classes=[0, 2, 3, 5, 7])
depth_map = self.depth_estimator(frame)
warnings = []
for box in detections[0].boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
cx = (x1 + x2) // 2
# Дистанция из depth map (стерео или монокулярная)
roi_depth = depth_map[y1:y2, x1:x2]
distance = float(np.percentile(roi_depth, 10)) # ближняя часть объекта
# TTC при текущей скорости
if distance > 0 and ego_speed > 0:
ttc = distance / ego_speed # упрощённо, без учёта скорости объекта
else:
ttc = float('inf')
if ttc < self.ttc_critical:
action = 'AEB'
elif ttc < self.ttc_warning:
action = 'WARNING'
else:
continue
warnings.append({
'class': self.object_detector.model.names[int(box.cls)],
'distance_m': distance,
'ttc_sec': ttc,
'action': action
})
return {'warnings': sorted(warnings, key=lambda x: x['ttc_sec'])}
More about the detection pipeline
During preprocessing, we resize the image to 640x640 and normalize with mean=0.5, std=0.5. Then pass through YOLO to get bounding boxes, confidence scores, class IDs. Post-processing includes NMS with a threshold of 0.45 to eliminate duplicates.How AEB Works
When an object is detected at less than critical distance (TTC < 1.5 s), the system activates braking. We combine stereo vision and monocular depth to estimate distance. In practice, at 60 km/h, distance accuracy is ±1.5 m at 20 m range.
Why Latency Matters More Than Accuracy
At 100 km/h, the car travels 27.8 m per second. A 100 ms system delay means 2.78 m of blind travel. Therefore for ADAS:
| Function | Max Latency | Recommended Model |
|---|---|---|
| AEB (emergency braking) | < 30 ms | YOLOv8n + TensorRT INT8 |
| LDW (lane departure warning) | < 50 ms | CLRNet or UFLD |
| BSW (blind spot warning) | < 100 ms | YOLOv8s |
| ACC (adaptive cruise control) | < 100 ms | Depth + detection |
| Traffic signs | < 200 ms | EfficientDet-D2 |
YOLOv8n with TensorRT FP16 on NVIDIA Orin: 3–5 ms per frame. On Qualcomm SA8295P (Snapdragon Ride): 8–12 ms via QNN SDK.
Source: ISO 26262, AEB response time requirements
Model Comparison: YOLOv8n vs YOLOv8s
For AEB, YOLOv8n is better: its latency on TensorRT INT8 is 5–8 ms on NVIDIA Orin, 2.5 times faster than YOLOv8s. Meanwhile, mAP (0.5) drops from 0.52 to 0.48—negligible in practice. For BSW we use YOLOv8s (latency up to 100 ms).
Monocular Depth Estimation
If no stereo camera is available, we use MonoDepth2 or DPT (Dense Prediction Transformer). Accuracy is lower than stereo but sufficient for warnings:
from transformers import AutoImageProcessor, AutoModelForDepthEstimation
class MonocularDepth:
def __init__(self):
self.processor = AutoImageProcessor.from_pretrained(
"LiheYoung/depth-anything-large-hf"
)
self.model = AutoModelForDepthEstimation.from_pretrained(
"LiheYoung/depth-anything-large-hf"
)
@torch.no_grad()
def estimate(self, image: np.ndarray) -> np.ndarray:
inputs = self.processor(images=image, return_tensors="pt")
outputs = self.model(**inputs)
depth = outputs.predicted_depth.squeeze().numpy()
# Масштабируем в метры через калибровочный коэффициент
return depth
Depth Anything v2 Large gives AbsRel = 0.076 on KITTI—sufficient for distance estimation within ±10% at 10–30 m.
How We Implement the ADAS System
- Analyze requirements and select sensors (cameras, radars, lidars).
- Collect and annotate data for target scenarios (urban, highway, night).
- Train models with fine-tuning and quantization (INT8/FP16).
- Deploy on target hardware (NVIDIA Orin, Qualcomm Snapdragon, TI TDA4).
- Validate offline on datasets and online in real conditions.
- Document and hand over to the client.
What Is Included in the Project
- System architecture and sensor selection (cameras, radars, lidars)
- Datasets: collection, annotation, augmentation
- Model training: fine-tuning, quantization (INT8/FP16), pruning
- Deployment on target hardware (NVIDIA Orin, Qualcomm Snapdragon, TI TDA4)
- Validation: offline (on datasets) and online (real scenarios)
- Documentation: functional spec, test plan, CI/CD pipeline
- Client team training
Certification and Standards
ADAS systems for production vehicles must comply with:
- ISO 26262 (Functional Safety, ASIL-B/C for AEB)
- ISO/SAE 21434 (Cybersecurity)
- UNECE R79/R130 (regulatory requirements for LDW and AEB)
For in-plant or carport applications (not public road), requirements are softer—we use automotive grade without full ISO 26262 certification.
| Project Type | Timeline |
|---|---|
| Prototype of a single function (LDW or AEB) | 6–10 weeks |
| Full L2 ADAS suite (4–6 functions) | 4–7 months |
| Automotive-grade with ISO 26262 | 12–24 months |
Timelines and Investment
Development of a single module (e.g., AEB) requires a certain investment; contact us for a tailored estimate. Order a pilot project for 1–2 functions — turnaround 6–8 weeks.
Our Experience
Over 7 years in embedded vision, 15+ ADAS projects (from prototypes to pre-series). We use automotive-grade approaches: ROS 2, DDS, SafeRTOS.
Why Choose Us
We don't just train a model—we take it to production on your specific hardware, accounting for thermal profiles and energy budget.







