mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-08-05 02:35:41 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3201845f2 | |||
| 9567c074c1 | |||
| a79a2ac494 | |||
| e6055d68be | |||
| 3b907acfe7 |
@@ -67,15 +67,7 @@ jobs:
|
|||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
run: |
|
run: |
|
||||||
cd $STRIPPED_DIR
|
cd $STRIPPED_DIR
|
||||||
${{ env.RUN }} "release/check-dirty.sh && \
|
${{ env.RUN }} "release/check-dirty.sh"
|
||||||
MAX_EXAMPLES=5 $PYTEST -m 'not slow' selfdrive/car system/manager"
|
|
||||||
- name: Static analysis
|
|
||||||
timeout-minutes: 1
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE
|
|
||||||
cp pyproject.toml $STRIPPED_DIR
|
|
||||||
cd $STRIPPED_DIR
|
|
||||||
${{ env.RUN }} "scripts/lint/lint.sh --skip check_added_large_files"
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on:
|
runs-on:
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ jobs:
|
|||||||
run: >-
|
run: >-
|
||||||
sudo apt-get install -y imagemagick
|
sudo apt-get install -y imagemagick
|
||||||
|
|
||||||
scenes="homescreen settings_device settings_software settings_sunnylink settings_toggles settings_sunnypilot settings_sunnypilot_mads settings_trips settings_developer offroad_alert update_available prime onroad onroad_disengaged onroad_override onroad_sidebar onroad_wide onroad_wide_sidebar onroad_alert_small onroad_alert_mid onroad_alert_full driver_camera body keyboard"
|
scenes="homescreen settings_device settings_software settings_sunnylink settings_toggles settings_sunnypilot settings_sunnypilot_mads settings_trips settings_developer offroad_alert update_available prime onroad onroad_disengaged onroad_override onroad_sidebar onroad_wide onroad_wide_sidebar onroad_alert_small onroad_alert_mid onroad_alert_full driver_camera body keyboard keyboard_uppercase"
|
||||||
A=($scenes)
|
A=($scenes)
|
||||||
|
|
||||||
DIFF=""
|
DIFF=""
|
||||||
|
|||||||
+12
-5
@@ -1,16 +1,23 @@
|
|||||||
Version 0.9.8 (2024-XX-XX)
|
Version 0.9.9 (2025-03-30)
|
||||||
|
========================
|
||||||
|
* Coming soon
|
||||||
|
* Rivian support
|
||||||
|
* F-150 & Mach-E support
|
||||||
|
* Tesla Model 3 support
|
||||||
|
|
||||||
|
Version 0.9.8 (2025-01-30)
|
||||||
========================
|
========================
|
||||||
* New driving model
|
|
||||||
* Trained in brand new ML simulator
|
|
||||||
* Model now gates applying positive accel in Chill mode
|
|
||||||
* New driving monitoring model
|
* New driving monitoring model
|
||||||
* Reduced false positives related to passengers
|
* Reduced false positives related to passengers
|
||||||
* Image processing pipeline moved to the ISP
|
* Image processing pipeline moved to the ISP
|
||||||
* More GPU time for driving models
|
* More GPU time for driving models
|
||||||
* Power draw reduced 0.5W, which means your device runs cooler
|
* Power draw reduced 0.5W, which means your device runs cooler
|
||||||
* Added toggle to enable driver monitoring even when openpilot is not engaged
|
* Added toggle to enable driver monitoring even when openpilot is not engaged
|
||||||
* Enable openpilot longitudinal control for Ford Q3 vehicles
|
* Enable openpilot longitudinal control for Ford Q3 vehicles
|
||||||
* New Toyota TSS2 longitudinal tune
|
* New Toyota TSS2 longitudinal tune
|
||||||
|
* Coming soon
|
||||||
|
* New driving model with gas gating
|
||||||
|
* Training data upload mode
|
||||||
|
|
||||||
Version 0.9.7 (2024-06-13)
|
Version 0.9.7 (2024-06-13)
|
||||||
========================
|
========================
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ struct OnroadEvent @0xc4fa6047f024e718 {
|
|||||||
silentParkBrake @162;
|
silentParkBrake @162;
|
||||||
controlsMismatchLateral @163;
|
controlsMismatchLateral @163;
|
||||||
hyundaiRadarTracksConfirmed @164;
|
hyundaiRadarTracksConfirmed @164;
|
||||||
|
experimentalModeSwitched @165;
|
||||||
|
|
||||||
soundsUnavailableDEPRECATED @47;
|
soundsUnavailableDEPRECATED @47;
|
||||||
}
|
}
|
||||||
@@ -483,6 +484,7 @@ struct GpsLocationData {
|
|||||||
speedAccuracy @12 :Float32;
|
speedAccuracy @12 :Float32;
|
||||||
|
|
||||||
hasFix @13 :Bool;
|
hasFix @13 :Bool;
|
||||||
|
satelliteCount @14 :Int8;
|
||||||
|
|
||||||
enum SensorSource {
|
enum SensorSource {
|
||||||
android @0;
|
android @0;
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ cl_context cl_create_context(cl_device_id device_id) {
|
|||||||
return CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err));
|
return CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cl_release_context(cl_context context) {
|
||||||
|
clReleaseContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args) {
|
cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args) {
|
||||||
return cl_program_from_source(ctx, device_id, util::read_file(path), args);
|
return cl_program_from_source(ctx, device_id, util::read_file(path), args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
cl_device_id cl_get_device_id(cl_device_type device_type);
|
cl_device_id cl_get_device_id(cl_device_type device_type);
|
||||||
cl_context cl_create_context(cl_device_id device_id);
|
cl_context cl_create_context(cl_device_id device_id);
|
||||||
|
void cl_release_context(cl_context context);
|
||||||
cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args = nullptr);
|
cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args = nullptr);
|
||||||
cl_program cl_program_from_binary(cl_context ctx, cl_device_id device_id, const uint8_t* binary, size_t length, const char* args = nullptr);
|
cl_program cl_program_from_binary(cl_context ctx, cl_device_id device_id, const uint8_t* binary, size_t length, const char* args = nullptr);
|
||||||
cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args);
|
cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args);
|
||||||
|
|||||||
+6
-9
@@ -1,9 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from numbers import Number
|
from numbers import Number
|
||||||
|
|
||||||
from openpilot.common.numpy_fast import clip, interp
|
|
||||||
|
|
||||||
|
|
||||||
class PIDController:
|
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_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
||||||
self._k_p = k_p
|
self._k_p = k_p
|
||||||
@@ -28,15 +25,15 @@ class PIDController:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def k_p(self):
|
def k_p(self):
|
||||||
return interp(self.speed, self._k_p[0], self._k_p[1])
|
return np.interp(self.speed, self._k_p[0], self._k_p[1])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def k_i(self):
|
def k_i(self):
|
||||||
return interp(self.speed, self._k_i[0], self._k_i[1])
|
return np.interp(self.speed, self._k_i[0], self._k_i[1])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def k_d(self):
|
def k_d(self):
|
||||||
return interp(self.speed, self._k_d[0], self._k_d[1])
|
return np.interp(self.speed, self._k_d[0], self._k_d[1])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def error_integral(self):
|
def error_integral(self):
|
||||||
@@ -64,10 +61,10 @@ class PIDController:
|
|||||||
|
|
||||||
# Clip i to prevent exceeding control limits
|
# Clip i to prevent exceeding control limits
|
||||||
control_no_i = self.p + self.d + self.f
|
control_no_i = self.p + self.d + self.f
|
||||||
control_no_i = clip(control_no_i, self.neg_limit, self.pos_limit)
|
control_no_i = np.clip(control_no_i, self.neg_limit, self.pos_limit)
|
||||||
self.i = clip(self.i, self.neg_limit - control_no_i, self.pos_limit - control_no_i)
|
self.i = np.clip(self.i, self.neg_limit - control_no_i, self.pos_limit - control_no_i)
|
||||||
|
|
||||||
control = self.p + self.i + self.d + self.f
|
control = self.p + self.i + self.d + self.f
|
||||||
|
|
||||||
self.control = clip(control, self.neg_limit, self.pos_limit)
|
self.control = np.clip(control, self.neg_limit, self.pos_limit)
|
||||||
return self.control
|
return self.control
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ public:
|
|||||||
zmq_setsockopt(sock, ZMQ_LINGER, &timeout, sizeof(timeout));
|
zmq_setsockopt(sock, ZMQ_LINGER, &timeout, sizeof(timeout));
|
||||||
zmq_connect(sock, Path::swaglog_ipc().c_str());
|
zmq_connect(sock, Path::swaglog_ipc().c_str());
|
||||||
|
|
||||||
|
// workaround for https://github.com/dropbox/json11/issues/38
|
||||||
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
|
||||||
print_level = CLOUDLOG_WARNING;
|
print_level = CLOUDLOG_WARNING;
|
||||||
if (const char* print_lvl = getenv("LOGPRINT")) {
|
if (const char* print_lvl = getenv("LOGPRINT")) {
|
||||||
if (strcmp(print_lvl, "debug") == 0) {
|
if (strcmp(print_lvl, "debug") == 0) {
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import numpy as np
|
|
||||||
|
|
||||||
from openpilot.common.numpy_fast import interp
|
|
||||||
|
|
||||||
|
|
||||||
class TestInterp:
|
|
||||||
def test_correctness_controls(self):
|
|
||||||
_A_CRUISE_MIN_BP = np.asarray([0., 5., 10., 20., 40.])
|
|
||||||
_A_CRUISE_MIN_V = np.asarray([-1.0, -.8, -.67, -.5, -.30])
|
|
||||||
v_ego_arr = [-1, -1e-12, 0, 4, 5, 6, 7, 10, 11, 15.2, 20, 21, 39,
|
|
||||||
39.999999, 40, 41]
|
|
||||||
|
|
||||||
expected = np.interp(v_ego_arr, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
|
||||||
actual = interp(v_ego_arr, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
|
||||||
|
|
||||||
np.testing.assert_equal(actual, expected)
|
|
||||||
|
|
||||||
for v_ego in v_ego_arr:
|
|
||||||
expected = np.interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
|
||||||
actual = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
|
||||||
np.testing.assert_equal(actual, expected)
|
|
||||||
+1
-1
@@ -88,7 +88,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2017-18">Buy Here</a></sub></details>||
|
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2017-18">Buy Here</a></sub></details>||
|
||||||
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2019">Buy Here</a></sub></details>||
|
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2019">Buy Here</a></sub></details>||
|
||||||
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||||
|Hyundai|Elantra GT 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra GT 2017-19">Buy Here</a></sub></details>||
|
|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra GT 2017-20">Buy Here</a></sub></details>||
|
||||||
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||||
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Genesis 2015-16">Buy Here</a></sub></details>||
|
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Genesis 2015-16">Buy Here</a></sub></details>||
|
||||||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=i30 2017-19">Buy Here</a></sub></details>||
|
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=i30 2017-19">Buy Here</a></sub></details>||
|
||||||
|
|||||||
+1
-1
Submodule opendbc_repo updated: 6a2ad131eb...003db4f6c6
+1
-1
Submodule panda updated: 781af8b4f1...96632fa921
+2
-175
@@ -6,41 +6,11 @@ from pathlib import Path
|
|||||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
ROOT = HERE + "/.."
|
ROOT = HERE + "/.."
|
||||||
|
|
||||||
# blacklisting is for two purposes:
|
|
||||||
# - minimizing release download size
|
|
||||||
# - keeping the diff readable
|
|
||||||
blacklist = [
|
blacklist = [
|
||||||
"panda/drivers/",
|
".git/",
|
||||||
"panda/examples/",
|
|
||||||
"panda/tests/safety/",
|
|
||||||
|
|
||||||
"opendbc_repo/dbc/.*.dbc$",
|
|
||||||
"opendbc_repo/dbc/generator/",
|
|
||||||
|
|
||||||
"cereal/.*test.*",
|
|
||||||
"^common/tests/",
|
|
||||||
|
|
||||||
# particularly large text files
|
|
||||||
"uv.lock",
|
|
||||||
"third_party/catch2",
|
|
||||||
"selfdrive/car/tests/test_models.*",
|
|
||||||
|
|
||||||
"^tools/",
|
|
||||||
"^tinygrad_repo/",
|
|
||||||
|
|
||||||
"matlab.*.md",
|
"matlab.*.md",
|
||||||
|
|
||||||
".git/",
|
|
||||||
".github/",
|
|
||||||
".devcontainer/",
|
|
||||||
"Darwin/",
|
|
||||||
".vscode",
|
|
||||||
|
|
||||||
# common things
|
|
||||||
"LICENSE",
|
|
||||||
"Dockerfile",
|
|
||||||
".pre-commit",
|
|
||||||
|
|
||||||
# no LFS or submodules in release
|
# no LFS or submodules in release
|
||||||
".lfsconfig",
|
".lfsconfig",
|
||||||
".gitattributes",
|
".gitattributes",
|
||||||
@@ -48,153 +18,10 @@ blacklist = [
|
|||||||
".gitmodules",
|
".gitmodules",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Sunnypilot blacklist
|
|
||||||
sunnypilot_blacklist = [
|
|
||||||
"system/loggerd/sunnylink_uploader.py", # Temporarily, until we are ready to roll it out widely
|
|
||||||
".idea/",
|
|
||||||
".run/",
|
|
||||||
".*__pycache__/.*",
|
|
||||||
".*\\.pyc",
|
|
||||||
"teleoprtc/*",
|
|
||||||
"third_party/snpe/x86_64/*",
|
|
||||||
"body/board/canloader.py",
|
|
||||||
"body/board/flash_base.sh",
|
|
||||||
"body/board/flash_knee.sh",
|
|
||||||
"body/board/recover.sh",
|
|
||||||
".*/test/",
|
|
||||||
".*/tests/",
|
|
||||||
".*tinygrad_repo/tinygrad/renderer/",
|
|
||||||
"README.md",
|
|
||||||
".*internal/",
|
|
||||||
"docs/.*",
|
|
||||||
".sconsign.dblite",
|
|
||||||
"release/ci/scons_cache/",
|
|
||||||
".gitlab-ci.yml",
|
|
||||||
".clang-tidy",
|
|
||||||
".dockerignore",
|
|
||||||
".editorconfig",
|
|
||||||
".python-version",
|
|
||||||
"SECURITY.md",
|
|
||||||
"codecov.yml",
|
|
||||||
"conftest.py",
|
|
||||||
"poetry.lock",
|
|
||||||
".venv/",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Merge the blacklists
|
|
||||||
blacklist += sunnypilot_blacklist
|
|
||||||
|
|
||||||
# gets you through the blacklist
|
# gets you through the blacklist
|
||||||
whitelist = [
|
whitelist: list[str] = [
|
||||||
"tools/lib/",
|
|
||||||
"tools/bodyteleop/",
|
|
||||||
"tools/joystick/",
|
|
||||||
"tools/longitudinal_maneuvers/",
|
|
||||||
|
|
||||||
"tinygrad_repo/examples/openpilot/compile3.py",
|
|
||||||
"tinygrad_repo/extra/onnx.py",
|
|
||||||
"tinygrad_repo/extra/onnx_ops.py",
|
|
||||||
"tinygrad_repo/extra/thneed.py",
|
|
||||||
"tinygrad_repo/extra/utils.py",
|
|
||||||
"tinygrad_repo/tinygrad/codegen/kernel.py",
|
|
||||||
"tinygrad_repo/tinygrad/codegen/linearizer.py",
|
|
||||||
"tinygrad_repo/tinygrad/features/image.py",
|
|
||||||
"tinygrad_repo/tinygrad/features/search.py",
|
|
||||||
"tinygrad_repo/tinygrad/nn/*",
|
|
||||||
"tinygrad_repo/tinygrad/renderer/cstyle.py",
|
|
||||||
"tinygrad_repo/tinygrad/renderer/opencl.py",
|
|
||||||
"tinygrad_repo/tinygrad/runtime/lib.py",
|
|
||||||
"tinygrad_repo/tinygrad/runtime/ops_cpu.py",
|
|
||||||
"tinygrad_repo/tinygrad/runtime/ops_disk.py",
|
|
||||||
"tinygrad_repo/tinygrad/runtime/ops_gpu.py",
|
|
||||||
"tinygrad_repo/tinygrad/shape/*",
|
|
||||||
"tinygrad_repo/tinygrad/.*.py",
|
|
||||||
|
|
||||||
# TODO: do this automatically
|
|
||||||
"opendbc_repo/dbc/comma_body.dbc",
|
|
||||||
"opendbc_repo/dbc/chrysler_ram_hd_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/chrysler_ram_dt_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/chrysler_pacifica_2017_hybrid_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc",
|
|
||||||
"opendbc_repo/dbc/gm_global_a_powertrain_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/gm_global_a_object.dbc",
|
|
||||||
"opendbc_repo/dbc/gm_global_a_chassis.dbc",
|
|
||||||
"opendbc_repo/dbc/FORD_CADS.dbc",
|
|
||||||
"opendbc_repo/dbc/ford_fusion_2018_adas.dbc",
|
|
||||||
"opendbc_repo/dbc/ford_lincoln_base_pt.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_accord_2018_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/acura_ilx_2016_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/acura_rdx_2018_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/acura_rdx_2020_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_civic_touring_2016_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_civic_hatchback_ex_2017_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_crv_touring_2016_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_crv_ex_2017_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_crv_ex_2017_body_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_crv_executive_2016_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_fit_ex_2018_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_odyssey_exl_2018_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_odyssey_extreme_edition_2018_china_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_insight_ex_2019_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/acura_ilx_2016_nidec.dbc",
|
|
||||||
"opendbc_repo/dbc/honda_civic_ex_2022_can_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/hyundai_canfd.dbc",
|
|
||||||
"opendbc_repo/dbc/hyundai_kia_generic.dbc",
|
|
||||||
"opendbc_repo/dbc/hyundai_kia_mando_front_radar_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/mazda_2017.dbc",
|
|
||||||
"opendbc_repo/dbc/nissan_x_trail_2017_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/nissan_leaf_2018_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/subaru_global_2017_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/subaru_global_2020_hybrid_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/subaru_outback_2015_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/subaru_outback_2019_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/subaru_forester_2017_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/toyota_tnga_k_pt_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/toyota_new_mc_pt_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/toyota_nodsu_pt_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/toyota_adas.dbc",
|
|
||||||
"opendbc_repo/dbc/toyota_tss2_adas.dbc",
|
|
||||||
"opendbc_repo/dbc/vw_golf_mk4.dbc",
|
|
||||||
"opendbc_repo/dbc/vw_mqb_2010.dbc",
|
|
||||||
"opendbc_repo/dbc/tesla_can.dbc",
|
|
||||||
"opendbc_repo/dbc/tesla_radar_bosch_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/tesla_radar_continental_generated.dbc",
|
|
||||||
"opendbc_repo/dbc/tesla_powertrain.dbc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Sunnypilot whitelist
|
|
||||||
sunnypilot_whitelist = [
|
|
||||||
"^README.md",
|
|
||||||
".*selfdrive/test/fuzzy_generation.py",
|
|
||||||
".*selfdrive/test/helpers.py",
|
|
||||||
".*selfdrive/test/__init__.py",
|
|
||||||
".*selfdrive/test/setup_device_ci.sh",
|
|
||||||
".*selfdrive/test/test_time_to_onroad.py",
|
|
||||||
".*selfdrive/test/test_onroad.py",
|
|
||||||
".*system/manager/test/test_manager.py",
|
|
||||||
".*system/manager/test/__init__.py",
|
|
||||||
".*system/qcomgpsd/tests/test_qcomgpsd.py",
|
|
||||||
".*system/updated/casync/tests/test_casync.py",
|
|
||||||
".*system/updated/tests/test_git.py",
|
|
||||||
".*system/updated/tests/test_base.py",
|
|
||||||
".*selfdrive/ui/tests/test_translations.py",
|
|
||||||
".*selfdrive/car/tests/__init__.py",
|
|
||||||
".*selfdrive/car/tests/test_car_interfaces.py",
|
|
||||||
".*selfdrive/navd/tests/test_navd.py",
|
|
||||||
".*selfdrive/navd/tests/test_map_renderer.py",
|
|
||||||
".*selfdrive/boardd/tests/test_boardd_loopback.py",
|
|
||||||
".*INTEGRATION.md",
|
|
||||||
".*HOW-TOS.md",
|
|
||||||
".*CARS.md",
|
|
||||||
".*LIMITATIONS.md",
|
|
||||||
".*CONTRIBUTING.md",
|
|
||||||
".*sunnyhaibin0850_qrcode_paypal.me.png",
|
|
||||||
"opendbc/.*.dbc",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Merge the whitelists
|
|
||||||
whitelist += sunnypilot_whitelist
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
for f in Path(ROOT).rglob("**/*"):
|
for f in Path(ROOT).rglob("**/*"):
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class CarSpecificEvents:
|
|||||||
|
|
||||||
elif self.CP.carName == 'volkswagen':
|
elif self.CP.carName == 'volkswagen':
|
||||||
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic],
|
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic],
|
||||||
pcm_enable=not self.CP.openpilotLongitudinalControl,
|
pcm_enable=self.CP.pcmCruise,
|
||||||
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
|
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
|
||||||
|
|
||||||
# Low speed steer alert hysteresis logic
|
# Low speed steer alert hysteresis logic
|
||||||
@@ -149,7 +149,7 @@ class CarSpecificEvents:
|
|||||||
# Main button also can trigger an engagement on these cars
|
# Main button also can trigger an engagement on these cars
|
||||||
self.cruise_buttons.append(any(ev.type in HYUNDAI_ENABLE_BUTTONS for ev in CS.buttonEvents))
|
self.cruise_buttons.append(any(ev.type in HYUNDAI_ENABLE_BUTTONS for ev in CS.buttonEvents))
|
||||||
events = self.create_common_events(CS, CS_prev, extra_gears=(GearShifter.sport, GearShifter.manumatic),
|
events = self.create_common_events(CS, CS_prev, extra_gears=(GearShifter.sport, GearShifter.manumatic),
|
||||||
pcm_enable=self.CP.pcmCruise, allow_enable=any(self.cruise_buttons))
|
pcm_enable=self.CP.pcmCruise, allow_enable=any(self.cruise_buttons), allow_button_cancel=False)
|
||||||
|
|
||||||
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
|
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
|
||||||
if CS.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
|
if CS.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
|
||||||
@@ -165,7 +165,7 @@ class CarSpecificEvents:
|
|||||||
return events
|
return events
|
||||||
|
|
||||||
def create_common_events(self, CS: structs.CarState, CS_prev: car.CarState, extra_gears=None, pcm_enable=True,
|
def create_common_events(self, CS: structs.CarState, CS_prev: car.CarState, extra_gears=None, pcm_enable=True,
|
||||||
allow_enable=True, enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise)):
|
allow_enable=True, allow_button_cancel=True, enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise)):
|
||||||
events = Events()
|
events = Events()
|
||||||
|
|
||||||
if CS.doorOpen:
|
if CS.doorOpen:
|
||||||
@@ -191,7 +191,7 @@ class CarSpecificEvents:
|
|||||||
events.add(EventName.speedTooHigh)
|
events.add(EventName.speedTooHigh)
|
||||||
if CS.cruiseState.nonAdaptive:
|
if CS.cruiseState.nonAdaptive:
|
||||||
events.add(EventName.wrongCruiseMode)
|
events.add(EventName.wrongCruiseMode)
|
||||||
if CS.brakeHoldActive and self.CP.openpilotLongitudinalControl:
|
if CS.brakeHoldActive and self.CP.openpilotLongitudinalControl and self.CP.carName != 'toyota':
|
||||||
events.add(EventName.brakeHold)
|
events.add(EventName.brakeHold)
|
||||||
if CS.parkingBrake:
|
if CS.parkingBrake:
|
||||||
events.add(EventName.parkBrake)
|
events.add(EventName.parkBrake)
|
||||||
@@ -216,7 +216,8 @@ class CarSpecificEvents:
|
|||||||
if not self.CP.pcmCruise and (b.type in enable_buttons and not b.pressed):
|
if not self.CP.pcmCruise and (b.type in enable_buttons and not b.pressed):
|
||||||
events.add(EventName.buttonEnable)
|
events.add(EventName.buttonEnable)
|
||||||
# Disable on rising and falling edge of cancel for both stock and OP long
|
# Disable on rising and falling edge of cancel for both stock and OP long
|
||||||
if b.type == ButtonType.cancel:
|
# TODO: only check the cancel button with openpilot longitudinal on all brands to match panda safety
|
||||||
|
if b.type == ButtonType.cancel and (allow_button_cancel or not self.CP.pcmCruise):
|
||||||
events.add(EventName.buttonCancel)
|
events.add(EventName.buttonCancel)
|
||||||
|
|
||||||
# Handle permanent and temporary steering faults
|
# Handle permanent and temporary steering faults
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class Car:
|
|||||||
self.can_rcv_cum_timeout_counter = 0
|
self.can_rcv_cum_timeout_counter = 0
|
||||||
|
|
||||||
self.CC_prev = car.CarControl.new_message()
|
self.CC_prev = car.CarControl.new_message()
|
||||||
|
self.CS_prev = car.CarState.new_message()
|
||||||
self.initialized_prev = False
|
self.initialized_prev = False
|
||||||
|
|
||||||
self.last_actuators_output = structs.CarControl.Actuators()
|
self.last_actuators_output = structs.CarControl.Actuators()
|
||||||
@@ -188,8 +189,12 @@ class Car:
|
|||||||
if can_rcv_valid and REPLAY:
|
if can_rcv_valid and REPLAY:
|
||||||
self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime
|
self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime
|
||||||
|
|
||||||
# TODO: mirror the carState.cruiseState struct?
|
|
||||||
self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric)
|
self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric)
|
||||||
|
if self.sm['carControl'].enabled and not self.CC_prev.enabled:
|
||||||
|
# Use CarState w/ buttons from the step selfdrived enables on
|
||||||
|
self.v_cruise_helper.initialize_v_cruise(self.CS_prev, self.experimental_mode)
|
||||||
|
|
||||||
|
# TODO: mirror the carState.cruiseState struct?
|
||||||
CS.vCruise = float(self.v_cruise_helper.v_cruise_kph)
|
CS.vCruise = float(self.v_cruise_helper.v_cruise_kph)
|
||||||
CS.vCruiseCluster = float(self.v_cruise_helper.v_cruise_cluster_kph)
|
CS.vCruiseCluster = float(self.v_cruise_helper.v_cruise_cluster_kph)
|
||||||
|
|
||||||
@@ -247,9 +252,6 @@ class Car:
|
|||||||
def step(self):
|
def step(self):
|
||||||
CS, RD = self.state_update()
|
CS, RD = self.state_update()
|
||||||
|
|
||||||
if self.sm['carControl'].enabled and not self.CC_prev.enabled:
|
|
||||||
self.v_cruise_helper.initialize_v_cruise(CS, self.experimental_mode)
|
|
||||||
|
|
||||||
self.state_publish(CS, RD)
|
self.state_publish(CS, RD)
|
||||||
|
|
||||||
initialized = (not any(e.name == EventName.selfdriveInitializing for e in self.sm['onroadEvents']) and
|
initialized = (not any(e.name == EventName.selfdriveInitializing for e in self.sm['onroadEvents']) and
|
||||||
@@ -258,6 +260,7 @@ class Car:
|
|||||||
self.controls_update(CS, self.sm['carControl'])
|
self.controls_update(CS, self.sm['carControl'])
|
||||||
|
|
||||||
self.initialized_prev = initialized
|
self.initialized_prev = initialized
|
||||||
|
self.CS_prev = CS
|
||||||
|
|
||||||
def params_thread(self, evt):
|
def params_thread(self, evt):
|
||||||
while not evt.is_set():
|
while not evt.is_set():
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import math
|
import math
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from cereal import car
|
from cereal import car
|
||||||
from openpilot.common.conversions import Conversions as CV
|
from openpilot.common.conversions import Conversions as CV
|
||||||
from openpilot.common.numpy_fast import clip
|
|
||||||
|
|
||||||
|
|
||||||
# WARNING: this value was determined based on the model's training distribution,
|
# WARNING: this value was determined based on the model's training distribution,
|
||||||
@@ -106,7 +106,7 @@ class VCruiseHelper:
|
|||||||
if CS.gasPressed and button_type in (ButtonType.decelCruise, ButtonType.setCruise):
|
if CS.gasPressed and button_type in (ButtonType.decelCruise, ButtonType.setCruise):
|
||||||
self.v_cruise_kph = max(self.v_cruise_kph, CS.vEgo * CV.MS_TO_KPH)
|
self.v_cruise_kph = max(self.v_cruise_kph, CS.vEgo * CV.MS_TO_KPH)
|
||||||
|
|
||||||
self.v_cruise_kph = clip(round(self.v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX)
|
self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX)
|
||||||
|
|
||||||
def update_button_timers(self, CS, enabled):
|
def update_button_timers(self, CS, enabled):
|
||||||
# increment timer for buttons still pressed
|
# increment timer for buttons still pressed
|
||||||
@@ -130,6 +130,6 @@ class VCruiseHelper:
|
|||||||
if any(b.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for b in CS.buttonEvents) and self.v_cruise_initialized:
|
if any(b.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for b in CS.buttonEvents) and self.v_cruise_initialized:
|
||||||
self.v_cruise_kph = self.v_cruise_kph_last
|
self.v_cruise_kph = self.v_cruise_kph_last
|
||||||
else:
|
else:
|
||||||
self.v_cruise_kph = int(round(clip(CS.vEgo * CV.MS_TO_KPH, initial, V_CRUISE_MAX)))
|
self.v_cruise_kph = int(round(np.clip(CS.vEgo * CV.MS_TO_KPH, initial, V_CRUISE_MAX)))
|
||||||
|
|
||||||
self.v_cruise_cluster_kph = self.v_cruise_kph
|
self.v_cruise_cluster_kph = self.v_cruise_kph
|
||||||
|
|||||||
@@ -119,15 +119,16 @@ class Controls:
|
|||||||
|
|
||||||
# accel PID loop
|
# accel PID loop
|
||||||
pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, CS.vCruise * CV.KPH_TO_MS)
|
pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, CS.vCruise * CV.KPH_TO_MS)
|
||||||
actuators.accel = self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits)
|
actuators.accel = float(self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits))
|
||||||
|
|
||||||
# Steering PID loop and lateral MPC
|
# Steering PID loop and lateral MPC
|
||||||
self.desired_curvature = clip_curvature(CS.vEgo, self.desired_curvature, model_v2.action.desiredCurvature)
|
self.desired_curvature = clip_curvature(CS.vEgo, self.desired_curvature, model_v2.action.desiredCurvature)
|
||||||
actuators.curvature = self.desired_curvature
|
actuators.curvature = float(self.desired_curvature)
|
||||||
actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp,
|
steer, steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp,
|
||||||
self.steer_limited, self.desired_curvature,
|
self.steer_limited, self.desired_curvature,
|
||||||
self.calibrated_pose) # TODO what if not available
|
self.calibrated_pose) # TODO what if not available
|
||||||
|
actuators.steer = float(steer)
|
||||||
|
actuators.steeringAngleDeg = float(steeringAngleDeg)
|
||||||
# Ensure no NaNs/Infs
|
# Ensure no NaNs/Infs
|
||||||
for p in ACTUATOR_FIELDS:
|
for p in ACTUATOR_FIELDS:
|
||||||
attr = getattr(actuators, p)
|
attr = getattr(actuators, p)
|
||||||
@@ -192,7 +193,7 @@ class Controls:
|
|||||||
|
|
||||||
cs.longitudinalPlanMonoTime = self.sm.logMonoTime['longitudinalPlan']
|
cs.longitudinalPlanMonoTime = self.sm.logMonoTime['longitudinalPlan']
|
||||||
cs.lateralPlanMonoTime = self.sm.logMonoTime['modelV2']
|
cs.lateralPlanMonoTime = self.sm.logMonoTime['modelV2']
|
||||||
cs.desiredCurvature = self.desired_curvature
|
cs.desiredCurvature = float(self.desired_curvature)
|
||||||
cs.longControlState = self.LoC.long_control_state
|
cs.longControlState = self.LoC.long_control_state
|
||||||
cs.upAccelCmd = float(self.LoC.pid.p)
|
cs.upAccelCmd = float(self.LoC.pid.p)
|
||||||
cs.uiAccelCmd = float(self.LoC.pid.i)
|
cs.uiAccelCmd = float(self.LoC.pid.i)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import numpy as np
|
||||||
from cereal import log
|
from cereal import log
|
||||||
from openpilot.common.numpy_fast import clip
|
|
||||||
from openpilot.common.realtime import DT_CTRL
|
from openpilot.common.realtime import DT_CTRL
|
||||||
|
|
||||||
MIN_SPEED = 1.0
|
MIN_SPEED = 1.0
|
||||||
@@ -13,10 +13,10 @@ MAX_LATERAL_JERK = 5.0
|
|||||||
MAX_VEL_ERR = 5.0
|
MAX_VEL_ERR = 5.0
|
||||||
|
|
||||||
def clip_curvature(v_ego, prev_curvature, new_curvature):
|
def clip_curvature(v_ego, prev_curvature, new_curvature):
|
||||||
new_curvature = clip(new_curvature, -MAX_CURVATURE, MAX_CURVATURE)
|
new_curvature = np.clip(new_curvature, -MAX_CURVATURE, MAX_CURVATURE)
|
||||||
v_ego = max(MIN_SPEED, v_ego)
|
v_ego = max(MIN_SPEED, v_ego)
|
||||||
max_curvature_rate = MAX_LATERAL_JERK / (v_ego**2) # inexact calculation, check https://github.com/commaai/openpilot/pull/24755
|
max_curvature_rate = MAX_LATERAL_JERK / (v_ego**2) # inexact calculation, check https://github.com/commaai/openpilot/pull/24755
|
||||||
safe_desired_curvature = clip(new_curvature,
|
safe_desired_curvature = np.clip(new_curvature,
|
||||||
prev_curvature - max_curvature_rate * DT_CTRL,
|
prev_curvature - max_curvature_rate * DT_CTRL,
|
||||||
prev_curvature + max_curvature_rate * DT_CTRL)
|
prev_curvature + max_curvature_rate * DT_CTRL)
|
||||||
|
|
||||||
@@ -26,6 +26,6 @@ def clip_curvature(v_ego, prev_curvature, new_curvature):
|
|||||||
def get_speed_error(modelV2: log.ModelDataV2, v_ego: float) -> float:
|
def get_speed_error(modelV2: log.ModelDataV2, v_ego: float) -> float:
|
||||||
# ToDo: Try relative error, and absolute speed
|
# ToDo: Try relative error, and absolute speed
|
||||||
if len(modelV2.temporalPose.trans):
|
if len(modelV2.temporalPose.trans):
|
||||||
vel_err = clip(modelV2.temporalPose.trans[0] - v_ego, -MAX_VEL_ERR, MAX_VEL_ERR)
|
vel_err = np.clip(modelV2.temporalPose.trans[0] - v_ego, -MAX_VEL_ERR, MAX_VEL_ERR)
|
||||||
return float(vel_err)
|
return float(vel_err)
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import numpy as np
|
||||||
from abc import abstractmethod, ABC
|
from abc import abstractmethod, ABC
|
||||||
|
|
||||||
from openpilot.common.numpy_fast import clip
|
|
||||||
from openpilot.common.realtime import DT_CTRL
|
from openpilot.common.realtime import DT_CTRL
|
||||||
|
|
||||||
MIN_LATERAL_CONTROL_SPEED = 0.3 # m/s
|
MIN_LATERAL_CONTROL_SPEED = 0.3 # m/s
|
||||||
@@ -28,5 +28,5 @@ class LatControl(ABC):
|
|||||||
self.sat_count += self.sat_count_rate
|
self.sat_count += self.sat_count_rate
|
||||||
else:
|
else:
|
||||||
self.sat_count -= self.sat_count_rate
|
self.sat_count -= self.sat_count_rate
|
||||||
self.sat_count = clip(self.sat_count, 0.0, self.sat_limit)
|
self.sat_count = np.clip(self.sat_count, 0.0, self.sat_limit)
|
||||||
return self.sat_count > (self.sat_limit - 1e-3)
|
return self.sat_count > (self.sat_limit - 1e-3)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class LatControlAngle(LatControl):
|
|||||||
angle_steers_des += params.angleOffsetDeg
|
angle_steers_des += params.angleOffsetDeg
|
||||||
|
|
||||||
angle_control_saturated = abs(angle_steers_des - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD
|
angle_control_saturated = abs(angle_steers_des - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD
|
||||||
angle_log.saturated = self._check_saturation(angle_control_saturated, CS, False)
|
angle_log.saturated = bool(self._check_saturation(angle_control_saturated, CS, False))
|
||||||
angle_log.steeringAngleDeg = float(CS.steeringAngleDeg)
|
angle_log.steeringAngleDeg = float(CS.steeringAngleDeg)
|
||||||
angle_log.steeringAngleDesiredDeg = angle_steers_des
|
angle_log.steeringAngleDesiredDeg = angle_steers_des
|
||||||
return 0, float(angle_steers_des), angle_log
|
return 0, float(angle_steers_des), angle_log
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ class LatControlPID(LatControl):
|
|||||||
output_steer = self.pid.update(error, override=CS.steeringPressed,
|
output_steer = self.pid.update(error, override=CS.steeringPressed,
|
||||||
feedforward=steer_feedforward, speed=CS.vEgo)
|
feedforward=steer_feedforward, speed=CS.vEgo)
|
||||||
pid_log.active = True
|
pid_log.active = True
|
||||||
pid_log.p = self.pid.p
|
pid_log.p = float(self.pid.p)
|
||||||
pid_log.i = self.pid.i
|
pid_log.i = float(self.pid.i)
|
||||||
pid_log.f = self.pid.f
|
pid_log.f = float(self.pid.f)
|
||||||
pid_log.output = output_steer
|
pid_log.output = float(output_steer)
|
||||||
pid_log.saturated = self._check_saturation(self.steer_max - abs(output_steer) < 1e-3, CS, steer_limited)
|
pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_steer) < 1e-3, CS, steer_limited))
|
||||||
|
|
||||||
return output_steer, angle_steers_des, pid_log
|
return output_steer, angle_steers_des, pid_log
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import math
|
import math
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from cereal import log
|
from cereal import log
|
||||||
from opendbc.car.interfaces import LatControlInputs
|
from opendbc.car.interfaces import LatControlInputs
|
||||||
from openpilot.common.numpy_fast import interp
|
|
||||||
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
|
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
|
||||||
from openpilot.common.pid import PIDController
|
from openpilot.common.pid import PIDController
|
||||||
from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
|
from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
|
||||||
@@ -51,7 +51,7 @@ class LatControlTorque(LatControl):
|
|||||||
else:
|
else:
|
||||||
assert calibrated_pose is not None
|
assert calibrated_pose is not None
|
||||||
actual_curvature_pose = calibrated_pose.angular_velocity.yaw / CS.vEgo
|
actual_curvature_pose = calibrated_pose.angular_velocity.yaw / CS.vEgo
|
||||||
actual_curvature = interp(CS.vEgo, [2.0, 5.0], [actual_curvature_vm, actual_curvature_pose])
|
actual_curvature = np.interp(CS.vEgo, [2.0, 5.0], [actual_curvature_vm, actual_curvature_pose])
|
||||||
curvature_deadzone = 0.0
|
curvature_deadzone = 0.0
|
||||||
desired_lateral_accel = desired_curvature * CS.vEgo ** 2
|
desired_lateral_accel = desired_curvature * CS.vEgo ** 2
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ class LatControlTorque(LatControl):
|
|||||||
actual_lateral_accel = actual_curvature * CS.vEgo ** 2
|
actual_lateral_accel = actual_curvature * CS.vEgo ** 2
|
||||||
lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2
|
lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2
|
||||||
|
|
||||||
low_speed_factor = interp(CS.vEgo, LOW_SPEED_X, LOW_SPEED_Y)**2
|
low_speed_factor = np.interp(CS.vEgo, LOW_SPEED_X, LOW_SPEED_Y)**2
|
||||||
setpoint = desired_lateral_accel + low_speed_factor * desired_curvature
|
setpoint = desired_lateral_accel + low_speed_factor * desired_curvature
|
||||||
measurement = actual_lateral_accel + low_speed_factor * actual_curvature
|
measurement = actual_lateral_accel + low_speed_factor * actual_curvature
|
||||||
gravity_adjusted_lateral_accel = desired_lateral_accel - roll_compensation
|
gravity_adjusted_lateral_accel = desired_lateral_accel - roll_compensation
|
||||||
@@ -68,7 +68,7 @@ class LatControlTorque(LatControl):
|
|||||||
setpoint, lateral_accel_deadzone, friction_compensation=False, gravity_adjusted=False)
|
setpoint, lateral_accel_deadzone, friction_compensation=False, gravity_adjusted=False)
|
||||||
torque_from_measurement = self.torque_from_lateral_accel(LatControlInputs(measurement, roll_compensation, CS.vEgo, CS.aEgo), self.torque_params,
|
torque_from_measurement = self.torque_from_lateral_accel(LatControlInputs(measurement, roll_compensation, CS.vEgo, CS.aEgo), self.torque_params,
|
||||||
measurement, lateral_accel_deadzone, friction_compensation=False, gravity_adjusted=False)
|
measurement, lateral_accel_deadzone, friction_compensation=False, gravity_adjusted=False)
|
||||||
pid_log.error = torque_from_setpoint - torque_from_measurement
|
pid_log.error = float(torque_from_setpoint - torque_from_measurement)
|
||||||
ff = self.torque_from_lateral_accel(LatControlInputs(gravity_adjusted_lateral_accel, roll_compensation, CS.vEgo, CS.aEgo), self.torque_params,
|
ff = self.torque_from_lateral_accel(LatControlInputs(gravity_adjusted_lateral_accel, roll_compensation, CS.vEgo, CS.aEgo), self.torque_params,
|
||||||
desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, friction_compensation=True,
|
desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, friction_compensation=True,
|
||||||
gravity_adjusted=True)
|
gravity_adjusted=True)
|
||||||
@@ -80,14 +80,14 @@ class LatControlTorque(LatControl):
|
|||||||
freeze_integrator=freeze_integrator)
|
freeze_integrator=freeze_integrator)
|
||||||
|
|
||||||
pid_log.active = True
|
pid_log.active = True
|
||||||
pid_log.p = self.pid.p
|
pid_log.p = float(self.pid.p)
|
||||||
pid_log.i = self.pid.i
|
pid_log.i = float(self.pid.i)
|
||||||
pid_log.d = self.pid.d
|
pid_log.d = float(self.pid.d)
|
||||||
pid_log.f = self.pid.f
|
pid_log.f = float(self.pid.f)
|
||||||
pid_log.output = -output_torque
|
pid_log.output = float(-output_torque)
|
||||||
pid_log.actualLateralAccel = actual_lateral_accel
|
pid_log.actualLateralAccel = float(actual_lateral_accel)
|
||||||
pid_log.desiredLateralAccel = desired_lateral_accel
|
pid_log.desiredLateralAccel = float(desired_lateral_accel)
|
||||||
pid_log.saturated = self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited)
|
pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited))
|
||||||
|
|
||||||
# TODO left is positive in this convention
|
# TODO left is positive in this convention
|
||||||
return -output_torque, 0.0, pid_log
|
return -output_torque, 0.0, pid_log
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import numpy as np
|
||||||
from cereal import car
|
from cereal import car
|
||||||
from openpilot.common.numpy_fast import clip
|
|
||||||
from openpilot.common.realtime import DT_CTRL
|
from openpilot.common.realtime import DT_CTRL
|
||||||
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N
|
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N
|
||||||
from openpilot.common.pid import PIDController
|
from openpilot.common.pid import PIDController
|
||||||
@@ -84,5 +84,5 @@ class LongControl:
|
|||||||
output_accel = self.pid.update(error, speed=CS.vEgo,
|
output_accel = self.pid.update(error, speed=CS.vEgo,
|
||||||
feedforward=a_target)
|
feedforward=a_target)
|
||||||
|
|
||||||
self.last_output_accel = clip(output_accel, accel_limits[0], accel_limits[1])
|
self.last_output_accel = np.clip(output_accel, accel_limits[0], accel_limits[1])
|
||||||
return self.last_output_accel
|
return self.last_output_accel
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import time
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from cereal import log
|
from cereal import log
|
||||||
from opendbc.car.interfaces import ACCEL_MIN
|
from opendbc.car.interfaces import ACCEL_MIN
|
||||||
from openpilot.common.numpy_fast import clip
|
|
||||||
from openpilot.common.realtime import DT_MDL
|
from openpilot.common.realtime import DT_MDL
|
||||||
from openpilot.common.swaglog import cloudlog
|
from openpilot.common.swaglog import cloudlog
|
||||||
# WARNING: imports outside of constants will not trigger a rebuild
|
# WARNING: imports outside of constants will not trigger a rebuild
|
||||||
@@ -320,9 +319,9 @@ class LongitudinalMpc:
|
|||||||
# MPC will not converge if immediate crash is expected
|
# MPC will not converge if immediate crash is expected
|
||||||
# Clip lead distance to what is still possible to brake for
|
# Clip lead distance to what is still possible to brake for
|
||||||
min_x_lead = ((v_ego + v_lead)/2) * (v_ego - v_lead) / (-ACCEL_MIN * 2)
|
min_x_lead = ((v_ego + v_lead)/2) * (v_ego - v_lead) / (-ACCEL_MIN * 2)
|
||||||
x_lead = clip(x_lead, min_x_lead, 1e8)
|
x_lead = np.clip(x_lead, min_x_lead, 1e8)
|
||||||
v_lead = clip(v_lead, 0.0, 1e8)
|
v_lead = np.clip(v_lead, 0.0, 1e8)
|
||||||
a_lead = clip(a_lead, -10., 5.)
|
a_lead = np.clip(a_lead, -10., 5.)
|
||||||
lead_xv = self.extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau)
|
lead_xv = self.extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau)
|
||||||
return lead_xv
|
return lead_xv
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from openpilot.common.numpy_fast import clip, interp
|
|
||||||
|
|
||||||
import cereal.messaging as messaging
|
import cereal.messaging as messaging
|
||||||
from opendbc.car.interfaces import ACCEL_MIN, ACCEL_MAX
|
from opendbc.car.interfaces import ACCEL_MIN, ACCEL_MAX
|
||||||
@@ -30,7 +29,7 @@ _A_TOTAL_MAX_BP = [20., 40.]
|
|||||||
|
|
||||||
|
|
||||||
def get_max_accel(v_ego):
|
def get_max_accel(v_ego):
|
||||||
return interp(v_ego, A_CRUISE_MAX_BP, A_CRUISE_MAX_VALS)
|
return np.interp(v_ego, A_CRUISE_MAX_BP, A_CRUISE_MAX_VALS)
|
||||||
|
|
||||||
def get_coast_accel(pitch):
|
def get_coast_accel(pitch):
|
||||||
return np.sin(pitch) * -5.65 - 0.3 # fitted from data using xx/projects/allow_throttle/compute_coast_accel.py
|
return np.sin(pitch) * -5.65 - 0.3 # fitted from data using xx/projects/allow_throttle/compute_coast_accel.py
|
||||||
@@ -43,7 +42,7 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP):
|
|||||||
"""
|
"""
|
||||||
# FIXME: This function to calculate lateral accel is incorrect and should use the VehicleModel
|
# FIXME: This function to calculate lateral accel is incorrect and should use the VehicleModel
|
||||||
# The lookup table for turns should also be updated if we do this
|
# The lookup table for turns should also be updated if we do this
|
||||||
a_total_max = interp(v_ego, _A_TOTAL_MAX_BP, _A_TOTAL_MAX_V)
|
a_total_max = np.interp(v_ego, _A_TOTAL_MAX_BP, _A_TOTAL_MAX_V)
|
||||||
a_y = v_ego ** 2 * angle_steers * CV.DEG_TO_RAD / (CP.steerRatio * CP.wheelbase)
|
a_y = v_ego ** 2 * angle_steers * CV.DEG_TO_RAD / (CP.steerRatio * CP.wheelbase)
|
||||||
a_x_allowed = math.sqrt(max(a_total_max ** 2 - a_y ** 2, 0.))
|
a_x_allowed = math.sqrt(max(a_total_max ** 2 - a_y ** 2, 0.))
|
||||||
|
|
||||||
@@ -55,9 +54,9 @@ def get_accel_from_plan(speeds, accels, action_t=DT_MDL, vEgoStopping=0.05):
|
|||||||
v_now = speeds[0]
|
v_now = speeds[0]
|
||||||
a_now = accels[0]
|
a_now = accels[0]
|
||||||
|
|
||||||
v_target = interp(action_t, CONTROL_N_T_IDX, speeds)
|
v_target = np.interp(action_t, CONTROL_N_T_IDX, speeds)
|
||||||
a_target = 2 * (v_target - v_now) / (action_t) - a_now
|
a_target = 2 * (v_target - v_now) / (action_t) - a_now
|
||||||
v_target_1sec = interp(action_t + 1.0, CONTROL_N_T_IDX, speeds)
|
v_target_1sec = np.interp(action_t + 1.0, CONTROL_N_T_IDX, speeds)
|
||||||
else:
|
else:
|
||||||
v_target = 0.0
|
v_target = 0.0
|
||||||
v_target_1sec = 0.0
|
v_target_1sec = 0.0
|
||||||
@@ -139,7 +138,7 @@ class LongitudinalPlanner:
|
|||||||
if reset_state:
|
if reset_state:
|
||||||
self.v_desired_filter.x = v_ego
|
self.v_desired_filter.x = v_ego
|
||||||
# Clip aEgo to cruise limits to prevent large accelerations when becoming active
|
# Clip aEgo to cruise limits to prevent large accelerations when becoming active
|
||||||
self.a_desired = clip(sm['carState'].aEgo, accel_limits[0], accel_limits[1])
|
self.a_desired = np.clip(sm['carState'].aEgo, accel_limits[0], accel_limits[1])
|
||||||
|
|
||||||
# Prevent divergence, smooth in current v_ego
|
# Prevent divergence, smooth in current v_ego
|
||||||
self.v_desired_filter.x = max(0.0, self.v_desired_filter.update(v_ego))
|
self.v_desired_filter.x = max(0.0, self.v_desired_filter.update(v_ego))
|
||||||
@@ -151,7 +150,7 @@ class LongitudinalPlanner:
|
|||||||
|
|
||||||
if not self.allow_throttle:
|
if not self.allow_throttle:
|
||||||
clipped_accel_coast = max(accel_coast, accel_limits_turns[0])
|
clipped_accel_coast = max(accel_coast, accel_limits_turns[0])
|
||||||
clipped_accel_coast_interp = interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_limits_turns[1], clipped_accel_coast])
|
clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_limits_turns[1], clipped_accel_coast])
|
||||||
accel_limits_turns[1] = min(accel_limits_turns[1], clipped_accel_coast_interp)
|
accel_limits_turns[1] = min(accel_limits_turns[1], clipped_accel_coast_interp)
|
||||||
|
|
||||||
if force_slow_decel:
|
if force_slow_decel:
|
||||||
@@ -176,7 +175,7 @@ class LongitudinalPlanner:
|
|||||||
|
|
||||||
# Interpolate 0.05 seconds and save as starting point for next iteration
|
# Interpolate 0.05 seconds and save as starting point for next iteration
|
||||||
a_prev = self.a_desired
|
a_prev = self.a_desired
|
||||||
self.a_desired = float(interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory))
|
self.a_desired = float(np.interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory))
|
||||||
self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0
|
self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0
|
||||||
|
|
||||||
def publish(self, sm, pm):
|
def publish(self, sm, pm):
|
||||||
@@ -200,9 +199,9 @@ class LongitudinalPlanner:
|
|||||||
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
|
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
|
||||||
a_target, should_stop = get_accel_from_plan(longitudinalPlan.speeds, longitudinalPlan.accels,
|
a_target, should_stop = get_accel_from_plan(longitudinalPlan.speeds, longitudinalPlan.accels,
|
||||||
action_t=action_t, vEgoStopping=self.CP.vEgoStopping)
|
action_t=action_t, vEgoStopping=self.CP.vEgoStopping)
|
||||||
longitudinalPlan.aTarget = a_target
|
longitudinalPlan.aTarget = float(a_target)
|
||||||
longitudinalPlan.shouldStop = should_stop
|
longitudinalPlan.shouldStop = bool(should_stop)
|
||||||
longitudinalPlan.allowBrake = True
|
longitudinalPlan.allowBrake = True
|
||||||
longitudinalPlan.allowThrottle = self.allow_throttle
|
longitudinalPlan.allowThrottle = bool(self.allow_throttle)
|
||||||
|
|
||||||
pm.send('longitudinalPlan', plan_send)
|
pm.send('longitudinalPlan', plan_send)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import math
|
import math
|
||||||
|
import numpy as np
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import capnp
|
import capnp
|
||||||
from cereal import messaging, log, car
|
from cereal import messaging, log, car
|
||||||
from openpilot.common.numpy_fast import interp
|
|
||||||
from openpilot.common.params import Params
|
from openpilot.common.params import Params
|
||||||
from openpilot.common.realtime import DT_MDL, Priority, config_realtime_process
|
from openpilot.common.realtime import DT_MDL, Priority, config_realtime_process
|
||||||
from openpilot.common.swaglog import cloudlog
|
from openpilot.common.swaglog import cloudlog
|
||||||
@@ -44,7 +44,7 @@ class KalmanParams:
|
|||||||
0.28144091, 0.27958406, 0.27783249, 0.27617149, 0.27458948, 0.27307714,
|
0.28144091, 0.27958406, 0.27783249, 0.27617149, 0.27458948, 0.27307714,
|
||||||
0.27162685, 0.27023228, 0.26888809, 0.26758976, 0.26633338, 0.26511557,
|
0.27162685, 0.27023228, 0.26888809, 0.26758976, 0.26633338, 0.26511557,
|
||||||
0.26393339, 0.26278425]
|
0.26393339, 0.26278425]
|
||||||
self.K = [[interp(dt, dts, K0)], [interp(dt, dts, K1)]]
|
self.K = [[np.interp(dt, dts, K0)], [np.interp(dt, dts, K1)]]
|
||||||
|
|
||||||
|
|
||||||
class Track:
|
class Track:
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
from subprocess import check_output, CalledProcessError
|
from subprocess import check_output, CalledProcessError
|
||||||
|
from opendbc.car.uds import UdsClient, MessageTimeoutError, SESSION_TYPE, DTC_GROUP_TYPE
|
||||||
from panda import Panda
|
from panda import Panda
|
||||||
from panda.python.uds import UdsClient, MessageTimeoutError, SESSION_TYPE, DTC_GROUP_TYPE
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="clear DTC status")
|
parser = argparse.ArgumentParser(description="clear DTC status")
|
||||||
parser.add_argument("addr", type=lambda x: int(x,0), nargs="?", default=0x7DF) # default is functional (broadcast) address
|
parser.add_argument("addr", type=lambda x: int(x,0), nargs="?", default=0x7DF) # default is functional (broadcast) address
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
from opendbc.car import uds
|
||||||
from openpilot.tools.lib.live_logreader import live_logreader
|
from openpilot.tools.lib.live_logreader import live_logreader
|
||||||
from openpilot.tools.lib.logreader import LogReader, ReadMode
|
from openpilot.tools.lib.logreader import LogReader, ReadMode
|
||||||
from panda.python import uds
|
|
||||||
|
|
||||||
|
|
||||||
def main(route: str | None, addrs: list[int]):
|
def main(route: str | None, addrs: list[int]):
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import argparse
|
|||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
from subprocess import check_output, CalledProcessError
|
from subprocess import check_output, CalledProcessError
|
||||||
|
|
||||||
|
from opendbc.car.uds import UdsClient, SESSION_TYPE, DATA_IDENTIFIER_TYPE
|
||||||
from panda.python import Panda
|
from panda.python import Panda
|
||||||
from panda.python.uds import UdsClient, SESSION_TYPE, DATA_IDENTIFIER_TYPE
|
|
||||||
|
|
||||||
class ConfigValues(NamedTuple):
|
class ConfigValues(NamedTuple):
|
||||||
default_config: bytes
|
default_config: bytes
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import argparse
|
import argparse
|
||||||
|
import numpy as np
|
||||||
import capnp
|
import capnp
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from cereal.messaging import SubMaster
|
from cereal.messaging import SubMaster
|
||||||
from openpilot.common.numpy_fast import mean
|
|
||||||
|
|
||||||
def cputime_total(ct):
|
def cputime_total(ct):
|
||||||
return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq
|
return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq
|
||||||
@@ -49,7 +49,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
if sm.updated['deviceState']:
|
if sm.updated['deviceState']:
|
||||||
t = sm['deviceState']
|
t = sm['deviceState']
|
||||||
last_temp = mean(t.cpuTempC)
|
last_temp = np.mean(t.cpuTempC)
|
||||||
last_mem = t.memoryUsagePercent
|
last_mem = t.memoryUsagePercent
|
||||||
|
|
||||||
if sm.updated['procLog']:
|
if sm.updated['procLog']:
|
||||||
@@ -72,7 +72,7 @@ if __name__ == "__main__":
|
|||||||
total_times = total_times_new[:]
|
total_times = total_times_new[:]
|
||||||
busy_times = busy_times_new[:]
|
busy_times = busy_times_new[:]
|
||||||
|
|
||||||
print(f"CPU {100.0 * mean(cores):.2f}% - RAM: {last_mem:.2f}% - Temp {last_temp:.2f}C")
|
print(f"CPU {100.0 * np.mean(cores):.2f}% - RAM: {last_mem:.2f}% - Temp {last_temp:.2f}C")
|
||||||
|
|
||||||
if args.cpu and prev_proclog is not None and prev_proclog_t is not None:
|
if args.cpu and prev_proclog is not None and prev_proclog_t is not None:
|
||||||
procs: dict[str, float] = defaultdict(float)
|
procs: dict[str, float] = defaultdict(float)
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
from subprocess import check_output, CalledProcessError
|
from subprocess import check_output, CalledProcessError
|
||||||
|
from opendbc.car.uds import UdsClient, SESSION_TYPE, DTC_REPORT_TYPE, DTC_STATUS_MASK_TYPE, get_dtc_num_as_str, get_dtc_status_names
|
||||||
from panda import Panda
|
from panda import Panda
|
||||||
from panda.python.uds import UdsClient, SESSION_TYPE, DTC_REPORT_TYPE, DTC_STATUS_MASK_TYPE
|
|
||||||
from panda.python.uds import get_dtc_num_as_str, get_dtc_status_names
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="read DTC status")
|
parser = argparse.ArgumentParser(description="read DTC status")
|
||||||
parser.add_argument("addr", type=lambda x: int(x,0))
|
parser.add_argument("addr", type=lambda x: int(x,0))
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import struct
|
import struct
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from panda import Panda
|
from opendbc.car.uds import UdsClient, MessageTimeoutError, NegativeResponseError, SESSION_TYPE,\
|
||||||
from panda.python.uds import UdsClient, MessageTimeoutError, NegativeResponseError, SESSION_TYPE,\
|
|
||||||
DATA_IDENTIFIER_TYPE, ACCESS_TYPE
|
DATA_IDENTIFIER_TYPE, ACCESS_TYPE
|
||||||
|
from panda import Panda
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
# TODO: extend UDS library to allow custom/vendor-defined data identifiers without ignoring type checks
|
# TODO: extend UDS library to allow custom/vendor-defined data identifiers without ignoring type checks
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import cereal.messaging as messaging
|
|||||||
from cereal import car, log
|
from cereal import car, log
|
||||||
from openpilot.common.params import Params
|
from openpilot.common.params import Params
|
||||||
from openpilot.common.realtime import config_realtime_process, DT_MDL
|
from openpilot.common.realtime import config_realtime_process, DT_MDL
|
||||||
from openpilot.common.numpy_fast import clip
|
|
||||||
from openpilot.selfdrive.locationd.models.car_kf import CarKalman, ObservationKind, States
|
from openpilot.selfdrive.locationd.models.car_kf import CarKalman, ObservationKind, States
|
||||||
from openpilot.selfdrive.locationd.models.constants import GENERATED_DIR
|
from openpilot.selfdrive.locationd.models.constants import GENERATED_DIR
|
||||||
from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose
|
from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose
|
||||||
@@ -66,7 +65,7 @@ class ParamsLearner:
|
|||||||
# This is done to bound the road roll estimate when localizer values are invalid
|
# This is done to bound the road roll estimate when localizer values are invalid
|
||||||
roll = 0.0
|
roll = 0.0
|
||||||
roll_std = np.radians(10.0)
|
roll_std = np.radians(10.0)
|
||||||
self.roll = clip(roll, self.roll - ROLL_MAX_DELTA, self.roll + ROLL_MAX_DELTA)
|
self.roll = np.clip(roll, self.roll - ROLL_MAX_DELTA, self.roll + ROLL_MAX_DELTA)
|
||||||
|
|
||||||
yaw_rate_valid = msg.angularVelocityDevice.valid and self.calibrator.calib_valid
|
yaw_rate_valid = msg.angularVelocityDevice.valid and self.calibrator.calib_valid
|
||||||
yaw_rate_valid = yaw_rate_valid and 0 < self.yaw_rate_std < 10 # rad/s
|
yaw_rate_valid = yaw_rate_valid and 0 < self.yaw_rate_std < 10 # rad/s
|
||||||
@@ -203,11 +202,11 @@ def main():
|
|||||||
learner = ParamsLearner(CP, CP.steerRatio, 1.0, 0.0)
|
learner = ParamsLearner(CP, CP.steerRatio, 1.0, 0.0)
|
||||||
x = learner.kf.x
|
x = learner.kf.x
|
||||||
|
|
||||||
angle_offset_average = clip(math.degrees(x[States.ANGLE_OFFSET].item()),
|
angle_offset_average = np.clip(math.degrees(x[States.ANGLE_OFFSET].item()),
|
||||||
angle_offset_average - MAX_ANGLE_OFFSET_DELTA, angle_offset_average + MAX_ANGLE_OFFSET_DELTA)
|
angle_offset_average - MAX_ANGLE_OFFSET_DELTA, angle_offset_average + MAX_ANGLE_OFFSET_DELTA)
|
||||||
angle_offset = clip(math.degrees(x[States.ANGLE_OFFSET].item() + x[States.ANGLE_OFFSET_FAST].item()),
|
angle_offset = np.clip(math.degrees(x[States.ANGLE_OFFSET].item() + x[States.ANGLE_OFFSET_FAST].item()),
|
||||||
angle_offset - MAX_ANGLE_OFFSET_DELTA, angle_offset + MAX_ANGLE_OFFSET_DELTA)
|
angle_offset - MAX_ANGLE_OFFSET_DELTA, angle_offset + MAX_ANGLE_OFFSET_DELTA)
|
||||||
roll = clip(float(x[States.ROAD_ROLL].item()), roll - ROLL_MAX_DELTA, roll + ROLL_MAX_DELTA)
|
roll = np.clip(float(x[States.ROAD_ROLL].item()), roll - ROLL_MAX_DELTA, roll + ROLL_MAX_DELTA)
|
||||||
roll_std = float(P[States.ROAD_ROLL].item())
|
roll_std = float(P[States.ROAD_ROLL].item())
|
||||||
if learner.active and learner.speed > LOW_ACTIVE_SPEED:
|
if learner.active and learner.speed > LOW_ACTIVE_SPEED:
|
||||||
# Account for the opposite signs of the yaw rates
|
# Account for the opposite signs of the yaw rates
|
||||||
@@ -226,9 +225,9 @@ def main():
|
|||||||
liveParameters.sensorValid = sensors_valid
|
liveParameters.sensorValid = sensors_valid
|
||||||
liveParameters.steerRatio = float(x[States.STEER_RATIO].item())
|
liveParameters.steerRatio = float(x[States.STEER_RATIO].item())
|
||||||
liveParameters.stiffnessFactor = float(x[States.STIFFNESS].item())
|
liveParameters.stiffnessFactor = float(x[States.STIFFNESS].item())
|
||||||
liveParameters.roll = roll
|
liveParameters.roll = float(roll)
|
||||||
liveParameters.angleOffsetAverageDeg = angle_offset_average
|
liveParameters.angleOffsetAverageDeg = float(angle_offset_average)
|
||||||
liveParameters.angleOffsetDeg = angle_offset
|
liveParameters.angleOffsetDeg = float(angle_offset)
|
||||||
liveParameters.valid = all((
|
liveParameters.valid = all((
|
||||||
avg_offset_valid,
|
avg_offset_valid,
|
||||||
total_offset_valid,
|
total_offset_valid,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ cdef extern from "common/clutil.h":
|
|||||||
cdef unsigned long CL_DEVICE_TYPE_DEFAULT
|
cdef unsigned long CL_DEVICE_TYPE_DEFAULT
|
||||||
cl_device_id cl_get_device_id(unsigned long)
|
cl_device_id cl_get_device_id(unsigned long)
|
||||||
cl_context cl_create_context(cl_device_id)
|
cl_context cl_create_context(cl_device_id)
|
||||||
|
void cl_release_context(cl_context)
|
||||||
|
|
||||||
cdef extern from "selfdrive/modeld/models/commonmodel.h":
|
cdef extern from "selfdrive/modeld/models/commonmodel.h":
|
||||||
cppclass ModelFrame:
|
cppclass ModelFrame:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from libc.stdint cimport uintptr_t
|
|||||||
|
|
||||||
from msgq.visionipc.visionipc cimport cl_mem
|
from msgq.visionipc.visionipc cimport cl_mem
|
||||||
from msgq.visionipc.visionipc_pyx cimport VisionBuf, CLContext as BaseCLContext
|
from msgq.visionipc.visionipc_pyx cimport VisionBuf, CLContext as BaseCLContext
|
||||||
from .commonmodel cimport CL_DEVICE_TYPE_DEFAULT, cl_get_device_id, cl_create_context
|
from .commonmodel cimport CL_DEVICE_TYPE_DEFAULT, cl_get_device_id, cl_create_context, cl_release_context
|
||||||
from .commonmodel cimport mat3, ModelFrame as cppModelFrame, DrivingModelFrame as cppDrivingModelFrame, MonitoringModelFrame as cppMonitoringModelFrame
|
from .commonmodel cimport mat3, ModelFrame as cppModelFrame, DrivingModelFrame as cppDrivingModelFrame, MonitoringModelFrame as cppMonitoringModelFrame
|
||||||
|
|
||||||
|
|
||||||
@@ -17,6 +17,10 @@ cdef class CLContext(BaseCLContext):
|
|||||||
self.device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT)
|
self.device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT)
|
||||||
self.context = cl_create_context(self.device_id)
|
self.context = cl_create_context(self.device_id)
|
||||||
|
|
||||||
|
def __dealloc__(self):
|
||||||
|
if self.context:
|
||||||
|
cl_release_context(self.context)
|
||||||
|
|
||||||
cdef class CLMem:
|
cdef class CLMem:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
cdef create(void * cmem):
|
cdef create(void * cmem):
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from math import atan2
|
from math import atan2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from cereal import car, log
|
from cereal import car, log
|
||||||
import cereal.messaging as messaging
|
import cereal.messaging as messaging
|
||||||
from openpilot.selfdrive.selfdrived.events import Events
|
from openpilot.selfdrive.selfdrived.events import Events
|
||||||
from openpilot.common.numpy_fast import interp
|
|
||||||
from openpilot.common.realtime import DT_DMON
|
from openpilot.common.realtime import DT_DMON
|
||||||
from openpilot.common.filter_simple import FirstOrderFilter
|
from openpilot.common.filter_simple import FirstOrderFilter
|
||||||
from openpilot.common.stat_live import RunningStatFilter
|
from openpilot.common.stat_live import RunningStatFilter
|
||||||
@@ -205,10 +205,10 @@ class DriverMonitoring:
|
|||||||
bp = model_data.meta.disengagePredictions.brakeDisengageProbs[0] # brake disengage prob in next 2s
|
bp = model_data.meta.disengagePredictions.brakeDisengageProbs[0] # brake disengage prob in next 2s
|
||||||
k1 = max(-0.00156*((car_speed-16)**2)+0.6, 0.2)
|
k1 = max(-0.00156*((car_speed-16)**2)+0.6, 0.2)
|
||||||
bp_normal = max(min(bp / k1, 0.5),0)
|
bp_normal = max(min(bp / k1, 0.5),0)
|
||||||
self.pose.cfactor_pitch = interp(bp_normal, [0, 0.5],
|
self.pose.cfactor_pitch = np.interp(bp_normal, [0, 0.5],
|
||||||
[self.settings._POSE_PITCH_THRESHOLD_SLACK,
|
[self.settings._POSE_PITCH_THRESHOLD_SLACK,
|
||||||
self.settings._POSE_PITCH_THRESHOLD_STRICT]) / self.settings._POSE_PITCH_THRESHOLD
|
self.settings._POSE_PITCH_THRESHOLD_STRICT]) / self.settings._POSE_PITCH_THRESHOLD
|
||||||
self.pose.cfactor_yaw = interp(bp_normal, [0, 0.5],
|
self.pose.cfactor_yaw = np.interp(bp_normal, [0, 0.5],
|
||||||
[self.settings._POSE_YAW_THRESHOLD_SLACK,
|
[self.settings._POSE_YAW_THRESHOLD_SLACK,
|
||||||
self.settings._POSE_YAW_THRESHOLD_STRICT]) / self.settings._POSE_YAW_THRESHOLD
|
self.settings._POSE_YAW_THRESHOLD_STRICT]) / self.settings._POSE_YAW_THRESHOLD
|
||||||
|
|
||||||
|
|||||||
@@ -1063,6 +1063,10 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
|||||||
|
|
||||||
EventName.hyundaiRadarTracksConfirmed: {
|
EventName.hyundaiRadarTracksConfirmed: {
|
||||||
ET.PERMANENT: NormalPermanentAlert("Radar tracks available. Restart the car to initialize")
|
ET.PERMANENT: NormalPermanentAlert("Radar tracks available. Restart the car to initialize")
|
||||||
|
},
|
||||||
|
|
||||||
|
EventName.experimentalModeSwitched: {
|
||||||
|
ET.WARNING: NormalPermanentAlert("Experimental Mode Switched", duration=1.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ from openpilot.system.version import get_build_metadata
|
|||||||
|
|
||||||
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
|
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
|
||||||
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
|
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
|
||||||
|
from openpilot.sunnypilot.selfdrive.car.experimental_switcher import ExperimentalSwitcher
|
||||||
|
|
||||||
REPLAY = "REPLAY" in os.environ
|
REPLAY = "REPLAY" in os.environ
|
||||||
SIMULATION = "SIMULATION" in os.environ
|
SIMULATION = "SIMULATION" in os.environ
|
||||||
@@ -44,7 +45,7 @@ SafetyModel = car.CarParams.SafetyModel
|
|||||||
IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
|
IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
|
||||||
|
|
||||||
|
|
||||||
class SelfdriveD:
|
class SelfdriveD(ExperimentalSwitcher):
|
||||||
def __init__(self, CP=None):
|
def __init__(self, CP=None):
|
||||||
self.params = Params()
|
self.params = Params()
|
||||||
|
|
||||||
@@ -140,6 +141,8 @@ class SelfdriveD:
|
|||||||
|
|
||||||
self.car_events_sp = CarSpecificEventsSP(self.CP, self.params)
|
self.car_events_sp = CarSpecificEventsSP(self.CP, self.params)
|
||||||
|
|
||||||
|
ExperimentalSwitcher.__init__(self, self.params)
|
||||||
|
|
||||||
def update_events(self, CS):
|
def update_events(self, CS):
|
||||||
"""Compute onroadEvents from carState"""
|
"""Compute onroadEvents from carState"""
|
||||||
|
|
||||||
@@ -367,12 +370,18 @@ class SelfdriveD:
|
|||||||
if self.sm['modelV2'].frameDropPerc > 20:
|
if self.sm['modelV2'].frameDropPerc > 20:
|
||||||
self.events.add(EventName.modeldLagging)
|
self.events.add(EventName.modeldLagging)
|
||||||
|
|
||||||
|
# toggle experimental mode once on distance button hold
|
||||||
|
if self.CP.openpilotLongitudinalControl:
|
||||||
|
ExperimentalSwitcher.update(self, CS, self.events, self.experimental_mode)
|
||||||
|
|
||||||
# decrement personality on distance button press
|
# decrement personality on distance button press
|
||||||
if self.CP.openpilotLongitudinalControl:
|
if self.CP.openpilotLongitudinalControl:
|
||||||
if any(not be.pressed and be.type == ButtonType.gapAdjustCruise for be in CS.buttonEvents):
|
if any(not be.pressed and be.type == ButtonType.gapAdjustCruise for be in CS.buttonEvents):
|
||||||
self.personality = (self.personality - 1) % 3
|
if not self.experimental_mode_switched:
|
||||||
self.params.put_nonblocking('LongitudinalPersonality', str(self.personality))
|
self.personality = (self.personality - 1) % 3
|
||||||
self.events.add(EventName.personalityChanged)
|
self.params.put_nonblocking('LongitudinalPersonality', str(self.personality))
|
||||||
|
self.events.add(EventName.personalityChanged)
|
||||||
|
self.experimental_mode_switched = False
|
||||||
|
|
||||||
def data_sample(self):
|
def data_sample(self):
|
||||||
car_state = messaging.recv_one(self.car_state_sock)
|
car_state = messaging.recv_one(self.car_state_sock)
|
||||||
@@ -452,6 +461,7 @@ class SelfdriveD:
|
|||||||
ss.alertStatus = self.AM.current_alert.alert_status
|
ss.alertStatus = self.AM.current_alert.alert_status
|
||||||
ss.alertType = self.AM.current_alert.alert_type
|
ss.alertType = self.AM.current_alert.alert_type
|
||||||
ss.alertSound = self.AM.current_alert.audible_alert
|
ss.alertSound = self.AM.current_alert.audible_alert
|
||||||
|
ss.alertHudVisual = self.AM.current_alert.visual_alert
|
||||||
|
|
||||||
self.pm.send('selfdriveState', ss_msg)
|
self.pm.send('selfdriveState', ss_msg)
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class Plant:
|
|||||||
ss.selfdriveState.personality = self.personality
|
ss.selfdriveState.personality = self.personality
|
||||||
control.controlsState.forceDecel = self.force_decel
|
control.controlsState.forceDecel = self.force_decel
|
||||||
car_state.carState.vEgo = float(self.speed)
|
car_state.carState.vEgo = float(self.speed)
|
||||||
car_state.carState.standstill = self.speed < 0.01
|
car_state.carState.standstill = bool(self.speed < 0.01)
|
||||||
car_state.carState.vCruise = float(v_cruise * 3.6)
|
car_state.carState.vCruise = float(v_cruise * 3.6)
|
||||||
car_control.carControl.orientationNED = [0., float(pitch), 0.]
|
car_control.carControl.orientationNED = [0., float(pitch), 0.]
|
||||||
|
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:eb4235545588e617a82d698721503bdd048a5858da9d60b9b90eeecc8c969498
|
||||||
|
size 356186
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:79ccc3bd2094ba8a55adedf0007b0152eb3a68edc5e2d35aeccbba122d5811c6
|
|
||||||
size 356151
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c02a2432cb761440b9b5a0e432a13f05f5b03b9890bc5fe99f6c533be4f459f1
|
||||||
|
size 256426
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:45f39fe1d1dc8c271f577d1a12812e01da34979bf3fffaad01a19a7a61b6d456
|
|
||||||
size 256342
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:f7b1411e8b4a91b4df94322023d83f5f2f27245fa761db73ffafd06b91068062
|
||||||
|
size 284390
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:531fae8fa368a3edbcd291174d501095c1760d20ecbf1963f3eb5ce80163251f
|
|
||||||
size 284311
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:58c05f3c0b39e0525a586598982923b13e9b54c5ec9f41f87d88156552374a71
|
||||||
|
size 332428
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:ec8f8d879b38a4c8d4319a3bd67872d5e5d348bc5472443c4c8aa1cb1dd62cf5
|
|
||||||
size 332404
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d66335e9f34ac3baff73188c5042e2292c42979d9c6769a7953ecd17dc9e3956
|
||||||
|
size 268874
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:68afd54dc68f6abff699d2740f90830b0f492db8818869e8936a63e7bed80458
|
|
||||||
size 268827
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:fc70028fe66f0292f208dc4449e9f1291f5b28a8c44ebf8076f24b690364d256
|
||||||
|
size 435674
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:32a458c0b364c1c793a4a843fe7a8fd21dd4ad45ff87dc8ad41a8e8759e52c80
|
|
||||||
size 437811
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:11025e5a2cc0c21c3525dd002b4834db18006016a606b7ad83e7ec2c2aa8d710
|
||||||
|
size 308599
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:7b3d412d4066f9ac90788e11a20d99ea3ff92eafdc8a317610b7d9c918aedd59
|
|
||||||
size 308644
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:177c3c81df0a10f4e56122196ecfc2ebc807491171b405f7caa4f62363856c7a
|
||||||
|
size 393110
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:8ad0c3881d7d88f9038a1b3a5e43c779e84dca47e2f7f6d45a3449cd8a7dec99
|
|
||||||
size 393122
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d35c3b33f528bfcd9f15b53a41031c37d47739604b4b6f721670af44df901280
|
||||||
|
size 334227
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:6a0f9dc3743e4e09375f7a3289228b64486915ae4ef6dfcff66572a34820d5d2
|
|
||||||
size 334502
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:572a2b5a4ea929451b3f6aaa8786029f198eb3f3d823ba72e579a791fd0c8af8
|
||||||
|
size 470462
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:944406ae64efb422b568437588fec6a8a8b5b7d9e577dc1d22c83a1d6d3813ff
|
|
||||||
size 470417
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e55efae47740ead32d95e4d1c677ce07f95441c5cfea72a80c7f2a5cda996633
|
||||||
|
size 260412
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:d80c61dc2a0b3685a522013c8aa8347adfdfc6d0611485da88b3a17771c68301
|
|
||||||
size 260913
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:ed0cfd5fff468b94c14ea0d965b0a6d9f827b14f31c87657f4015137f7811e82
|
||||||
|
size 29648
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:074f0bbd96d130e2350d6a3db872696cd35a4c2fe7e32845b53698528a500587
|
|
||||||
size 29645
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4223262ea5da92b081a6024d135c2ed892901363c7b2b8be0b121578ee9eb4aa
|
||||||
|
size 234609
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:1c4ddf166d015b6886ee3250c977ff1d37542a6a3b364dc58316b30f21dbe56d
|
|
||||||
size 234433
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:3b1ed44ae652a3eeb4786c989219e2fd09e0755b5003ca53ba1c0ec01cd7d8c0
|
||||||
|
size 217471
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:3271e31149f7053d134d3a0217851167e573647a8b415138e8c80d429d0a02c9
|
|
||||||
size 217488
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:05249897ed80e89bfecd69f3719ce6e58112994718d0e0a02b0cd1003beab761
|
||||||
|
size 293036
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:35c95eaf222affae2e236f0b717c17e7f3b8a30e85d4ebb4ad1506e5025ce0b8
|
|
||||||
size 293078
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4b1514a19e37f8bcf252380a258633f2496f1c038cc3411aff10bbc934a0ae0e
|
||||||
|
size 260925
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:c8c8fe4943bba5bc86dd0116f75ac6b4fbae551c65ff530a5f62ee6e44b96314
|
|
||||||
size 259680
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1b602ecb28c53366eddb90efec1e2560f2ce021cf9d6d7a2fbd2fb4d06f0db86
|
||||||
|
size 29487
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:02117e335193889d0d13027de4755896bd6f401951e85564169fd4354e1cd523
|
|
||||||
size 29479
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e48e881d04b6aeec25b07b3f6c6b7c38eeac10877b50b3c6a909e579a18a4f57
|
||||||
|
size 102222
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:7701c8d0230dbf234da6e8ee954cd81e67b0a735e98441abe19f6b08a89b84e7
|
|
||||||
size 102213
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c97c909cce68a14b255c91d7dac8cd29aa4e73537d0b4ca4dddd1954471713bb
|
||||||
|
size 100071
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:396e46dfc38ea8f9b513ce81cc6019e76a51cca733360b662cc2c5d0933584d5
|
|
||||||
size 100090
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user