Compare commits

...

42 Commits

Author SHA1 Message Date
firestar5683 4795656d6c User adjustable offsets 2026-02-07 23:34:03 -06:00
firestar5683 8cb3ded338 Integrator Smooth On Handoff 2026-02-06 15:48:11 -06:00
firestar5683 17d5f8d611 Malibu ASCM Fingerprint 2026-02-06 12:29:39 -06:00
firestar5683 c77a3f2e6a Lights 2026-02-05 22:40:31 -06:00
firestar5683 1f4ad6a588 New Models 2026-02-05 15:06:41 -06:00
firestar5683 fe8f2ef2db Increase Fault Resilience 2026-02-05 13:35:58 -06:00
firestarsdog 6adacfdbf6 Stats 2026-02-01 22:46:48 -06:00
firestar5683 5b8df0f73c Revert "Mac Update"
This reverts commit bfc24b8882.
2026-01-19 11:42:32 -06:00
firestarsdog be969f716c Add SASCM to vehicle settings detection/stats 2026-01-19 10:34:34 -06:00
firestar5683 bfc24b8882 Mac Update 2026-01-18 22:22:34 -06:00
firestarsdog 165ee6eb68 Stats 2026-01-18 22:17:25 -06:00
firestar5683 48b44ed1e4 Update redneck 2026-01-15 22:53:42 -06:00
firestar5683 437979e0f4 fix redneck v2 2026-01-14 13:59:35 -06:00
firestar5683 499e77ce23 Remove lat smooth seconds 2026-01-14 13:50:26 -06:00
firestar5683 1068bf2644 frogpilot migration 2026-01-12 22:10:56 -06:00
firestar5683 51eb994927 Update defaults 2026-01-12 22:05:26 -06:00
firestar5683 0a1916d08f More defaults 2026-01-12 22:05:18 -06:00
firestar5683 6b0ca6ef8d Big Mac 2026-01-11 16:59:12 -06:00
firestar5683 edd8257985 Try Higher Friction 2026-01-10 14:04:54 -06:00
firestar5683 2f779de7f1 Autotune Off 2026-01-09 22:44:21 -06:00
firestar5683 642d43c764 merry christmas 2025-12-24 22:23:54 -06:00
firestar5683 26486e5f6a ds2 2025-12-24 21:28:57 -06:00
firestar5683 c35c687bfc No sub? 2025-12-18 12:29:34 -06:00
firestar5683 9be6134a5b Use new torque Controller 2025-12-16 22:12:57 -06:00
firestar5683 ba7d5f7ab7 Fix Volt 2019? 2025-12-16 17:18:19 -06:00
firestar5683 b094ebf9f2 Update interface.py 2025-12-16 16:34:52 -06:00
firestar5683 e24df5c403 volt 2019 torquetune 2025-12-16 14:45:18 -06:00
firestar5683 87160b52f9 Try friction adjustment 2025-12-16 14:38:40 -06:00
firestar5683 ddd2a8fadd Red Panda 2025-12-15 14:55:02 -06:00
firestar5683 1470baffa7 Update frogpilot_tracking.py 2025-12-15 00:55:44 -06:00
firestar5683 24cccabeb1 minsteer speed 2025-12-14 14:46:33 -06:00
firestar5683 649a9f648c test 2025-12-13 23:51:39 -06:00
firestar5683 f2fbcb5539 Reapply "Rest of Fleet V2"
This reverts commit db3fbcb687.
2025-12-13 23:51:12 -06:00
firestar5683 db3fbcb687 Revert "Rest of Fleet V2"
This reverts commit 22eb74e4c8.
2025-12-13 23:50:15 -06:00
firestar5683 22eb74e4c8 Rest of Fleet V2 2025-12-13 23:44:46 -06:00
firestar5683 214b6ab711 Update values.py 2025-12-13 23:23:00 -06:00
firestar5683 1b49bafc0d Reapply "Gas"
This reverts commit 08e1ee83ae.
2025-12-13 23:08:16 -06:00
firestar5683 896b3bb454 Revert "Torque Rest of Fleet"
This reverts commit eee41cbf77.
2025-12-13 23:08:03 -06:00
firestar5683 08e1ee83ae Revert "Gas"
This reverts commit 43818e0d48.
2025-12-13 22:57:55 -06:00
firestar5683 92fbc1ceb3 Update Percentages 2025-12-13 19:13:49 -06:00
firestar5683 43818e0d48 Gas 2025-12-13 19:07:17 -06:00
firestar5683 eee41cbf77 Torque Rest of Fleet 2025-12-13 18:51:46 -06:00
67 changed files with 1013 additions and 245 deletions
+1 -1
View File
@@ -105,7 +105,7 @@ struct FrogPilotCarParams @0xf35cc4560bbf6ec2 {
isHDA2 @3 :Bool;
openpilotLongitudinalControlDisabled @4 :Bool;
safetyConfigs @5 :List(SafetyConfig);
canUseSASCM @6 :Bool;
struct SafetyConfig {
safetyParam @0 :UInt16;
+51 -35
View File
@@ -642,7 +642,7 @@ const ::capnp::_::RawSchema s_aedffd8f31e7b55d = {
};
#endif // !CAPNP_LITE
CAPNP_DEFINE_ENUM(EventName_aedffd8f31e7b55d, aedffd8f31e7b55d);
static const ::capnp::_::AlignedData<123> b_f35cc4560bbf6ec2 = {
static const ::capnp::_::AlignedData<139> b_f35cc4560bbf6ec2 = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
194, 110, 191, 11, 86, 196, 92, 243,
13, 0, 0, 0, 1, 0, 1, 0,
@@ -652,7 +652,7 @@ static const ::capnp::_::AlignedData<123> b_f35cc4560bbf6ec2 = {
21, 0, 0, 0, 2, 1, 0, 0,
33, 0, 0, 0, 23, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
45, 0, 0, 0, 87, 1, 0, 0,
45, 0, 0, 0, 143, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
99, 117, 115, 116, 111, 109, 46, 99,
@@ -664,49 +664,56 @@ static const ::capnp::_::AlignedData<123> b_f35cc4560bbf6ec2 = {
1, 0, 0, 0, 106, 0, 0, 0,
83, 97, 102, 101, 116, 121, 67, 111,
110, 102, 105, 103, 0, 0, 0, 0,
24, 0, 0, 0, 3, 0, 4, 0,
28, 0, 0, 0, 3, 0, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
153, 0, 0, 0, 98, 0, 0, 0,
181, 0, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
152, 0, 0, 0, 3, 0, 1, 0,
164, 0, 0, 0, 2, 0, 1, 0,
180, 0, 0, 0, 3, 0, 1, 0,
192, 0, 0, 0, 2, 0, 1, 0,
1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
161, 0, 0, 0, 90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
160, 0, 0, 0, 3, 0, 1, 0,
172, 0, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
169, 0, 0, 0, 66, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
164, 0, 0, 0, 3, 0, 1, 0,
176, 0, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
173, 0, 0, 0, 58, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
168, 0, 0, 0, 3, 0, 1, 0,
180, 0, 0, 0, 2, 0, 1, 0,
4, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
177, 0, 0, 0, 42, 1, 0, 0,
189, 0, 0, 0, 90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
188, 0, 0, 0, 3, 0, 1, 0,
200, 0, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
197, 0, 0, 0, 66, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
192, 0, 0, 0, 3, 0, 1, 0,
204, 0, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
201, 0, 0, 0, 58, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
196, 0, 0, 0, 3, 0, 1, 0,
208, 0, 0, 0, 2, 0, 1, 0,
4, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
205, 0, 0, 0, 42, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
216, 0, 0, 0, 3, 0, 1, 0,
228, 0, 0, 0, 2, 0, 1, 0,
5, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
197, 0, 0, 0, 114, 0, 0, 0,
225, 0, 0, 0, 114, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
196, 0, 0, 0, 3, 0, 1, 0,
224, 0, 0, 0, 2, 0, 1, 0,
224, 0, 0, 0, 3, 0, 1, 0,
252, 0, 0, 0, 2, 0, 1, 0,
6, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
249, 0, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
248, 0, 0, 0, 3, 0, 1, 0,
4, 1, 0, 0, 2, 0, 1, 0,
99, 97, 110, 85, 115, 101, 80, 101,
100, 97, 108, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
@@ -764,6 +771,15 @@ static const ::capnp::_::AlignedData<123> b_f35cc4560bbf6ec2 = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
14, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
99, 97, 110, 85, 115, 101, 83, 65,
83, 67, 77, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
@@ -772,11 +788,11 @@ static const ::capnp::_::AlignedData<123> b_f35cc4560bbf6ec2 = {
static const ::capnp::_::RawSchema* const d_f35cc4560bbf6ec2[] = {
&s_8d65dd40bad40951,
};
static const uint16_t m_f35cc4560bbf6ec2[] = {0, 1, 2, 3, 4, 5};
static const uint16_t i_f35cc4560bbf6ec2[] = {0, 1, 2, 3, 4, 5};
static const uint16_t m_f35cc4560bbf6ec2[] = {0, 6, 1, 2, 3, 4, 5};
static const uint16_t i_f35cc4560bbf6ec2[] = {0, 1, 2, 3, 4, 5, 6};
const ::capnp::_::RawSchema s_f35cc4560bbf6ec2 = {
0xf35cc4560bbf6ec2, b_f35cc4560bbf6ec2.words, 123, d_f35cc4560bbf6ec2, m_f35cc4560bbf6ec2,
1, 6, i_f35cc4560bbf6ec2, nullptr, nullptr, { &s_f35cc4560bbf6ec2, nullptr, nullptr, 0, 0, nullptr }, false
0xf35cc4560bbf6ec2, b_f35cc4560bbf6ec2.words, 139, d_f35cc4560bbf6ec2, m_f35cc4560bbf6ec2,
1, 7, i_f35cc4560bbf6ec2, nullptr, nullptr, { &s_f35cc4560bbf6ec2, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<36> b_8d65dd40bad40951 = {
+19
View File
@@ -669,6 +669,8 @@ public:
inline bool hasSafetyConfigs() const;
inline ::capnp::List< ::cereal::FrogPilotCarParams::SafetyConfig, ::capnp::Kind::STRUCT>::Reader getSafetyConfigs() const;
inline bool getCanUseSASCM() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -719,6 +721,9 @@ public:
inline void adoptSafetyConfigs(::capnp::Orphan< ::capnp::List< ::cereal::FrogPilotCarParams::SafetyConfig, ::capnp::Kind::STRUCT>>&& value);
inline ::capnp::Orphan< ::capnp::List< ::cereal::FrogPilotCarParams::SafetyConfig, ::capnp::Kind::STRUCT>> disownSafetyConfigs();
inline bool getCanUseSASCM();
inline void setCanUseSASCM(bool value);
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -2220,6 +2225,20 @@ inline ::capnp::Orphan< ::capnp::List< ::cereal::FrogPilotCarParams::SafetyConfi
::capnp::bounded<0>() * ::capnp::POINTERS));
}
inline bool FrogPilotCarParams::Reader::getCanUseSASCM() const {
return _reader.getDataField<bool>(
::capnp::bounded<4>() * ::capnp::ELEMENTS);
}
inline bool FrogPilotCarParams::Builder::getCanUseSASCM() {
return _builder.getDataField<bool>(
::capnp::bounded<4>() * ::capnp::ELEMENTS);
}
inline void FrogPilotCarParams::Builder::setCanUseSASCM(bool value) {
_builder.setDataField<bool>(
::capnp::bounded<4>() * ::capnp::ELEMENTS, value);
}
inline ::uint16_t FrogPilotCarParams::SafetyConfig::Reader::getSafetyParam() const {
return _reader.getDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
Binary file not shown.
+2
View File
@@ -535,6 +535,8 @@ std::unordered_map<std::string, uint32_t> keys = {
{"SteerDelayStock", PERSISTENT},
{"SteerFriction", PERSISTENT},
{"SteerFrictionStock", PERSISTENT},
{"SteerOffset", PERSISTENT},
{"SteerOffsetStock", PERSISTENT},
{"SteerLatAccel", PERSISTENT},
{"SteerLatAccelStock", PERSISTENT},
{"SteerKP", PERSISTENT},
Binary file not shown.
+24 -4
View File
@@ -107,7 +107,7 @@ class ModelManager:
self.downloading_model = False
return
if model_version in ("v8", "v9", "v10", "v11"):
if model_version in ("v8", "v9", "v10", "v11", "v12"):
# Download all PKL and metadata files for multi-file tinygrad models (v8 and v9)
filenames = [
f"{model_to_download}_driving_policy_tinygrad.pkl",
@@ -115,6 +115,11 @@ class ModelManager:
f"{model_to_download}_driving_policy_metadata.pkl",
f"{model_to_download}_driving_vision_metadata.pkl",
]
if model_version == "v12":
filenames += [
f"{model_to_download}_driving_off_policy_tinygrad.pkl",
f"{model_to_download}_driving_off_policy_metadata.pkl",
]
for filename in filenames:
model_path = MODELS_PATH / filename
model_url = f"{repo_url}/Models/{filename}"
@@ -208,13 +213,18 @@ class ModelManager:
except Exception:
model_version = None
if model_version in ("v8", "v9", "v10", "v11"):
if model_version in ("v8", "v9", "v10", "v11", "v12"):
v8_v9_files = [
f"{model}_driving_policy_tinygrad.pkl",
f"{model}_driving_vision_tinygrad.pkl",
f"{model}_driving_policy_metadata.pkl",
f"{model}_driving_vision_metadata.pkl",
]
if model_version == "v12":
v8_v9_files += [
f"{model}_driving_off_policy_tinygrad.pkl",
f"{model}_driving_off_policy_metadata.pkl",
]
if all((MODELS_PATH / f).is_file() for f in v8_v9_files):
downloaded_models.add(model)
elif model_version == "v7":
@@ -259,13 +269,18 @@ class ModelManager:
except Exception:
model_version = None
if model_version in ("v8", "v9", "v10", "v11"):
if model_version in ("v8", "v9", "v10", "v11", "v12"):
v8_v9_files = [
f"{model}_driving_policy_tinygrad.pkl",
f"{model}_driving_vision_tinygrad.pkl",
f"{model}_driving_policy_metadata.pkl",
f"{model}_driving_vision_metadata.pkl",
]
if model_version == "v12":
v8_v9_files += [
f"{model}_driving_off_policy_tinygrad.pkl",
f"{model}_driving_off_policy_metadata.pkl",
]
for filename in v8_v9_files:
path = MODELS_PATH / filename
expected_size = model_sizes.get(filename.rsplit(".", 1)[0])
@@ -378,13 +393,18 @@ class ModelManager:
handle_error(None, "Download cancelled...", "Download cancelled...", MODEL_DOWNLOAD_ALL_PARAM, DOWNLOAD_PROGRESS_PARAM, params_memory)
return
if model_version in ("v8", "v9", "v10", "v11"):
if model_version in ("v8", "v9", "v10", "v11", "v12"):
required_files = [
f"{model}_driving_policy_tinygrad.pkl",
f"{model}_driving_vision_tinygrad.pkl",
f"{model}_driving_policy_metadata.pkl",
f"{model}_driving_vision_metadata.pkl",
]
if model_version == "v12":
required_files += [
f"{model}_driving_off_policy_tinygrad.pkl",
f"{model}_driving_off_policy_metadata.pkl",
]
missing = [f for f in required_files if not (MODELS_PATH / f).is_file()]
if missing:
print(f"Tinygrad model {model} is missing files. Preparing to download...")
Binary file not shown.

Before

Width:  |  Height:  |  Size: 875 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

+17 -10
View File
@@ -96,6 +96,8 @@ EXCLUDED_KEYS = {
}
TINYGRAD_FILES = [
("driving_off_policy_metadata.pkl", "off-policy metadata"),
("driving_off_policy_tinygrad.pkl", "off-policy model"),
("driving_policy_metadata.pkl", "policy metadata"),
("driving_policy_tinygrad.pkl", "policy model"),
("driving_vision_metadata.pkl", "vision metadata"),
@@ -128,7 +130,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("AdjacentPath", "0", 3, "0"),
("AdjacentPathMetrics", "0", 3, "0"),
("AdvancedCustomUI", "0", 2, "0"),
("AdvancedLateralTune", "0", 2, "0"),
("AdvancedLateralTune", "1", 2, "0"),
("AdvancedLongitudinalTune", "0", 3, "0"),
("EVTuning", "", 3, "0"),
("AggressiveFollow", "1.25", 2, "1.25"),
@@ -157,7 +159,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("BlacklistedModels", "", 2, ""),
("BlindSpotMetrics", "1", 3, "0"),
("BlindSpotPath", "1", 1, "0"),
("BorderMetrics", "0", 3, "0"),
("BorderMetrics", "1", 3, "0"),
("CalibratedLateralAcceleration", str(DEFAULT_LATERAL_ACCELERATION), 2, str(DEFAULT_LATERAL_ACCELERATION)),
("CalibrationProgress", "0", 3, "0"),
("CameraView", "3", 2, "0"),
@@ -196,7 +198,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("CustomUI", "1", 1, "0"),
("DecelerationProfile", "1", 2, "0"),
("DeveloperMetrics", "1", 3, "0"),
("DeveloperSidebar", "1", 3, "0"),
("DeveloperSidebar", "0", 3, "0"),
("DeveloperSidebarMetric1", "1", 3, "0"),
("DeveloperSidebarMetric2", "2", 3, "0"),
("DeveloperSidebarMetric3", "3", 3, "0"),
@@ -205,7 +207,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("DeveloperSidebarMetric6", "6", 3, "0"),
("DeveloperSidebarMetric7", "7", 3, "0"),
("DeveloperWidgets", "1", 3, "0"),
("DeveloperUI", "0", 3, "0"),
("DeveloperUI", "1", 3, "0"),
("DeviceManagement", "1", 1, "0"),
("DeviceShutdown", "9", 1, "33"),
("DisableOnroadUploads", "0", 2, "0"),
@@ -223,7 +225,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("Fahrenheit", "0", 3, "0"),
("FavoriteDestinations", "", 0, ""),
("ForceAutoTune", "0", 2, "0"),
("ForceAutoTuneOff", "0", 2, "0"),
("ForceAutoTuneOff", "1", 2, "0"),
("ForceFingerprint", "0", 2, "0"),
("ForceMPHDashboard", "0", 2, "0"),
("ForceStops", "0", 2, "0"),
@@ -341,7 +343,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("RelaxedJerkSpeed", "50", 3, "50"),
("RelaxedJerkSpeedDecrease", "50", 3, "50"),
("RelaxedPersonalityProfile", "1", 2, "0"),
("ReverseCruise", "0", 1, "0"),
("ReverseCruise", "1", 1, "0"),
("RoadEdgesWidth", "2", 2, "2"),
("RoadNameUI", "1", 2, "0"),
("RotatingWheel", "1", 1, "0"),
@@ -365,7 +367,7 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("ShownToggleDescriptions", "", 0, ""),
("ShowSLCOffset", "1", 0, "0"),
("ShowSpeedLimits", "1", 1, "0"),
("ShowSteering", "0", 3, "0"),
("ShowSteering", "1", 3, "0"),
("ShowStoppingPoint", "0", 2, "0"),
("ShowStoppingPointMetrics", "0", 2, "0"),
("ShowStorageLeft", "0", 3, "0"),
@@ -407,6 +409,8 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("SteerDelayStock", "", 3, ""),
("SteerFriction", "", 3, ""),
("SteerFrictionStock", "", 3, ""),
("SteerOffset", "", 3, ""),
("SteerOffsetStock", "", 3, ""),
("SteerKP", "", 3, ""),
("SteerKPStock", "", 3, ""),
("SteerLatAccel", "", 3, ""),
@@ -429,8 +433,8 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("TrafficJerkSpeed", "50", 3, "50"),
("TrafficJerkSpeedDecrease", "50", 3, "50"),
("TrafficPersonalityProfile", "1", 2, "0"),
("TuningLevel", "0", 0, "0"),
("TuningLevelConfirmed", "0", 0, "0"),
("TuningLevel", "3", 0, "0"),
("TuningLevelConfirmed", "1", 0, "0"),
("TurnDesires", "0", 2, "0"),
("UnlimitedLength", "1", 2, "0"),
("UnlockDoors", "1", 0, "0"),
@@ -569,6 +573,7 @@ class FrogPilotVariables:
toggle.has_pedal = CP.enableGasInterceptor
has_radar = not CP.radarUnavailable
toggle.has_sdsu = toggle.car_make == "toyota" and bool(CP.flags & ToyotaFlags.SMART_DSU.value)
toggle.has_sascm = toggle.car_make == "gm" and bool(CP.flags & GMFlags.SASCM.value)
has_sng = CP.autoResumeSng
toggle.has_zss = toggle.car_make == "toyota" and bool(FPCP.fpFlags & ToyotaFrogPilotFlags.ZSS.value)
is_angle_car = CP.steerControlType == car.CarParams.SteerControlType.angle
@@ -612,6 +617,7 @@ class FrogPilotVariables:
toggle.steerActuatorDelay = np.clip(params.get_float("SteerDelay"), 0.01, 1.0) if advanced_lateral_tuning and tuning_level >= level["SteerDelay"] else steerActuatorDelay
toggle.use_custom_steerActuatorDelay = bool(round(toggle.steerActuatorDelay, 2) != round(steerActuatorDelay, 2))
toggle.friction = np.clip(params.get_float("SteerFriction"), 0, 0.5) if advanced_lateral_tuning and tuning_level >= level["SteerFriction"] else friction
toggle.steer_offset = np.clip(params.get_float("SteerOffset"), -0.2, 0.2) if advanced_lateral_tuning and tuning_level >= level["SteerOffset"] and toggle.car_make == "gm" else 0.0
toggle.use_custom_friction = bool(round(toggle.friction, 2) != round(friction, 2)) and is_torque_car and not toggle.force_auto_tune or toggle.force_auto_tune_off
toggle.steerKp = [[0], [np.clip(params.get_float("SteerKP"), steerKp * 0.5, steerKp * 1.5) if advanced_lateral_tuning and is_torque_car and tuning_level >= level["SteerKP"] else steerKp]]
toggle.latAccelFactor = np.clip(params.get_float("SteerLatAccel"), latAccelFactor * 0.75, latAccelFactor * 1.25) if advanced_lateral_tuning and tuning_level >= level["SteerLatAccel"] else latAccelFactor
@@ -887,7 +893,7 @@ class FrogPilotVariables:
toggle.model_version = DEFAULT_MODEL_VERSION
toggle.classic_longitudinal = toggle.model_version in {"v1", "v2", "v3", "v4"}
toggle.classic_model = toggle.model_version in {"v1", "v2", "v3", "v4"}
toggle.tinygrad_model = toggle.model_version in {"v8", "v9", "v10", "v11"}
toggle.tinygrad_model = toggle.model_version in {"v8", "v9", "v10", "v11", "v12"}
toggle.tomb_raider = toggle.model == "space-lab"
toggle.model_ui = params.get_bool("ModelUI") if tuning_level >= level["ModelUI"] else default.get_bool("ModelUI")
@@ -1002,6 +1008,7 @@ class FrogPilotVariables:
volt_models = {
"CHEVROLET_VOLT",
"CHEVROLET_VOLT_2019",
"CHEVROLET_VOLT_ASCM",
"CHEVROLET_VOLT_CAMERA",
}
+1 -1
View File
@@ -51,7 +51,7 @@ class FrogPilotTracking:
self.sound = FrogPilotAudibleAlert.none
self.state = State.disabled
self.model_name = clean_model_name(dict(zip(frogpilot_toggles.available_models.split(","), frogpilot_toggles.available_model_names.split(",")))[frogpilot_toggles.model])
self.model_name = clean_model_name(frogpilot_toggles.model_name)
def update(self, now, time_validated, sm, frogpilot_toggles):
v_cruise = min(sm["controlsState"].vCruiseCluster, V_CRUISE_MAX) * CV.KPH_TO_MS
BIN
View File
Binary file not shown.
Binary file not shown.
+42 -22
View File
@@ -20,6 +20,30 @@ from openpilot.frogpilot.common.frogpilot_variables import get_frogpilot_toggles
BASE_URL = "https://nominatim.openstreetmap.org"
MINIMUM_POPULATION = 100_000
SEARCH_RADIUS_DEGREES = 1.45
def get_population_value(population_str):
if population_str is None:
return None
try:
return int(str(population_str).replace(",", "").split(";")[0].strip())
except Exception:
return None
def search_nearby_major_cities(lat, lon, session, state_name, country_name):
viewbox = f"{lon - SEARCH_RADIUS_DEGREES},{lat + SEARCH_RADIUS_DEGREES},{lon + SEARCH_RADIUS_DEGREES},{lat - SEARCH_RADIUS_DEGREES}"
cities = (session.get(f"{BASE_URL}/search", params={
"addressdetails": 1, "bounded": 1, "extratags": 1, "format": "jsonv2", "limit": 20, "q": "city", "viewbox": viewbox
}, timeout=10).json() or [])
qualifying = [c for c in cities if (get_population_value((c.get("extratags") or {}).get("population")) or 0) >= MINIMUM_POPULATION]
if not qualifying:
return None
nearest = min(qualifying, key=lambda c: (float(c["lat"]) - lat) ** 2 + (float(c["lon"]) - lon) ** 2)
addr = nearest.get("address") or {}
return float(nearest["lat"]), float(nearest["lon"]), addr.get("city") or addr.get("town") or nearest.get("display_name", "").split(",")[0], state_name, country_name
def get_city_center(latitude, longitude):
try:
@@ -44,14 +68,7 @@ def get_city_center(latitude, longitude):
if data:
tags = data[0]
population = (tags.get("extratags") or {}).get("population")
population_value = None
if population is not None:
try:
population_value = int(str(population).replace(",", "").split(";")[0].strip())
except Exception:
population_value = None
population_value = get_population_value((tags.get("extratags") or {}).get("population"))
if population_value is not None and population_value >= MINIMUM_POPULATION:
latitude_value = float(tags["lat"])
@@ -62,6 +79,10 @@ def get_city_center(latitude, longitude):
return latitude_value, longitude_value, city_label, state_name, country_name
nearby_result = search_nearby_major_cities(latitude, longitude, session, state_name, country_name)
if nearby_result:
return nearby_result
query = f"{state_name} state capital" if country_code == "us" else f"capital of {state_name}, {country_name}"
response = session.get(f"{BASE_URL}/search", params={"addressdetails": 1, "extratags": 1, "format": "jsonv2", "limit": 5, "q": query}, timeout=10)
response.raise_for_status()
@@ -99,14 +120,14 @@ def get_city_center(latitude, longitude):
def update_branch_commits(now):
points = []
for branch in ["FrogPilot", "FrogPilot-Staging", "FrogPilot-Testing"]:
try:
response = requests.get(f"https://api.github.com/repos/FrogAi/FrogPilot/commits/{branch}")
response.raise_for_status()
sha = response.json()["sha"]
points.append(Point("branch_commits").field("commit", sha).tag("branch", branch).time(now))
except Exception as e:
print(f"Failed to fetch commit for {branch}: {e}")
branch = get_build_metadata().channel # Current running branch
try:
response = requests.get(f"https://api.github.com/repos/firestar5683/StarPilot/commits/{branch}")
response.raise_for_status()
sha = response.json()["sha"]
points.append(Point("branch_commits").field("commit", sha).tag("branch", branch).time(now))
except Exception as e:
print(f"Failed to fetch commit for {branch}: {e}")
return points
@@ -129,11 +150,9 @@ def send_stats():
if frogpilot_toggles.car_make == "mock":
return
bucket = os.environ.get("STATS_BUCKET", "")
org_ID = os.environ.get("STATS_ORG_ID", "")
token = os.environ.get("STATS_TOKEN", "")
url = os.environ.get("STATS_URL", "")
bucket = "StarPilot"
org_ID = "StarPilot"
url = "https://stats.firestar.link"
frogpilot_stats = json.loads(params.get("FrogPilotStats") or "{}")
location = json.loads(params.get("LastGPSPosition") or "{}")
@@ -178,6 +197,7 @@ def send_stats():
.field("has_openpilot_longitudinal", frogpilot_toggles.openpilot_longitudinal)
.field("has_pedal", frogpilot_toggles.has_pedal)
.field("has_sdsu", frogpilot_toggles.has_sdsu)
.field("has_sascm", frogpilot_toggles.has_sascm)
.field("has_zss", frogpilot_toggles.has_zss)
.field("latitude", latitude)
.field("longitude", longitude)
@@ -201,7 +221,7 @@ def send_stats():
all_points = [user_point] + update_branch_commits(now)
client = InfluxDBClient(org=org_ID, token=token, url=url)
client = InfluxDBClient(org=org_ID, token=org_ID, url=url)
client.write_api(write_options=SYNCHRONOUS).write(bucket=bucket, org=org_ID, record=all_points)
print("Successfully sent FrogPilot stats!")
except Exception as exception:
+104 -28
View File
@@ -35,7 +35,7 @@ PROCESS_NAME = "frogpilot.tinygrad_modeld.tinygrad_modeld"
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED')
LAT_SMOOTH_SECONDS = 0.1
LAT_SMOOTH_SECONDS = 0.0
LONG_SMOOTH_SECONDS = 0.3
MIN_LAT_CONTROL_SPEED = 0.3
@@ -84,6 +84,34 @@ class ModelState:
output: np.ndarray
prev_desire: np.ndarray # for tracking the rising edge of the pulse
def _build_policy_inputs(self, input_shapes: dict[str, tuple[int, ...]]) -> tuple[dict[str, np.ndarray], str | None]:
numpy_inputs: dict[str, np.ndarray] = {}
# Always-supported inputs (if model expects them)
desire_key_init = next((k for k in input_shapes if k.startswith('desire')), None)
if desire_key_init:
numpy_inputs[desire_key_init] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32)
if 'traffic_convention' in input_shapes:
numpy_inputs['traffic_convention'] = np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32)
if 'features_buffer' in input_shapes:
numpy_inputs['features_buffer'] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32)
# Optional inputs for non-v11 (and some v10/v9 variants)
# Lateral control params
if 'lateral_control_params' in input_shapes:
numpy_inputs['lateral_control_params'] = np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32)
# Previous desired curvature: handle both singular and plural key names across model versions
prev_desired_curv_key = None
if 'prev_desired_curv' in input_shapes:
prev_desired_curv_key = 'prev_desired_curv'
numpy_inputs['prev_desired_curv'] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32)
elif 'prev_desired_curvs' in input_shapes:
prev_desired_curv_key = 'prev_desired_curvs'
numpy_inputs['prev_desired_curvs'] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32)
return numpy_inputs, prev_desired_curv_key
def __init__(self, context: CLContext):
# Dynamically build paths based on current model ID
params = Params()
@@ -102,13 +130,17 @@ class ModelState:
models_dir = Path(__file__).parent / "models"
VISION_PKL_PATH = models_dir / "driving_vision_tinygrad.pkl"
POLICY_PKL_PATH = models_dir / "driving_policy_tinygrad.pkl"
OFF_POLICY_PKL_PATH = models_dir / "driving_off_policy_tinygrad.pkl"
VISION_METADATA_PATH = models_dir / "driving_vision_metadata.pkl"
POLICY_METADATA_PATH = models_dir / "driving_policy_metadata.pkl"
OFF_POLICY_METADATA_PATH = models_dir / "driving_off_policy_metadata.pkl"
else:
VISION_PKL_PATH = model_dir / f"{model_id}_driving_vision_tinygrad.pkl"
POLICY_PKL_PATH = model_dir / f"{model_id}_driving_policy_tinygrad.pkl"
OFF_POLICY_PKL_PATH = model_dir / f"{model_id}_driving_off_policy_tinygrad.pkl"
VISION_METADATA_PATH = model_dir / f"{model_id}_driving_vision_metadata.pkl"
POLICY_METADATA_PATH = model_dir / f"{model_id}_driving_policy_metadata.pkl"
OFF_POLICY_METADATA_PATH = model_dir / f"{model_id}_driving_off_policy_metadata.pkl"
# If ModelVersion is not set or not available, try to determine it from available model data
if not model_version:
@@ -160,7 +192,7 @@ class ModelState:
self.policy_generation = model_version or "v8"
self.is_v11 = (self.policy_generation == "v11")
self.is_v9 = (self.policy_generation == "v9")
self.mlsim = (self.policy_generation in ("v8", "v10", "v11"))
self.mlsim = (self.policy_generation in ("v8", "v10", "v11", "v12"))
self.frames = {name: DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) for name in self.vision_input_names}
self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32)
@@ -171,33 +203,50 @@ class ModelState:
# policy inputs (built dynamically to support all generations)
self.numpy_inputs = {}
self.numpy_inputs, self.prev_desired_curv_key = self._build_policy_inputs(self.policy_input_shapes)
# Always-supported inputs (if model expects them)
desire_key_init = next((k for k in self.policy_input_shapes if k.startswith('desire')), None)
if desire_key_init:
self.numpy_inputs[desire_key_init] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32)
if 'traffic_convention' in self.policy_input_shapes:
self.numpy_inputs['traffic_convention'] = np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32)
if 'features_buffer' in self.policy_input_shapes:
self.numpy_inputs['features_buffer'] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32)
# Off-policy model (optional)
self.off_policy_enabled = False
self.off_policy_input_shapes: dict[str, tuple[int, ...]] = {}
self.off_policy_output_slices: dict[str, slice] = {}
self.off_policy_numpy_inputs: dict[str, np.ndarray] = {}
self.off_policy_prev_desired_curv_key: str | None = None
self.off_policy_desire_key: str | None = None
self.off_policy_inputs: dict[str, Tensor] | None = None
self.off_policy_output: np.ndarray | None = None
# Optional inputs for non-v11 (and some v10/v9 variants)
# Lateral control params
if 'lateral_control_params' in self.policy_input_shapes:
self.numpy_inputs['lateral_control_params'] = np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32)
off_policy_metadata = None
if self.policy_generation == "v12" or OFF_POLICY_METADATA_PATH.is_file() or OFF_POLICY_PKL_PATH.is_file():
try:
with open(OFF_POLICY_METADATA_PATH, 'rb') as f:
off_policy_metadata = pickle.load(f)
except FileNotFoundError:
cloudlog.error(f"Missing metadata {OFF_POLICY_METADATA_PATH}, downloading...")
from openpilot.frogpilot.assets.model_manager import ModelManager
ModelManager().download_model(model_id)
try:
with open(OFF_POLICY_METADATA_PATH, 'rb') as f:
off_policy_metadata = pickle.load(f)
except FileNotFoundError:
cloudlog.warning(f"Off-policy metadata still missing: {OFF_POLICY_METADATA_PATH}")
# Previous desired curvature: handle both singular and plural key names across model versions
self.prev_desired_curv_key = None
if 'prev_desired_curv' in self.policy_input_shapes:
self.prev_desired_curv_key = 'prev_desired_curv'
self.numpy_inputs['prev_desired_curv'] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32)
elif 'prev_desired_curvs' in self.policy_input_shapes:
self.prev_desired_curv_key = 'prev_desired_curvs'
self.numpy_inputs['prev_desired_curvs'] = np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32)
if off_policy_metadata is not None:
self.off_policy_input_shapes = off_policy_metadata['input_shapes']
self.off_policy_output_slices = off_policy_metadata['output_slices']
off_policy_output_size = off_policy_metadata['output_shapes']['outputs'][1]
self.off_policy_numpy_inputs, self.off_policy_prev_desired_curv_key = self._build_policy_inputs(self.off_policy_input_shapes)
self.off_policy_desire_key = next((k for k in self.off_policy_numpy_inputs if k.startswith('desire')), None)
self.off_policy_inputs = {k: Tensor(v, device='NPY').realize() for k, v in self.off_policy_numpy_inputs.items()}
self.off_policy_output = np.zeros(off_policy_output_size, dtype=np.float32)
try:
with open(OFF_POLICY_PKL_PATH, "rb") as f:
self.off_policy_run = pickle.load(f)
self.off_policy_enabled = True
except FileNotFoundError:
cloudlog.warning(f"Missing off-policy model {OFF_POLICY_PKL_PATH}, skipping off-policy")
# Optional temporal buffer for previous desired curvature (allocate only if the policy expects it)
if getattr(self, 'prev_desired_curv_key', None) is not None:
# Optional temporal buffer for previous desired curvature (allocate only if any model expects it)
if self.prev_desired_curv_key is not None or self.off_policy_prev_desired_curv_key is not None:
self.full_prev_desired_curv = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32)
@@ -207,6 +256,7 @@ class ModelState:
self.policy_inputs = {k: Tensor(v, device='NPY').realize() for k,v in self.numpy_inputs.items()}
self.policy_output = np.zeros(policy_output_size, dtype=np.float32)
self.parser = Parser()
self.off_policy_parser = Parser(ignore_missing=True)
with open(VISION_PKL_PATH, "rb") as f:
self.vision_run = pickle.load(f)
@@ -232,10 +282,18 @@ class ModelState:
self.full_desire[0,:-1] = self.full_desire[0,1:]
self.full_desire[0,-1] = new_desire
self.numpy_inputs[self.desire_key][:] = self.full_desire.reshape((1,ModelConstants.INPUT_HISTORY_BUFFER_LEN,ModelConstants.TEMPORAL_SKIP,-1)).max(axis=2)
if self.off_policy_enabled and self.off_policy_desire_key is not None:
self.off_policy_numpy_inputs[self.off_policy_desire_key][:] = self.numpy_inputs[self.desire_key]
if 'traffic_convention' in self.numpy_inputs:
self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention']
if self.off_policy_enabled and 'traffic_convention' in self.off_policy_numpy_inputs:
self.off_policy_numpy_inputs['traffic_convention'][:] = inputs['traffic_convention']
self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention']
if 'lateral_control_params' in self.numpy_inputs:
self.numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params']
if self.off_policy_enabled and 'lateral_control_params' in self.off_policy_numpy_inputs:
self.off_policy_numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params']
if prepare_only:
return None
@@ -257,7 +315,10 @@ class ModelState:
self.full_features_buffer[0,:-1] = self.full_features_buffer[0,1:]
self.full_features_buffer[0,-1] = vision_outputs_dict['hidden_state'][0, :]
self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs]
if 'features_buffer' in self.numpy_inputs:
self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs]
if self.off_policy_enabled and 'features_buffer' in self.off_policy_numpy_inputs:
self.off_policy_numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs]
self.policy_output = self.policy_run(**self.policy_inputs).contiguous().realize().uop.base.buffer.numpy()
policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices))
@@ -274,9 +335,24 @@ class ModelState:
else:
self.numpy_inputs[self.prev_desired_curv_key][:] = self.full_prev_desired_curv[0, self.temporal_idxs]
if self.off_policy_enabled and self.off_policy_prev_desired_curv_key is not None:
if self.is_v9:
self.off_policy_numpy_inputs[self.off_policy_prev_desired_curv_key][:] = 0 * self.full_prev_desired_curv[0, self.temporal_idxs]
else:
self.off_policy_numpy_inputs[self.off_policy_prev_desired_curv_key][:] = self.full_prev_desired_curv[0, self.temporal_idxs]
combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict}
if self.off_policy_enabled:
self.off_policy_output = self.off_policy_run(**self.off_policy_inputs).contiguous().realize().uop.base.buffer.numpy()
off_policy_outputs_dict = self.off_policy_parser.parse_policy_outputs(
self.slice_outputs(self.off_policy_output, self.off_policy_output_slices)
)
combined_outputs_dict.update(off_policy_outputs_dict)
if SEND_RAW_PRED:
combined_outputs_dict['raw_pred'] = np.concatenate([self.vision_output.copy(), self.policy_output.copy()])
raw_pred = [self.vision_output.copy(), self.policy_output.copy()]
if self.off_policy_enabled and self.off_policy_output is not None:
raw_pred.append(self.off_policy_output.copy())
combined_outputs_dict['raw_pred'] = np.concatenate(raw_pred)
return combined_outputs_dict
@@ -269,6 +269,7 @@ void FrogPilotSettingsWindow::updateVariables() {
hasPedal = CP.getEnableGasInterceptor();
hasRadar = !CP.getRadarUnavailable();
hasSDSU = frogpilot_toggles.value("has_sdsu").toBool();
hasSASCM = frogpilot_toggles.value("has_sascm").toBool();
hasSNG = hasOpenpilotLongitudinal && CP.getAutoResumeSng();
hasZSS = frogpilot_toggles.value("has_zss").toBool();
isAngleCar = CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE;
@@ -285,6 +286,7 @@ void FrogPilotSettingsWindow::updateVariables() {
longitudinalActuatorDelay = CP.getLongitudinalActuatorDelay();
startAccel = CP.getStartAccel();
steerActuatorDelay = CP.getSteerActuatorDelay();
steerOffset = 0.0f;
steerKp = CP.getLateralTuning().which() == cereal::CarParams::LateralTuning::PID ? CP.getLateralTuning().getPid().getKpV()[0] : 0.6;
steerRatio = CP.getSteerRatio();
stopAccel = CP.getStopAccel();
@@ -296,6 +298,7 @@ void FrogPilotSettingsWindow::updateVariables() {
float currentDelayStock = params.getFloat("SteerDelayStock");
float currentFrictionStock = params.getFloat("SteerFrictionStock");
float currentSteerOffsetStock = params.getFloat("SteerOffsetStock");
float currentKPStock = params.getFloat("SteerKPStock");
float currentLatAccelStock = params.getFloat("SteerLatAccelStock");
float currentLongDelayStock = params.getFloat("LongitudinalActuatorDelayStock");
@@ -320,6 +323,13 @@ void FrogPilotSettingsWindow::updateVariables() {
params.putFloat("SteerFrictionStock", friction);
}
if (currentSteerOffsetStock != steerOffset) {
if (params.getFloat("SteerOffset") == currentSteerOffsetStock) {
params.putFloat("SteerOffset", steerOffset);
}
params.putFloat("SteerOffsetStock", steerOffset);
}
if (currentKPStock != steerKp && steerKp != 0) {
if (params.getFloat("SteerKP") == currentKPStock || currentKPStock == 0) {
params.putFloat("SteerKP", steerKp);
@@ -392,6 +402,7 @@ void FrogPilotSettingsWindow::updateVariables() {
canUsePedal = FPCP.getCanUsePedal();
canUseSDSU = FPCP.getCanUseSDSU();
canUseSASCM = FPCP.getCanUseSASCM();
openpilotLongitudinalControlDisabled = FPCP.getOpenpilotLongitudinalControlDisabled();
}
@@ -13,6 +13,7 @@ public:
bool canUsePedal = false;
bool canUseSDSU = false;
bool canUseSASCM = false;
bool forceOpenDescriptions = false;
bool hasAutoTune = true;
bool hasBSM = true;
@@ -24,6 +25,7 @@ public:
bool hasPedal = false;
bool hasRadar = true;
bool hasSDSU = false;
bool hasSASCM = false;
bool hasSNG = false;
bool hasZSS = false;
bool isAngleCar = false;
@@ -45,6 +47,7 @@ public:
float longitudinalActuatorDelay;
float startAccel;
float steerActuatorDelay;
float steerOffset;
float steerKp;
float steerRatio;
float stopAccel;
@@ -41,6 +41,7 @@ FrogPilotLateralPanel::FrogPilotLateralPanel(FrogPilotSettingsWindow *parent) :
{"AdvancedLateralTune", tr("Advanced Lateral Tuning"), tr("<b>Advanced steering control changes to fine-tune how openpilot drives.</b>"), "../../frogpilot/assets/toggle_icons/icon_advanced_lateral_tune.png"},
{"SteerDelay", parent->steerActuatorDelay != 0 ? QString(tr("Actuator Delay (Default: %1)")).arg(QString::number(parent->steerActuatorDelay, 'f', 2)) : tr("Actuator Delay"), tr("<b>The time between openpilot's steering command and the vehicle's response.</b> Increase if the vehicle reacts late; decrease if it feels jumpy. Auto-learned by default."), ""},
{"SteerFriction", parent->friction != 0 ? QString(tr("Friction (Default: %1)")).arg(QString::number(parent->friction, 'f', 2)) : tr("Friction"), tr("<b>Compensates for steering friction.</b> Increase if the wheel sticks near center; decrease if it jitters. Auto-learned by default."), ""},
{"SteerOffset", parent->steerOffset != 0 ? QString(tr("Steer Offset (Default: %1)")).arg(QString::number(parent->steerOffset, 'f', 3)) : tr("Steer Offset"), tr("<b>Offsets steering torque to help compensate for alignment or tire issues.</b> More negative pulls the car right; more positive pulls it left. Most users should not need to touch this."), ""},
{"SteerKP", parent->steerKp != 0 ? QString(tr("Kp Factor (Default: %1)")).arg(QString::number(parent->steerKp, 'f', 2)) : tr("Kp Factor"), tr("<b>How strongly openpilot corrects lane position.</b> Higher is tighter but twitchier; lower is smoother but slower. Auto-learned by default."), ""},
{"SteerLatAccel", parent->latAccelFactor != 0 ? QString(tr("Lateral Acceleration (Default: %1)")).arg(QString::number(parent->latAccelFactor, 'f', 2)) : tr("Lateral Acceleration"), tr("<b>Maps steering torque to turning response.</b> Increase for sharper turns; decrease for gentler steering. Auto-learned by default."), ""},
{"SteerRatio", parent->steerRatio != 0 ? QString(tr("Steer Ratio (Default: %1)")).arg(QString::number(parent->steerRatio, 'f', 2)) : tr("Steer Ratio"), tr("<b>The relationship between steering wheel rotation and road wheel angle.</b> Increase if steering feels too quick or twitchy; decrease if it feels too slow or weak. Auto-learned by default."), ""},
@@ -87,6 +88,9 @@ FrogPilotLateralPanel::FrogPilotLateralPanel(FrogPilotSettingsWindow *parent) :
} else if (param == "SteerFriction") {
std::vector<QString> steerFrictionButton{"Reset"};
lateralToggle = new FrogPilotParamValueButtonControl(param, title, desc, icon, 0, 0.5, QString(), std::map<float, QString>(), 0.01, false, {}, steerFrictionButton, false, false);
} else if (param == "SteerOffset") {
std::vector<QString> steerOffsetButton{"Reset"};
lateralToggle = new FrogPilotParamValueButtonControl(param, title, desc, icon, -0.2, 0.2, QString(), std::map<float, QString>(), 0.005, false, {}, steerOffsetButton, false, false);
} else if (param == "SteerKP") {
std::vector<QString> steerKPButton{"Reset"};
lateralToggle = new FrogPilotParamValueButtonControl(param, title, desc, icon, parent->steerKp * 0.5, parent->steerKp * 1.5, QString(), std::map<float, QString>(), 0.01, false, {}, steerKPButton, false, false);
@@ -216,6 +220,14 @@ FrogPilotLateralPanel::FrogPilotLateralPanel(FrogPilotSettingsWindow *parent) :
}
});
steerOffsetToggle = static_cast<FrogPilotParamValueButtonControl*>(toggles["SteerOffset"]);
QObject::connect(steerOffsetToggle, &FrogPilotParamValueButtonControl::buttonClicked, [parent, this]() {
if (FrogPilotConfirmationDialog::yesorno(tr("Reset <b>Steer Offset</b> to its default value?"), this)) {
params.putFloat("SteerOffset", parent->steerOffset);
steerOffsetToggle->refresh();
}
});
steerKPToggle = static_cast<FrogPilotParamValueButtonControl*>(toggles["SteerKP"]);
QObject::connect(steerKPToggle, &FrogPilotParamValueButtonControl::buttonClicked, [parent, this]() {
if (FrogPilotConfirmationDialog::yesorno(tr("Reset <b>Kp Factor</b> to its default value?"), this)) {
@@ -255,6 +267,7 @@ void FrogPilotLateralPanel::showEvent(QShowEvent *event) {
steerDelayToggle->setTitle(QString(tr("Actuator Delay (Default: %1)")).arg(QString::number(parent->steerActuatorDelay, 'f', 2)));
steerFrictionToggle->setTitle(QString(tr("Friction (Default: %1)")).arg(QString::number(parent->friction, 'f', 2)));
steerOffsetToggle->setTitle(QString(tr("Steer Offset (Default: %1)")).arg(QString::number(parent->steerOffset, 'f', 3)));
steerKPToggle->setTitle(QString(tr("Kp Factor (Default: %1)")).arg(QString::number(parent->steerKp, 'f', 2)));
steerKPToggle->updateControl(parent->steerKp * 0.5, parent->steerKp * 1.5);
steerLatAccelToggle->setTitle(QString(tr("Lateral Accel (Default: %1)")).arg(QString::number(parent->latAccelFactor, 'f', 2)));
@@ -405,6 +418,12 @@ void FrogPilotLateralPanel::updateToggles() {
setVisible &= !usingNNFF;
}
else if (key == "SteerOffset") {
setVisible &= parent->isGM;
setVisible &= parent->isTorqueCar || forcingTorqueController;
setVisible &= !usingNNFF;
}
else if (key == "SteerKP") {
setVisible &= parent->steerKp != 0;
setVisible &= !parent->isAngleCar;
+3 -1
View File
@@ -31,6 +31,7 @@ private:
float friction;
float latAccelFactor;
float steerActuatorDelay;
float steerOffset;
float steerKp;
float steerRatio;
@@ -38,7 +39,7 @@ private:
std::map<QString, AbstractControl*> toggles;
QSet<QString> advancedLateralTuneKeys = {"ForceAutoTune", "ForceAutoTuneOff", "ForceTorqueController", "SteerDelay", "SteerFriction", "SteerLatAccel", "SteerKP", "SteerRatio"};
QSet<QString> advancedLateralTuneKeys = {"ForceAutoTune", "ForceAutoTuneOff", "ForceTorqueController", "SteerDelay", "SteerFriction", "SteerOffset", "SteerLatAccel", "SteerKP", "SteerRatio"};
QSet<QString> aolKeys = {"AlwaysOnLateralLKAS", "AlwaysOnLateralMain", "PauseAOLOnBrake"};
QSet<QString> laneChangeKeys = {"LaneChangeTime", "LaneDetectionWidth", "MinimumLaneChangeSpeed", "NudgelessLaneChange", "OneLaneChange"};
QSet<QString> lateralTuneKeys = {"NNFF", "NNFFLite", "TurnDesires"};
@@ -48,6 +49,7 @@ private:
FrogPilotParamValueButtonControl *steerDelayToggle;
FrogPilotParamValueButtonControl *steerFrictionToggle;
FrogPilotParamValueButtonControl *steerOffsetToggle;
FrogPilotParamValueButtonControl *steerLatAccelToggle;
FrogPilotParamValueButtonControl *steerKPToggle;
FrogPilotParamValueButtonControl *steerRatioToggle;
@@ -503,6 +503,8 @@ bool FrogPilotModelPanel::isModelInstalled(const QString &key) const {
bool has_policy_tg = false;
bool has_vision_meta = false;
bool has_vision_tg = false;
bool has_off_policy_meta = false;
bool has_off_policy_tg = false;
bool foundAny = false;
for (const QString &file : modelDir.entryList(QDir::Files)) {
@@ -521,6 +523,10 @@ bool FrogPilotModelPanel::isModelInstalled(const QString &key) const {
has_policy_meta = true;
} else if (base.contains("_driving_policy_tinygrad")) {
has_policy_tg = true;
} else if (base.contains("_driving_off_policy_metadata")) {
has_off_policy_meta = true;
} else if (base.contains("_driving_off_policy_tinygrad")) {
has_off_policy_tg = true;
} else if (base.contains("_driving_vision_metadata")) {
has_vision_meta = true;
} else if (base.contains("_driving_vision_tinygrad")) {
@@ -534,6 +540,9 @@ bool FrogPilotModelPanel::isModelInstalled(const QString &key) const {
}
if (has_policy_meta && has_policy_tg && has_vision_meta && has_vision_tg) {
if (has_off_policy_meta || has_off_policy_tg) {
return has_off_policy_meta && has_off_policy_tg;
}
return true;
}
@@ -189,6 +189,7 @@ FrogPilotVehiclesPanel::FrogPilotVehiclesPanel(FrogPilotSettingsWindow *parent)
{"PedalSupport", tr("comma Pedal Support"), tr("<b>Does your vehicle support the \"comma pedal\"?</b>"), ""},
{"OpenpilotLongitudinal", tr("openpilot Longitudinal Support"), tr("<b>Can openpilot control the vehicle's acceleration and braking?</b>"), ""},
{"RadarSupport", tr("Radar Support"), tr("<b>Does openpilot use the vehicle's radar data</b> alongside the device's camera for tracking lead vehicles?"), ""},
{"SASCMSupport", tr("SASCM Support"), tr("<b>Does your vehicle support \"SASCMs\"?</b>"), ""},
{"SDSUSupport", tr("SDSU Support"), tr("<b>Does your vehicle support \"SDSUs\"?</b>"), ""},
{"SNGSupport", tr("Stop-and-Go Support"), tr("<b>Does your vehicle support stop-and-go driving?</b>"), ""}
};
@@ -342,6 +343,7 @@ void FrogPilotVehiclesPanel::showEvent(QShowEvent *event) {
QStringList detected;
if (hasPedal) detected << "comma Pedal";
if (parent->hasSASCM) detected << "SASCM";
if (parent->hasSDSU) detected << "SDSU";
if (parent->hasZSS) detected << "ZSS";
static_cast<LabelControl*>(toggles["HardwareDetected"])->setText(detected.isEmpty() ? tr("None") : detected.join(", "));
@@ -350,6 +352,7 @@ void FrogPilotVehiclesPanel::showEvent(QShowEvent *event) {
static_cast<LabelControl*>(toggles["OpenpilotLongitudinal"])->setText(hasOpenpilotLongitudinal ? tr("Yes") : tr("No"));
static_cast<LabelControl*>(toggles["PedalSupport"])->setText(parent->canUsePedal ? tr("Yes") : tr("No"));
static_cast<LabelControl*>(toggles["RadarSupport"])->setText(parent->hasRadar ? tr("Yes") : tr("No"));
static_cast<LabelControl*>(toggles["SASCMSupport"])->setText(parent->canUseSASCM ? tr("Yes") : tr("No"));
static_cast<LabelControl*>(toggles["SDSUSupport"])->setText(parent->canUseSDSU ? tr("Yes") : tr("No"));
static_cast<LabelControl*>(toggles["SNGSupport"])->setText(hasSNG ? tr("Yes") : tr("No"));
+1 -1
View File
@@ -40,7 +40,7 @@ private:
QSet<QString> hkgKeys = {"NewLongAPI", "TacoTuneHacks"};
QSet<QString> longitudinalKeys = {"ExperimentalGMTune", "FrogsGoMoosTweak", "LongPitch", "NewLongAPI", "SNGHack", "VoltSNG"};
QSet<QString> toyotaKeys = {"ClusterOffset", "FrogsGoMoosTweak", "LockDoorsTimer", "SNGHack", "ToyotaDoors"};
QSet<QString> vehicleInfoKeys = {"BlindSpotSupport", "HardwareDetected", "OpenpilotLongitudinal", "PedalSupport", "RadarSupport", "SDSUSupport", "SNGSupport"};
QSet<QString> vehicleInfoKeys = {"BlindSpotSupport", "HardwareDetected", "OpenpilotLongitudinal", "PedalSupport", "RadarSupport", "SASCMSupport", "SDSUSupport", "SNGSupport"};
QSet<QString> parentKeys;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -10,14 +10,14 @@ const SteeringLimits GM_STEERING_LIMITS = {
};
const LongitudinalLimits GM_ASCM_LONG_LIMITS = {
.max_gas = 7168,
.max_gas = 8191,
.min_gas = 5500,
.inactive_gas = 5500,
.max_brake = 400,
};
const LongitudinalLimits GM_CAM_LONG_LIMITS = {
.max_gas = 7496,
.max_gas = 8848,
.min_gas = 5610,
.inactive_gas = 5650,
.max_brake = 400,
+19 -15
View File
@@ -805,7 +805,8 @@ class Panda:
# The panda will NAK CAN writes when there is CAN congestion.
# libusb will try to send it again, with a max timeout.
# Timeout is in ms. If set to 0, the timeout is infinite.
CAN_SEND_TIMEOUT_MS = 10
CAN_SEND_TIMEOUT_MS = 5
CAN_MAX_RETRIES = 3
def can_reset_communications(self):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xc0, 0, 0, b'')
@@ -813,18 +814,18 @@ class Panda:
@ensure_can_packet_version
def can_send_many(self, arr, timeout=CAN_SEND_TIMEOUT_MS):
snds = pack_can_buffer(arr)
while True:
try:
for tx in snds:
while True:
bs = self._handle.bulkWrite(3, tx, timeout=timeout)
tx = tx[bs:]
if len(tx) == 0:
break
logging.error("CAN: PARTIAL SEND MANY, RETRYING")
break
except (usb1.USBErrorIO, usb1.USBErrorOverflow):
logging.error("CAN: BAD SEND MANY, RETRYING")
for tx in snds:
retries = 0
while len(tx) > 0:
bs = self._handle.bulkWrite(3, tx, timeout=timeout)
if bs == 0:
retries += 1
if retries > self.CAN_MAX_RETRIES:
logging.warning("CAN send: no progress after retries, dropping")
break
else:
retries = 0
tx = tx[bs:]
def can_send(self, addr, dat, bus, timeout=CAN_SEND_TIMEOUT_MS):
self.can_send_many([[addr, None, dat, bus]], timeout=timeout)
@@ -832,13 +833,16 @@ class Panda:
@ensure_can_packet_version
def can_recv(self):
dat = bytearray()
while True:
for _ in range(self.CAN_MAX_RETRIES):
try:
dat = self._handle.bulkRead(1, 16384) # Max receive batch size + 2 extra reserve frames
break
except (usb1.USBErrorIO, usb1.USBErrorOverflow):
logging.error("CAN: BAD RECV, RETRYING")
time.sleep(0.1)
time.sleep(0.01)
else:
logging.error("CAN: recv failed after retries")
return []
msgs, self.can_rx_overflow_buffer = unpack_can_buffer(self.can_rx_overflow_buffer + dat)
return msgs
+12 -1
View File
@@ -27,7 +27,10 @@ NACK = 0x1F
CHECKSUM_START = 0xAB
MIN_ACK_TIMEOUT_MS = 100
MAX_ACK_TIMEOUT_MS = 500 # like C++ SPI_ACK_TIMEOUT
DEFAULT_TIMEOUT_MS = 500 # default when timeout=0
MAX_XFER_RETRY_COUNT = 5
MAX_TIMEOUT_RETRIES = 5 # like C++
XFER_SIZE = 0x40*31
@@ -152,6 +155,8 @@ class PandaSpiHandle(BaseHandle):
return cksum
def _wait_for_ack(self, spi, ack_val: int, timeout: int, tx: int, length: int = 1) -> bytes:
# Original behavior preserved - timeout=0 means wait forever within this function
# The caller (_transfer) handles the overall timeout
timeout_s = max(MIN_ACK_TIMEOUT_MS, timeout) * 1e-3
start = time.monotonic()
@@ -225,10 +230,15 @@ class PandaSpiHandle(BaseHandle):
logging.debug("starting transfer: endpoint=%d, max_rx_len=%d", endpoint, max_rx_len)
logging.debug("==============================================")
# Fix timeout=0 infinite loop: default to DEFAULT_TIMEOUT_MS
if timeout == 0:
timeout = DEFAULT_TIMEOUT_MS
n = 0
start_time = time.monotonic()
exc = PandaSpiException()
while (timeout == 0) or (time.monotonic() - start_time) < timeout*1e-3:
# Use the timeout for the overall loop, matching original behavior but with timeout=0 fixed
while (time.monotonic() - start_time) < timeout * 1e-3:
n += 1
logging.debug("\ntry #%d", n)
with self.dev.acquire() as spi:
@@ -238,6 +248,7 @@ class PandaSpiHandle(BaseHandle):
exc = e
logging.debug("SPI transfer failed, retrying", exc_info=True)
logging.error("SPI transfer failed after %d tries, %.2fms", n, (time.monotonic() - start_time) * 1000)
raise exc
def get_protocol_version(self) -> bytes:
+45 -20
View File
@@ -48,13 +48,12 @@ class CarController(CarControllerBase):
self.lka_icon_status_last = (False, False)
self.params = CarControllerParams(self.CP)
self.is_volt = self.CP.carFingerprint in (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_CC)
if self.is_volt:
self.mass = CP.mass
self.tireRadius = 0.075 * CP.wheelbase + 0.1453
self.frontalArea = 1.05 * CP.wheelbase + 0.0679
self.coeffDrag = 0.30
self.airDensity = 1.225
self.is_volt = self.CP.carFingerprint in (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_CC)
self.mass = CP.mass
self.tireRadius = 0.075 * CP.wheelbase + 0.1453
self.frontalArea = 1.05 * CP.wheelbase + 0.0679
self.coeffDrag = 0.30
self.airDensity = 1.225
self.params_ = Params()
self.packer_pt = CANPacker(DBC[self.CP.carFingerprint]['pt'])
@@ -166,21 +165,46 @@ class CarController(CarControllerBase):
accel = clip(accel, self.params.ACCEL_MIN, self.params.ACCEL_MAX)
brake_accel = clip(brake_accel, self.params.ACCEL_MIN, self.params.ACCEL_MAX)
if self.CP.carFingerprint in EV_CAR:
self.params.update_ev_gas_brake_threshold(CS.out.vEgo)
self.apply_gas = int(round(interp(accel, self.params.EV_GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
self.apply_brake = int(round(interp(brake_accel, self.params.EV_BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
if self.CP.carFingerprint in EV_CAR:
self.params.update_ev_gas_brake_threshold(CS.out.vEgo)
self.apply_gas = int(round(interp(accel, self.params.EV_GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
self.apply_brake = int(round(interp(brake_accel, self.params.EV_BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
else:
self.apply_gas = int(round(interp(accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
self.apply_brake = int(round(interp(brake_accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
# Clamp within message-valid ranges to avoid ASCM faults from overshoot or rounding
self.apply_gas = int(round(clip(self.apply_gas, self.params.MAX_ACC_REGEN, self.params.MAX_GAS)))
self.apply_brake = int(round(clip(self.apply_brake, 0, self.params.MAX_BRAKE)))
if self.apply_brake > 0:
# Volt should never present positive torque alongside friction braking
self.apply_gas = self.params.INACTIVE_REGEN
else:
self.apply_gas = int(round(interp(accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
if len(CC.orientationNED) == 3 and CS.out.vEgo > self.CP.vEgoStopping:
accel_due_to_pitch = math.sin(CC.orientationNED[1]) * ACCELERATION_DUE_TO_GRAVITY
else:
accel_due_to_pitch = 0.0
gas_max = self.params.MAX_GAS
accel_max = self.params.ACCEL_MAX
accel = clip(actuators.accel + accel_due_to_pitch, self.params.ACCEL_MIN, accel_max)
torque = self.tireRadius * ((self.mass * accel) + (0.5 * self.coeffDrag * self.frontalArea * self.airDensity * CS.out.vEgo ** 2))
scaled_torque = torque + self.params.ZERO_GAS
apply_gas_torque = clip(scaled_torque, self.params.MAX_ACC_REGEN, gas_max)
BRAKE_SWITCH = int(round(interp(CS.out.vEgo, self.params.BRAKE_SWITCH_LOOKUP_BP, self.params.BRAKE_SWITCH_LOOKUP_V)))
brake_accel = min((scaled_torque - BRAKE_SWITCH) / (self.tireRadius * self.mass), 0)
self.apply_gas = int(round(apply_gas_torque))
self.apply_brake = int(round(interp(brake_accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
# Clamp within message-valid ranges to avoid ASCM faults from overshoot or rounding
self.apply_gas = int(round(clip(self.apply_gas, self.params.MAX_ACC_REGEN, self.params.MAX_GAS)))
self.apply_brake = int(round(clip(self.apply_brake, 0, self.params.MAX_BRAKE)))
# Clamp within message-valid ranges to avoid ASCM faults from overshoot or rounding
self.apply_gas = int(round(clip(self.apply_gas, self.params.MAX_ACC_REGEN, self.params.MAX_GAS)))
self.apply_brake = int(round(clip(self.apply_brake, 0, self.params.MAX_BRAKE)))
if self.is_volt and self.apply_brake > 0:
# Volt should never present positive torque alongside friction braking
self.apply_gas = self.params.INACTIVE_REGEN
if self.apply_brake > 0 and self.apply_gas > self.params.INACTIVE_REGEN:
self.apply_gas = self.params.INACTIVE_REGEN
# Don't allow any gas above inactive regen while stopping
# FIXME: brakes aren't applied immediately when enabling at a stop
if stopping:
@@ -198,10 +222,11 @@ class CarController(CarControllerBase):
idx = (self.frame // 4) % 4
if self.CP.flags & GMFlags.CC_LONG.value:
if CC.longActive and CS.out.vEgo > self.CP.minEnableSpeed:
if CC.longActive and CS.out.cruiseState.enabled and CS.out.vEgo > self.CP.minEnableSpeed:
# Using extend instead of append since the message is only sent intermittently
can_sends.extend(gmcan.create_gm_cc_spam_command(self.packer_pt, self, CS, actuators, frogpilot_toggles))
elif CC.enabled and self.frame % 52 == 0 and CS.cruise_buttons == CruiseButtons.UNPRESS and CS.out.gasPressed and CS.out.cruiseState.speed < CS.out.vEgo < hud_v_cruise:
elif (CS.out.cruiseState.enabled and CC.enabled and self.frame % 52 == 0 and
CS.cruise_buttons == CruiseButtons.UNPRESS and CS.out.gasPressed and CS.out.cruiseState.speed < CS.out.vEgo < hud_v_cruise):
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.POWERTRAIN, (CS.buttons_counter + 1) % 4, CruiseButtons.DECEL_SET))
if self.CP.enableGasInterceptor:
can_sends.append(create_gas_interceptor_command(self.packer_pt, interceptor_gas_cmd, idx))
+3
View File
@@ -66,6 +66,9 @@ FINGERPRINTS = {
CAR.CHEVROLET_MALIBU: [{
190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 456: 8, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1013: 3, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1930: 7, 2016: 8, 2024: 8
}],
CAR.CHEVROLET_MALIBU_ASCM: [{
190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 456: 8, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1013: 3, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1930: 7, 2016: 8, 2024: 8
}],
CAR.GMC_ACADIA: [{
190: 6, 192: 5, 193: 8, 197: 8, 199: 4, 201: 6, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 1, 290: 1, 298: 8, 304: 8, 309: 8, 313: 8, 320: 8, 322: 7, 328: 1, 352: 7, 368: 8, 381: 8, 384: 8, 386: 8, 388: 8, 393: 8, 398: 8, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 458: 8, 460: 4, 462: 4, 463: 3, 479: 3, 481: 7, 485: 8, 489: 5, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 512: 3, 530: 8, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 567: 5, 568: 2, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 789: 5, 800: 6, 801: 8, 803: 8, 804: 3, 805: 8, 832: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1003: 5, 1005: 6, 1009: 8, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1906: 7, 1907: 7, 1912: 7, 1914: 7, 1918: 7, 1919: 7, 1920: 7, 1930: 7
},
+44 -28
View File
@@ -35,6 +35,7 @@ VOLT_LIKE_CARS = (
CAR.CHEVROLET_VOLT_CAMERA,
CAR.CHEVROLET_VOLT_ASCM,
CAR.CHEVROLET_MALIBU,
CAR.CHEVROLET_MALIBU_ASCM,
CAR.CHEVROLET_MALIBU_SDGM,
CAR.CHEVROLET_MALIBU_CC,
CAR.CHEVROLET_MALIBU_HYBRID_CC,
@@ -50,6 +51,10 @@ NON_LINEAR_TORQUE_PARAMS = {
class CarInterface(CarInterfaceBase):
def __init__(self, CP, FPCP, CarController, CarState):
super().__init__(CP, FPCP, CarController, CarState)
self.steer_offset = 0.0
@staticmethod
def get_pid_accel_limits(CP, current_speed, cruise_speed):
return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX
@@ -91,30 +96,44 @@ class CarInterface(CarInterfaceBase):
torque_values, lataccel_values = self.get_lataccel_torque_siglin()
def torque_from_lateral_accel_siglin(lateral_acceleration: float, torque_params: car.CarParams.LateralTorqueTuning):
return np.interp(lateral_acceleration, lataccel_values, torque_values)
return float(np.interp(lateral_acceleration, lataccel_values, torque_values) + self.steer_offset)
return torque_from_lateral_accel_siglin
else:
return self.torque_from_lateral_accel_linear
def torque_from_lateral_accel_linear(lateral_acceleration: float, torque_params: car.CarParams.LateralTorqueTuning):
return self.torque_from_lateral_accel_linear(lateral_acceleration, torque_params) + self.steer_offset
return torque_from_lateral_accel_linear
def lateral_accel_from_torque(self) -> LateralAccelFromTorqueCallbackType:
if self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS:
torque_values, lataccel_values = self.get_lataccel_torque_siglin()
def lateral_accel_from_torque_siglin(torque: float, torque_params: car.CarParams.LateralTorqueTuning):
return np.interp(torque, torque_values, lataccel_values)
return np.interp(torque - self.steer_offset, torque_values, lataccel_values)
return lateral_accel_from_torque_siglin
else:
return self.lateral_accel_from_torque_linear
def lateral_accel_from_torque_linear(torque: float, torque_params: car.CarParams.LateralTorqueTuning):
return self.lateral_accel_from_torque_linear(torque - self.steer_offset, torque_params)
return lateral_accel_from_torque_linear
def update(self, c: car.CarControl, can_strings: list[bytes], frogpilot_toggles) -> car.CarState:
self.steer_offset = float(getattr(frogpilot_toggles, "steer_offset", 0.0))
return super().update(c, can_strings, frogpilot_toggles)
@staticmethod
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs, frogpilot_toggles):
ret.carName = "gm"
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.gm)]
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.noOutput),
get_safety_config(car.CarParams.SafetyModel.gm)]
ret.autoResumeSng = False
ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN]
# Detect Beartech SASCM allows openpilot longitudinal control on SDGM and ASCM_INT vehicles
if 0x2FF in fingerprint[0]:
ret.flags |= GMFlags.SASCM.value
if PEDAL_MSG in fingerprint[0]:
ret.enableGasInterceptor = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_GAS_INTERCEPTOR
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_GAS_INTERCEPTOR
# When a pedal interceptor is present, always use normal longitudinal (block stock cruise)
experimental_long = False
@@ -133,32 +152,32 @@ class CarInterface(CarInterfaceBase):
ret.minEnableSpeed = 5 * CV.KPH_TO_MS
ret.minSteerSpeed = 10 * CV.KPH_TO_MS
if candidate in SDGM_CAR:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_SDGM
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_SDGM
# Use C9 brake bit only on SDGM variants that lack 0xBE (ECMAcceleratorPos)
if ACCELERATOR_POS_MSG not in fingerprint[CanBus.POWERTRAIN]:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_FORCE_BRAKE_C9
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_FORCE_BRAKE_C9
ret.flags |= GMFlags.FORCE_BRAKE_C9.value
ret.minEnableSpeed = -1. # engage speed is decided by pcm
ret.minSteerSpeed = 7 * CV.MPH_TO_MS
elif candidate in ASCM_INT:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_CAM
ret.minSteerSpeed = 7 * CV.MPH_TO_MS
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_ASCM_INT
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_ASCM_INT
else:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_CAM
# Tuning for experimental long
ret.longitudinalTuning.kiV = [1.0, 1.0]
ret.longitudinalTuning.kiV = [0.5, 0.5]
ret.stoppingDecelRate = 1.0 # reach brake quickly after enabling
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
ret.stopAccel = -0.20
ret.stopAccel = -0.25
if ret.experimentalLongitudinalAvailable and experimental_long:
ret.pcmCruise = False
ret.openpilotLongitudinalControl = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
else: # ASCM, OBD-II harness
ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long
@@ -178,7 +197,7 @@ class CarInterface(CarInterfaceBase):
if ret.enableGasInterceptor:
# Need to set ASCM long limits when using pedal interceptor, instead of camera ACC long limits
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_ASCM_LONG
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_ASCM_LONG
# Start with a baseline tuning for all GM vehicles. Override tuning as needed in each model section below.
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
@@ -199,11 +218,7 @@ class CarInterface(CarInterfaceBase):
ret.minEnableSpeed = -1
if candidate in VOLT_LIKE_CARS:
ret.lateralTuning.pid.kpBP = [0., 40.]
ret.lateralTuning.pid.kpV = [0., 0.17]
ret.lateralTuning.pid.kiBP = [0.]
ret.lateralTuning.pid.kiV = [0.]
ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt()
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
ret.steerActuatorDelay = 0.2
elif candidate == CAR.GMC_ACADIA:
@@ -304,7 +319,7 @@ class CarInterface(CarInterfaceBase):
if ret.enableGasInterceptor and frogpilot_toggles.gm_pedal_longitudinal:
ret.networkLocation = NetworkLocation.fwdCamera
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_CAM
ret.minEnableSpeed = -1
ret.pcmCruise = False
ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long
@@ -313,7 +328,7 @@ class CarInterface(CarInterfaceBase):
if candidate in CC_ONLY_CAR:
ret.flags |= GMFlags.PEDAL_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_PEDAL_LONG
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_PEDAL_LONG
# Note: Low speed, stop and go not tested. Should be fairly smooth on highway
ret.longitudinalTuning.kiBP = [0.0, 5., 35.]
ret.longitudinalTuning.kiV = [0.0, 0.35, 0.5]
@@ -323,7 +338,7 @@ class CarInterface(CarInterfaceBase):
ret.pcmCruise = False
ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long
else: # Pedal used for SNG, ACC for longitudinal control otherwise
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
ret.startingState = True
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
@@ -331,7 +346,7 @@ class CarInterface(CarInterfaceBase):
elif candidate in CC_ONLY_CAR:
ret.flags |= GMFlags.CC_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_CC_LONG
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_CC_LONG
ret.radarUnavailable = True
ret.experimentalLongitudinalAvailable = False
ret.minEnableSpeed = 24 * CV.MPH_TO_MS
@@ -353,12 +368,12 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kiV = [0.1]
if candidate in CC_ONLY_CAR:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_ACC
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_NO_ACC
# Exception for flashed cars, or cars whose camera was removed
if (ret.networkLocation == NetworkLocation.fwdCamera or candidate in CC_ONLY_CAR) and CAM_MSG not in fingerprint[CanBus.CAMERA] and not candidate in (SDGM_CAR | ASCM_INT):
ret.flags |= GMFlags.NO_CAMERA.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_CAMERA
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_GM_NO_CAMERA
if ACCELERATOR_POS_MSG not in fingerprint[CanBus.POWERTRAIN]:
ret.flags |= GMFlags.NO_ACCELERATOR_POS_MSG.value
@@ -400,8 +415,9 @@ class CarInterface(CarInterfaceBase):
if ret.vEgo < self.CP.minSteerSpeed:
events.add(EventName.belowSteerSpeed)
if (self.CP.flags & GMFlags.CC_LONG.value) and ret.vEgo < self.CP.minEnableSpeed and ret.cruiseState.enabled:
events.add(EventName.speedTooLow)
if (self.CP.flags & GMFlags.CC_LONG.value) and ret.vEgo < self.CP.minEnableSpeed:
if ret.cruiseState.enabled or self.CS.out.cruiseState.enabled:
events.add(EventName.speedTooLow)
if (self.CP.flags & GMFlags.PEDAL_LONG.value) and \
self.CP.transmissionType == TransmissionType.direct and \
+16 -11
View File
@@ -38,12 +38,12 @@ class CarControllerParams:
def __init__(self, CP):
# Gas/brake lookups
self.ZERO_GAS = 6144 # Coasting
self.ZERO_GAS = 6150 # Coasting
self.MAX_BRAKE = 400 # ~ -4.0 m/s^2 with regen
self.BRAKE_SWITCH_MAX = self.ZERO_GAS
if CP.carFingerprint in (CAMERA_ACC_CAR | SDGM_CAR) and CP.carFingerprint not in CC_ONLY_CAR and CP.carFingerprint != CAR.CHEVROLET_BOLT_EUV:
self.MAX_GAS = 7496
self.MAX_GAS = 8848
self.MAX_GAS_PLUS = 8848
self.MAX_ACC_REGEN = 5610
self.INACTIVE_REGEN = 5650
@@ -52,8 +52,8 @@ class CarControllerParams:
self.max_regen_acceleration = 0.
else:
self.MAX_GAS = 7168 # Safety limit, not ACC max. Stock ACC >8192 from standstill.
self.MAX_GAS_PLUS = 8191 # 8292 uses new bit, possible but not tested. Matches Twilsonco tw-main max
self.MAX_GAS = 8191 # Safety limit, not ACC max. Stock ACC >8192 from standstill.
self.MAX_GAS_PLUS = 8191
self.MAX_ACC_REGEN = 5500 # Max ACC regen is slightly less than max paddle regen
self.INACTIVE_REGEN = 5500
# ICE has much less engine braking force compared to regen in EVs,
@@ -144,6 +144,10 @@ class CAR(Platforms):
[GMCarDocs("Chevrolet Malibu Premier 2017")],
GMCarSpecs(mass=1496, wheelbase=2.83, steerRatio=15.8, centerToFrontRatio=0.4),
)
CHEVROLET_MALIBU_ASCM = GMPlatformConfig(
[GMCarDocs("Chevrolet Malibu 2017-19 ASCM Harness")],
CHEVROLET_MALIBU.specs,
)
GMC_ACADIA = GMASCMPlatformConfig(
[GMCarDocs("GMC Acadia 2018", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo")],
GMCarSpecs(mass=1975, wheelbase=2.86, steerRatio=14.4, centerToFrontRatio=0.4),
@@ -293,12 +297,12 @@ class AccState:
STANDSTILL = 4
class CanBus:
POWERTRAIN = 0
OBSTACLE = 1
CAMERA = 2
CHASSIS = 2
LOOPBACK = 128
DROPPED = 192
POWERTRAIN = 4
OBSTACLE = 5
CAMERA = 6
CHASSIS = 6
LOOPBACK = 132
DROPPED = 196
class GMFlags(IntFlag):
PEDAL_LONG = 1
@@ -306,6 +310,7 @@ class GMFlags(IntFlag):
NO_CAMERA = 4
NO_ACCELERATOR_POS_MSG = 8
FORCE_BRAKE_C9 = 16
SASCM = 32
# In a Data Module, an identifier is a string used to recognize an object,
@@ -364,7 +369,7 @@ CC_ONLY_CAR = {CAR.CHEVROLET_VOLT_CC, CAR.CHEVROLET_BOLT_CC, CAR.CHEVROLET_EQUIN
# We're integrated at the Safety Data Gateway Module on these cars
SDGM_CAR = {CAR.CADILLAC_XT4, CAR.CADILLAC_XT6, CAR.CHEVROLET_TRAVERSE, CAR.CHEVROLET_BLAZER, CAR.CHEVROLET_MALIBU_SDGM, CAR.BUICK_BABYENCLAVE, CAR.CHEVROLET_VOLT_2019}
ASCM_INT = {CAR.CHEVROLET_VOLT_ASCM, CAR.GMC_ACADIA_ASCM}
ASCM_INT = {CAR.CHEVROLET_VOLT_ASCM, CAR.GMC_ACADIA_ASCM, CAR.CHEVROLET_MALIBU_ASCM}
# We're integrated at the camera with VOACC on these cars (instead of ASCM w/ OBD-II harness)
CAMERA_ACC_CAR = {CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_SILVERADO, CAR.CHEVROLET_EQUINOX, CAR.CHEVROLET_TRAILBLAZER, CAR.CHEVROLET_TRAX, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_BLAZER}
+2 -1
View File
@@ -42,7 +42,7 @@ FRICTION_THRESHOLD = 0.09
def get_friction_threshold(v_ego):
# Interpolate friction threshold from 0.09 at 50 mph to 0.15 at 75 mph
from openpilot.common.numpy_fast import interp
return interp(v_ego, [50 * CV.MPH_TO_MS, 75 * CV.MPH_TO_MS], [0.09, 0.15])
return interp(v_ego, [1 * CV.MPH_TO_MS, 75 * CV.MPH_TO_MS], [0.12, 0.25])
TORQUE_PARAMS_PATH = os.path.join(BASEDIR, 'selfdrive/car/torque_data/params.toml')
TORQUE_OVERRIDE_PATH = os.path.join(BASEDIR, 'selfdrive/car/torque_data/override.toml')
@@ -187,6 +187,7 @@ class CarInterfaceBase(ABC):
elif platform in GMCAR:
fp_ret.canUsePedal = True
fp_ret.canUseSASCM = True
elif platform in HondaCAR:
if candidate == HondaCAR.HONDA_CLARITY:
+1
View File
@@ -5,6 +5,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"AUDI_A3_MK3" = [1.5122414863077502, 1.7443517531719404, 0.15194151892450905]
"AUDI_Q3_MK2" = [1.4439223359448605, 1.2254955789112076, 0.1413798895978097]
"CHEVROLET_VOLT" = [1.5961527626411784, 1.8422651988094612, 0.1572393918005158]
"CHEVROLET_MALIBU_HYBRID_CC" = [1.5961527626411784, 1.8422651988094612, 0.1572393918005158]
"CHRYSLER_PACIFICA_2018" = [2.07140, 1.3366521181047952, 0.13776367250652022]
"CHRYSLER_PACIFICA_2020" = [1.86206, 1.509076559398423, 0.14328246159386085]
"CHRYSLER_PACIFICA_2017_HYBRID" = [1.79422, 1.06831764583744, 0.116237]
+1 -1
View File
@@ -56,9 +56,9 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"CADILLAC_ESCALADE_ESV" = "CHEVROLET_VOLT"
"CADILLAC_ATS" = "CHEVROLET_VOLT"
"CHEVROLET_MALIBU" = "CHEVROLET_VOLT"
"CHEVROLET_MALIBU_ASCM" = "CHEVROLET_VOLT"
"CHEVROLET_MALIBU_SDGM" = "CHEVROLET_VOLT"
"CHEVROLET_MALIBU_CC" = "CHEVROLET_VOLT"
"CHEVROLET_MALIBU_HYBRID_CC" = "CHEVROLET_VOLT"
"HOLDEN_ASTRA" = "CHEVROLET_VOLT"
"CHEVROLET_VOLT_CC" = "CHEVROLET_VOLT"
"CHEVROLET_VOLT_CAMERA" = "CHEVROLET_VOLT"
+10 -3
View File
@@ -1,20 +1,21 @@
import math
from cereal import log
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
from openpilot.selfdrive.controls.lib.latcontrol import LatControl, MIN_LATERAL_CONTROL_SPEED
from openpilot.selfdrive.controls.lib.pid import PIDController
class LatControlPID(LatControl):
def __init__(self, CP, CI, dt):
super().__init__(CP, CI, dt)
self.steer_release_i_decay = 0.8
self.prev_steering_pressed = False
self.pid = PIDController((CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
(CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
pos_limit=self.steer_max, neg_limit=-self.steer_max)
self.ff_factor = CP.lateralTuning.pid.kf
self.get_steer_feedforward = CI.get_steer_feedforward_function()
self.low_speed_reset_threshold = 7 * CV.MPH_TO_MS
self.low_speed_reset_threshold = max(CP.minSteerSpeed, MIN_LATERAL_CONTROL_SPEED)
def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, curvature_limited, lat_delay, llk, model_data, frogpilot_toggles):
pid_log = log.ControlsState.LateralPIDState.new_message()
@@ -30,8 +31,12 @@ class LatControlPID(LatControl):
if not active:
output_torque = 0.0
pid_log.active = False
self.pid.reset()
else:
if self.prev_steering_pressed and not CS.steeringPressed:
self.pid.i *= self.steer_release_i_decay
# offset does not contribute to resistive torque
ff = self.ff_factor * self.get_steer_feedforward(angle_steers_des_no_offset, CS.vEgo)
if CS.vEgo < self.low_speed_reset_threshold:
@@ -50,4 +55,6 @@ class LatControlPID(LatControl):
pid_log.output = float(output_torque)
pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_safety, curvature_limited))
self.prev_steering_pressed = CS.steeringPressed
return output_torque, angle_steers_des, pid_log
+10 -4
View File
@@ -3,11 +3,10 @@ import numpy as np
from collections import deque
from cereal import log
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car.interfaces import FRICTION_THRESHOLD, get_friction_threshold
from openpilot.selfdrive.controls.lib.drive_helpers import MIN_SPEED, get_friction
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
from openpilot.selfdrive.controls.lib.latcontrol import LatControl, MIN_LATERAL_CONTROL_SPEED
from openpilot.selfdrive.controls.lib.pid import PIDController
from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
@@ -41,6 +40,8 @@ VERSION = 2
class LatControlTorque(LatControl):
def __init__(self, CP, CI, dt):
super().__init__(CP, CI, dt)
self.steer_release_i_decay = 0.8
self.prev_steering_pressed = False
self.torque_params = CP.lateralTuning.torque
self.torque_from_lateral_accel = CI.torque_from_lateral_accel()
self.lateral_accel_from_torque = CI.lateral_accel_from_torque()
@@ -53,7 +54,7 @@ class LatControlTorque(LatControl):
self.jerk_filter = FirstOrderFilter(0.0, 1 / (2 * np.pi * LP_FILTER_CUTOFF_HZ), self.dt)
self.previous_measurement = 0.0
self.measurement_rate_filter = FirstOrderFilter(0.0, 1 / (2 * np.pi * (MAX_LAT_JERK_UP - 0.5)), self.dt)
self.low_speed_reset_threshold = 7 * CV.MPH_TO_MS
self.low_speed_reset_threshold = max(CP.minSteerSpeed, MIN_LATERAL_CONTROL_SPEED)
def update_live_torque_params(self, latAccelFactor, latAccelOffset, friction):
self.torque_params.latAccelFactor = latAccelFactor
@@ -76,6 +77,9 @@ class LatControlTorque(LatControl):
self.measurement_rate_filter.x = 0.0
self.lat_accel_request_buffer = deque([0.] * self.lat_accel_request_buffer_len , maxlen=self.lat_accel_request_buffer_len)
else:
if self.prev_steering_pressed and not CS.steeringPressed:
self.pid.i *= self.steer_release_i_decay
measured_curvature = -VM.calc_curvature(math.radians(CS.steeringAngleDeg - params.angleOffsetDeg), CS.vEgo, params.roll)
roll_compensation = params.roll * ACCELERATION_DUE_TO_GRAVITY
curvature_deadzone = abs(VM.calc_curvature(math.radians(self.steering_angle_deadzone_deg), CS.vEgo, 0.0))
@@ -125,5 +129,7 @@ class LatControlTorque(LatControl):
pid_log.desiredLateralJerk = float(desired_lateral_jerk)
pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_safety, curvature_limited))
self.prev_steering_pressed = CS.steeringPressed
# TODO left is positive in this convention
return -output_torque, 0.0, pid_log
return -output_torque, 0.0, pid_log
@@ -5,7 +5,6 @@ import numpy as np
from cereal import log
from openpilot.common.numpy_fast import clip, interp
from openpilot.common.realtime import DT_MDL
from openpilot.common.swaglog import cloudlog
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.common.conversions import Conversions as CV
# WARNING: imports outside of constants will not trigger a rebuild
@@ -422,9 +421,6 @@ class LongitudinalMpc:
scale = float(np.interp(uncertainty, [0.45, 0.60], [1.2, 1.5]))
speed_jerk *= scale
if abs(filter_time_factor - prev_filter_time_factor) > 1e-3:
cloudlog.error(f"LON_FILTER; filter_time_factor={filter_time_factor:.2f}; uncertainty={uncertainty:.3f}; v_ego={v_ego:.2f} mps; lead_dist={lead_dist:.2f} m; accel_reengage={accel_reengage}")
if self.mode == 'acc':
a_change_cost = acceleration_jerk if prev_accel_constraint else 0
cost_weights = [self.current_x_ego_cost, X_EGO_COST, V_EGO_COST, A_EGO_COST, a_change_cost, speed_jerk]
@@ -627,11 +623,7 @@ class LongitudinalMpc:
self.prev_a = np.interp(T_IDXS + self.dt, T_IDXS, self.a_solution)
t = time.monotonic()
if self.solution_status != 0:
if t > self.last_cloudlog_t + 5.0:
self.last_cloudlog_t = t
cloudlog.warning(f"Long mpc reset, solution_status: {self.solution_status}")
self.reset()
# reset = 1
# print(f"long_mpc timings: total internal {self.solve_time:.2e}, external: {(time.monotonic() - t0):.2e} qp {self.time_qp_solution:.2e}, \
+1 -17
View File
@@ -111,9 +111,6 @@ class LongitudinalPlanner:
self.a_desired_trajectory = np.zeros(CONTROL_N)
self.j_desired_trajectory = np.zeros(CONTROL_N)
self.solverExecutionTime = 0.0
# logging cadence & state
self.last_uncert_log_t = 0.0
self.prev_uncert_over = False
# ---- Rubberband mitigation state ----
# Two uncertainty tracks (slow/fast) for asymmetric gating
@@ -138,7 +135,7 @@ class LongitudinalPlanner:
@property
def mlsim(self):
return self.generation in ("v8", "v10", "v11")
return self.generation in ("v8", "v10", "v11", "v12")
def get_mpc_mode(self) -> str:
"""
@@ -344,19 +341,6 @@ class LongitudinalPlanner:
# now_t defined earlier
over = uncertainty > 1.0
# Log on threshold edge or at ~1 Hz
if over != self.prev_uncert_over or (now_t - self.last_uncert_log_t) > 1.0:
try:
cloudlog.error(
f"LON_UNCERT; v_ego={v_ego:.2f} mps; desireEntropy={desire_entropy:.3f}; "
f"brakeRawMax={(raw_brake_max if 'raw_brake_max' in locals() else -1.0):.3f}; "
f"brakeDecayed={(disengage_risk if 'disengage_risk' in locals() else -1.0):.3f}; "
f"lam={(lam if 'lam' in locals() else -1.0):.2f}; uncertainty={uncertainty:.3f}; over={over}"
)
except Exception as e:
cloudlog.warning(f"LON_UNCERT log error: {e}")
self.prev_uncert_over = over
self.last_uncert_log_t = now_t
# Asymmetric accel release with hysteresis + dwell to prevent on/off pulsing
rise_dwell_s, fall_dwell_s = 0.6, 0.4
+3 -3
View File
@@ -33,7 +33,7 @@ class DRIVER_MONITOR_SETTINGS:
self._SG_THRESHOLD = 0.9
self._BLINK_THRESHOLD = 0.865
self._EE_THRESH11 = 0.4
self._EE_THRESH11 = 0.6
self._EE_THRESH12 = 15.0
self._EE_MAX_OFFSET1 = 0.06
self._EE_MIN_OFFSET1 = 0.025
@@ -44,9 +44,9 @@ class DRIVER_MONITOR_SETTINGS:
self._POSE_YAW_THRESHOLD = 0.4020
self._POSE_YAW_THRESHOLD_SLACK = 0.5042
self._POSE_YAW_THRESHOLD_STRICT = self._POSE_YAW_THRESHOLD
self._PITCH_NATURAL_OFFSET = 0.029 # initial value before offset is learned
self._PITCH_NATURAL_OFFSET = 0.011 # initial value before offset is learned
self._PITCH_NATURAL_THRESHOLD = 0.449
self._YAW_NATURAL_OFFSET = 0.097 # initial value before offset is learned
self._YAW_NATURAL_OFFSET = 0.075 # initial value before offset is learned
self._PITCH_MAX_OFFSET = 0.124
self._PITCH_MIN_OFFSET = -0.0881
self._YAW_MAX_OFFSET = 0.289
Binary file not shown.
Binary file not shown.
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;تعديلات Twilsonco المعتمدة على العزم لتنعيم التوجيه في المنعطفات.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1200,6 +1200,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsonco make torque tweak. Steering smooth in curve.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3802,6 +3818,14 @@ Developer - Many custom setting for seasoned enthusiast</translation>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsoncos drehmomentbasierte Anpassungen zur Glättung der Lenkung in Kurven.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Entwickler Hochgradig anpassbare Einstellungen für versierte Enthusiasten</
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1201,6 +1201,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Quack! Twilsoncos torque tweaks to smooth out steering in curves, waddle-waddle.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3800,6 +3816,14 @@ Developer - Ultra-custom settings for seasoned duckthusiasts</translation>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Ajustes basados en par de Twilsonco para suavizar la dirección en curvas.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3797,6 +3813,14 @@ Desarrollador: configuración altamente personalizable para entusiastas veterano
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Ajustements basés sur le couple de Twilsonco pour adoucir la direction dans les virages.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3797,6 +3813,14 @@ Développeur Paramètres hautement personnalisables pour passionnés chevron
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Ribbit! Twilsoncos torque tweaks smooth steering through curves, croak.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Developer - Highly customizable settings for seasoned swamp pros</translation>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsoncoのトルクベース調整&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3796,6 +3812,14 @@ Developer - こだわりのある上級者向けの高度にカスタマイズ
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt; Twilsonco의 .&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3797,6 +3813,14 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsoncos torque-based tweaks t smooth out steerin in curves, arr!&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Developer - Highly customizable riggins fer seasoned enthusiasts</translation
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Ajustes baseados em torque do Twilsonco para suavizar a direção em curvas.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Desenvolvedor - Configurações altamente personalizáveis para entusiastas expe
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
@@ -1203,6 +1203,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsoncos torque-wrought tweaks to make steering flow smoother midst the curves.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3808,6 +3824,14 @@ Developer - Most customizable settings for well-tried enthusiasts</translation>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt; Twilsonco &lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Virajlarda direksiyonu yumuşatmak için Twilsonconun torka dayalı ayarlamaları.&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3797,6 +3813,14 @@ Geliştirici - Tecrübeli meraklılar için yüksek özelleştirilebilir ayarlar
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsonco &lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
+24
View File
@@ -1199,6 +1199,22 @@
<source>&lt;b&gt;Twilsonco's torque-based adjustments to smoothen out steering in curves.&lt;/b&gt;</source>
<translation type="gpt-5-generated">&lt;b&gt;Twilsonco 調&lt;/b&gt;</translation>
</message>
<message>
<source>Steer Offset (Default: %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Steer Offset</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Offsets steering torque to help compensate for alignment or tire issues.&lt;/b&gt; More negative pulls the car right; more positive pulls it left. Most users should not need to touch this.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset &lt;b&gt;Steer Offset&lt;/b&gt; to its default value?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotLongitudinalPanel</name>
@@ -3798,6 +3814,14 @@ Developer - 為資深愛好者提供高度自訂的設定</translation>
<source>&lt;b&gt;Use the pedal interceptor for longitudinal control&lt;/b&gt; instead of camera ACC/Redneck when available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SASCM Support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&lt;b&gt;Does your vehicle support "SASCMs"?&lt;/b&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FrogPilotVisualsPanel</name>
BIN
View File
Binary file not shown.
+62 -6
View File
@@ -92,6 +92,40 @@ def manager_init() -> None:
params.put_bool("IsTestedBranch", build_metadata.tested_channel)
params.put_bool("IsReleaseBranch", build_metadata.release_channel)
# One-time migration to align FrogPilot defaults after install
frogpilot_migration_flag_file = "/data/media/0/frogpilot_migrated.flag"
if not os.path.exists(frogpilot_migration_flag_file):
params.put_bool("NNFF", False)
params.put_bool("NNFFLite", False)
params.put_bool("AdvancedLateralTune", True)
params.put_bool("ForceAutoTuneOff", True)
params.put_bool("ForceAutoTune", False)
params.put_bool("CECurves", False)
params.put_bool("CENavigation", False)
params.put_bool("ShowCEMStatus", True)
params.put_bool("CESlowerLead", True)
params.put_bool("CEStoppedLead", True)
params.put_int("CEModelStopTime", 8)
params.put_bool("ReverseCruise", True)
params.put_bool("HumanFollowing", False)
params.put_bool("HumanAcceleration", False)
params.put_int("TuningLevel", 3)
params.put_bool("TuningLevelConfirmed", True)
params.put_bool("DeveloperUI", True)
params.put_bool("DeveloperWidgets", True)
params.put_bool("DeveloperSidebar", False)
params.put_bool("LeadInfo", True)
params.put_bool("BorderMetrics", True)
params.put_bool("ShowSteering", True)
params.put_bool("BlindSpotMetrics", True)
with open(frogpilot_migration_flag_file, "w") as f:
f.write("migrated")
# One-time migration for HumanAcceleration and HumanFollowing to off
migration_flag_file = "/data/media/0/frogpilot_human_toggles_migrated.flag"
if not os.path.exists(migration_flag_file):
@@ -110,13 +144,15 @@ def manager_init() -> None:
with open(nnfflite_migration_flag_file, "w") as f:
f.write("migrated")
# One-time migration for NNFF to on
nnff_migration_flag_file = "/data/media/0/frogpilot_nnff_migrated.flag"
if not os.path.exists(nnff_migration_flag_file):
# One-time migration to force NNFF + NNFFLite off
nnff_reset_flag_file = "/data/media/0/frogpilot_nnff_reset.flag"
if not os.path.exists(nnff_reset_flag_file):
if params.get_bool("NNFF"):
params.put_bool("NNFF", True)
with open(nnff_migration_flag_file, "w") as f:
f.write("migrated")
params.put_bool("NNFF", False)
if params.get_bool("NNFFLite"):
params.put_bool("NNFFLite", False)
with open(nnff_reset_flag_file, "w") as f:
f.write("reset")
# One-time migration for CEM settings
cem_migration_flag_file = "/data/media/0/frogpilot_cem_migrated.flag"
@@ -142,6 +178,26 @@ def manager_init() -> None:
with open(nnff_migration_flag_file, "w") as f:
f.write("migrated")
# One-time migration for lateral tuning/auto-tune preferences
lateral_tuning_migration_flag_file = "/data/media/0/frogpilot_lateral_tuning_migrated.flag"
if not os.path.exists(lateral_tuning_migration_flag_file):
if not params.get_bool("AdvancedLateralTune"):
params.put_bool("AdvancedLateralTune", True)
if params.get_bool("ForceAutoTune"):
params.put_bool("ForceAutoTune", False)
if not params.get_bool("ForceAutoTuneOff"):
params.put_bool("ForceAutoTuneOff", True)
with open(lateral_tuning_migration_flag_file, "w") as f:
f.write("migrated")
# One-time migration for MaxDesiredAcceleration to 4
max_desired_acceleration_migration_flag_file = "/data/media/0/frogpilot_max_desired_acceleration_migrated.flag"
if not os.path.exists(max_desired_acceleration_migration_flag_file):
if params.get_float("MaxDesiredAcceleration") != 4.0:
params.put_float("MaxDesiredAcceleration", 4.0)
with open(max_desired_acceleration_migration_flag_file, "w") as f:
f.write("migrated")
# set dongle id
reg_res = register(show_spinner=True)
if reg_res:
+23 -19
View File
@@ -1,5 +1,6 @@
"""Install exception handler for process crash."""
import glob
import os
import re
import sentry_sdk
import traceback
from datetime import datetime
@@ -9,15 +10,16 @@ from sentry_sdk.integrations.threading import ThreadingIntegration
from openpilot.common.params import Params
from openpilot.system.hardware import HARDWARE, PC
from openpilot.common.swaglog import cloudlog
from openpilot.system.hardware.hw import Paths
from openpilot.system.version import get_build_metadata, get_version
from openpilot.frogpilot.common.frogpilot_variables import ERROR_LOGS_PATH, params
class SentryProject(Enum):
# python project
SELFDRIVE = os.environ.get("SENTRY_DSN", "")
SELFDRIVE = "https://7305139359a548fcb348ec09497dc389@bugsink.firestar.link/1"
# native project
SELFDRIVE_NATIVE = os.environ.get("SENTRY_DSN", "")
SELFDRIVE_NATIVE = "https://7305139359a548fcb348ec09497dc389@bugsink.firestar.link/1"
def report_tombstone(fn: str, message: str, contents: str) -> None:
@@ -26,6 +28,12 @@ def report_tombstone(fn: str, message: str, contents: str) -> None:
with sentry_sdk.configure_scope() as scope:
scope.set_extra("tombstone_fn", fn)
scope.set_extra("tombstone", contents)
# Attach qlog for debugging context
qlogs = glob.glob(f"{Paths.log_root()}/*/qlog")
if qlogs:
scope.add_attachment(path=max(qlogs, key=os.path.getmtime), filename="qlog")
sentry_sdk.capture_message(message=message)
sentry_sdk.flush()
@@ -51,8 +59,14 @@ def capture_exception(*args, crash_log=True, **kwargs) -> None:
cloudlog.error("crash", exc_info=kwargs.get('exc_info', 1))
try:
sentry_sdk.capture_exception(*args, **kwargs)
sentry_sdk.flush() # https://github.com/getsentry/sentry-python/issues/291
with sentry_sdk.push_scope() as scope:
# Attach qlog for debugging context
qlogs = glob.glob(f"{Paths.log_root()}/*/qlog")
if qlogs:
scope.add_attachment(path=max(qlogs, key=os.path.getmtime), filename="qlog")
sentry_sdk.capture_exception(*args, **kwargs)
sentry_sdk.flush() # https://github.com/getsentry/sentry-python/issues/291
except Exception:
cloudlog.exception("sentry exception")
@@ -90,25 +104,15 @@ def save_exception(exc_text: str, crash_log) -> None:
def init(project: SentryProject) -> bool:
build_metadata = get_build_metadata()
FrogPilot = "frogai" in build_metadata.openpilot.git_origin.lower()
if not FrogPilot or PC:
if PC:
return False
build_metadata = get_build_metadata()
short_branch = build_metadata.channel
if short_branch in ["COMMA", "HEAD"]:
return
elif short_branch == "FrogPilot-Development":
env = "Development"
elif build_metadata.release_channel:
env = "Release"
elif short_branch == "FrogPilot-Testing":
env = short_branch
if re.search("test", short_branch, re.IGNORECASE):
env = "Testing"
elif build_metadata.tested_channel:
env = "Staging"
else:
env = short_branch
dongle_id = params.get("DongleId", encoding="utf-8")
installed = params.get("InstallDate", encoding="utf-8")
+65 -3
View File
@@ -184,6 +184,39 @@ def finalize_update(params) -> None:
"""Take the current OverlayFS merged view and finalize a copy outside of
OverlayFS, ready to be swapped-in at BASEDIR. Copy using shutil.copytree"""
def get_directory_size(path: str) -> int:
size = 0
for root, _, files in os.walk(path):
for name in files:
file_path = os.path.join(root, name)
if not os.path.islink(file_path):
try:
size += os.lstat(file_path).st_size
except FileNotFoundError:
pass
return size
total_size = get_directory_size(OVERLAY_MERGED)
copied_size = 0
def copy_with_progress(src, dst, *, follow_symlinks=True):
nonlocal copied_size
if os.path.islink(src):
linkto = os.readlink(src)
os.symlink(linkto, dst)
return dst
result = shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
try:
copied_size += os.lstat(src).st_size
if total_size > 0:
progress = min(int((copied_size / total_size) * 100), 100)
params.put("UpdaterState", f"finalizing update... {progress}%")
except FileNotFoundError:
pass
return result
# Remove the update ready flag and any old updates
cloudlog.info("creating finalized version of the overlay")
set_consistent_flag(False)
@@ -191,7 +224,12 @@ def finalize_update(params) -> None:
# Copy the merged overlay view and set the update ready flag
if os.path.exists(FINALIZED):
shutil.rmtree(FINALIZED)
shutil.copytree(OVERLAY_MERGED, FINALIZED, symlinks=True)
if total_size == 0:
shutil.copytree(OVERLAY_MERGED, FINALIZED, symlinks=True)
else:
params.put("UpdaterState", "finalizing update... 0%")
shutil.copytree(OVERLAY_MERGED, FINALIZED, symlinks=True, copy_function=copy_with_progress)
params.put("UpdaterState", "finalizing update... 100%")
run(["git", "reset", "--hard"], FINALIZED)
run(["git", "submodule", "foreach", "--recursive", "git", "reset", "--hard"], FINALIZED)
@@ -377,10 +415,34 @@ class Updater:
else:
cloudlog.info(f"up to date on {cur_branch} ({str(cur_commit)[:7]})")
def _git_fetch_with_progress(self, branch: str) -> str:
fetch_cmd = ["git", "fetch", "--progress", "origin", branch]
progress = 0
output_lines: list[str] = []
with subprocess.Popen(fetch_cmd, cwd=OVERLAY_MERGED, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1) as proc:
assert proc.stdout is not None
for line in proc.stdout:
output_lines.append(line)
matches = re.findall(r"(\d+)%", line)
if matches:
progress = max(progress, int(matches[-1]))
self.params.put("UpdaterState", f"downloading... {progress}%")
proc.wait()
if proc.returncode != 0:
raise subprocess.CalledProcessError(proc.returncode, fetch_cmd, output=''.join(output_lines))
if progress < 100:
self.params.put("UpdaterState", "downloading... 100%")
return ''.join(output_lines)
def fetch_update(self) -> None:
cloudlog.info("attempting git fetch inside staging overlay")
self.params.put("UpdaterState", "downloading...")
self.params.put("UpdaterState", "downloading... 0%")
# TODO: cleanly interrupt this and invalidate old update
set_consistent_flag(False)
@@ -389,7 +451,7 @@ class Updater:
setup_git_options(OVERLAY_MERGED)
branch = self.target_branch
git_fetch_output = run(["git", "fetch", "origin", branch], OVERLAY_MERGED)
git_fetch_output = self._git_fetch_with_progress(branch)
cloudlog.info("git fetch success: %s", git_fetch_output)
cloudlog.info("git reset in progress")