mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-27 03:03:44 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 38893bdc71 | |||
| 71c1d79807 | |||
| 36d0c074f1 | |||
| 6dccb85b96 | |||
| d11ecaf457 | |||
| b302637e4d | |||
| e28f72c661 | |||
| 2db8d95905 | |||
| db5922db43 | |||
| 96f5819c6a | |||
| cfd221b89c | |||
| 013f8579d7 | |||
| 2b53b59bee | |||
| 33f6d69a32 | |||
| 58e919c264 | |||
| 17e5542b1b | |||
| e1458d4723 | |||
| 06f9e43e4e | |||
| f8e03a9fc5 | |||
| 7c6741a93e | |||
| 4b3372d006 | |||
| 9a9e7cd1e9 |
+4
-51
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
import importlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -129,41 +128,6 @@ elif arch == "aarch64" and AGNOS:
|
||||
arch = "larch64"
|
||||
assert arch in ["larch64", "aarch64", "x86_64", "Darwin"]
|
||||
|
||||
# AGNOS 19.6 ships native dependencies as versioned Python packages. Link
|
||||
# Cap'n Proto statically from that managed package so release binaries don't
|
||||
# depend on the removed libcapnp-1.0.2.so system library.
|
||||
try:
|
||||
capnproto = importlib.import_module("capnproto")
|
||||
except ModuleNotFoundError:
|
||||
capnproto = None
|
||||
try:
|
||||
ffmpeg = importlib.import_module("ffmpeg")
|
||||
except ModuleNotFoundError:
|
||||
ffmpeg = None
|
||||
|
||||
capnproto_include_dirs = [capnproto.INCLUDE_DIR] if capnproto is not None else []
|
||||
capnproto_lib_dirs = [capnproto.LIB_DIR] if capnproto is not None else []
|
||||
ffmpeg_include_dirs = [ffmpeg.INCLUDE_DIR] if ffmpeg is not None else []
|
||||
ffmpeg_lib_dirs = [ffmpeg.LIB_DIR] if ffmpeg is not None else []
|
||||
|
||||
# Cross-builds install managed dependencies in /work/.venv-linux-arm64, but
|
||||
# comma devices expose the same packages from /usr/local/venv. Never embed the
|
||||
# host/container mount path in release binaries.
|
||||
ffmpeg_runtime_lib_dirs = ffmpeg_lib_dirs
|
||||
if arch == "larch64" and ffmpeg is not None:
|
||||
ffmpeg_runtime_lib_dirs = [os.path.join("/usr/local/venv", os.path.relpath(ffmpeg.LIB_DIR, sys.prefix))]
|
||||
|
||||
# The managed native-dependency packages keep their tools inside the package
|
||||
# instead of installing them into /usr/local/venv/bin. cereal invokes capnpc
|
||||
# directly while SConscript files are evaluated, so make the packaged tools
|
||||
# discoverable to both SCons actions and configure-time subprocesses.
|
||||
dependency_bin_dirs = [
|
||||
package.BIN_DIR for package in (capnproto, ffmpeg)
|
||||
if package is not None and os.path.isdir(package.BIN_DIR)
|
||||
]
|
||||
if dependency_bin_dirs:
|
||||
os.environ["PATH"] = os.pathsep.join([*dependency_bin_dirs, os.environ["PATH"]])
|
||||
|
||||
# Homebrew llvm can shadow Apple clang and break macOS SDK header resolution.
|
||||
# Use the system toolchain explicitly on macOS for reliable local builds.
|
||||
cc = '/usr/bin/clang' if arch == "Darwin" else 'clang'
|
||||
@@ -305,10 +269,7 @@ env = Environment(
|
||||
"-Wno-vla-cxx-extension",
|
||||
] + cflags + ccflags,
|
||||
|
||||
# Managed dependencies must precede the compatibility sysroot. The sysroot
|
||||
# can intentionally retain legacy libraries for C3 support, but new release
|
||||
# binaries must link against the versions shipped in the managed venv.
|
||||
CPPPATH=capnproto_include_dirs + ffmpeg_include_dirs + cpppath + [
|
||||
CPPPATH=cpppath + [
|
||||
"#",
|
||||
"#third_party/acados/include",
|
||||
"#third_party/acados/include/blasfeo/include",
|
||||
@@ -327,11 +288,11 @@ env = Environment(
|
||||
RANLIB=ranlib,
|
||||
LINKFLAGS=ldflags,
|
||||
|
||||
RPATH=ffmpeg_runtime_lib_dirs + rpath,
|
||||
RPATH=rpath,
|
||||
|
||||
CFLAGS=["-std=gnu11"] + cflags,
|
||||
CXXFLAGS=["-std=c++1z"] + cxxflags,
|
||||
LIBPATH=capnproto_lib_dirs + ffmpeg_lib_dirs + libpath + [
|
||||
LIBPATH=libpath + [
|
||||
"#msgq_repo",
|
||||
"#third_party",
|
||||
"#selfdrive/pandad",
|
||||
@@ -410,15 +371,7 @@ SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog})
|
||||
SConscript(['cereal/SConscript'])
|
||||
|
||||
Import('socketmaster', 'msgq')
|
||||
if capnproto is not None:
|
||||
messaging = [
|
||||
socketmaster,
|
||||
msgq,
|
||||
File(os.path.join(capnproto.LIB_DIR, "libcapnp.a")),
|
||||
File(os.path.join(capnproto.LIB_DIR, "libkj.a")),
|
||||
]
|
||||
else:
|
||||
messaging = [socketmaster, msgq, 'capnp', 'kj']
|
||||
messaging = [socketmaster, msgq, 'capnp', 'kj',]
|
||||
Export('messaging')
|
||||
|
||||
|
||||
|
||||
@@ -265,6 +265,7 @@ struct StarPilotSelfdriveState @0xf416ec09499d9d19 {
|
||||
alertSize @3 :AlertSize;
|
||||
alertType @4 :Text;
|
||||
alertSound @5 :Car.CarControl.HUDControl.AudibleAlert;
|
||||
vEgo @6 :Float32;
|
||||
|
||||
enum AlertStatus {
|
||||
normal @0;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -66,7 +66,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"HondaLateralPidKiScale", {PERSISTENT, FLOAT, "1.0", "1.0", 3}},
|
||||
{"HondaLateralPidKpScale", {PERSISTENT, FLOAT, "1.0", "1.0", 3}},
|
||||
{"HondaWindFactorParams", {PERSISTENT, FLOAT}},
|
||||
{"HomeScreenName", {PERSISTENT, STRING, "StarPilot", "StarPilot", 3}},
|
||||
{"InstallDate", {PERSISTENT, TIME}},
|
||||
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||
{"IsEngaged", {PERSISTENT, BOOL}},
|
||||
@@ -346,6 +345,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"FordCurvatureBlendHigh", {PERSISTENT, FLOAT, "0.4", "0.4", 2}},
|
||||
{"FordCurvatureBlendLow", {PERSISTENT, FLOAT, "0.4", "0.4", 2}},
|
||||
{"FordCurvatureLaneChangeFactor", {PERSISTENT, FLOAT, "0.85", "0.85", 2}},
|
||||
{"FordHandsFreeCluster", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"FordHumanTurnDetection", {PERSISTENT, BOOL, "1", "1", 2}},
|
||||
{"FordLateralMode", {PERSISTENT, INT, "1", "1", 2}},
|
||||
{"FLMActiveOverrides", {PERSISTENT, JSON, "{}", "{}", 2}},
|
||||
@@ -517,6 +517,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"PIPPreviewMask", {PERSISTENT, JSON, "{\"width\":1928,\"height\":1208,\"center_left\":[315,548],\"center_right\":[1571,539],\"crop_size\":580}", "{\"width\":1928,\"height\":1208,\"center_left\":[315,548],\"center_right\":[1571,539],\"crop_size\":580}", 2}},
|
||||
{"PIPPreviewShowOnBlinker", {PERSISTENT, BOOL, "0", "0", 1}},
|
||||
{"PIPPreviewShowOnBSM", {PERSISTENT, BOOL, "0", "0", 1}},
|
||||
{"PIPPreviewInvert", {PERSISTENT, BOOL, "0", "0", 1}},
|
||||
{"GalaxyPaired", {PERSISTENT, BOOL, "0", "0", 0}},
|
||||
{"GalaxyUploadPending", {PERSISTENT, BOOL, "0", "0", 0}},
|
||||
{"PreferredSchedule", {PERSISTENT, INT, "2", "0", 0}},
|
||||
@@ -680,6 +681,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"TuningLevel", {PERSISTENT, INT, "0", "0", 0}},
|
||||
{"TuningLevelConfirmed", {PERSISTENT, BOOL, "0", "0", 0}},
|
||||
{"TurnDesires", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"TurnSteeringLimitMuteSpeed", {PERSISTENT, INT, "0", "0", 0}},
|
||||
{"UnlockDoors", {PERSISTENT, BOOL, "1", "0", 0}},
|
||||
{"Updated", {PERSISTENT, STRING, "0", "0"}},
|
||||
{"UpdateSpeedLimits", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+3
-94
@@ -147,101 +147,10 @@ function launch {
|
||||
while true; do sleep 1; done
|
||||
fi
|
||||
|
||||
function prebuilt_runtime_compatible {
|
||||
python3 - <<'PY'
|
||||
import importlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
|
||||
from openpilot.common.file_chunker import get_existing_chunks
|
||||
|
||||
start = time.monotonic()
|
||||
last = start
|
||||
log_path = os.environ.get("SP_BOOT_TIMING_LOG")
|
||||
|
||||
def emit(line):
|
||||
print(line, flush=True)
|
||||
if log_path:
|
||||
try:
|
||||
with open(log_path, "a") as f:
|
||||
f.write(line + "\n")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def log_step(label):
|
||||
global last
|
||||
now = time.monotonic()
|
||||
emit(f"SP_BOOT_TIMING prebuilt_compat {label} +{now - last:.3f}s total={now - start:.3f}s")
|
||||
last = now
|
||||
|
||||
mods = [
|
||||
"openpilot.common.params_pyx",
|
||||
"msgq.ipc_pyx",
|
||||
"msgq.visionipc.visionipc_pyx",
|
||||
"openpilot.common.transformations.transformations",
|
||||
"openpilot.selfdrive.pandad.pandad_api_impl",
|
||||
"openpilot.selfdrive.controls.lib.lateral_mpc_lib.c_generated_code.acados_ocp_solver_pyx",
|
||||
"openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.c_generated_code.acados_ocp_solver_pyx",
|
||||
]
|
||||
|
||||
for mod in mods:
|
||||
try:
|
||||
importlib.import_module(mod)
|
||||
except Exception as e:
|
||||
print(f"Prebuilt compatibility failure in {mod}: {e}", file=sys.stderr)
|
||||
raise
|
||||
log_step(f"import:{mod}")
|
||||
|
||||
repo_root = Path.cwd().parents[1]
|
||||
required_model_artifacts = [
|
||||
repo_root / "selfdrive/modeld/models/driving_tinygrad.pkl",
|
||||
repo_root / "selfdrive/modeld/models/dmonitoring_model_metadata.pkl",
|
||||
repo_root / "selfdrive/modeld/models/dmonitoring_model_tinygrad.pkl",
|
||||
repo_root / "selfdrive/modeld/models/dm_warp_1928x1208_tinygrad.pkl",
|
||||
repo_root / "selfdrive/modeld/models/dm_warp_1344x760_tinygrad.pkl",
|
||||
]
|
||||
required_files = [
|
||||
repo_root / "selfdrive/pandad/pandad_api_impl.so",
|
||||
repo_root / "selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so",
|
||||
repo_root / "selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/libacados_ocp_solver_lat.so",
|
||||
repo_root / "selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so",
|
||||
repo_root / "selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/libacados_ocp_solver_long.so",
|
||||
repo_root / "opendbc_repo/opendbc/dbc/gm_global_a_powertrain_generated.dbc",
|
||||
]
|
||||
|
||||
for path in required_model_artifacts:
|
||||
try:
|
||||
artifact_paths = [Path(p) for p in get_existing_chunks(path)]
|
||||
except Exception as e:
|
||||
raise FileNotFoundError(f"Missing prebuilt runtime artifact: {path}") from e
|
||||
missing_chunks = [p for p in artifact_paths if not p.is_file()]
|
||||
if missing_chunks:
|
||||
missing = ", ".join(str(p) for p in missing_chunks)
|
||||
raise FileNotFoundError(f"Missing prebuilt runtime artifact chunks for {path}: {missing}")
|
||||
log_step("required_model_artifacts")
|
||||
|
||||
for path in required_files:
|
||||
if not path.is_file():
|
||||
raise FileNotFoundError(f"Missing prebuilt runtime artifact: {path}")
|
||||
log_step("required_files")
|
||||
PY
|
||||
}
|
||||
|
||||
USE_PREBUILT=1
|
||||
if [ -f /data/params/d/UsePrebuilt ]; then
|
||||
USE_PREBUILT=$(tr -d '\n' < /data/params/d/UsePrebuilt)
|
||||
fi
|
||||
|
||||
sp_launch_timing "prebuilt_decision_done"
|
||||
if [ "$USE_PREBUILT" = "1" ] && [ -f $DIR/prebuilt ] && ! prebuilt_runtime_compatible; then
|
||||
echo "Prebuilt runtime artifacts are incompatible on this device; rebuilding locally."
|
||||
USE_PREBUILT=0
|
||||
fi
|
||||
sp_launch_timing "prebuilt_compat_done"
|
||||
|
||||
if [ "$USE_PREBUILT" != "1" ] || [ ! -f $DIR/prebuilt ]; then
|
||||
# Published trees carry this marker and must never compile on-device.
|
||||
# Developers can remove it explicitly when working from a source tree.
|
||||
if [ ! -f "$DIR/prebuilt" ]; then
|
||||
sp_launch_timing "build_start"
|
||||
./build.py
|
||||
sp_launch_timing "build_done"
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ fi
|
||||
export QCOM_PRIORITY=12
|
||||
|
||||
if [ -z "$AGNOS_VERSION" ]; then
|
||||
export AGNOS_VERSION="19.6.10"
|
||||
export AGNOS_VERSION="19.6.2"
|
||||
fi
|
||||
|
||||
if [ -z "$AGNOS_ACCEPTED_VERSIONS" ]; then
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -255,9 +255,15 @@ class CarController(CarControllerBase):
|
||||
|
||||
if (self.frame % CarControllerParams.ACC_UI_STEP) == 0 or send_ui:
|
||||
show_distance_bars = self.frame - self.distance_bar_frame < 400
|
||||
hands_free_cluster = bool(
|
||||
self.ford_lateral is not None
|
||||
and self.ford_lateral.mode != FordLateralMode.native
|
||||
and self.ford_lateral.mode == self.ford_lateral_announced_mode
|
||||
and self.ford_lateral.hands_free_cluster_enabled)
|
||||
can_sends.append(fordcan.create_acc_ui_msg(self.packer, self.CAN, self.CP, main_on, CC.latActive,
|
||||
fcw_alert, CS.out.cruiseState.standstill, show_distance_bars,
|
||||
hud_control, CS.acc_tja_status_stock_values))
|
||||
hud_control, CS.acc_tja_status_stock_values,
|
||||
hands_free_cluster))
|
||||
|
||||
self.main_on_last = main_on
|
||||
self.lkas_enabled_last = CC.latActive
|
||||
|
||||
@@ -181,7 +181,7 @@ def create_acc_msg(packer, CAN: CanBus, long_active: bool, gas: float, accel: fl
|
||||
|
||||
|
||||
def create_acc_ui_msg(packer, CAN: CanBus, CP, main_on: bool, enabled: bool, fcw_alert: bool, standstill: bool,
|
||||
show_distance_bars: bool, hud_control, stock_values: dict):
|
||||
show_distance_bars: bool, hud_control, stock_values: dict, hands_free_cluster: bool = False):
|
||||
"""
|
||||
Creates a CAN message for the Ford IPC adaptive cruise, forward collision warning and traffic jam
|
||||
assist status.
|
||||
@@ -197,6 +197,8 @@ def create_acc_ui_msg(packer, CAN: CanBus, CP, main_on: bool, enabled: bool, fcw
|
||||
status = 3 # ActiveInterventionLeft
|
||||
elif hud_control.rightLaneDepart:
|
||||
status = 4 # ActiveInterventionRight
|
||||
elif hands_free_cluster:
|
||||
status = 7 # Hands-free assistance display
|
||||
else:
|
||||
status = 2 # Active
|
||||
elif main_on:
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import random
|
||||
from collections.abc import Iterable
|
||||
from types import SimpleNamespace
|
||||
|
||||
from hypothesis import settings, given, strategies as st
|
||||
from parameterized import parameterized
|
||||
|
||||
from opendbc.car import gen_empty_fingerprint
|
||||
from opendbc.can import CANPacker
|
||||
from opendbc.car.ford import fordcan
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.fw_versions import build_fw_dict
|
||||
from opendbc.car.ford.interface import CarInterface
|
||||
@@ -172,3 +175,29 @@ def test_mach_e_longitudinal_toggle_controls_stock_acc_selection():
|
||||
assert enhanced.alphaLongitudinalAvailable
|
||||
assert enhanced.openpilotLongitudinalControl
|
||||
assert enhanced.safetyConfigs[-1].safetyParam & FordSafetyFlags.LONG_CONTROL
|
||||
|
||||
|
||||
def test_hands_free_cluster_status_is_opt_in():
|
||||
packer = CANPacker("ford_lincoln_base_pt")
|
||||
CAN = SimpleNamespace(main=0)
|
||||
CP = SimpleNamespace(openpilotLongitudinalControl=False)
|
||||
hud = SimpleNamespace(leftLaneDepart=False, rightLaneDepart=False)
|
||||
stock_values = dict.fromkeys([
|
||||
"HaDsply_No_Cs", "HaDsply_No_Cnt", "AccStopStat_D_Dsply", "AccTrgDist2_D_Dsply",
|
||||
"AccStopRes_B_Dsply", "TjaWarn_D_Rq", "TjaMsgTxt_D_Dsply", "IaccLamp_D_Rq",
|
||||
"AccMsgTxt_D2_Rq", "FcwDeny_B_Dsply", "FcwMemStat_B_Actl", "AccTGap_B_Dsply",
|
||||
"CadsAlignIncplt_B_Actl", "AccFllwMde_B_Dsply", "CadsRadrBlck_B_Actl",
|
||||
"CmbbPostEvnt_B_Dsply", "AccStopMde_B_Dsply", "FcwMemSens_D_Actl",
|
||||
"FcwMsgTxt_D_Rq", "AccWarn_D_Dsply", "FcwVisblWarn_B_Rq", "FcwAudioWarn_B_Rq",
|
||||
"AccTGap_D_Dsply", "AccMemEnbl_B_RqDrv", "FdaMem_B_Stat",
|
||||
], 0)
|
||||
|
||||
regular = fordcan.create_acc_ui_msg(
|
||||
packer, CAN, CP, True, True, False, False, False, hud, stock_values)
|
||||
hands_free = fordcan.create_acc_ui_msg(
|
||||
packer, CAN, CP, True, True, False, False, False, hud, stock_values, True)
|
||||
expected_regular = packer.make_can_msg("ACCDATA_3", 0, {"Tja_D_Stat": 2})
|
||||
expected_hands_free = packer.make_can_msg("ACCDATA_3", 0, {"Tja_D_Stat": 7})
|
||||
|
||||
assert regular == expected_regular
|
||||
assert hands_free == expected_hands_free
|
||||
|
||||
@@ -988,6 +988,45 @@ class TestHyundaiFingerprint:
|
||||
assert long_xceed.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.HYBRID_GAS
|
||||
assert long_xceed.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG
|
||||
|
||||
def test_g80_alpha_long_preserves_legacy_safety(self):
|
||||
toggles = get_test_toggles()
|
||||
|
||||
stock_g80 = CarInterface.get_params(CAR.GENESIS_G80, gen_empty_fingerprint(), [], False, False, False, toggles)
|
||||
assert CAR.GENESIS_G80 in LEGACY_LONGITUDINAL_CAR
|
||||
assert stock_g80.alphaLongitudinalAvailable
|
||||
assert not stock_g80.openpilotLongitudinalControl
|
||||
assert stock_g80.pcmCruise
|
||||
assert stock_g80.safetyConfigs[-1].safetyModel == CarParams.SafetyModel.hyundaiLegacy
|
||||
assert not (stock_g80.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG)
|
||||
|
||||
long_g80 = CarInterface.get_params(CAR.GENESIS_G80, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
assert long_g80.alphaLongitudinalAvailable
|
||||
assert long_g80.openpilotLongitudinalControl
|
||||
assert not long_g80.pcmCruise
|
||||
assert long_g80.safetyConfigs[-1].safetyModel == CarParams.SafetyModel.hyundaiLegacy
|
||||
assert long_g80.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG
|
||||
|
||||
@pytest.mark.parametrize("ecu_disabled", (True, False))
|
||||
def test_g80_alpha_long_disables_stock_scc(self, monkeypatch, ecu_disabled):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.GENESIS_G80, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
|
||||
called = {}
|
||||
|
||||
def fake_disable_ecu(*args, **kwargs):
|
||||
called.update(kwargs)
|
||||
return ecu_disabled
|
||||
|
||||
monkeypatch.setattr("opendbc.car.hyundai.interface.disable_ecu", fake_disable_ecu)
|
||||
CarInterface.init(CP, None, None)
|
||||
|
||||
assert called["addr"] == 0x7d0
|
||||
assert called["bus"] == 0
|
||||
assert called["reset"] is False
|
||||
assert CP.openpilotLongitudinalControl == ecu_disabled
|
||||
assert CP.pcmCruise != ecu_disabled
|
||||
assert bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG) == ecu_disabled
|
||||
|
||||
def test_xceed_phev_disable_failure_falls_back_to_stock_acc(self, monkeypatch):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.KIA_XCEED_PHEV, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
|
||||
@@ -1213,6 +1213,9 @@ NON_SCC_CAR = CAR.with_flags(HyundaiFlags.NON_SCC)
|
||||
# HyundaiFlags.CANFD_RADAR_SCC | HyundaiFlags.CANFD_NO_RADAR_DISABLE | )
|
||||
UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.LEGACY) | CAR.with_flags(HyundaiFlags.UNSUPPORTED_LONGITUDINAL)
|
||||
|
||||
LEGACY_LONGITUDINAL_CAR = {CAR.KIA_XCEED_PHEV}
|
||||
LEGACY_LONGITUDINAL_CAR = {
|
||||
CAR.GENESIS_G80,
|
||||
CAR.KIA_XCEED_PHEV,
|
||||
}
|
||||
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
@@ -15,6 +15,7 @@ LEAF_ADAS_ECU_BUS = 0
|
||||
LEAF_ADAS_COMMAND_BUS = 1
|
||||
LEAF_ADAS_COMMAND_ADDRS = frozenset((0x1C3, 0x2B0))
|
||||
LEAF_2025_SV_PLUS_CAMERA_FW = b'6WK2CDB\x04\x18\x00\x00\x00\x00\x00R=1\x18\x99\x10\x00\x00\x00\x80'
|
||||
LEAF_2025_SV_PLUS_ALPHA_LONG_ENABLED = False
|
||||
|
||||
LEAF_KWP_EXTENDED_REQUEST = b"\x10\xC0"
|
||||
LEAF_KWP_EXTENDED_RESPONSE = b"\x50\xC0"
|
||||
@@ -26,7 +27,7 @@ LEAF_KWP_TAKEOVER_SESSIONS = (
|
||||
|
||||
|
||||
def is_leaf_2025_sv_plus_longitudinal(candidate, car_fw):
|
||||
return candidate == CAR.NISSAN_LEAF and any(
|
||||
return LEAF_2025_SV_PLUS_ALPHA_LONG_ENABLED and candidate == CAR.NISSAN_LEAF and any(
|
||||
fw.address == LEAF_ADAS_ECU_ADDR and bytes(fw.fwVersion) == LEAF_2025_SV_PLUS_CAMERA_FW
|
||||
for fw in car_fw
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import pytest
|
||||
|
||||
from opendbc.car import Bus, ButtonType, gen_empty_fingerprint, structs
|
||||
from opendbc.car.can_definitions import CanData
|
||||
from opendbc.car.nissan import interface as nissan_interface
|
||||
from opendbc.car.nissan.carstate import CarState
|
||||
from opendbc.car.nissan.interface import CarInterface, LEAF_2025_SV_PLUS_CAMERA_FW, leaf_adas_commands_present, \
|
||||
leaf_adas_commands_silent, restore_leaf_adas_tx
|
||||
@@ -18,6 +19,12 @@ SUPPORTED_LEAF_FW = [structs.CarParams.CarFw(
|
||||
)]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def experimental_leaf_long(monkeypatch):
|
||||
"""Exercise the dormant implementation without making it available in production."""
|
||||
monkeypatch.setattr(nissan_interface, "LEAF_2025_SV_PLUS_ALPHA_LONG_ENABLED", True)
|
||||
|
||||
|
||||
def run_controller(alpha_long, accel=0.0, long_active=True, long_state=structs.CarControl.Actuators.LongControlState.pid):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, alpha_long, False, False, TEST_TOGGLES)
|
||||
FPCP = CarInterface.get_starpilot_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, CP, TEST_TOGGLES)
|
||||
@@ -33,7 +40,28 @@ def run_controller(alpha_long, accel=0.0, long_active=True, long_state=structs.C
|
||||
return {msg[0]: msg for msg in can_sends}
|
||||
|
||||
|
||||
def test_leaf_2025_sv_plus_alpha_long_params():
|
||||
def test_leaf_2025_sv_plus_alpha_long_is_disabled(monkeypatch):
|
||||
stock = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, False, False, False, None)
|
||||
alpha_long = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
|
||||
assert not stock.alphaLongitudinalAvailable
|
||||
assert not stock.openpilotLongitudinalControl
|
||||
assert stock.pcmCruise
|
||||
assert not (stock.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL)
|
||||
|
||||
assert not alpha_long.alphaLongitudinalAvailable
|
||||
assert not alpha_long.openpilotLongitudinalControl
|
||||
assert alpha_long.pcmCruise
|
||||
assert not alpha_long.autoResumeSng
|
||||
assert not (alpha_long.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL)
|
||||
|
||||
disable_calls = []
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: disable_calls.append((args, kwargs)))
|
||||
CarInterface.init(alpha_long, None, None)
|
||||
assert not disable_calls
|
||||
|
||||
|
||||
def test_dormant_leaf_2025_sv_plus_alpha_long_params(experimental_leaf_long):
|
||||
stock = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, False, False, False, None)
|
||||
alpha_long = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
|
||||
@@ -79,7 +107,13 @@ def test_stock_controller_does_not_send_longitudinal_messages():
|
||||
assert not ({0x2B0, 0x1C3, 0x707} & can_sends.keys())
|
||||
|
||||
|
||||
def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive():
|
||||
def test_disabled_alpha_long_controller_does_not_send_longitudinal_messages():
|
||||
can_sends = run_controller(True)
|
||||
|
||||
assert not ({0x2B0, 0x1C3, 0x707} & can_sends.keys())
|
||||
|
||||
|
||||
def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive(experimental_leaf_long):
|
||||
can_sends = run_controller(True)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "ff6090ac5b000e03"
|
||||
@@ -89,13 +123,13 @@ def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive():
|
||||
assert can_sends[0x707][2] == 0
|
||||
|
||||
|
||||
def test_alpha_long_controller_clamps_to_panda_accel_limit():
|
||||
def test_alpha_long_controller_clamps_to_panda_accel_limit(experimental_leaf_long):
|
||||
can_sends = run_controller(True, accel=5.0)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "007f8fac5b000e0c"
|
||||
|
||||
|
||||
def test_alpha_long_controller_blends_friction_brake_below_regen_limit():
|
||||
def test_alpha_long_controller_blends_friction_brake_below_regen_limit(experimental_leaf_long):
|
||||
can_sends = run_controller(True, accel=-2.0)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "a827d5ac5b000e09"
|
||||
@@ -104,7 +138,7 @@ def test_alpha_long_controller_blends_friction_brake_below_regen_limit():
|
||||
assert brake[5] & 0x84 == 0x84
|
||||
|
||||
|
||||
def test_alpha_long_controller_sends_inactive_commands_when_disengaged():
|
||||
def test_alpha_long_controller_sends_inactive_commands_when_disengaged(experimental_leaf_long):
|
||||
can_sends = run_controller(True, accel=1.0, long_active=False)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "dc53a2ac1b000e03"
|
||||
@@ -113,7 +147,7 @@ def test_alpha_long_controller_sends_inactive_commands_when_disengaged():
|
||||
|
||||
@pytest.mark.parametrize(("signal", "button_type"), [("SET_BUTTON", ButtonType.decelCruise),
|
||||
("RES_BUTTON", ButtonType.accelCruise)])
|
||||
def test_leaf_set_resume_release_enables_alpha_long(signal, button_type):
|
||||
def test_leaf_set_resume_release_enables_alpha_long(signal, button_type, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, TEST_TOGGLES)
|
||||
FPCP = CarInterface.get_starpilot_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, CP, TEST_TOGGLES)
|
||||
CS = CarState(CP, FPCP)
|
||||
@@ -130,7 +164,7 @@ def test_leaf_set_resume_release_enables_alpha_long(signal, button_type):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ecu_disabled", [False, True])
|
||||
def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
|
||||
def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
calls = []
|
||||
|
||||
@@ -158,7 +192,7 @@ def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
|
||||
assert bool(CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL) is ecu_disabled
|
||||
|
||||
|
||||
def test_leaf_kwp_no_response_disable_can_confirm_ecu_silence(monkeypatch):
|
||||
def test_leaf_kwp_no_response_disable_can_confirm_ecu_silence(monkeypatch, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: True)
|
||||
@@ -171,7 +205,7 @@ def test_leaf_kwp_no_response_disable_can_confirm_ecu_silence(monkeypatch):
|
||||
assert CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL
|
||||
|
||||
|
||||
def test_leaf_positive_disable_response_without_command_silence_falls_back(monkeypatch):
|
||||
def test_leaf_positive_disable_response_without_command_silence_falls_back(monkeypatch, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
restore_calls = []
|
||||
|
||||
|
||||
@@ -165,13 +165,18 @@ class TestCarInterfaces:
|
||||
"Center_Stack_2": {"LKAS_Button": 1},
|
||||
}, is_ram=True)
|
||||
|
||||
def test_chrysler_wd_mod_enables_steer_to_zero(self):
|
||||
@pytest.mark.parametrize("candidate", (
|
||||
CHRYSLER_CAR.CHRYSLER_PACIFICA_2020,
|
||||
CHRYSLER_CAR.JEEP_GRAND_CHEROKEE,
|
||||
CHRYSLER_CAR.JEEP_GRAND_CHEROKEE_2019,
|
||||
))
|
||||
def test_chrysler_steer_to_zero_module(self, candidate):
|
||||
fingerprint = {bus: {} for bus in range(8)}
|
||||
fingerprint[0][0x4FF] = 8
|
||||
toggles = get_test_starpilot_toggles()
|
||||
|
||||
car_params = ChryslerCarInterface.get_params(
|
||||
CHRYSLER_CAR.CHRYSLER_PACIFICA_2020,
|
||||
candidate,
|
||||
fingerprint,
|
||||
[],
|
||||
alpha_long=False,
|
||||
@@ -182,7 +187,7 @@ class TestCarInterfaces:
|
||||
assert car_params.minSteerSpeed > 0.
|
||||
|
||||
fp_car_params = ChryslerCarInterface.get_starpilot_params(
|
||||
CHRYSLER_CAR.CHRYSLER_PACIFICA_2020,
|
||||
candidate,
|
||||
fingerprint,
|
||||
[],
|
||||
car_params,
|
||||
@@ -206,11 +211,14 @@ class TestCarInterfaces:
|
||||
button_message="CRUISE_BUTTONS",
|
||||
auto_high_beam=0,
|
||||
)
|
||||
controller.update(CC, CS, 0, toggles)
|
||||
controller.update(CC, CS, 0, toggles)
|
||||
_, can_sends = controller.update(CC, CS, 0, toggles)
|
||||
|
||||
lkas_parser = CANParser(CHRYSLER_DBC[car_params.carFingerprint][Bus.pt], [("LKAS_COMMAND", 50)], 0)
|
||||
lkas_parser.update([0, can_sends])
|
||||
assert lkas_parser.vl["LKAS_COMMAND"]["LKAS_CONTROL_BIT"] == 1
|
||||
assert lkas_parser.vl["LKAS_COMMAND"]["STEERING_TORQUE"] != 0
|
||||
|
||||
@pytest.mark.parametrize("candidate", (CHRYSLER_CAR.JEEP_GRAND_CHEROKEE, CHRYSLER_CAR.JEEP_GRAND_CHEROKEE_2019))
|
||||
def test_jeep_brake_hold_safety_capability_is_provisioned(self, candidate):
|
||||
|
||||
@@ -1103,6 +1103,7 @@ class SafetyTest(SafetyTestBase):
|
||||
'TestHyundaiSafetyFCEVLong', 'TestHyundaiLongitudinalAolLkasOnEngageSafety',
|
||||
'TestHyundaiSafetyCanRefreshLong', 'TestHyundaiSafetyCanRefreshLongCameraSCC',
|
||||
'TestHyundaiCanCanfdBlendedLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafetyHEV'}):
|
||||
continue
|
||||
volkswagen_shared = ('TestVolkswagenMqb', 'TestVolkswagenMlb', 'TestVolkswagenMeb')
|
||||
@@ -1156,6 +1157,7 @@ class SafetyTest(SafetyTestBase):
|
||||
if attr.startswith('TestHyundaiLongitudinal') or attr in ('TestHyundaiSafetyFCEVLong',
|
||||
'TestHyundaiLongitudinalAolLkasOnEngageSafety',
|
||||
'TestHyundaiCanCanfdBlendedLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafetyHEV'):
|
||||
# exceptions for common msgs across different Hyundai CAN platforms
|
||||
tx = list(filter(lambda m: m[0] not in [0x420, 0x50A, 0x389, 0x4A2], tx))
|
||||
|
||||
@@ -597,6 +597,14 @@ class TestHyundaiSafetyFCEVLong(TestHyundaiLongitudinalSafety, TestHyundaiSafety
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHyundaiLegacyLongitudinalSafety(TestHyundaiLongitudinalSafety, TestHyundaiLegacySafety):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.LONG)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHyundaiLegacyLongitudinalSafetyHEV(TestHyundaiLongitudinalSafety, TestHyundaiLegacySafetyHEV):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
extern const uint8_t gitversion[19];
|
||||
const uint8_t gitversion[19] = "DEV-590fcdd9-DEBUG";
|
||||
const uint8_t gitversion[19] = "DEV-e28f72c6-DEBUG";
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
DEV-590fcdd9-DEBUG
|
||||
DEV-e28f72c6-DEBUG
|
||||
@@ -29,11 +29,6 @@ dependencies = [
|
||||
"setuptools",
|
||||
"numpy >=2.0",
|
||||
|
||||
# AGNOS 19.6 native build dependencies
|
||||
"comma-deps-capnproto; python_version >= '3.12'",
|
||||
"comma-deps-ffmpeg; python_version >= '3.12'",
|
||||
"libdatachannel-py>=2026.1.0.dev2; python_version >= '3.12'",
|
||||
|
||||
# body / webrtcd
|
||||
"aiohttp",
|
||||
"aiortc",
|
||||
|
||||
Binary file not shown.
@@ -467,66 +467,6 @@ EOF
|
||||
echo "==> larch64 scons completed in $(( $(date +%s) - started_at ))s"
|
||||
}
|
||||
|
||||
validate_larch64_artifacts() {
|
||||
local engine
|
||||
engine="$(detect_engine)"
|
||||
|
||||
echo "==> Validating larch64 runtime dependencies"
|
||||
"${engine}" run --rm --platform linux/arm64 \
|
||||
--user "${DOCKER_RUN_USER}" \
|
||||
-v "${HOST_ROOT_DIR}:/work" \
|
||||
-v "${HOST_VENV_DIR}:/work/.venv-linux-arm64:ro" \
|
||||
-v "${HOST_SYSROOT_DIR}:/opt/tici-sysroot:ro" \
|
||||
-v "${HOST_SYSROOT_DIR}/system/vendor/lib64:/system/vendor/lib64:ro" \
|
||||
-w /work \
|
||||
"${IMAGE_NAME}" bash -lc '
|
||||
set -euo pipefail
|
||||
ffmpeg_lib_dir="/work/.venv-linux-arm64/lib/python3.12/site-packages/ffmpeg/install/lib"
|
||||
target_ffmpeg_runpath="/usr/local/venv/lib/python3.12/site-packages/ffmpeg/install/lib"
|
||||
runtime_library_path="${ffmpeg_lib_dir}:/work/third_party/acados/larch64/lib:/work/third_party/libyuv/larch64/lib:/work/selfdrive/controls/lib/lateral_mpc_lib/c_generated_code:/work/selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code:/opt/tici-sysroot/usr/local/lib:/opt/tici-sysroot/lib/aarch64-linux-gnu:/opt/tici-sysroot/usr/lib/aarch64-linux-gnu:/system/vendor/lib64"
|
||||
failures=0
|
||||
|
||||
while IFS= read -r -d "" artifact; do
|
||||
if ! readelf -h "${artifact}" 2>/dev/null | grep -q "Machine:.*AArch64"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
dynamic="$(readelf -d "${artifact}" 2>/dev/null || true)"
|
||||
if grep -Eq "(RPATH|RUNPATH).*\/work\/" <<<"${dynamic}"; then
|
||||
echo "ERROR: ${artifact} embeds a build-host runtime path" >&2
|
||||
failures=1
|
||||
fi
|
||||
|
||||
has_ffmpeg=0
|
||||
while IFS= read -r needed; do
|
||||
case "${needed}" in
|
||||
libavformat.so.*|libavcodec.so.*|libswresample.so.*|libavutil.so.*)
|
||||
has_ffmpeg=1
|
||||
if [[ ! -e "${ffmpeg_lib_dir}/${needed}" ]]; then
|
||||
echo "ERROR: ${artifact} links ${needed}, which is not shipped by the managed FFmpeg package" >&2
|
||||
failures=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < <(sed -n "s/.*Shared library: \[\([^]]*\)\].*/\1/p" <<<"${dynamic}")
|
||||
|
||||
if [[ "${has_ffmpeg}" -eq 1 ]] && ! grep -Fq "${target_ffmpeg_runpath}" <<<"${dynamic}"; then
|
||||
echo "ERROR: ${artifact} links FFmpeg without the target managed-venv RUNPATH" >&2
|
||||
failures=1
|
||||
fi
|
||||
|
||||
missing="$(LD_LIBRARY_PATH="${runtime_library_path}" ldd "${artifact}" 2>&1 | grep "not found" || true)"
|
||||
if [[ -n "${missing}" ]]; then
|
||||
echo "ERROR: ${artifact} has unresolved target dependencies:" >&2
|
||||
echo "${missing}" >&2
|
||||
failures=1
|
||||
fi
|
||||
done < <(git ls-files -z)
|
||||
|
||||
exit "${failures}"
|
||||
'
|
||||
}
|
||||
|
||||
setup_host_venv() {
|
||||
if [[ ! -f "${ROOT_DIR}/.venv/bin/activate" ]]; then
|
||||
if [[ -x "${ROOT_DIR}/tools/install_python_dependencies.sh" ]]; then
|
||||
@@ -576,7 +516,6 @@ run_larch64_build() {
|
||||
cereal/messaging/bridge \
|
||||
msgq_repo/msgq/ipc_pyx.so \
|
||||
msgq_repo/msgq/visionipc/visionipc_pyx.so
|
||||
validate_larch64_artifacts
|
||||
touch "${ROOT_DIR}/prebuilt"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,99 +1,17 @@
|
||||
info face="como-heavy" size=-200 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=0 aa=1 padding=0,0,0,0 spacing=0,0 outline=0
|
||||
common lineHeight=200 base=200 scaleW=2048 scaleH=2048 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||
common lineHeight=200 base=200 scaleW=1024 scaleH=512 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||
page id=0 file="como-heavy.png"
|
||||
chars count=95
|
||||
chars count=13
|
||||
char id=32 x=6 y=6 width=39 height=200 xoffset=0 yoffset=0 xadvance=39 page=0 chnl=15
|
||||
char id=33 x=57 y=6 width=32 height=114 xoffset=8 yoffset=48 xadvance=48 page=0 chnl=15
|
||||
char id=34 x=101 y=6 width=68 height=64 xoffset=6 yoffset=48 xadvance=80 page=0 chnl=15
|
||||
char id=35 x=181 y=6 width=101 height=111 xoffset=3 yoffset=51 xadvance=107 page=0 chnl=15
|
||||
char id=36 x=294 y=6 width=90 height=136 xoffset=8 yoffset=40 xadvance=107 page=0 chnl=15
|
||||
char id=37 x=396 y=6 width=115 height=113 xoffset=3 yoffset=50 xadvance=121 page=0 chnl=15
|
||||
char id=38 x=523 y=6 width=109 height=116 xoffset=3 yoffset=47 xadvance=113 page=0 chnl=15
|
||||
char id=39 x=644 y=6 width=30 height=64 xoffset=6 yoffset=48 xadvance=42 page=0 chnl=15
|
||||
char id=40 x=686 y=6 width=53 height=131 xoffset=8 yoffset=48 xadvance=67 page=0 chnl=15
|
||||
char id=41 x=751 y=6 width=53 height=131 xoffset=6 yoffset=48 xadvance=67 page=0 chnl=15
|
||||
char id=42 x=816 y=6 width=82 height=79 xoffset=4 yoffset=43 xadvance=90 page=0 chnl=15
|
||||
char id=43 x=910 y=6 width=97 height=98 xoffset=5 yoffset=63 xadvance=107 page=0 chnl=15
|
||||
char id=44 x=1019 y=6 width=42 height=60 xoffset=-3 yoffset=129 xadvance=48 page=0 chnl=15
|
||||
char id=45 x=1073 y=6 width=61 height=29 xoffset=5 yoffset=102 xadvance=71 page=0 chnl=15
|
||||
char id=46 x=1146 y=6 width=33 height=33 xoffset=8 yoffset=129 xadvance=48 page=0 chnl=15
|
||||
char id=47 x=1191 y=6 width=57 height=114 xoffset=1 yoffset=48 xadvance=59 page=0 chnl=15
|
||||
char id=48 x=1260 y=6 width=95 height=113 xoffset=6 yoffset=50 xadvance=107 page=0 chnl=15
|
||||
char id=49 x=1367 y=6 width=63 height=110 xoffset=20 yoffset=52 xadvance=107 page=0 chnl=15
|
||||
char id=50 x=1442 y=6 width=87 height=111 xoffset=11 yoffset=50 xadvance=107 page=0 chnl=15
|
||||
char id=51 x=1541 y=6 width=87 height=113 xoffset=11 yoffset=50 xadvance=107 page=0 chnl=15
|
||||
char id=52 x=1640 y=6 width=99 height=111 xoffset=5 yoffset=51 xadvance=107 page=0 chnl=15
|
||||
char id=53 x=1751 y=6 width=88 height=111 xoffset=10 yoffset=52 xadvance=107 page=0 chnl=15
|
||||
char id=54 x=1851 y=6 width=91 height=113 xoffset=8 yoffset=50 xadvance=107 page=0 chnl=15
|
||||
char id=55 x=6 y=218 width=92 height=110 xoffset=9 yoffset=52 xadvance=107 page=0 chnl=15
|
||||
char id=56 x=110 y=218 width=94 height=113 xoffset=7 yoffset=50 xadvance=107 page=0 chnl=15
|
||||
char id=57 x=216 y=218 width=90 height=113 xoffset=9 yoffset=50 xadvance=107 page=0 chnl=15
|
||||
char id=58 x=318 y=218 width=33 height=83 xoffset=8 yoffset=79 xadvance=48 page=0 chnl=15
|
||||
char id=59 x=363 y=218 width=44 height=110 xoffset=-3 yoffset=79 xadvance=48 page=0 chnl=15
|
||||
char id=60 x=419 y=218 width=95 height=90 xoffset=6 yoffset=67 xadvance=107 page=0 chnl=15
|
||||
char id=61 x=526 y=218 width=95 height=66 xoffset=6 yoffset=79 xadvance=107 page=0 chnl=15
|
||||
char id=62 x=633 y=218 width=94 height=90 xoffset=7 yoffset=67 xadvance=107 page=0 chnl=15
|
||||
char id=63 x=739 y=218 width=81 height=115 xoffset=0 yoffset=47 xadvance=83 page=0 chnl=15
|
||||
char id=64 x=832 y=218 width=115 height=117 xoffset=5 yoffset=55 xadvance=124 page=0 chnl=15
|
||||
char id=65 x=959 y=218 width=107 height=115 xoffset=7 yoffset=47 xadvance=120 page=0 chnl=15
|
||||
char id=66 x=1078 y=218 width=103 height=112 xoffset=8 yoffset=49 xadvance=114 page=0 chnl=15
|
||||
char id=67 x=1193 y=218 width=110 height=116 xoffset=5 yoffset=47 xadvance=116 page=0 chnl=15
|
||||
char id=68 x=1315 y=218 width=108 height=112 xoffset=8 yoffset=49 xadvance=121 page=0 chnl=15
|
||||
char id=69 x=1435 y=218 width=99 height=112 xoffset=8 yoffset=49 xadvance=109 page=0 chnl=15
|
||||
char id=70 x=1546 y=218 width=97 height=113 xoffset=8 yoffset=49 xadvance=105 page=0 chnl=15
|
||||
char id=71 x=1655 y=218 width=114 height=116 xoffset=5 yoffset=47 xadvance=123 page=0 chnl=15
|
||||
char id=72 x=1781 y=218 width=108 height=114 xoffset=8 yoffset=48 xadvance=124 page=0 chnl=15
|
||||
char id=73 x=1901 y=218 width=32 height=114 xoffset=8 yoffset=48 xadvance=48 page=0 chnl=15
|
||||
char id=74 x=6 y=430 width=95 height=115 xoffset=1 yoffset=48 xadvance=102 page=0 chnl=15
|
||||
char id=75 x=113 y=430 width=101 height=114 xoffset=8 yoffset=48 xadvance=112 page=0 chnl=15
|
||||
char id=76 x=226 y=430 width=96 height=113 xoffset=8 yoffset=48 xadvance=103 page=0 chnl=15
|
||||
char id=77 x=334 y=430 width=129 height=114 xoffset=8 yoffset=48 xadvance=145 page=0 chnl=15
|
||||
char id=78 x=475 y=430 width=107 height=114 xoffset=8 yoffset=48 xadvance=123 page=0 chnl=15
|
||||
char id=79 x=594 y=430 width=119 height=116 xoffset=5 yoffset=47 xadvance=128 page=0 chnl=15
|
||||
char id=80 x=725 y=430 width=100 height=113 xoffset=8 yoffset=49 xadvance=110 page=0 chnl=15
|
||||
char id=81 x=837 y=430 width=119 height=129 xoffset=5 yoffset=47 xadvance=128 page=0 chnl=15
|
||||
char id=82 x=968 y=430 width=100 height=113 xoffset=8 yoffset=49 xadvance=112 page=0 chnl=15
|
||||
char id=83 x=1080 y=430 width=101 height=116 xoffset=4 yoffset=47 xadvance=108 page=0 chnl=15
|
||||
char id=84 x=1193 y=430 width=111 height=113 xoffset=0 yoffset=49 xadvance=110 page=0 chnl=15
|
||||
char id=85 x=1316 y=430 width=101 height=116 xoffset=7 yoffset=48 xadvance=114 page=0 chnl=15
|
||||
char id=86 x=1429 y=430 width=115 height=114 xoffset=0 yoffset=48 xadvance=115 page=0 chnl=15
|
||||
char id=87 x=1556 y=430 width=162 height=114 xoffset=1 yoffset=48 xadvance=164 page=0 chnl=15
|
||||
char id=88 x=1730 y=430 width=106 height=114 xoffset=3 yoffset=48 xadvance=112 page=0 chnl=15
|
||||
char id=89 x=1848 y=430 width=111 height=114 xoffset=0 yoffset=48 xadvance=110 page=0 chnl=15
|
||||
char id=90 x=6 y=642 width=102 height=112 xoffset=3 yoffset=49 xadvance=108 page=0 chnl=15
|
||||
char id=91 x=120 y=642 width=51 height=129 xoffset=10 yoffset=49 xadvance=67 page=0 chnl=15
|
||||
char id=92 x=183 y=642 width=57 height=114 xoffset=1 yoffset=48 xadvance=59 page=0 chnl=15
|
||||
char id=93 x=252 y=642 width=52 height=129 xoffset=6 yoffset=49 xadvance=67 page=0 chnl=15
|
||||
char id=94 x=316 y=642 width=97 height=75 xoffset=5 yoffset=48 xadvance=107 page=0 chnl=15
|
||||
char id=95 x=425 y=642 width=84 height=14 xoffset=0 yoffset=168 xadvance=83 page=0 chnl=15
|
||||
char id=96 x=521 y=642 width=40 height=36 xoffset=16 yoffset=36 xadvance=83 page=0 chnl=15
|
||||
char id=97 x=573 y=642 width=88 height=85 xoffset=5 yoffset=78 xadvance=100 page=0 chnl=15
|
||||
char id=98 x=673 y=642 width=88 height=120 xoffset=7 yoffset=43 xadvance=100 page=0 chnl=15
|
||||
char id=99 x=773 y=642 width=80 height=85 xoffset=5 yoffset=78 xadvance=87 page=0 chnl=15
|
||||
char id=100 x=865 y=642 width=88 height=120 xoffset=5 yoffset=43 xadvance=100 page=0 chnl=15
|
||||
char id=101 x=965 y=642 width=85 height=85 xoffset=5 yoffset=78 xadvance=93 page=0 chnl=15
|
||||
char id=102 x=1062 y=642 width=64 height=120 xoffset=7 yoffset=42 xadvance=69 page=0 chnl=15
|
||||
char id=103 x=1138 y=642 width=88 height=116 xoffset=5 yoffset=78 xadvance=100 page=0 chnl=15
|
||||
char id=104 x=1238 y=642 width=83 height=119 xoffset=7 yoffset=43 xadvance=96 page=0 chnl=15
|
||||
char id=105 x=1333 y=642 width=31 height=121 xoffset=6 yoffset=41 xadvance=43 page=0 chnl=15
|
||||
char id=106 x=1376 y=642 width=46 height=152 xoffset=-9 yoffset=41 xadvance=43 page=0 chnl=15
|
||||
char id=107 x=1434 y=642 width=79 height=119 xoffset=7 yoffset=43 xadvance=88 page=0 chnl=15
|
||||
char id=108 x=1525 y=642 width=29 height=119 xoffset=7 yoffset=43 xadvance=43 page=0 chnl=15
|
||||
char id=109 x=1566 y=642 width=126 height=84 xoffset=7 yoffset=78 xadvance=138 page=0 chnl=15
|
||||
char id=110 x=1704 y=642 width=83 height=84 xoffset=7 yoffset=78 xadvance=96 page=0 chnl=15
|
||||
char id=111 x=1799 y=642 width=88 height=85 xoffset=5 yoffset=78 xadvance=98 page=0 chnl=15
|
||||
char id=112 x=1899 y=642 width=88 height=115 xoffset=7 yoffset=78 xadvance=100 page=0 chnl=15
|
||||
char id=113 x=6 y=854 width=88 height=115 xoffset=5 yoffset=78 xadvance=100 page=0 chnl=15
|
||||
char id=114 x=106 y=854 width=63 height=83 xoffset=7 yoffset=79 xadvance=69 page=0 chnl=15
|
||||
char id=115 x=181 y=854 width=77 height=85 xoffset=4 yoffset=78 xadvance=84 page=0 chnl=15
|
||||
char id=116 x=270 y=854 width=63 height=111 xoffset=6 yoffset=52 xadvance=70 page=0 chnl=15
|
||||
char id=117 x=345 y=854 width=83 height=84 xoffset=6 yoffset=79 xadvance=96 page=0 chnl=15
|
||||
char id=118 x=440 y=854 width=86 height=83 xoffset=0 yoffset=79 xadvance=86 page=0 chnl=15
|
||||
char id=119 x=538 y=854 width=129 height=83 xoffset=0 yoffset=79 xadvance=128 page=0 chnl=15
|
||||
char id=120 x=679 y=854 width=81 height=83 xoffset=3 yoffset=79 xadvance=87 page=0 chnl=15
|
||||
char id=121 x=772 y=854 width=83 height=115 xoffset=6 yoffset=79 xadvance=96 page=0 chnl=15
|
||||
char id=122 x=867 y=854 width=79 height=81 xoffset=3 yoffset=80 xadvance=85 page=0 chnl=15
|
||||
char id=123 x=958 y=854 width=62 height=129 xoffset=2 yoffset=49 xadvance=70 page=0 chnl=15
|
||||
char id=124 x=1032 y=854 width=22 height=150 xoffset=16 yoffset=43 xadvance=53 page=0 chnl=15
|
||||
char id=125 x=1066 y=854 width=62 height=129 xoffset=6 yoffset=49 xadvance=70 page=0 chnl=15
|
||||
char id=126 x=1140 y=854 width=97 height=38 xoffset=5 yoffset=92 xadvance=107 page=0 chnl=15
|
||||
char id=63 x=57 y=6 width=81 height=115 xoffset=0 yoffset=47 xadvance=83 page=0 chnl=15
|
||||
char id=80 x=150 y=6 width=100 height=113 xoffset=8 yoffset=49 xadvance=110 page=0 chnl=15
|
||||
char id=83 x=262 y=6 width=101 height=116 xoffset=4 yoffset=47 xadvance=108 page=0 chnl=15
|
||||
char id=97 x=375 y=6 width=88 height=85 xoffset=5 yoffset=78 xadvance=100 page=0 chnl=15
|
||||
char id=105 x=475 y=6 width=31 height=121 xoffset=6 yoffset=41 xadvance=43 page=0 chnl=15
|
||||
char id=108 x=518 y=6 width=29 height=119 xoffset=7 yoffset=43 xadvance=43 page=0 chnl=15
|
||||
char id=111 x=559 y=6 width=88 height=85 xoffset=5 yoffset=78 xadvance=98 page=0 chnl=15
|
||||
char id=112 x=659 y=6 width=88 height=115 xoffset=7 yoffset=78 xadvance=100 page=0 chnl=15
|
||||
char id=114 x=759 y=6 width=63 height=83 xoffset=7 yoffset=79 xadvance=69 page=0 chnl=15
|
||||
char id=115 x=834 y=6 width=77 height=85 xoffset=4 yoffset=78 xadvance=84 page=0 chnl=15
|
||||
char id=116 x=923 y=6 width=63 height=111 xoffset=6 yoffset=52 xadvance=70 page=0 chnl=15
|
||||
char id=122 x=6 y=218 width=79 height=81 xoffset=3 yoffset=80 xadvance=85 page=0 chnl=15
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 24 KiB |
@@ -12,7 +12,7 @@ LANGUAGES_FILE = TRANSLATIONS_DIR / "languages.json"
|
||||
GLYPH_PADDING = 6
|
||||
EXTRA_CHARS = "–‑✓×°§•X⚙✕◀▶✔⌫⇧␣○●↳çêüñ–‑✓×°§•€£¥²⚠ⓘ"
|
||||
UNIFONT_LANGUAGES = {"ar", "th", "zh-CHT", "zh-CHS", "ko", "ja"}
|
||||
BRAND_FONT_CHARS = "".join(chr(codepoint) for codepoint in range(32, 127))
|
||||
BRAND_FONT_CHARS = " StarPilotstarpilot?z"
|
||||
|
||||
|
||||
def _languages():
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user