mirror of
https://github.com/MoreTore/openpilot.git
synced 2026-07-26 20:32:04 +08:00
September 4th, 2024 Patch
This commit is contained in:
+25
-26
@@ -50,32 +50,31 @@ struct FrogPilotPlan @0x80ae746ee2596b11 {
|
||||
accelerationJerk @0 :Float32;
|
||||
accelerationJerkStock @1 :Float32;
|
||||
adjustedCruise @2 :Float32;
|
||||
alwaysOnLateralActive @3 :Bool;
|
||||
dangerJerk @4 :Float32;
|
||||
desiredFollowDistance @5 :Float32;
|
||||
experimentalMode @6 :Bool;
|
||||
forcingStop @7 :Bool;
|
||||
frogpilotEvents @8: List(Car.CarEvent);
|
||||
lateralCheck @9 :Bool;
|
||||
laneWidthLeft @10 :Float32;
|
||||
laneWidthRight @11 :Float32;
|
||||
maxAcceleration @12 :Float32;
|
||||
minAcceleration @13 :Float32;
|
||||
redLight @14 :Bool;
|
||||
safeObstacleDistance @15 :Int32;
|
||||
safeObstacleDistanceStock @16 :Int32;
|
||||
slcOverridden @17 :Bool;
|
||||
slcOverriddenSpeed @18 :Float32;
|
||||
slcSpeedLimit @19 :Float32;
|
||||
slcSpeedLimitOffset @20 :Float32;
|
||||
speedJerk @21 :Float32;
|
||||
speedJerkStock @22 :Float32;
|
||||
speedLimitChanged @23 :Bool;
|
||||
stoppedEquivalenceFactor @24 :Int32;
|
||||
tFollow @25 :Float32;
|
||||
unconfirmedSlcSpeedLimit @26 :Float32;
|
||||
vCruise @27 :Float32;
|
||||
vtscControllingCurve @28 :Bool;
|
||||
dangerJerk @3 :Float32;
|
||||
desiredFollowDistance @4 :Float32;
|
||||
experimentalMode @5 :Bool;
|
||||
forcingStop @6 :Bool;
|
||||
frogpilotEvents @7: List(Car.CarEvent);
|
||||
lateralCheck @8 :Bool;
|
||||
laneWidthLeft @9 :Float32;
|
||||
laneWidthRight @10 :Float32;
|
||||
maxAcceleration @11 :Float32;
|
||||
minAcceleration @12 :Float32;
|
||||
redLight @13 :Bool;
|
||||
safeObstacleDistance @14 :Int32;
|
||||
safeObstacleDistanceStock @15 :Int32;
|
||||
slcOverridden @16 :Bool;
|
||||
slcOverriddenSpeed @17 :Float32;
|
||||
slcSpeedLimit @18 :Float32;
|
||||
slcSpeedLimitOffset @19 :Float32;
|
||||
speedJerk @20 :Float32;
|
||||
speedJerkStock @21 :Float32;
|
||||
speedLimitChanged @22 :Bool;
|
||||
stoppedEquivalenceFactor @23 :Int32;
|
||||
tFollow @24 :Float32;
|
||||
unconfirmedSlcSpeedLimit @25 :Float32;
|
||||
vCruise @26 :Float32;
|
||||
vtscControllingCurve @27 :Bool;
|
||||
}
|
||||
|
||||
struct CustomReserved5 @0xa5cd762cd951a455 {
|
||||
|
||||
@@ -76,7 +76,7 @@ class CarState(CarStateBase):
|
||||
self.zss_angle_offset = 0
|
||||
self.zss_threshold_count = 0
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_toggles):
|
||||
def update(self, cp, cp_cam, CC, frogpilot_toggles):
|
||||
ret = car.CarState.new_message()
|
||||
fp_ret = custom.FrogPilotCarState.new_message()
|
||||
|
||||
@@ -229,15 +229,14 @@ class CarState(CarStateBase):
|
||||
self.pcm_neutral_force = cp.vl["PCM_CRUISE"]["NEUTRAL_FORCE"]
|
||||
|
||||
# ZSS Support - Credit goes to the DragonPilot team!
|
||||
if self.CP.flags & ToyotaFlags.ZSS and self.zss_threshold_count < ZSS_THRESHOLD_COUNT:
|
||||
if self.CP.flags & ToyotaFlags.ZSS and self.zss_threshold_count <= ZSS_THRESHOLD_COUNT:
|
||||
zorro_steer = cp.vl["SECONDARY_STEER_ANGLE"]["ZORRO_STEER"]
|
||||
|
||||
# Only compute ZSS offset when cruise is active
|
||||
cruise_active = ret.cruiseState.available
|
||||
if cruise_active and not self.zss_cruise_active_last:
|
||||
self.zss_compute = True # Cruise was just activated, so allow offset to be recomputed
|
||||
# Only compute ZSS offset when control is active
|
||||
if CC.latActive and not self.zss_cruise_active_last:
|
||||
self.zss_threshold_count = 0
|
||||
self.zss_cruise_active_last = cruise_active
|
||||
self.zss_compute = True # Control was just activated, so allow offset to be recomputed
|
||||
self.zss_cruise_active_last = CC.latActive
|
||||
|
||||
# Compute ZSS offset
|
||||
if self.zss_compute:
|
||||
|
||||
@@ -175,7 +175,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_toggles):
|
||||
ret, fp_ret = self.CS.update(self.cp, self.cp_cam, frogpilot_toggles)
|
||||
ret, fp_ret = self.CS.update(self.cp, self.cp_cam, c, frogpilot_toggles)
|
||||
|
||||
if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR) or (self.CP.flags & ToyotaFlags.SMART_DSU and not self.CP.flags & ToyotaFlags.RADAR_CAN_FILTER):
|
||||
ret.buttonEvents = [
|
||||
|
||||
@@ -53,6 +53,7 @@ EventName = car.CarEvent.EventName
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
FrogPilotButtonType = custom.FrogPilotCarState.ButtonEvent.Type
|
||||
SafetyModel = car.CarParams.SafetyModel
|
||||
GearShifter = car.CarState.GearShifter
|
||||
|
||||
IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
|
||||
CSID_MAP = {"1": EventName.roadCameraError, "2": EventName.wideRoadCameraError, "0": EventName.driverCameraError}
|
||||
@@ -555,8 +556,8 @@ class Controls:
|
||||
|
||||
# Check if openpilot is engaged and actuators are enabled
|
||||
self.enabled = self.state in ENABLED_STATES
|
||||
self.active = self.state in ACTIVE_STATES or self.always_on_lateral_active
|
||||
if self.active:
|
||||
self.active = self.state in ACTIVE_STATES
|
||||
if self.active or self.always_on_lateral_active:
|
||||
self.current_alert_types.append(ET.WARNING)
|
||||
|
||||
def state_control(self, CS):
|
||||
@@ -583,7 +584,7 @@ class Controls:
|
||||
|
||||
# Check which actuators can be enabled
|
||||
standstill = CS.vEgo <= max(self.CP.minSteerSpeed, MIN_LATERAL_CONTROL_SPEED) or CS.standstill
|
||||
CC.latActive = self.active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \
|
||||
CC.latActive = (self.active or self.always_on_lateral_active) and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \
|
||||
(not standstill or self.joystick_mode) and self.sm['frogpilotPlan'].lateralCheck
|
||||
CC.longActive = self.enabled and not self.events.contains(ET.OVERRIDE_LONGITUDINAL) and self.CP.openpilotLongitudinalControl
|
||||
|
||||
@@ -710,7 +711,13 @@ class Controls:
|
||||
return CC, lac_log, FPCC
|
||||
|
||||
def update_frogpilot_variables(self, CS):
|
||||
self.always_on_lateral_active = self.sm['frogpilotPlan'].alwaysOnLateralActive and self.sm.all_checks(['frogpilotPlan'])
|
||||
self.always_on_lateral_active |= self.frogpilot_toggles.always_on_lateral_main or CS.cruiseState.enabled
|
||||
self.always_on_lateral_active &= self.frogpilot_toggles.always_on_lateral and CS.cruiseState.available
|
||||
self.always_on_lateral_active &= CS.gearShifter not in (GearShifter.neutral, GearShifter.park, GearShifter.reverse, GearShifter.unknown)
|
||||
self.always_on_lateral_active &= self.sm['frogpilotPlan'].lateralCheck
|
||||
self.always_on_lateral_active &= not (self.frogpilot_toggles.always_on_lateral_lkas and self.sm['frogpilotCarState'].alwaysOnLateralDisabled)
|
||||
self.always_on_lateral_active &= not (CS.brakePressed and CS.vEgo < self.frogpilot_toggles.always_on_lateral_pause_speed) or CS.standstill
|
||||
|
||||
if self.frogpilot_toggles.conditional_experimental_mode:
|
||||
self.experimental_mode = self.sm['frogpilotPlan'].experimentalMode
|
||||
|
||||
@@ -728,7 +735,7 @@ class Controls:
|
||||
self.resume_previously_pressed = self.resume_pressed
|
||||
|
||||
FPCC = custom.FrogPilotCarControl.new_message()
|
||||
FPCC.alwaysOnLateralActive = self.always_on_lateral_active
|
||||
FPCC.alwaysOnLateralActive = bool(self.always_on_lateral_active)
|
||||
FPCC.fcwEventTriggered = self.fcw_event_triggered
|
||||
FPCC.noEntryEventTriggered = self.no_entry_alert_triggered
|
||||
FPCC.resumePressed = self.resume_previously_pressed
|
||||
|
||||
@@ -30,7 +30,8 @@ class FrogPilotPlanner:
|
||||
self.frogpilot_vcruise = FrogPilotVCruise(self)
|
||||
self.lead_one = Lead()
|
||||
|
||||
self.always_on_lateral_active = False
|
||||
self.tracking_lead_mac = WeightedMovingAverageCalculator(window_size=5)
|
||||
|
||||
self.lateral_check = False
|
||||
self.lead_departing = False
|
||||
self.model_stopped = False
|
||||
@@ -43,8 +44,6 @@ class FrogPilotPlanner:
|
||||
self.tracking_lead_distance = 0
|
||||
self.v_cruise = 0
|
||||
|
||||
self.tracking_lead_mac = WeightedMovingAverageCalculator(window_size=4)
|
||||
|
||||
def update(self, carState, controlsState, frogpilotCarControl, frogpilotCarState, frogpilotNavigation, modelData, radarState, frogpilot_toggles):
|
||||
if frogpilot_toggles.radarless_model:
|
||||
model_leads = list(modelData.leadsV3)
|
||||
@@ -69,15 +68,8 @@ class FrogPilotPlanner:
|
||||
if frogpilot_toggles.openpilot_longitudinal:
|
||||
self.frogpilot_acceleration.update(controlsState, frogpilotCarState, v_cruise, v_ego, frogpilot_toggles)
|
||||
|
||||
self.always_on_lateral_active |= frogpilot_toggles.always_on_lateral_main or carState.cruiseState.enabled
|
||||
self.always_on_lateral_active &= frogpilot_toggles.always_on_lateral and carState.cruiseState.available
|
||||
self.always_on_lateral_active &= driving_gear
|
||||
self.always_on_lateral_active &= self.lateral_check
|
||||
self.always_on_lateral_active &= not (frogpilot_toggles.always_on_lateral_lkas and frogpilotCarState.alwaysOnLateralDisabled)
|
||||
self.always_on_lateral_active &= not (carState.brakePressed and v_ego < frogpilot_toggles.always_on_lateral_pause_speed) or carState.standstill
|
||||
|
||||
run_cem = frogpilot_toggles.conditional_experimental_mode or frogpilot_toggles.force_stops or frogpilot_toggles.green_light_alert or frogpilot_toggles.show_stopping_point
|
||||
if run_cem and (controlsState.enabled or self.always_on_lateral_active) and driving_gear:
|
||||
if run_cem and (controlsState.enabled or frogpilotCarControl.alwaysOnLateralActive) and driving_gear:
|
||||
self.cem.update(carState, frogpilotNavigation, modelData, v_ego, v_lead, frogpilot_toggles)
|
||||
else:
|
||||
self.cem.stop_light_detected = False
|
||||
@@ -119,7 +111,8 @@ class FrogPilotPlanner:
|
||||
else:
|
||||
self.taking_curve_quickly = False
|
||||
|
||||
self.tracking_lead = self.set_lead_status(lead_distance, stopping_distance, v_ego)
|
||||
self.tracking_lead = self.set_lead_status(carState, lead_distance, stopping_distance, v_ego)
|
||||
|
||||
if frogpilot_toggles.openpilot_longitudinal:
|
||||
self.v_cruise = self.frogpilot_vcruise.update(carState, controlsState, frogpilotCarControl, frogpilotCarState, frogpilotNavigation, modelData, v_cruise, v_ego, frogpilot_toggles)
|
||||
else:
|
||||
@@ -129,8 +122,9 @@ class FrogPilotPlanner:
|
||||
if self.frogpilot_events.frame == 1: # Force update to check the current state of "Always On Lateral" and holiday theme
|
||||
update_frogpilot_toggles()
|
||||
|
||||
def set_lead_status(self, lead_distance, stopping_distance, v_ego):
|
||||
following_lead = self.lead_one.status and 1 < lead_distance < self.model_length + stopping_distance
|
||||
def set_lead_status(self, carState, lead_distance, stopping_distance, v_ego):
|
||||
following_lead = self.lead_one.status
|
||||
following_lead &= 1 < lead_distance < self.model_length + stopping_distance or carState.standstill and self.tracking_lead
|
||||
following_lead &= v_ego > CRUISING_SPEED or self.tracking_lead
|
||||
|
||||
self.tracking_lead_mac.add_data(following_lead)
|
||||
@@ -151,8 +145,6 @@ class FrogPilotPlanner:
|
||||
frogpilotPlan.adjustedCruise = float(min(self.frogpilot_vcruise.mtsc_target, self.frogpilot_vcruise.vtsc_target) * (CV.MS_TO_KPH if frogpilot_toggles.is_metric else CV.MS_TO_MPH))
|
||||
frogpilotPlan.vtscControllingCurve = bool(self.frogpilot_vcruise.mtsc_target > self.frogpilot_vcruise.vtsc_target)
|
||||
|
||||
frogpilotPlan.alwaysOnLateralActive = self.always_on_lateral_active
|
||||
|
||||
frogpilotPlan.desiredFollowDistance = self.frogpilot_following.safe_obstacle_distance - self.frogpilot_following.stopped_equivalence_factor
|
||||
frogpilotPlan.safeObstacleDistance = self.frogpilot_following.safe_obstacle_distance
|
||||
frogpilotPlan.safeObstacleDistanceStock = self.frogpilot_following.safe_obstacle_distance_stock
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from openpilot.common.params import Params
|
||||
|
||||
from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_functions import WeightedMovingAverageCalculator
|
||||
from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_variables import CITY_SPEED_LIMIT, THRESHOLD
|
||||
|
||||
@@ -5,10 +7,9 @@ class ConditionalExperimentalMode:
|
||||
def __init__(self, FrogPilotPlanner):
|
||||
self.frogpilot_planner = FrogPilotPlanner
|
||||
|
||||
self.params_memory = self.frogpilot_planner.params_memory
|
||||
self.params_memory = Params("/dev/shm/params")
|
||||
|
||||
self.curvature_wmac = WeightedMovingAverageCalculator(window_size=5)
|
||||
self.slow_lead_wmac = WeightedMovingAverageCalculator(window_size=3)
|
||||
self.stop_light_wmac = WeightedMovingAverageCalculator(window_size=5)
|
||||
|
||||
self.curve_detected = False
|
||||
@@ -61,6 +62,8 @@ class ConditionalExperimentalMode:
|
||||
self.status_value = 17
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update_conditions(self, tracking_lead, v_ego, v_lead, frogpilot_toggles):
|
||||
self.curve_detection(tracking_lead, v_ego, frogpilot_toggles)
|
||||
self.slow_lead(tracking_lead, v_lead, frogpilot_toggles)
|
||||
@@ -82,10 +85,8 @@ class ConditionalExperimentalMode:
|
||||
slower_lead = self.frogpilot_planner.frogpilot_following.slower_lead and frogpilot_toggles.conditional_slower_lead
|
||||
stopped_lead = frogpilot_toggles.conditional_stopped_lead and v_lead < 1
|
||||
|
||||
self.slow_lead_wmac.add_data(slower_lead or stopped_lead)
|
||||
self.slow_lead_detected = self.slow_lead_wmac.get_weighted_average() >= THRESHOLD
|
||||
self.slow_lead_detected = slower_lead or stopped_lead
|
||||
else:
|
||||
self.slow_lead_wmac.reset_data()
|
||||
self.slow_lead_detected = False
|
||||
|
||||
def stop_sign_and_light(self, tracking_lead, v_ego, frogpilot_toggles):
|
||||
|
||||
@@ -208,7 +208,11 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
std::vector<QString> navigationToggleNames{tr("Intersections"), tr("Turns"), tr("With Lead")};
|
||||
controlToggle = new FrogPilotParamToggleControl(param, title, desc, icon, navigationToggles, navigationToggleNames);
|
||||
} else if (param == "CEModelStopTime") {
|
||||
controlToggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 10, std::map<int, QString>(), this, false, tr(" seconds"));
|
||||
std::map<int, QString> modelStopTimeLabels;
|
||||
for (int i = 0; i <= 10; i++) {
|
||||
modelStopTimeLabels[i] = (i == 0) ? tr("Off") : QString::number(i) + " seconds";
|
||||
}
|
||||
controlToggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 10, modelStopTimeLabels, this, false);
|
||||
|
||||
} else if (param == "DeviceManagement") {
|
||||
FrogPilotParamManageControl *deviceManagementToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
|
||||
@@ -268,8 +272,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
});
|
||||
controlToggle = reinterpret_cast<AbstractControl*>(personalitiesInfoBtn);
|
||||
} else if (param == "ResetTrafficPersonality" || param == "ResetAggressivePersonality" || param == "ResetStandardPersonality" || param == "ResetRelaxedPersonality") {
|
||||
std::vector<QString> personalityOptions{tr("Reset")};
|
||||
FrogPilotButtonsControl *profileBtn = new FrogPilotButtonsControl(title, desc, icon, personalityOptions);
|
||||
FrogPilotButtonsControl *profileBtn = new FrogPilotButtonsControl(title, {tr("Reset")}, desc);
|
||||
controlToggle = profileBtn;
|
||||
} else if (param == "TrafficPersonalityProfile") {
|
||||
FrogPilotParamManageControl *trafficPersonalityToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
|
||||
@@ -326,8 +329,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
}
|
||||
|
||||
} else if (param == "OnroadDistanceButtonButtons") {
|
||||
std::vector<QString> CustomDistanceIconsOptions{tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")};
|
||||
manageDistanceIconsBtn = new FrogPilotButtonsControl(title, desc, icon, CustomDistanceIconsOptions);
|
||||
manageDistanceIconsBtn = new FrogPilotButtonsControl(title, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}, desc);
|
||||
|
||||
std::function<QString(QString)> formatIconName = [](QString name) -> QString {
|
||||
QChar separator = name.contains('_') ? '_' : '-';
|
||||
@@ -406,7 +408,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
themeDeleting = false;
|
||||
}
|
||||
} else if (id == 1) {
|
||||
if (manageDistanceIconsBtn->getButton(id)->text() == tr("CANCEL")) {
|
||||
if (iconsDownloading) {
|
||||
paramsMemory.putBool("CancelThemeDownload", true);
|
||||
cancellingDownload = true;
|
||||
|
||||
@@ -523,11 +525,11 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
controlToggle = longitudinalTuneToggle;
|
||||
} else if (param == "AccelerationProfile") {
|
||||
std::vector<QString> profileOptions{tr("Standard"), tr("Eco"), tr("Sport"), tr("Sport+")};
|
||||
FrogPilotButtonParamControl *profileSelection = new FrogPilotButtonParamControl(param, title, desc, icon, profileOptions);
|
||||
ButtonParamControl *profileSelection = new ButtonParamControl(param, title, desc, icon, profileOptions);
|
||||
controlToggle = profileSelection;
|
||||
} else if (param == "DecelerationProfile") {
|
||||
std::vector<QString> profileOptions{tr("Standard"), tr("Eco"), tr("Sport")};
|
||||
FrogPilotButtonParamControl *profileSelection = new FrogPilotButtonParamControl(param, title, desc, icon, profileOptions);
|
||||
ButtonParamControl *profileSelection = new ButtonParamControl(param, title, desc, icon, profileOptions);
|
||||
controlToggle = profileSelection;
|
||||
} else if (param == "StoppingDistance") {
|
||||
controlToggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 10, std::map<int, QString>(), this, false, tr(" feet"));
|
||||
@@ -582,7 +584,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
});
|
||||
controlToggle = modelRandomizerToggle;
|
||||
} else if (param == "ManageBlacklistedModels") {
|
||||
FrogPilotButtonsControl *blacklistBtn = new FrogPilotButtonsControl(title, desc, icon, {tr("ADD"), tr("REMOVE")});
|
||||
FrogPilotButtonsControl *blacklistBtn = new FrogPilotButtonsControl(title, {tr("ADD"), tr("REMOVE")}, desc);
|
||||
QObject::connect(blacklistBtn, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
QStringList blacklistedModels = QString::fromStdString(params.get("BlacklistedModels")).split(",", QString::SkipEmptyParts);
|
||||
QMap<QString, QString> labelToModelMap;
|
||||
@@ -841,7 +843,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
selectModelBtn->setValue(QString::fromStdString(params.get("ModelName")));
|
||||
controlToggle = reinterpret_cast<AbstractControl*>(selectModelBtn);
|
||||
} else if (param == "ResetCalibrations") {
|
||||
FrogPilotButtonsControl *resetCalibrationsBtn = new FrogPilotButtonsControl(title, desc, icon, {tr("RESET ALL"), tr("RESET ONE")});
|
||||
FrogPilotButtonsControl *resetCalibrationsBtn = new FrogPilotButtonsControl(title, {tr("RESET ALL"), tr("RESET ONE")}, desc);
|
||||
QObject::connect(resetCalibrationsBtn, &FrogPilotButtonsControl::showDescriptionEvent, this, &FrogPilotControlsPanel::updateCalibrationDescription);
|
||||
QObject::connect(resetCalibrationsBtn, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
if (id == 0) {
|
||||
@@ -1013,11 +1015,11 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
||||
controlToggle = new FrogPilotParamToggleControl(param, title, desc, icon, slcOffsetToggles, slcOffsetToggleNames);
|
||||
} else if (param == "SLCFallback") {
|
||||
std::vector<QString> fallbackOptions{tr("Set Speed"), tr("Experimental Mode"), tr("Previous Limit")};
|
||||
FrogPilotButtonParamControl *fallbackSelection = new FrogPilotButtonParamControl(param, title, desc, icon, fallbackOptions);
|
||||
ButtonParamControl *fallbackSelection = new ButtonParamControl(param, title, desc, icon, fallbackOptions);
|
||||
controlToggle = fallbackSelection;
|
||||
} else if (param == "SLCOverride") {
|
||||
std::vector<QString> overrideOptions{tr("None"), tr("Manual Set Speed"), tr("Set Speed")};
|
||||
FrogPilotButtonParamControl *overrideSelection = new FrogPilotButtonParamControl(param, title, desc, icon, overrideOptions);
|
||||
ButtonParamControl *overrideSelection = new ButtonParamControl(param, title, desc, icon, overrideOptions);
|
||||
controlToggle = overrideSelection;
|
||||
} else if (param == "SLCPriority") {
|
||||
ButtonControl *slcPriorityButton = new ButtonControl(title, tr("SELECT"), desc);
|
||||
@@ -1305,9 +1307,9 @@ void FrogPilotControlsPanel::updateState(const UIState &s) {
|
||||
}
|
||||
|
||||
manageDistanceIconsBtn->setText(1, iconsDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
manageDistanceIconsBtn->setButtonEnabled(0, !themeDeleting && !themeDownloading);
|
||||
manageDistanceIconsBtn->setButtonEnabled(1, s.scene.online && (!themeDownloading || iconsDownloading) && !cancellingDownload && !themeDeleting && !iconsDownloaded);
|
||||
manageDistanceIconsBtn->setButtonEnabled(2, !themeDeleting && !themeDownloading);
|
||||
manageDistanceIconsBtn->setEnabledButtons(0, !themeDeleting && !themeDownloading);
|
||||
manageDistanceIconsBtn->setEnabledButtons(1, s.scene.online && (!themeDownloading || iconsDownloading) && !cancellingDownload && !themeDeleting && !iconsDownloaded);
|
||||
manageDistanceIconsBtn->setEnabledButtons(2, !themeDeleting && !themeDownloading);
|
||||
} else if (modelManagementOpen) {
|
||||
downloadAllModelsBtn->setText(modelDownloading && allModelsDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
downloadModelBtn->setText(modelDownloading && !allModelsDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
|
||||
@@ -119,8 +119,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
});
|
||||
visualToggle = personalizeOpenpilotToggle;
|
||||
} else if (param == "CustomColors") {
|
||||
std::vector<QString> customColorsOptions{tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")};
|
||||
manageCustomColorsBtn = new FrogPilotButtonsControl(title, desc, icon, customColorsOptions);
|
||||
manageCustomColorsBtn = new FrogPilotButtonsControl(title, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}, desc);
|
||||
|
||||
std::function<QString(QString)> formatColorName = [](QString name) -> QString {
|
||||
QChar separator = name.contains('_') ? '_' : '-';
|
||||
@@ -201,7 +200,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
themeDeleting = false;
|
||||
}
|
||||
} else if (id == 1) {
|
||||
if (manageCustomColorsBtn->getButton(id)->text() == tr("CANCEL")) {
|
||||
if (colorDownloading) {
|
||||
paramsMemory.putBool("CancelThemeDownload", true);
|
||||
cancellingDownload = true;
|
||||
|
||||
@@ -250,8 +249,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
manageCustomColorsBtn->setValue(currentColor);
|
||||
visualToggle = reinterpret_cast<AbstractControl*>(manageCustomColorsBtn);
|
||||
} else if (param == "CustomIcons") {
|
||||
std::vector<QString> customIconsOptions{tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")};
|
||||
manageCustomIconsBtn = new FrogPilotButtonsControl(title, desc, icon, customIconsOptions);
|
||||
manageCustomIconsBtn = new FrogPilotButtonsControl(title, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}, desc);
|
||||
|
||||
std::function<QString(QString)> formatIconName = [](QString name) -> QString {
|
||||
QChar separator = name.contains('_') ? '_' : '-';
|
||||
@@ -331,7 +329,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
themeDeleting = false;
|
||||
}
|
||||
} else if (id == 1) {
|
||||
if (manageCustomIconsBtn->getButton(id)->text() == tr("CANCEL")) {
|
||||
if (iconDownloading) {
|
||||
paramsMemory.putBool("CancelThemeDownload", true);
|
||||
cancellingDownload = true;
|
||||
|
||||
@@ -380,8 +378,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
manageCustomIconsBtn->setValue(currentIcon);
|
||||
visualToggle = reinterpret_cast<AbstractControl*>(manageCustomIconsBtn);
|
||||
} else if (param == "CustomSignals") {
|
||||
std::vector<QString> customSignalsOptions{tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")};
|
||||
manageCustomSignalsBtn = new FrogPilotButtonsControl(title, desc, icon, customSignalsOptions);
|
||||
manageCustomSignalsBtn = new FrogPilotButtonsControl(title, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}, desc);
|
||||
|
||||
std::function<QString(QString)> formatSignalName = [](QString name) -> QString {
|
||||
QChar separator = name.contains('_') ? '_' : '-';
|
||||
@@ -461,7 +458,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
themeDeleting = false;
|
||||
}
|
||||
} else if (id == 1) {
|
||||
if (manageCustomSignalsBtn->getButton(id)->text() == tr("CANCEL")) {
|
||||
if (signalDownloading) {
|
||||
paramsMemory.putBool("CancelThemeDownload", true);
|
||||
cancellingDownload = true;
|
||||
|
||||
@@ -510,8 +507,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
manageCustomSignalsBtn->setValue(currentSignal);
|
||||
visualToggle = reinterpret_cast<AbstractControl*>(manageCustomSignalsBtn);
|
||||
} else if (param == "CustomSounds") {
|
||||
std::vector<QString> customSoundsOptions{tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")};
|
||||
manageCustomSoundsBtn = new FrogPilotButtonsControl(title, desc, icon, customSoundsOptions);
|
||||
manageCustomSoundsBtn = new FrogPilotButtonsControl(title, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}, desc);
|
||||
|
||||
std::function<QString(QString)> formatSoundName = [](QString name) -> QString {
|
||||
QChar separator = name.contains('_') ? '_' : '-';
|
||||
@@ -591,7 +587,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
themeDeleting = false;
|
||||
}
|
||||
} else if (id == 1) {
|
||||
if (manageCustomSoundsBtn->getButton(id)->text() == tr("CANCEL")) {
|
||||
if (soundDownloading) {
|
||||
paramsMemory.putBool("CancelThemeDownload", true);
|
||||
cancellingDownload = true;
|
||||
|
||||
@@ -640,8 +636,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
manageCustomSoundsBtn->setValue(currentSound);
|
||||
visualToggle = reinterpret_cast<AbstractControl*>(manageCustomSoundsBtn);
|
||||
} else if (param == "WheelIcon") {
|
||||
std::vector<QString> wheelIconOptions{tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")};
|
||||
manageWheelIconsBtn = new FrogPilotButtonsControl(title, desc, icon, wheelIconOptions);
|
||||
manageWheelIconsBtn = new FrogPilotButtonsControl(title, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}, desc);
|
||||
|
||||
std::function<QString(QString)> formatWheelName = [](QString name) -> QString {
|
||||
QChar separator = name.contains('_') ? '_' : '-';
|
||||
@@ -721,15 +716,15 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
themeDeleting = false;
|
||||
}
|
||||
} else if (id == 1) {
|
||||
if (manageWheelIconsBtn->getButton(id)->text() == tr("CANCEL")) {
|
||||
if (wheelDownloading) {
|
||||
paramsMemory.putBool("CancelThemeDownload", true);
|
||||
cancellingDownload = true;
|
||||
|
||||
QTimer::singleShot(2000, [=]() {
|
||||
paramsMemory.putBool("CancelThemeDownload", false);
|
||||
cancellingDownload = false;
|
||||
themeDownloading = false;
|
||||
wheelDownloading = false;
|
||||
themeDownloading = false;
|
||||
});
|
||||
} else {
|
||||
QStringList downloadableWheels = QString::fromStdString(params.get("DownloadableWheels")).split(",");
|
||||
@@ -773,8 +768,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
downloadStatusLabel = new LabelControl(title, "Idle");
|
||||
visualToggle = reinterpret_cast<AbstractControl*>(downloadStatusLabel);
|
||||
} else if (param == "StartupAlert") {
|
||||
std::vector<QString> startupAlertOptions{tr("STOCK"), tr("FROGPILOT"), tr("CUSTOM"), tr("CLEAR")};
|
||||
FrogPilotButtonsControl *startupAlertButton = new FrogPilotButtonsControl(title, desc, icon, startupAlertOptions);
|
||||
FrogPilotButtonsControl *startupAlertButton = new FrogPilotButtonsControl(title, {tr("STOCK"), tr("FROGPILOT"), tr("CUSTOM"), tr("CLEAR")}, desc);
|
||||
QObject::connect(startupAlertButton, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
int maxLengthTop = 35;
|
||||
int maxLengthBottom = 45;
|
||||
@@ -947,7 +941,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
|
||||
visualToggle = qolToggle;
|
||||
} else if (param == "CameraView") {
|
||||
std::vector<QString> cameraOptions{tr("Auto"), tr("Driver"), tr("Standard"), tr("Wide")};
|
||||
FrogPilotButtonParamControl *preferredCamera = new FrogPilotButtonParamControl(param, title, desc, icon, cameraOptions);
|
||||
ButtonParamControl *preferredCamera = new ButtonParamControl(param, title, desc, icon, cameraOptions);
|
||||
visualToggle = preferredCamera;
|
||||
} else if (param == "BigMap") {
|
||||
std::vector<QString> mapToggles{"FullMap"};
|
||||
@@ -1102,29 +1096,29 @@ void FrogPilotVisualsPanel::updateState(const UIState &s) {
|
||||
}
|
||||
|
||||
manageCustomColorsBtn->setText(1, colorDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
manageCustomColorsBtn->setButtonEnabled(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomColorsBtn->setButtonEnabled(1, s.scene.online && (!themeDownloading || colorDownloading) && !cancellingDownload && !themeDeleting && !colorsDownloaded);
|
||||
manageCustomColorsBtn->setButtonEnabled(2, !themeDeleting && !themeDownloading);
|
||||
manageCustomColorsBtn->setEnabledButtons(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomColorsBtn->setEnabledButtons(1, s.scene.online && (!themeDownloading || colorDownloading) && !cancellingDownload && !themeDeleting && !colorsDownloaded);
|
||||
manageCustomColorsBtn->setEnabledButtons(2, !themeDeleting && !themeDownloading);
|
||||
|
||||
manageCustomIconsBtn->setText(1, iconDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
manageCustomIconsBtn->setButtonEnabled(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomIconsBtn->setButtonEnabled(1, s.scene.online && (!themeDownloading || iconDownloading) && !cancellingDownload && !themeDeleting && !iconsDownloaded);
|
||||
manageCustomIconsBtn->setButtonEnabled(2, !themeDeleting && !themeDownloading);
|
||||
manageCustomIconsBtn->setEnabledButtons(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomIconsBtn->setEnabledButtons(1, s.scene.online && (!themeDownloading || iconDownloading) && !cancellingDownload && !themeDeleting && !iconsDownloaded);
|
||||
manageCustomIconsBtn->setEnabledButtons(2, !themeDeleting && !themeDownloading);
|
||||
|
||||
manageCustomSignalsBtn->setText(1, signalDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
manageCustomSignalsBtn->setButtonEnabled(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomSignalsBtn->setButtonEnabled(1, s.scene.online && (!themeDownloading || signalDownloading) && !cancellingDownload && !themeDeleting && !signalsDownloaded);
|
||||
manageCustomSignalsBtn->setButtonEnabled(2, !themeDeleting && !themeDownloading);
|
||||
manageCustomSignalsBtn->setEnabledButtons(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomSignalsBtn->setEnabledButtons(1, s.scene.online && (!themeDownloading || signalDownloading) && !cancellingDownload && !themeDeleting && !signalsDownloaded);
|
||||
manageCustomSignalsBtn->setEnabledButtons(2, !themeDeleting && !themeDownloading);
|
||||
|
||||
manageCustomSoundsBtn->setText(1, soundDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
manageCustomSoundsBtn->setButtonEnabled(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomSoundsBtn->setButtonEnabled(1, s.scene.online && (!themeDownloading || soundDownloading) && !cancellingDownload && !themeDeleting && !soundsDownloaded);
|
||||
manageCustomSoundsBtn->setButtonEnabled(2, !themeDeleting && !themeDownloading);
|
||||
manageCustomSoundsBtn->setEnabledButtons(0, !themeDeleting && !themeDownloading);
|
||||
manageCustomSoundsBtn->setEnabledButtons(1, s.scene.online && (!themeDownloading || soundDownloading) && !cancellingDownload && !themeDeleting && !soundsDownloaded);
|
||||
manageCustomSoundsBtn->setEnabledButtons(2, !themeDeleting && !themeDownloading);
|
||||
|
||||
manageWheelIconsBtn->setText(1, wheelDownloading ? tr("CANCEL") : tr("DOWNLOAD"));
|
||||
manageWheelIconsBtn->setButtonEnabled(0, !themeDeleting && !themeDownloading);
|
||||
manageWheelIconsBtn->setButtonEnabled(1, s.scene.online && (!themeDownloading || wheelDownloading) && !cancellingDownload && !themeDeleting && !wheelsDownloaded);
|
||||
manageWheelIconsBtn->setButtonEnabled(2, !themeDeleting && !themeDownloading);
|
||||
manageWheelIconsBtn->setEnabledButtons(0, !themeDeleting && !themeDownloading);
|
||||
manageWheelIconsBtn->setEnabledButtons(1, s.scene.online && (!themeDownloading || wheelDownloading) && !cancellingDownload && !themeDeleting && !wheelsDownloaded);
|
||||
manageWheelIconsBtn->setEnabledButtons(2, !themeDeleting && !themeDownloading);
|
||||
}
|
||||
|
||||
started = s.scene.started;
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
Params paramsMemory{"/dev/shm/params"};
|
||||
|
||||
std::atomic<int> callCounter(0);
|
||||
|
||||
void updateFrogPilotToggles() {
|
||||
int currentCall = ++callCounter;
|
||||
|
||||
std::thread([currentCall]() {
|
||||
paramsMemory.putBool("FrogPilotTogglesUpdated", true);
|
||||
util::sleep_for(1000);
|
||||
if (currentCall == callCounter) {
|
||||
|
||||
if (currentCall == callCounter.load()) {
|
||||
paramsMemory.putBool("FrogPilotTogglesUpdated", false);
|
||||
}
|
||||
}).detach();
|
||||
@@ -21,53 +22,28 @@ QColor loadThemeColors(const QString &colorKey) {
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError);
|
||||
file.close();
|
||||
|
||||
if (parseError.error != QJsonParseError::NoError || !doc.isObject()) return QColor();
|
||||
|
||||
QJsonObject colorObj = doc.object().value(colorKey).toObject();
|
||||
int red = colorObj["red"].toInt();
|
||||
int green = colorObj["green"].toInt();
|
||||
int blue = colorObj["blue"].toInt();
|
||||
int alpha = colorObj["alpha"].toInt();
|
||||
|
||||
return QColor(red, green, blue, alpha);
|
||||
return QColor(
|
||||
colorObj["red"].toInt(),
|
||||
colorObj["green"].toInt(),
|
||||
colorObj["blue"].toInt(),
|
||||
colorObj["alpha"].toInt()
|
||||
);
|
||||
}
|
||||
|
||||
bool FrogPilotConfirmationDialog::toggle(const QString &prompt_text, const QString &confirm_text, QWidget *parent) {
|
||||
ConfirmationDialog d = ConfirmationDialog(prompt_text, confirm_text, tr("Reboot Later"), false, parent);
|
||||
ConfirmationDialog d(prompt_text, confirm_text, tr("Reboot Later"), false, parent);
|
||||
return d.exec();
|
||||
}
|
||||
|
||||
bool FrogPilotConfirmationDialog::toggleAlert(const QString &prompt_text, const QString &button_text, QWidget *parent) {
|
||||
ConfirmationDialog d = ConfirmationDialog(prompt_text, button_text, "", false, parent);
|
||||
ConfirmationDialog d(prompt_text, button_text, "", false, parent);
|
||||
return d.exec();
|
||||
}
|
||||
|
||||
bool FrogPilotConfirmationDialog::yesorno(const QString &prompt_text, QWidget *parent) {
|
||||
ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Yes"), tr("No"), false, parent);
|
||||
ConfirmationDialog d(prompt_text, tr("Yes"), tr("No"), false, parent);
|
||||
return d.exec();
|
||||
}
|
||||
|
||||
FrogPilotButtonIconControl::FrogPilotButtonIconControl(const QString &title, const QString &text, const QString &desc, const QString &icon, QWidget *parent) : AbstractControl(title, desc, icon, parent) {
|
||||
btn.setText(text);
|
||||
btn.setStyleSheet(R"(
|
||||
QPushButton {
|
||||
padding: 0;
|
||||
border-radius: 50px;
|
||||
font-size: 35px;
|
||||
font-weight: 500;
|
||||
color: #E4E4E4;
|
||||
background-color: #393939;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #4a4a4a;
|
||||
}
|
||||
QPushButton:disabled {
|
||||
color: #33E4E4E4;
|
||||
}
|
||||
)");
|
||||
btn.setFixedSize(250, 100);
|
||||
QObject::connect(&btn, &QPushButton::clicked, this, &FrogPilotButtonIconControl::clicked);
|
||||
hlayout->addWidget(&btn);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,16 @@ public:
|
||||
|
||||
class FrogPilotListWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FrogPilotListWidget(QWidget *parent = nullptr) : QWidget(parent), outer_layout(this) {
|
||||
explicit FrogPilotListWidget(QWidget *parent = nullptr) : QWidget(parent), outer_layout(this), inner_layout() {
|
||||
outer_layout.setMargin(0);
|
||||
outer_layout.setSpacing(0);
|
||||
outer_layout.addLayout(&inner_layout);
|
||||
|
||||
inner_layout.setMargin(0);
|
||||
inner_layout.setSpacing(25); // default spacing is 25
|
||||
outer_layout.addStretch();
|
||||
}
|
||||
|
||||
inline void addItem(QWidget *w) {
|
||||
@@ -47,93 +50,53 @@ public:
|
||||
|
||||
inline void setSpacing(int spacing) {
|
||||
inner_layout.setSpacing(spacing);
|
||||
adjustStretch();
|
||||
}
|
||||
|
||||
private:
|
||||
void adjustStretch() {
|
||||
if (inner_layout.stretch(inner_layout.count() - 1) > 0) {
|
||||
inner_layout.setStretch(inner_layout.count() - 1, 0);
|
||||
}
|
||||
if (inner_layout.count() > 3) {
|
||||
outer_layout.addStretch();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override {
|
||||
QPainter p(this);
|
||||
p.setPen(Qt::gray);
|
||||
|
||||
int visibleWidgetCount = 0;
|
||||
std::vector<QRect> visibleRects;
|
||||
|
||||
for (int i = 0; i < inner_layout.count(); ++i) {
|
||||
QWidget *widget = inner_layout.itemAt(i)->widget();
|
||||
if (widget && widget->isVisible()) {
|
||||
visibleWidgetCount++;
|
||||
visibleRects.push_back(inner_layout.itemAt(i)->geometry());
|
||||
visibleRects.push_back(widget->geometry());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < visibleWidgetCount - 1; ++i) {
|
||||
int bottom = visibleRects[i].bottom() + inner_layout.spacing() / 2;
|
||||
int lineOffset = inner_layout.spacing() / 2;
|
||||
for (size_t i = 0; i + 1 < visibleRects.size(); ++i) {
|
||||
int bottom = visibleRects[i].bottom() + lineOffset;
|
||||
p.drawLine(visibleRects[i].left() + 40, bottom, visibleRects[i].right() - 40, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void adjustStretch() {
|
||||
if (inner_layout.count() > 3) {
|
||||
outer_layout.addStretch();
|
||||
}
|
||||
}
|
||||
|
||||
QVBoxLayout outer_layout;
|
||||
QVBoxLayout inner_layout;
|
||||
};
|
||||
|
||||
class FrogPilotButtonControl : public AbstractControl {
|
||||
class FrogPilotButtonsControl : public AbstractControl {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FrogPilotButtonControl(const QString &title, const QString &text, const QString &desc = "", QWidget *parent = nullptr);
|
||||
inline void setText(const QString &text) { btn.setText(text); }
|
||||
inline QString text() const { return btn.text(); }
|
||||
FrogPilotButtonsControl(const QString &title, const std::vector<QString> &button_labels, const QString &desc, bool checkable = false, QWidget *parent = nullptr)
|
||||
: AbstractControl(title, desc, "") {
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
public slots:
|
||||
void setEnabled(bool enabled) { btn.setEnabled(enabled); }
|
||||
|
||||
private:
|
||||
QPushButton btn;
|
||||
};
|
||||
|
||||
class FrogPilotButtonIconControl : public AbstractControl {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FrogPilotButtonIconControl(const QString &title, const QString &text, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr);
|
||||
inline void setText(const QString &text) { btn.setText(text); }
|
||||
inline QString text() const { return btn.text(); }
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
public slots:
|
||||
void setEnabled(bool enabled) { btn.setEnabled(enabled); }
|
||||
|
||||
private:
|
||||
QPushButton btn;
|
||||
};
|
||||
|
||||
class FrogPilotButtonParamControl : public ParamControl {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FrogPilotButtonParamControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon,
|
||||
const std::vector<QString> &button_texts, const int minimum_button_width = 225)
|
||||
: ParamControl(param, title, desc, icon) {
|
||||
const QString style = R"(
|
||||
QPushButton {
|
||||
border-radius: 50px;
|
||||
font-size: 40px;
|
||||
font-weight: 500;
|
||||
height:100px;
|
||||
padding: 0 25 0 25;
|
||||
height: 100px;
|
||||
padding: 0 25px;
|
||||
color: #E4E4E4;
|
||||
background-color: #393939;
|
||||
}
|
||||
@@ -148,95 +111,18 @@ public:
|
||||
}
|
||||
)";
|
||||
|
||||
key = param.toStdString();
|
||||
int value = atoi(params.get(key).c_str());
|
||||
|
||||
button_group = new QButtonGroup(this);
|
||||
button_group->setExclusive(true);
|
||||
for (size_t i = 0; i < button_texts.size(); i++) {
|
||||
QPushButton *button = new QPushButton(button_texts[i], this);
|
||||
button->setCheckable(true);
|
||||
button->setChecked(i == value);
|
||||
|
||||
for (int i = 0; i < button_labels.size(); ++i) {
|
||||
QPushButton *button = new QPushButton(button_labels[i], this);
|
||||
button->setCheckable(checkable);
|
||||
button->setStyleSheet(style);
|
||||
button->setMinimumWidth(minimum_button_width);
|
||||
button->setMinimumWidth(255);
|
||||
hlayout->addWidget(button);
|
||||
button_group->addButton(button, i);
|
||||
}
|
||||
|
||||
QObject::connect(button_group, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), [=](int id, bool checked) {
|
||||
if (checked) {
|
||||
params.put(key, std::to_string(id));
|
||||
refresh();
|
||||
emit buttonClicked(id);
|
||||
}
|
||||
});
|
||||
|
||||
toggle.hide();
|
||||
}
|
||||
|
||||
void setEnabled(bool enable) {
|
||||
for (auto btn : button_group->buttons()) {
|
||||
btn->setEnabled(enable);
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
void buttonClicked(int id);
|
||||
|
||||
private:
|
||||
std::string key;
|
||||
Params params;
|
||||
QButtonGroup *button_group;
|
||||
};
|
||||
|
||||
class FrogPilotButtonsControl : public ParamControl {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FrogPilotButtonsControl(const QString &title, const QString &desc, const QString &icon,
|
||||
const std::vector<QString> &button_texts, const bool checkable = false, const int minimum_button_width = 225)
|
||||
: ParamControl("", title, desc, icon) {
|
||||
const QString style = R"(
|
||||
QPushButton {
|
||||
border-radius: 50px;
|
||||
font-size: 40px;
|
||||
font-weight: 500;
|
||||
height: 100px;
|
||||
padding: 0 25px 0 25px;
|
||||
color: #E4E4E4;
|
||||
background-color: #393939;
|
||||
}
|
||||
QPushButton:checked {
|
||||
background-color: #33Ab4C;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #33Ab4C;
|
||||
}
|
||||
QPushButton:disabled {
|
||||
color: #33E4E4E4;
|
||||
}
|
||||
)";
|
||||
|
||||
button_group = new QButtonGroup(this);
|
||||
|
||||
for (size_t i = 0; i < button_texts.size(); i++) {
|
||||
QPushButton *button = new QPushButton(button_texts[i], this);
|
||||
button->setStyleSheet(style);
|
||||
button->setCheckable(checkable);
|
||||
button->setMinimumWidth(minimum_button_width);
|
||||
hlayout->addWidget(button);
|
||||
button_group->addButton(button, static_cast<int>(i));
|
||||
|
||||
connect(button, &QPushButton::clicked, this, [this, i]() {
|
||||
emit buttonClicked(static_cast<int>(i));
|
||||
});
|
||||
}
|
||||
|
||||
toggle.hide();
|
||||
}
|
||||
|
||||
void updateButtonStyles(int id) {
|
||||
for (auto button : button_group->buttons()) {
|
||||
button->setChecked(button_group->id(button) == id);
|
||||
connect(button, &QPushButton::clicked, this, [this, i]() { emit buttonClicked(i); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,27 +132,31 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setButtonEnabled(int id, bool enable) {
|
||||
if (QPushButton *button = qobject_cast<QPushButton *>(button_group->button(id))) {
|
||||
void setCheckedButton(int id) {
|
||||
if (auto button = button_group->button(id)) {
|
||||
button->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void setEnabledButtons(int id, bool enable) {
|
||||
QPushButton *button = qobject_cast<QPushButton *>(button_group->button(id));
|
||||
if (button) {
|
||||
button->setEnabled(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void setText(int id, const QString &text) {
|
||||
if (QPushButton *button = qobject_cast<QPushButton *>(button_group->button(id))) {
|
||||
QPushButton *button = qobject_cast<QPushButton *>(button_group->button(id));
|
||||
if (button) {
|
||||
button->setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
QPushButton *getButton(int id) const {
|
||||
return qobject_cast<QPushButton *>(button_group->button(id));
|
||||
}
|
||||
private:
|
||||
QButtonGroup *button_group;
|
||||
|
||||
signals:
|
||||
void buttonClicked(int id);
|
||||
|
||||
private:
|
||||
QButtonGroup *button_group;
|
||||
};
|
||||
|
||||
class FrogPilotButtonsParamControl : public ParamControl {
|
||||
|
||||
@@ -126,12 +126,21 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
|
||||
|
||||
ListWidget *list = new ListWidget(this);
|
||||
// Enable tethering layout
|
||||
std::vector<QString> tetheringSelection{tr("Off"), tr("Only Onroad"), tr("Always")};
|
||||
tetheringToggle = new FrogPilotButtonParamControl("TetheringEnabled", "Enable Tethering", "", "", tetheringSelection);
|
||||
std::vector<QString> tetheringSelection{tr("Off"), tr("Always"), tr("Only Onroad"), tr("Until Reboot")};
|
||||
tetheringToggle = new ButtonParamControl("TetheringEnabled", tr("Enable Tethering"),
|
||||
tr("Allow tethering with your data SIM and keep it active either while driving or continuously."),
|
||||
"", tetheringSelection);
|
||||
if (params.getInt("TetheringEnabled") == 3) {
|
||||
params.remove("TetheringEnabled");
|
||||
tetheringToggle->setCheckedButton(0);
|
||||
}
|
||||
QButtonGroup *buttonGroup = tetheringToggle->findChild<QButtonGroup *>();
|
||||
if (buttonGroup) {
|
||||
QObject::connect(buttonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), [this](int id) {
|
||||
toggleTethering(id);
|
||||
});
|
||||
}
|
||||
list->addItem(tetheringToggle);
|
||||
QObject::connect(tetheringToggle, &FrogPilotButtonParamControl::buttonClicked, [this](int id) {
|
||||
toggleTethering(id);
|
||||
});
|
||||
|
||||
// Change tethering password
|
||||
ButtonControl *editPasswordButton = new ButtonControl(tr("Tethering Password"), tr("EDIT"));
|
||||
@@ -224,7 +233,7 @@ void AdvancedNetworking::refresh() {
|
||||
}
|
||||
|
||||
void AdvancedNetworking::toggleTethering(int id) {
|
||||
wifi->setTetheringEnabled(id == 2);
|
||||
wifi->setTetheringEnabled(id == 1 || id == 3);
|
||||
tetheringToggle->setEnabled(false);
|
||||
updateFrogPilotToggles();
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
|
||||
private:
|
||||
LabelControl* ipLabel;
|
||||
FrogPilotButtonParamControl* tetheringToggle;
|
||||
ButtonParamControl* tetheringToggle;
|
||||
ToggleControl* roamingToggle;
|
||||
ButtonControl* editApnButton;
|
||||
ButtonControl* hiddenNetworkButton;
|
||||
|
||||
@@ -316,8 +316,7 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
addItem(deleteDrivingDataBtn);
|
||||
|
||||
// Screen recordings
|
||||
std::vector<QString> recordingsOptions{tr("DELETE"), tr("RENAME")};
|
||||
FrogPilotButtonsControl *screenRecordingsBtn = new FrogPilotButtonsControl(tr("Screen Recordings"), tr("Delete or rename your screen recordings."), "", recordingsOptions);
|
||||
FrogPilotButtonsControl *screenRecordingsBtn = new FrogPilotButtonsControl(tr("Screen Recordings"), {tr("DELETE"), tr("RENAME")}, tr("Delete or rename your screen recordings."));
|
||||
connect(screenRecordingsBtn, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
QDir recordingsDir("/data/media/0/videos");
|
||||
QStringList recordingsNames = recordingsDir.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
@@ -372,8 +371,7 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
addItem(screenRecordingsBtn);
|
||||
|
||||
// Backup FrogPilot
|
||||
std::vector<QString> frogpilotBackupOptions{tr("BACKUP"), tr("DELETE"), tr("RESTORE")};
|
||||
FrogPilotButtonsControl *frogpilotBackupBtn = new FrogPilotButtonsControl(tr("FrogPilot Backups"), tr("Backup, delete, or restore your FrogPilot backups."), "", frogpilotBackupOptions);
|
||||
FrogPilotButtonsControl *frogpilotBackupBtn = new FrogPilotButtonsControl(tr("FrogPilot Backups"), {tr("BACKUP"), tr("DELETE"), tr("RESTORE")}, tr("Backup, delete, or restore your FrogPilot backups."));
|
||||
connect(frogpilotBackupBtn, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
QDir backupDir("/data/backups");
|
||||
QStringList backupNames = backupDir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
|
||||
@@ -529,8 +527,7 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
addItem(frogpilotBackupBtn);
|
||||
|
||||
// Backup toggles
|
||||
std::vector<QString> toggleBackupOptions{tr("BACKUP"), tr("DELETE"), tr("RESTORE")};
|
||||
FrogPilotButtonsControl *toggleBackupBtn = new FrogPilotButtonsControl(tr("Toggle Backups"), tr("Backup, delete, or restore your toggle backups."), "", toggleBackupOptions);
|
||||
FrogPilotButtonsControl *toggleBackupBtn = new FrogPilotButtonsControl(tr("Toggle Backups"), {tr("BACKUP"), tr("DELETE"), tr("RESTORE")}, tr("Backup, delete, or restore your toggle backups."));
|
||||
connect(toggleBackupBtn, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
QDir backupDir("/data/toggle_backups");
|
||||
QStringList backupNames = backupDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@@ -674,8 +671,7 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
addItem(resetTogglesBtn);
|
||||
|
||||
// Force offroad/onroad
|
||||
std::vector<QString> forceStartedOptions{tr("OFFROAD"), tr("ONROAD"), tr("OFF")};
|
||||
forceStartedBtn = new FrogPilotButtonsControl(tr("Force Started State"), tr("Force openpilot either offroad or onroad."), "", forceStartedOptions, true);
|
||||
forceStartedBtn = new FrogPilotButtonsControl(tr("Force Started State"), {tr("OFFROAD"), tr("ONROAD"), tr("OFF")}, tr("Force openpilot either offroad or onroad."), true);
|
||||
connect(forceStartedBtn, &FrogPilotButtonsControl::buttonClicked, [=](int id) {
|
||||
if (id == 0) {
|
||||
paramsMemory.putBool("ForceOffroad", true);
|
||||
@@ -687,9 +683,9 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
paramsMemory.putBool("ForceOffroad", false);
|
||||
paramsMemory.putBool("ForceOnroad", false);
|
||||
}
|
||||
forceStartedBtn->updateButtonStyles(id);
|
||||
forceStartedBtn->setCheckedButton(id);
|
||||
});
|
||||
forceStartedBtn->updateButtonStyles(2);
|
||||
forceStartedBtn->setCheckedButton(2);
|
||||
addItem(forceStartedBtn);
|
||||
|
||||
// power buttons
|
||||
@@ -859,7 +855,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
|
||||
{tr("Network"), new Networking(this)},
|
||||
{tr("Toggles"), toggles},
|
||||
{tr("Software"), new SoftwarePanel(this)},
|
||||
{tr("Controls"), frogpilotControls},
|
||||
{tr("Driving"), frogpilotControls},
|
||||
{tr("Navigation"), new FrogPilotNavigationPanel(this)},
|
||||
{tr("Vehicles"), new FrogPilotVehiclesPanel(this)},
|
||||
{tr("Visuals"), frogpilotVisuals},
|
||||
|
||||
@@ -901,40 +901,26 @@ void AnnotatedCameraWidget::updateSignals() {
|
||||
|
||||
const QString signalFolderPath = "../frogpilot/assets/active_theme/signals/";
|
||||
QDir directory(signalFolderPath);
|
||||
const QTransform flipTransform = QTransform().scale(-1, 1);
|
||||
|
||||
QFileInfoList fileList = directory.entryInfoList({"turn_signal_*.png"}, QDir::Files);
|
||||
|
||||
const QTransform flipTransform = QTransform().scale(-1, 1);
|
||||
std::vector<QPixmap> flippedImages;
|
||||
QFileInfoList nonPngFileList = directory.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
|
||||
nonPngFileList.erase(std::remove_if(nonPngFileList.begin(), nonPngFileList.end(), [](const QFileInfo &fileInfo) {return fileInfo.suffix() == "png";}), nonPngFileList.end());
|
||||
|
||||
for (const QFileInfo &fileInfo : fileList) {
|
||||
QPixmap pixmap(fileInfo.absoluteFilePath());
|
||||
|
||||
if (fileInfo.fileName().contains("blindspot")) {
|
||||
blindspotImages.push_back(pixmap);
|
||||
blindspotImages.push_back(pixmap.transformed(flipTransform));
|
||||
} else {
|
||||
regularImages.push_back(pixmap);
|
||||
flippedImages.push_back(pixmap.transformed(flipTransform));
|
||||
}
|
||||
QVector<QPixmap> *targetList = fileInfo.fileName().contains("blindspot") ? &blindspotImages : ®ularImages;
|
||||
targetList->push_back(pixmap);
|
||||
}
|
||||
|
||||
regularImages.insert(regularImages.end(), flippedImages.begin(), flippedImages.end());
|
||||
|
||||
QFileInfoList nonPngFileList = directory.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
|
||||
|
||||
for (QFileInfoList::iterator it = nonPngFileList.begin(); it != nonPngFileList.end(); ) {
|
||||
if ((*it).suffix() == "png") {
|
||||
it = nonPngFileList.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
for (const QFileInfo &fileInfo : fileList) {
|
||||
QPixmap pixmap(fileInfo.absoluteFilePath());
|
||||
QVector<QPixmap> *targetList = fileInfo.fileName().contains("blindspot") ? &blindspotImages : ®ularImages;
|
||||
targetList->push_back(pixmap.transformed(flipTransform));
|
||||
}
|
||||
|
||||
if (!nonPngFileList.isEmpty()) {
|
||||
const QFileInfo &fileInfo = nonPngFileList.first();
|
||||
const QStringList parts = fileInfo.fileName().split('_');
|
||||
|
||||
QStringList parts = nonPngFileList.first().fileName().split('_');
|
||||
if (parts.size() == 2) {
|
||||
signalStyle = parts[0];
|
||||
signalAnimationLength = parts[1].toInt();
|
||||
|
||||
@@ -180,8 +180,8 @@ private:
|
||||
|
||||
QTimer *animationTimer;
|
||||
|
||||
std::vector<QPixmap> regularImages;
|
||||
std::vector<QPixmap> blindspotImages;
|
||||
QVector<QPixmap> regularImages;
|
||||
QVector<QPixmap> blindspotImages;
|
||||
|
||||
inline QColor blueColor(int alpha = 255) { return QColor(0, 150, 255, alpha); }
|
||||
inline QColor greenColor(int alpha = 242) { return QColor(23, 134, 68, alpha); }
|
||||
|
||||
+2
-2
@@ -451,7 +451,7 @@ void ui_update_frogpilot_params(UIState *s, Params ¶ms) {
|
||||
scene.use_vienna_slc_sign = scene.speed_limit_controller && params.getBool("UseVienna");
|
||||
|
||||
scene.tethering_config = params.getInt("TetheringEnabled");
|
||||
if (scene.tethering_config == 2) {
|
||||
if (scene.tethering_config == 1) {
|
||||
WifiManager(s).setTetheringEnabled(true);
|
||||
}
|
||||
}
|
||||
@@ -488,7 +488,7 @@ void UIState::updateStatus() {
|
||||
started_prev = scene.started;
|
||||
scene.world_objects_visible = false;
|
||||
emit offroadTransition(!scene.started);
|
||||
if (scene.tethering_config == 1) {
|
||||
if (scene.tethering_config == 2) {
|
||||
wifi->setTetheringEnabled(scene.started);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ import cereal.messaging as messaging
|
||||
import openpilot.system.sentry as sentry
|
||||
from openpilot.common.params import Params, ParamKeyType
|
||||
from openpilot.common.text_window import TextWindow
|
||||
from openpilot.selfdrive.controls.lib.desire_helper import LANE_CHANGE_SPEED_MIN
|
||||
from openpilot.system.hardware import HARDWARE, PC
|
||||
from openpilot.system.hardware.power_monitoring import VBATT_PAUSE_CHARGING
|
||||
from openpilot.system.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog
|
||||
from openpilot.system.manager.process import ensure_running
|
||||
from openpilot.system.manager.process_config import managed_processes
|
||||
@@ -201,7 +203,7 @@ def manager_init() -> None:
|
||||
("LosAngelesLiveTorqueParameters", ""),
|
||||
("LosAngelesScore", "0"),
|
||||
("LoudBlindspotAlert", "0"),
|
||||
("LowVoltageShutdown", "11.8"),
|
||||
("LowVoltageShutdown", "VBATT_PAUSE_CHARGING"),
|
||||
("MapAcceleration", "0"),
|
||||
("MapDeceleration", "0"),
|
||||
("MapGears", "0"),
|
||||
@@ -209,7 +211,7 @@ def manager_init() -> None:
|
||||
("MapboxSecretKey", ""),
|
||||
("MapsSelected", ""),
|
||||
("MapStyle", "10"),
|
||||
("MinimumLaneChangeSpeed", "20"),
|
||||
("MinimumLaneChangeSpeed", "LANE_CHANGE_SPEED_MIN"),
|
||||
("Model", DEFAULT_MODEL),
|
||||
("ModelManagement", "0"),
|
||||
("ModelName", DEFAULT_MODEL_NAME),
|
||||
|
||||
Reference in New Issue
Block a user