diff --git a/selfdrive/ui/qt/offroad/developer_panel.cc b/selfdrive/ui/qt/offroad/developer_panel.cc
index e679720a1b..c5adc79ac2 100644
--- a/selfdrive/ui/qt/offroad/developer_panel.cc
+++ b/selfdrive/ui/qt/offroad/developer_panel.cc
@@ -57,6 +57,11 @@ DeveloperPanel::DeveloperPanel(SettingsWindow *parent) : ListWidget(parent) {
});
addItem(hyundaiRadarTracksToggle);
+#if SUNNYPILOT
+ neuralNetworkLateralControlToggle = neuralNetworkLateralControl.toggle;
+ addItem(neuralNetworkLateralControlToggle);
+#endif
+
auto enableGithubRunner = new ParamControl("EnableGithubRunner", tr("Enable GitHub runner service"), tr("Enables or disables the github runner service."), "");
addItem(enableGithubRunner);
@@ -111,6 +116,7 @@ void DeveloperPanel::updateToggles(bool _offroad) {
hyundaiRadarTracksToggle->setVisible(false);
}
experimentalLongitudinalToggle->refresh();
+ neuralNetworkLateralControl.refresh();
offroad = _offroad;
}
diff --git a/selfdrive/ui/qt/offroad/developer_panel.h b/selfdrive/ui/qt/offroad/developer_panel.h
index beecc24dee..41ac4018fa 100644
--- a/selfdrive/ui/qt/offroad/developer_panel.h
+++ b/selfdrive/ui/qt/offroad/developer_panel.h
@@ -2,6 +2,7 @@
#ifdef SUNNYPILOT
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h"
+#include "selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.h"
#else
#include "selfdrive/ui/qt/offroad/settings.h"
#endif
@@ -19,6 +20,10 @@ private:
ParamControl* longManeuverToggle;
ParamControl* experimentalLongitudinalToggle;
ParamControl* hyundaiRadarTracksToggle;
+ ParamControl* neuralNetworkLateralControlToggle;
+#ifdef SUNNYPILOT
+ NeuralNetworkLateralcontrol neuralNetworkLateralControl;
+#endif
bool is_release;
bool offroad = false;
diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript
index 2975450124..f8b69b2625 100644
--- a/selfdrive/ui/sunnypilot/SConscript
+++ b/selfdrive/ui/sunnypilot/SConscript
@@ -33,6 +33,7 @@ qt_src = [
sunnypilot_panel_qt_src = [
"sunnypilot/qt/offroad/settings/sunnypilot/mads_settings.cc",
+ "sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.cc",
]
vehicle_panel_qt_src = [
diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.cc
new file mode 100644
index 0000000000..381944ed61
--- /dev/null
+++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.cc
@@ -0,0 +1,67 @@
+/**
+* Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
+ *
+ * This file is part of sunnypilot and is licensed under the MIT License.
+ * See the LICENSE.md file in the root directory for more details.
+ */
+
+#include "selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.h"
+
+NeuralNetworkLateralcontrol::NeuralNetworkLateralcontrol(QWidget *parent) {
+ toggle = new ParamControl(
+ "NeuralNetworkLateralControlToggle",
+ tr("Neural Network Lateral Control (NNLC)"),
+ nnff_description,
+ "");
+ toggle->setConfirmation(true, false);
+}
+
+void NeuralNetworkLateralcontrol::refresh() {
+ QString nnff_available_desc = tr("NNLC is currently not available on this platform.");
+ QString nnff_fuzzy_desc = tr("Match: \"Exact\" is ideal, but \"Fuzzy\" is fine too. Reach out to the sunnypilot team in the following channel at the sunnypilot Discord server if there are any issues: ")
+ + "#tuning-nnlc";
+ QString nnff_status_init = "⚠️ " + tr("Start the car to check car compatibility") + "";
+ QString nnff_not_loaded = "⚠️ " + tr("NNLC Not Loaded") + "";
+ QString nnff_loaded = "✅ " + tr("NNLC Loaded") + "";
+ auto _car_model = QString::fromStdString(params.get("NNFFCarModel"));
+
+ auto cp_bytes = params.get("CarParamsPersistent");
+ auto cp_sp_bytes = params.get("CarParamsSPPersistent");
+ if (!cp_bytes.empty() && !cp_sp_bytes.empty()) {
+ AlignedBuffer aligned_buf;
+ AlignedBuffer aligned_buf_sp;
+ capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
+ capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size()));
+ cereal::CarParams::Reader CP = cmsg.getRoot();
+ cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot();
+
+ if (CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE) {
+ params.remove("EnforceTorqueLateral");
+
+ toggle->setDescription(nnffDescriptionBuilder(nnff_available_desc));
+ toggle->setEnabled(false);
+ params.remove("NNFF");
+ } else if (toggle->isToggled()) {
+ if (CP.getLateralTuning().which() == cereal::CarParams::LateralTuning::TORQUE) {
+ QString nn_model_name = QString::fromStdString(CP_SP.getNeuralNetworkLateralControl().getModelName());
+ QString nn_fuzzy = CP_SP.getNeuralNetworkLateralControl().getFuzzyFingerprint() ? tr("Fuzzy") : tr("Exact");
+
+ toggle->setDescription(nnffDescriptionBuilder(
+ (nn_model_name == "") ? nnff_status_init :
+ (nn_model_name == "mock") ? (nnff_not_loaded + "
" + tr("Reach out to the sunnypilot team in the following channel at the sunnypilot Discord server and donate logs to get NNLC loaded for your car: ")
+ + "#tuning-nnlc") :
+ (nnff_loaded + " | " + tr("Match") + " = " + nn_fuzzy + " | " + _car_model + "
" + nnff_fuzzy_desc)));
+ } else {
+ toggle->setDescription(nnffDescriptionBuilder(nnff_status_init));
+ }
+ } else {
+ toggle->setDescription(nnff_description);
+ }
+ }
+}
+
+
+// ParamControlSP *NeuralNetworkLateralcontrol::configure_settings_interaction(ListWidgetSP *list) {
+// list->addItem(neuralNetworkLateralControlToggle);
+// return neuralNetworkLateralControlToggle;
+// }
\ No newline at end of file
diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.h
new file mode 100644
index 0000000000..c01b7a69ba
--- /dev/null
+++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/sunnypilot/neural_network_lateral_control.h
@@ -0,0 +1,40 @@
+/**
+* Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
+ *
+ * This file is part of sunnypilot and is licensed under the MIT License.
+ * See the LICENSE.md file in the root directory for more details.
+ */
+
+#pragma once
+
+#include