Compare commits

..

12 Commits

Author SHA1 Message Date
eFini 61475e98f6 Add error handling for Params import
Handle ImportError for Params and set default value.
2025-12-03 22:20:02 +08:00
Rick Lan 06bcd25b48 translation 2025-11-29 19:21:23 +08:00
Rick Lan 31c5d72ab4 pre-build 2025-11-29 19:21:23 +08:00
Rick Lan e554c5132b fix: c4 lite detection 2025-11-29 19:21:10 +08:00
Rick Lan db4aa22794 feat(ui): C4 UI Mode 2025-11-26 16:55:10 +08:00
Rick Lan f68789f76e feat(ui): Torque Bar for c3 2025-11-26 16:46:53 +08:00
Rick Lan 8fb0289ff6 Fix: dp panel scroller type 2025-11-26 16:46:53 +08:00
Rick Lan aa4eeafa84 Fix: syntax error 2025-11-26 16:46:53 +08:00
Rick Lan 6ba90e3185 feat: Squash all pre-brand features into pre 2025-11-26 11:19:59 +08:00
Rick Lan c56902a616 feat: Squash all min-features into full 2025-11-26 11:10:07 +08:00
Rick Lan 1ebc3523c6 feat: Squash all core features into min 2025-11-26 10:25:16 +08:00
Vehicle Researcher 161005a0c1 openpilot v0.10.2 release
date: 2025-11-19T19:10:11
master commit: a29fdbd02407d41ecbcc69d151bb4837bfba3cbc
2025-11-19 19:10:16 -08:00
908 changed files with 91064 additions and 19670 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ simulation:
ui:
- changed-files:
- any-glob-to-all-files: '{selfdrive/ui/**,system/ui/**}'
- any-glob-to-all-files: '{selfdrive/assets/**,selfdrive/ui/**,system/ui/**}'
tools:
- changed-files:
+1
View File
@@ -38,6 +38,7 @@ a.out
*.vcd
*.mo
*_pyx.cpp
*.stats
config.json
clcache
compile_commands.json
+45
View File
@@ -1,3 +1,48 @@
dragonpilot 0.10.2 r1 (2025-11-30)
=======================
* ✅ openpilot 0.10.2 (devel-staging) (2025-11-20)
* ✨ 🚧 UI: C4 UI Mode (2025-11-26)
* ✨ UI: Torque Bar from C4 UI (2025-11-26)
* ✅ UI: Extend screen timeout (2025-11-04)
* ✅ UI: Display Lead & Radar Stats (2025-10-30)
* ✅ UI: Border Indicators (2025-05-27)
* ✅ UI: Rainbow Path (2025-04-02)
* ✅ UI: Speed Based HUD (2025-04-01)
* ✅ UI: Display Mode (2025-03-14)
* ✅ LAT: Auto Lane Change (2025-04-14)
* ✅ LAT: Road Edge Detection (2025-04-01)
* ✅ LAT: LCA Speed Changer (2025-03-21)
* ✅ LAT: ALKA (2025-03-14)
* ✅ 🚧 LON: Dynamic Turn Speed Control (DTSC) (2025-11-04)
* ✅ 🚧 LON: Adaptive Experimental Mode (AEM) (2025-05-14)
* ✅ LON: Adaptive Coasting Mode (ACM) (2025-04-06)
* ✅ LON: Ext Radar Support (2025-03-31)
* ✅ MISC: Branch Selector (2025-11-14)
* ✅ MISC: Tether on boot (2025-11-04)
* ✅ MISC: Disable Comma Connect (2025-09-22)
* ✅ MISC: C3/C3X/O3 series Support (2025-09-15)
* ✅ MISC: Delay Starting Loggerd (2025-06-30)
* ✅ MISC: Auto Shutdown (2025-04-28)
* ✅ MISC: Increase Max Speed Allowed (2025-04-18)
* ✅ MISC: Audible Alert Mode (2025-04-17)
* ✅ MISC: Error Logs Btn (2025-04-08)
* ✅ MISC: Reset Conf Btn (2025-04-08)
* ✅ MISC: Model Selector (2025-03-14)
* ✅ Toyota: DSU Bypass Support by @cydia2020 (2025-09-09)
* ✅ Toyota: Stock Lon Mode (2025-04-01)
* ✅ Toyota: Door Auto Lock/Unlock (2025-03-14)
* ✅ Toyota: Radar Filter (2025-03-14)
* ✅ Toyota: TSS1 SnG Mod (2025-03-14)
* ✅ Toyota: SDSU Support (2025-03-14)
* ✅ Toyota: ZSS Support (2025-03-14)
* ✅ Honda: EPS Mod Support (2025-09-09)
* ✅ VAG: Avoid EPS Lockout Toggle (2025-04-17)
* ✅ VAG: Remove Dashcam for VAG PQ (2025-04-06)
* ✅ VAG: PQ Steering Patch (2025-04-02)
* ✅ VAG: MQB A0 SnG Mod (2025-03-20)
* ✅ HKG: SMDPS Support (2025-04-17)
* ✅ 🚧 Subaru: Increase torque limits for early Impreza/Crosstek by @ClockeNessMnstr (2025-09-25)
dragonpilot 0.10.1 r3 (2025-11-25)
=======================
* ✅ openpilot 0.10.1 (devel-staging) (2025-10-24)
+2 -2
View File
@@ -22,7 +22,7 @@
Quick start: `bash <(curl -fsSL openpilot.comma.ai)`
[![openpilot tests](https://github.com/commaai/openpilot/actions/workflows/selfdrive_tests.yaml/badge.svg)](https://github.com/commaai/openpilot/actions/workflows/selfdrive_tests.yaml)
[![openpilot tests](https://github.com/commaai/openpilot/actions/workflows/tests.yaml/badge.svg)](https://github.com/commaai/openpilot/actions/workflows/tests.yaml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![X Follow](https://img.shields.io/twitter/follow/comma_ai)](https://x.com/comma_ai)
[![Discord](https://img.shields.io/discord/469524606043160576)](https://discord.comma.ai)
@@ -74,7 +74,7 @@ Safety and Testing
----
* openpilot observes [ISO26262](https://en.wikipedia.org/wiki/ISO_26262) guidelines, see [SAFETY.md](docs/SAFETY.md) for more details.
* openpilot has software-in-the-loop [tests](.github/workflows/selfdrive_tests.yaml) that run on every commit.
* openpilot has software-in-the-loop [tests](.github/workflows/tests.yaml) that run on every commit.
* The code enforcing the safety model lives in panda and is written in C, see [code rigor](https://github.com/commaai/panda#code-rigor) for more details.
* panda has software-in-the-loop [safety tests](https://github.com/commaai/panda/tree/master/tests/safety).
* Internally, we have a hardware-in-the-loop Jenkins test suite that builds and unit tests the various processes.
+4
View File
@@ -1,3 +1,7 @@
Version 0.10.2 (2025-11-19)
========================
* comma four support
Version 0.10.1 (2025-09-08)
========================
* New driving model #36276
+1 -1
View File
@@ -22,7 +22,7 @@ AddOption('--ccflags', action='store', type='string', default='', help='pass arb
AddOption('--minimal',
action='store_false',
dest='extras',
default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS)
default=os.path.exists(File('#.gitattributes').abspath), # minimal by default on release branch (where there's no LFS)
help='the minimum build to run openpilot. no tests, tools, etc.')
# Detect platform
+5 -1
View File
@@ -918,6 +918,8 @@ struct ControlsState @0x97ff69c53601abf1 {
saturated @7 :Bool;
actualLateralAccel @9 :Float32;
desiredLateralAccel @10 :Float32;
desiredLateralJerk @11 :Float32;
version @12 :Int32;
}
struct LateralLQRState {
@@ -2164,7 +2166,8 @@ struct DriverStateV2 {
leftBlinkProb @7 :Float32;
rightBlinkProb @8 :Float32;
sunglassesProb @9 :Float32;
notReadyProb @12 :List(Float32);
phoneProb @13 :Float32;
notReadyProbDEPRECATED @12 :List(Float32);
occludedProbDEPRECATED @10 :Float32;
readyProbDEPRECATED @11 :List(Float32);
}
@@ -2222,6 +2225,7 @@ struct DriverMonitoringState @0xb83cda094a1da284 {
hiStdCount @14 :UInt32;
isActiveMode @16 :Bool;
isRHD @4 :Bool;
uncertainCount @19 :UInt32;
isPreviewDEPRECATED @15 :Bool;
rhdCheckedDEPRECATED @5 :Bool;
+13 -3
View File
@@ -7,11 +7,14 @@ from openpilot.system.version import get_version
API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
# name : jwt signature algorithm
KEYS = {"id_rsa" : "RS256",
"id_ecdsa" : "ES256"}
class Api:
def __init__(self, dongle_id):
self.dongle_id = dongle_id
with open(Paths.persist_root()+'/comma/id_rsa') as f:
self.private_key = f.read()
self.jwt_algorithm, self.private_key, _ = get_key_pair()
def get(self, *args, **kwargs):
return self.request('GET', *args, **kwargs)
@@ -32,7 +35,7 @@ class Api:
}
if payload_extra is not None:
payload.update(payload_extra)
token = jwt.encode(payload, self.private_key, algorithm='RS256')
token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm)
if isinstance(token, bytes):
token = token.decode('utf8')
return token
@@ -46,3 +49,10 @@ def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
headers['User-Agent'] = "openpilot-" + get_version()
return requests.request(method, API_HOST + "/" + endpoint, timeout=timeout, headers=headers, params=params)
def get_key_pair():
for key in KEYS:
if os.path.isfile(Paths.persist_root() + f'/comma/{key}') and os.path.isfile(Paths.persist_root() + f'/comma/{key}.pub'):
with open(Paths.persist_root() + f'/comma/{key}') as private, open(Paths.persist_root() + f'/comma/{key}.pub') as public:
return KEYS[key], private.read(), public.read()
return None, None, None
-9
View File
@@ -1,9 +0,0 @@
# remove all keys that end in DEPRECATED
def strip_deprecated_keys(d):
for k in list(d.keys()):
if isinstance(k, str):
if k.endswith('DEPRECATED'):
d.pop(k)
elif isinstance(d[k], dict):
strip_deprecated_keys(d[k])
return d
+17
View File
@@ -15,3 +15,20 @@ class FirstOrderFilter:
self.initialized = True
self.x = x
return self.x
class BounceFilter(FirstOrderFilter):
def __init__(self, x0, rc, dt, initialized=True, bounce=2):
self.velocity = FirstOrderFilter(0.0, 0.15, dt)
self.bounce = bounce
super().__init__(x0, rc, dt, initialized)
def update(self, x):
super().update(x)
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
self.velocity.update(0.0)
if abs(self.velocity.x) < 1e-5:
self.velocity.x = 0.0
self.x += self.velocity.x
return self.x
+1 -1
View File
@@ -1,6 +1,6 @@
from functools import cache
import subprocess
from openpilot.common.run import run_cmd, run_cmd_default
from openpilot.common.utils import run_cmd, run_cmd_default
@cache
+3 -2
View File
@@ -97,6 +97,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_DriverMonitoringUncertain", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
{"OpenpilotEnabledToggle", {PERSISTENT, BOOL, "1"}},
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
@@ -108,11 +109,10 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"RecordFront", {PERSISTENT, BOOL}},
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
{"SecOCKey", {PERSISTENT | DONT_LOG, STRING}},
{"ShowDebugInfo", {PERSISTENT, BOOL}},
{"RouteCount", {PERSISTENT, INT, "0"}},
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"SshEnabled", {PERSISTENT, BOOL}},
{"TermsVersion", {PERSISTENT, STRING}},
{"TrainingVersion", {PERSISTENT, STRING}},
{"UbloxAvailable", {PERSISTENT, BOOL}},
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"UpdateFailedCount", {CLEAR_ON_MANAGER_START, INT}},
@@ -160,4 +160,5 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"dp_vag_a0_sng", {PERSISTENT, BOOL, "0"}},
{"dp_vag_pq_steering_patch", {PERSISTENT, BOOL, "0"}},
{"dp_vag_avoid_eps_lockout", {PERSISTENT, BOOL, "0"}},
{"dp_ui_four", {PERSISTENT, BOOL, "0"}},
};
+2 -3
View File
@@ -2,11 +2,10 @@ import numpy as np
from numbers import Number
class PIDController:
def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
self._k_p = k_p
self._k_i = k_i
self._k_d = k_d
self.k_f = k_f # feedforward gain
if isinstance(self._k_p, Number):
self._k_p = [[0], [self._k_p]]
if isinstance(self._k_i, Number):
@@ -48,7 +47,7 @@ class PIDController:
self.speed = speed
self.p = self.k_p * float(error)
self.d = self.k_d * error_rate
self.f = self.k_f * feedforward
self.f = feedforward
if not freeze_integrator:
i = self.i + self.k_i * self.i_dt * error
-30
View File
@@ -1,30 +0,0 @@
import time
import functools
from openpilot.common.swaglog import cloudlog
def retry(attempts=3, delay=1.0, ignore_failure=False):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(attempts):
try:
return func(*args, **kwargs)
except Exception:
cloudlog.exception(f"{func.__name__} failed, trying again")
time.sleep(delay)
if ignore_failure:
cloudlog.error(f"{func.__name__} failed after retry")
else:
raise Exception(f"{func.__name__} failed after retry")
return wrapper
return decorator
if __name__ == "__main__":
@retry(attempts=10)
def abc():
raise ValueError("abc failed :(")
abc()
-28
View File
@@ -1,28 +0,0 @@
import subprocess
from contextlib import contextmanager
from subprocess import Popen, PIPE, TimeoutExpired
def run_cmd(cmd: list[str], cwd=None, env=None) -> str:
return subprocess.check_output(cmd, encoding='utf8', cwd=cwd, env=env).strip()
def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> str:
try:
return run_cmd(cmd, cwd=cwd, env=env)
except subprocess.CalledProcessError:
return default
@contextmanager
def managed_proc(cmd: list[str], env: dict[str, str]):
proc = Popen(cmd, env=env, stdout=PIPE, stderr=PIPE)
try:
yield proc
finally:
if proc.poll() is None:
proc.terminate()
try:
proc.wait(timeout=5)
except TimeoutExpired:
proc.kill()
+1 -1
View File
@@ -1,7 +1,7 @@
import os
from uuid import uuid4
from openpilot.common.file_helpers import atomic_write_in_dir
from openpilot.common.utils import atomic_write_in_dir
class TestFileHelpers:
+62 -2
View File
@@ -2,9 +2,14 @@ import io
import os
import tempfile
import contextlib
import subprocess
import time
import functools
from subprocess import Popen, PIPE, TimeoutExpired
import zstandard as zstd
from openpilot.common.swaglog import cloudlog
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
class CallbackReader:
@@ -27,7 +32,7 @@ class CallbackReader:
@contextlib.contextmanager
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str = None, newline: str = None,
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None,
overwrite: bool = False):
"""Write to a file atomically using a temporary file in the same directory as the destination file."""
dir_name = os.path.dirname(path)
@@ -56,3 +61,58 @@ def get_upload_stream(filepath: str, should_compress: bool) -> tuple[io.Buffered
compressed_size = compressed_stream.tell()
compressed_stream.seek(0)
return compressed_stream, compressed_size
# remove all keys that end in DEPRECATED
def strip_deprecated_keys(d):
for k in list(d.keys()):
if isinstance(k, str):
if k.endswith('DEPRECATED'):
d.pop(k)
elif isinstance(d[k], dict):
strip_deprecated_keys(d[k])
return d
def run_cmd(cmd: list[str], cwd=None, env=None) -> str:
return subprocess.check_output(cmd, encoding='utf8', cwd=cwd, env=env).strip()
def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> str:
try:
return run_cmd(cmd, cwd=cwd, env=env)
except subprocess.CalledProcessError:
return default
@contextlib.contextmanager
def managed_proc(cmd: list[str], env: dict[str, str]):
proc = Popen(cmd, env=env, stdout=PIPE, stderr=PIPE)
try:
yield proc
finally:
if proc.poll() is None:
proc.terminate()
try:
proc.wait(timeout=5)
except TimeoutExpired:
proc.kill()
def retry(attempts=3, delay=1.0, ignore_failure=False):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(attempts):
try:
return func(*args, **kwargs)
except Exception:
cloudlog.exception(f"{func.__name__} failed, trying again")
time.sleep(delay)
if ignore_failure:
cloudlog.error(f"{func.__name__} failed after retry")
else:
raise Exception(f"{func.__name__} failed after retry")
return wrapper
return decorator
+1 -1
View File
@@ -1 +1 @@
#define COMMA_VERSION "0.10.1"
#define COMMA_VERSION "0.10.2"
+65
View File
@@ -0,0 +1,65 @@
# CarState signals
## Required for basic lateral control
* `brakePressed`
* `cruiseState`
* `doorOpen`
* `espDisabled`
* `gasPressed`
* `gearShifter`
* `leftBlinker` / `rightBlinker`
* `seatbeltUnlatched`
* `standstill`
* `steeringAngleDeg`
* `steeringPressed`
* `steeringTorque`
* `steerFaultPermanent`
* `steerFaultTemporary`
* `vCruise`
* `wheelSpeeds.[fl|fr|rl|rr]`: Speed of each of the car's four wheels, in m/s. The car's CAN bus often broadcasts the
speed in kph, so the helper function `parse_wheel_speeds` performs this conversion by default.
## Recommended / Required for openpilot longitudinal control
* `accFaulted`
* `espActive`
* `parkingBrake`
## Application Dependent
* `blockPcmEnable`
* `buttonEnable`
* `brakeHoldActive`
* `carFaultedNonCritical`
* `invalidLkasSetting`
* `lowSpeedAlert`
* `regenBraking`
* `steeringAngleOffsetDeg`
* `steeringDisengage`
* `steeringTorqueEps`
* `stockLkas`
* `vCruiseCluster`
* `vEgoCluster`
* `vehicleSensorsInvalid`
## Automatically populated
* `buttonEvents`
These values are populated automatically by `parse_wheel_speeds`:
* `aEgo`: Acceleration of the ego vehicle, Kalman filtered derivative of `vEgo`.
* `vEgo`: Speed of the ego vehicle, Kalman filtered from `vEgoRaw`.
* `vEgoRaw`: Speed of the ego vehicle, based on the average of all four wheel speeds, unfiltered.
## Optional
* `brake`
* `charging`
* `fuelGauge`
* `leftBlindspot` / `rightBlindspot`
* `steeringRateDeg`
* `stockAeb`
* `stockFcw`
* `yawRate`
+85
View File
@@ -0,0 +1,85 @@
# Stimulus-Response Tests
These are example test drives that can help identify the CAN bus messaging necessary for ADAS control. Each scripted
test should be done in a separate route (ignition cycle). These tests are a guide, not necessarily exhaustive.
While testing, constant power to the comma device is highly recommended, using [comma power](https://comma.ai/shop/comma-power) if
necessary to make sure all test activity is fully captured and for ease of uploading. If constant power isn't
available, keep the ignition on for at least one minute after your test to make sure power loss doesn't result
in loss of the last minute of testing data.
## Stationary ignition-only tests, part 1
1. Ignition on, but don't start engine, remain in Park
2. Open and close each door in a defined order: driver, passenger, rear left, rear right
3. Re-enter the vehicle, close the driver's door, and fasten the driver's seatbelt
4. Slowly press and release the accelerator pedal 3 times
5. Slowly press and release the brake pedal 3 times
6. Hold the brake and move the gearshift to reverse, then neutral, then drive, then sport/eco/etc if applicable
7. Return to Park, ignition off
Brake-pressed information may show up in several messages and signals, both as on/off states and as a percentage or
pressure. It may reflect a switch on the driver's brake pedal, or a pressure-threshold state, or signals to turn on
the rear brake lights. Start by identifying all the potential signals, and confirm while driving with ACC later.
Locate signals for all four door states if possible, but some cars only expose the driver's door state on the ADAS bus.
Driver/passenger door signals may or may not change positions for LHD vs RHD cars. For cars where only the driver's
door signal is available, the same signal may follow the driver.
## Stationary ignition-only tests, part 2
1. Ignition on, but don't start engine, remain in Park
2. Press each ACC button in a defined order: main switch on/off, set, resume, cancel, accel, decel, gap adjust
3. Set the left turn signal for about five seconds
4. Operate the left turn signal one time in its touch-to-pass mode
5. Set the right turn signal for about five seconds
6. Operate the right turn signal one time in its touch-to-pass mode
7. Set the hazard / emergency indicator switch for about five seconds
8. Ignition off
Your vehicle may have a momentary-press main ACC switch or a physical toggle that remains set. Actual ACC engagement
isn't necessary for purposes of detecting the ACC button presses.
## Steering angle and steering torque tests
Power steering should be available. On ICE cars, engine RPM may be present.
1. Ignition on, start engine if applicable, remain in Park
2. Rotate the steering wheel as follows, with a few seconds pause between each step
* Start as close to exact center as possible
* Turn to 45 degrees right and hold
* Turn to 90 degrees right and hold
* Turn to 180 degrees right and hold
* Turn to full lock right and hold, with firm pressure against lock
* Release the wheel and allow it to bounce back slightly from lock
* Turn to 180 degrees left and hold
* Return to center and release
3. Ignition off
Performing the full test to the right, followed by an abbreviated test to the left, helps give additional confirmation
of signal scale, and sign/direction for both the steering wheel angle and driver input torque signals.
## Low speed / parking lot driving tests
Before this test, drive to a place like an empty parking lot where you are free to drive in a series of curves.
1. Ignition on, start engine if applicable, prepare to drive
2. Slowly (10-20mph at most) drive a figure-8 if possible, or at least one sharp left and one sharp right.
3. Come to a complete stop
4. When and where safe, drive in reverse for a short distance (10-15 feet)
5. Park the car in a safe place, ignition off
## High speed / highway driving tests
Select a place and time where you can safely set cruise control at normal travel speeds with little interference from
traffic ahead, and safely test the response of your factory lane guidance system.
1. Ignition on, start engine if applicable, prepare to drive
2. When safely able, engage adaptive cruise control below 50 mph
3. When safely able, use the ACC buttons to accelerate to 50mph, then 55mph, then 60mph
4. Disengage adaptive cruise
5. When safely able, allow your factory lane guidance to prevent lane departures, 2-3 times on both the left and right
The series of setpoints can be adjusted to local traffic regulations, and of course metric units. The specific cruise
setpoints are useful for locating the ACC HUD signals later, and confirming their precise scaling. When the car reaches
and holds the setpoint, that can also provide additional confirmation of wheel speed scaling.
@@ -2,12 +2,13 @@ import os
from openpilot.system.ui.widgets import Widget, DialogResult
from openpilot.common.params import Params, UnknownKeyName
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.widgets.scroller import Scroller
from openpilot.system.ui.widgets.scroller_tici import Scroller
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.widgets.list_view import multiple_button_item, toggle_item, simple_item, button_item, spin_button_item, double_spin_button_item, text_spin_button_item
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dialog
LITE = os.getenv("LITE") is not None
class DragonpilotLayout(Widget):
def __init__(self):
@@ -202,7 +203,7 @@ class DragonpilotLayout(Widget):
def _device_toggles(self):
self._toggles["title_dev"] = simple_item(title=lambda: tr("### Device ###"))
if "LITE" in os.environ:
if LITE:
self._toggles["dp_dev_is_rhd"] = toggle_item(
title=lambda: tr("Enable Right-Hand Drive Mode"),
description=lambda: tr("Allow openpilot to obey right-hand traffic conventions on right driver seat."),
@@ -0,0 +1,133 @@
import numpy as np
import pyray as rl
from opendbc.car import ACCELERATION_DUE_TO_GRAVITY
from openpilot.selfdrive.ui.mici.onroad import blend_colors
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.shader_polygon import draw_polygon, Gradient
from openpilot.system.ui.widgets import Widget
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.ui.mici.onroad.torque_bar import arc_bar_pts
# TODO: arc_bar_pts doesn't consider rounded end caps part of the angle span
TORQUE_ANGLE_SPAN = 12.7
DEBUG = False
SCALE = 2.5
class TorqueBar(Widget):
def __init__(self, demo: bool = False):
super().__init__()
self._demo = demo
self._torque_filter = FirstOrderFilter(0, 0.1, 1 / gui_app.target_fps)
self._torque_line_alpha_filter = FirstOrderFilter(0.0, 0.1, 1 / gui_app.target_fps)
def update_filter(self, value: float):
"""Update the torque filter value (for demo mode)."""
self._torque_filter.update(value)
def _update_state(self):
if self._demo:
return
# torque line
if ui_state.sm['controlsState'].lateralControlState.which() == 'angleState':
controls_state = ui_state.sm['controlsState']
car_state = ui_state.sm['carState']
live_parameters = ui_state.sm['liveParameters']
lateral_acceleration = controls_state.curvature * car_state.vEgo ** 2 - live_parameters.roll * ACCELERATION_DUE_TO_GRAVITY
# TODO: pull from carparams
max_lateral_acceleration = 3
# from selfdrived
actual_lateral_accel = controls_state.curvature * car_state.vEgo ** 2
desired_lateral_accel = controls_state.desiredCurvature * car_state.vEgo ** 2
accel_diff = (desired_lateral_accel - actual_lateral_accel)
self._torque_filter.update(min(max(lateral_acceleration / max_lateral_acceleration + accel_diff, -1), 1))
else:
self._torque_filter.update(-ui_state.sm['carOutput'].actuatorsOutput.torque)
def _render(self, rect: rl.Rectangle) -> None:
# adjust y pos with torque
torque_line_offset = np.interp(abs(self._torque_filter.x), [0.5, 1], [22 * SCALE, 26 * SCALE])
torque_line_height = np.interp(abs(self._torque_filter.x), [0.5, 1], [14 * SCALE, 56 * SCALE])
# animate alpha and angle span
if not self._demo:
self._torque_line_alpha_filter.update(ui_state.status != UIStatus.DISENGAGED)
else:
self._torque_line_alpha_filter.update(1.0)
torque_line_bg_alpha = np.interp(abs(self._torque_filter.x), [0.5, 1.0], [0.25, 0.5])
torque_line_bg_color = rl.Color(255, 255, 255, int(255 * torque_line_bg_alpha * self._torque_line_alpha_filter.x))
if ui_state.status != UIStatus.ENGAGED and not self._demo:
torque_line_bg_color = rl.Color(255, 255, 255, int(255 * 0.15 * self._torque_line_alpha_filter.x))
# draw curved line polygon torque bar
torque_line_radius = 1200 * SCALE
top_angle = -90
torque_bg_angle_span = self._torque_line_alpha_filter.x * TORQUE_ANGLE_SPAN
torque_start_angle = top_angle - torque_bg_angle_span / 2
torque_end_angle = top_angle + torque_bg_angle_span / 2
# centerline radius & center
mid_r = torque_line_radius + torque_line_height / 2
cx = rect.x + rect.width / 2 + (8 * SCALE)
cy = rect.y + rect.height + torque_line_radius - torque_line_offset
# SCALED: pass cap_radius explicitly so the corners round properly
scaled_cap_radius = 7 * SCALE
# draw bg torque indicator line
bg_pts = arc_bar_pts(cx, cy, mid_r, torque_line_height, torque_start_angle, torque_end_angle,
cap_radius=scaled_cap_radius)
draw_polygon(rect, bg_pts, color=torque_line_bg_color)
# draw torque indicator line
a0s = top_angle
a1s = a0s + torque_bg_angle_span / 2 * self._torque_filter.x
sl_pts = arc_bar_pts(cx, cy, mid_r, torque_line_height, a0s, a1s,
cap_radius=scaled_cap_radius)
# draw beautiful gradient from center to 65% of the bg torque bar width
start_grad_pt = cx / rect.width
if self._torque_filter.x < 0:
end_grad_pt = (cx * (1 - 0.65) + (min(bg_pts[:, 0]) * 0.65)) / rect.width
else:
end_grad_pt = (cx * (1 - 0.65) + (max(bg_pts[:, 0]) * 0.65)) / rect.width
# fade to orange as we approach max torque
start_color = blend_colors(
rl.Color(255, 255, 255, int(255 * 0.9 * self._torque_line_alpha_filter.x)),
rl.Color(255, 200, 0, int(255 * self._torque_line_alpha_filter.x)), # yellow
max(0, abs(self._torque_filter.x) - 0.75) * 4,
)
end_color = blend_colors(
rl.Color(255, 255, 255, int(255 * 0.9 * self._torque_line_alpha_filter.x)),
rl.Color(255, 115, 0, int(255 * self._torque_line_alpha_filter.x)), # orange
max(0, abs(self._torque_filter.x) - 0.75) * 4,
)
if ui_state.status != UIStatus.ENGAGED and not self._demo:
start_color = end_color = rl.Color(255, 255, 255, int(255 * 0.35 * self._torque_line_alpha_filter.x))
gradient = Gradient(
start=(start_grad_pt, 0),
end=(end_grad_pt, 0),
colors=[
start_color,
end_color,
],
stops=[0.0, 1.0],
)
draw_polygon(rect, sl_pts, gradient=gradient)
# draw center torque bar dot
if abs(self._torque_filter.x) < 0.5:
dot_y = rect.y + rect.height - torque_line_offset - torque_line_height / 2
rl.draw_circle(int(cx), int(dot_y), int(10 * SCALE) // 2,
rl.Color(182, 182, 182, int(255 * 0.9 * self._torque_line_alpha_filter.x)))
+1 -1
View File
@@ -1 +1 @@
405631baf9685e171a0dd19547cb763f1b163d18
a29fdbd02407d41ecbcc69d151bb4837bfba3cbc
+1 -1
View File
@@ -1 +1 @@
1761284549 2025-10-23 22:42:29 -0700
1763595829 2025-11-19 15:43:49 -0800
+7 -5
View File
@@ -45,12 +45,14 @@ set_tici_hw() {
}
set_lite_hw() {
output=$(i2cget -y 0 0x10 0x00 2>/dev/null)
if grep -q "tici" /sys/firmware/devicetree/base/model 2>/dev/null; then
output=$(i2cget -y 0 0x10 0x00 2>/dev/null)
if [ -z "$output" ]; then
echo "Lite HW"
export LITE=1
export DISABLE_DRIVER=1
if [ -z "$output" ]; then
echo "Lite HW"
export LITE=1
export DISABLE_DRIVER=1
fi
fi
}
+10 -1
View File
@@ -6,8 +6,17 @@ export NUMEXPR_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1
# models get lower priority than ui
# - ui is ~5ms
# - modeld is 20ms
# - DM is 10ms
# in order to run ui at 60fps (16.67ms), we need to allow
# it to preempt the model workloads. we have enough
# headroom for this until ui is moved to the CPU.
export QCOM_PRIORITY=12
if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="14.3"
export AGNOS_VERSION="15.1"
fi
export STAGING_ROOT="/data/safe_staging"
+7 -1
View File
@@ -96,7 +96,13 @@ VisionBuf * VisionIpcClient::recv(VisionIpcBufExtra * extra, const int timeout_m
assert(r->getSize() == sizeof(VisionIpcPacket));
VisionIpcPacket *packet = (VisionIpcPacket*)r->getData();
assert(packet->idx < num_buffers);
// Check if packet index is out of bounds, indicating server has changed
if (packet->idx >= num_buffers) {
connected = false;
delete r;
return nullptr;
}
VisionBuf * buf = &buffers[packet->idx];
if (buf->server_id != packet->server_id){
+1 -1
View File
@@ -242,7 +242,7 @@
|Mazda|CX-5 2022-25|All|[Upstream](#upstream)|
|Mazda|CX-9 2016-20|All|[Dashcam mode](#dashcam)|
|Mazda|CX-9 2021-23|All|[Upstream](#upstream)|
|Nissan|Altima 2019-20|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|Altima 2019-20, 2024|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|Leaf 2018-23|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|Rogue 2018-20|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|X-Trail 2017|ProPILOT Assist|[Upstream](#upstream)|
+5 -5
View File
@@ -549,15 +549,15 @@ struct CarParams {
}
struct LateralTorqueTuning {
kp @1 :Float32;
ki @2 :Float32;
kd @8 : Float32;
friction @3 :Float32;
kf @4 :Float32;
steeringAngleDeadzoneDeg @5 :Float32;
latAccelFactor @6 :Float32;
latAccelOffset @7 :Float32;
useSteeringAngleDEPRECATED @0 :Bool;
kpDEPRECATED @1 :Float32;
kiDEPRECATED @2 :Float32;
kfDEPRECATED @4 :Float32;
kdDEPRECATED @8 : Float32;
}
struct LongitudinalPIDTuning {
@@ -565,7 +565,7 @@ struct CarParams {
kpV @1 :List(Float32);
kiBP @2 :List(Float32);
kiV @3 :List(Float32);
kf @6 :Float32;
kfDEPRECATED @6 :Float32;
deadzoneBPDEPRECATED @4 :List(Float32);
deadzoneVDEPRECATED @5 :List(Float32);
}
@@ -351,6 +351,7 @@ FW_VERSIONS = {
b'68402707AB',
b'68402708AB',
b'68402714AB',
b'68402736AB',
b'68402971AD',
b'68454144AD',
b'68454145AB',
@@ -379,6 +380,7 @@ FW_VERSIONS = {
b'68417279AA',
b'68417280AA',
b'68417281AA',
b'68417283AA',
b'68453431AA',
b'68453433AA',
b'68453435AA',
@@ -391,6 +393,7 @@ FW_VERSIONS = {
b'05035674AB ',
b'68412635AE ',
b'68412635AG ',
b'68412635AH ',
b'68412660AD ',
b'68412660AF ',
b'68422860AB',
@@ -404,6 +407,7 @@ FW_VERSIONS = {
(Ecu.transmission, 0x7e1, None): [
b'05035707AA',
b'68419672AC',
b'68419675AC',
b'68419678AB',
b'68423905AB',
b'68449258AC',
@@ -26,7 +26,7 @@ FW_VERSIONS = {
],
(Ecu.fwdCamera, 0x18dab5f1, None): [
b'38897-TTA-J010\x00\x00',
]
],
},
CAR.HONDA_ACCORD: {
(Ecu.shiftByWire, 0x18da0bf1, None): [
@@ -331,6 +331,7 @@ FW_VERSIONS = {
(Ecu.vsa, 0x18da28f1, None): [
b'57114-T1W-A230\x00\x00',
b'57114-T1W-A240\x00\x00',
b'57114-TFF-A930\x00\x00',
b'57114-TFF-A940\x00\x00',
],
(Ecu.srs, 0x18da53f1, None): [
@@ -1055,7 +1056,7 @@ FW_VERSIONS = {
(Ecu.fwdRadar, 0x18dab0f1, None): [
b'36802-TGV-A060\x00\x00',
],
(Ecu.fwdCamera, 0x18dab5f1, None): [
(Ecu.fwdCamera, 0x18dab5f1, None): [
b'36161-TGV-A030\x00\x00',
],
},
+1 -1
View File
@@ -121,7 +121,7 @@ def create_steering_control(packer, CAN, apply_torque, lkas_active, tja_control)
}
if tja_control:
values["STEER_DOWN_TO_ZERO"] = 1
values["STEER_DOWN_TO_ZERO"] = lkas_active
return packer.make_can_msg("STEERING_CONTROL", CAN.lkas, values)
+1 -1
View File
@@ -48,7 +48,7 @@ class CarInterface(CarInterfaceBase):
# If Bosch radarless, this blocks ACC messages from the camera
# TODO: get radar disable working on Bosch CANFD
ret.alphaLongitudinalAvailable = candidate not in HONDA_BOSCH_CANFD
ret.openpilotLongitudinalControl = alpha_long
ret.openpilotLongitudinalControl = alpha_long and (candidate not in HONDA_BOSCH_CANFD)
ret.pcmCruise = not ret.openpilotLongitudinalControl
else:
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hondaNidec)]
-5
View File
@@ -210,7 +210,6 @@ class CarInterfaceBase(ABC):
ret.stoppingDecelRate = 0.8 # brake_travel/s while trying to stop
ret.vEgoStopping = 0.5
ret.vEgoStarting = 0.5
ret.longitudinalTuning.kf = 1.
ret.longitudinalTuning.kpBP = [0.]
ret.longitudinalTuning.kpV = [0.]
ret.longitudinalTuning.kiBP = [0.]
@@ -225,10 +224,6 @@ class CarInterfaceBase(ABC):
params = get_torque_params()[candidate]
tune.init('torque')
tune.torque.kf = 1.0
tune.torque.kp = 1.0
tune.torque.ki = 0.3
tune.torque.kd = 0.0
tune.torque.friction = params['FRICTION']
tune.torque.latAccelFactor = params['LAT_ACCEL_FACTOR']
tune.torque.latAccelOffset = 0.0
@@ -11,12 +11,15 @@ FW_VERSIONS = {
],
(Ecu.eps, 0x742, None): [
b'6CA2B\xa9A\x02\x02G8A89P90D6A\x00\x00\x01\x80',
b'6CA2C\xa9A\x02\x02G8A89P90D6A\x00\x00\x01\x80',
],
(Ecu.engine, 0x7e0, None): [
b'237106GU3B',
b'237109HE2B',
],
(Ecu.gateway, 0x18dad0f1, None): [
b'284U29HE0A',
b'284U29HF0A',
],
},
CAR.NISSAN_LEAF: {
@@ -56,6 +59,7 @@ FW_VERSIONS = {
b'5SK0ADB\x04\x18\x00\x00\x00\x00\x00_(5\x07\x9aQ\x00\x00\x00\x80',
],
(Ecu.abs, 0x740, None): [
b'476605SD2D',
b'476605SD2E',
b'476605SH1D',
b'476605SH7D',
@@ -66,13 +70,17 @@ FW_VERSIONS = {
b'5SH2A\x99A\x05\x02N123F\x15\x81\x00\x00\x00\x00\x00\x00\x00\x80',
b'5SH2A\xb7A\x05\x02N123F\x15\xa3\x00\x00\x00\x00\x00\x00\x00\x80',
b'5SH2C\xb7A\x05\x02N123F\x15\xa3\x00\x00\x00\x00\x00\x00\x00\x80',
b'5SH3A\x99A\x05\x02N123F\x15\x81\x00\x00\x00\x00\x00\x00\x00\x80',
b'5SH3C\xb7A\x05\x02N123F\x15\xa3\x00\x00\x00\x00\x00\x00\x00\x80',
b'5SK3A\x99A\x05\x02N123F\x15u\x00\x00\x00\x00\x00\x00\x00\x80',
],
(Ecu.gateway, 0x18dad0f1, None): [
b'284U25SF0C',
b'284U25SH3A',
b'284U25SH3B',
b'284U25SK2D',
b'284U25SR0B',
b'284U25SR0C',
],
},
CAR.NISSAN_XTRAIL: {
+1 -1
View File
@@ -72,7 +72,7 @@ class CAR(Platforms):
NissanCarSpecs(mass=1610, wheelbase=2.705)
)
NISSAN_ALTIMA = NissanPlatformConfig(
[NissanCarDocs("Nissan Altima 2019-20", car_parts=CarParts.common([CarHarness.nissan_b]))],
[NissanCarDocs("Nissan Altima 2019-20, 2024", car_parts=CarParts.common([CarHarness.nissan_b]))],
NissanCarSpecs(mass=1492, wheelbase=2.824)
)
@@ -87,7 +87,7 @@ class TestCarInterfaces:
assert len(tune.pid.kiV) > 0 and len(tune.pid.kiV) == len(tune.pid.kiBP)
elif tune.which() == 'torque':
assert not math.isnan(tune.torque.kf) and tune.torque.kf > 0
assert not math.isnan(tune.torque.latAccelFactor) and tune.torque.latAccelFactor > 0
assert not math.isnan(tune.torque.friction) and tune.torque.friction > 0
# Run car interface
@@ -159,14 +159,14 @@ class CarState(CarStateBase):
ret.steerFaultTemporary, ret.steerFaultPermanent = self.update_hca_state(hca_status)
# Update gas, brakes, and gearshift.
ret.gasPressed = pt_cp.vl["Motor_3"]["Fahrpedal_Rohsignal"] > 0
ret.gasPressed = pt_cp.vl["Motor_3"]["MO3_Pedalwert"] > 0
ret.brake = pt_cp.vl["Bremse_5"]["BR5_Bremsdruck"] / 250.0 # FIXME: this is pressure in Bar, not sure what OP expects
ret.brakePressed = bool(pt_cp.vl["Motor_2"]["MO2_BLS"])
ret.parkingBrake = bool(pt_cp.vl["Kombi_1"]["Bremsinfo"])
# Update gear and/or clutch position data.
if self.CP.transmissionType == TransmissionType.automatic:
ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Getriebe_1"]["Waehlhebelposition__Getriebe_1_"], None))
ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Getriebe_1"]["GE1_Wahl_Pos"], None))
elif self.CP.transmissionType == TransmissionType.manual:
reverse_light = bool(pt_cp.vl["Gate_Komf_1"]["GK1_Rueckfahr"])
if reverse_light:
@@ -206,7 +206,7 @@ class CarState(CarStateBase):
# Update ACC radar status.
self.acc_type = ext_cp.vl["ACC_System"]["ACS_Typ_ACC"]
ret.cruiseState.available = bool(pt_cp.vl["Motor_5"]["GRA_Hauptschalter"])
ret.cruiseState.available = bool(pt_cp.vl["Motor_5"]["MO5_GRA_Hauptsch"])
ret.cruiseState.enabled = pt_cp.vl["Motor_2"]["MO2_Sta_GRA"] in (1, 2)
if self.CP.pcmCruise:
ret.accFaulted = ext_cp.vl["ACC_GRA_Anzeige"]["ACA_StaACC"] in (6, 7)
@@ -81,7 +81,7 @@ class CarControllerParams:
self.STEER_DELTA_DOWN = 10 # Min HCA reached in 0.60s (STEER_MAX / (50Hz * 0.60))
if CP.transmissionType == TransmissionType.automatic:
self.shifter_values = can_define.dv["Getriebe_1"]["Waehlhebelposition__Getriebe_1_"]
self.shifter_values = can_define.dv["Getriebe_1"]["GE1_Wahl_Pos"]
self.hca_status_values = can_define.dv["Lenkhilfe_2"]["LH2_Sta_HCA"]
self.BUTTONS = [
@@ -90,7 +90,7 @@ class CarControllerParams:
Button(structs.CarState.ButtonEvent.Type.accelCruise, "GRA_Neu", "GRA_Up_kurz", [1]),
Button(structs.CarState.ButtonEvent.Type.decelCruise, "GRA_Neu", "GRA_Down_kurz", [1]),
Button(structs.CarState.ButtonEvent.Type.cancel, "GRA_Neu", "GRA_Abbrechen", [1]),
Button(structs.CarState.ButtonEvent.Type.gapAdjustCruise, "GRA_Neu", "GRA_Zeitluecke", [1]),
Button(structs.CarState.ButtonEvent.Type.gapAdjustCruise, "GRA_Neu", "GRA_Zeitluecke", [3]),
]
self.LDW_MESSAGES = {
+235 -99
View File
@@ -22,6 +22,7 @@ NS_ :
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
SG_MUL_VAL_
BS_:
@@ -330,50 +331,64 @@ BO_ 1160 Motor_6: 8 XXX
SG_ Sollmoment_f_r_Getriebe : 8|8@1+ (0.39,0) [0|99] "MDI" XXX
SG_ Checksumme_Motor_6 : 0|8@1+ (1,0) [0|0] "" XXX
BO_ 1152 Motor_5: 8 XXX
SG_ CHECKSUM : 56|8@1+ (1,0) [0|0] "" XXX
SG_ Motortext_Bits__4_1_ : 52|4@1+ (1,0) [0|0] "" XXX
SG_ Doppelte_Momente : 51|1@1+ (1,0) [0|0] "" XXX
SG_ GRA_Hauptschalter : 50|1@1+ (1,0) [0|0] "" XXX
SG_ Anlasser_Ausspuren : 49|1@1+ (1,0) [0|0] "" XXX
SG_ Anlasser_Freigabe : 48|1@1+ (1,0) [0|0] "" XXX
SG_ Klimadrucksignal__Motor_5_ : 40|8@1+ (0.2,0) [0|50.8] "bar" XXX
SG_ K_hlerluefteransteuerung : 32|8@1+ (0.4,0) [0|101.6] "%" XXX
SG_ Verbrauch_Ueberlauf : 31|1@1+ (1,0) [0|0] "" XXX
SG_ Kraftstoffverbrauchssignal : 16|15@1+ (1,0) [0|32767] "ul" XXX
SG_ Klimakompressor_Leistungsreduzi : 15|1@1+ (1,0) [0|0] "" XXX
SG_ Kennfeldkuehlung : 14|1@1+ (1,0) [0|0] "" XXX
SG_ Klimakompressor_aus__Motor_5_ : 13|1@1+ (1,0) [0|0] "" XXX
SG_ CAT_Warnung : 12|1@1+ (1,0) [0|0] "" XXX
SG_ OBD_2_Lampe : 11|1@1+ (1,0) [0|0] "" XXX
SG_ E_Gas_Lampe : 10|1@1+ (1,0) [0|0] "" XXX
SG_ Vorgluehlampe__Motor_5_ : 9|1@1+ (1,0) [0|0] "" XXX
SG_ Ladekontroll_Lampe : 8|1@1+ (1,0) [0|0] "" XXX
SG_ Multiplex_Code M : 6|2@1+ (1,0) [0|0] "" XXX
SG_ Multiplex_Info_norm__Verbrauch m3 : 0|6@1+ (20,0) [0|1260] "l/Zyl" XXX
SG_ Multiplex_Info_Motortyp m2 : 0|6@1+ (1,0) [0|0] "" XXX
SG_ Multiplex_Info_Drehzahl_MD_Max m1 : 0|6@1+ (100,0) [0|6300] "U/min" XXX
SG_ Multiplex_Info_Max_Drehmoment m0 : 0|6@1+ (10,0) [0|630] "Nm" XXX
BO_ 1152 Motor_5: 8 Motor
SG_ MO5_Mp_Code M : 6|2@1+ (1,0) [0|3] "" Gateway
SG_ MO5_max_Moment m0 : 0|6@1+ (10,0) [0|630] "Nm" Gateway
SG_ MO5_Drehzahl m1 : 0|6@1+ (100,0) [0|6300] "U/min" Gateway
SG_ MO5_Motortyp m2 : 0|6@1+ (1,0) [0|63] "" Gateway
SG_ MO5_Abgastyp m3 : 0|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Abgastyp2 m3 : 1|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Abgastyp3 m3 : 2|1@1+ (1,0) [0|1] "" Gateway
SG_ OBD_Kaltstart_Denominator m3 : 3|1@1+ (1,0) [0|1] "" Gateway
SG_ OBD_Minimum_Trip m3 : 4|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_DPF_reg m3 : 5|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Vorgluehen : 9|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_E_Gas : 10|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_OBD_2 : 11|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Heissl : 12|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_KlimaKompr : 13|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Feld_kuehl : 14|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_KliKo_Red : 15|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Verbrauch : 16|15@1+ (1,0) [0|32767] "µl" KOMBI
SG_ MO5_UeberlVerb : 31|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Luefter : 32|8@1+ (0.4,0) [0|101.6] "%" Gateway
SG_ MO5_HLeuchte : 40|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_PartikelLamp : 41|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Sta_BKU : 42|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_TypStartSteu : 43|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_TDE_Lampe : 44|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_TDE_Text : 45|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_DZM_Daempf : 46|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Interlock : 47|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Start : 48|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Anlasser : 49|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_GRA_Hauptsch : 50|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Momente : 51|1@1+ (1,0) [0|1] "" Gateway
SG_ MO5_Motortext1 : 52|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Motortext2 : 53|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Motortext3 : 54|1@1+ (1,0) [0|1] "" KOMBI
SG_ MO5_Motortext4 : 55|1@1+ (1,0) [0|1] "" KOMBI
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" Gateway
BO_ 896 Motor_3: 8 XXX
SG_ Drosselklappenpoti : 56|8@1+ (0.4,0) [0|101.6] "%" XXX
SG_ Motor_Wunschdrehzahl : 48|8@1+ (25,0) [0|6350] "U/min" XXX
SG_ Motordrehzahlbeeinflussung : 40|8@1+ (0.392,0) [0|100] "%" XXX
SG_ Kein_Start_Stop : 39|1@1+ (1,0) [0|0] "" XXX
SG_ Kein_E_Gas : 38|1@1+ (1,0) [0|0] "" XXX
SG_ Reserviert_Motor_3_1 : 37|1@1+ (1,0) [0|0] "" XXX
SG_ Vorzeichen_Rad_Wunschmoment : 36|1@1+ (1,0) [0|0] "" XXX
SG_ Rad_Wunschmoment : 24|12@1+ (0.39,0) [0|1597] "MDI" XXX
SG_ Fahrpedal_Rohsignal : 16|8@1+ (0.4,0) [0|101.6] "%" XXX
SG_ Ansauglufttemperatur : 8|8@1+ (0.75,-48) [-48|142.5] "" XXX
SG_ Fehlerstatus_Ansauglufttemperat : 7|1@1+ (1,0) [0|0] "" XXX
SG_ Motorsteuerger_t_gesperrt : 6|1@1+ (1,0) [0|0] "" XXX
SG_ Drosselklappenwinkel_ungenau : 5|1@1+ (1,0) [0|0] "" XXX
SG_ Fahrpedalwert_ungenau__Motor_3_ : 4|1@1+ (1,0) [0|0] "" XXX
SG_ Frei_Motor_3_1 : 3|1@1+ (1,0) [0|0] "" XXX
SG_ Motor_Wunschdrehzahl_Priorit_t : 2|1@1+ (1,0) [0|0] "" XXX
SG_ Uebertemperaturschutz__Motor_3_ : 1|1@1+ (1,0) [0|0] "" XXX
SG_ Vorgluehmeldung : 0|1@1+ (1,0) [0|0] "" XXX
BO_ 896 Motor_3: 8 Motor
SG_ MO3_Vorgluehen : 0|1@1+ (1,0) [0|1] "" Gateway
SG_ MO3_Prio_Dz : 1|1@1+ (1,0) [0|1] "" Transmission
SG_ MO_Schalter_StartStopp : 2|1@1+ (1,0) [0|1] "" Gateway
SG_ MO3_Winterprg : 3|1@1+ (1,0) [0|1] "" Transmission
SG_ MO3_Sta_Pedal : 4|1@1+ (1,0) [0|1] "" Gateway
SG_ MO3_Sta_FPG M : 5|1@1+ (1,0) [0|1] "" ESP
SG_ MO3_Sign_FPG m1 : 6|1@1+ (1,0) [0|1] "" ESP
SG_ MO3_Sta_Temp : 7|1@1+ (1,0) [0|1] "" Gateway
SG_ MO3_Offsentemp : 8|8@1+ (0.75,-48) [-48|142.5] "°C" Gateway
SG_ MO3_Pedalwert : 16|8@1+ (0.4,0) [0|101.6] "%" Gateway
SG_ MO3_Rad_Wu_Mo : 24|12@1+ (0.39,0) [0|1596.66] "%" Transmission
SG_ MO3_Vorz_RadWu : 36|1@1+ (1,0) [0|1] "" Transmission
SG_ MO3_Freigabe_Segeln : 37|1@1+ (1,0) [0|1] "" Transmission
SG_ MO_StartStopp_StoppVorbereitung : 38|1@1+ (1,0) [0|1] "" Gateway
SG_ MO3_Dz_Beeinfl : 40|8@1+ (0.39,0) [0|99.45] "%" Transmission
SG_ MO3_WunschDz : 48|8@1+ (25,0) [0|6350] "U/min" Transmission
SG_ MO3_DKW m0 : 56|8@1+ (0.4,0) [0|101.6] "%" Gateway
SG_ MO3_FPGradient m1 : 56|8@1+ (25,0) [0|6350] "%/s" ESP
BO_ 648 Motor_2: 8 Motor
SG_ MO2_Mp_Code m : 6|2@1+ (1,0) [0|3] "" Gateway
@@ -705,28 +720,27 @@ BO_ 1344 Getriebe_2: 8 XXX
SG_ Schubabschaltunterstuetzung : 1|1@1+ (1,0) [0|0] "" XXX
SG_ LFR_Adaption_Freigabeflag : 0|1@1+ (1,0) [0|0] "" XXX
BO_ 1088 Getriebe_1: 8 XXX
SG_ Wandlerverlustmoment : 56|8@1+ (0.39,0) [0|99.06] "MDI" XXX
SG_ Fehlerspeichereintrag__Getriebe : 55|1@1+ (1,0) [0|0] "" XXX
SG_ COUNTER : 51|4@1+ (1,0) [0|15] "" XXX
SG_ Gang_eingelegt : 50|1@1+ (1,0) [0|0] "" XXX
SG_ Schaltabsicht : 49|1@1+ (1,0) [0|0] "" XXX
SG_ Motor_aus : 48|1@1+ (1,0) [0|0] "" XXX
SG_ OBD_Status__Getriebe_1___4_1_ : 46|2@1+ (1,0) [0|0] "" XXX
SG_ Kuehlleistung : 44|2@1+ (1,0) [0|0] "" XXX
SG_ Getriebe_Notlauf : 40|4@1+ (1,0) [0|0] "" XXX
SG_ Fahrwiderstandsindex : 32|8@1+ (0.249,-31.6) [-31.6|31.6] "" XXX
SG_ inneres_Soll_Motormoment : 24|8@1+ (0.39,0) [0|99.06] "MDI" XXX
SG_ Uebertragungsfunktion : 16|8@1+ (0.1,0) [0|25.4] "" XXX
SG_ Waehlhebelposition__Getriebe_1_ : 12|4@1+ (1,0) [0|0] "" XXX
SG_ Zielgang_oder_eingelegter_Gang : 8|4@1+ (1,0) [0|0] "" XXX
SG_ EGS_Anforderung : 7|1@1+ (1,0) [0|0] "" XXX
SG_ Kodierung_im_MSG : 6|1@1+ (1,0) [0|0] "" XXX
SG_ Leerlaufsolldrehzahlanhebung : 5|1@1+ (1,0) [0|0] "" XXX
SG_ Wandlerkupplung : 3|2@1+ (1,0) [0|0] "" XXX
SG_ Klimakompressor_aus__Getriebe_1 : 2|1@1+ (1,0) [0|0] "" XXX
SG_ Status_Getriebe_und_Wandlerschu : 1|1@1+ (1,0) [0|0] "" XXX
SG_ Schaltung_aktiv__Getriebe_1_ : 0|1@1+ (1,0) [0|0] "" XXX
BO_ 1088 Getriebe_1: 8 Transmission
SG_ GE1_Schaltung : 0|1@1+ (1,0) [0|1] "" Gateway
SG_ GE1_Sta_Schutz : 1|1@1+ (1,0) [0|1] "" Motor
SG_ GE1_Klimakompr : 2|1@1+ (1,0) [0|1] "" Motor
SG_ GE1_WK : 3|2@1+ (1,0) [0|3] "" Gateway
SG_ GE1_StSt_Info : 5|2@1+ (1,0) [0|3] "" Gateway
SG_ GE1_EGS_Anf : 7|1@1+ (1,0) [0|1] "" Motor
SG_ GE1_Zielgang : 8|4@1+ (1,0) [0|15] "" Gateway
SG_ GE1_Wahl_Pos : 12|4@1+ (1,0) [0|15] "" Gateway
SG_ GE1_Mrad_Mkurb : 16|8@1+ (0.1,0) [0|25.4] "" Gateway
SG_ GE1_Soll_Mo : 24|8@1+ (0.39,0) [0|99.06] "%" Motor
SG_ GE1_Fahrwistd : 32|8@1+ (0.249,-31.623) [-31.623|31.623] "" Gateway
SG_ GE1_Notlauf : 40|4@1+ (1,0) [0|15] "" Gateway
SG_ GE1_Kuehlung : 44|2@1+ (1,0) [0|3] "" Gateway
SG_ GE1_Sta_OBD : 47|1@1+ (1,0) [0|1] "" Motor
SG_ GE1_LaunchControl : 48|1@1+ (1,0) [0|1] "" ESP
SG_ GE1_Infobit : 49|1@1+ (1,0) [0|1] "" Gateway
SG_ GE1_SleepInd : 50|1@1+ (1,0) [0|1] "" Gateway
SG_ COUNTER : 51|4@1+ (1,0) [0|15] "" Gateway
SG_ GE1_Fehlereintr : 55|1@1+ (1,0) [0|1] "" Gateway
SG_ GE1_WaVerl_Mo : 56|8@1+ (0.39,0) [0|99.06] "%" Motor
BO_ 912 Gate_Komf_1: 8 XXX
SG_ GK1_Sta_RDK_Warn : 0|1@1+ (1,0) [0|1] "" XXX
@@ -1406,6 +1420,8 @@ BO_ 1175 Parkhilfe_01: 8 XXX
SG_ PH_KD_Fehler : 63|1@1+ (1,0) [0|1] "" XXX
BO_ 1463 Bremse_11: 8 XXX
SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX
SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX
SG_ B11_HydHalten : 13|1@1+ (1,0) [0|1] "" XXX
SG_ B11_Br_StSt_Info : 14|2@1+ (1,0) [0|3] "" XXX
SG_ B11_OBD_Nib_VL : 16|4@1+ (1,0) [0|15] "" XXX
@@ -1600,14 +1616,24 @@ CM_ SG_ 648 MO2_LL_Solldz "Idle target speed";
CM_ SG_ 648 MO2_Begr_Mo "Limiting torque - max possible at speed";
CM_ SG_ 648 MO2_Mo_ZWR "Minimum engine torque with ignition angle retardation";
CM_ SG_ 896 Drosselklappenpoti "Throttle Position";
CM_ SG_ 896 Motor_Wunschdrehzahl "Desired engine speed";
CM_ SG_ 896 Motordrehzahlbeeinflussung "Shift Target Influence";
CM_ SG_ 896 Fahrpedal_Rohsignal "Accelerator Pedal Position";
CM_ SG_ 896 Ansauglufttemperatur "Intake Air Temperature";
CM_ SG_ 896 Kein_E_Gas "ETB flag";
CM_ SG_ 896 Kein_Start_Stop "Start/stop flag";
CM_ SG_ 896 Rad_Wunschmoment "Desired wheel torque";
CM_ SG_ 896 MO3_Vorgluehen "Pre-glow active (diesel engines)";
CM_ SG_ 896 MO3_Prio_Dz "Engine speed priority: 0=request, 1=mandatory";
CM_ SG_ 896 MO_Schalter_StartStopp "Start/stop deactivated by driver (LED on when 0)";
CM_ SG_ 896 MO3_Winterprg "Winter driving program active";
CM_ SG_ 896 MO3_Sta_Pedal "Accelerator pedal status: 0=OK, 1=substitute value";
CM_ SG_ 896 MO3_Sta_FPG "Accelerator pedal gradient control bit (multiplexer for byte 8)";
CM_ SG_ 896 MO3_Sign_FPG "Accelerator pedal gradient sign (only when MO3_Sta_FPG=1)";
CM_ SG_ 896 MO3_Sta_Temp "Intake air temperature status: 0=OK, 1=substitute value";
CM_ SG_ 896 MO3_Offsentemp "Intake air temperature";
CM_ SG_ 896 MO3_Pedalwert "Accelerator pedal raw signal (0-101.6%)";
CM_ SG_ 896 MO3_Rad_Wu_Mo "Wheel torque request (12-bit value, 0-1596.66% MDI)";
CM_ SG_ 896 MO3_Vorz_RadWu "Wheel torque sign: 0=positive, 1=negative";
CM_ SG_ 896 MO3_Freigabe_Segeln "Sailing operation enable for transmission";
CM_ SG_ 896 MO_StartStopp_StoppVorbereitung "Engine stop in preparation";
CM_ SG_ 896 MO3_Dz_Beeinfl "Engine speed influence factor (0-100% interpolation)";
CM_ SG_ 896 MO3_WunschDz "Desired engine speed (when MO3_Prio_Dz=1)";
CM_ SG_ 896 MO3_DKW "Throttle valve position when MO3_Sta_FPG=0 (0-101.6%)";
CM_ SG_ 896 MO3_FPGradient "Accelerator pedal gradient when MO3_Sta_FPG=1 (0-6350%/s)";
CM_ SG_ 912 GK1_Fa_Tuerkont "Status of the driver's door rotary latch";
CM_ SG_ 912 BSK_HL_geoeffnet "Status of the rear left door rotary latch";
@@ -1615,18 +1641,28 @@ CM_ SG_ 912 BSK_HR_geoeffnet "Status of the rear right door rotary latch";
CM_ SG_ 912 BSK_BT_geoeffnet "Status of the passenger door rotary latch";
CM_ SG_ 912 BSK_HD_Hauptraste "Status of trunk lid main detent";
CM_ SG_ 1088 Zaehler_Getriebe_1 "Counter Getriebe_1";
CM_ SG_ 1088 Waehlhebelposition__Getriebe_1_ "Gear Selector Position";
CM_ SG_ 1088 inneres_Soll_Motormoment "Desired Inner Torque";
CM_ SG_ 1088 Gang_eingelegt "Gear Engaged";
CM_ SG_ 1088 Schaltabsicht "Shift Intent";
CM_ SG_ 1088 Kuehlleistung "Cooling Power";
CM_ SG_ 1088 Wandlerverlustmoment "Converter Torque Loss";
CM_ SG_ 1088 Getriebe_Notlauf "Transmission_Notlauf";
CM_ SG_ 1088 Zielgang_oder_eingelegter_Gang "target_gear_or_gear_in_engagement";
CM_ SG_ 1088 Uebertragungsfunktion "transfer function";
CM_ SG_ 1088 EGS_Anforderung "EGS Requirement";
CM_ SG_ 1088 Schaltung_aktiv__Getriebe_1_ "Shift Activity";
CM_ BO_ 1088 "Getriebe 1 - Contains gear status, torque requests, and control signals";
CM_ SG_ 1088 GE1_Schaltung "Gear shift active: 0=no shift, 1=shift in progress";
CM_ SG_ 1088 GE1_Sta_Schutz "Transmission/converter protection request (power reduction or ignition angle)";
CM_ SG_ 1088 GE1_Klimakompr "AC compressor off request";
CM_ SG_ 1088 GE1_WK "Torque converter clutch status";
CM_ SG_ 1088 GE1_StSt_Info "Start/stop coordinator info";
CM_ SG_ 1088 GE1_EGS_Anf "EGS request - byte 4 becomes valid when set";
CM_ SG_ 1088 GE1_Zielgang "Target gear when shifting or current gear";
CM_ SG_ 1088 GE1_Wahl_Pos "Selector lever position / driving program";
CM_ SG_ 1088 GE1_Mrad_Mkurb "Wheel torque to crankshaft torque ratio (Mrad/Mcrank)";
CM_ SG_ 1088 GE1_Soll_Mo "Internal target engine torque request (0-99.06%)";
CM_ SG_ 1088 GE1_Fahrwistd "Driving resistance index (normalized % slope)";
CM_ SG_ 1088 GE1_Notlauf "Emergency mode status";
CM_ SG_ 1088 GE1_Kuehlung "Cooling request level";
CM_ SG_ 1088 GE1_Sta_OBD "OBD status - MIL lamp control";
CM_ SG_ 1088 GE1_LaunchControl "Launch control active";
CM_ SG_ 1088 GE1_Infobit "Transmission type: 0=stepped automatic, 1=CVT";
CM_ SG_ 1088 GE1_SleepInd "Sleep readiness after terminal 15 off";
CM_ SG_ 1088 GE1_Zaehler "Message counter (synchronized with Getriebe_2)";
CM_ SG_ 1088 GE1_Fehlereintr "Fault memory entry present";
CM_ SG_ 1088 GE1_WaVerl_Mo "Transmission torque loss / clutch torque (0-99.06%)";
CM_ SG_ 1056 Fehlerstatus_Aussentemp__4_1 "ambient temp error";
CM_ SG_ 1056 Fehlerstatus_Oeltemperatur_4_1 "oil temp error";
@@ -1637,19 +1673,45 @@ CM_ SG_ 1056 Kuehlmitteltemp__4_1__Kombi_2_ "kombi coolant temperature";
CM_ SG_ 1096 Zaehler_Waehlhebel_1 "Counter Waehlhebel_1";
CM_ SG_ 1152 CHECKSUM "Checksum Motor_5";
CM_ SG_ 1152 Anlasser_Ausspuren "Starter Disable";
CM_ SG_ 1152 Anlasser_Freigabe "Starter Release";
CM_ SG_ 1152 Klimadrucksignal__Motor_5_ "Air conditioning pressure signal";
CM_ SG_ 1152 Kraftstoffverbrauchssignal "Fuel consumption signal";
CM_ SG_ 1152 K_hlerluefteransteuerung "Cooling fan control signal";
CM_ SG_ 1152 Klimakompressor_Leistungsreduzi "Air conditioning compressor power reduction flag";
CM_ SG_ 1152 Klimakompressor_aus__Motor_5_ "Air conditioning compressor";
CM_ SG_ 1152 Anlasser_Freigabe "Starter release";
CM_ SG_ 1152 OBD_2_Lampe "OBD light";
CM_ SG_ 1152 E_Gas_Lampe "ETB light";
CM_ SG_ 1152 Ladekontroll_Lampe "Charge light";
CM_ SG_ 1152 Vorgluehlampe__Motor_5_ "Glow light";
CM_ BO_ 1152 "Motor message 5 - Contains engine type, consumption, lamps, and diagnostic info";
CM_ SG_ 1152 MO5_Mp_Code "Multiplex selector - switches every 4 transmissions";
CM_ SG_ 1152 MO5_max_Moment "Maximum torque when Mp_Code=0 (0-630 Nm)";
CM_ SG_ 1152 MO5_Drehzahl "Engine speed at max torque when Mp_Code=1 (0-6300 RPM)";
CM_ SG_ 1152 MO5_Motortyp "Engine type info when Mp_Code=2 (cylinder count, turbo, fuel type)";
CM_ SG_ 1152 MO5_Abgastyp "Exhaust type EOBD when Mp_Code=3";
CM_ SG_ 1152 MO5_Abgastyp2 "Exhaust type OBD when Mp_Code=3";
CM_ SG_ 1152 MO5_Abgastyp3 "DPF installed when Mp_Code=3";
CM_ SG_ 1152 OBD_Kaltstart_Denominator "Cold start denominator increment when Mp_Code=3";
CM_ SG_ 1152 OBD_Minimum_Trip "Minimum normalized trip when Mp_Code=3";
CM_ SG_ 1152 MO5_DPF_reg "DPF regenerating when Mp_Code=3";
CM_ SG_ 1152 MO5_Vorgluehen "Diesel pre-glow lamp";
CM_ SG_ 1152 MO5_E_Gas "E-Gas system lamp (petrol only)";
CM_ SG_ 1152 MO5_OBD_2 "OBD/MIL lamp control";
CM_ SG_ 1152 MO5_Heissl "Coolant overheat warning lamp";
CM_ SG_ 1152 MO5_KlimaKompr "AC compressor off request";
CM_ SG_ 1152 MO5_Feld_kuehl "Map cooling installed and OK";
CM_ SG_ 1152 MO5_KliKo_Red "AC compressor power reduction";
CM_ SG_ 1152 MO5_Verbrauch "Fuel consumption counter (15-bit, µl)";
CM_ SG_ 1152 MO5_UeberlVerb "Consumption counter overflow";
CM_ SG_ 1152 MO5_Luefter "Cooling fan PWM control (0-101.6%)";
CM_ SG_ 1152 MO5_HLeuchte "Overheat pre-warning";
CM_ SG_ 1152 MO5_PartikelLamp "Particle filter lamp";
CM_ SG_ 1152 MO5_Sta_BKU "Brake vacuum pump status (Porsche only)";
CM_ SG_ 1152 MO5_TypStartSteu "Starter control type: 0=BSG/BCM, 1=MSG";
CM_ SG_ 1152 MO5_TDE_Lampe "Fuel cap warning lamp (petrol only)";
CM_ SG_ 1152 MO5_TDE_Text "Fuel cap text display (petrol only)";
CM_ SG_ 1152 MO5_DZM_Daempf "RPM gauge damping control";
CM_ SG_ 1152 MO5_Interlock "Interlock switch for manual transmission start";
CM_ SG_ 1152 MO5_Start "Automatic start permission";
CM_ SG_ 1152 MO5_Anlasser "Starter control permission";
CM_ SG_ 1152 MO5_GRA_Hauptsch "GRA main switch / readiness";
CM_ SG_ 1152 MO5_Momente "MDI torque values doubled";
CM_ SG_ 1152 MO5_Motortext1 "Text: Engine workshop";
CM_ SG_ 1152 MO5_Motortext2 "Text: Exhaust workshop (deprecated)";
CM_ SG_ 1152 MO5_Motortext3 "Text: Fuel system fault";
CM_ SG_ 1152 MO5_Motortext4 "Text: Particle filter needs regeneration";
CM_ SG_ 1152 CHECKSUM "Checksum with final value 0x0";
CM_ SG_ 1160 Zaehler_Motor_6 "Counter Motor_6";
CM_ SG_ 1160 Hoeheninfo__Motor_6_ "Altitude Correction";
@@ -1688,6 +1750,10 @@ CM_ SG_ 1550 MFA_v_Signal_02 "0=km/h, 1=mph";
SG_MUL_VAL_ 416 BR1_ASRMo_fa BR1_MSR_Anf 0-0;
SG_MUL_VAL_ 416 BR1_MSR_Mo_inv BR1_MSR_Anf 1-1;
SG_MUL_VAL_ 896 MO3_DKW MO3_Sta_FPG 0-0;
SG_MUL_VAL_ 896 MO3_FPGradient MO3_Sta_FPG 1-1;
SG_MUL_VAL_ 896 MO3_Sign_FPG MO3_Sta_FPG 1-1;
VAL_ 194 LW1_LRW_Sign 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen";
VAL_ 194 LW1_Gesch_Sign 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen";
VAL_ 194 LW1_ID 0 "noch_not_kalibriert" 128 "kalibriert_nur_bei_PQ35_46_VW32x_VW411";
@@ -1721,6 +1787,16 @@ SG_MUL_VAL_ 648 MO2_max_Mo MO2_Mp_Code 3-3;
SG_MUL_VAL_ 648 MO2_CAN_Vers MO2_Mp_Code 0-0;
SG_MUL_VAL_ 648 MO2_Motor_Code MO2_Mp_Code 1-1;
SG_MUL_VAL_ 1152 MO5_max_Moment MO5_Mp_Code 0-0;
SG_MUL_VAL_ 1152 MO5_Drehzahl MO5_Mp_Code 1-1;
SG_MUL_VAL_ 1152 MO5_Motortyp MO5_Mp_Code 2-2;
SG_MUL_VAL_ 1152 MO5_Abgastyp MO5_Mp_Code 3-3;
SG_MUL_VAL_ 1152 MO5_Abgastyp2 MO5_Mp_Code 3-3;
SG_MUL_VAL_ 1152 MO5_Abgastyp3 MO5_Mp_Code 3-3;
SG_MUL_VAL_ 1152 OBD_Kaltstart_Denominator MO5_Mp_Code 3-3;
SG_MUL_VAL_ 1152 OBD_Minimum_Trip MO5_Mp_Code 3-3;
SG_MUL_VAL_ 1152 MO5_DPF_reg MO5_Mp_Code 3-3;
VAL_ 648 MO2_Mp_Code 0 "CAN_Stand" 1 "Motor_Kod" 2 "Getriebe_Kod" 3 "MDI_Max";
VAL_ 648 MO2_Getr_Code 0 "_5HP19" 1 "_5HP24" 2 "AG4" 3 "VL300" 4 "VQ250" 5 "VQ35" 6 "AG4_yestco" 7 "AG5_yestco" 8 "autom_Kupplung" 9 "autom_Kupplung_mit_ASG" 10 "AG6_yestco_ZF_6HP_AISIN" 11 "DQ500_DQ250_DQ200" 12 "SQ100_SQ200" 14 "AL1000_AL551_AL951_ZF8HPx" 15 "Handschalter_konv" 16 "DL800" 17 "E_Fahrzeug__Single_Gear";
@@ -1779,8 +1855,68 @@ VAL_ 872 ACS_Fehler 1 "Fehlerspeichereintrag" 0 "kein_Fehlerspeichereintrag" ;
VAL_ 872 ACS_zul_Regelabw 254 "ADR_nicht_aktiv" 255 "Fehler" ;
VAL_ 872 ACS_max_AendGrad 254 "Neutralwert" 0 "Neutralwert" 255 "Fehler" ;
VAL_ 896 MO3_Vorgluehen 0 "no_Vorgluehen" 1 "Vorgluehen_active";
VAL_ 896 MO3_Prio_Dz 0 "Wunsch" 1 "Zwang";
VAL_ 896 MO_Schalter_StartStopp 0 "StartStopp_ueber_Hauptschalter_deactivated_LED_an" 1 "StartStopp_ueber_Hauptschalter_activated_LED_aus";
VAL_ 896 MO3_Winterprg 0 "not_active" 1 "active";
VAL_ 896 MO3_Sta_Pedal 0 "Fahrpedal_iO" 1 "Ersatzwert";
VAL_ 896 MO3_Sta_FPG 0 "Gradient_not_bed" 1 "Gradient_bed";
VAL_ 896 MO3_Sign_FPG 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen";
VAL_ 896 MO3_Sta_Temp 0 "Geber_iO" 1 "Ersatzwert";
VAL_ 896 MO3_Vorz_RadWu 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen";
VAL_ 896 MO3_Freigabe_Segeln 0 "Segelbetrieb_not_freigegeben" 1 "Segelbetrieb_freigegeben";
VAL_ 896 MO_StartStopp_StoppVorbereitung 0 "Motorstopp_not_in_Vorbereitung" 1 "Motorstopp_in_Vorbereitung";
CM_ BO_ 896 "Motor message 3 - Contains accelerator pedal, temperatures, and control signals";
VAL_ 978 LH2_Sta_HCA 0 "disabled" 1 "initializing" 2 "fault" 3 "ready" 4 "rejected" 5 "active" 7 "active";
VAL_ 1088 Waehlhebelposition__Getriebe_1_ 8 "P" 7 "R" 6 "N" 5 "D" 9 "U" 12 "S" 14 "T" 10 "T" 11 "T";
VAL_ 1088 GE1_Schaltung 0 "no_circuit" 1 "circuit_is_running";
VAL_ 1088 GE1_Sta_Schutz 0 "no_protection" 1 "protection_requested";
VAL_ 1088 GE1_Klimakompr 0 "no_Anforderung" 1 "Kompressor_aus";
VAL_ 1088 GE1_WK 0 "WK_open" 1 "WK_regulated" 2 "WK_closed" 3 "Failure";
VAL_ 1088 GE1_StSt_Info 0 "Engine_running_not_necessary_stop_release" 1 "Motor_start_not_mandatory_necessary_stop_prohibition" 2 "Motor_start_absolute_necessary_start_request" 3 "System_error";
VAL_ 1088 GE1_EGS_Anf 0 "no_requirement" 1 "EGS_requirement";
VAL_ 1088 GE1_Zielgang 0 "P (Park) | Disengaged" 1 "Gear 1 | Engaged" 2 "Gear 2 | Engaged" 3 "Gear 3 | Engaged" 4 "Gear 4 | Engaged" 5 "Gear 5 | Engaged" 6 "1m Gear" 7 "Gang_R" 8 "Gear 6 | Engaged" 9 "Gear 7 | Engaged" 10 "Gear 8 | Engaged" 14 "Speed Not Defined" 15 "Failure";
VAL_ 1088 GE1_Wahl_Pos 0 "Intermediate Position" 1 "Pos_1" 2 "Pos_2" 3 "Pos_3" 4 "Pos_4" 5 "D (Drive)" 6 "Pos_N" 7 "R (Reverse)" 8 "P (Park)" 9 "Tiptronic Override" 10 "Pos_Z1" 11 "Pos_Z2" 12 "S (Sport)" 13 "Pos_L" 14 "Gas Pedal Force Downshift" 15 "Failure";
VAL_ 1088 GE1_Notlauf 0 "No Emergency" 1 "No Switching" 2 "Switch to Neutral" 3 "50% Shifting Capacity" 4 "Driving Without UK" 5 "No Emeregency" 6 "No Emergency" 7 "No Emergency, Target Shifting Reached" 15 "Failure";
VAL_ 1088 GE1_Kuehlung 0 "No Additional Cooling Requested" 1 "20% Additional Fan Cooling Requested" 2 "40% Additional Fan Cooling Requested" 3 "Maximum Additional Fan Cooling Requested";
VAL_ 1088 GE1_Sta_OBD 0 "MIL Off" 1 "MIL On";
VAL_ 1088 GE1_LaunchControl 0 "Launch Control Not Active" 1 "Launch Control Program Active";
VAL_ 1088 GE1_Infobit 0 "Standard Automatic" 1 "CVT";
VAL_ 1088 GE1_SleepInd 0 "CAN is Required" 1 "Sleep Ready";
VAL_ 1088 GE1_Fehlereintr 0 "No Failure Memory Entry" 1 "Failure Memory Entry";
VAL_ 1152 MO5_Mp_Code 0 "Max_Moment" 1 "Drehzahl" 2 "Motor_Typ" 3 "Abgastyp_od_norm_Verbrauch";
VAL_ 1152 MO5_Abgastyp 0 "no_EOBD" 1 "EOBD";
VAL_ 1152 MO5_Abgastyp2 0 "no_OBD" 1 "OBD";
VAL_ 1152 MO5_Abgastyp3 0 "no_DPF_verbaut" 1 "DPF_verbaut";
VAL_ 1152 OBD_Kaltstart_Denominator 0 "Denominator_not_hochzaehlen" 1 "Bedingungen_zum_Inkr_des_Kaltstart_Denom_erf";
VAL_ 1152 OBD_Minimum_Trip 0 "no_Min_Normed_Trip" 1 "Min_Normed_Trip";
VAL_ 1152 MO5_DPF_reg 0 "DPF_regeneriert_nicht" 1 "DPF_regeneriert";
VAL_ 1152 MO5_Vorgluehen 0 "Lamp_off" 1 "Lamp_on";
VAL_ 1152 MO5_E_Gas 0 "Lamp_off" 1 "Lamp_on";
VAL_ 1152 MO5_OBD_2 0 "Lamp_off" 1 "Lamp_on";
VAL_ 1152 MO5_Heissl 0 "Lamp_off" 1 "Lamp_on";
VAL_ 1152 MO5_KlimaKompr 0 "no_Anforderung" 1 "Klimakompr_aus";
VAL_ 1152 MO5_Feld_kuehl 0 "no" 1 "yes";
VAL_ 1152 MO5_KliKo_Red 0 "no" 1 "yes";
VAL_ 1152 MO5_UeberlVerb 0 "no_Ueberlauf" 1 "mindestens_einmal_uebergelaufen";
VAL_ 1152 MO5_HLeuchte 0 "no_Warnung" 1 "Vorwarnung";
VAL_ 1152 MO5_PartikelLamp 0 "Lamp_off" 1 "Lamp_on";
VAL_ 1152 MO5_Sta_BKU 0 "iO_oder_not_verbaut" 1 "n_iO";
VAL_ 1152 MO5_TypStartSteu 0 "Startersteuerung_BSG_BCM_KessyD1_ZAS" 1 "Startersteuerung_durch_MSG";
VAL_ 1152 MO5_TDE_Lampe 0 "Lamp_off" 1 "Lamp_on";
VAL_ 1152 MO5_TDE_Text 0 "no_Text" 1 "Textanzeige_nach_ISO";
VAL_ 1152 MO5_DZM_Daempf 0 "normale_Daempfung" 1 "dynamische_Daempfung";
VAL_ 1152 MO5_Interlock 0 "Interlock_not_betaetigt" 1 "Interlock_betaetigt";
VAL_ 1152 MO5_Start 0 "Start_not_zulaessig" 1 "Startfreigabe";
VAL_ 1152 MO5_Anlasser 0 "Anlasser_darf_angesteuert_werden" 1 "Anlasser_ausspuren_Ansteuerung_not_moeglich";
VAL_ 1152 MO5_GRA_Hauptsch 0 "Off" 1 "On";
VAL_ 1152 MO5_Momente 0 "Einfach" 1 "Doppelt";
VAL_ 1152 MO5_Motortext1 0 "no_Text" 1 "Text_1";
VAL_ 1152 MO5_Motortext2 0 "no_Text" 1 "Text_2";
VAL_ 1152 MO5_Motortext3 0 "no_Text" 1 "Text_3";
VAL_ 1152 MO5_Motortext4 0 "no_Text" 1 "Text_4";
VAL_ 1386 ACA_StaACC 6 "ACC_rev_aus" 0 "Hauptschalter_aus" 4 "ACC_im_Hintergrund" 3 "ACC_aktiv" 1 "Reserve" 2 "ACC_passiv" 7 "ACC_irrev_aus" 5 "frei" ;
VAL_ 1386 ACA_ID_StaACC 0 "keine_Anzeige" ;
@@ -73,6 +73,7 @@ static void chrysler_rx_hook(const CANPacket_t *msg) {
// enter controls on rising edge of ACC, exit controls on ACC off
const unsigned int das_3_bus = (chrysler_platform == CHRYSLER_PACIFICA) ? 0U : 2U;
if ((msg->bus == das_3_bus) && (msg->addr == chrysler_addrs->DAS_3)) {
acc_main_on = GET_BIT(msg, 20U);
bool cruise_engaged = GET_BIT(msg, 21U);
pcm_cruise_check(cruise_engaged);
}
+1
View File
@@ -157,6 +157,7 @@ static void ford_rx_hook(const CANPacket_t *msg) {
// Signal: CcStat_D_Actl
unsigned int cruise_state = msg->data[1] & 0x07U;
bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U);
acc_main_on = (cruise_state == 3U) || cruise_engaged;
pcm_cruise_check(cruise_engaged);
}
}
+4
View File
@@ -89,6 +89,10 @@ static void gm_rx_hook(const CANPacket_t *msg) {
if (msg->addr == 0xBDU) {
regen_braking = (msg->data[0] >> 4) != 0U;
}
if (msg->addr == 0xC9U) {
acc_main_on = GET_BIT(msg, 29U);
}
}
}
@@ -32,6 +32,7 @@ static void mazda_rx_hook(const CANPacket_t *msg) {
// enter controls on rising edge of ACC, exit controls on ACC off
if (msg->addr == MAZDA_CRZ_CTRL) {
acc_main_on = GET_BIT(msg, 17U);
bool cruise_engaged = msg->data[0] & 0x8U;
pcm_cruise_check(cruise_engaged);
}
@@ -43,6 +43,14 @@ static void nissan_rx_hook(const CANPacket_t *msg) {
brake_pressed = ((msg->data[4] >> 5) & 1U) != 0U;
}
}
if ((msg->bus == 0U) && (msg->addr == 0x239U)) {
acc_main_on = GET_BIT(msg, 17U);
}
if ((msg->bus == (nissan_alt_eps ? 2U : 1U)) && (msg->addr == 0x1B6U)) {
acc_main_on = GET_BIT(msg, 36U);
}
}
// Handle cruise enabled
@@ -109,6 +109,7 @@ static void subaru_rx_hook(const CANPacket_t *msg) {
// enter controls on rising edge of ACC, exit controls on ACC off
if ((msg->addr == MSG_SUBARU_CruiseControl) && (msg->bus == alt_main_bus)) {
acc_main_on = GET_BIT(msg, 40U);
bool cruise_engaged = (msg->data[5] >> 1) & 1U;
pcm_cruise_check(cruise_engaged);
}
@@ -31,6 +31,7 @@ static void subaru_preglobal_rx_hook(const CANPacket_t *msg) {
// enter controls on rising edge of ACC, exit controls on ACC off
if (msg->addr == MSG_SUBARU_PG_CruiseControl) {
acc_main_on = GET_BIT(msg, 48U);
bool cruise_engaged = (msg->data[6] >> 1) & 1U;
pcm_cruise_check(cruise_engaged);
}
@@ -201,6 +201,14 @@ static void toyota_rx_hook(const CANPacket_t *msg) {
UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 * KPH_TO_MS);
}
if (msg->addr == 0x1D3U) {
acc_main_on = GET_BIT(msg, 15U);
}
if (msg->addr == 0x365U) {
acc_main_on = GET_BIT(msg, 0U);
}
}
}
@@ -78,7 +78,7 @@ static safety_config volkswagen_pq_init(uint16_t param) {
static void volkswagen_pq_rx_hook(const CANPacket_t *msg) {
if (msg->bus == 0U) {
// Update in-motion state from speed value.
// Signal: Bremse_1.Geschwindigkeit_neu__Bremse_1_
// Signal: Bremse_1.BR1_Rad_kmh
if (msg->addr == MSG_BREMSE_1) {
int speed = ((msg->data[2] & 0xFEU) >> 1) | (msg->data[3] << 7);
vehicle_moving = speed > 0;
@@ -99,7 +99,7 @@ static void volkswagen_pq_rx_hook(const CANPacket_t *msg) {
if (volkswagen_longitudinal) {
if (msg->addr == MSG_MOTOR_5) {
// ACC main switch on is a prerequisite to enter controls, exit controls immediately on main switch off
// Signal: Motor_5.GRA_Hauptschalter
// Signal: Motor_5.MO5_GRA_Hauptsch
acc_main_on = GET_BIT(msg, 50U);
if (!acc_main_on) {
controls_allowed = false;
@@ -126,19 +126,19 @@ static void volkswagen_pq_rx_hook(const CANPacket_t *msg) {
} else {
if (msg->addr == MSG_MOTOR_2) {
// Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages
// Signal: Motor_2.GRA_Status
// Signal: Motor_2.MO2_Sta_GRA
int acc_status = (msg->data[2] & 0xC0U) >> 6;
bool cruise_engaged = (acc_status == 1) || (acc_status == 2);
pcm_cruise_check(cruise_engaged);
}
}
// Signal: Motor_3.Fahrpedal_Rohsignal
// Signal: Motor_3.MO3_Pedalwert
if (msg->addr == MSG_MOTOR_3) {
gas_pressed = (msg->data[2]);
}
// Signal: Motor_2.Bremslichtschalter
// Signal: Motor_2.MO2_BLS
if (msg->addr == MSG_MOTOR_2) {
brake_pressed = (msg->data[2] & 0x1U);
}
@@ -75,12 +75,12 @@ class TestVolkswagenPqSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeri
# ACC main switch status
def _motor_5_msg(self, main_switch=False):
values = {"GRA_Hauptschalter": main_switch}
values = {"MO5_GRA_Hauptsch": main_switch}
return self.packer.make_can_msg_safety("Motor_5", 0, values)
# Driver throttle input (Motor_3)
def _user_gas_msg(self, gas):
values = {"Fahrpedal_Rohsignal": gas}
values = {"MO3_Pedalwert": gas}
return self.packer.make_can_msg_safety("Motor_3", 0, values)
# Cruise control buttons (GRA_Neu)
+2 -2
View File
@@ -177,7 +177,7 @@ quiet-level = 3
# if you've got a short variable name that's getting flagged, add it here
ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite"
builtin = "clear,rare,informal,code,names,en-GB_to_en-US"
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.po, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*"
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.po, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*, selfdrive/assets/offroad/mici_fcc.html"
[tool.mypy]
python_version = "3.11"
@@ -235,7 +235,7 @@ lint.ignore = [
"B027",
"B024",
"NPY002", # new numpy random syntax is worse
"UP038", # (x, y) -> x|y for isinstance
"UP045", "UP007", # these don't play nice with raylib atm
]
line-length = 160
target-version ="py311"
+1 -1
View File
@@ -12,7 +12,7 @@ from openpilot.common.basedir import BASEDIR
DIRS = ['cereal', 'openpilot']
EXTS = ['.png', '.py', '.ttf', '.capnp']
EXTS = ['.png', '.py', '.ttf', '.capnp', '.json', '.fnt', '.mo']
INTERPRETER = '/usr/bin/env python3'
+2
View File
@@ -1,2 +1,4 @@
*.cc
fonts/*.fnt
fonts/*.png
translations_assets.qrc
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env python3
from pathlib import Path
import json
import pyray as rl
FONT_DIR = Path(__file__).resolve().parent
SELFDRIVE_DIR = FONT_DIR.parents[1]
TRANSLATIONS_DIR = SELFDRIVE_DIR / "ui" / "translations"
LANGUAGES_FILE = TRANSLATIONS_DIR / "languages.json"
GLYPH_PADDING = 6
EXTRA_CHARS = "–‑✓×°§•X⚙✕◀▶✔⌫⇧␣○●↳çêüñ–‑✓×°§•€£¥"
UNIFONT_LANGUAGES = {"ar", "th", "zh-CHT", "zh-CHS", "ko", "ja"}
def _languages():
if not LANGUAGES_FILE.exists():
return {}
with LANGUAGES_FILE.open(encoding="utf-8") as f:
return json.load(f)
def _char_sets():
base = set(map(chr, range(32, 127))) | set(EXTRA_CHARS)
unifont = set(base)
for language, code in _languages().items():
unifont.update(language)
po_path = TRANSLATIONS_DIR / f"app_{code}.po"
try:
chars = set(po_path.read_text(encoding="utf-8"))
except FileNotFoundError:
continue
(unifont if code in UNIFONT_LANGUAGES else base).update(chars)
return tuple(sorted(ord(c) for c in base)), tuple(sorted(ord(c) for c in unifont))
def _glyph_metrics(glyphs, rects, codepoints):
entries = []
min_offset_y, max_extent = None, 0
for idx, codepoint in enumerate(codepoints):
glyph = glyphs[idx]
rect = rects[idx]
width = int(round(rect.width))
height = int(round(rect.height))
offset_y = int(round(glyph.offsetY))
min_offset_y = offset_y if min_offset_y is None else min(min_offset_y, offset_y)
max_extent = max(max_extent, offset_y + height)
entries.append({
"id": codepoint,
"x": int(round(rect.x)),
"y": int(round(rect.y)),
"width": width,
"height": height,
"xoffset": int(round(glyph.offsetX)),
"yoffset": offset_y,
"xadvance": int(round(glyph.advanceX)),
})
if min_offset_y is None:
raise RuntimeError("No glyphs were generated")
line_height = int(round(max_extent - min_offset_y))
base = int(round(max_extent))
return entries, line_height, base
def _write_bmfont(path: Path, font_size: int, face: str, atlas_name: str, line_height: int, base: int, atlas_size, entries):
# TODO: why doesn't raylib calculate these metrics correctly?
if line_height != font_size:
print("using font size for line height", atlas_name)
line_height = font_size
lines = [
f"info face=\"{face}\" size=-{font_size} bold=0 italic=0 charset=\"\" unicode=1 stretchH=100 smooth=0 aa=1 padding=0,0,0,0 spacing=0,0 outline=0",
f"common lineHeight={line_height} base={base} scaleW={atlas_size[0]} scaleH={atlas_size[1]} pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4",
f"page id=0 file=\"{atlas_name}\"",
f"chars count={len(entries)}",
]
for entry in entries:
lines.append(
("char id={id:<4} x={x:<5} y={y:<5} width={width:<5} height={height:<5} " +
"xoffset={xoffset:<5} yoffset={yoffset:<5} xadvance={xadvance:<5} page=0 chnl=15").format(**entry)
)
path.write_text("\n".join(lines) + "\n")
def _process_font(font_path: Path, codepoints: tuple[int, ...]):
print(f"Processing {font_path.name}...")
font_size = {
"unifont.otf": 16, # unifont is only 16x8 or 16x16 pixels per glyph
}.get(font_path.name, 200)
data = font_path.read_bytes()
file_buf = rl.ffi.new("unsigned char[]", data)
cp_buffer = rl.ffi.new("int[]", codepoints)
cp_ptr = rl.ffi.cast("int *", cp_buffer)
glyphs = rl.load_font_data(rl.ffi.cast("unsigned char *", file_buf), len(data), font_size, cp_ptr, len(codepoints), rl.FontType.FONT_DEFAULT)
if glyphs == rl.ffi.NULL:
raise RuntimeError("raylib failed to load font data")
rects_ptr = rl.ffi.new("Rectangle **")
image = rl.gen_image_font_atlas(glyphs, rects_ptr, len(codepoints), font_size, GLYPH_PADDING, 0)
if image.width == 0 or image.height == 0:
raise RuntimeError("raylib returned an empty atlas")
rects = rects_ptr[0]
atlas_name = f"{font_path.stem}.png"
atlas_path = FONT_DIR / atlas_name
entries, line_height, base = _glyph_metrics(glyphs, rects, codepoints)
if not rl.export_image(image, atlas_path.as_posix()):
raise RuntimeError("Failed to export atlas image")
_write_bmfont(FONT_DIR / f"{font_path.stem}.fnt", font_size, font_path.stem, atlas_name, line_height, base, (image.width, image.height), entries)
def main():
base_cp, unifont_cp = _char_sets()
fonts = sorted(FONT_DIR.glob("*.ttf")) + sorted(FONT_DIR.glob("*.otf"))
for font in fonts:
if "emoji" in font.name.lower():
continue
glyphs = unifont_cp if font.stem.lower().startswith("unifont") else base_cp
_process_font(font, glyphs)
return 0
if __name__ == "__main__":
raise SystemExit(main())
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Some files were not shown because too many files have changed in this diff Show More