diff --git a/.github/workflows/compile_frogpilot.yaml b/.github/workflows/compile_frogpilot.yaml index c5b747eb6..dd4bff7c9 100644 --- a/.github/workflows/compile_frogpilot.yaml +++ b/.github/workflows/compile_frogpilot.yaml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: runner: - description: "Select the runner" + description: "Select runner" required: true default: "c3" type: choice @@ -14,22 +14,22 @@ on: not_vetted: description: "This branch is not vetted" required: false - default: "false" + default: false type: boolean publish_frogpilot: description: "Push to FrogPilot" required: false - default: "false" + default: false type: boolean publish_staging: description: "Push to FrogPilot-Staging" required: false - default: "false" + default: false type: boolean publish_testing: description: "Push to FrogPilot-Testing" required: false - default: "false" + default: false type: boolean publish_custom_branch: description: "Push to custom branch:" @@ -39,18 +39,18 @@ on: update_translations: description: "Update missing/outdated translations" required: false - default: "false" + default: false type: boolean vet_existing_translations: description: "Vet existing translations" required: false - default: "false" + default: false type: boolean env: - BASEDIR: "${{ github.workspace }}" + BASEDIR: ${{ github.workspace }} BUILD_DIR: /data/openpilot - OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}" + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} jobs: get_branch: @@ -61,19 +61,16 @@ jobs: branch: ${{ steps.get_branch.outputs.branch }} python_version: ${{ steps.get_python_version.outputs.python_version }} steps: - - name: Determine Current Branch on Runner + - name: Get Current Branch id: get_branch run: | cd $BUILD_DIR + echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_OUTPUT - BRANCH=$(git rev-parse --abbrev-ref HEAD) - echo "branch=$BRANCH" >> $GITHUB_OUTPUT - - - name: Get Python Version from Runner + - name: Get Python Version id: get_python_version run: | - PYTHON_VERSION=$(tr -d '[:space:]' < "$BUILD_DIR/.python-version") - echo "python_version=$PYTHON_VERSION" >> $GITHUB_OUTPUT + echo "python_version=$(tr -d '[:space:]' < "$BUILD_DIR/.python-version")" >> $GITHUB_OUTPUT translate: if: inputs.update_translations @@ -100,29 +97,28 @@ jobs: - name: Set Up Python uses: actions/setup-python@v4 with: - python-version: "${{ needs.get_branch.outputs.python_version }}" + python-version: ${{ needs.get_branch.outputs.python_version }} - name: Install Dependencies - run: pip install requests - - - name: Install Qt5 Tools - run: sudo apt update && sudo apt install -y qttools5-dev-tools + run: | + pip install requests + sudo apt update && sudo apt install -y qttools5-dev-tools - name: Update Translations run: python selfdrive/ui/update_translations.py --vanish - name: Update Missing Translations continue-on-error: true - run: python selfdrive/ui/translations/auto_translate.py --all-files timeout-minutes: 300 + run: python selfdrive/ui/translations/auto_translate.py --all-files - name: Vet Existing Translations - if: github.event.inputs.vet_existing_translations == 'true' + if: inputs.vet_existing_translations continue-on-error: true - run: python selfdrive/ui/translations/auto_translate.py --all-files --vet-translations timeout-minutes: 300 + run: python selfdrive/ui/translations/auto_translate.py --all-files --vet-translations - - name: Commit and Push Translation Updates + - name: Commit and Push Translations run: | if git diff --quiet selfdrive/ui/translations/*.ts; then echo "No translation updates detected." @@ -136,9 +132,7 @@ jobs: git push --force origin ${{ needs.get_branch.outputs.branch }} build_and_push: - needs: - - get_branch - - translate + needs: [get_branch, translate] if: always() runs-on: - self-hosted @@ -149,27 +143,23 @@ jobs: run: working-directory: ${{ env.BUILD_DIR }} steps: - - name: Configure Git Identity + - name: Configure Git run: | git config --global http.postBuffer 104857600 - git config --global user.name "James" git config --global user.email "91348155+FrogAi@users.noreply.github.com" - - - name: Update Repository - run: | git remote set-url origin https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/FrogAi/FrogPilot.git - if [ "${{ github.event.inputs.update_translations }}" = "true" ]; then - git fetch origin ${{ needs.get_branch.outputs.branch }} - git reset --hard FETCH_HEAD - fi - - - name: Take Ownership of Build + - name: Sync Translation Updates + if: inputs.update_translations run: | - sudo chown -R $(whoami):$(whoami) . + git fetch origin ${{ needs.get_branch.outputs.branch }} + git reset --hard FETCH_HEAD - - name: Finalize Build + - name: Take Ownership of Build Directory + run: sudo chown -R $(whoami):$(whoami) . + + - name: Clean Build Artifacts run: | rm -f .clang-tidy rm -f .dockerignore @@ -215,7 +205,6 @@ jobs: rm -rf teleoprtc_repo/ find .github -mindepth 1 -maxdepth 1 ! -name 'workflows' -exec rm -rf {} + - find .github/workflows -mindepth 1 ! \( \ -type f \( \ -name 'compile_frogpilot.yaml' -o \ @@ -233,8 +222,6 @@ jobs: find third_party/ -name '*x86*' -exec rm -rf {} + find third_party/ -name '*Darwin*' -exec rm -rf {} + - find tools/ -mindepth 1 -maxdepth 1 ! \( -name '__init__.py' -o -name 'bodyteleop' -o -name 'lib' -o -name 'scripts' \) -exec rm -rf {} + - find . -name 'SConstruct' -delete find . -name 'SConscript' -delete @@ -244,34 +231,32 @@ jobs: find . -type f -regex '.*matlab.*\.md' -delete touch prebuilt + [ "${{ inputs.not_vetted }}" = "true" ] && touch not_vetted || true - if [ "${{ github.event.inputs.not_vetted }}" = "true" ]; then - touch not_vetted - fi - - - name: Add the update_date file - if: github.event.inputs.publish_staging == 'true' + - name: Add Update Date File + if: inputs.publish_staging + continue-on-error: true run: | - curl -fLsS https://raw.githubusercontent.com/FrogAi/FrogPilot/FrogPilot-Staging/.github/update_date -o .github/update_date || echo "No update_date found, skipping." + curl -fLsS https://raw.githubusercontent.com/FrogAi/FrogPilot/FrogPilot-Staging/.github/update_date -o .github/update_date || echo "No update_date found, skipping..." - - name: Commit Build + - name: Commit and Push Build run: | git add -f . git commit -m "Compile FrogPilot" git push --force origin HEAD - if [ "${{ github.event.inputs.publish_frogpilot }}" = "true" ]; then - git push --force origin HEAD:"FrogPilot" + if [ "${{ inputs.publish_frogpilot }}" = "true" ]; then + git push --force origin HEAD:FrogPilot fi - if [ "${{ github.event.inputs.publish_staging }}" = "true" ]; then - git push --force origin HEAD:"FrogPilot-Staging" + if [ "${{ inputs.publish_staging }}" = "true" ]; then + git push --force origin HEAD:FrogPilot-Staging fi - if [ "${{ github.event.inputs.publish_testing }}" = "true" ]; then - git push --force origin HEAD:"FrogPilot-Testing" + if [ "${{ inputs.publish_testing }}" = "true" ]; then + git push --force origin HEAD:FrogPilot-Testing fi - if [ -n "${{ github.event.inputs.publish_custom_branch }}" ]; then - git push --force origin HEAD:"${{ github.event.inputs.publish_custom_branch }}" + if [ -n "${{ inputs.publish_custom_branch }}" ]; then + git push --force origin HEAD:"${{ inputs.publish_custom_branch }}" fi diff --git a/README.md b/README.md index cf21c9989..35382ce70 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ We have detailed instructions for [how to install the harness and device in a ca [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/FrogAi/FrogPilot) [![Discord](https://img.shields.io/discord/1137853399715549214?label=Discord)](https://discord.frogpilot.download) -[![Last Updated](https://img.shields.io/badge/Last%20Updated-October%2018th%2C%202025-brightgreen)](https://github.com/FrogAi/FrogPilot/releases/latest) +[![Last Updated](https://img.shields.io/badge/Last%20Updated-November%2015th%2C%202025-brightgreen)](https://github.com/FrogAi/FrogPilot/releases/latest) [![Wiki](https://img.shields.io/badge/Wiki-FrogPilot-blue?logo=wiki)](https://frogpilot.wiki.gg/) diff --git a/cereal/car.capnp b/cereal/car.capnp index 02971fda4..fffecb1a2 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -530,14 +530,14 @@ struct CarParams { struct LateralTorqueTuning { useSteeringAngle @0 :Bool; + kp @1 :Float32; + ki @2 :Float32; + kd @8 : Float32; friction @3 :Float32; steeringAngleDeadzoneDeg @5 :Float32; latAccelFactor @6 :Float32; latAccelOffset @7 :Float32; - kpDEPRECATED @1 :Float32; - kiDEPRECATED @2 :Float32; kfDEPRECATED @4 :Float32; - kdDEPRECATED @8 : Float32; } struct LongitudinalPIDTuning { diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 202f87907..8876020eb 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -186,38 +186,39 @@ struct FrogPilotPlan @0xa1680744031fdb2d { cscControllingSpeed @2 :Bool; cscSpeed @3 :Float32; cscTraining @4 :Bool; - dangerJerk @5 :Float32; - desiredFollowDistance @6 :Int64; - experimentalMode @7 :Bool; - forcingStop @8 :Bool; - forcingStopLength @9 :Float32; - frogpilotEvents @10 :List(FrogPilotCarEvent); - increasedStoppedDistance @11 :Float32; - lateralCheck @12 :Bool; - laneWidthLeft @13 :Float32; - laneWidthRight @14 :Float32; - maxAcceleration @15 :Float32; - minAcceleration @16 :Float32; - redLight @17 :Bool; - roadCurvature @18 :Float32; - slcMapSpeedLimit @19 :Float32; - slcMapboxSpeedLimit @20 :Float32; - slcNextSpeedLimit @21 :Float32; - slcOverriddenSpeed @22 :Float32; - slcSpeedLimit @23 :Float32; - slcSpeedLimitOffset @24 :Float32; - slcSpeedLimitSource @25 :Text; - speedJerk @26 :Float32; - speedJerkStock @27 :Float32; - speedLimitChanged @28 :Bool; - tFollow @29 :Float32; - themeUpdated @30 :Bool; - togglesUpdated @31 :Bool; - trackingLead @32 :Bool; - unconfirmedSlcSpeedLimit @33 :Float32; - vCruise @34 :Float32; - weatherDaytime @35 :Bool; - weatherId @36 :Int16; + dangerFactor @5 :Float32; + dangerJerk @6 :Float32; + desiredFollowDistance @7 :Int64; + experimentalMode @8 :Bool; + forcingStop @9 :Bool; + forcingStopLength @10 :Float32; + frogpilotEvents @11 :List(FrogPilotCarEvent); + increasedStoppedDistance @12 :Float32; + lateralCheck @13 :Bool; + laneWidthLeft @14 :Float32; + laneWidthRight @15 :Float32; + maxAcceleration @16 :Float32; + minAcceleration @17 :Float32; + redLight @18 :Bool; + roadCurvature @19 :Float32; + slcMapSpeedLimit @20 :Float32; + slcMapboxSpeedLimit @21 :Float32; + slcNextSpeedLimit @22 :Float32; + slcOverriddenSpeed @23 :Float32; + slcSpeedLimit @24 :Float32; + slcSpeedLimitOffset @25 :Float32; + slcSpeedLimitSource @26 :Text; + speedJerk @27 :Float32; + speedJerkStock @28 :Float32; + speedLimitChanged @29 :Bool; + tFollow @30 :Float32; + themeUpdated @31 :Bool; + togglesUpdated @32 :Bool; + trackingLead @33 :Bool; + unconfirmedSlcSpeedLimit @34 :Float32; + vCruise @35 :Float32; + weatherDaytime @36 :Bool; + weatherId @37 :Int16; } struct FrogPilotRadarState @0xcb9fd56c7057593a { diff --git a/frogpilot/common/frogpilot_variables.py b/frogpilot/common/frogpilot_variables.py index 84bf5de81..396502d93 100644 --- a/frogpilot/common/frogpilot_variables.py +++ b/frogpilot/common/frogpilot_variables.py @@ -22,7 +22,6 @@ from openpilot.selfdrive.car.mock.values import CAR as MOCK from openpilot.selfdrive.car.subaru.values import SubaruFlags from openpilot.selfdrive.car.toyota.values import ToyotaFlags, ToyotaFrogPilotFlags from openpilot.selfdrive.controls.lib.desire_helper import LANE_CHANGE_SPEED_MIN -from openpilot.selfdrive.controls.lib.latcontrol_torque import KP from openpilot.selfdrive.modeld.constants import ModelConstants from openpilot.system.hardware import HARDWARE from openpilot.system.hardware.power_monitoring import VBATT_PAUSE_CHARGING @@ -90,6 +89,26 @@ BUTTON_FUNCTIONS = { "TRAFFIC_MODE": 6 } +DEVELOPER_SIDEBAR_METRICS = { + "NONE": 0, + "ACCELERATION_CURRENT": 1, + "ACCELERATION_MAX": 2, + "AUTOTUNE_ACTUATOR_DELAY": 3, + "AUTOTUNE_FRICTION": 4, + "AUTOTUNE_LATERAL_ACCELERATION": 5, + "AUTOTUNE_STEER_RATIO": 6, + "AUTOTUNE_STIFFNESS_FACTOR": 7, + "ENGAGEMENT_LATERAL": 8, + "ENGAGEMENT_LONGITUDINAL": 9, + "LATERAL_STEERING_ANGLE": 10, + "LATERAL_TORQUE_USED": 11, + "LONGITUDINAL_ACTUATOR_ACCELERATION": 12, + "LONGITUDINAL_MPC_DANGER_FACTOR": 13, + "LONGITUDINAL_MPC_JERK_ACCELERATION": 14, + "LONGITUDINAL_MPC_JERK_DANGER_ZONE": 15, + "LONGITUDINAL_MPC_JERK_SPEED_CONTROL": 16 +} + EXCLUDED_KEYS = { "AvailableModels", "AvailableModelNames", "CalibratedLateralAcceleration", "CalibrationProgress", "CarParamsPersistent", "CurvatureData", "ExperimentalLongitudinalEnabled", "KonikMinutes", "MapBoxRequests", "ModelDrivesAndScores", "ModelVersions", @@ -608,7 +627,7 @@ class FrogPilotVariables: startAccel = CP.startAccel stopAccel = CP.stopAccel steerActuatorDelay = CP.steerActuatorDelay - steerKp = CP.lateralTuning.pid.kp if CP.lateralTuning.which() == "pid" else KP + steerKp = CP.lateralTuning.torque.kp steerRatio = CP.steerRatio toggle.stoppingDecelRate = CP.stoppingDecelRate taco_hacks_allowed = CP.safetyConfigs[0].safetyModel == SafetyModel.hyundaiCanfd @@ -649,7 +668,7 @@ class FrogPilotVariables: toggle.steerRatio = np.clip(params.get_float("SteerRatio"), steerRatio * 0.5, steerRatio * 1.5) if advanced_lateral_tuning and tuning_level >= level["SteerRatio"] else steerRatio toggle.use_custom_steerRatio = bool(round(toggle.steerRatio, 2) != round(steerRatio, 2)) and not toggle.force_auto_tune or toggle.force_auto_tune_off - advanced_longitudinal_tuning = params.get_bool("AdvancedLongitudinalTune") if tuning_level >= level["AdvancedLongitudinalTune"] else default.get_bool("AdvancedLongitudinalTune") + advanced_longitudinal_tuning = toggle.openpilot_longitudinal and (params.get_bool("AdvancedLongitudinalTune") if tuning_level >= level["AdvancedLongitudinalTune"] else default.get_bool("AdvancedLongitudinalTune")) toggle.longitudinalActuatorDelay = np.clip(params.get_float("LongitudinalActuatorDelay"), 0, 1) if advanced_longitudinal_tuning and tuning_level >= level["LongitudinalActuatorDelay"] else longitudinalActuatorDelay toggle.max_desired_acceleration = np.clip(params.get_float("MaxDesiredAcceleration"), 0.1, 4.0) if advanced_longitudinal_tuning and tuning_level >= level["MaxDesiredAcceleration"] else default.get_float("MaxDesiredAcceleration") toggle.startAccel = np.clip(params.get_float("StartAccel"), 0, 4) if advanced_longitudinal_tuning and tuning_level >= level["StartAccel"] else startAccel @@ -768,13 +787,13 @@ class FrogPilotVariables: toggle.storage_used_metrics = developer_metrics and (params.get_bool("ShowStorageUsed") if tuning_level >= level["ShowStorageUsed"] else default.get_bool("ShowStorageUsed")) and not toggle.debug_mode toggle.use_si_metrics = developer_metrics and (params.get_bool("UseSI") if tuning_level >= level["UseSI"] else default.get_bool("UseSI")) or toggle.debug_mode toggle.developer_sidebar = toggle.developer_ui and (params.get_bool("DeveloperSidebar") if tuning_level >= level["DeveloperSidebar"] else default.get_bool("DeveloperSidebar")) or toggle.debug_mode - toggle.developer_sidebar_metric1 = params.get_int("DeveloperSidebarMetric1") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric1"] else 1 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric1") - toggle.developer_sidebar_metric2 = params.get_int("DeveloperSidebarMetric2") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric2"] else 3 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric2") - toggle.developer_sidebar_metric3 = params.get_int("DeveloperSidebarMetric3") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric3"] else 4 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric3") - toggle.developer_sidebar_metric4 = params.get_int("DeveloperSidebarMetric4") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric4"] else 5 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric4") - toggle.developer_sidebar_metric5 = params.get_int("DeveloperSidebarMetric5") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric5"] else 6 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric5") - toggle.developer_sidebar_metric6 = params.get_int("DeveloperSidebarMetric6") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric6"] else 7 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric6") - toggle.developer_sidebar_metric7 = params.get_int("DeveloperSidebarMetric7") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric7"] else 11 if toggle.debug_mode else default.get_int("DeveloperSidebarMetric7") + toggle.developer_sidebar_metric1 = params.get_int("DeveloperSidebarMetric1") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric1"] else DEVELOPER_SIDEBAR_METRICS["ACCELERATION_CURRENT"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric1") + toggle.developer_sidebar_metric2 = params.get_int("DeveloperSidebarMetric2") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric2"] else DEVELOPER_SIDEBAR_METRICS["AUTOTUNE_ACTUATOR_DELAY"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric2") + toggle.developer_sidebar_metric3 = params.get_int("DeveloperSidebarMetric3") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric3"] else DEVELOPER_SIDEBAR_METRICS["AUTOTUNE_FRICTION"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric3") + toggle.developer_sidebar_metric4 = params.get_int("DeveloperSidebarMetric4") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric4"] else DEVELOPER_SIDEBAR_METRICS["AUTOTUNE_LATERAL_ACCELERATION"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric4") + toggle.developer_sidebar_metric5 = params.get_int("DeveloperSidebarMetric5") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric5"] else DEVELOPER_SIDEBAR_METRICS["AUTOTUNE_STEER_RATIO"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric5") + toggle.developer_sidebar_metric6 = params.get_int("DeveloperSidebarMetric6") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric6"] else DEVELOPER_SIDEBAR_METRICS["AUTOTUNE_STIFFNESS_FACTOR"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric6") + toggle.developer_sidebar_metric7 = params.get_int("DeveloperSidebarMetric7") if toggle.developer_sidebar and tuning_level >= level["DeveloperSidebarMetric7"] else DEVELOPER_SIDEBAR_METRICS["LATERAL_TORQUE_USED"] if toggle.debug_mode else default.get_int("DeveloperSidebarMetric7") developer_widgets = toggle.developer_ui and params.get_bool("DeveloperWidgets") if tuning_level >= level["DeveloperWidgets"] else default.get_bool("DeveloperWidgets") toggle.adjacent_lead_tracking = has_radar and ((developer_widgets and params.get_bool("AdjacentLeadsUI") if tuning_level >= level["AdjacentLeadsUI"] else default.get_bool("AdjacentLeadsUI")) or toggle.debug_mode) toggle.radar_tracks = has_radar and ((developer_widgets and params.get_bool("RadarTracksUI") if tuning_level >= level["RadarTracksUI"] else default.get_bool("RadarTracksUI")) or toggle.debug_mode) @@ -832,9 +851,9 @@ class FrogPilotVariables: toggle.holiday_themes = params.get_bool("HolidayThemes") if tuning_level >= level["HolidayThemes"] else default.get_bool("HolidayThemes") toggle.current_holiday_theme = holiday_theme if toggle.holiday_themes else "stock" - toggle.honda_alt_Tune = toggle.car_make == "honda" and honda_nidec and (params.get_bool("HondaAltTune") if tuning_level >= level["HondaAltTune"] else default.get_bool("HondaAltTune")) - toggle.honda_low_speed_pedal = toggle.car_make == "honda" and toggle.has_pedal and (params.get_bool("HondaLowSpeedPedal") if tuning_level >= level["HondaLowSpeedPedal"] else default.get_bool("HondaLowSpeedPedal")) - toggle.honda_nidec_max_brake = toggle.car_make == "honda" and honda_nidec and (params.get_bool("HondaMaxBrake") if tuning_level >= level["HondaMaxBrake"] else default.get_bool("HondaMaxBrake")) + toggle.honda_alt_Tune = toggle.openpilot_longitudinal and toggle.car_make == "honda" and honda_nidec and (params.get_bool("HondaAltTune") if tuning_level >= level["HondaAltTune"] else default.get_bool("HondaAltTune")) + toggle.honda_low_speed_pedal = toggle.openpilot_longitudinal and toggle.car_make == "honda" and toggle.has_pedal and (params.get_bool("HondaLowSpeedPedal") if tuning_level >= level["HondaLowSpeedPedal"] else default.get_bool("HondaLowSpeedPedal")) + toggle.honda_nidec_max_brake = toggle.openpilot_longitudinal and toggle.car_make == "honda" and honda_nidec and (params.get_bool("HondaMaxBrake") if tuning_level >= level["HondaMaxBrake"] else default.get_bool("HondaMaxBrake")) toggle.lane_changes = params.get_bool("LaneChanges") if tuning_level >= level["LaneChanges"] else default.get_bool("LaneChanges") toggle.lane_change_delay = params.get_float("LaneChangeTime") if toggle.lane_changes and tuning_level >= level["LaneChangeTime"] else default.get_float("LaneChangeTime") @@ -934,7 +953,7 @@ class FrogPilotVariables: toggle.pause_lateral_below_speed = params.get_int("PauseLateralSpeed") * speed_conversion if quality_of_life_lateral and tuning_level >= level["PauseLateralSpeed"] else default.get_int("PauseLateralSpeed") * CV.MPH_TO_MS toggle.pause_lateral_below_signal = toggle.pause_lateral_below_speed != 0 and (params.get_bool("PauseLateralOnSignal") if tuning_level >= level["PauseLateralOnSignal"] else default.get_bool("PauseLateralOnSignal")) - quality_of_life_longitudinal = params.get_bool("QOLLongitudinal") if tuning_level >= level["QOLLongitudinal"] else default.get_bool("QOLLongitudinal") + quality_of_life_longitudinal = toggle.openpilot_longitudinal and (params.get_bool("QOLLongitudinal") if tuning_level >= level["QOLLongitudinal"] else default.get_bool("QOLLongitudinal")) toggle.cruise_increase = params.get_int("CustomCruise") if quality_of_life_longitudinal and not pcm_cruise and tuning_level >= level["CustomCruise"] else default.get_int("CustomCruise") toggle.cruise_increase_long = params.get_int("CustomCruiseLong") if quality_of_life_longitudinal and not pcm_cruise and tuning_level >= level["CustomCruiseLong"] else default.get_int("CustomCruiseLong") toggle.force_stops = quality_of_life_longitudinal and (params.get_bool("ForceStops") if tuning_level >= level["ForceStops"] else default.get_bool("ForceStops")) diff --git a/frogpilot/controls/frogpilot_card.py b/frogpilot/controls/frogpilot_card.py index a5a437aef..98c53fa58 100644 --- a/frogpilot/controls/frogpilot_card.py +++ b/frogpilot/controls/frogpilot_card.py @@ -36,7 +36,7 @@ class FrogPilotCard: self.gap_counter = 0 def update_distance_button(self, sm): - if self.car.frogpilot_toggles.experimental_mode_via_distance and sm["carControl"].longActive: + if sm["carControl"].longActive and self.car.frogpilot_toggles.experimental_mode_via_distance: handle_experimental_mode(self.car.frogpilot_toggles.conditional_experimental_mode) elif self.car.frogpilot_toggles.force_coast_via_distance: self.force_coast = not self.force_coast @@ -44,11 +44,11 @@ class FrogPilotCard: self.pause_lateral = not self.pause_lateral elif self.car.frogpilot_toggles.pause_longitudinal_via_distance: self.pause_longitudinal = not self.pause_longitudinal - elif self.car.frogpilot_toggles.traffic_mode_via_distance and sm["carControl"].longActive: + elif sm["carControl"].longActive and self.car.frogpilot_toggles.traffic_mode_via_distance: self.traffic_mode_enabled = not self.traffic_mode_enabled def update_distance_button_long(self, sm): - if self.car.frogpilot_toggles.experimental_mode_via_distance_long and sm["carControl"].longActive: + if sm["carControl"].longActive and self.car.frogpilot_toggles.experimental_mode_via_distance_long: handle_experimental_mode(self.car.frogpilot_toggles.conditional_experimental_mode) elif self.car.frogpilot_toggles.force_coast_via_distance_long: self.force_coast = not self.force_coast @@ -56,13 +56,13 @@ class FrogPilotCard: self.pause_lateral = not self.pause_lateral elif self.car.frogpilot_toggles.pause_longitudinal_via_distance_long: self.pause_longitudinal = not self.pause_longitudinal - elif self.car.frogpilot_toggles.traffic_mode_via_distance_long and sm["carControl"].longActive: + elif sm["carControl"].longActive and self.car.frogpilot_toggles.traffic_mode_via_distance_long: self.traffic_mode_enabled = not self.traffic_mode_enabled def update_distance_button_very_long(self, sm): self.update_distance_button_long(sm) - if self.car.frogpilot_toggles.experimental_mode_via_distance_very_long and sm["carControl"].longActive: + if sm["carControl"].longActive and self.car.frogpilot_toggles.experimental_mode_via_distance_very_long: handle_experimental_mode(self.car.frogpilot_toggles.conditional_experimental_mode) elif self.car.frogpilot_toggles.force_coast_via_distance_very_long: self.force_coast = not self.force_coast @@ -70,11 +70,11 @@ class FrogPilotCard: self.pause_lateral = not self.pause_lateral elif self.car.frogpilot_toggles.pause_longitudinal_via_distance_very_long: self.pause_longitudinal = not self.pause_longitudinal - elif self.car.frogpilot_toggles.traffic_mode_via_distance_very_long and sm["carControl"].longActive: + elif sm["carControl"].longActive and self.car.frogpilot_toggles.traffic_mode_via_distance_very_long: self.traffic_mode_enabled = not self.traffic_mode_enabled def update_lkas_button(self, sm): - if self.car.frogpilot_toggles.experimental_mode_via_lkas and sm["carControl"].longActive: + if sm["carControl"].longActive and self.car.frogpilot_toggles.experimental_mode_via_lkas: handle_experimental_mode(self.car.frogpilot_toggles.conditional_experimental_mode) elif self.car.frogpilot_toggles.force_coast_via_lkas: self.force_coast = not self.force_coast @@ -82,7 +82,7 @@ class FrogPilotCard: self.pause_lateral = not self.pause_lateral elif self.car.frogpilot_toggles.pause_longitudinal_via_lkas: self.pause_longitudinal = not self.pause_longitudinal - elif self.car.frogpilot_toggles.traffic_mode_via_lkas and sm["carControl"].longActive: + elif sm["carControl"].longActive and self.car.frogpilot_toggles.traffic_mode_via_lkas: self.traffic_mode_enabled = not self.traffic_mode_enabled def update(self, carState, frogpilotCarState, sm): diff --git a/frogpilot/controls/frogpilot_planner.py b/frogpilot/controls/frogpilot_planner.py index 29266a0d6..75114f6de 100644 --- a/frogpilot/controls/frogpilot_planner.py +++ b/frogpilot/controls/frogpilot_planner.py @@ -4,7 +4,7 @@ import math import cereal.messaging as messaging -from cereal import car, log +from cereal import log from openpilot.common.conversions import Conversions as CV from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.realtime import DT_MDL @@ -29,9 +29,6 @@ class FrogPilotPlanner: self.frogpilot_vcruise = FrogPilotVCruise(self) self.frogpilot_weather = WeatherChecker() - with car.CarParams.from_bytes(params.get("CarParams", block=True)) as msg: - self.CP = msg - self.tracking_lead_filter = FirstOrderFilter(0, 0.5, DT_MDL) self.driving_in_curve = False @@ -87,8 +84,6 @@ class FrogPilotPlanner: params_memory.remove("LastGPSPosition") - self.lateral_acceleration = v_ego**2 * (sm["carState"].steeringAngleDeg - sm["liveParameters"].angleOffsetDeg) * CV.DEG_TO_RAD / (self.CP.steerRatio * self.CP.wheelbase) - check_lane_width = frogpilot_toggles.adjacent_paths or frogpilot_toggles.adjacent_path_metrics or frogpilot_toggles.blind_spot_path or frogpilot_toggles.lane_detection if check_lane_width and v_ego >= frogpilot_toggles.minimum_lane_change_speed: self.lane_width_left = calculate_lane_width(sm["modelV2"].laneLines[0], sm["modelV2"].laneLines[1], sm["modelV2"].roadEdges[0]) @@ -97,6 +92,8 @@ class FrogPilotPlanner: self.lane_width_left = 0 self.lane_width_right = 0 + self.lateral_acceleration = v_ego**2 * sm["controlsState"].curvature + self.lateral_check = v_ego >= frogpilot_toggles.pause_lateral_below_speed self.lateral_check |= not (sm["carState"].leftBlinker or sm["carState"].rightBlinker) and frogpilot_toggles.pause_lateral_below_signal self.lateral_check |= sm["carState"].standstill @@ -134,6 +131,7 @@ class FrogPilotPlanner: frogpilotPlan.accelerationJerk = A_CHANGE_COST * self.frogpilot_following.acceleration_jerk frogpilotPlan.accelerationJerkStock = A_CHANGE_COST * self.frogpilot_following.base_acceleration_jerk + frogpilotPlan.dangerFactor = self.frogpilot_following.danger_factor frogpilotPlan.dangerJerk = DANGER_ZONE_COST * self.frogpilot_following.danger_jerk frogpilotPlan.speedJerk = J_EGO_COST * self.frogpilot_following.speed_jerk frogpilotPlan.speedJerkStock = J_EGO_COST * self.frogpilot_following.base_speed_jerk diff --git a/frogpilot/controls/lib/conditional_experimental_mode.py b/frogpilot/controls/lib/conditional_experimental_mode.py index be8111d52..aff26d685 100644 --- a/frogpilot/controls/lib/conditional_experimental_mode.py +++ b/frogpilot/controls/lib/conditional_experimental_mode.py @@ -22,7 +22,7 @@ class ConditionalExperimentalMode: else: self.status_value = 0 - if self.status_value not in {1, 2} and not sm["carState"].standstill: + if self.status_value not in (1, 2) and not sm["carState"].standstill: self.update_conditions(v_ego, sm, frogpilot_toggles) self.experimental_mode = self.check_conditions(v_ego, sm, frogpilot_toggles) @@ -30,12 +30,12 @@ class ConditionalExperimentalMode: params_memory.put_int("CEStatus", self.status_value if self.experimental_mode else 0) else: self.experimental_mode = self.status_value == 2 or sm["carState"].standstill and self.experimental_mode and self.frogpilot_planner.model_stopped - self.stop_light_detected &= self.status_value not in {1, 2} + self.stop_light_detected &= self.status_value not in (1, 2) self.stop_light_filter.x = 0 def check_conditions(self, v_ego, sm, frogpilot_toggles): - below_speed = frogpilot_toggles.conditional_limit > v_ego >= 1 and not self.frogpilot_planner.frogpilot_following.following_lead - below_speed_with_lead = frogpilot_toggles.conditional_limit_lead > v_ego >= 1 and self.frogpilot_planner.frogpilot_following.following_lead + below_speed = not self.frogpilot_planner.frogpilot_following.following_lead and 1 <= v_ego < frogpilot_toggles.conditional_limit + below_speed_with_lead = self.frogpilot_planner.frogpilot_following.following_lead and 1 <= v_ego < frogpilot_toggles.conditional_limit_lead if below_speed or below_speed_with_lead: self.status_value = 3 if self.frogpilot_planner.frogpilot_following.following_lead else 4 return True @@ -47,19 +47,19 @@ class ConditionalExperimentalMode: return True approaching_maneuver = sm["frogpilotNavigation"].approachingIntersection or sm["frogpilotNavigation"].approachingTurn - if frogpilot_toggles.conditional_navigation and approaching_maneuver and (frogpilot_toggles.conditional_navigation_lead or not self.frogpilot_planner.frogpilot_following.following_lead): + if approaching_maneuver and (not self.frogpilot_planner.frogpilot_following.following_lead or frogpilot_toggles.conditional_navigation_lead) and frogpilot_toggles.conditional_navigation: self.status_value = 6 if sm["frogpilotNavigation"].approachingIntersection else 7 return True - if frogpilot_toggles.conditional_curves and self.curve_detected and (frogpilot_toggles.conditional_curves_lead or not self.frogpilot_planner.frogpilot_following.following_lead): + if self.curve_detected and (not self.frogpilot_planner.frogpilot_following.following_lead or frogpilot_toggles.conditional_curves_lead) and frogpilot_toggles.conditional_curves: self.status_value = 8 return True - if frogpilot_toggles.conditional_lead and self.slow_lead_detected: + if self.slow_lead_detected and frogpilot_toggles.conditional_lead: self.status_value = 9 if self.frogpilot_planner.lead_one.vLead < 1 else 10 return True - if frogpilot_toggles.conditional_model_stop_time != 0 and self.stop_light_detected: + if self.stop_light_detected and frogpilot_toggles.conditional_model_stop_time != 0: self.status_value = 11 if not self.frogpilot_planner.frogpilot_vcruise.forcing_stop else 12 return True @@ -71,17 +71,17 @@ class ConditionalExperimentalMode: def update_conditions(self, v_ego, sm, frogpilot_toggles): self.curve_detection(v_ego, frogpilot_toggles) - self.slow_lead(frogpilot_toggles) + self.slow_lead(v_ego, frogpilot_toggles) self.stop_sign_and_light(v_ego, sm, frogpilot_toggles.conditional_model_stop_time) def curve_detection(self, v_ego, frogpilot_toggles): self.curvature_filter.update(self.frogpilot_planner.road_curvature_detected or self.frogpilot_planner.driving_in_curve) self.curve_detected = self.curvature_filter.x >= THRESHOLD and v_ego > CRUISING_SPEED - def slow_lead(self, frogpilot_toggles): + def slow_lead(self, v_ego, frogpilot_toggles): if self.frogpilot_planner.tracking_lead: - slower_lead = frogpilot_toggles.conditional_slower_lead and self.frogpilot_planner.frogpilot_following.slower_lead - stopped_lead = frogpilot_toggles.conditional_stopped_lead and self.frogpilot_planner.lead_one.vLead < 1 + slower_lead = (v_ego - self.frogpilot_planner.lead_one.vLead) > CRUISING_SPEED and frogpilot_toggles.conditional_slower_lead + stopped_lead = self.frogpilot_planner.lead_one.vLead < 1 and frogpilot_toggles.conditional_stopped_lead self.slow_lead_filter.update(slower_lead or stopped_lead) self.slow_lead_detected = self.slow_lead_filter.x >= THRESHOLD diff --git a/frogpilot/controls/lib/frogpilot_acceleration.py b/frogpilot/controls/lib/frogpilot_acceleration.py index d544e5a51..af4544d01 100644 --- a/frogpilot/controls/lib/frogpilot_acceleration.py +++ b/frogpilot/controls/lib/frogpilot_acceleration.py @@ -42,7 +42,7 @@ class FrogPilotAcceleration: if sm["frogpilotCarState"].trafficModeEnabled: self.max_accel = get_max_accel(v_ego) - elif frogpilot_toggles.map_acceleration and (eco_gear or sport_gear): + elif (eco_gear or sport_gear) and frogpilot_toggles.map_acceleration: if eco_gear: self.max_accel = get_max_accel_eco(v_ego) else: @@ -71,7 +71,7 @@ class FrogPilotAcceleration: self.min_accel = ACCEL_MIN elif sm["frogpilotCarState"].forceCoast: self.min_accel = A_CRUISE_MIN_ECO - elif frogpilot_toggles.map_deceleration and (eco_gear or sport_gear): + elif (eco_gear or sport_gear) and frogpilot_toggles.map_deceleration: if eco_gear: self.min_accel = A_CRUISE_MIN_ECO else: diff --git a/frogpilot/controls/lib/frogpilot_events.py b/frogpilot/controls/lib/frogpilot_events.py index 442f60bcb..c5bec2272 100644 --- a/frogpilot/controls/lib/frogpilot_events.py +++ b/frogpilot/controls/lib/frogpilot_events.py @@ -4,7 +4,7 @@ import random from openpilot.common.conversions import Conversions as CV from openpilot.common.realtime import DT_MDL from openpilot.selfdrive.controls.lib.desire_helper import TurnDirection -from openpilot.selfdrive.controls.lib.events import ET, EventName, FrogPilotEventName, Events +from openpilot.selfdrive.controls.lib.events import ET, EVENT_NAME, FROGPILOT_EVENT_NAME, EventName, FrogPilotEventName, Events from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY from openpilot.frogpilot.common.frogpilot_variables import CRUISING_SPEED, NON_DRIVING_GEARS, params, params_memory @@ -34,8 +34,8 @@ class FrogPilotEvents: self.played_events = set() def update(self, v_cruise, sm, frogpilot_toggles): - self.event_names = {event.name for event in sm["onroadEvents"]} - self.frogpilot_event_names = {event.name for event in sm["frogpilotOnroadEvents"]} + current_alert = sm["controlsState"].alertType + current_frogpilot_alert = sm["frogpilotControlsState"].alertType alerts_empty = all(sm[state].alertText1 == "" and sm[state].alertText2 == "" for state in ["controlsState", "frogpilotControlsState"]) @@ -75,7 +75,7 @@ class FrogPilotEvents: else: self.stopped_for_light = False - if "holidayActive" not in self.played_events and self.startup_seen and alerts_empty and frogpilot_toggles.current_holiday_theme != "stock" and len(self.events) == 0: + if "holidayActive" not in self.played_events and self.startup_seen and alerts_empty and len(self.events) == 0 and frogpilot_toggles.current_holiday_theme != "stock": self.events.add(FrogPilotEventName.holidayActive) self.played_events.add("holidayActive") @@ -135,13 +135,13 @@ class FrogPilotEvents: self.random_event_playing = True self.played_events.add("dejaVuCurve") - if "hal9000" not in self.played_events and (sm["controlsState"].alertType == ET.NO_ENTRY or sm["frogpilotControlsState"].alertType == ET.NO_ENTRY): + if "hal9000" not in self.played_events and (ET.NO_ENTRY in current_alert or ET.NO_ENTRY in current_frogpilot_alert): self.events.add(FrogPilotEventName.hal9000) self.random_event_playing = True self.played_events.add("hal9000") - if (EventName.steerSaturated in self.event_names or FrogPilotEventName.goatSteerSaturated in self.frogpilot_event_names): + if f"{EVENT_NAME[EventName.steerSaturated]}/" in current_alert or f"{FROGPILOT_EVENT_NAME[FrogPilotEventName.goatSteerSaturated]}/" in current_frogpilot_alert: event_choices = [] if "firefoxSteerSaturated" not in self.played_events: event_choices.append("firefoxSteerSaturated") @@ -178,21 +178,22 @@ class FrogPilotEvents: self.random_event_playing = True self.played_events.add("vCruise69") - if (EventName.fcw in self.event_names or EventName.stockAeb in self.event_names): + if f"{EVENT_NAME[EventName.fcw]}/" in current_alert or f"{EVENT_NAME[EventName.stockAeb]}/" in current_alert: event_choices = [] if "toBeContinued" not in self.played_events: event_choices.append("toBeContinued") if "yourFrogTriedToKillMe" not in self.played_events: event_choices.append("yourFrogTriedToKillMe") - event_choice = random.choice(event_choices) - if event_choice == "toBeContinued": - self.events.add(FrogPilotEventName.toBeContinued) - elif event_choice == "yourFrogTriedToKillMe": - self.events.add(FrogPilotEventName.yourFrogTriedToKillMe) + if event_choices: + event_choice = random.choice(event_choices) + if event_choice == "toBeContinued": + self.events.add(FrogPilotEventName.toBeContinued) + elif event_choice == "yourFrogTriedToKillMe": + self.events.add(FrogPilotEventName.yourFrogTriedToKillMe) - self.random_event_playing = True - self.played_events.add(event_choice) + self.random_event_playing = True + self.played_events.add(event_choice) if "youveGotMail" not in self.played_events and sm["frogpilotCarState"].alwaysOnLateralEnabled and not self.always_on_lateral_enabled_previously: if random.random() < RANDOM_EVENTS_CHANCE: @@ -203,7 +204,7 @@ class FrogPilotEvents: self.always_on_lateral_enabled_previously = sm["frogpilotCarState"].alwaysOnLateralEnabled - if frogpilot_toggles.speed_limit_changed_alert and self.frogpilot_planner.frogpilot_vcruise.slc.speed_limit_changed_timer == DT_MDL: + if self.frogpilot_planner.frogpilot_vcruise.slc.speed_limit_changed_timer == DT_MDL and frogpilot_toggles.speed_limit_changed_alert: self.events.add(FrogPilotEventName.speedLimitChanged) self.startup_seen |= sm["frogpilotControlsState"].alertText1 == frogpilot_toggles.startup_alert_top and sm["frogpilotControlsState"].alertText2 == frogpilot_toggles.startup_alert_bottom diff --git a/frogpilot/controls/lib/frogpilot_following.py b/frogpilot/controls/lib/frogpilot_following.py index 12a4cc550..4658d52dd 100644 --- a/frogpilot/controls/lib/frogpilot_following.py +++ b/frogpilot/controls/lib/frogpilot_following.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 import numpy as np -from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import COMFORT_BRAKE, STOP_DISTANCE, desired_follow_distance, get_jerk_factor, get_T_FOLLOW +from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import COMFORT_BRAKE, LEAD_DANGER_FACTOR, STOP_DISTANCE, desired_follow_distance, get_jerk_factor, get_T_FOLLOW -from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT, MAX_T_FOLLOW +from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT, CRUISING_SPEED, MAX_T_FOLLOW TRAFFIC_MODE_BP = [0., CITY_SPEED_LIMIT] @@ -12,7 +12,6 @@ class FrogPilotFollowing: self.frogpilot_planner = FrogPilotPlanner self.following_lead = False - self.slower_lead = False self.acceleration_jerk = 0 self.danger_jerk = 0 @@ -60,6 +59,7 @@ class FrogPilotFollowing: self.t_follow = 0 self.acceleration_jerk = self.base_acceleration_jerk + self.danger_factor = LEAD_DANGER_FACTOR self.danger_jerk = self.base_danger_jerk self.speed_jerk = self.base_speed_jerk @@ -69,7 +69,7 @@ class FrogPilotFollowing: self.t_follow = min(self.t_follow + self.frogpilot_planner.frogpilot_weather.increase_following_distance, MAX_T_FOLLOW) if sm["controlsState"].enabled and self.frogpilot_planner.tracking_lead: - if not sm["frogpilotCarState"].trafficModeEnabled: + if not sm["frogpilotCarState"].trafficModeEnabled and frogpilot_toggles.human_following: self.update_follow_values(self.frogpilot_planner.lead_one.dRel, v_ego, self.frogpilot_planner.lead_one.vLead, frogpilot_toggles) self.desired_follow_distance = int(desired_follow_distance(v_ego, self.frogpilot_planner.lead_one.vLead, self.t_follow)) else: @@ -77,7 +77,7 @@ class FrogPilotFollowing: def update_follow_values(self, lead_distance, v_ego, v_lead, frogpilot_toggles): # Offset by FrogAi for FrogPilot for a more natural approach to a faster lead - if frogpilot_toggles.human_following and v_lead > v_ego: + if v_lead > v_ego: distance_factor = max(lead_distance - (v_ego * self.t_follow), 1) accelerating_offset = float(np.clip(STOP_DISTANCE - v_ego, 1, distance_factor)) @@ -86,14 +86,14 @@ class FrogPilotFollowing: self.t_follow /= accelerating_offset # Offset by FrogAi for FrogPilot for a more natural approach to a slower lead - if (frogpilot_toggles.conditional_slower_lead or frogpilot_toggles.human_following) and v_lead < v_ego: + if v_lead < v_ego: distance_factor = max(lead_distance - (v_lead * self.t_follow), 1) braking_offset = float(np.clip(min(v_ego - v_lead, v_lead) - COMFORT_BRAKE, 1, distance_factor)) - if frogpilot_toggles.human_following: - if not self.following_lead and v_lead > CITY_SPEED_LIMIT: - far_lead_offset = max(lead_distance - (v_ego * self.t_follow) - STOP_DISTANCE, 0) - else: - far_lead_offset = 0 - self.t_follow /= braking_offset + far_lead_offset - self.slower_lead = braking_offset > 1 + self.danger_factor += (braking_offset / 100) + + if lead_distance >= 100: + far_lead_offset = max(lead_distance - (v_ego * self.t_follow) - STOP_DISTANCE, 0) + braking_offset += far_lead_offset + + self.t_follow /= braking_offset diff --git a/frogpilot/controls/lib/neural_network_feedforward.py b/frogpilot/controls/lib/neural_network_feedforward.py index 4557b118e..e68d71d0c 100644 --- a/frogpilot/controls/lib/neural_network_feedforward.py +++ b/frogpilot/controls/lib/neural_network_feedforward.py @@ -14,7 +14,6 @@ from openpilot.common.numpy_fast import interp from openpilot.common.params import Params from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N from openpilot.selfdrive.controls.lib.latcontrol import LatControl -from openpilot.selfdrive.controls.lib.latcontrol_torque import KD, KI, KP from openpilot.selfdrive.controls.lib.pid import PIDController from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY from openpilot.selfdrive.modeld.constants import ModelConstants @@ -175,7 +174,7 @@ class LatControlNNFF(LatControl): self.nnff_loaded = self.lat_torque_nn_model is not None self.torque_params = CP.lateralTuning.torque - self.pid = PIDController(KP, KI, k_d=KD, + self.pid = PIDController(self.torque_params.kp, self.torque_params.ki, pos_limit=self.steer_max, neg_limit=-self.steer_max) self.torque_from_lateral_accel = CI.torque_from_lateral_accel() self.use_steering_angle = self.torque_params.useSteeringAngle diff --git a/frogpilot/controls/lib/speed_limit_controller.py b/frogpilot/controls/lib/speed_limit_controller.py index 403ea5694..46e0953e1 100644 --- a/frogpilot/controls/lib/speed_limit_controller.py +++ b/frogpilot/controls/lib/speed_limit_controller.py @@ -51,7 +51,7 @@ class SpeedLimitController: @property def experimental_mode(self): - return self.frogpilot_toggles.slc_fallback_experimental_mode and self.target == 0 + return self.target == 0 and self.frogpilot_toggles.slc_fallback_experimental_mode @property def offset(self): diff --git a/frogpilot/controls/lib/weather_checker.py b/frogpilot/controls/lib/weather_checker.py index d0ac23c48..1d5bf5eda 100644 --- a/frogpilot/controls/lib/weather_checker.py +++ b/frogpilot/controls/lib/weather_checker.py @@ -42,6 +42,8 @@ class WeatherChecker: def __init__(self): self.is_daytime = False + self.api_25_calls = 0 + self.api_3_calls = 0 self.increase_following_distance = 0 self.increase_stopped_distance = 0 self.reduce_acceleration = 0 @@ -147,10 +149,12 @@ class WeatherChecker: for attempt in range(1, MAX_RETRIES + 1): try: + self.api_3_calls += 1 response = self.session.get("https://api.openweathermap.org/data/3.0/onecall", params=params, timeout=10) if response.status_code == 429: fallback_params = params.copy() fallback_params.pop("exclude", None) + self.api_25_calls += 1 fallback_response = self.session.get("https://api.openweathermap.org/data/2.5/weather", params=fallback_params, timeout=10) fallback_response.raise_for_status() return fallback_response.json() diff --git a/frogpilot/frogpilot_process.py b/frogpilot/frogpilot_process.py index 1cd1e1f5f..8dfb91e04 100644 --- a/frogpilot/frogpilot_process.py +++ b/frogpilot/frogpilot_process.py @@ -14,8 +14,8 @@ from openpilot.frogpilot.common.frogpilot_functions import backup_toggles from openpilot.frogpilot.common.frogpilot_utilities import capture_report, flash_panda, is_url_pingable, lock_doors, run_thread_with_lock, update_maps, update_openpilot from openpilot.frogpilot.common.frogpilot_variables import ERROR_LOGS_PATH, FrogPilotVariables, get_frogpilot_toggles, params, params_cache, params_memory from openpilot.frogpilot.controls.frogpilot_planner import FrogPilotPlanner -from openpilot.frogpilot.controls.lib.frogpilot_tracking import FrogPilotTracking from openpilot.frogpilot.system.frogpilot_stats import send_stats +from openpilot.frogpilot.system.frogpilot_tracking import FrogPilotTracking ASSET_CHECK_RATE = (1 / DT_MDL) diff --git a/frogpilot/controls/lib/frogpilot_tracking.py b/frogpilot/system/frogpilot_tracking.py similarity index 75% rename from frogpilot/controls/lib/frogpilot_tracking.py rename to frogpilot/system/frogpilot_tracking.py index 028f84e79..2857caf94 100644 --- a/frogpilot/controls/lib/frogpilot_tracking.py +++ b/frogpilot/system/frogpilot_tracking.py @@ -1,14 +1,17 @@ #!/usr/bin/env python3 import json +from cereal import log from openpilot.common.conversions import Conversions as CV from openpilot.common.realtime import DT_MDL from openpilot.selfdrive.controls.controlsd import ACTIVE_STATES, EventName, FrogPilotEventName, State from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX +from openpilot.selfdrive.controls.lib.events import EVENT_NAME from openpilot.selfdrive.ui.soundd import FrogPilotAudibleAlert from openpilot.frogpilot.common.frogpilot_utilities import clean_model_name from openpilot.frogpilot.common.frogpilot_variables import params +from openpilot.frogpilot.controls.lib.weather_checker import WEATHER_CATEGORIES RANDOM_EVENTS = { FrogPilotEventName.accel30: "accel30", @@ -28,6 +31,7 @@ RANDOM_EVENTS = { class FrogPilotTracking: def __init__(self, frogpilot_planner, frogpilot_toggles): self.frogpilot_events = frogpilot_planner.frogpilot_events + self.frogpilot_weather = frogpilot_planner.frogpilot_weather self.frogpilot_stats = json.loads(params.get("FrogPilotStats") or "{}") self.frogpilot_stats.setdefault("AOLTime", self.frogpilot_stats.get("TotalAOLTime", 0)) @@ -35,7 +39,14 @@ class FrogPilotTracking: self.frogpilot_stats.setdefault("LongitudinalTime", self.frogpilot_stats.get("TotalLongitudinalTime", 0)) self.frogpilot_stats.setdefault("TrackedTime", self.frogpilot_stats.get("TotalTrackedTime", 0)) - self.frogpilot_stats = {key: value for key, value in self.frogpilot_stats.items() if not key.startswith("Total")} + self.frogpilot_stats = { + key: ( + {sub_key: sub_value for sub_key, sub_value in value.items() if sub_key.lower() != "unknown"} + if isinstance(value, dict) else value + ) + for key, value in self.frogpilot_stats.items() + if not key.startswith("Total") and key.lower() != "unknown" + } if "ResetStats" not in self.frogpilot_stats: self.frogpilot_stats["Disengages"] = 0 @@ -53,9 +64,11 @@ class FrogPilotTracking: self.distance_since_override = 0 self.tracked_time = 0 - self.previous_events = set() self.previous_random_events = set() + self.personality_map = {key: key.capitalize() for key in log.LongitudinalPersonality.schema.enumerants.keys()} + + self.previous_alert_type = "" self.previous_state = State.disabled self.sound = FrogPilotAudibleAlert.none @@ -91,6 +104,11 @@ class FrogPilotTracking: self.frogpilot_stats["LateralTime"] = self.frogpilot_stats.get("LateralTime", 0) + DT_MDL if sm["carControl"].longActive: self.frogpilot_stats["LongitudinalTime"] = self.frogpilot_stats.get("LongitudinalTime", 0) + DT_MDL + + personality_name = self.personality_map.get(str(sm["controlsState"].personality), "Unknown") + total_personality_times = self.frogpilot_stats.get("PersonalityTimes", {}) + total_personality_times[personality_name] = total_personality_times.get(personality_name, 0) + DT_MDL + self.frogpilot_stats["PersonalityTimes"] = total_personality_times elif sm["frogpilotCarState"].alwaysOnLateralEnabled: self.frogpilot_stats["AOLTime"] = self.frogpilot_stats.get("AOLTime", 0) + DT_MDL @@ -125,15 +143,13 @@ class FrogPilotTracking: self.previous_state = sm["controlsState"].state - current_events = {event for event in self.frogpilot_events.event_names} - if len(current_events) > 0: - new_events = current_events - self.previous_events + if sm["controlsState"].alertType not in (self.previous_alert_type, ""): + alert_name = sm["controlsState"].alertType.split('/')[0] + total_events = self.frogpilot_stats.get("TotalEvents", {}) + total_events[alert_name] = total_events.get(alert_name, 0) + 1 + self.frogpilot_stats["TotalEvents"] = total_events - if new_events: - if (EventName.fcw in self.frogpilot_events.event_names or EventName.stockAeb in self.frogpilot_events.event_names): - self.frogpilot_stats["AEBEvents"] = self.frogpilot_stats.get("AEBEvents", 0) + 1 - - self.previous_events = current_events + self.previous_alert_type = sm["controlsState"].alertType current_random_events = {event for event in self.frogpilot_events.events.names if event in RANDOM_EVENTS} if len(current_random_events) > 0: @@ -148,6 +164,30 @@ class FrogPilotTracking: self.previous_random_events = current_random_events + if self.frogpilot_weather.sunrise != 0 and self.frogpilot_weather.sunset != 0: + if self.frogpilot_weather.is_daytime: + self.frogpilot_stats["DayTime"] = self.frogpilot_stats.get("DayTime", 0) + DT_MDL + else: + self.frogpilot_stats["NightTime"] = self.frogpilot_stats.get("NightTime", 0) + DT_MDL + + weather_api_calls = self.frogpilot_stats.get("WeatherAPICalls", {}) + weather_api_calls["2.5"] = weather_api_calls.get("2.5", 0) + self.frogpilot_weather.api_25_calls + weather_api_calls["3.0"] = weather_api_calls.get("3.0", 0) + self.frogpilot_weather.api_3_calls + self.frogpilot_stats["WeatherAPICalls"] = weather_api_calls + + self.frogpilot_weather.api_25_calls = 0 + self.frogpilot_weather.api_3_calls = 0 + + suffix = "Unknown" + for category in WEATHER_CATEGORIES.values(): + if any(start <= self.frogpilot_weather.weather_id <= end for start, end in category["ranges"]): + suffix = category["suffix"] + break + + weather_times = self.frogpilot_stats.get("WeatherTimes", {}) + weather_times[suffix] = weather_times.get(suffix, 0) + DT_MDL + self.frogpilot_stats["WeatherTimes"] = weather_times + if self.tracked_time > 60 and sm["carState"].standstill and self.enabled: if time_validated: current_month = now.month diff --git a/frogpilot/ui/qt/offroad/data_settings.cc b/frogpilot/ui/qt/offroad/data_settings.cc index c0b92c95e..32dce3cf4 100644 --- a/frogpilot/ui/qt/offroad/data_settings.cc +++ b/frogpilot/ui/qt/offroad/data_settings.cc @@ -660,15 +660,19 @@ void FrogPilotDataPanel::updateStatsLabels(FrogPilotListWidget *labelsList) { {"Month", {tr("Month"), "other"}}, {"Overrides", {tr("Total Overrides"), "count"}}, {"OverrideTime", {tr("Time Overriding openpilot"), "time"}}, + {"PersonalityTimes", {tr("Driving Personalities:"), "other"}}, {"RandomEvents", {tr("Random Events:"), "other"}}, {"StandstillTime", {tr("Time Stopped"), "time"}}, {"StopLightTime", {tr("Time Spent at Stoplights"), "time"}}, - {"TrackedTime", {tr("Total Time Tracked"), "time"}} + {"TrackedTime", {tr("Total Time Tracked"), "time"}}, + {"WeatherTimes", {tr("Time Spent in Weather:"), "other"}} }; static QSet parent_keys = { "ModelTimes", - "RandomEvents" + "PersonalityTimes", + "RandomEvents", + "WeatherTimes" }; static QSet percentage_keys = { @@ -742,7 +746,18 @@ void FrogPilotDataPanel::updateStatsLabels(FrogPilotListWidget *labelsList) { QString label_text = key_map.value(key).first; QString type = key_map.value(key).second; - if (key == "CruiseSpeedTimes" && value.isObject()) { + if (key == "AEBEvents") { + QJsonObject totalEvents = stats.value("TotalEvents").toObject(); + + QString trimmed_label = label_text; + if (trimmed_label.startsWith(tr("Total "))) { + trimmed_label = trimmed_label.mid(6); + } + QString display_value = format_number(totalEvents.value("stockAeb").toInt(0) + totalEvents.value("fcw").toInt(0)) + " " + trimmed_label; + + labelsList->addItem(new LabelControl(label_text, display_value, "", this)); + + } else if (key == "CruiseSpeedTimes" && value.isObject()) { QJsonObject speeds = value.toObject(); double max_time = -1.0; @@ -783,6 +798,9 @@ void FrogPilotDataPanel::updateStatsLabels(FrogPilotListWidget *labelsList) { } else if (key == "RandomEvents") { display_a = random_events_map.value(a, a); display_b = random_events_map.value(b, b); + } else if (key == "WeatherTimes") { + display_a = a.left(1).toUpper() + a.mid(1); + display_b = b.left(1).toUpper() + b.mid(1); } else { display_a = a; display_b = b; @@ -791,17 +809,23 @@ void FrogPilotDataPanel::updateStatsLabels(FrogPilotListWidget *labelsList) { }); for (const QString &subkey : subkeys) { + if (subkey == "Unknown") { + continue; + } + QString display_subkey; if (key == "ModelTimes") { display_subkey = processModelName(subkey); } else if (key == "RandomEvents") { display_subkey = random_events_map.value(subkey, subkey); + } else if (key == "WeatherTimes") { + display_subkey = subkey.left(1).toUpper() + subkey.mid(1); } else { display_subkey = subkey; } QString subvalue; - if (key == "ModelTimes") { + if (key == "ModelTimes" || key == "PersonalityTimes" || key == "WeatherTimes") { subvalue = format_time(subobj.value(subkey).toDouble()); } else { subvalue = subobj.value(subkey).toVariant().toString().isEmpty() ? "0" : format_number(subobj.value(subkey).toInt()); diff --git a/frogpilot/ui/qt/offroad/frogpilot_settings.cc b/frogpilot/ui/qt/offroad/frogpilot_settings.cc index d638fae7d..2cad861ca 100644 --- a/frogpilot/ui/qt/offroad/frogpilot_settings.cc +++ b/frogpilot/ui/qt/offroad/frogpilot_settings.cc @@ -304,7 +304,7 @@ void FrogPilotSettingsWindow::updateVariables() { hasPedal = CP.getEnableGasInterceptor(); hasRadar = !CP.getRadarUnavailable(); hasSDSU = frogpilot_toggles.value("has_sdsu").toBool(); - hasSNG = hasOpenpilotLongitudinal && CP.getAutoResumeSng(); + hasSNG = CP.getAutoResumeSng(); hasZSS = frogpilot_toggles.value("has_zss").toBool(); isAngleCar = CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE; isBolt = carFingerprint == "CHEVROLET_BOLT_CC" || carFingerprint == "CHEVROLET_BOLT_EUV"; @@ -322,7 +322,7 @@ void FrogPilotSettingsWindow::updateVariables() { longitudinalActuatorDelay = CP.getLongitudinalActuatorDelay(); startAccel = CP.getStartAccel(); steerActuatorDelay = CP.getSteerActuatorDelay(); - steerKp = CP.getLateralTuning().which() == cereal::CarParams::LateralTuning::PID ? CP.getLateralTuning().getPid().getKpV()[0] : 1.0; + steerKp = 1.0; steerRatio = CP.getSteerRatio(); stopAccel = CP.getStopAccel(); stoppingDecelRate = CP.getStoppingDecelRate(); diff --git a/frogpilot/ui/qt/offroad/lateral_settings.cc b/frogpilot/ui/qt/offroad/lateral_settings.cc index d99244d54..84b7be6e2 100644 --- a/frogpilot/ui/qt/offroad/lateral_settings.cc +++ b/frogpilot/ui/qt/offroad/lateral_settings.cc @@ -365,7 +365,7 @@ void FrogPilotLateralPanel::updateToggles() { else if (key == "ForceAutoTune") { setVisible &= !parent->hasAutoTune; setVisible &= !parent->isAngleCar; - setVisible &= parent->isTorqueCar || forcingTorqueController; + setVisible &= parent->isTorqueCar || forcingTorqueController || usingNNFF; } else if (key == "ForceAutoTuneOff") { @@ -402,19 +402,20 @@ void FrogPilotLateralPanel::updateToggles() { else if (key == "SteerFriction") { setVisible &= parent->friction != 0; setVisible &= parent->hasAutoTune ? forcingAutoTuneOff : !forcingAutoTune; - setVisible &= parent->isTorqueCar || forcingTorqueController; + setVisible &= parent->isTorqueCar || forcingTorqueController || usingNNFF; setVisible &= !usingNNFF; } else if (key == "SteerKP") { setVisible &= parent->steerKp != 0; + setVisible &= parent->isTorqueCar || forcingTorqueController || usingNNFF; setVisible &= !parent->isAngleCar; } else if (key == "SteerLatAccel") { setVisible &= parent->latAccelFactor != 0; setVisible &= parent->hasAutoTune ? forcingAutoTuneOff : !forcingAutoTune; - setVisible &= parent->isTorqueCar || forcingTorqueController; + setVisible &= parent->isTorqueCar || forcingTorqueController || usingNNFF; setVisible &= !usingNNFF; } diff --git a/frogpilot/ui/qt/offroad/longitudinal_settings.cc b/frogpilot/ui/qt/offroad/longitudinal_settings.cc index 20daee0c3..44446bc94 100644 --- a/frogpilot/ui/qt/offroad/longitudinal_settings.cc +++ b/frogpilot/ui/qt/offroad/longitudinal_settings.cc @@ -430,14 +430,14 @@ FrogPilotLongitudinalPanel::FrogPilotLongitudinalPanel(FrogPilotSettingsWindow * weatherKeyControl->setVisibleButton(1, false); } } else { - QString key = InputDialog::getText(tr("Enter your \"OpenWeatherMap\" key"), this).trimmed(); - if (key.length() == 32) { - params.put("WeatherToken", key.toStdString()); + int keyLength = 32; + QString currentKey = QString::fromStdString(params.get("WeatherToken")); + QString newKey = InputDialog::getText(tr("Enter your \"OpenWeatherMap\" key"), this, tr("Characters: 0/%1").arg(keyLength), false, -1, currentKey, keyLength).trimmed(); + if (!newKey.isEmpty()) { + params.put("WeatherToken", newKey.toStdString()); weatherKeyControl->setText(0, tr("REMOVE")); weatherKeyControl->setVisibleButton(1, true); - } else if (!key.isEmpty()) { - ConfirmationDialog::alert(tr("Invalid key!"), this); } } } else { diff --git a/frogpilot/ui/qt/offroad/navigation_settings.cc b/frogpilot/ui/qt/offroad/navigation_settings.cc index 55b8d60cc..24818c89a 100644 --- a/frogpilot/ui/qt/offroad/navigation_settings.cc +++ b/frogpilot/ui/qt/offroad/navigation_settings.cc @@ -52,18 +52,14 @@ FrogPilotNavigationPanel::FrogPilotNavigationPanel(FrogPilotSettingsWindow *pare updateButtons(); } } else { - QString key = InputDialog::getText(tr("Enter your Public Mapbox Key"), this).trimmed(); + int minKeyLength = 80; + QString key = InputDialog::getText(tr("Enter your Public Mapbox Key"), this, "", false, minKeyLength).trimmed(); if (!key.isEmpty()) { if (!key.startsWith("pk.")) { key = "pk." + key; } - if (key.length() >= 80) { - params.put("MapboxPublicKey", key.toStdString()); - - updateButtons(); - } else { - ConfirmationDialog::alert(tr("Inputted key is invalid or too short!"), this); - } + params.put("MapboxPublicKey", key.toStdString()); + updateButtons(); } } } else { @@ -103,18 +99,14 @@ FrogPilotNavigationPanel::FrogPilotNavigationPanel(FrogPilotSettingsWindow *pare updateButtons(); } } else { - QString key = InputDialog::getText(tr("Enter your Secret Mapbox Key"), this).trimmed(); + int minKeyLength = 80; + QString key = InputDialog::getText(tr("Enter your Secret Mapbox Key"), this, "", false, minKeyLength).trimmed(); if (!key.isEmpty()) { if (!key.startsWith("sk.")) { key = "sk." + key; } - if (key.length() >= 80) { - params.put("MapboxSecretKey", key.toStdString()); - - updateButtons(); - } else { - ConfirmationDialog::alert(tr("Inputted key is invalid or too short!"), this); - } + params.put("MapboxSecretKey", key.toStdString()); + updateButtons(); } } } else { @@ -325,16 +317,12 @@ void FrogPilotNavigationPanel::createKeyControl(ButtonControl *&control, const Q control = new ButtonControl(label, "", tr("Manage your \"%1\".").arg(label)); QObject::connect(control, &ButtonControl::clicked, [=] { if (control->text() == tr("ADD")) { - QString key = InputDialog::getText(tr("Enter your %1").arg(label), this).trimmed(); - - if (!key.startsWith(prefix)) { - key = prefix + key; - } - - if (key.length() >= minLength) { + QString key = InputDialog::getText(tr("Enter your %1").arg(label), this, "", false, minLength).trimmed(); + if (!key.isEmpty()) { + if (!key.startsWith(prefix)) { + key = prefix + key; + } params.put(paramKey, key.toStdString()); - } else { - ConfirmationDialog::alert(tr("Inputted key is invalid or too short!"), this); } } else { if (FrogPilotConfirmationDialog::yesorno(tr("Remove your %1?").arg(label), this)) { diff --git a/frogpilot/ui/qt/offroad/theme_settings.cc b/frogpilot/ui/qt/offroad/theme_settings.cc index fdc5fdf05..04063c708 100644 --- a/frogpilot/ui/qt/offroad/theme_settings.cc +++ b/frogpilot/ui/qt/offroad/theme_settings.cc @@ -599,9 +599,12 @@ FrogPilotThemesPanel::FrogPilotThemesPanel(FrogPilotSettingsWindow *parent) : Fr params.put("StartupMessageTop", frogpilotTop.toStdString()); params.put("StartupMessageBottom", frogpilotBottom.toStdString()); } else if (id == 2) { + QString currentTop = QString::fromStdString(params.get("StartupMessageTop")); QString newTop = InputDialog::getText(tr("Enter the text for the top half"), this, tr("Characters: 0/%1").arg(maxLengthTop), false, -1, currentTop, maxLengthTop).trimmed(); if (!newTop.isEmpty()) { params.put("StartupMessageTop", newTop.toStdString()); + + QString currentBottom = QString::fromStdString(params.get("StartupMessageBottom")); QString newBottom = InputDialog::getText(tr("Enter the text for the bottom half"), this, tr("Characters: 0/%1").arg(maxLengthBottom), false, -1, currentBottom, maxLengthBottom).trimmed(); if (!newBottom.isEmpty()) { params.put("StartupMessageBottom", newBottom.toStdString()); diff --git a/frogpilot/ui/qt/offroad/vehicle_settings.cc b/frogpilot/ui/qt/offroad/vehicle_settings.cc index 26d09dfa2..073982d6f 100644 --- a/frogpilot/ui/qt/offroad/vehicle_settings.cc +++ b/frogpilot/ui/qt/offroad/vehicle_settings.cc @@ -313,7 +313,7 @@ FrogPilotVehiclesPanel::FrogPilotVehiclesPanel(FrogPilotSettingsWindow *parent) static_cast(toggles["LockDoorsTimer"])->setWarning("Warning: openpilot can't detect if keys are still inside the car, so ensure you have a spare key to prevent accidental lockouts!"); - QSet rebootKeys = {"HondaAltTune", "NewLongAPI", "SubaruSNG", "TacoTuneHacks"}; + QSet rebootKeys = {"HondaAltTune", "NewLongAPI", "TacoTuneHacks"}; for (const QString &key : rebootKeys) { QObject::connect(static_cast(toggles[key]), &ToggleControl::toggleFlipped, [key, this](bool state) { if (started) { diff --git a/frogpilot/ui/qt/offroad/visual_settings.cc b/frogpilot/ui/qt/offroad/visual_settings.cc index 092154de7..654258a8b 100644 --- a/frogpilot/ui/qt/offroad/visual_settings.cc +++ b/frogpilot/ui/qt/offroad/visual_settings.cc @@ -211,9 +211,10 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(FrogPilotSettingsWindow *parent) : {10, tr("Lateral Control: Steering Angle")}, {11, tr("Lateral Control: Torque % Used")}, {12, tr("Longitudinal Control: Actuator Acceleration Output")}, - {13, tr("Longitudinal MPC Jerk: Acceleration")}, - {14, tr("Longitudinal MPC Jerk: Danger Zone")}, - {15, tr("Longitudinal MPC Jerk: Speed Control")}, + {13, tr("Longitudinal MPC: Danger Factor")}, + {14, tr("Longitudinal MPC Jerk: Acceleration")}, + {15, tr("Longitudinal MPC Jerk: Danger Zone")}, + {16, tr("Longitudinal MPC Jerk: Speed Control")}, }; ButtonControl *metricToggle = new ButtonControl(title, tr("SELECT"), desc); diff --git a/frogpilot/ui/qt/onroad/frogpilot_onroad.cc b/frogpilot/ui/qt/onroad/frogpilot_onroad.cc index 3292e8507..1275b510a 100644 --- a/frogpilot/ui/qt/onroad/frogpilot_onroad.cc +++ b/frogpilot/ui/qt/onroad/frogpilot_onroad.cc @@ -26,9 +26,7 @@ void FrogPilotOnroadWindow::updateState(const UIState &s, const FrogPilotUIState showSignal = (turnSignalLeft || turnSignalRight) && frogpilot_toggles.value("signal_metrics").toBool(); showSteering = frogpilot_toggles.value("steering_metrics").toBool(); - if (showBlindspot || showFPS || showSignal || showSteering) { - update(); - } + update(); } void FrogPilotOnroadWindow::paintEvent(QPaintEvent *event) { diff --git a/frogpilot/ui/qt/widgets/developer_sidebar.cc b/frogpilot/ui/qt/widgets/developer_sidebar.cc index c16ffdb8f..409b56798 100644 --- a/frogpilot/ui/qt/widgets/developer_sidebar.cc +++ b/frogpilot/ui/qt/widgets/developer_sidebar.cc @@ -117,6 +117,7 @@ void DeveloperSidebar::updateState(const UIState &s, const FrogPilotUIState &fs) accelerationStatus = ItemStatus(QPair(tr("ACCEL"), QString::number(acceleration, 'f', 2) + accelerationUnit), metricColor); accelerationJerkStatus = ItemStatus(QPair(tr("ACCEL JERK"), QString::number(frogpilotPlan.getAccelerationJerk())), metricColor); actuatorAccelerationStatus = ItemStatus(QPair(tr("ACT ACCEL"), QString::number(carControl.getActuators().getAccel() * accelerationConversion, 'f', 2) + accelerationUnit), metricColor); + dangerFactorStatus = ItemStatus(QPair(tr("DANGER %"), QString::number(frogpilotPlan.getDangerFactor(), 'f', 2)), metricColor); dangerJerkStatus = ItemStatus(QPair(tr("DANGER JERK"), QString::number(frogpilotPlan.getDangerJerk())), metricColor); delayStatus = ItemStatus(QPair(tr("STEER DELAY"), QString::number(liveDelay.getLateralDelay(), 'f', 5)), metricColor); frictionStatus = ItemStatus(QPair(tr("FRICTION"), QString::number(liveTorqueParameters.getFrictionCoefficientFiltered(), 'f', 5)), metricColor); @@ -153,9 +154,10 @@ void DeveloperSidebar::paintEvent(QPaintEvent *event) { metricMap.insert(10, &steerAngleStatus); metricMap.insert(11, &torqueStatus); metricMap.insert(12, &actuatorAccelerationStatus); - metricMap.insert(13, &accelerationJerkStatus); - metricMap.insert(14, &dangerJerkStatus); - metricMap.insert(15, &speedJerkStatus); + metricMap.insert(13, &dangerFactorStatus); + metricMap.insert(14, &accelerationJerkStatus); + metricMap.insert(15, &dangerJerkStatus); + metricMap.insert(16, &speedJerkStatus); int count = 0; for (size_t i = 0; i < metricAssignments.size(); ++i) { diff --git a/frogpilot/ui/qt/widgets/developer_sidebar.h b/frogpilot/ui/qt/widgets/developer_sidebar.h index 473bcced9..bb5b53cd8 100644 --- a/frogpilot/ui/qt/widgets/developer_sidebar.h +++ b/frogpilot/ui/qt/widgets/developer_sidebar.h @@ -28,6 +28,7 @@ private: ItemStatus accelerationJerkStatus; ItemStatus accelerationStatus; ItemStatus actuatorAccelerationStatus; + ItemStatus dangerFactorStatus; ItemStatus dangerJerkStatus; ItemStatus delayStatus; ItemStatus frictionStatus; diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 9572103ef..43758aeb7 100644 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -273,6 +273,7 @@ class CarInterface(CarInterfaceBase): # 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] + ret.longitudinalTuning.kfDEPRECATED = 0.15 ret.stoppingDecelRate = 0.8 else: # Pedal used for SNG, ACC for longitudinal control otherwise ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 34feea6b8..0c20f0868 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -287,6 +287,7 @@ class CarInterfaceBase(ABC): ret.vEgoStopping = 0.5 ret.vEgoStarting = 0.5 ret.stoppingControl = True + ret.longitudinalTuning.kfDEPRECATED = 1. ret.longitudinalTuning.kpBP = [0.] ret.longitudinalTuning.kpV = [0.] ret.longitudinalTuning.kiBP = [0.] @@ -302,6 +303,9 @@ class CarInterfaceBase(ABC): tune.init('torque') tune.torque.useSteeringAngle = use_steering_angle + tune.torque.kp = 1.0 + tune.torque.ki = 0.3 + tune.torque.kd = 0.0 tune.torque.friction = params['FRICTION'] tune.torque.latAccelFactor = params['LAT_ACCEL_FACTOR'] tune.torque.latAccelOffset = 0.0 diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 7f58bf970..67d3489d9 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -770,7 +770,7 @@ class Controls: if self.frogpilot_toggles.conditional_experimental_mode or self.frogpilot_toggles.slc_fallback_experimental_mode: self.experimental_mode = self.sm['frogpilotPlan'].experimentalMode - if hasattr(self.LaC, "pid"): + if hasattr(self.LaC, "pid") and self.CP.lateralTuning.which() != "pid": self.LaC.pid._k_p = self.frogpilot_toggles.steerKp # Update FrogPilot variables diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 2f090cb02..ade706b62 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -16,22 +16,15 @@ from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_G # wheel slip, or to speed. # This controller applies torque to achieve desired lateral -# accelerations. To compensate for the low speed effects the -# proportional gain is increased at low speeds by the PID controller. -# Additionally, there is friction in the steering wheel that needs -# to be overcome to move it at all, this is compensated for too. +# accelerations. To compensate for the low speed effects we +# use a LOW_SPEED_FACTOR in the error. Additionally, there is +# friction in the steering wheel that needs to be overcome to +# move it at all, this is compensated for too. -KP = 1.0 -KI = 0.1 -KD = 0.3 -INTERP_SPEEDS = [1, 1.5, 2.0, 3.0, 5, 7.5, 10, 15, 30] -KP_INTERP = [250, 120, 65, 30, 11.5, 5.5, 3.5, 2.0, KP] +LOW_SPEED_X = [0, 10, 20, 30] +LOW_SPEED_Y = [15, 13, 10, 5] -LP_FILTER_CUTOFF_HZ = 1.2 -JERK_LOOKAHEAD_SECONDS = 0.19 -JERK_GAIN = 0.3 -LAT_ACCEL_REQUEST_BUFFER_SECONDS = 1.0 -VERSION = 1 # bump this when changing controller +MAX_LAT_JERK_UP = 2.5 # m/s^3 class LatControlTorque(LatControl): def __init__(self, CP, CI, dt): @@ -39,15 +32,13 @@ class LatControlTorque(LatControl): 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() - self.pid = PIDController([INTERP_SPEEDS, KP_INTERP], KI, KD, rate=1/self.dt) + self.pid = PIDController(self.torque_params.kp, self.torque_params.ki, rate=1/self.dt) self.update_limits() self.steering_angle_deadzone_deg = self.torque_params.steeringAngleDeadzoneDeg - self.lookahead_frames = int(JERK_LOOKAHEAD_SECONDS / self.dt) - self.lat_accel_request_buffer_len = int(LAT_ACCEL_REQUEST_BUFFER_SECONDS / self.dt) - self.lat_accel_request_buffer = deque([0.] * self.lat_accel_request_buffer_len , maxlen=self.lat_accel_request_buffer_len) - self.jerk_filter = FirstOrderFilter(0.0, 1 / (2 * np.pi * LP_FILTER_CUTOFF_HZ), self.dt) - self.measurement_rate_filter = FirstOrderFilter(0.0, 1 / (2 * np.pi * LP_FILTER_CUTOFF_HZ), self.dt) + self.LATACCEL_REQUEST_BUFFER_NUM_FRAMES = int(1 / self.dt) + self.requested_lateral_accel_buffer = deque([0.] * self.LATACCEL_REQUEST_BUFFER_NUM_FRAMES , maxlen=self.LATACCEL_REQUEST_BUFFER_NUM_FRAMES) self.previous_measurement = 0.0 + self.measurement_rate_filter = FirstOrderFilter(0.0, 1 / (2 * np.pi * (MAX_LAT_JERK_UP - 0.5)), self.dt) def update_live_torque_params(self, latAccelFactor, latAccelOffset, friction): self.torque_params.latAccelFactor = latAccelFactor @@ -61,7 +52,6 @@ class LatControlTorque(LatControl): 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.LateralTorqueState.new_message() - pid_log.version = VERSION if not active: output_torque = 0.0 pid_log.active = False @@ -71,31 +61,37 @@ class LatControlTorque(LatControl): curvature_deadzone = abs(VM.calc_curvature(math.radians(self.steering_angle_deadzone_deg), CS.vEgo, 0.0)) lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 - delay_frames = int(np.clip(lat_delay / self.dt, 1, self.lat_accel_request_buffer_len)) - expected_lateral_accel = self.lat_accel_request_buffer[-delay_frames] - lookahead_idx = int(np.clip(-delay_frames + self.lookahead_frames, -self.lat_accel_request_buffer_len+1, -2)) - raw_lateral_jerk = (self.lat_accel_request_buffer[lookahead_idx+1] - self.lat_accel_request_buffer[lookahead_idx-1]) / (2 * self.dt) - desired_lateral_jerk = self.jerk_filter.update(raw_lateral_jerk) + delay_frames = int(np.clip(lat_delay / self.dt, 1, self.LATACCEL_REQUEST_BUFFER_NUM_FRAMES)) + expected_lateral_accel = self.requested_lateral_accel_buffer[-delay_frames] + # TODO factor out lateral jerk from error to later replace it with delay independent alternative future_desired_lateral_accel = desired_curvature * CS.vEgo ** 2 - self.lat_accel_request_buffer.append(future_desired_lateral_accel) + self.requested_lateral_accel_buffer.append(future_desired_lateral_accel) gravity_adjusted_future_lateral_accel = future_desired_lateral_accel - roll_compensation - setpoint = expected_lateral_accel + desired_lateral_jerk = (future_desired_lateral_accel - expected_lateral_accel) / lat_delay measurement = measured_curvature * CS.vEgo ** 2 measurement_rate = self.measurement_rate_filter.update((measurement - self.previous_measurement) / self.dt) self.previous_measurement = measurement + low_speed_factor = (np.interp(CS.vEgo, LOW_SPEED_X, LOW_SPEED_Y) / max(CS.vEgo, MIN_SPEED)) ** 2 + setpoint = lat_delay * desired_lateral_jerk + expected_lateral_accel error = setpoint - measurement + error_lsf = error + low_speed_factor / self.torque_params.kp * error # do error correction in lateral acceleration space, convert at end to handle non-linear torque responses correctly - pid_log.error = float(error) + pid_log.error = float(error_lsf) ff = gravity_adjusted_future_lateral_accel # latAccelOffset corrects roll compensation bias from device roll misalignment relative to car roll ff -= self.torque_params.latAccelOffset - ff += get_friction(error + JERK_GAIN * desired_lateral_jerk, lateral_accel_deadzone, FRICTION_THRESHOLD, self.torque_params) + # TODO jerk is weighted by lat_delay for legacy reasons, but should be made independent of it + ff += get_friction(error, lateral_accel_deadzone, FRICTION_THRESHOLD, self.torque_params) freeze_integrator = steer_limited_by_safety or CS.steeringPressed or CS.vEgo < 5 - output_lataccel = self.pid.update(pid_log.error, -measurement_rate, CS.vEgo, ff, freeze_integrator) + output_lataccel = self.pid.update(pid_log.error, + -measurement_rate, + feedforward=ff, + speed=CS.vEgo, + freeze_integrator=freeze_integrator) output_torque = self.torque_from_lateral_accel(output_lataccel, self.torque_params) pid_log.active = True @@ -103,10 +99,9 @@ class LatControlTorque(LatControl): pid_log.i = float(self.pid.i) pid_log.d = float(self.pid.d) pid_log.f = float(self.pid.f) - pid_log.output = float(-output_torque) # TODO: log lat accel? + pid_log.output = float(-output_torque) # TODO: log lat accel? pid_log.actualLateralAccel = float(measurement) pid_log.desiredLateralAccel = float(setpoint) - 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)) # TODO left is positive in this convention diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py index f92b3cdb1..9b3c16733 100644 --- a/selfdrive/controls/lib/longcontrol.py +++ b/selfdrive/controls/lib/longcontrol.py @@ -92,7 +92,7 @@ class LongControl: self.long_control_state = LongCtrlState.off self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), (CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV), - rate=1 / DT_CTRL) + k_f=CP.longitudinalTuning.kfDEPRECATED, rate=1 / DT_CTRL) self.v_pid = 0.0 self.last_output_accel = 0.0 diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py index 21410e23f..7ebdaabd9 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @@ -350,7 +350,7 @@ class LongitudinalMpc: lead_xv = self.extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau) return lead_xv - def update(self, radarstate, v_cruise, x, v, a, j, t_follow, personality=log.LongitudinalPersonality.standard): + def update(self, radarstate, v_cruise, x, v, a, j, danger_factor, t_follow, personality=log.LongitudinalPersonality.standard): v_ego = self.x0[1] self.status = radarstate.leadOne.status or radarstate.leadTwo.status @@ -368,7 +368,7 @@ class LongitudinalMpc: # Update in ACC mode or ACC/e2e blend if self.mode == 'acc': - self.params[:,5] = LEAD_DANGER_FACTOR + self.params[:,5] = danger_factor # Fake an obstacle for cruise, this ensures smooth acceleration to set speed # when the leads are no factor. diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 2fb2bde9d..e72c12812 100644 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -155,7 +155,7 @@ class LongitudinalPlanner: self.mpc.set_weights(sm['frogpilotPlan'].accelerationJerk, sm['frogpilotPlan'].dangerJerk, sm['frogpilotPlan'].speedJerk, prev_accel_constraint, personality=sm['controlsState'].personality) self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) - self.mpc.update(sm['radarState'], v_cruise, x, v, a, j, sm['frogpilotPlan'].tFollow, personality=sm['controlsState'].personality) + self.mpc.update(sm['radarState'], v_cruise, x, v, a, j, sm['frogpilotPlan'].dangerFactor, sm['frogpilotPlan'].tFollow, personality=sm['controlsState'].personality) self.a_desired_trajectory_full = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.a_solution) self.v_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.v_solution) diff --git a/selfdrive/controls/lib/pid.py b/selfdrive/controls/lib/pid.py index e3fa8afdf..7cf25ed5a 100644 --- a/selfdrive/controls/lib/pid.py +++ b/selfdrive/controls/lib/pid.py @@ -2,10 +2,11 @@ import numpy as np from numbers import Number class PIDController: - def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100): + def __init__(self, k_p, k_i, k_f=1., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100): self._k_p = k_p self._k_i = k_i self._k_d = k_d + self.k_f = k_f # feedforward gain if isinstance(self._k_p, Number): self._k_p = [[0], [self._k_p]] if isinstance(self._k_i, Number): @@ -47,7 +48,7 @@ class PIDController: self.speed = speed self.p = self.k_p * float(error) self.d = self.k_d * error_rate - self.f = feedforward + self.f = self.k_f * feedforward if not freeze_integrator: i = self.i + self.k_i * self.i_dt * error diff --git a/selfdrive/controls/radard.py b/selfdrive/controls/radard.py index 902f48bbc..999770ff2 100644 --- a/selfdrive/controls/radard.py +++ b/selfdrive/controls/radard.py @@ -110,8 +110,8 @@ class Track: "radarTrackId": self.identifier, } - def potential_adjacent_lead(self, left: bool, standstill: bool, model_data: capnp._DynamicStructReader): - if standstill or self.vLead < 1 or self.leadTrackID == self.identifier: + def potential_adjacent_lead(self, left: bool, model_data: capnp._DynamicStructReader): + if self.vLeadK < 1 or self.leadTrackID == self.identifier: return False far_left_lane = interp(self.dRel, model_data.laneLines[0].x, model_data.laneLines[0].y) @@ -119,22 +119,19 @@ class Track: right_lane = interp(self.dRel, model_data.laneLines[2].x, model_data.laneLines[2].y) far_right_lane = interp(self.dRel, model_data.laneLines[3].x, model_data.laneLines[3].y) - self.leadLeft = far_left_lane < -self.yRel < left_lane - self.leadRight = right_lane < -self.yRel < far_right_lane + self.leadLeft = far_left_lane < -self.yRel < left_lane and self.dRel < model_data.position.x[-1] + self.leadRight = right_lane < -self.yRel < far_right_lane and self.dRel < model_data.position.x[-1] if left: return self.leadLeft else: return self.leadRight - def potential_far_lead(self, standstill: bool, model_data: capnp._DynamicStructReader): - if standstill or self.vLead < 1: - return False - + def potential_far_lead(self, lead_msg: capnp._DynamicStructReader, model_data: capnp._DynamicStructReader): left_lane = interp(self.dRel, model_data.laneLines[1].x, model_data.laneLines[1].y) right_lane = interp(self.dRel, model_data.laneLines[2].x, model_data.laneLines[2].y) - if left_lane < -self.yRel < right_lane: + if left_lane < -self.yRel < right_lane and self.dRel < model_data.position.x[-1] and (self.vLeadK > 1 or lead_msg.prob > 0.25): self.radarfulFilter.update(1) return True else: @@ -214,7 +211,7 @@ def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: floa def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capnp._DynamicStructReader, - model_v_ego: float, model_data: capnp._DynamicStructReader, standstill: bool, + model_v_ego: float, model_data: capnp._DynamicStructReader, frogpilot_plan: capnp._DynamicStructReader, frogpilot_toggles: SimpleNamespace, low_speed_override: bool = True) -> dict[str, Any]: # Determine leads, this is where the essential logic happens @@ -239,7 +236,7 @@ def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capn lead_dict = closest_track.get_RadarState() if not lead_dict['status'] and len(tracks) > 0: - far_lead_tracks = [c for c in tracks.values() if c.potential_far_lead(standstill, model_data) and c.radarfulFilter.x >= THRESHOLD] + far_lead_tracks = [c for c in tracks.values() if c.potential_far_lead(lead_msg, model_data) and c.radarfulFilter.x >= THRESHOLD] if len(far_lead_tracks) > 0: closest_track = min(far_lead_tracks, key=lambda c: c.dRel) lead_dict = closest_track.get_RadarState() @@ -253,10 +250,10 @@ def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capn return lead_dict -def get_adjacent_lead(tracks: dict[int, Track], standstill: bool, model_data: capnp._DynamicStructReader, left: bool = True) -> dict[str, Any]: +def get_adjacent_lead(tracks: dict[int, Track], model_data: capnp._DynamicStructReader, left: bool = True) -> dict[str, Any]: lead_dict = {'status': False} - adjacent_tracks = [c for c in tracks.values() if c.potential_adjacent_lead(left, standstill, model_data)] + adjacent_tracks = [c for c in tracks.values() if c.potential_adjacent_lead(left, model_data)] if len(adjacent_tracks) > 0: closest_track = min(adjacent_tracks, key=lambda c: c.dRel) lead_dict = closest_track.get_RadarState() @@ -336,12 +333,12 @@ class RadarD: model_v_ego = self.v_ego leads_v3 = sm['modelV2'].leadsV3 if len(leads_v3) > 1: - self.radar_state.leadOne = get_lead(self.v_ego, self.ready, self.tracks, leads_v3[0], model_v_ego, sm['modelV2'], sm['carState'].standstill, sm['frogpilotPlan'], self.frogpilot_toggles, low_speed_override=True) - self.radar_state.leadTwo = get_lead(self.v_ego, self.ready, self.tracks, leads_v3[1], model_v_ego, sm['modelV2'], sm['carState'].standstill, sm['frogpilotPlan'], self.frogpilot_toggles, low_speed_override=False) + self.radar_state.leadOne = get_lead(self.v_ego, self.ready, self.tracks, leads_v3[0], model_v_ego, sm['modelV2'], sm['frogpilotPlan'], self.frogpilot_toggles, low_speed_override=True) + self.radar_state.leadTwo = get_lead(self.v_ego, self.ready, self.tracks, leads_v3[1], model_v_ego, sm['modelV2'], sm['frogpilotPlan'], self.frogpilot_toggles, low_speed_override=False) if (self.frogpilot_toggles.adjacent_lead_tracking or self.frogpilot_toggles.human_lane_changes) and self.ready: - self.frogpilot_radar_state.leadLeft = get_adjacent_lead(self.tracks, sm['carState'].standstill, sm['modelV2'], left=True) - self.frogpilot_radar_state.leadRight = get_adjacent_lead(self.tracks, sm['carState'].standstill, sm['modelV2'], left=False) + self.frogpilot_radar_state.leadLeft = get_adjacent_lead(self.tracks, sm['modelV2'], left=True) + self.frogpilot_radar_state.leadRight = get_adjacent_lead(self.tracks, sm['modelV2'], left=False) # Update FrogPilot variables if sm['frogpilotPlan'].togglesUpdated: diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts index 1d54e208d..4f5f5185d 100644 --- a/selfdrive/ui/translations/main_ar.ts +++ b/selfdrive/ui/translations/main_ar.ts @@ -253,6 +253,10 @@ TORQUE % عزم + + DANGER FACTOR + عامل الخطر + DevicePanel @@ -966,6 +970,14 @@ % of % من + + Driving Personalities: + شخصيات القيادة + + + Time Spent in Weather: + الوقت المستغرق في الطقس + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 حدث خطأ: %1 + + Characters: 0/%1 + عدد الأحرف: 0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 أدخل %1 الخاص بك - - Inputted key is invalid or too short! - المفتاح المُدخل غير صالح أو قصير جدًا! - Remove your %1? هل تريد إزالة %1؟ @@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>اضبط سماكة حافة الطريق.</b><br><br>القيمة الافتراضية تطابق نصف معيار MUTCD لعرض خط المسار وهو 10 سنتيمترات. + + Longitudinal MPC: Danger Factor + عامل الخطر لمنظّم الحركة الطولي (MPC) + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_caveman.ts b/selfdrive/ui/translations/main_caveman.ts index 39380a350..ec8410844 100644 --- a/selfdrive/ui/translations/main_caveman.ts +++ b/selfdrive/ui/translations/main_caveman.ts @@ -254,6 +254,10 @@ TORQUE % TORQUE % + + DANGER FACTOR + DANGER FACTOR + DevicePanel @@ -967,6 +971,14 @@ % of % of + + Driving Personalities: + Drive Personality: + + + Time Spent in Weather: + Time Spent in Sky Mood: + FrogPilotDevicePanel @@ -2608,6 +2620,10 @@ An error occurred: %1 Error happen: %1 + + Characters: 0/%1 + Marks: 0/%1 + FrogPilotManageControl @@ -3219,10 +3235,6 @@ It reset in %1 hour and %2 minute. Enter your %1 You put %1 - - Inputted key is invalid or too short! - Key bad or too short! - Remove your %1? You remove %1? @@ -5030,6 +5042,10 @@ Developer - Many custom setting for seasoned enthusiast <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Set road-edge thickness.</b><br><br>Default same as half MUTCD lane-line width standard, 10 centimeters. + + Longitudinal MPC: Danger Factor + Longitudinal MPC: Danger Factor + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 765bf741b..a6eed7c55 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -253,6 +253,10 @@ TORQUE % DREHMOMENT % + + DANGER FACTOR + GEFAHRENFAKTOR + DevicePanel @@ -966,6 +970,14 @@ % of % von + + Driving Personalities: + Fahrprofile: + + + Time Spent in Weather: + Verbrachte Zeit bei Wetterbedingungen: + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Ein Fehler ist aufgetreten: %1 + + Characters: 0/%1 + Zeichen: 0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ Es wird in %1 Stunden und %2 Minuten zurückgesetzt. Enter your %1 Geben Sie Ihr %1 ein - - Inputted key is invalid or too short! - Eingegebener Schlüssel ist ungültig oder zu kurz! - Remove your %1? Entfernen Sie Ihr %1? @@ -5024,6 +5036,10 @@ Entwickler – Hochgradig anpassbare Einstellungen für versierte Enthusiasten<b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Stellen Sie die Randstreifendicke ein.</b><br><br>Standard entspricht der Hälfte des MUTCD-Standards für Fahrbahnmarkierungsbreite von 10 Zentimetern. + + Longitudinal MPC: Danger Factor + Längsdynamik-MPC: Gefahrenfaktor + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_duck.ts b/selfdrive/ui/translations/main_duck.ts index a84cd788f..35cde7596 100644 --- a/selfdrive/ui/translations/main_duck.ts +++ b/selfdrive/ui/translations/main_duck.ts @@ -253,6 +253,10 @@ TORQUE % Quack! TORQUE % — waddle-whoosh! + + DANGER FACTOR + QUACK DANGER FACTOR WADDLE! + DevicePanel @@ -966,6 +970,14 @@ % of Quack % of quack! + + Driving Personalities: + Quack-Quack Driving Personalities: Waddle! + + + Time Spent in Weather: + Quack Time in Weather: Waddle Waddle! + FrogPilotDevicePanel @@ -2608,6 +2620,10 @@ An error occurred: %1 Quack! An error splashed in: %1 + + Characters: 0/%1 + Quack-acters: 0/%1 + FrogPilotManageControl @@ -3219,10 +3235,6 @@ Waddle back later—resets in %1 hours and %2 minutes. Enter your %1 Quack! Waddle in your %1 - - Inputted key is invalid or too short! - Quack! That key’s invalid or too short, waddley-woot! - Remove your %1? Quack! Remove your %1, waddly-waddle? @@ -5026,6 +5038,10 @@ Developer - Ultra-custom settings for seasoned duckthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Quack! Set the road-edge thickness, waddlers.</b><br><br>Default quacks to half the MUTCD lane-line width standard of 10 centimeters. + + Longitudinal MPC: Danger Factor + Longitudinal MPC: Quack! Danger Factor 🦆 + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_es.ts b/selfdrive/ui/translations/main_es.ts index ac1fd8ce8..9dba58b76 100644 --- a/selfdrive/ui/translations/main_es.ts +++ b/selfdrive/ui/translations/main_es.ts @@ -253,6 +253,10 @@ TORQUE % PAR % + + DANGER FACTOR + FACTOR DE PELIGRO + DevicePanel @@ -966,6 +970,14 @@ % of % de + + Driving Personalities: + Personalidades de conducción + + + Time Spent in Weather: + Tiempo en el clima + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Ocurrió un error: %1 + + Characters: 0/%1 + Caracteres: 0/%1 + FrogPilotManageControl @@ -3216,10 +3232,6 @@ Se restablecerá en %1 horas y %2 minutos. Enter your %1 Introduce tu %1 - - Inputted key is invalid or too short! - ¡La clave introducida es inválida o demasiado corta! - Remove your %1? ¿Quitar su %1? @@ -5023,6 +5035,10 @@ Desarrollador: configuración altamente personalizable para entusiastas veterano <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Establece el grosor del borde de la carretera.</b><br><br>El valor predeterminado coincide con la mitad del estándar MUTCD de ancho de línea de carril de 10 centímetros. + + Longitudinal MPC: Danger Factor + MPC longitudinal: factor de peligro + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_fr.ts b/selfdrive/ui/translations/main_fr.ts index 6ba9e0731..7e69b5547 100644 --- a/selfdrive/ui/translations/main_fr.ts +++ b/selfdrive/ui/translations/main_fr.ts @@ -253,6 +253,10 @@ TORQUE % COUPLE % + + DANGER FACTOR + FACTEUR DE DANGER + DevicePanel @@ -966,6 +970,14 @@ % of % de + + Driving Personalities: + Personnalités de conduite + + + Time Spent in Weather: + Temps passé par météo + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Une erreur s’est produite : %1 + + Characters: 0/%1 + Caractères : 0/%1 + FrogPilotManageControl @@ -3216,10 +3232,6 @@ Elle sera réinitialisée dans %1 heures et %2 minutes. Enter your %1 Saisissez votre %1 - - Inputted key is invalid or too short! - La clé saisie est invalide ou trop courte ! - Remove your %1? Retirer votre %1 ? @@ -5023,6 +5035,10 @@ Développeur – Paramètres hautement personnalisables pour passionnés chevron <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Réglez l’épaisseur du bord de route.</b><br><br>La valeur par défaut correspond à la moitié de la largeur standard des lignes de voie du MUTCD, soit 10 centimètres. + + Longitudinal MPC: Danger Factor + MPC longitudinal : facteur de danger + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_frog.ts b/selfdrive/ui/translations/main_frog.ts index 523a3c63c..fa958dc69 100644 --- a/selfdrive/ui/translations/main_frog.ts +++ b/selfdrive/ui/translations/main_frog.ts @@ -253,6 +253,10 @@ TORQUE % Ribbit TORQUE % croak + + DANGER FACTOR + RIBBIT DANGER FACTOR CROAK + DevicePanel @@ -966,6 +970,14 @@ % of Ribbit % of croak + + Driving Personalities: + Ribbit Rides: Croak-sonalities! + + + Time Spent in Weather: + Ribbit! Time Spent in Weather, croak! + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Ribbit! An error croaked up: %1 + + Characters: 0/%1 + Ribbit: 0/%1 croak + FrogPilotManageControl @@ -3217,10 +3233,6 @@ It’ll reset in %1 hours and %2 minutes. Enter your %1 Ribbit! Enter your %1, croak. - - Inputted key is invalid or too short! - Ribbit! That key’s no good or too tiny, croak! - Remove your %1? Ribbit! Remove your %1? Croak! @@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned swamp pros <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Croak! Set the road-edge thickness.</b><br><br>Default ribbits to half the MUTCD lane-line width standard of 10 centimeters. + + Longitudinal MPC: Danger Factor + Ribbit-longitudinal MPC: Danger Factor, croak! + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 146d27da7..5199dc760 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -253,6 +253,10 @@ TORQUE % トルク % + + DANGER FACTOR + 危険要因 + DevicePanel @@ -966,6 +970,14 @@ % of % の + + Driving Personalities: + 運転の個性 + + + Time Spent in Weather: + 天候での経過時間 + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 エラーが発生しました: %1 + + Characters: 0/%1 + 文字数: 0/%1 + FrogPilotManageControl @@ -3215,10 +3231,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 %1 を入力してください - - Inputted key is invalid or too short! - 入力したキーが無効か短すぎます! - Remove your %1? %1 を取り外しますか? @@ -5022,6 +5034,10 @@ Developer - こだわりのある上級者向けの高度にカスタマイズ <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>道路端の太さを設定します。</b><br><br>デフォルトは、MUTCDの車線線幅標準10センチメートルの半分に一致します。 + + Longitudinal MPC: Danger Factor + 縦方向MPC:危険係数 + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 5501954a1..1dfa69575 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -253,6 +253,10 @@ TORQUE % 토크 % + + DANGER FACTOR + 위험 요소 + DevicePanel @@ -966,6 +970,14 @@ % of % 중 + + Driving Personalities: + 운전 성향:" + + + Time Spent in Weather: + 날씨에서 보낸 시간 + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 오류가 발생했습니다: %1 + + Characters: 0/%1 + 문자: 0/%1 + FrogPilotManageControl @@ -3216,10 +3232,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 %1을(를) 입력하세요 - - Inputted key is invalid or too short! - 입력한 키가 유효하지 않거나 너무 짧습니다! - Remove your %1? %1을(를) 제거하시겠습니까? @@ -5023,6 +5035,10 @@ Developer - Highly customizable settings for seasoned enthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>도로 가장자리 두께를 설정하세요.</b><br><br>기본값은 MUTCD 차선선 폭 표준 10센티미터의 절반과 일치합니다. + + Longitudinal MPC: Danger Factor + 종방향 MPC: 위험 요인 + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_pirate.ts b/selfdrive/ui/translations/main_pirate.ts index 2baadd05c..8775c7b1d 100644 --- a/selfdrive/ui/translations/main_pirate.ts +++ b/selfdrive/ui/translations/main_pirate.ts @@ -253,6 +253,10 @@ TORQUE % TORQUE % + + DANGER FACTOR + DANGER FACTOR, ye scallywag + DevicePanel @@ -966,6 +970,14 @@ % of % o’ + + Driving Personalities: + Sailin’ Personalities: + + + Time Spent in Weather: + Time Spent in Thar Weather: + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Arr, an error befall'd: %1 + + Characters: 0/%1 + Characters: 0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ It’ll reset in %1 hours ‘n %2 minutes. Enter your %1 Avast! Enter yer %1 - - Inputted key is invalid or too short! - Arr, the key ye entered be invalid or too short! - Remove your %1? Be ye removin’ yer %1? @@ -5024,6 +5036,10 @@ Developer - Highly customizable riggin’s fer seasoned enthusiasts<b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Set th’ road-edge thickness, ye landlubber.</b><br><br>Default be half o’ the MUTCD lane-line width standard o’ 10 centimeters. + + Longitudinal MPC: Danger Factor + Longitudinal MPC: Peril Factor + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index d718d8e41..8d9e6e72b 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -253,6 +253,10 @@ TORQUE % TORQUE % + + DANGER FACTOR + FATOR DE PERIGO + DevicePanel @@ -966,6 +970,14 @@ % of % de + + Driving Personalities: + Personalidades de Condução + + + Time Spent in Weather: + Tempo gasto em clima: + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Ocorreu um erro: %1 + + Characters: 0/%1 + Caracteres: 0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ Ele será reiniciado em %1 horas e %2 minutos. Enter your %1 Insira seu %1 - - Inputted key is invalid or too short! - A chave inserida é inválida ou muito curta! - Remove your %1? Remover seu %1? @@ -5024,6 +5036,10 @@ Desenvolvedor - Configurações altamente personalizáveis para entusiastas expe <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Defina a espessura da borda da estrada.</b><br><br>O padrão corresponde à metade do padrão de largura de faixa do MUTCD de 10 centímetros. + + Longitudinal MPC: Danger Factor + MPC Longitudinal: Fator de Perigo + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_shakespearean.ts b/selfdrive/ui/translations/main_shakespearean.ts index c7d8443b5..e9c810eda 100644 --- a/selfdrive/ui/translations/main_shakespearean.ts +++ b/selfdrive/ui/translations/main_shakespearean.ts @@ -253,6 +253,10 @@ TORQUE % TORQUE % + + DANGER FACTOR + PERILOUS FACTOR + DevicePanel @@ -971,6 +975,14 @@ % of % of + + Driving Personalities: + Driving Dispositions: + + + Time Spent in Weather: + Time Bestow’d in Tempest: + FrogPilotDevicePanel @@ -2615,6 +2627,10 @@ An error occurred: %1 An error hath occurred: %1 + + Characters: 0/%1 + Characters: 0/%1 + FrogPilotManageControl @@ -3226,10 +3242,6 @@ It shall reset in %1 hours and %2 minutes. Enter your %1 Enter thy %1 - - Inputted key is invalid or too short! - The key thou hast entered is invalid or too brief! - Remove your %1? Wilt thou remove thy %1? @@ -5039,6 +5051,10 @@ Developer - Most customizable settings for well-tried enthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Set the road-edge thickness.</b><br><br>The default doth match half the MUTCD lane-line width standard of 10 centimeters. + + Longitudinal MPC: Danger Factor + Longitudinal MPC: Peril Factor + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts index b7a9268ab..48dcf6281 100644 --- a/selfdrive/ui/translations/main_th.ts +++ b/selfdrive/ui/translations/main_th.ts @@ -253,6 +253,10 @@ TORQUE % แรงบิด % + + DANGER FACTOR + ปัจจัยอันตราย + DevicePanel @@ -966,6 +970,14 @@ % of % ของ + + Driving Personalities: + ลักษณะการขับขี่ + + + Time Spent in Weather: + เวลาที่ใช้ในสภาพอากาศ + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 เกิดข้อผิดพลาด: %1 + + Characters: 0/%1 + อักขระ: 0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 ป้อน %1 ของคุณ - - Inputted key is invalid or too short! - คีย์ที่ป้อนไม่ถูกต้องหรือสั้นเกินไป! - Remove your %1? ลบ %1 ของคุณหรือไม่? @@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>ตั้งค่าความหนาของขอบถนน</b><br><br>ค่าเริ่มต้นเท่ากับครึ่งหนึ่งของมาตรฐานความกว้างเส้นแบ่งช่องจราจรของ MUTCD ที่ 10 เซนติเมตร + + Longitudinal MPC: Danger Factor + MPC ตามยาว: ปัจจัยอันตราย + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_tr.ts b/selfdrive/ui/translations/main_tr.ts index 2cc27d17e..72efa5056 100644 --- a/selfdrive/ui/translations/main_tr.ts +++ b/selfdrive/ui/translations/main_tr.ts @@ -253,6 +253,10 @@ TORQUE % TORK % + + DANGER FACTOR + TEHLİKE FAKTÖRÜ + DevicePanel @@ -966,6 +970,14 @@ % of % of + + Driving Personalities: + Sürüş Kişilikleri + + + Time Spent in Weather: + Havada Geçirilen Süre: + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Bir hata oluştu: %1 + + Characters: 0/%1 + Karakterler: 0/%1 + FrogPilotManageControl @@ -3216,10 +3232,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 %1 girin - - Inputted key is invalid or too short! - Girilen anahtar geçersiz veya çok kısa! - Remove your %1? %1 öğenizi kaldırın? @@ -5023,6 +5035,10 @@ Geliştirici - Tecrübeli meraklılar için yüksek özelleştirilebilir ayarlar <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Yol kenarı kalınlığını ayarlayın.</b><br><br>Varsayılan, MUTCD şerit çizgisi genişliği standardı olan 10 santimetrenin yarısına karşılık gelir. + + Longitudinal MPC: Danger Factor + Boylamsal MPC: Tehlike Faktörü + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_uk.ts b/selfdrive/ui/translations/main_uk.ts index 7505c77f3..dbdceea40 100644 --- a/selfdrive/ui/translations/main_uk.ts +++ b/selfdrive/ui/translations/main_uk.ts @@ -253,6 +253,10 @@ TORQUE % МОМЕНТ % + + DANGER FACTOR + ФАКТОР НЕБЕЗПЕКИ + DevicePanel @@ -966,6 +970,14 @@ % of % від + + Driving Personalities: + Стилі водіння + + + Time Spent in Weather: + Час, проведений у погодних умовах: + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 Сталася помилка: %1 + + Characters: 0/%1 + Символи: 0/%1 + FrogPilotManageControl @@ -3125,10 +3141,6 @@ Enter your %1 Введіть ваш %1 - - Inputted key is invalid or too short! - Введений ключ недійсний або занадто короткий! - REMOVE ПРИБРАТИ @@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>Встановіть товщину краю дороги.</b><br><br>За замовчуванням встановлюється половина стандартної ширини смуги руху MUTCD, яка становить 10 сантиметрів. + + Longitudinal MPC: Danger Factor + Поздовжній MPC: Фактор небезпеки + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 1a33ce4a3..cd73c9c08 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -253,6 +253,10 @@ TORQUE % 扭矩 % + + DANGER FACTOR + 危险因素 + DevicePanel @@ -966,6 +970,14 @@ % of % 的 + + Driving Personalities: + 驾驶风格 + + + Time Spent in Weather: + 在天气中的时间 + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 发生错误:%1 + + Characters: 0/%1 + 字符:0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 输入你的%1 - - Inputted key is invalid or too short! - 输入的密钥无效或过短! - Remove your %1? 要移除你的%1吗? @@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>设置路缘厚度。</b><br><br>默认值等于 MUTCD 车道线宽度标准 10 厘米的一半。 + + Longitudinal MPC: Danger Factor + 纵向MPC:危险系数 + FrogPilotWheelPanel diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index cc25070e1..c03f762bd 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -253,6 +253,10 @@ TORQUE % 扭矩 % + + DANGER FACTOR + 危險因素 + DevicePanel @@ -966,6 +970,14 @@ % of % 的 + + Driving Personalities: + 駕駛風格: + + + Time Spent in Weather: + 在天氣中的花費時間: + FrogPilotDevicePanel @@ -2606,6 +2618,10 @@ An error occurred: %1 發生錯誤:%1 + + Characters: 0/%1 + 字元:0/%1 + FrogPilotManageControl @@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes. Enter your %1 輸入您的 %1 - - Inputted key is invalid or too short! - 輸入的金鑰無效或過短! - Remove your %1? 要移除您的 %1 嗎? @@ -5024,6 +5036,10 @@ Developer - 為資深愛好者提供高度自訂的設定 <b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters. <b>設定道路邊緣粗細。</b><br><br>預設值相當於符合 MUTCD 車道線標準 10 公分的一半。 + + Longitudinal MPC: Danger Factor + 縱向 MPC:危險因子 + FrogPilotWheelPanel diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 3273c1ce0..6393241fc 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -404,6 +404,9 @@ void Device::setAwake(bool on) { void Device::resetInteractiveTimeout(int timeout, int timeout_onroad) { if (timeout == -1) { timeout = (ignition_on ? 10 : 30); + } else { + // FrogPilot variables + timeout = (ignition_on ? timeout_onroad : timeout); } interactive_timeout = timeout * UI_FREQ; }