Files
OBD2-Simulator/app/simulator.py
2025-08-24 23:46:59 +02:00

67 lines
2.4 KiB
Python

# simulator.py — Driveline & ECU-State
from __future__ import annotations
import threading
import time
from dataclasses import dataclass
@dataclass
class DrivelineModel:
idle_rpm: int = 1400
max_rpm: int = 9500
kmh_per_krpm: tuple = (0.0, 12.0, 19.0, 25.0, 32.0, 38.0, 45.0)
rpm_rise_per_s: int = 5000
rpm_fall_per_s: int = 3500
def target_rpm_from_throttle(self, throttle_pct: int) -> int:
t = max(0, min(100, throttle_pct)) / 100.0
return int(self.idle_rpm + t * (self.max_rpm - self.idle_rpm))
def speed_from_rpm_gear(self, rpm: int, gear: int) -> float:
if gear <= 0:
return 0.0
k = self.kmh_per_krpm[min(gear, len(self.kmh_per_krpm) - 1)]
return (rpm / 1000.0) * k
class EcuState:
"""Thread-sichere Zustandsmaschine (Gang, Gas, RPM, Speed)."""
def __init__(self, model: DrivelineModel | None = None) -> None:
self.model = model or DrivelineModel()
self._lock = threading.Lock()
self._gear = 0
self._throttle = 0
self._rpm = self.model.idle_rpm
self._speed = 0.0
self._last = time.monotonic()
def set_gear(self, gear: int) -> None:
with self._lock:
self._gear = max(0, min(6, int(gear)))
def set_throttle(self, thr: int) -> None:
with self._lock:
self._throttle = max(0, min(100, int(thr)))
def snapshot(self) -> tuple[int, int, int, float]:
with self._lock:
return self._gear, self._throttle, self._rpm, self._speed
def update(self) -> None:
now = time.monotonic()
dt = max(0.0, min(0.1, now - self._last))
self._last = now
with self._lock:
target = self.model.target_rpm_from_throttle(self._throttle)
if self._rpm < target:
self._rpm = min(self._rpm + int(self.model.rpm_rise_per_s * dt), target)
else:
self._rpm = max(self._rpm - int(self.model.rpm_fall_per_s * dt), target)
min_idle = 800 if self._gear == 0 and self._throttle == 0 else self.model.idle_rpm
self._rpm = max(min_idle, min(self._rpm, self.model.max_rpm))
target_speed = self.model.speed_from_rpm_gear(self._rpm, self._gear)
alpha = min(1.0, 4.0 * dt)
if self._gear == 0:
target_speed = 0.0
self._speed = (1 - alpha) * self._speed + alpha * target_speed
self._speed = max(0.0, min(self._speed, 299.0))