feat: Squash all core features into min

This commit is contained in:
Rick Lan
2025-08-21 12:30:31 +08:00
parent 3a9999ce05
commit 028b6e5664
57 changed files with 651 additions and 54 deletions
+3
View File
@@ -4,5 +4,8 @@
"ms-vscode.cpptools",
"elagil.pre-commit-helper",
"charliermarsh.ruff",
"JamiTech.simply-blame",
"k--kato.intellij-idea-keybindings",
"trinm1709.dracula-theme-from-intellij"
]
}
+16 -1
View File
@@ -3,10 +3,25 @@
"editor.insertSpaces": true,
"editor.renderWhitespace": "trailing",
"files.trimTrailingWhitespace": true,
"terminal.integrated.defaultProfile.linux": "dragonpilot",
"terminal.integrated.profiles.linux": {
"dragonpilot": {
"path": "bash",
"args": ["-c", "distrobox enter dp"]
}
},
"search.exclude": {
"**/.git": true,
"**/.venv": true,
"**/__pycache__": true
"**/__pycache__": true,
"msgq_repo/": true,
"opendbc/": true,
"rednose/": true,
"rednose_repo/": true,
"openpilot/": true,
"teleoprtc_repo/": true,
"tinygrad/": true,
"tinygrad_repo/": true
},
"files.exclude": {
"**/.git": true,
+30
View File
@@ -0,0 +1,30 @@
Copyright (c) 2019, Rick Lan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, and/or sublicense,
for non-commercial purposes only, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
- Commercial use (e.g. use in a product, service, or activity intended to
generate revenue) is prohibited without explicit written permission from
the copyright holder.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
Copyright (c) 2018, Comma.ai, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+3 -1
View File
@@ -28,7 +28,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"CurrentBootlog", {PERSISTENT, STRING}},
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"DisableLogging", {PERSISTENT, BOOL, "0"}},
{"DisablePowerDown", {PERSISTENT, BOOL}},
{"DisableUpdates", {PERSISTENT, BOOL}},
{"DisengageOnAccelerator", {PERSISTENT, BOOL, "0"}},
@@ -129,4 +129,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
{"Version", {PERSISTENT, STRING}},
{"dp_device_last_log", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"dp_device_reset_conf", {CLEAR_ON_MANAGER_START, BOOL}},
};
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="256"
height="256"
viewBox="0 0 64 64"
fill="none"
version="1.1"
id="svg2"
sodipodi:docname="icon_empty.svg"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.0820312"
inkscape:cx="128"
inkscape:cy="114.37262"
inkscape:window-width="2560"
inkscape:window-height="1021"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File
+1 -1
View File
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.notCar = True
ret.brand = "body"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.body)]
+2 -2
View File
@@ -149,7 +149,7 @@ def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_mu
def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, alpha_long_allowed: bool,
is_release: bool, num_pandas: int = 1, cached_params: CarParamsT | None = None):
is_release: bool, num_pandas: int = 1, dp_params: int = 0, cached_params: CarParamsT | None = None):
candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params)
if candidate is None:
@@ -157,7 +157,7 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip
candidate = "MOCK"
CarInterface = interfaces[candidate]
CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, docs=False)
CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, dp_params, docs=False)
CP.carVin = vin
CP.carFw = car_fw
CP.fingerprintSource = source
@@ -13,7 +13,7 @@ class CarInterface(CarInterfaceBase):
RadarInterface = RadarInterface
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "chrysler"
ret.dashcamOnly = candidate in RAM_HD
+1 -1
View File
@@ -32,7 +32,7 @@ def get_params_for_docs(platform) -> CarParams:
cp_platform = platform if platform in interfaces else MOCK.MOCK
CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(),
car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)],
alpha_long=True, is_release=False, docs=True)
alpha_long=True, is_release=False, dp_params=0, docs=True)
return CP
+1 -1
View File
@@ -26,7 +26,7 @@ class CarInterface(CarInterfaceBase):
return CarControllerParams.ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS)
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "ford"
ret.radarUnavailable = Bus.radar not in DBC[candidate]
+1 -1
View File
@@ -82,7 +82,7 @@ class CarInterface(CarInterfaceBase):
return self.torque_from_lateral_accel_linear
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "gm"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.gm)]
ret.autoResumeSng = False
+1 -1
View File
@@ -31,7 +31,7 @@ class CarInterface(CarInterfaceBase):
return CarControllerParams.NIDEC_ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS)
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "honda"
CAN = CanBus(ret, fingerprint)
@@ -23,7 +23,7 @@ class CarInterface(CarInterfaceBase):
RadarInterface = RadarInterface
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "hyundai"
# "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera.
@@ -51,7 +51,7 @@ class TestHyundaiFingerprint:
if lka_steering:
cam_can = CanBus(None, fingerprint).CAM
fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False)
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, 0, False)
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering
# radar available
@@ -59,14 +59,14 @@ class TestHyundaiFingerprint:
fingerprint = gen_empty_fingerprint()
if radar:
fingerprint[1][RADAR_START_ADDR] = 8
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False)
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, 0, False)
assert CP.radarUnavailable != radar
def test_alternate_limits(self):
# Alternate lateral control limits, for high torque cars, verify Panda safety mode flag is set
fingerprint = gen_empty_fingerprint()
for car_model in CAR:
CP = CarInterface.get_params(car_model, fingerprint, [], False, False, False)
CP = CarInterface.get_params(car_model, fingerprint, [], False, False, 0, False)
assert bool(CP.flags & HyundaiFlags.ALT_LIMITS) == bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.ALT_LIMITS)
def test_can_features(self):
+4 -4
View File
@@ -130,11 +130,11 @@ class CarInterfaceBase(ABC):
"""
Parameters essential to controlling the car may be incomplete or wrong without FW versions or fingerprints.
"""
return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False, False)
return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False, 0, False)
@classmethod
def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[structs.CarParams.CarFw],
alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams:
alpha_long: bool, is_release: bool, dp_params: int, docs: bool) -> structs.CarParams:
ret = CarInterfaceBase.get_std_params(candidate)
platform = PLATFORMS[candidate]
@@ -147,7 +147,7 @@ class CarInterfaceBase(ABC):
ret.tireStiffnessFactor = platform.config.specs.tireStiffnessFactor
ret.flags |= int(platform.config.flags)
ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, is_release, docs)
ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs)
# Vehicle mass is published curb weight plus assumed payload such as a human driver; notCars have no assumed payload
if not ret.notCar:
@@ -162,7 +162,7 @@ class CarInterfaceBase(ABC):
@staticmethod
@abstractmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint: dict[int, dict[int, int]],
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams:
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release: bool, dp_params: int, docs: bool) -> structs.CarParams:
raise NotImplementedError
@staticmethod
+1 -1
View File
@@ -12,7 +12,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "mazda"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.mazda)]
ret.radarUnavailable = True
+1 -1
View File
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "mock"
ret.mass = 1700.
ret.wheelbase = 2.70
+1 -1
View File
@@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "nissan"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.nissan)]
ret.autoResumeSng = False
+1 -1
View File
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = 'psa'
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.psa)]
+1 -1
View File
@@ -12,7 +12,7 @@ class CarInterface(CarInterfaceBase):
RadarInterface = RadarInterface
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "rivian"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.rivian)]
+3
View File
@@ -18,3 +18,6 @@ CarStateT = capnp.lib.capnp._StructModule
RadarDataT = capnp.lib.capnp._StructModule
CarControlT = capnp.lib.capnp._StructModule
CarParamsT = capnp.lib.capnp._StructModule
class DPFlags:
pass
+1 -1
View File
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "subaru"
ret.radarUnavailable = True
# for HYBRID CARS to be upstreamed, we need:
+1 -1
View File
@@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "tesla"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.tesla)]
@@ -64,7 +64,7 @@ class TestCarInterfaces:
args = get_fuzzy_car_interface_args(data.draw)
car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'],
alpha_long=args['alpha_long'], is_release=False, docs=False)
alpha_long=args['alpha_long'], is_release=False, dp_params=0, docs=False)
car_interface = CarInterface(car_params)
assert car_params
assert car_interface
+1 -1
View File
@@ -21,7 +21,7 @@ class CarInterface(CarInterfaceBase):
return CarControllerParams(CP).ACCEL_MIN, CarControllerParams(CP).ACCEL_MAX
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "toyota"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.toyota)]
ret.safetyConfigs[0].safetyParam = EPS_SCALE[candidate]
@@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase):
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "volkswagen"
ret.radarUnavailable = True
+3 -1
View File
@@ -82,6 +82,8 @@ class Car:
is_release = self.params.get_bool("IsReleaseBranch")
dp_params = 0
if CI is None:
# wait for one pandaState and one CAN packet
print("Waiting for CAN messages...")
@@ -99,7 +101,7 @@ class Car:
with car.CarParams.from_bytes(cached_params_raw) as _cached_params:
cached_params = _cached_params
self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, cached_params)
self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, dp_params, cached_params)
self.RI = interfaces[self.CI.CP.carFingerprint].RadarInterface(self.CI.CP)
self.CP = self.CI.CP
+1 -1
View File
@@ -12,7 +12,7 @@ V_CRUISE_MIN = 8
V_CRUISE_MAX = 145
V_CRUISE_UNSET = 255
V_CRUISE_INITIAL = 40
V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 105
V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 50
IMPERIAL_INCREMENT = round(CV.MPH_TO_KPH, 1) # round here to avoid rounding errors incrementing set speed
ButtonEvent = car.CarState.ButtonEvent
+1 -1
View File
@@ -39,7 +39,7 @@ class TestCarInterfaces:
args = get_fuzzy_car_interface_args(data.draw)
car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'],
alpha_long=args['alpha_long'], is_release=False, docs=False)
alpha_long=args['alpha_long'], is_release=False, dp_params=0, docs=False)
car_params = car_params.as_reader()
car_interface = CarInterface(car_params)
assert car_params
+1 -1
View File
@@ -149,7 +149,7 @@ class TestCarModelBase(unittest.TestCase):
cls.openpilot_enabled = cls.car_safety_mode_frame is not None
cls.CarInterface = interfaces[cls.platform]
cls.CP = cls.CarInterface.get_params(cls.platform, cls.fingerprint, car_fw, alpha_long, False, docs=False)
cls.CP = cls.CarInterface.get_params(cls.platform, cls.fingerprint, car_fw, alpha_long, False, dp_params=0, docs=False)
assert cls.CP
assert cls.CP.carFingerprint == cls.platform
@@ -26,6 +26,8 @@ MIN_ALLOW_THROTTLE_SPEED = 2.5
_A_TOTAL_MAX_V = [1.7, 3.2]
_A_TOTAL_MAX_BP = [20., 40.]
class DPFlags:
pass
def get_max_accel(v_ego):
return np.interp(v_ego, A_CRUISE_MAX_BP, A_CRUISE_MAX_VALS)
@@ -89,7 +91,7 @@ class LongitudinalPlanner:
throttle_prob = 1.0
return x, v, a, j, throttle_prob
def update(self, sm):
def update(self, sm, dp_flags = 0):
mode = 'blended' if sm['selfdriveState'].experimentalMode else 'acc'
if len(sm['carControl'].orientationNED) == 3:
+4 -2
View File
@@ -4,7 +4,7 @@ from openpilot.common.params import Params
from openpilot.common.realtime import Priority, config_realtime_process
from openpilot.common.swaglog import cloudlog
from openpilot.selfdrive.controls.lib.ldw import LaneDepartureWarning
from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner
from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner, DPFlags
import cereal.messaging as messaging
@@ -22,10 +22,12 @@ def main():
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState'],
poll='modelV2')
dp_flags = 0
while True:
sm.update()
if sm.updated['modelV2']:
longitudinal_planner.update(sm)
longitudinal_planner.update(sm, dp_flags)
longitudinal_planner.publish(sm, pm)
ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl'])
+1 -1
View File
@@ -130,7 +130,7 @@ class SelfdriveD:
self.ignored_processes = {'loggerd', }
# Determine startup event
self.startup_event = EventName.startup if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster
self.startup_event = EventName.startup #if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster
if not car_recognized:
self.startup_event = EventName.startupNoCar
elif car_recognized and self.CP.passive:
+1 -1
View File
@@ -27,7 +27,7 @@ qt_libs = [widgets, qt_util] + base_libs
qt_src = ["main.cc", "ui.cc", "qt/sidebar.cc", "qt/body.cc",
"qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc",
"qt/offroad/software_settings.cc", "qt/offroad/developer_panel.cc", "qt/offroad/onboarding.cc",
"qt/offroad/software_settings.cc", "qt/offroad/developer_panel.cc", "qt/offroad/onboarding.cc", "qt/offroad/dp_panel.cc",
"qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc", "qt/offroad/firehose.cc",
"qt/onroad/onroad_home.cc", "qt/onroad/annotated_camera.cc", "qt/onroad/model.cc",
"qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc", "qt/onroad/hud.cc"]
@@ -45,6 +45,21 @@ DeveloperPanel::DeveloperPanel(SettingsWindow *parent) : ListWidget(parent) {
// Toggles should be not available to change in onroad state
QObject::connect(uiState(), &UIState::offroadTransition, this, &DeveloperPanel::updateToggles);
// error logs
QPushButton* error_log_btn = new QPushButton(QObject::tr("Show Last Errors"));
error_log_btn->setObjectName("error_log_btn");
error_log_btn->setStyleSheet(R"(
#error_log_btn { height: 120px; border-radius: 15px; background-color: #393939; }
#error_log_btn:pressed { background-color: #4a4a4a; }
)");
addItem(error_log_btn);
QObject::connect(error_log_btn, &QPushButton::clicked, [=]() {
ConfirmationDialog::rich(QString::fromStdString(params.get("dp_device_last_log")), parent);
});
}
void DeveloperPanel::updateToggles(bool _offroad) {
+295
View File
@@ -0,0 +1,295 @@
#include "selfdrive/ui/qt/offroad/dp_panel.h"
void DPPanel::add_toyota_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("Toyota / Lexus"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
void DPPanel::add_vag_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("VW / Audi / Skoda"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
void DPPanel::add_mazda_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("Mazda"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
void DPPanel::add_lateral_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("Lateral Ctrl"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
void DPPanel::add_longitudinal_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("Longitudinal Ctrl"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
void DPPanel::add_ui_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("UI"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
void DPPanel::add_device_toggles() {
std::vector<std::tuple<QString, QString, QString>> toggle_defs{
{
"",
QString::fromUtf8("🐉 ") + tr("Device"),
"",
},
};
QWidget *label = nullptr;
bool has_toggle = false;
for (auto &[param, title, desc] : toggle_defs) {
if (param.isEmpty()) {
label = new LabelControl(title, "");
addItem(label);
continue;
}
has_toggle = true;
auto toggle = new ParamControl(param, title, desc, "", this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
addItem(toggle);
toggles[param.toStdString()] = toggle;
}
// If no toggles were added, hide the label
if (!has_toggle && label) {
label->hide();
}
}
DPPanel::DPPanel(SettingsWindow *parent) : ListWidget(parent) {
auto cp_bytes = params.get("CarParamsPersistent");
if (!cp_bytes.empty()) {
AlignedBuffer aligned_buf;
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
brand = QString::fromStdString(CP.getBrand());
vehicle_has_long_ctrl = hasLongitudinalControl(CP);
vehicle_has_radar_unavailable = CP.getRadarUnavailable();
}
if (brand == "toyota") {
add_toyota_toggles();
} else if (brand == "volkswagen") {
add_vag_toggles();
} else if (brand == "mazda") {
add_mazda_toggles();
}
add_lateral_toggles();
add_longitudinal_toggles();
add_ui_toggles();
add_device_toggles();
auto resetBtn = new ButtonControl(tr("Reset dragonpilot settings"), tr("RESET"));
connect(resetBtn, &ButtonControl::clicked, [&]() {
if (ConfirmationDialog::confirm(tr("Are you sure you want to reset all settings?"), tr("Reset"), this)) {
params.putBool("dp_device_reset_conf", true);
}
});
addItem(resetBtn);
fs_watch = new ParamWatcher(this);
QObject::connect(fs_watch, &ParamWatcher::paramChanged, [=](const QString &param_name, const QString &param_value) {
updateStates();
});
connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
is_onroad = !offroad;
updateStates();
});
updateStates();
}
void DPPanel::showEvent(QShowEvent *event) {
updateStates();
}
void DPPanel::updateStates() {
// do fs_watch here
if (!isVisible()) {
return;
}
// do state change logic here
}
void DPPanel::expandToggleDescription(const QString &param) {
toggles[param.toStdString()]->showDescription();
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include "selfdrive/ui/qt/offroad/settings.h"
class DPPanel : public ListWidget {
Q_OBJECT
public:
explicit DPPanel(SettingsWindow *parent);
public slots:
void expandToggleDescription(const QString &param);
private:
Params params;
ParamWatcher *fs_watch;
std::map<std::string, ParamControl*> toggles;
QString brand;
bool is_onroad = false;
bool vehicle_has_long_ctrl;
bool vehicle_has_radar_unavailable;
void add_toyota_toggles();
void add_vag_toggles();
void add_mazda_toggles();
void add_lateral_toggles();
void add_longitudinal_toggles();
void add_ui_toggles();
void add_device_toggles();
void updateStates();
void showEvent(QShowEvent *event) override;
};
+23 -7
View File
@@ -15,6 +15,7 @@
#include "selfdrive/ui/qt/widgets/scrollview.h"
#include "selfdrive/ui/qt/offroad/developer_panel.h"
#include "selfdrive/ui/qt/offroad/firehose.h"
#include "selfdrive/ui/qt/offroad/dp_panel.h"
TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
// param, title, desc, icon, restart needed
@@ -75,6 +76,20 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
"../assets/icons/metric.png",
false,
},
{
"DisableLogging",
tr("Disable Logging"),
"",
"../assets/offroad/icon_empty.svg",
true,
},
{
"DisableUpdates",
tr("Disable Updates"),
"",
"../assets/offroad/icon_empty.svg",
true,
},
};
@@ -278,13 +293,13 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
QObject::connect(uiState()->prime_state, &PrimeState::changed, [this] (PrimeState::Type type) {
pair_device->setVisible(type == PrimeState::PRIME_TYPE_UNPAIRED);
});
QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
for (auto btn : findChildren<ButtonControl *>()) {
if (btn != pair_device && btn != resetCalibBtn) {
btn->setEnabled(offroad);
}
}
});
// QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
// for (auto btn : findChildren<ButtonControl *>()) {
// if (btn != pair_device && btn != resetCalibBtn) {
// btn->setEnabled(offroad);
// }
// }
// });
// power buttons
QHBoxLayout *power_layout = new QHBoxLayout();
@@ -475,6 +490,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
{tr("Software"), new SoftwarePanel(this)},
{tr("Firehose"), new FirehosePanel(this)},
{tr("Developer"), new DeveloperPanel(this)},
{"DP", new DPPanel(this)},
};
nav_btns = new QButtonGroup(this);
+3 -1
View File
@@ -50,6 +50,7 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
addItem(installBtn);
// branch selecting
/*
targetBranchBtn = new ButtonControl(tr("Target Branch"), tr("SELECT"));
connect(targetBranchBtn, &ButtonControl::clicked, [=]() {
auto current = params.get("GitBranch");
@@ -73,6 +74,7 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
if (!params.getBool("IsTestedBranch")) {
addItem(targetBranchBtn);
}
*/
// uninstall button
auto uninstallBtn = new ButtonControl(tr("Uninstall %1").arg(getBrand()), tr("UNINSTALL"));
@@ -142,7 +144,7 @@ void SoftwarePanel::updateLabels() {
}
downloadBtn->setEnabled(true);
}
targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch")));
// targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch")));
// current + new versions
versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription")));
+1 -1
View File
@@ -19,7 +19,7 @@ void drawIcon(QPainter &p, const QPoint &center, const QPixmap &img, const QBrus
ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(false), engageable(false), QPushButton(parent) {
setFixedSize(btn_size, btn_size);
engage_img = loadPixmap("../assets/icons/chffr_wheel.png", {img_size, img_size});
engage_img = loadPixmap("../../dragonpilot/selfdrive/assets/dragonpilot.png", {img_size, img_size});
experimental_img = loadPixmap("../assets/icons/experimental.svg", {img_size, img_size});
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode);
}
+1 -1
View File
@@ -25,7 +25,7 @@ void Sidebar::drawMetric(QPainter &p, const QPair<QString, QString> &label, QCol
}
Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false), mic_indicator_pressed(false) {
home_img = loadPixmap("../assets/images/button_home.png", home_btn.size());
home_img = loadPixmap("../../dragonpilot/selfdrive/assets/dragonpilot.png", home_btn.size());
flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size());
settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio);
mic_img = loadPixmap("../assets/icons/microphone.png", QSize(30, 30));
+2 -2
View File
@@ -27,11 +27,11 @@ QString getVersion() {
}
QString getBrand() {
return QObject::tr("openpilot");
return QObject::tr("dragonpilot");
}
QString getUserAgent() {
return "openpilot-" + getVersion();
return "dragonpilot-" + getVersion();
}
std::optional<QString> getDongleId() {
+137
View File
@@ -88,6 +88,10 @@ public:
label.setText(text);
label.setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hlayout->addWidget(&label);
if (text == "") {
setContentsMargins(0, 50, 0, 0); // 30px top margin, 10px bottom margin
// This will create space above and below the entire header control.
}
}
void setText(const QString &text) { label.setText(text); }
@@ -317,3 +321,136 @@ public:
setLayout(l);
}
};
#include <QSpinBox>
class SpinBoxControl : public AbstractControl {
Q_OBJECT
public:
SpinBoxControl(const QString &title, const QString &desc = "", const QString &icon = "", const int val = 0, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) {
spinbox.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
spinbox.setAlignment(Qt::AlignCenter);
spinbox.setStyleSheet(R"(
QSpinBox {
width: 300px;
height: 80px;
padding: 0px;
border-radius:40px;
font-size: 36px;
}
QSpinBox::up-button {
subcontrol-origin: margin;
subcontrol-position: center right;
image: url(../../dragonpilot/selfdrive/assets/icons/icon_plus.png);
right: 1px;
height: 80px;
width: 80px;
}
QSpinBox::down-button {
subcontrol-origin: margin;
subcontrol-position: center left;
image: url(../../dragonpilot/selfdrive/assets/icons/icon_minus.png);
left: 1px;
height: 80px;
width: 80px;
}
)");
hlayout->addWidget(&spinbox);
QObject::connect(&spinbox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SpinBoxControl::valChanged);
}
signals:
void valChanged(int val);
protected:
QSpinBox spinbox;
};
class ParamSpinBoxControl : public SpinBoxControl {
Q_OBJECT
public:
ParamSpinBoxControl(const QString &param, const QString &title, const QString &desc, const QString &icon, const int minimum = 0, const int maximum = 100, const int step = 1, const QString suffix = "", const QString minText = "", QWidget *parent = nullptr) : SpinBoxControl(title, desc, icon, 0, parent) {
spinbox.setRange(minimum, maximum);
spinbox.setSingleStep(step);
spinbox.setSuffix(suffix);
spinbox.setSpecialValueText(minText);
std::string str_val = Params().get(param.toStdString().c_str());
if (str_val != "") {
int val = std::stoi(str_val);
spinbox.setValue(val);
QObject::connect(this, &SpinBoxControl::valChanged, [=](int val) {
Params().put(param.toStdString(), std::to_string(val));
});
}
}
};
class DoubleSpinBoxControl : public AbstractControl {
Q_OBJECT
public:
DoubleSpinBoxControl(const QString &title, const QString &desc = "", const QString &icon = "", const double val = 0.0, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) {
spinbox.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
spinbox.setAlignment(Qt::AlignCenter);
spinbox.setStyleSheet(R"(
QDoubleSpinBox {
width: 300px;
height: 80px;
padding: 0px;
border-radius:40px;
font-size: 36px;
}
QDoubleSpinBox::up-button {
subcontrol-origin: margin;
subcontrol-position: center right;
image: url(../../dragonpilot/selfdrive/assets/icons/icon_plus.png);
right: 1px;
height: 80px;
width: 80px;
}
QDoubleSpinBox::down-button {
subcontrol-origin: margin;
subcontrol-position: center left;
image: url(../../dragonpilot/selfdrive/assets/icons/icon_minus.png);
left: 1px;
height: 80px;
width: 80px;
}
)");
hlayout->addWidget(&spinbox);
QObject::connect(&spinbox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &DoubleSpinBoxControl::valChanged);
}
signals:
void valChanged(double val);
protected:
QDoubleSpinBox spinbox;
};
class ParamDoubleSpinBoxControl : public DoubleSpinBoxControl {
Q_OBJECT
public:
ParamDoubleSpinBoxControl(const QString &param, const QString &title, const QString &desc, const QString &icon, const double minimum = 0.0, const double maximum = 100.0, const double step = 1.0, const QString suffix = "", const QString minText = "", QWidget *parent = nullptr) : DoubleSpinBoxControl(title, desc, icon, 0.0, parent) {
spinbox.setRange(minimum, maximum);
spinbox.setSingleStep(step);
spinbox.setSuffix(suffix);
spinbox.setSpecialValueText(minText);
std::string str_val = Params().get(param.toStdString().c_str());
if (str_val != "") {
double val = std::stod(str_val);
spinbox.setValue(val);
QObject::connect(this, &DoubleSpinBoxControl::valChanged, [=](double val) {
Params().put(param.toStdString(), std::to_string(val));
});
}
}
void setValue(float v) { spinbox.setValue(v); }
};
+3 -1
View File
@@ -171,8 +171,10 @@ def manager_thread() -> None:
# Exit main loop when uninstall/shutdown/reboot is needed
shutdown = False
for param in ("DoUninstall", "DoShutdown", "DoReboot"):
for param in ("DoUninstall", "DoShutdown", "DoReboot", "dp_device_reset_conf"):
if params.get_bool(param):
if param == "dp_device_reset_conf":
os.system("rm -fr /data/params/d/dp_*")
shutdown = True
params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}")
cloudlog.warning(f"Shutting down manager - {param} set")
+1 -1
View File
@@ -19,7 +19,7 @@ def iscar(started: bool, params: Params, CP: car.CarParams) -> bool:
return started and not CP.notCar
def logging(started: bool, params: Params, CP: car.CarParams) -> bool:
run = (not CP.notCar) or not params.get_bool("DisableLogging")
run = not params.get_bool("DisableLogging")
return started and run
def ublox_available() -> bool:
+7 -2
View File
@@ -12,9 +12,9 @@ from openpilot.system.version import get_build_metadata, get_version
class SentryProject(Enum):
# python project
SELFDRIVE = "https://6f3c7076c1e14b2aa10f5dde6dda0cc4@o33823.ingest.sentry.io/77924"
SELFDRIVE = "https://980a0cba712a4c3593c33c78a12446e1@o273754.ingest.sentry.io/1488600"
# native project
SELFDRIVE_NATIVE = "https://3e4b586ed21a4479ad5d85083b639bc6@o33823.ingest.sentry.io/157615"
SELFDRIVE_NATIVE = "https://980a0cba712a4c3593c33c78a12446e1@o273754.ingest.sentry.io/1488600"
def report_tombstone(fn: str, message: str, contents: str) -> None:
@@ -26,11 +26,16 @@ def report_tombstone(fn: str, message: str, contents: str) -> None:
sentry_sdk.capture_message(message=message)
sentry_sdk.flush()
def save_exception(exc_text):
log = "\n".join(exc_text.splitlines()) + "\n"
Params().put("dp_device_last_log", log)
def capture_exception(*args, **kwargs) -> None:
cloudlog.error("crash", exc_info=kwargs.get('exc_info', 1))
try:
import traceback
save_exception(traceback.format_exc())
sentry_sdk.capture_exception(*args, **kwargs)
sentry_sdk.flush() # https://github.com/getsentry/sentry-python/issues/291
except Exception:
+1 -1
View File
@@ -26,7 +26,7 @@ def clamp(value, min_value, max_value):
class Spinner(Widget):
def __init__(self):
super().__init__()
self._comma_texture = gui_app.texture("images/spinner_comma.png", TEXTURE_SIZE, TEXTURE_SIZE)
self._comma_texture = gui_app.texture("../../dragonpilot/selfdrive/assets/images/spinner_comma.png", TEXTURE_SIZE, TEXTURE_SIZE)
self._spinner_texture = gui_app.texture("images/spinner_track.png", TEXTURE_SIZE, TEXTURE_SIZE, alpha_premultiply=True)
self._rotation = 0.0
self._progress: int | None = None