Remote Start Toggle & RedPanda

This commit is contained in:
firestar5683
2026-02-09 12:26:14 -06:00
parent 104a60c9e0
commit e82e034a31
9 changed files with 95 additions and 26 deletions
+2
View File
@@ -469,6 +469,8 @@ std::unordered_map<std::string, uint32_t> keys = {
{"RoadEdgesWidth", PERSISTENT},
{"RoadName", CLEAR_ON_MANAGER_START},
{"RoadNameUI", PERSISTENT},
{"RedPanda", PERSISTENT},
{"RemoteStartBootsComma", PERSISTENT},
{"RotatingWheel", PERSISTENT},
{"ScreenBrightness", PERSISTENT},
{"ScreenBrightnessOnroad", PERSISTENT},
+5
View File
@@ -237,6 +237,8 @@ frogpilot_default_params: list[tuple[str, str | bytes, int, str]] = [
("FullMap", "0", 2, "0"),
("GasRegenCmd", "1", 2, "0"),
("GMPedalLongitudinal", "1", 2, "1"),
("RedPanda", "0", 3, "0"),
("RemoteStartBootsComma", "0", 3, "0"),
("GithubSshKeys", "", 0, ""),
("GithubUsername", "", 0, ""),
("GoatScream", "0", 1, "0"),
@@ -808,6 +810,9 @@ class FrogPilotVariables:
toggle.vEgoStarting = 0.15 if toggle.experimental_gm_tune else toggle.vEgoStarting
toggle.vEgoStopping = 0.15 if toggle.experimental_gm_tune else toggle.vEgoStopping
toggle.red_panda = toggle.car_make == "gm" and (params.get_bool("RedPanda") if tuning_level >= level["RedPanda"] else default.get_bool("RedPanda"))
toggle.remote_start_boots_comma = toggle.car_make == "gm" and (params.get_bool("RemoteStartBootsComma") if tuning_level >= level["RemoteStartBootsComma"] else default.get_bool("RemoteStartBootsComma"))
toggle.force_fingerprint = (params.get_bool("ForceFingerprint") if tuning_level >= level["ForceFingerprint"] else default.get_bool("ForceFingerprint")) and toggle.car_model is not None
toggle.frogsgomoo_tweak = toggle.openpilot_longitudinal and toggle.car_make == "toyota" and (params.get_bool("FrogsGoMoosTweak") if tuning_level >= level["FrogsGoMoosTweak"] else default.get_bool("FrogsGoMoosTweak"))
@@ -1,6 +1,9 @@
#include <QRegularExpression>
#include <QTextStream>
#include <chrono>
#include <thread>
#include "frogpilot/ui/qt/offroad/vehicle_settings.h"
QStringList getCarNames(const QString &carMake, QMap<QString, QString> &carModels) {
@@ -170,6 +173,8 @@ FrogPilotVehiclesPanel::FrogPilotVehiclesPanel(FrogPilotSettingsWindow *parent)
{"ExperimentalGMTune", tr("FrogsGoMoo's Experimental Tune"), tr("<b>Experimental GM tune by FrogsGoMoo</b> that attempts to smoothen stopping and takeoff control. Use at your own risk!"), ""},
{"GMPedalLongitudinal", tr("Use Pedal for Longitudinal Control"), tr("<b>Use the pedal interceptor for longitudinal control</b> instead of camera ACC/Redneck when available."), ""},
{"LongPitch", tr("Smooth Pedal Response on Hills"), tr("<b>Smoothen acceleration and braking</b> when driving downhill/uphill."), ""},
{"RedPanda", tr("Red Panda"), tr("<b>Enable Red Panda behavior</b> for GM (alternate safety config and bus numbering). Requires a reboot to take effect."), ""},
{"RemoteStartBootsComma", tr("Remote Start Boots Comma"), tr("<b>Use GM C9 SystemPowerMode</b> for ignition detection. Toggle requires a panda firmware update and a reboot to take effect."), ""},
{"VoltSNG", tr("Stop-and-Go Hack"), tr("<b>Force stop-and-go</b> on the 2017 Chevy Volt."), ""},
{"HKGToggles", tr("Hyundai/Kia/Genesis Settings"), tr("<b>FrogPilot features for Genesis, Hyundai, and Kia vehicles.</b>"), ""},
@@ -300,6 +305,25 @@ FrogPilotVehiclesPanel::FrogPilotVehiclesPanel(FrogPilotSettingsWindow *parent)
});
}
ParamControl *remoteStartToggle = static_cast<ParamControl*>(toggles["RemoteStartBootsComma"]);
QObject::connect(remoteStartToggle, &ToggleControl::toggleFlipped, [parent, remoteStartToggle, this](bool state) {
const QString prompt = tr("Remote Start requires a Panda firmware update. Flash the Panda now?");
if (!FrogPilotConfirmationDialog::yesorno(prompt, this)) {
params.putBool("RemoteStartBootsComma", !state);
remoteStartToggle->refresh();
return;
}
std::thread([parent, this]() {
parent->keepScreenOn = true;
params_memory.putBool("FlashPanda", true);
while (params_memory.getBool("FlashPanda")) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
Hardware::reboot();
}).detach();
});
openDescriptions(forceOpenDescriptions, toggles);
QObject::connect(uiState(), &UIState::offroadTransition, [selectMakeButton, selectModelButton, this]() {
+2 -1
View File
@@ -36,7 +36,7 @@ private:
std::map<QString, AbstractControl*> toggles;
QSet<QString> gmKeys = {"ExperimentalGMTune", "GMPedalLongitudinal", "LongPitch", "VoltSNG"};
QSet<QString> gmKeys = {"ExperimentalGMTune", "GMPedalLongitudinal", "LongPitch", "RedPanda", "RemoteStartBootsComma", "VoltSNG"};
QSet<QString> hkgKeys = {"NewLongAPI", "TacoTuneHacks"};
QSet<QString> longitudinalKeys = {"ExperimentalGMTune", "FrogsGoMoosTweak", "LongPitch", "NewLongAPI", "SNGHack", "VoltSNG"};
QSet<QString> toyotaKeys = {"ClusterOffset", "FrogsGoMoosTweak", "LockDoorsTimer", "SNGHack", "ToyotaDoors"};
@@ -50,6 +50,7 @@ private:
ParamControl *forceFingerprint;
Params params;
Params params_memory{"/dev/shm/params"};
Params params_default{"/dev/shm/params_default"};
QJsonObject frogpilotToggleLevels;
+13 -4
View File
@@ -33,6 +33,7 @@ extern bool can_loopback;
// Ignition detected from CAN meessages
bool ignition_can = false;
uint32_t ignition_can_cnt = 0U;
extern bool gm_remote_start_boots_comma;
#define ALL_CAN_SILENT 0xFF
#define ALL_CAN_LIVE 0
@@ -202,10 +203,18 @@ void ignition_can_hook(CANPacket_t *to_push) {
int len = GET_LEN(to_push);
// GM exception
if ((addr == 0xC9) && (len == 8)) {
// Matches SystemPowerMode (1=Run, 0=Off)
ignition_can = (GET_BYTE(to_push, 6) & 0x10U) != 0U;
ignition_can_cnt = 0U;
if (gm_remote_start_boots_comma) {
if ((addr == 0xC9) && (len == 8)) {
// Matches SystemPowerMode (1=Run, 0=Off)
ignition_can = (GET_BYTE(to_push, 6) & 0x10U) != 0U;
ignition_can_cnt = 0U;
}
} else {
if ((addr == 0x1F1) && (len == 8)) {
// SystemPowerMode (2=Run, 3=Crank Request)
ignition_can = (GET_BYTE(to_push, 0) & 0x2U) != 0U;
ignition_can_cnt = 0U;
}
}
// Tesla exception
+3
View File
@@ -85,6 +85,7 @@ const uint16_t GM_PARAM_BOLT_2017 = 512;
const uint16_t GM_PARAM_BOLT_2022_PEDAL = 1024;
const uint16_t GM_PARAM_ASCM_INT = 2048;
const uint16_t GM_PARAM_FORCE_BRAKE_C9 = 4096;
const uint16_t GM_PARAM_REMOTE_START_BOOTS_COMMA = 8192;
enum {
GM_BTN_UNPRESS = 1,
@@ -108,6 +109,7 @@ bool gm_skip_relay_check = false;
bool gm_force_ascm = false;
bool gm_bolt_2022_pedal = false;
bool gm_force_brake_c9 = false;
bool gm_remote_start_boots_comma = false;
static void handle_gm_wheel_buttons(const CANPacket_t *to_push) {
int button = (GET_BYTE(to_push, 5) & 0x70U) >> 4;
@@ -376,6 +378,7 @@ static safety_config gm_init(uint16_t param) {
gm_has_acc = !GET_FLAG(param, GM_PARAM_NO_ACC);
enable_gas_interceptor = GET_FLAG(param, GM_PARAM_PEDAL_INTERCEPTOR);
gm_force_brake_c9 = GET_FLAG(param, GM_PARAM_FORCE_BRAKE_C9);
gm_remote_start_boots_comma = GET_FLAG(param, GM_PARAM_REMOTE_START_BOOTS_COMMA);
safety_config ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_ASCM_TX_MSGS);
if (gm_hw == GM_CAM) {
+1
View File
@@ -242,6 +242,7 @@ class Panda:
FLAG_GM_BOLT_2022_PEDAL = 1024
FLAG_GM_ASCM_INT = 2048
FLAG_GM_FORCE_BRAKE_C9 = 4096
FLAG_GM_REMOTE_START_BOOTS_COMMA = 8192
FLAG_FORD_LONG_CONTROL = 1
FLAG_FORD_CANFD = 2
+29 -21
View File
@@ -7,7 +7,7 @@ from panda import Panda
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import create_button_events, get_safety_config
from openpilot.selfdrive.car.gm.radar_interface import RADAR_HEADER_MSG
from openpilot.selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, CanBus, GMFlags, CC_ONLY_CAR, SDGM_CAR, ASCM_INT
from openpilot.selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, CanBus, GMFlags, CC_ONLY_CAR, SDGM_CAR, ASCM_INT, set_red_panda_canbus
from openpilot.selfdrive.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, FRICTION_THRESHOLD, LateralAccelFromTorqueCallbackType, get_friction_threshold
from openpilot.selfdrive.controls.lib.drive_helpers import get_friction
@@ -141,7 +141,13 @@ class CarInterface(CarInterfaceBase):
@staticmethod
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs, frogpilot_toggles):
ret.carName = "gm"
red_panda = getattr(frogpilot_toggles, "red_panda", False)
set_red_panda_canbus(red_panda)
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.gm)]
if red_panda:
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.noOutput), ret.safetyConfigs[0]]
gm_safety_cfg = ret.safetyConfigs[-1] if red_panda else ret.safetyConfigs[0]
ret.autoResumeSng = False
ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN]
@@ -154,13 +160,13 @@ class CarInterface(CarInterfaceBase):
if PEDAL_MSG in fingerprint[0]:
ret.enableGasInterceptor = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_GAS_INTERCEPTOR
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_GAS_INTERCEPTOR
# When a pedal interceptor is present, always use normal longitudinal (block stock cruise)
experimental_long = False
if candidate == CAR.CHEVROLET_BOLT_ACC_2022_2023:
# Hard-block pedal interceptor for ACC fingerprinted Bolts
ret.enableGasInterceptor = False
ret.safetyConfigs[0].safetyParam &= ~Panda.FLAG_GM_GAS_INTERCEPTOR
gm_safety_cfg.safetyParam &= ~Panda.FLAG_GM_GAS_INTERCEPTOR
if candidate in EV_CAR:
ret.transmissionType = TransmissionType.direct
@@ -180,19 +186,19 @@ 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
gm_safety_cfg.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
gm_safety_cfg.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
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM
ret.minSteerSpeed = 7 * CV.MPH_TO_MS
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_ASCM_INT
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_ASCM_INT
else:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM
# Tuning for experimental long
ret.longitudinalTuning.kiV = [0.5, 0.5] if candidate in kaofui_cars else [0.5, 0.5, 0.5]
@@ -207,11 +213,10 @@ class CarInterface(CarInterfaceBase):
if ret.experimentalLongitudinalAvailable and experimental_long:
ret.pcmCruise = False
ret.openpilotLongitudinalControl = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
if is_bolt_2022_2023_pedal:
ret.experimentalLongitudinalAvailable = False
ret.pcmCruise = False
else: # ASCM, OBD-II harness
ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long
ret.networkLocation = NetworkLocation.gateway
@@ -231,7 +236,10 @@ 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
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_ASCM_LONG
if getattr(frogpilot_toggles, "remote_start_boots_comma", False):
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_REMOTE_START_BOOTS_COMMA
# 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.]]
@@ -288,7 +296,7 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.torque.kfDEPRECATED = 0.02
if candidate == CAR.CHEVROLET_BOLT_CC_2017:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_BOLT_2017
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_BOLT_2017
if ret.enableGasInterceptor:
# ACC Bolts use pedal for full longitudinal control, not just sng
@@ -297,8 +305,8 @@ class CarInterface(CarInterfaceBase):
# Enable pedal interceptor for ACC models when detected
if is_bolt_2022_2023_pedal:
ret.flags |= GMFlags.PEDAL_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_ACC
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_BOLT_2022_PEDAL
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_NO_ACC
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_BOLT_2022_PEDAL
if candidate == CAR.CHEVROLET_SILVERADO:
# On the Bolt, the ECM and camera independently check that you are either above 5 kph or at a stop
@@ -365,7 +373,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
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM
ret.minEnableSpeed = -1
ret.pcmCruise = False
ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long
@@ -374,7 +382,7 @@ class CarInterface(CarInterfaceBase):
if candidate in CC_ONLY_CAR or (candidate in CAMERA_ACC_CAR and ret.enableGasInterceptor): #pedal interceptor tuning
ret.flags |= GMFlags.PEDAL_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_PEDAL_LONG
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_PEDAL_LONG
# Note: Low speed, stop and go not tested. Should be fairly smooth on highway
if candidate in (CAR.CHEVROLET_MALIBU_CC, CAR.CHEVROLET_MALIBU_HYBRID_CC):
ret.longitudinalTuning.kiBP = [0.0, 5., 35.]
@@ -390,14 +398,14 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kfDEPRECATED = 0.25
ret.stoppingDecelRate = 0.8
else: # Pedal used for SNG, ACC for longitudinal control otherwise
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
ret.startingState = True
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
if ret.enableGasInterceptor and candidate == CAR.CHEVROLET_MALIBU_HYBRID_CC:
ret.flags |= GMFlags.PEDAL_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_PEDAL_LONG
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_PEDAL_LONG
ret.longitudinalTuning.kiBP = [0.0, 5., 35.]
ret.longitudinalTuning.kiV = [0.0, 0.18, 0.25]
ret.longitudinalTuning.kfDEPRECATED = 0.15
@@ -408,7 +416,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
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_CC_LONG
ret.radarUnavailable = True
ret.experimentalLongitudinalAvailable = False
ret.minEnableSpeed = 24 * CV.MPH_TO_MS
@@ -431,12 +439,12 @@ class CarInterface(CarInterfaceBase):
ret.stoppingDecelRate = 11.18 # == 25 mph/s (.04 rate)
if candidate in CC_ONLY_CAR:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_ACC
gm_safety_cfg.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
gm_safety_cfg.safetyParam |= Panda.FLAG_GM_NO_CAMERA
if ACCELERATOR_POS_MSG not in fingerprint[CanBus.POWERTRAIN]:
ret.flags |= GMFlags.NO_ACCELERATOR_POS_MSG.value
+16
View File
@@ -333,6 +333,22 @@ class CanBus:
LOOPBACK = 128
DROPPED = 192
def set_red_panda_canbus(enabled: bool) -> None:
if enabled:
CanBus.POWERTRAIN = 4
CanBus.OBSTACLE = 5
CanBus.CAMERA = 6
CanBus.CHASSIS = 6
CanBus.LOOPBACK = 132
CanBus.DROPPED = 196
else:
CanBus.POWERTRAIN = 0
CanBus.OBSTACLE = 1
CanBus.CAMERA = 2
CanBus.CHASSIS = 2
CanBus.LOOPBACK = 128
CanBus.DROPPED = 192
class GMFlags(IntFlag):
PEDAL_LONG = 1
CC_LONG = 2