mirror of
https://github.com/MoreTore/openpilot.git
synced 2026-08-06 00:36:32 +08:00
November 15th, 2025 Patch
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -57,7 +57,7 @@ We have detailed instructions for [how to install the harness and device in a ca
|
||||
|
||||
[](https://deepwiki.com/FrogAi/FrogPilot)
|
||||
[](https://discord.frogpilot.download)
|
||||
[](https://github.com/FrogAi/FrogPilot/releases/latest)
|
||||
[](https://github.com/FrogAi/FrogPilot/releases/latest)
|
||||
[](https://frogpilot.wiki.gg/)
|
||||
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
+33
-32
@@ -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 {
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+50
-10
@@ -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
|
||||
@@ -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<QString> parent_keys = {
|
||||
"ModelTimes",
|
||||
"RandomEvents"
|
||||
"PersonalityTimes",
|
||||
"RandomEvents",
|
||||
"WeatherTimes"
|
||||
};
|
||||
|
||||
static QSet<QString> 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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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("<b>Manage your \"%1\".</b>").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)) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -313,7 +313,7 @@ FrogPilotVehiclesPanel::FrogPilotVehiclesPanel(FrogPilotSettingsWindow *parent)
|
||||
|
||||
static_cast<FrogPilotParamValueControl*>(toggles["LockDoorsTimer"])->setWarning("<b>Warning:</b> openpilot can't detect if keys are still inside the car, so ensure you have a spare key to prevent accidental lockouts!");
|
||||
|
||||
QSet<QString> rebootKeys = {"HondaAltTune", "NewLongAPI", "SubaruSNG", "TacoTuneHacks"};
|
||||
QSet<QString> rebootKeys = {"HondaAltTune", "NewLongAPI", "TacoTuneHacks"};
|
||||
for (const QString &key : rebootKeys) {
|
||||
QObject::connect(static_cast<ToggleControl*>(toggles[key]), &ToggleControl::toggleFlipped, [key, this](bool state) {
|
||||
if (started) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -117,6 +117,7 @@ void DeveloperSidebar::updateState(const UIState &s, const FrogPilotUIState &fs)
|
||||
accelerationStatus = ItemStatus(QPair<QString, QString>(tr("ACCEL"), QString::number(acceleration, 'f', 2) + accelerationUnit), metricColor);
|
||||
accelerationJerkStatus = ItemStatus(QPair<QString, QString>(tr("ACCEL JERK"), QString::number(frogpilotPlan.getAccelerationJerk())), metricColor);
|
||||
actuatorAccelerationStatus = ItemStatus(QPair<QString, QString>(tr("ACT ACCEL"), QString::number(carControl.getActuators().getAccel() * accelerationConversion, 'f', 2) + accelerationUnit), metricColor);
|
||||
dangerFactorStatus = ItemStatus(QPair<QString, QString>(tr("DANGER %"), QString::number(frogpilotPlan.getDangerFactor(), 'f', 2)), metricColor);
|
||||
dangerJerkStatus = ItemStatus(QPair<QString, QString>(tr("DANGER JERK"), QString::number(frogpilotPlan.getDangerJerk())), metricColor);
|
||||
delayStatus = ItemStatus(QPair<QString, QString>(tr("STEER DELAY"), QString::number(liveDelay.getLateralDelay(), 'f', 5)), metricColor);
|
||||
frictionStatus = ItemStatus(QPair<QString, QString>(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) {
|
||||
|
||||
@@ -28,6 +28,7 @@ private:
|
||||
ItemStatus accelerationJerkStatus;
|
||||
ItemStatus accelerationStatus;
|
||||
ItemStatus actuatorAccelerationStatus;
|
||||
ItemStatus dangerFactorStatus;
|
||||
ItemStatus dangerJerkStatus;
|
||||
ItemStatus delayStatus;
|
||||
ItemStatus frictionStatus;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">عزم</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">عامل الخطر</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% من</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">شخصيات القيادة</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">الوقت المستغرق في الطقس</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">حدث خطأ: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">عدد الأحرف: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">أدخل %1 الخاص بك</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">المفتاح المُدخل غير صالح أو قصير جدًا!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">هل تريد إزالة %1؟</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>اضبط سماكة حافة الطريق.</b><br><br>القيمة الافتراضية تطابق نصف معيار MUTCD لعرض خط المسار وهو 10 سنتيمترات.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">عامل الخطر لمنظّم الحركة الطولي (MPC)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -254,6 +254,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">TORQUE %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">DANGER FACTOR</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -967,6 +971,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% of</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Drive Personality:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Time Spent in Sky Mood:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2608,6 +2620,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Error happen: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Marks: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3219,10 +3235,6 @@ It reset in %1 hour and %2 minute.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">You put %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">Key bad or too short!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">You remove %1?</translation>
|
||||
@@ -5030,6 +5042,10 @@ Developer - Many custom setting for seasoned enthusiast</translation>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>Set road-edge thickness.</b><br><br>Default same as half MUTCD lane-line width standard, 10 centimeters.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Longitudinal MPC: Danger Factor</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">DREHMOMENT %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">GEFAHRENFAKTOR</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% von</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Fahrprofile:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Verbrachte Zeit bei Wetterbedingungen:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Ein Fehler ist aufgetreten: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Zeichen: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ Es wird in %1 Stunden und %2 Minuten zurückgesetzt.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Geben Sie Ihr %1 ein</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">Eingegebener Schlüssel ist ungültig oder zu kurz!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Entfernen Sie Ihr %1?</translation>
|
||||
@@ -5024,6 +5036,10 @@ Entwickler – Hochgradig anpassbare Einstellungen für versierte Enthusiasten</
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>Stellen Sie die Randstreifendicke ein.</b><br><br>Standard entspricht der Hälfte des MUTCD-Standards für Fahrbahnmarkierungsbreite von 10 Zentimetern.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Längsdynamik-MPC: Gefahrenfaktor</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">Quack! TORQUE % — waddle-whoosh!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">QUACK DANGER FACTOR WADDLE!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">Quack % of quack!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Quack-Quack Driving Personalities: Waddle!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Quack Time in Weather: Waddle Waddle!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2608,6 +2620,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Quack! An error splashed in: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Quack-acters: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3219,10 +3235,6 @@ Waddle back later—resets in %1 hours and %2 minutes.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Quack! Waddle in your %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">Quack! That key’s invalid or too short, waddley-woot!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Quack! Remove your %1, waddly-waddle?</translation>
|
||||
@@ -5026,6 +5038,10 @@ Developer - Ultra-custom settings for seasoned duckthusiasts</translation>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>Quack! Set the road-edge thickness, waddlers.</b><br><br>Default quacks to half the MUTCD lane-line width standard of 10 centimeters.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Longitudinal MPC: Quack! Danger Factor 🦆</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">PAR %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">FACTOR DE PELIGRO</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% de</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Personalidades de conducción</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Tiempo en el clima</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Ocurrió un error: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Caracteres: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3216,10 +3232,6 @@ Se restablecerá en %1 horas y %2 minutos.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Introduce tu %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">¡La clave introducida es inválida o demasiado corta!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">¿Quitar su %1?</translation>
|
||||
@@ -5023,6 +5035,10 @@ Desarrollador: configuración altamente personalizable para entusiastas veterano
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><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.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">MPC longitudinal: factor de peligro</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">COUPLE %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">FACTEUR DE DANGER</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% de</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Personnalités de conduite</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Temps passé par météo</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Une erreur s’est produite : %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Caractères : 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3216,10 +3232,6 @@ Elle sera réinitialisée dans %1 heures et %2 minutes.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Saisissez votre %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">La clé saisie est invalide ou trop courte !</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Retirer votre %1 ?</translation>
|
||||
@@ -5023,6 +5035,10 @@ Développeur – Paramètres hautement personnalisables pour passionnés chevron
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><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.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">MPC longitudinal : facteur de danger</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">Ribbit TORQUE % croak</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">RIBBIT DANGER FACTOR CROAK</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">Ribbit % of croak</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Ribbit Rides: Croak-sonalities!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Ribbit! Time Spent in Weather, croak!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Ribbit! An error croaked up: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Ribbit: 0/%1 croak</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ It’ll reset in %1 hours and %2 minutes.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Ribbit! Enter your %1, croak.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">Ribbit! That key’s no good or too tiny, croak!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Ribbit! Remove your %1? Croak!</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned swamp pros</translation>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>Croak! Set the road-edge thickness.</b><br><br>Default ribbits to half the MUTCD lane-line width standard of 10 centimeters.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Ribbit-longitudinal MPC: Danger Factor, croak!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">トルク %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">危険要因</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% の</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">運転の個性</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">天候での経過時間</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">エラーが発生しました: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">文字数: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3215,10 +3231,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">%1 を入力してください</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">入力したキーが無効か短すぎます!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">%1 を取り外しますか?</translation>
|
||||
@@ -5022,6 +5034,10 @@ Developer - こだわりのある上級者向けの高度にカスタマイズ
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>道路端の太さを設定します。</b><br><br>デフォルトは、MUTCDの車線線幅標準10センチメートルの半分に一致します。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">縦方向MPC:危険係数</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">토크 %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">위험 요소</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% 중</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">운전 성향:"</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">날씨에서 보낸 시간</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">오류가 발생했습니다: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">문자: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3216,10 +3232,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">%1을(를) 입력하세요</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">입력한 키가 유효하지 않거나 너무 짧습니다!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">%1을(를) 제거하시겠습니까?</translation>
|
||||
@@ -5023,6 +5035,10 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>도로 가장자리 두께를 설정하세요.</b><br><br>기본값은 MUTCD 차선선 폭 표준 10센티미터의 절반과 일치합니다.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">종방향 MPC: 위험 요인</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">TORQUE %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">DANGER FACTOR, ye scallywag</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% o’</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Sailin’ Personalities:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Time Spent in Thar Weather:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Arr, an error befall'd: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Characters: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ It’ll reset in %1 hours ‘n %2 minutes.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Avast! Enter yer %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">Arr, the key ye entered be invalid or too short!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Be ye removin’ yer %1?</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - Highly customizable riggin’s fer seasoned enthusiasts</translation
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>Set th’ road-edge thickness, ye landlubber.</b><br><br>Default be half o’ the MUTCD lane-line width standard o’ 10 centimeters.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Longitudinal MPC: Peril Factor</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">TORQUE %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">FATOR DE PERIGO</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% de</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Personalidades de Condução</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Tempo gasto em clima:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Ocorreu um erro: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Caracteres: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ Ele será reiniciado em %1 horas e %2 minutos.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Insira seu %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">A chave inserida é inválida ou muito curta!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Remover seu %1?</translation>
|
||||
@@ -5024,6 +5036,10 @@ Desenvolvedor - Configurações altamente personalizáveis para entusiastas expe
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><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.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">MPC Longitudinal: Fator de Perigo</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">TORQUE %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">PERILOUS FACTOR</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -971,6 +975,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% of</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Driving Dispositions:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Time Bestow’d in Tempest:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2615,6 +2627,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">An error hath occurred: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Characters: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3226,10 +3242,6 @@ It shall reset in %1 hours and %2 minutes.</translation>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">Enter thy %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">The key thou hast entered is invalid or too brief!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">Wilt thou remove thy %1?</translation>
|
||||
@@ -5039,6 +5051,10 @@ Developer - Most customizable settings for well-tried enthusiasts</translation>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>Set the road-edge thickness.</b><br><br>The default doth match half the MUTCD lane-line width standard of 10 centimeters.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Longitudinal MPC: Peril Factor</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">แรงบิด %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">ปัจจัยอันตราย</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% ของ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">ลักษณะการขับขี่</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">เวลาที่ใช้ในสภาพอากาศ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">เกิดข้อผิดพลาด: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">อักขระ: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">ป้อน %1 ของคุณ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">คีย์ที่ป้อนไม่ถูกต้องหรือสั้นเกินไป!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">ลบ %1 ของคุณหรือไม่?</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>ตั้งค่าความหนาของขอบถนน</b><br><br>ค่าเริ่มต้นเท่ากับครึ่งหนึ่งของมาตรฐานความกว้างเส้นแบ่งช่องจราจรของ MUTCD ที่ 10 เซนติเมตร</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">MPC ตามยาว: ปัจจัยอันตราย</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">TORK %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">TEHLİKE FAKTÖRÜ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% of</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Sürüş Kişilikleri</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Havada Geçirilen Süre:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Bir hata oluştu: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Karakterler: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3216,10 +3232,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">%1 girin</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">Girilen anahtar geçersiz veya çok kısa!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">%1 öğenizi kaldırın?</translation>
|
||||
@@ -5023,6 +5035,10 @@ Geliştirici - Tecrübeli meraklılar için yüksek özelleştirilebilir ayarlar
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><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.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Boylamsal MPC: Tehlike Faktörü</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation>МОМЕНТ %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">ФАКТОР НЕБЕЗПЕКИ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% від</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">Стилі водіння</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">Час, проведений у погодних умовах:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">Сталася помилка: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">Символи: 0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3125,10 +3141,6 @@
|
||||
<source>Enter your %1</source>
|
||||
<translation>Введіть ваш %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation>Введений ключ недійсний або занадто короткий!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>REMOVE</source>
|
||||
<translation>ПРИБРАТИ</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation><b>Встановіть товщину краю дороги.</b><br><br>За замовчуванням встановлюється половина стандартної ширини смуги руху MUTCD, яка становить 10 сантиметрів.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">Поздовжній MPC: Фактор небезпеки</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">扭矩 %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">危险因素</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% 的</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">驾驶风格</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">在天气中的时间</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">发生错误:%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">字符:0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">输入你的%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">输入的密钥无效或过短!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">要移除你的%1吗?</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - Highly customizable settings for seasoned enthusiasts</source>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>设置路缘厚度。</b><br><br>默认值等于 MUTCD 车道线宽度标准 10 厘米的一半。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">纵向MPC:危险系数</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
<source>TORQUE %</source>
|
||||
<translation type="gpt-5-generated">扭矩 %</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DANGER FACTOR</source>
|
||||
<translation type="gpt-5-generated">危險因素</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicePanel</name>
|
||||
@@ -966,6 +970,14 @@
|
||||
<source>% of </source>
|
||||
<translation type="gpt-5-generated">% 的</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driving Personalities:</source>
|
||||
<translation type="gpt-5-generated">駕駛風格:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Time Spent in Weather:</source>
|
||||
<translation type="gpt-5-generated">在天氣中的花費時間:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotDevicePanel</name>
|
||||
@@ -2606,6 +2618,10 @@
|
||||
<source>An error occurred: %1</source>
|
||||
<translation type="gpt-5-generated">發生錯誤:%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Characters: 0/%1</source>
|
||||
<translation type="gpt-5-generated">字元:0/%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotManageControl</name>
|
||||
@@ -3217,10 +3233,6 @@ It will reset in %1 hours and %2 minutes.</source>
|
||||
<source>Enter your %1</source>
|
||||
<translation type="gpt-5-generated">輸入您的 %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Inputted key is invalid or too short!</source>
|
||||
<translation type="gpt-5-generated">輸入的金鑰無效或過短!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove your %1?</source>
|
||||
<translation type="gpt-5-generated">要移除您的 %1 嗎?</translation>
|
||||
@@ -5024,6 +5036,10 @@ Developer - 為資深愛好者提供高度自訂的設定</translation>
|
||||
<source><b>Set the road-edge thickness.</b><br><br>Default matches half of the MUTCD lane-line width standard of 10 centimeters.</source>
|
||||
<translation type="gpt-5-generated"><b>設定道路邊緣粗細。</b><br><br>預設值相當於符合 MUTCD 車道線標準 10 公分的一半。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitudinal MPC: Danger Factor</source>
|
||||
<translation type="gpt-5-generated">縱向 MPC:危險因子</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FrogPilotWheelPanel</name>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user