mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-07-11 22:32:07 +08:00
Compare commits
246 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d77743cf6 | |||
| 17f3bc475b | |||
| 749d56ef7d | |||
| 4345f01d17 | |||
| bd4836df14 | |||
| 1eee21622a | |||
| 617805f924 | |||
| 48885b2848 | |||
| 962b29573e | |||
| 33b7513c8d | |||
| c7c2dbb4f2 | |||
| de8cec269a | |||
| b9fd55d17b | |||
| c0f2f232d0 | |||
| fd468531fa | |||
| 4720e7b11a | |||
| 63e4e742e3 | |||
| 12bed4d731 | |||
| a900462ef1 | |||
| 0e2313dc31 | |||
| 79ea7db103 | |||
| f9ae9192fa | |||
| 7ec23006c6 | |||
| 2be9447a6c | |||
| cfd926778e | |||
| a97a67e3d0 | |||
| 518b6de08d | |||
| 6933e3bcdb | |||
| 05e0ca8bee | |||
| 410614fcf3 | |||
| e2bc0996ef | |||
| 1be0c20cf5 | |||
| 839143b9ed | |||
| bce86637ae | |||
| b833d3ee89 | |||
| e0441dfb4b | |||
| 62ec40bba6 | |||
| 15c6d38028 | |||
| 56eb9f555c | |||
| 2f9951df02 | |||
| 6030bf4da3 | |||
| 074694d660 | |||
| df35f48f3b | |||
| 4fb9704540 | |||
| 48cbe266fc | |||
| 21aa7ff367 | |||
| 7caf05dd51 | |||
| 2d779f5db9 | |||
| 18208f1da0 | |||
| 5a3c6ddf57 | |||
| eaa8732ab0 | |||
| 6f0284c84f | |||
| 999ea03f23 | |||
| 0975db3ff1 | |||
| 8d70a8b80a | |||
| da93f92887 | |||
| 9117f6c071 | |||
| 3567ff9691 | |||
| f44ae2ced9 | |||
| 376e0ca615 | |||
| 32b7686468 | |||
| b9e0f52ea9 | |||
| a3163b680f | |||
| 8a927d808f | |||
| bc7d5e474d | |||
| 36f192b5fe | |||
| ffd5cd4ac2 | |||
| e4a00fcd6c | |||
| 0bdcb41103 | |||
| 78051085ca | |||
| 4910d5809a | |||
| 8dd862ff28 | |||
| 1b57497da9 | |||
| 8d8d1ffc7a | |||
| c5919d5495 | |||
| da71951c95 | |||
| 25a152cd8b | |||
| 9077a1082a | |||
| 7ae7000254 | |||
| 7029455706 | |||
| 3a71a62215 | |||
| 00622e8c33 | |||
| 549da3ee92 | |||
| e038a65ef8 | |||
| 8d0513c657 | |||
| 2cea48f4cd | |||
| 8855a9ab65 | |||
| 32321c01cc | |||
| 52cd65fefb | |||
| 1fcdeccd40 | |||
| 3517c36978 | |||
| fb30c3c1e8 | |||
| 1c25e568d5 | |||
| f172122b7c | |||
| 67d6cdc7cd | |||
| 6724085cfd | |||
| 6774f34eee | |||
| 6d0402896d | |||
| 344021a3d9 | |||
| a9b85ab27d | |||
| 17204a46e4 | |||
| 7c4d415462 | |||
| b8985b6d72 | |||
| c669473f88 | |||
| 8751435bf5 | |||
| 30ae210761 | |||
| 3eb693f58b | |||
| 7b4a31c5ac | |||
| 1527c8cf88 | |||
| ab0a7ae666 | |||
| 11ec2f1f21 | |||
| 2c6808d37e | |||
| 2e96382c49 | |||
| 0239e440ca | |||
| 76b972daff | |||
| bc3ef3e7dd | |||
| 9839291dd0 | |||
| 17cba328d6 | |||
| 86093765d8 | |||
| 05fa1c8ae8 | |||
| e8a40d6b85 | |||
| c265e0bb85 | |||
| c6b118788b | |||
| b004f6dbdc | |||
| cd4930b680 | |||
| f861aca628 | |||
| 1ff0d8e2ee | |||
| d76d70764e | |||
| dc73ce0b71 | |||
| 3f666748af | |||
| 8de8a8838c | |||
| f563b7eb71 | |||
| 3c18b83708 | |||
| bd35f5904b | |||
| 474f2737f6 | |||
| ea1ac4a212 | |||
| 165d7c7b36 | |||
| b53cbb2e18 | |||
| b95f8c5929 | |||
| e564bb0b85 | |||
| e2ec8a7b13 | |||
| 75c6f0f10e | |||
| af38044b42 | |||
| 684fa846d8 | |||
| 416e722855 | |||
| 9fd4613bbb | |||
| a0362e3c5f | |||
| e32ef1cdc0 | |||
| 20673ec8a6 | |||
| 53fbdf7329 | |||
| 6f72b74fac | |||
| e83705a32e | |||
| 95d36b9ba2 | |||
| b9e74254bd | |||
| b4405b200d | |||
| a8a3fdac54 | |||
| 4eddc622a7 | |||
| 4e42ada240 | |||
| 6266217655 | |||
| ea09d32e98 | |||
| 15958c88d3 | |||
| b80d7fb5ea | |||
| 1c3d25c6ff | |||
| c9f22b32c7 | |||
| c0524985bb | |||
| 83839c7ea7 | |||
| c1a1d4b4c3 | |||
| b5af7a905a | |||
| 96b1b2f55f | |||
| 9361ba5d70 | |||
| 4e9014311e | |||
| 232873fc70 | |||
| 0a61fca9c9 | |||
| 480bdc34dc | |||
| 716b475a13 | |||
| b1ec5ec034 | |||
| 470613c2b7 | |||
| 336c5b4154 | |||
| abdb9dc750 | |||
| ab98683973 | |||
| 186c24dbe6 | |||
| 9cdf6340a1 | |||
| 2855b1341c | |||
| cf28f99976 | |||
| a39d67dc47 | |||
| 7e75257f12 | |||
| df38449553 | |||
| 1385ef3bc5 | |||
| 7c23c11c51 | |||
| aeff2e12ec | |||
| 7274899671 | |||
| 6c00fd608f | |||
| df6a034c11 | |||
| acb109c290 | |||
| b227b00249 | |||
| 3ec9d6c18a | |||
| 86db8b95f0 | |||
| 4cfff8a35f | |||
| 962fedf48c | |||
| 04494414d1 | |||
| 0b83576e9b | |||
| ce4ef0f817 | |||
| f0b15c1c56 | |||
| f898e9fdfe | |||
| 8ee7804b0e | |||
| 923228194e | |||
| 8837b2e3f6 | |||
| f48c9dc1c2 | |||
| 74aa07a8cd | |||
| 5236e4860f | |||
| 3d174da1c3 | |||
| 8faa40f3a3 | |||
| 3e03275f28 | |||
| 7595cf8a25 | |||
| 2675d43adb | |||
| d9f4ce82e6 | |||
| 648a1845d8 | |||
| a87eff6d1c | |||
| dd6ad37e23 | |||
| c5e778b939 | |||
| a9ab81a77a | |||
| 2d40e1d8e5 | |||
| 7c8f367a5d | |||
| ff4cf558aa | |||
| 0e151e51bc | |||
| 60cc0031b0 | |||
| d24cac0998 | |||
| 45d110830c | |||
| ea3a9ae911 | |||
| 6bff8c0e7c | |||
| bc6b8802b8 | |||
| 252ef572d3 | |||
| 414d397e3f | |||
| 11b7b3789d | |||
| 871ac53717 | |||
| 64ea66b6e6 | |||
| 6d7c6759b3 | |||
| 4cea013570 | |||
| eb375c0587 | |||
| 7fd8a5a4bd | |||
| b3c90216bb | |||
| 10f345f956 | |||
| 956d2c36d0 | |||
| 55e688b6f2 | |||
| f017954027 | |||
| 7e992d11b1 |
@@ -2,5 +2,6 @@ Wen
|
||||
REGIST
|
||||
PullRequest
|
||||
cancelled
|
||||
indeces
|
||||
FOF
|
||||
NoO
|
||||
|
||||
Generated
+7
@@ -21,5 +21,12 @@
|
||||
</clean>
|
||||
</configuration>
|
||||
</target>
|
||||
<target id="f2590b2b-9b93-49f9-8510-da3f3724a2ae" name="replay" defaultType="TOOL">
|
||||
<configuration id="d475264f-6f4c-4092-9b4e-6773309f38b7" name="replay" toolchainName="Default">
|
||||
<build type="TOOL">
|
||||
<tool actionId="Tool_External Tools_uv build tools replay" />
|
||||
</build>
|
||||
</configuration>
|
||||
</target>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+7
@@ -20,4 +20,11 @@
|
||||
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
|
||||
</exec>
|
||||
</tool>
|
||||
<tool name="uv build tools replay" showInMainMenu="false" showInEditor="false" showInProject="false" showInSearchPopup="false" disabled="false" useConsole="true" showConsoleOnStdOut="false" showConsoleOnStdErr="false" synchronizeAfterRun="true">
|
||||
<exec>
|
||||
<option name="COMMAND" value="bash" />
|
||||
<option name="PARAMETERS" value="-c "source .venv/bin/activate && scons -u -j$(nproc) tools/replay/"" />
|
||||
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
|
||||
</exec>
|
||||
</tool>
|
||||
</toolSet>
|
||||
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Build Debug" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$ProjectFileDir$/selfdrive/ui" PASS_PARENT_ENVS_2="true" PROJECT_NAME="sunnypilot" TARGET_NAME="uv Scons Build Debug" CONFIG_NAME="uv Scons Build Debug" RUN_PATH="ui">
|
||||
<configuration default="false" name="Build Debug" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$ProjectFileDir$/selfdrive/ui" PASS_PARENT_ENVS_2="true" PROJECT_NAME="openpilot-special" TARGET_NAME="uv Scons Build Debug" CONFIG_NAME="uv Scons Build Debug" RUN_PATH="ui">
|
||||
<envs>
|
||||
<env name="QT_DBL_CLICK_DIST" value="150" />
|
||||
</envs>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Debug Route Controls" type="PythonConfigurationType" factoryName="Python">
|
||||
<module name="openpilot-special" />
|
||||
<option name="ENV_FILES" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="FINGERPRINT" value="KIA_EV9" />
|
||||
<env name="SKIP_FW_QUERY" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/selfdrive/car" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/selfdrive/car/card.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="true" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Replay for controls + ui" type="Multirun" separateTabs="false" reuseTabsWithFailures="false" startOneByOne="true" markFailedProcess="true" hideSuccessProcess="false" delayTime="0.0">
|
||||
<runConfiguration name="replay for controls" type="Native Application" />
|
||||
<runConfiguration name="Build Debug" type="Custom Build Application" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="replay for controls" type="CLionNativeAppRunConfigurationType" focusToolWindowBeforeRun="true" PROGRAM_PARAMS=""$Prompt$" --block "sendcan,carState,carParams,carOutput,liveTracks,carParamsSP,carStateSP,bookmarkButton"" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="true" WORKING_DIR="file://$ProjectFileDir$/tools/replay" PASS_PARENT_ENVS_2="true" PROJECT_NAME="openpilot-special" TARGET_NAME="replay" CONFIG_NAME="replay" version="1" RUN_PATH="replay">
|
||||
<method v="2">
|
||||
<option name="CLION.COMPOUND.BUILD" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
+1
-25
@@ -1,30 +1,6 @@
|
||||
sunnypilot Version 2025.003.000 (20xx-xx-xx)
|
||||
sunnypilot Version 2025.002.000 (2025-xx-xx)
|
||||
========================
|
||||
|
||||
sunnypilot Version 2025.002.000 (2025-11-06)
|
||||
========================
|
||||
* What's Changed (sunnypilot/sunnypilot)
|
||||
* models: bump model json to v8 by @Discountchubbs
|
||||
* Bug: Model UI Crash Fix by @nayan8teen
|
||||
* controlsd: add `CP_SP` to `get_pid_accel_limits` by @THERoenPR
|
||||
* sunnylink: update uploader button logic to support novice tier and above by @devtekve
|
||||
* Tesla: Coop Steering by @AmyJeanes
|
||||
* ui: update discord references and add forum widget by @devtekve
|
||||
* ui: Fix spacing in sunnylink panel by @devtekve
|
||||
* docs: Update README installation branches and discord links by @mpurnell1 in
|
||||
* stats: sunnylink integration by @devtekve
|
||||
* bug: Fix initial registration for sunnylink by @devtekve
|
||||
* What's Changed (sunnypilot/opendbc)
|
||||
* Honda: add brake hold messages for Clarity by @mvl-boston
|
||||
* interface: add `CP_SP` to `get_pid_accel_limits` method signature by @roenthomas
|
||||
* Honda: use fixed accel min/max constants for Gas Interceptor by @roenthomas
|
||||
* Tesla: Coop Steering by @AmyJeanes
|
||||
* New Contributors (sunnypilot/sunnypilot)
|
||||
* @THERoenPR made their first contribution in "controlsd: add `CP_SP` to `get_pid_accel_limits`"
|
||||
* @AmyJeanes made their first contribution in "Tesla: Coop Steering"
|
||||
* @mpurnell1 made their first contribution in "docs: Update README installation branches and discord links"
|
||||
* Full Changelog: https://github.com/sunnypilot/sunnypilot/compare/v2025.001.000...v2025.002.000
|
||||
|
||||
sunnypilot Version 2025.001.000 (2025-10-25)
|
||||
========================
|
||||
* 🛠️ Major rewrite
|
||||
|
||||
@@ -172,14 +172,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"VisualRadarTracks", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"VisualRadarTracksDelay", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
|
||||
{"VisualWideCam", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"VisualStyle", {PERSISTENT | BACKUP, INT, "0"}},
|
||||
{"VisualStyleZoom", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"VisualStyleOverhead", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"VisualStyleOverheadZoom", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"VisualStyleOverheadThreshold", {PERSISTENT | BACKUP, INT, "20"}},
|
||||
|
||||
// MADS params
|
||||
{"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||
@@ -268,4 +260,11 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
|
||||
{"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
|
||||
|
||||
// Tuning keys
|
||||
{"EnableHkgTuningAngleSmoothingFactor", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||
{"HkgTuningAngleMinTorqueReductionGain", {PERSISTENT | BACKUP, INT, "10"}},
|
||||
{"HkgTuningAngleMaxTorqueReductionGain", {PERSISTENT | BACKUP, INT, "100"}},
|
||||
{"HkgTuningAngleActiveTorqueReductionGain", {PERSISTENT | BACKUP, INT, "100"}},
|
||||
{"HkgTuningOverridingCycles", {PERSISTENT | BACKUP, INT, "17"}},
|
||||
};
|
||||
|
||||
+1
-1
Submodule opendbc_repo updated: c32e79f3c6...98fbb88984
@@ -13,7 +13,7 @@ cd $ROOT
|
||||
|
||||
FAILED=0
|
||||
|
||||
IGNORED_FILES="uv\.lock|docs\/CARS.md|LICENSE\.md"
|
||||
IGNORED_FILES="uv\.lock|docs\/CARS.md|LICENSE\.md|layouts\/.*\.xml|.*\.ipynb"
|
||||
IGNORED_DIRS="^third_party.*|^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*"
|
||||
|
||||
function run() {
|
||||
|
||||
@@ -25,11 +25,6 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
|
||||
// update engageability/experimental mode button
|
||||
experimental_btn->updateState(s);
|
||||
dmon.updateState(s);
|
||||
if (s.scene.visual_style == 0) {
|
||||
setBackgroundColor(bg_colors[STATUS_DISENGAGED]);
|
||||
} else {
|
||||
setBackgroundColor(QColor(0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::initializeGL() {
|
||||
@@ -40,12 +35,7 @@ void AnnotatedCameraWidget::initializeGL() {
|
||||
qInfo() << "OpenGL language version:" << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
prev_draw_t = millis_since_boot();
|
||||
auto *s = uiState();
|
||||
if (s->scene.visual_style == 0) {
|
||||
setBackgroundColor(bg_colors[STATUS_DISENGAGED]);
|
||||
} else {
|
||||
setBackgroundColor(QColor(0, 0, 0));
|
||||
}
|
||||
setBackgroundColor(bg_colors[STATUS_DISENGAGED]);
|
||||
}
|
||||
|
||||
mat4 AnnotatedCameraWidget::calcFrameMatrix() {
|
||||
@@ -128,13 +118,7 @@ void AnnotatedCameraWidget::paintGL() {
|
||||
} else if (v_ego > 15) {
|
||||
wide_cam_requested = false;
|
||||
}
|
||||
if (s->scene.visual_wide_cam == 1) {
|
||||
wide_cam_requested = true;
|
||||
} else if (s->scene.visual_wide_cam == 2) {
|
||||
wide_cam_requested = false;
|
||||
} else {
|
||||
wide_cam_requested = wide_cam_requested && sm["selfdriveState"].getSelfdriveState().getExperimentalMode();
|
||||
}
|
||||
wide_cam_requested = wide_cam_requested && sm["selfdriveState"].getSelfdriveState().getExperimentalMode();
|
||||
}
|
||||
CameraWidget::setStreamType(wide_cam_requested ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD);
|
||||
CameraWidget::setFrameId(sm["modelV2"].getModelV2().getFrameId());
|
||||
|
||||
+16
-241
@@ -1,5 +1,4 @@
|
||||
#include "selfdrive/ui/qt/onroad/model.h"
|
||||
#include <algorithm>
|
||||
|
||||
void ModelRenderer::draw(QPainter &painter, const QRect &surface_rect) {
|
||||
auto *s = uiState();
|
||||
@@ -50,14 +49,8 @@ void ModelRenderer::update_leads(const cereal::RadarState::Reader &radar_state,
|
||||
}
|
||||
|
||||
void ModelRenderer::update_model(const cereal::ModelDataV2::Reader &model, const cereal::RadarState::LeadData::Reader &lead) {
|
||||
auto *s = uiState();
|
||||
const auto &model_position = model.getPosition();
|
||||
float max_distance;
|
||||
if (s->scene.visual_style == 0) {
|
||||
max_distance = std::clamp(*(model_position.getX().end() - 1), MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE);
|
||||
} else {
|
||||
max_distance = std::clamp(*(model_position.getX().end() - 1), MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE);
|
||||
}
|
||||
float max_distance = std::clamp(*(model_position.getX().end() - 1), MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE);
|
||||
|
||||
// update lane lines
|
||||
const auto &lane_lines = model.getLaneLines();
|
||||
@@ -65,11 +58,7 @@ void ModelRenderer::update_model(const cereal::ModelDataV2::Reader &model, const
|
||||
int max_idx = get_path_length_idx(lane_lines[0], max_distance);
|
||||
for (int i = 0; i < std::size(lane_line_vertices); i++) {
|
||||
lane_line_probs[i] = line_probs[i];
|
||||
if (s->scene.visual_style == 2) {
|
||||
mapLineToPolygon(lane_lines[i], 0.075 * lane_line_probs[i], 0, &lane_line_vertices[i], max_idx);
|
||||
} else {
|
||||
mapLineToPolygon(lane_lines[i], 0.025 * lane_line_probs[i], 0, &lane_line_vertices[i], max_idx);
|
||||
}
|
||||
mapLineToPolygon(lane_lines[i], 0.025 * lane_line_probs[i], 0, &lane_line_vertices[i], max_idx);
|
||||
}
|
||||
|
||||
// update road edges
|
||||
@@ -77,11 +66,7 @@ void ModelRenderer::update_model(const cereal::ModelDataV2::Reader &model, const
|
||||
const auto &edge_stds = model.getRoadEdgeStds();
|
||||
for (int i = 0; i < std::size(road_edge_vertices); i++) {
|
||||
road_edge_stds[i] = edge_stds[i];
|
||||
if (s->scene.visual_style == 2) {
|
||||
mapLineToPolygon(road_edges[i], 0.1, 0, &road_edge_vertices[i], max_idx);
|
||||
} else {
|
||||
mapLineToPolygon(road_edges[i], 0.025, 0, &road_edge_vertices[i], max_idx);
|
||||
}
|
||||
mapLineToPolygon(road_edges[i], 0.025, 0, &road_edge_vertices[i], max_idx);
|
||||
}
|
||||
|
||||
// update path
|
||||
@@ -94,112 +79,16 @@ void ModelRenderer::update_model(const cereal::ModelDataV2::Reader &model, const
|
||||
}
|
||||
|
||||
void ModelRenderer::drawLaneLines(QPainter &painter) {
|
||||
auto *s = uiState();
|
||||
if (s->scene.visual_style == 2) {
|
||||
QRectF r = clip_region;
|
||||
// lanelines
|
||||
for (int i = 0; i < std::size(lane_line_vertices); ++i) {
|
||||
painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp<float>(lane_line_probs[i], 0.0, 0.7)));
|
||||
painter.drawPolygon(lane_line_vertices[i]);
|
||||
}
|
||||
|
||||
qreal horizonY = r.bottom();
|
||||
if (!road_edge_vertices[0].isEmpty() || !road_edge_vertices[1].isEmpty()) {
|
||||
qreal leftH = r.top();
|
||||
qreal rightH = r.top();
|
||||
|
||||
if (!road_edge_vertices[0].isEmpty()) {
|
||||
leftH = std::numeric_limits<qreal>::max();
|
||||
for (const QPointF &pt : road_edge_vertices[0]) {
|
||||
if (pt.y() < leftH) leftH = pt.y();
|
||||
}
|
||||
}
|
||||
|
||||
if (!road_edge_vertices[1].isEmpty()) {
|
||||
rightH = std::numeric_limits<qreal>::max();
|
||||
for (const QPointF &pt : road_edge_vertices[1]) {
|
||||
if (pt.y() < rightH) rightH = pt.y();
|
||||
}
|
||||
}
|
||||
|
||||
horizonY = std::max(leftH, rightH);
|
||||
}
|
||||
|
||||
painter.fillRect(QRectF(r.left(), horizonY + 0, r.width(), r.bottom() - (horizonY + 0)), QColor("#111111"));
|
||||
|
||||
auto buildFill = [&](const QPolygonF &edgeRibbon, bool isLeftSide) -> QPolygonF {
|
||||
if (edgeRibbon.isEmpty()) return {};
|
||||
|
||||
QMap<int, QPointF> byY;
|
||||
for (const QPointF &pt : edgeRibbon) {
|
||||
int yi = int(std::round(pt.y()));
|
||||
if (!byY.contains(yi)) {
|
||||
byY[yi] = pt;
|
||||
} else {
|
||||
if (isLeftSide) {
|
||||
if (pt.x() > byY[yi].x()) byY[yi] = pt;
|
||||
} else {
|
||||
if (pt.x() < byY[yi].x()) byY[yi] = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (byY.isEmpty()) return {};
|
||||
|
||||
QPolygonF curve;
|
||||
for (auto it = byY.cbegin(); it != byY.cend(); ++it) {
|
||||
curve << it.value();
|
||||
}
|
||||
if (curve.size() < 2) return {};
|
||||
|
||||
const qreal topY = curve.first().y();
|
||||
QPolygonF fill;
|
||||
if (isLeftSide) {
|
||||
fill << QPointF(r.left(), topY);
|
||||
for (const QPointF &pt : curve) fill << pt;
|
||||
fill << QPointF(r.left(), r.bottom());
|
||||
} else {
|
||||
fill << QPointF(r.right(), topY);
|
||||
for (const QPointF &pt : curve) fill << pt;
|
||||
fill << QPointF(r.right(), r.bottom());
|
||||
}
|
||||
return fill;
|
||||
};
|
||||
|
||||
QPolygonF leftFill = buildFill(road_edge_vertices[0], true);
|
||||
QPolygonF rightFill = buildFill(road_edge_vertices[1], false);
|
||||
|
||||
if (!leftFill.isEmpty()) {
|
||||
painter.setBrush(QColor("#222222"));
|
||||
painter.drawPolygon(leftFill);
|
||||
}
|
||||
if (!rightFill.isEmpty()) {
|
||||
painter.setBrush(QColor("#222222"));
|
||||
painter.drawPolygon(rightFill);
|
||||
}
|
||||
|
||||
for (int i = 0; i < std::size(lane_line_vertices); ++i) {
|
||||
painter.setBrush(QColor::fromRgbF(0.902, 0.902, 0.902, std::clamp<float>(lane_line_probs[i], 0.0, 0.7)));
|
||||
painter.drawPolygon(lane_line_vertices[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < std::size(road_edge_vertices); ++i) {
|
||||
painter.setBrush(QColor(0x55, 0x55, 0x55, 255));
|
||||
painter.drawPolygon(road_edge_vertices[i]);
|
||||
}
|
||||
|
||||
QLinearGradient bgGrad(r.left(), horizonY - 100, r.left(), horizonY + 100);
|
||||
bgGrad.setColorAt(0.0, QColor("#000000"));
|
||||
bgGrad.setColorAt(0.5, QColor("#111111"));
|
||||
bgGrad.setColorAt(1.0, QColor("#111111"));
|
||||
painter.fillRect(QRectF(r.left(), horizonY - 200, r.width(), 200), bgGrad);
|
||||
|
||||
} else {
|
||||
// lanelines
|
||||
for (int i = 0; i < std::size(lane_line_vertices); ++i) {
|
||||
painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp<float>(lane_line_probs[i], 0.0, 0.7)));
|
||||
painter.drawPolygon(lane_line_vertices[i]);
|
||||
}
|
||||
|
||||
// road edges
|
||||
for (int i = 0; i < std::size(road_edge_vertices); ++i) {
|
||||
painter.setBrush(QColor::fromRgbF(1.0, 0, 0, std::clamp<float>(1.0 - road_edge_stds[i], 0.0, 1.0)));
|
||||
painter.drawPolygon(road_edge_vertices[i]);
|
||||
}
|
||||
// road edges
|
||||
for (int i = 0; i < std::size(road_edge_vertices); ++i) {
|
||||
painter.setBrush(QColor::fromRgbF(1.0, 0, 0, std::clamp<float>(1.0 - road_edge_stds[i], 0.0, 1.0)));
|
||||
painter.drawPolygon(road_edge_vertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +175,6 @@ QColor ModelRenderer::blendColors(const QColor &start, const QColor &end, float
|
||||
|
||||
void ModelRenderer::drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data,
|
||||
const QPointF &vd, const QRect &surface_rect) {
|
||||
auto *s = uiState();
|
||||
const float speedBuff = 10.;
|
||||
const float leadBuff = 40.;
|
||||
const float d_rel = lead_data.getDRel();
|
||||
@@ -309,133 +197,20 @@ void ModelRenderer::drawLead(QPainter &painter, const cereal::RadarState::LeadDa
|
||||
float g_yo = sz / 10;
|
||||
|
||||
QPointF glow[] = {{x + (sz * 1.35) + g_xo, y + sz + g_yo}, {x, y - g_yo}, {x - (sz * 1.35) - g_xo, y + sz + g_yo}};
|
||||
if (s->scene.visual_style == 2) {
|
||||
painter.setBrush(QColor(0xE6, 0xE6, 0xE6, 255));
|
||||
} else {
|
||||
painter.setBrush(QColor(218, 202, 37, 255));
|
||||
}
|
||||
painter.setBrush(QColor(218, 202, 37, 255));
|
||||
painter.drawPolygon(glow, std::size(glow));
|
||||
|
||||
// chevron
|
||||
QPointF chevron[] = {{x + (sz * 1.25), y + sz}, {x, y}, {x - (sz * 1.25), y + sz}};
|
||||
if (s->scene.visual_style == 2) {
|
||||
painter.setBrush(QColor(0, 0, 0, fillAlpha));
|
||||
} else {
|
||||
painter.setBrush(QColor(201, 34, 49, fillAlpha));
|
||||
}
|
||||
painter.setBrush(QColor(201, 34, 49, fillAlpha));
|
||||
painter.drawPolygon(chevron, std::size(chevron));
|
||||
}
|
||||
|
||||
float mapRange(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||
if (in_min < in_max) {
|
||||
x = std::clamp(x, in_min, in_max);
|
||||
} else {
|
||||
x = std::clamp(x, in_max, in_min);
|
||||
}
|
||||
return out_min + (x - in_min) * (out_max - out_min) / (in_max - in_min);
|
||||
}
|
||||
|
||||
// Projects a point in car space to the corresponding point in full frame image space.
|
||||
// Projects a point in car to space to the corresponding point in full frame image space.
|
||||
bool ModelRenderer::mapToScreen(float in_x, float in_y, float in_z, QPointF *out) {
|
||||
auto *s = uiState();
|
||||
auto &sm = *(s->sm);
|
||||
float blend_speed_mph = fabsf(sm["carState"].getCarState().getVEgo() * 2.23694f);
|
||||
|
||||
Eigen::Vector3f input(in_x, in_y, in_z);
|
||||
|
||||
if ((s->scene.visual_style_zoom == 1 || s->scene.visual_style_zoom == 2) && s->scene.visual_style != 0) {
|
||||
float zoom_start = 20.0f;
|
||||
float zoom_end = 50.0f;
|
||||
|
||||
if (s->scene.visual_style_zoom == 2) {
|
||||
std::swap(zoom_start, zoom_end);
|
||||
}
|
||||
|
||||
float IN_X_OFFSET = mapRange(blend_speed_mph, zoom_start, zoom_end, 0.0f, 24.0f);
|
||||
float IN_Y_OFFSET = mapRange(blend_speed_mph, zoom_start, zoom_end, 1.0f, 2.0f);
|
||||
float IN_Z_OFFSET = mapRange(blend_speed_mph, zoom_start, zoom_end, 0.0f, 5.0f);
|
||||
float PITCH_DEG = mapRange(blend_speed_mph, zoom_start, zoom_end, 0.0f, 5.0f);
|
||||
|
||||
input = Eigen::Vector3f(in_x + IN_X_OFFSET, in_y / IN_Y_OFFSET, in_z + IN_Z_OFFSET);
|
||||
Eigen::AngleAxisf pitch_rot(PITCH_DEG * M_PI / 180.0f, Eigen::Vector3f::UnitY());
|
||||
input = pitch_rot * input;
|
||||
}
|
||||
|
||||
auto pt = car_space_transform * input;
|
||||
bool normal_valid = (pt.z() > 1e-3f &&
|
||||
std::isfinite(pt.x()) && std::isfinite(pt.y()));
|
||||
QPointF normal_view;
|
||||
if (normal_valid) {
|
||||
normal_view = QPointF(pt.x() / pt.z(), pt.y() / pt.z());
|
||||
}
|
||||
|
||||
const float base_scale_x = 20.0f;
|
||||
const float base_scale_y = 15.0f;
|
||||
const float y_offset = 450.0f;
|
||||
|
||||
float factor_scale_x = 0.0f;
|
||||
if (blend_speed_mph > 0.0f) {
|
||||
if (s->scene.visual_style_overhead_zoom == 1) {
|
||||
factor_scale_x = mapRange(blend_speed_mph, 0.0f, 50.0f, 30.0f, 0.0f);
|
||||
} else if (s->scene.visual_style_overhead_zoom == 2) {
|
||||
factor_scale_x = mapRange(blend_speed_mph, 50.0f, 0.0f, 30.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
float scale_x = base_scale_x + factor_scale_x;
|
||||
float scale_y = base_scale_y;
|
||||
|
||||
QPointF topdown_view(
|
||||
clip_region.center().x() + in_y * scale_x,
|
||||
(clip_region.bottom() - y_offset) - in_x * scale_y
|
||||
);
|
||||
|
||||
if ((s->scene.visual_style_overhead == 1 || s->scene.visual_style_overhead == 2) && s->scene.visual_style != 0) {
|
||||
static float blend = 0.0f;
|
||||
static float target_blend = 0.0f;
|
||||
static double last_t = millis_since_boot();
|
||||
|
||||
const bool inverted = (s->scene.visual_style_overhead == 2);
|
||||
const float threshold = s->scene.visual_style_overhead_threshold;
|
||||
const float hysteresis = 5.0f;
|
||||
|
||||
if (!inverted) {
|
||||
if (target_blend < 0.5f && blend_speed_mph > threshold) {
|
||||
target_blend = 1.0f;
|
||||
} else if (target_blend > 0.5f && blend_speed_mph < threshold - hysteresis) {
|
||||
target_blend = 0.0f;
|
||||
}
|
||||
} else {
|
||||
if (target_blend < 0.5f && blend_speed_mph < threshold) {
|
||||
target_blend = 1.0f;
|
||||
} else if (target_blend > 0.5f && blend_speed_mph > threshold + hysteresis) {
|
||||
target_blend = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
double now = millis_since_boot();
|
||||
double dt = (now - last_t) / 1000.0;
|
||||
last_t = now;
|
||||
|
||||
const float transition_time = 1.50f;
|
||||
float step = dt / transition_time;
|
||||
|
||||
if (blend < target_blend) {
|
||||
blend = std::min(blend + step, target_blend);
|
||||
} else if (blend > target_blend) {
|
||||
blend = std::max(blend - step, target_blend);
|
||||
}
|
||||
|
||||
if (!normal_valid) return false;
|
||||
*out = QPointF(
|
||||
(1 - blend) * normal_view.x() + blend * topdown_view.x(),
|
||||
(1 - blend) * normal_view.y() + blend * topdown_view.y()
|
||||
);
|
||||
} else {
|
||||
if (!normal_valid) return false;
|
||||
*out = normal_view;
|
||||
}
|
||||
|
||||
*out = QPointF(pt.x() / pt.z(), pt.y() / pt.z());
|
||||
return clip_region.contains(*out);
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,6 @@ mat4 CameraWidget::calcFrameMatrix() {
|
||||
}
|
||||
|
||||
void CameraWidget::paintGL() {
|
||||
auto *s = uiState();
|
||||
glClearColor(bg.redF(), bg.greenF(), bg.blueF(), bg.alphaF());
|
||||
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
@@ -249,9 +248,7 @@ void CameraWidget::paintGL() {
|
||||
|
||||
glUniformMatrix4fv(program->uniformLocation("uTransform"), 1, GL_TRUE, frame_mat.v);
|
||||
glEnableVertexAttribArray(0);
|
||||
if (s->scene.visual_style == 0) {
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (const void *)0);
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (const void *)0);
|
||||
glDisableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
@@ -52,6 +52,7 @@ lateral_panel_qt_src = [
|
||||
"sunnypilot/qt/offroad/settings/lateral/blinker_pause_lateral_settings.cc",
|
||||
"sunnypilot/qt/offroad/settings/lateral/lane_change_settings.cc",
|
||||
"sunnypilot/qt/offroad/settings/lateral/mads_settings.cc",
|
||||
"sunnypilot/qt/offroad/settings/lateral/angle_tuning_settings.cc",
|
||||
"sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.cc",
|
||||
"sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.cc",
|
||||
"sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.cc",
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
*
|
||||
* This file is part of sunnypilot and is licensed under the MIT License.
|
||||
* See the LICENSE.md file in the root directory for more details.
|
||||
*/
|
||||
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/angle_tuning_settings.h"
|
||||
|
||||
#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h"
|
||||
|
||||
AngleTunningSettings::AngleTunningSettings(QWidget *parent) : QWidget(parent) {
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
main_layout->setContentsMargins(50, 20, 50, 20);
|
||||
main_layout->setSpacing(20);
|
||||
|
||||
// Back button
|
||||
PanelBackButton *back = new PanelBackButton();
|
||||
connect(back, &QPushButton::clicked, [=]() { emit backPress(); });
|
||||
main_layout->addWidget(back, 0, Qt::AlignLeft);
|
||||
|
||||
auto *list = new ListWidgetSP(this, false);
|
||||
|
||||
main_layout->addWidget(new QWidget());
|
||||
|
||||
enableHkgAngleSmoothingFactor = new ExpandableToggleRow("EnableHkgTuningAngleSmoothingFactor", tr("HKG Angle Smoothing Factor"), tr("Applies EMA (Exponential Moving Average) to the desired angle steering and avoid overcorrections."), "../assets/offroad/icon_blank.png");
|
||||
list->addItem(enableHkgAngleSmoothingFactor);
|
||||
|
||||
auto first_row = new QHBoxLayout();
|
||||
hkgTuningOverridingCycles = new OptionControlSP("HkgTuningOverridingCycles", tr("Override Ramp-Down Cycles"), tr("Number of cycles to ramp down the current amount of torque on the steering wheel.<br/>A smaller value means a faster override by the user (less effort)"), "../assets/offroad/icon_blank.png", {10, 30}, 1);
|
||||
connect(hkgTuningOverridingCycles, &OptionControlSP::updateLabels, hkgTuningOverridingCycles, [=]() {
|
||||
this->updateToggles(offroad);
|
||||
});
|
||||
first_row->addWidget(hkgTuningOverridingCycles);
|
||||
|
||||
hkgAngleMinTorque = new OptionControlSP("HkgTuningAngleMinTorqueReductionGain", tr("Override Steering Effort"), tr("Sets the steering effort percentage used when the driver is overriding lateral control.<br/>Higher values increase resistance and make the wheel feel stiffer."), "../assets/offroad/icon_blank.png", {5, 60}, 1);
|
||||
connect(hkgAngleMinTorque, &OptionControlSP::updateLabels, hkgAngleMinTorque, [=]() {
|
||||
this->updateToggles(offroad);
|
||||
});
|
||||
first_row->addWidget(hkgAngleMinTorque);
|
||||
list->addItem(first_row);
|
||||
|
||||
auto second_row = new QHBoxLayout();
|
||||
hkgAngleActiveTorque = new OptionControlSP("HkgTuningAngleActiveTorqueReductionGain", tr("Min Active Torque"), tr("Torque applied when lateral control is active but the vehicle is not turning.<br/>Used to maintain lane centering on straight paths when no user input is detected."), "../assets/offroad/icon_blank.png", {10, 100}, 1);
|
||||
connect(hkgAngleActiveTorque, &OptionControlSP::updateLabels, hkgAngleActiveTorque, [=]() {
|
||||
this->updateToggles(offroad);
|
||||
});
|
||||
second_row->addWidget(hkgAngleActiveTorque);
|
||||
|
||||
hkgAngleMaxTorque = new OptionControlSP("HkgTuningAngleMaxTorqueReductionGain", tr("Max Torque Allowance"), tr("Sets the maximum torque reduction percentage the controller can apply during normal lateral control.<br/>"), "../assets/offroad/icon_blank.png", {10, 100}, 1);
|
||||
connect(hkgAngleMaxTorque, &OptionControlSP::updateLabels, hkgAngleMaxTorque, [=]() {
|
||||
this->updateToggles(offroad);
|
||||
});
|
||||
second_row->addWidget(hkgAngleMaxTorque);
|
||||
list->addItem(second_row);
|
||||
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, this, &AngleTunningSettings::updateToggles);
|
||||
|
||||
main_layout->addWidget(new ScrollViewSP(list, this));
|
||||
|
||||
auto *warning = new QLabel(tr("Reboot required for settings to apply; Tap on each setting to see more details."));
|
||||
warning->setStyleSheet("font-size: 30px; font-weight: 500; font-family: 'Noto Color Emoji'; color: orange;");
|
||||
main_layout->addWidget(warning, 0, Qt::AlignCenter);
|
||||
}
|
||||
|
||||
void AngleTunningSettings::showEvent(QShowEvent *event) {
|
||||
updateToggles(offroad);
|
||||
}
|
||||
|
||||
void AngleTunningSettings::updateToggles(bool _offroad) {
|
||||
auto HkgAngleSmoothingFactorValue = params.getBool("EnableHkgTuningAngleSmoothingFactor");
|
||||
enableHkgAngleSmoothingFactor->toggleFlipped(HkgAngleSmoothingFactorValue);
|
||||
|
||||
auto HkgAngleMinTorqueValue = QString::fromStdString(params.get("HkgTuningAngleMinTorqueReductionGain")).toInt();
|
||||
hkgAngleMinTorque->setLabel(QString::number(HkgAngleMinTorqueValue)+"%");
|
||||
|
||||
auto HkgAngleActiveTorqueValue = QString::fromStdString(params.get("HkgTuningAngleActiveTorqueReductionGain")).toInt();
|
||||
hkgAngleActiveTorque->setLabel(QString::number(HkgAngleActiveTorqueValue)+"%");
|
||||
|
||||
auto HkgAngleMaxTorqueValue = QString::fromStdString(params.get("HkgTuningAngleMaxTorqueReductionGain")).toInt();
|
||||
hkgAngleMaxTorque->setLabel(QString::number(HkgAngleMaxTorqueValue)+"%");
|
||||
|
||||
auto HkgTuningOverridingCyclesValue = QString::fromStdString(params.get("HkgTuningOverridingCycles")).toInt();
|
||||
hkgTuningOverridingCycles->setLabel(QString::number(HkgTuningOverridingCyclesValue));
|
||||
|
||||
offroad = _offroad;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
*
|
||||
* This file is part of sunnypilot and is licensed under the MIT License.
|
||||
* See the LICENSE.md file in the root directory for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
#include "selfdrive/ui/sunnypilot/ui.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/widgets/expandable_row.h"
|
||||
|
||||
class AngleTunningSettings : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AngleTunningSettings(QWidget *parent = nullptr);
|
||||
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
signals:
|
||||
void backPress();
|
||||
|
||||
public slots:
|
||||
void updateToggles(bool _offroad);
|
||||
|
||||
private:
|
||||
Params params;
|
||||
bool offroad;
|
||||
|
||||
ExpandableToggleRow* enableHkgAngleSmoothingFactor;
|
||||
OptionControlSP* hkgAngleMinTorque;
|
||||
OptionControlSP* hkgAngleActiveTorque;
|
||||
OptionControlSP* hkgAngleMaxTorque;
|
||||
OptionControlSP* hkgTuningOverridingCycles;
|
||||
};
|
||||
@@ -120,6 +120,36 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) {
|
||||
updateToggles(offroad);
|
||||
});
|
||||
|
||||
#pragma region hkg angle tuning
|
||||
list->addItem(vertical_space());
|
||||
list->addItem(horizontal_line());
|
||||
list->addItem(vertical_space());
|
||||
|
||||
// HKG Angle Tuning
|
||||
// angleTuningToggle = new ParamControl(
|
||||
// "AngleTuning",
|
||||
// tr("Modular Assistive Driving System (MADS)"),
|
||||
// tr("Enable the beloved MADS feature. Disable toggle to revert back to stock sunnypilot engagement/disengagement."),
|
||||
// "");
|
||||
// angleTuningToggle->setConfirmation(true, false);
|
||||
// list->addItem(angleTuningToggle);
|
||||
|
||||
angleTuningSettingsButton = new PushButtonSP(tr("Customize ANGLE Tuning"));
|
||||
angleTuningSettingsButton->setObjectName("angle_btn");
|
||||
connect(angleTuningSettingsButton, &QPushButton::clicked, [=]() {
|
||||
sunnypilotScroller->setLastScrollPosition();
|
||||
main_layout->setCurrentWidget(angleTuningWidget);
|
||||
});
|
||||
// QObject::connect(angleTuningToggle, &ToggleControl::toggleFlipped, angleTuningSettingsButton, &PushButtonSP::setEnabled);
|
||||
|
||||
angleTuningWidget = new AngleTunningSettings(this);
|
||||
connect(angleTuningWidget, &AngleTunningSettings::backPress, [=]() {
|
||||
sunnypilotScroller->restoreScrollPosition();
|
||||
main_layout->setCurrentWidget(sunnypilotScreen);
|
||||
});
|
||||
list->addItem(angleTuningSettingsButton);
|
||||
#pragma endregion
|
||||
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, this, &LateralPanel::updateToggles);
|
||||
|
||||
sunnypilotScroller = new ScrollViewSP(list, this);
|
||||
@@ -127,6 +157,7 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) {
|
||||
|
||||
main_layout->addWidget(sunnypilotScreen);
|
||||
main_layout->addWidget(madsWidget);
|
||||
main_layout->addWidget(angleTuningWidget);
|
||||
main_layout->addWidget(laneChangeWidget);
|
||||
main_layout->addWidget(torqueLateralControlWidget);
|
||||
|
||||
@@ -188,6 +219,7 @@ void LateralPanel::updateToggles(bool _offroad) {
|
||||
|
||||
madsToggle->setEnabled(_offroad);
|
||||
madsSettingsButton->setEnabled(madsToggle->isToggled());
|
||||
// angleTuningSettingsButton->setEnabled(angleTuningToggle->isToggled());
|
||||
|
||||
torqueLateralControlToggle->setEnabled(_offroad && torque_allowed && !nnlcToggle->isToggled());
|
||||
torqueLateralControlSettingsButton->setEnabled(torqueLateralControlToggle->isToggled());
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "selfdrive/ui/sunnypilot/ui.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/blinker_pause_lateral_settings.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/angle_tuning_settings.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/lane_change_settings.h"
|
||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h"
|
||||
@@ -39,8 +40,11 @@ private:
|
||||
bool offroad;
|
||||
|
||||
ParamControl *madsToggle;
|
||||
// ParamControl *angleTuningToggle;
|
||||
PushButtonSP *madsSettingsButton;
|
||||
PushButtonSP *angleTuningSettingsButton;
|
||||
MadsSettings *madsWidget = nullptr;
|
||||
AngleTunningSettings *angleTuningWidget = nullptr;
|
||||
PushButtonSP *laneChangeSettingsButton;
|
||||
LaneChangeSettings *laneChangeWidget = nullptr;
|
||||
NeuralNetworkLateralControl *nnlcToggle = nullptr;
|
||||
|
||||
@@ -188,7 +188,6 @@ void LongitudinalPanel::refresh(bool _offroad) {
|
||||
customAccIncrement->setDescription(accEnabledDescription);
|
||||
}
|
||||
} else {
|
||||
customAccIncrement->toggleFlipped(false);
|
||||
customAccIncrement->setDescription(accNoLongDescription);
|
||||
customAccIncrement->showDescription();
|
||||
}
|
||||
|
||||
@@ -11,18 +11,6 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) {
|
||||
param_watcher = new ParamWatcher(this);
|
||||
connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) {
|
||||
paramsRefresh();
|
||||
if (param_name == "VisualStyle") {
|
||||
visual_style_value = param_value.toInt();
|
||||
} else if (param_name == "VisualStyleOverhead") {
|
||||
visual_style_overhead_value = param_value.toInt();
|
||||
} else if (param_name == "VisualRadarTracks") {
|
||||
bool radar_tracks_enabled = param_value.toInt() != 0;
|
||||
visual_radar_tracks_delay_settings->setVisible(radar_tracks_enabled);
|
||||
}
|
||||
visual_style_zoom_settings->setVisible(visual_style_value != 0);
|
||||
visual_style_overhead_settings->setVisible(visual_style_value != 0);
|
||||
visual_style_overhead_zoom_settings->setVisible(visual_style_value != 0 && visual_style_overhead_value != 0);
|
||||
visual_style_overhead_threshold_settings->setVisible(visual_style_value != 0 && visual_style_overhead_value != 0);
|
||||
});
|
||||
|
||||
main_layout = new QStackedLayout(this);
|
||||
@@ -102,13 +90,6 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) {
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"VisualRadarTracks",
|
||||
tr("Show Radar Tracks"),
|
||||
tr("Shows what the cars radar sees."),
|
||||
"",
|
||||
false,
|
||||
},
|
||||
};
|
||||
|
||||
// Add regular toggles first
|
||||
@@ -135,111 +116,6 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) {
|
||||
param_watcher->addParam(param);
|
||||
}
|
||||
|
||||
// Visuals: Radar Tracks Delay
|
||||
visual_radar_tracks_delay_settings = new OptionControlSP("VisualRadarTracksDelay", tr("Adjust Visual Radar Tracks Delay"),
|
||||
tr("Delays radar tracks to better match what you see through the camera."),
|
||||
"", {0, 100}, 10, false, nullptr, true);
|
||||
|
||||
connect(visual_radar_tracks_delay_settings, &OptionControlSP::updateLabels, [=]() {
|
||||
float radar_tracks_delay_value = QString::fromStdString(params.get("VisualRadarTracksDelay")).toFloat();
|
||||
visual_radar_tracks_delay_settings->setLabel(QString::number(radar_tracks_delay_value, 'f', 1) + " s");
|
||||
});
|
||||
|
||||
float radar_tracks_delay_value = QString::fromStdString(params.get("VisualRadarTracksDelay")).toFloat();
|
||||
visual_radar_tracks_delay_settings->setLabel(QString::number(radar_tracks_delay_value, 'f', 1) + " s");
|
||||
|
||||
list->addItem(visual_radar_tracks_delay_settings);
|
||||
|
||||
// Wide Cam
|
||||
std::vector<QString> visual_wide_cam_settings_texts{tr("Auto"), tr("On"), tr("Off")};
|
||||
visual_wide_cam_settings = new ButtonParamControlSP(
|
||||
"VisualWideCam", tr("Wide Cam"), tr("Override the wide cam view regardless of experimental mode status."),
|
||||
"",
|
||||
visual_wide_cam_settings_texts,
|
||||
250);
|
||||
list->addItem(visual_wide_cam_settings);
|
||||
|
||||
// Visual Style
|
||||
std::vector<QString> visual_style_settings_texts{tr("Default"), tr("Minimal"), tr("Vision")};
|
||||
visual_style_settings = new ButtonParamControlSP(
|
||||
"VisualStyle", tr("Visual Style"),
|
||||
tr(
|
||||
"Switch between different on-road visualization layouts."
|
||||
"<ul style='margin-left: 10px; margin-top: 4px;'>"
|
||||
"<li><b>Default:</b> Standard OpenPilot layout with camera and path view.</li>"
|
||||
"<li><b>Minimal:</b> Clean interface without camera feed or extra elements.</li>"
|
||||
"<li><b>Vision:</b> Experimental layout that focuses on model perception and environment.</li>"
|
||||
"</ul>"
|
||||
),
|
||||
"",
|
||||
visual_style_settings_texts,
|
||||
380);
|
||||
list->addItem(visual_style_settings);
|
||||
|
||||
// Visual Style Zoom
|
||||
std::vector<QString> visual_style_zoom_settings_texts{tr("Disabled"), tr("Enabled"), tr("Inverted")};
|
||||
visual_style_zoom_settings = new ButtonParamControlSP(
|
||||
"VisualStyleZoom", tr("Visual Style Zoom"),
|
||||
tr(
|
||||
"Enables dynamic zooming based on driving speed in the selected visual style."
|
||||
"<ul style='margin-left: 10px; margin-top: 4px;'>"
|
||||
"<li><b>Disabled:</b> Keeps the zoom fixed.</li>"
|
||||
"<li><b>Enabled:</b> Zooms in at low speed and out at high speed.</li>"
|
||||
"<li><b>Inverted:</b> Reverses the zoom behavior.</li>"
|
||||
"</ul>"
|
||||
),
|
||||
"",
|
||||
visual_style_zoom_settings_texts,
|
||||
380);
|
||||
list->addItem(visual_style_zoom_settings);
|
||||
|
||||
// Visual Style Overhead
|
||||
std::vector<QString> visual_style_overhead_settings_texts{tr("Disabled"), tr("Enabled"), tr("Inverted")};
|
||||
visual_style_overhead_settings = new ButtonParamControlSP(
|
||||
"VisualStyleOverhead", tr("Visual Style Overhead"),
|
||||
tr(
|
||||
"Toggles an overhead (top-down) camera view for a 2D-style perspective."
|
||||
"<ul style='margin-left: 10px; margin-top: 4px;'>"
|
||||
"<li><b>Disabled:</b> Keeps the standard forward 3D view.</li>"
|
||||
"<li><b>Enabled:</b> Switches to overhead view when active.</li>"
|
||||
"<li><b>Inverted:</b> Reverses when the transition happens.</li>"
|
||||
"</ul>"
|
||||
),
|
||||
"",
|
||||
visual_style_overhead_settings_texts,
|
||||
380);
|
||||
list->addItem(visual_style_overhead_settings);
|
||||
|
||||
// Visual Style Overhead Zoom
|
||||
std::vector<QString> visual_style_overhead_zoom_settings_texts{tr("Disabled"), tr("Enabled"), tr("Inverted")};
|
||||
visual_style_overhead_zoom_settings = new ButtonParamControlSP(
|
||||
"VisualStyleOverheadZoom", tr("Visual Style Overhead Zoom"),
|
||||
tr(
|
||||
"Controls zooming behavior while in overhead mode."
|
||||
"<ul style='margin-left: 10px; margin-top: 4px;'>"
|
||||
"<li><b>Disabled:</b> Keeps a fixed zoom level in overhead mode.</li>"
|
||||
"<li><b>Enabled:</b> Zooms dynamically based on speed while overhead.</li>"
|
||||
"<li><b>Inverted:</b> Opposite zoom direction.</li>"
|
||||
"</ul>"
|
||||
),
|
||||
"",
|
||||
visual_style_overhead_zoom_settings_texts,
|
||||
380);
|
||||
list->addItem(visual_style_overhead_zoom_settings);
|
||||
|
||||
// Visual Style Overhead Threshold
|
||||
visual_style_overhead_threshold_settings = new OptionControlSP(
|
||||
"VisualStyleOverheadThreshold", tr("Visual Style Overhead Threshold"),
|
||||
tr("Sets the speed (in mph) where the display transitions between normal and overhead view."),
|
||||
"", {10, 80}, 5, false, nullptr, false);
|
||||
auto updateThresholdLabel = [=]() {
|
||||
int mph = QString::fromStdString(params.get("VisualStyleOverheadThreshold")).toInt();
|
||||
visual_style_overhead_threshold_settings->setLabel(QString("%1 mph").arg(mph));
|
||||
};
|
||||
connect(visual_style_overhead_threshold_settings, &OptionControlSP::updateLabels, updateThresholdLabel);
|
||||
updateThresholdLabel();
|
||||
list->addItem(visual_style_overhead_threshold_settings);
|
||||
|
||||
// Visuals: Display Metrics below Chevron
|
||||
std::vector<QString> chevron_info_settings_texts{tr("Off"), tr("Distance"), tr("Speed"), tr("Time"), tr("All")};
|
||||
chevron_info_settings = new ButtonParamControlSP(
|
||||
@@ -260,19 +136,6 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) {
|
||||
380);
|
||||
list->addItem(dev_ui_settings);
|
||||
|
||||
bool radar_tracks_enabled = QString::fromStdString(params.get("VisualRadarTracks")).toInt() != 0;
|
||||
visual_radar_tracks_delay_settings->setVisible(radar_tracks_enabled);
|
||||
param_watcher->addParam("VisualRadarTracks");
|
||||
|
||||
visual_style_value = QString::fromStdString(params.get("VisualStyle")).toInt();
|
||||
visual_style_overhead_value = QString::fromStdString(params.get("VisualStyleOverhead")).toInt();
|
||||
visual_style_zoom_settings->setVisible(visual_style_value != 0);
|
||||
visual_style_overhead_settings->setVisible(visual_style_value != 0);
|
||||
visual_style_overhead_zoom_settings->setVisible(visual_style_value != 0 && visual_style_overhead_value != 0);
|
||||
visual_style_overhead_threshold_settings->setVisible(visual_style_value != 0 && visual_style_overhead_value != 0);
|
||||
param_watcher->addParam("VisualStyle");
|
||||
param_watcher->addParam("VisualStyleOverhead");
|
||||
|
||||
sunnypilotScroller = new ScrollViewSP(list, this);
|
||||
vlayout->addWidget(sunnypilotScroller);
|
||||
|
||||
@@ -328,19 +191,4 @@ void VisualsPanel::paramsRefresh() {
|
||||
if (dev_ui_settings) {
|
||||
dev_ui_settings->refresh();
|
||||
}
|
||||
if (visual_wide_cam_settings) {
|
||||
visual_wide_cam_settings->refresh();
|
||||
}
|
||||
if (visual_style_settings) {
|
||||
visual_style_settings->refresh();
|
||||
}
|
||||
if (visual_style_zoom_settings) {
|
||||
visual_style_zoom_settings->refresh();
|
||||
}
|
||||
if (visual_style_overhead_settings) {
|
||||
visual_style_overhead_settings->refresh();
|
||||
}
|
||||
if (visual_style_overhead_zoom_settings) {
|
||||
visual_style_overhead_zoom_settings->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,14 +32,4 @@ protected:
|
||||
ButtonParamControlSP *dev_ui_settings;
|
||||
|
||||
bool has_longitudinal_control = false;
|
||||
|
||||
OptionControlSP *visual_radar_tracks_delay_settings;
|
||||
ButtonParamControlSP *visual_wide_cam_settings;
|
||||
int visual_style_value = 0;
|
||||
int visual_style_overhead_value = 0;
|
||||
ButtonParamControlSP *visual_style_settings;
|
||||
ButtonParamControlSP *visual_style_zoom_settings;
|
||||
ButtonParamControlSP *visual_style_overhead_settings;
|
||||
ButtonParamControlSP *visual_style_overhead_zoom_settings;
|
||||
OptionControlSP *visual_style_overhead_threshold_settings;
|
||||
};
|
||||
|
||||
@@ -8,12 +8,6 @@
|
||||
#include "selfdrive/ui/sunnypilot/qt/onroad/model.h"
|
||||
|
||||
|
||||
void ModelRendererSP::drawRadarPoint(QPainter &painter, const QPointF &pos, float v_rel, float radius) {
|
||||
painter.setBrush(QColor(255, 255, 255, 200));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawEllipse(pos, radius, radius);
|
||||
}
|
||||
|
||||
void ModelRendererSP::update_model(const cereal::ModelDataV2::Reader &model, const cereal::RadarState::LeadData::Reader &lead) {
|
||||
ModelRenderer::update_model(model, lead);
|
||||
const auto &model_position = model.getPosition();
|
||||
@@ -73,26 +67,6 @@ void ModelRendererSP::draw(QPainter &painter, const QRect &surface_rect) {
|
||||
const bool right_blindspot = car_state.getRightBlindspot();
|
||||
drawBlindspot(painter, surface_rect, left_blindspot, right_blindspot);
|
||||
}
|
||||
|
||||
if (s->scene.visual_radar_tracks) {
|
||||
if (sm.alive("liveTracks") && sm.rcv_frame("liveTracks") >= s->scene.started_frame) {
|
||||
const auto &tracks = sm["liveTracks"].getLiveTracks().getPoints();
|
||||
for (const auto &track : tracks) {
|
||||
if (!std::isfinite(track.getDRel()) || !std::isfinite(track.getYRel())) continue;
|
||||
float t_lag = s->scene.visual_radar_tracks_delay;
|
||||
float d_pred = track.getDRel();
|
||||
float y_pred = track.getYRel();
|
||||
if (t_lag > 0.0f) {
|
||||
d_pred += track.getVRel() * t_lag + 0.5f * track.getARel() * t_lag * t_lag;
|
||||
}
|
||||
QPointF screen_pt;
|
||||
if (mapToScreen(d_pred, -y_pred, path_offset_z, &screen_pt)) {
|
||||
drawRadarPoint(painter, screen_pt, track.getVRel(), 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawLeadStatus(painter, surface_rect.height(), surface_rect.width());
|
||||
|
||||
painter.restore();
|
||||
|
||||
@@ -28,6 +28,4 @@ private:
|
||||
|
||||
// Lead status animation
|
||||
float lead_status_alpha = 0.0f;
|
||||
|
||||
void drawRadarPoint(QPainter &painter, const QPointF &pos, float v_rel, float radius = 10.0f);
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) {
|
||||
"wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan",
|
||||
"modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP",
|
||||
"carControl", "gpsLocationExternal", "gpsLocation", "liveTorqueParameters",
|
||||
"carStateSP", "liveParameters", "liveMapDataSP", "carParamsSP", "liveTracks"
|
||||
"carStateSP", "liveParameters", "liveMapDataSP", "carParamsSP"
|
||||
});
|
||||
|
||||
// update timer
|
||||
@@ -44,14 +44,6 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) {
|
||||
});
|
||||
param_watcher->addParam("DevUIInfo");
|
||||
param_watcher->addParam("StandstillTimer");
|
||||
param_watcher->addParam("VisualRadarTracks");
|
||||
param_watcher->addParam("VisualRadarTracksDelay");
|
||||
param_watcher->addParam("VisualWideCam");
|
||||
param_watcher->addParam("VisualStyle");
|
||||
param_watcher->addParam("VisualStyleZoom");
|
||||
param_watcher->addParam("VisualStyleOverhead");
|
||||
param_watcher->addParam("VisualStyleOverheadZoom");
|
||||
param_watcher->addParam("VisualStyleOverheadThreshold");
|
||||
}
|
||||
|
||||
// This method overrides completely the update method from the parent class intentionally.
|
||||
@@ -84,17 +76,6 @@ void ui_update_params_sp(UIStateSP *s) {
|
||||
s->scene.chevron_info = std::atoi(params.get("ChevronInfo").c_str());
|
||||
s->scene.blindspot_ui = params.getBool("BlindSpot");
|
||||
s->scene.rainbow_mode = params.getBool("RainbowMode");
|
||||
|
||||
s->scene.visual_radar_tracks = QString::fromStdString(params.get("VisualRadarTracks")).toInt();
|
||||
s->scene.visual_radar_tracks_delay = QString::fromStdString(params.get("VisualRadarTracksDelay")).toFloat();
|
||||
|
||||
s->scene.visual_wide_cam = QString::fromStdString(params.get("VisualWideCam")).toInt();
|
||||
|
||||
s->scene.visual_style = QString::fromStdString(params.get("VisualStyle")).toInt();
|
||||
s->scene.visual_style_zoom = QString::fromStdString(params.get("VisualStyleZoom")).toInt();
|
||||
s->scene.visual_style_overhead = QString::fromStdString(params.get("VisualStyleOverhead")).toInt();
|
||||
s->scene.visual_style_overhead_zoom = QString::fromStdString(params.get("VisualStyleOverheadZoom")).toInt();
|
||||
s->scene.visual_style_overhead_threshold = QString::fromStdString(params.get("VisualStyleOverheadThreshold")).toInt();
|
||||
}
|
||||
|
||||
void UIStateSP::reset_onroad_sleep_timer(OnroadTimerStatusToggle toggleTimerStatus) {
|
||||
|
||||
@@ -21,12 +21,4 @@ typedef struct UISceneSP : UIScene {
|
||||
int chevron_info;
|
||||
bool blindspot_ui;
|
||||
bool rainbow_mode;
|
||||
int visual_radar_tracks = 0;
|
||||
float visual_radar_tracks_delay = 0;
|
||||
int visual_wide_cam = 0;
|
||||
int visual_style = 0;
|
||||
int visual_style_zoom = 0;
|
||||
int visual_style_overhead = 0;
|
||||
int visual_style_overhead_zoom = 0;
|
||||
int visual_style_overhead_threshold = 20.0;
|
||||
} UISceneSP;
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define SUNNYPILOT_VERSION "2025.003.000"
|
||||
#define SUNNYPILOT_VERSION "2025.002.000"
|
||||
|
||||
@@ -15,8 +15,6 @@ from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.helpers import set_
|
||||
|
||||
import openpilot.system.sentry as sentry
|
||||
|
||||
from sunnypilot.sunnylink.statsd import STATSLOGSP
|
||||
|
||||
|
||||
def log_fingerprint(CP: structs.CarParams) -> None:
|
||||
if CP.carFingerprint == "MOCK":
|
||||
@@ -102,9 +100,6 @@ def setup_interfaces(CI: CarInterfaceBase, params: Params = None) -> None:
|
||||
_initialize_torque_lateral_control(CI, CP, enforce_torque, nnlc_enabled)
|
||||
_cleanup_unsupported_params(CP, CP_SP)
|
||||
|
||||
STATSLOGSP.raw('sunnypilot.car_params', CP.to_dict())
|
||||
# STATSLOGSP.raw('sunnypilot_params.car_params_sp', CP_SP.to_dict()) # https://github.com/sunnypilot/opendbc/pull/361
|
||||
|
||||
|
||||
def initialize_params(params) -> list[dict[str, Any]]:
|
||||
keys: list = []
|
||||
|
||||
@@ -34,6 +34,9 @@ SUNNYLINK_RECONNECT_TIMEOUT_S = 70 # FYI changing this will also would require
|
||||
DISALLOW_LOG_UPLOAD = threading.Event()
|
||||
|
||||
params = Params()
|
||||
sunnylink_dongle_id = params.get("SunnylinkDongleId")
|
||||
sunnylink_api = SunnylinkApi(sunnylink_dongle_id)
|
||||
|
||||
|
||||
def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None:
|
||||
cloudlog.info("sunnylinkd.handle_long_poll started")
|
||||
@@ -49,7 +52,7 @@ def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None:
|
||||
threading.Thread(target=ws_queue, args=(end_event,), name='ws_queue'),
|
||||
threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler'),
|
||||
# threading.Thread(target=sunny_log_handler, args=(end_event, comma_prime_cellular_end_event), name='log_handler'),
|
||||
threading.Thread(target=stat_handler, args=(end_event, Paths.stats_sp_root(), True), name='stat_handler'),
|
||||
threading.Thread(target=stat_handler, args=(end_event, Paths.stats_sp_root()), name='stat_handler'),
|
||||
] + [
|
||||
threading.Thread(target=jsonrpc_handler, args=(end_event, partial(startLocalProxy, end_event),), name=f'worker_{x}')
|
||||
for x in range(HANDLER_THREADS)
|
||||
@@ -130,8 +133,6 @@ def ws_ping(ws: WebSocket, end_event: threading.Event) -> None:
|
||||
|
||||
|
||||
def ws_queue(end_event: threading.Event) -> None:
|
||||
sunnylink_dongle_id = params.get("SunnylinkDongleId")
|
||||
sunnylink_api = SunnylinkApi(sunnylink_dongle_id)
|
||||
resume_requested = False
|
||||
tries = 0
|
||||
|
||||
@@ -233,9 +234,6 @@ def saveParams(params_to_update: dict[str, str], compression: bool = False) -> N
|
||||
|
||||
|
||||
def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local_port: int) -> dict[str, int]:
|
||||
sunnylink_dongle_id = params.get("SunnylinkDongleId")
|
||||
sunnylink_api = SunnylinkApi(sunnylink_dongle_id)
|
||||
|
||||
cloudlog.debug("athena.startLocalProxy.starting")
|
||||
ws = create_connection(
|
||||
remote_ws_uri,
|
||||
@@ -257,8 +255,6 @@ def main(exit_event: threading.Event = None):
|
||||
cloudlog.info("Waiting for sunnylink registration to complete")
|
||||
time.sleep(10)
|
||||
|
||||
sunnylink_dongle_id = params.get("SunnylinkDongleId")
|
||||
sunnylink_api = SunnylinkApi(sunnylink_dongle_id)
|
||||
UploadQueueCache.initialize(upload_queue)
|
||||
|
||||
ws_uri = f"{SUNNYLINK_ATHENA_HOST}"
|
||||
|
||||
@@ -23,26 +23,21 @@ from openpilot.system.loggerd.config import STATS_DIR_FILE_LIMIT, STATS_SOCKET,
|
||||
from openpilot.system.statsd import METRIC_TYPE, StatLogSP
|
||||
from openpilot.common.realtime import Ratekeeper
|
||||
|
||||
STATSLOGSP = StatLogSP(intercept=False)
|
||||
|
||||
def sp_stats(end_event):
|
||||
"""Collect sunnypilot-specific statistics and send as raw metrics."""
|
||||
rk = Ratekeeper(.1, print_delay_threshold=None)
|
||||
statlogsp = STATSLOGSP
|
||||
statlogsp = StatLogSP(intercept=False)
|
||||
params = Params()
|
||||
|
||||
def flatten_dict(d, parent_key='', sep='.'):
|
||||
items = {}
|
||||
if isinstance(d, dict):
|
||||
for k, v in d.items():
|
||||
new_key = f"{parent_key}{sep}{k}" if parent_key else k
|
||||
for k, v in d.items():
|
||||
new_key = f"{parent_key}{sep}{k}" if parent_key else k
|
||||
if isinstance(v, dict):
|
||||
items.update(flatten_dict(v, new_key, sep=sep))
|
||||
elif isinstance(d, (list, tuple)):
|
||||
for i, v in enumerate(d):
|
||||
new_key = f"{parent_key}[{i}]"
|
||||
items.update(flatten_dict(v, new_key, sep=sep))
|
||||
else:
|
||||
items[parent_key] = d
|
||||
else:
|
||||
items[new_key] = v
|
||||
return items
|
||||
|
||||
# Collect sunnypilot parameters
|
||||
@@ -53,7 +48,6 @@ def sp_stats(end_event):
|
||||
'AutoLaneChangeBsmDelay',
|
||||
'AutoLaneChangeTimer',
|
||||
'CarPlatformBundle',
|
||||
'CurrentRoute',
|
||||
'DevUIInfo',
|
||||
'EnableCopyparty',
|
||||
'IntelligentCruiseButtonManagement',
|
||||
@@ -64,7 +58,6 @@ def sp_stats(end_event):
|
||||
'MadsMainCruiseAllowed',
|
||||
'MadsSteeringMode',
|
||||
'MadsUnifiedEngagementMode',
|
||||
'ModelManager_ActiveBundle',
|
||||
'ModelManager_Favs',
|
||||
'EnableSunnylinkUploader',
|
||||
'SunnylinkEnabled',
|
||||
@@ -86,13 +79,13 @@ def sp_stats(end_event):
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
if isinstance(value, (dict, list, tuple)):
|
||||
if isinstance(value, dict):
|
||||
stats_dict.update(flatten_dict(value, key))
|
||||
else:
|
||||
stats_dict[key] = value
|
||||
|
||||
if stats_dict:
|
||||
statlogsp.raw('sunnypilot.device_params', stats_dict)
|
||||
statlogsp.raw('sunnypilot_params', stats_dict)
|
||||
except Exception as e:
|
||||
cloudlog.error(f"Exception {e}")
|
||||
finally:
|
||||
@@ -118,26 +111,14 @@ def stats_main(end_event):
|
||||
res += f"sunnylink_dongle_id=\"{sunnylink_dongle_id}\",comma_dongle_id=\"{comma_dongle_id}\" {int(timestamp.timestamp() * 1e9)}\n"
|
||||
return res
|
||||
|
||||
def get_influxdb_line_raw(measurement: str, value: dict, timestamp: datetime, tags: dict) -> str:
|
||||
def get_influxdb_line_raw(measurement: str, value: dict[str, float], timestamp: datetime, tags: dict) -> str:
|
||||
res = f"{measurement}"
|
||||
try:
|
||||
custom_tags = ""
|
||||
for k, v in tags.items():
|
||||
custom_tags += f",{k}={str(v)}"
|
||||
res += custom_tags
|
||||
for k, v in tags.items():
|
||||
res += f",{k}={str(v)}"
|
||||
res += " "
|
||||
|
||||
fields = ""
|
||||
for k, v in value.items():
|
||||
# Skip complex types - only keep simple scalar values
|
||||
if isinstance(v, (dict, list, bytes, bytearray)):
|
||||
continue
|
||||
|
||||
fields += f"{k}={json.dumps(v)},"
|
||||
|
||||
res += f" {fields}"
|
||||
except Exception as e:
|
||||
cloudlog.error(f"Unable to get influxdb line for: {value}")
|
||||
res += f",invalid=1 reason={e},"
|
||||
for k, v in value.items():
|
||||
res += f"{k}=\"{str(v)}\","
|
||||
|
||||
res += f"sunnylink_dongle_id=\"{sunnylink_dongle_id}\",comma_dongle_id=\"{comma_dongle_id}\" {int(timestamp.timestamp() * 1e9)}\n"
|
||||
return res
|
||||
|
||||
@@ -744,7 +744,7 @@ def log_handler(end_event: threading.Event, log_attr_name=LOG_ATTR_NAME) -> None
|
||||
cloudlog.exception("athena.log_handler.exception")
|
||||
|
||||
|
||||
def stat_handler(end_event: threading.Event, stats_dir=None, is_sunnylink=False) -> None:
|
||||
def stat_handler(end_event: threading.Event, stats_dir=None) -> None:
|
||||
stats_dir = stats_dir or Paths.stats_root()
|
||||
last_scan = 0.0
|
||||
|
||||
@@ -756,28 +756,14 @@ def stat_handler(end_event: threading.Event, stats_dir=None, is_sunnylink=False)
|
||||
if len(stat_filenames) > 0:
|
||||
stat_path = os.path.join(stats_dir, stat_filenames[0])
|
||||
with open(stat_path) as f:
|
||||
payload = f.read()
|
||||
is_compressed = False
|
||||
|
||||
# Log the current size of the file
|
||||
if is_sunnylink:
|
||||
# Compress and encode the data if it exceeds the maximum size
|
||||
compressed_data = gzip.compress(payload.encode())
|
||||
payload = base64.b64encode(compressed_data).decode()
|
||||
is_compressed = True
|
||||
|
||||
jsonrpc = {
|
||||
"method": "storeStats",
|
||||
"params": {
|
||||
"stats": payload
|
||||
"stats": f.read()
|
||||
},
|
||||
"jsonrpc": "2.0",
|
||||
"id": stat_filenames[0]
|
||||
}
|
||||
|
||||
if is_sunnylink and is_compressed:
|
||||
jsonrpc["params"]["compressed"] = is_compressed
|
||||
|
||||
low_priority_send_queue.put_nowait(json.dumps(jsonrpc))
|
||||
os.remove(stat_path)
|
||||
last_scan = curr_scan
|
||||
|
||||
@@ -24,6 +24,8 @@ SP_BRANCH_MIGRATIONS = {
|
||||
("tizi", "staging-c3-new"): "staging",
|
||||
("tizi", "dev-c3-new"): "dev",
|
||||
("tizi", "master-dev-c3-new"): "master-dev",
|
||||
("tici", "hkg-angle-steering-2025"): "hkg-angle-steering-2025-tici",
|
||||
("tici", "hkg-angle-steering-2025-prebuilt"): "hkg-angle-steering-2025-tici-prebuilt"
|
||||
}
|
||||
|
||||
BUILD_METADATA_FILENAME = "build.json"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,183 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<root>
|
||||
<tabbed_widget parent="main_window" name="Main Window">
|
||||
<Tab containers="1" tab_name="actuator data">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.25;0.25;0.25;0.25" count="4">
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.100000" left="301.990881" top="0.100000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/torque" color="#17becf"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-130.920132" left="301.990881" top="103.993176" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/steeringAngleDeg" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.604818" left="301.990881" top="24.797527" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/vEgoRaw" color="#ff7f0e"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.037812" left="301.990881" top="0.047261" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/curvature" color="#f14cc1"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab containers="1" tab_name="steering messages (CAN)">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.142857;0.142857;0.142857;0.142857;0.142857;0.142857;0.142857" count="7">
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.025000" left="301.990881" top="1.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/can/128/LKAS_ALT/ADAS_ACIAnglTqRedcGainVal" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-128.740000" left="301.990881" top="103.940000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/can/128/LKAS_ALT/ADAS_StrAnglReqVal" color="#29d627"/>
|
||||
<curve name="/can/192/LKAS_ALT/ADAS_StrAnglReqVal" color="#b41f32"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.025000" left="301.990881" top="1.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/steeringPressed" color="#d62728"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="0.975000" left="301.990881" top="2.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/sendcan/0/LKAS_ALT/LKAS_ANGLE_ACTIVE" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.025000" left="301.990881" top="1.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/steerFaultTemporary" color="#d62728"/>
|
||||
<curve name="/carControl/latActive" color="#1ac938"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.025000" left="301.990881" top="1.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/can/1/CCNC_0x161/DAW_ICON" color="#f14cc1"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-14.375000" left="301.990881" top="589.375000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/pandaStates/0/safetyTxBlocked" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab containers="1" tab_name="Understanding Torque">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.5;0.5" count="2">
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-6.175000" left="429.901019" top="253.175000" right="590.696728"/>
|
||||
<limitY/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-24.190000" left="301.990881" top="21.590000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/steeringTorqueEps" color="#1ac938"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab containers="1" tab_name="tab2">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.25;0.25;0.25;0.25" count="4">
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Dots">
|
||||
<range bottom="-0.025000" left="301.990881" top="1.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/sendcan/0/LKAS_ALT/ADAS_ACIAnglTqRedcGainVal" color="#9467bd"/>
|
||||
<curve name="/can/1/LFA_ALT/ADAS_ACIAnglTqRedcGainVal" color="#17becf"/>
|
||||
<curve name="/can/128/LKAS_ALT/ADAS_ACIAnglTqRedcGainVal" color="#1f77b4"/>
|
||||
<curve name="/can/192/LKAS_ALT/ADAS_ACIAnglTqRedcGainVal" color="#d62728"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Dots">
|
||||
<range bottom="0.975000" left="301.990881" top="2.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/can/128/LKAS_ALT/LKAS_ANGLE_ACTIVE" color="#b8c91a"/>
|
||||
<curve name="/can/192/LKAS_ALT/LKAS_ANGLE_ACTIVE" color="#ff7f0e"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Lines">
|
||||
<range bottom="-0.025000" left="301.990881" top="1.025000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/can/1/CCNC_0x161/DAW_ICON" color="#f14cc1"/>
|
||||
<curve name="/carState/steerFaultTemporary" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot mode="TimeSeries" flip_x="false" flip_y="false" style="Dots">
|
||||
<range bottom="-14.375000" left="301.990881" top="589.375000" right="462.962504"/>
|
||||
<limitY/>
|
||||
<curve name="/pandaStates/0/safetyTxBlocked" color="#bcbd22"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<currentTabIndex index="3"/>
|
||||
</tabbed_widget>
|
||||
<use_relative_time_offset enabled="1"/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<Plugins>
|
||||
<plugin ID="DataLoad CSV">
|
||||
<default time_axis="" delimiter="0"/>
|
||||
</plugin>
|
||||
<plugin ID="DataLoad MCAP"/>
|
||||
<plugin ID="DataLoad Rlog"/>
|
||||
<plugin ID="DataLoad ULog"/>
|
||||
<plugin ID="Cereal Subscriber"/>
|
||||
<plugin ID="UDP Server"/>
|
||||
<plugin ID="WebSocket Server"/>
|
||||
<plugin ID="ZMQ Subscriber"/>
|
||||
<plugin ID="Fast Fourier Transform"/>
|
||||
<plugin ID="Quaternion to RPY"/>
|
||||
<plugin ID="Reactive Script Editor">
|
||||
<library code="--[[ Helper function to create a series from arrays

 new_series: a series previously created with ScatterXY.new(name)
 prefix: prefix of the timeseries, before the index of the array
 suffix_X: suffix to complete the name of the series containing the X value. If [nil], use the index of the array.
 suffix_Y: suffix to complete the name of the series containing the Y value
 timestamp: usually the tracker_time variable
 
 Example:
 
 Assuming we have multiple series in the form:
 
 /trajectory/node.{X}/position/x
 /trajectory/node.{X}/position/y
 
 where {N} is the index of the array (integer). We can create a reactive series from the array with:
 
 new_series = ScatterXY.new("my_trajectory") 
 CreateSeriesFromArray( new_series, "/trajectory/node", "position/x", "position/y", tracker_time );
--]]

function CreateSeriesFromArray( new_series, prefix, suffix_X, suffix_Y, timestamp )
 
 --- clear previous values
 new_series:clear()
 
 --- Append points to new_series
 index = 0
 while(true) do

 x = index;
 -- if not nil, get the X coordinate from a series
 if suffix_X ~= nil then 
 series_x = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_X) )
 if series_x == nil then break end
 x = series_x:atTime(timestamp)	 
 end
 
 series_y = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_Y) )
 if series_y == nil then break end 
 y = series_y:atTime(timestamp)
 
 new_series:push_back(x,y)
 index = index+1
 end
end

--[[ Similar to the built-in function GetSeriesNames(), but select only the names with a give prefix. --]]

function GetSeriesNamesByPrefix(prefix)
 -- GetSeriesNames(9 is a built-in function
 all_names = GetSeriesNames()
 filtered_names = {}
 for i, name in ipairs(all_names) do
 -- check the prefix
 if name:find(prefix, 1, #prefix) then
 table.insert(filtered_names, name);
 end
 end
 return filtered_names
end

--[[ Modify an existing series, applying offsets to all their X and Y values

 series: an existing timeseries, obtained with TimeseriesView.find(name)
 delta_x: offset to apply to each x value
 delta_y: offset to apply to each y value 
 
--]]

function ApplyOffsetInPlace(series, delta_x, delta_y)
 -- use C++ indeces, not Lua indeces
 for index=0, series:size()-1 do
 x,y = series:at(index)
 series:set(index, x + delta_x, y + delta_y)
 end
end
"/>
|
||||
<scripts/>
|
||||
</plugin>
|
||||
<plugin ID="CSV Exporter"/>
|
||||
</Plugins>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<customMathEquations/>
|
||||
<snippets/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
</root>
|
||||
|
||||
@@ -0,0 +1,636 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<root>
|
||||
<tabbed_widget name="Main Window" parent="main_window">
|
||||
<Tab tab_name="actuator data" containers="1">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.25;0.25;0.25;0.25" count="4">
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.100000" left="6.467547" top="0.100000"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/torque" color="#17becf"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-356.587494" left="6.467547" top="491.287506"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/steeringAngleDeg" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.856228" left="6.467547" top="35.834527"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/vEgoRaw" color="#ff7f0e"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.186684" left="6.467547" top="0.134230"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/curvature" color="#f14cc1"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab tab_name="steering messages (CAN)" containers="1">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.25;0.25;0.25;0.25" count="4">
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.022000" left="6.467547" top="0.902000"/>
|
||||
<limitY/>
|
||||
<curve name="/sendcan/0/LKAS_ALT/ADAS_ACIAnglTqRedcGainVal" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-5.168301" left="6.467547" top="4.590794"/>
|
||||
<limitY/>
|
||||
<curve name="IMU_LatAccelVal_ms^2_roll_compensated" color="#ff7f0e"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.025000" left="6.467547" top="1.025000"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/steeringPressed" color="#d62728"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.100000" left="6.467547" top="0.100000"/>
|
||||
<limitY/>
|
||||
<curve name="/can/1/CCNC_0x161/DAW_ICON" color="#f14cc1"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab tab_name="Understanding Torque" containers="1">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.5;0.5" count="2">
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="722.420439" bottom="-6.250000" left="0.000000" top="256.250000"/>
|
||||
<limitY/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-34.457500" left="6.467547" top="26.757499"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/steeringTorqueEps" color="#1ac938"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab tab_name="Angle Error and Saturation TQ" containers="1">
|
||||
<Container>
|
||||
<DockSplitter orientation="-" sizes="0.200218;0.200218;0.199129;0.200218;0.200218" count="5">
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-356.587494" left="6.467547" top="491.287506"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/actuators/steeringAngleDeg" color="#d62728"/>
|
||||
<curve name="/carState/steeringAngleDeg" color="#1ac938"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-134.196237" left="6.467547" top="34.112077"/>
|
||||
<limitY/>
|
||||
<curve name="Angle Error" color="#ff7f0e"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.022000" left="6.467547" top="0.902000"/>
|
||||
<limitY/>
|
||||
<curve name="/sendcan/0/LKAS_ALT/ADAS_ACIAnglTqRedcGainVal" color="#1f77b4"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.025000" left="6.467547" top="1.025000"/>
|
||||
<limitY/>
|
||||
<curve name="Angle Staturation" color="#f14cc1"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
||||
<range right="396.045059" bottom="-0.025000" left="6.467547" top="1.025000"/>
|
||||
<limitY/>
|
||||
<curve name="/carControl/latActive" color="#9467bd"/>
|
||||
<curve name="/carState/steeringPressed" color="#17becf"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<currentTabIndex index="3"/>
|
||||
</tabbed_widget>
|
||||
<use_relative_time_offset enabled="1"/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<Plugins>
|
||||
<plugin ID="DataLoad CSV">
|
||||
<default time_axis="" delimiter="0"/>
|
||||
</plugin>
|
||||
<plugin ID="DataLoad MCAP"/>
|
||||
<plugin ID="DataLoad Rlog"/>
|
||||
<plugin ID="DataLoad ULog"/>
|
||||
<plugin ID="Cereal Subscriber"/>
|
||||
<plugin ID="UDP Server"/>
|
||||
<plugin ID="WebSocket Server"/>
|
||||
<plugin ID="ZMQ Subscriber"/>
|
||||
<plugin ID="Fast Fourier Transform"/>
|
||||
<plugin ID="Quaternion to RPY"/>
|
||||
<plugin ID="Reactive Script Editor">
|
||||
<library code="--[[ Helper function to create a series from arrays

 new_series: a series previously created with ScatterXY.new(name)
 prefix: prefix of the timeseries, before the index of the array
 suffix_X: suffix to complete the name of the series containing the X value. If [nil], use the index of the array.
 suffix_Y: suffix to complete the name of the series containing the Y value
 timestamp: usually the tracker_time variable
 
 Example:
 
 Assuming we have multiple series in the form:
 
 /trajectory/node.{X}/position/x
 /trajectory/node.{X}/position/y
 
 where {N} is the index of the array (integer). We can create a reactive series from the array with:
 
 new_series = ScatterXY.new("my_trajectory") 
 CreateSeriesFromArray( new_series, "/trajectory/node", "position/x", "position/y", tracker_time );
--]]

function CreateSeriesFromArray( new_series, prefix, suffix_X, suffix_Y, timestamp )
 
 --- clear previous values
 new_series:clear()
 
 --- Append points to new_series
 index = 0
 while(true) do

 x = index;
 -- if not nil, get the X coordinate from a series
 if suffix_X ~= nil then 
 series_x = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_X) )
 if series_x == nil then break end
 x = series_x:atTime(timestamp)	 
 end
 
 series_y = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_Y) )
 if series_y == nil then break end 
 y = series_y:atTime(timestamp)
 
 new_series:push_back(x,y)
 index = index+1
 end
end

--[[ Similar to the built-in function GetSeriesNames(), but select only the names with a give prefix. --]]

function GetSeriesNamesByPrefix(prefix)
 -- GetSeriesNames(9 is a built-in function
 all_names = GetSeriesNames()
 filtered_names = {}
 for i, name in ipairs(all_names) do
 -- check the prefix
 if name:find(prefix, 1, #prefix) then
 table.insert(filtered_names, name);
 end
 end
 return filtered_names
end

--[[ Modify an existing series, applying offsets to all their X and Y values

 series: an existing timeseries, obtained with TimeseriesView.find(name)
 delta_x: offset to apply to each x value
 delta_y: offset to apply to each y value 
 
--]]

function ApplyOffsetInPlace(series, delta_x, delta_y)
 -- use C++ indeces, not Lua indeces
 for index=0, series:size()-1 do
 x,y = series:at(index)
 series:set(index, x + delta_x, y + delta_y)
 end
end
"/>
|
||||
<scripts/>
|
||||
</plugin>
|
||||
<plugin ID="CSV Exporter"/>
|
||||
</Plugins>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<previouslyLoaded_Datafiles>
|
||||
<fileInfo filename="../tmpgh9xhmjb.rlog" prefix="">
|
||||
<selected_datasources value=""/>
|
||||
</fileInfo>
|
||||
</previouslyLoaded_Datafiles>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<customMathEquations>
|
||||
<snippet name="Angle Staturation">
|
||||
<global></global>
|
||||
<function>if value > .3 then
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0</function>
|
||||
<linked_source>Angle Error</linked_source>
|
||||
</snippet>
|
||||
<snippet name="ang_cmd rate">
|
||||
<global>firstX = 0
|
||||
firstY = 0
|
||||
is_first = true
|
||||
secondX = 0
|
||||
secondY = 0
|
||||
is_second = false</global>
|
||||
<function>-- Wait for initial values
|
||||
if (is_first) then
|
||||
is_first = false
|
||||
is_second = true
|
||||
firstX = time
|
||||
firstY = value
|
||||
end
|
||||
|
||||
if (is_second) then
|
||||
is_second = false
|
||||
secondX = time
|
||||
secondY = value
|
||||
end
|
||||
|
||||
-- Central derivative: dy/dx ~= f(x+delta_x)-f(x-delta_x)/(2*delta_x)
|
||||
dx = time - firstX
|
||||
dy = value - firstY
|
||||
-- Increment
|
||||
firstX = secondX
|
||||
firstY = secondY
|
||||
secondX = time
|
||||
secondY = value
|
||||
|
||||
return dy/dx</function>
|
||||
<linked_source>/can/1/LFA_ALT/LKAS_ANGLE_CMD</linked_source>
|
||||
</snippet>
|
||||
<snippet name="max torque lj adj">
|
||||
<global>min=0
|
||||
max=250
|
||||
max_from_speed=96
|
||||
|
||||
k1=200
|
||||
k2=30
|
||||
k3=1
|
||||
k4=1
|
||||
k5=10
|
||||
|
||||
function sign(number)
|
||||
return number > 0 and 1 or (number == 0 and 0 or -1)
|
||||
end</global>
|
||||
<function>return 250 - value * 20</function>
|
||||
<linked_source>desired lateral jark</linked_source>
|
||||
</snippet>
|
||||
<snippet name="max torque(calc)">
|
||||
<global>min=0
|
||||
max=250
|
||||
max_from_speed=96
|
||||
|
||||
rate_lim = 500
|
||||
|
||||
la_deadzone = 0.38
|
||||
|
||||
k1=200
|
||||
k2=20
|
||||
k3=1.0
|
||||
k4=1
|
||||
k5=10
|
||||
|
||||
old = 0
|
||||
|
||||
function sign(number)
|
||||
return number > 0 and 1 or (number == 0 and 0 or -1)
|
||||
end
|
||||
|
||||
function apply_rate_limit(old, new, limit)
|
||||
return math.min(math.max(new, old - limit), old + limit)
|
||||
end
|
||||
|
||||
function apply_deadzone(val, deadzone)
|
||||
if math.abs(val) <= deadzone then
|
||||
return 0.0
|
||||
elseif val < 0.0 then
|
||||
return val + deadzone
|
||||
else
|
||||
return val - deadzone
|
||||
end
|
||||
end</global>
|
||||
<function>la = apply_deadzone(v2, la_deadzone)
|
||||
lj = v3
|
||||
|
||||
if la == 0.0 then
|
||||
lj = 0.0
|
||||
end
|
||||
|
||||
fla = math.min(math.abs(k1 * la)^k3, max)
|
||||
flj = math.min(math.abs(k2 * lj)^k4, max)
|
||||
|
||||
out = fla
|
||||
|
||||
flv = math.min(max_from_speed, k5 * v4)
|
||||
|
||||
out = out + flv
|
||||
|
||||
out = math.max(math.min(out, max), min)
|
||||
|
||||
if sign(la) == sign(lj) then
|
||||
out = out - flj
|
||||
else
|
||||
out = out + flj
|
||||
end
|
||||
|
||||
|
||||
if v5 == 1.0 then
|
||||
out = 0.0
|
||||
end
|
||||
|
||||
out = math.max(math.min(out, max), min)
|
||||
out = apply_rate_limit(old, out, rate_lim)
|
||||
old = out
|
||||
|
||||
return out</function>
|
||||
<linked_source>/can/1/LFA_ALT/LKAS_ANGLE_CMD</linked_source>
|
||||
<additional_sources>
|
||||
<v1>ang_cmd rate</v1>
|
||||
<v2>desired lat accel</v2>
|
||||
<v3>desired lateral jark</v3>
|
||||
<v4>/carState/vEgo</v4>
|
||||
<v5>/can/1/LFA_ALT/LKAS_ANGLE_ACTIVE</v5>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="carState.vEgo mph">
|
||||
<global></global>
|
||||
<function>return value * 2.23694</function>
|
||||
<linked_source>/carState/vEgo</linked_source>
|
||||
</snippet>
|
||||
<snippet name="abs(des la accel)">
|
||||
<global></global>
|
||||
<function>return math.abs(value)</function>
|
||||
<linked_source>desired lat accel</linked_source>
|
||||
</snippet>
|
||||
<snippet name="roll compensated lateral acceleration">
|
||||
<global></global>
|
||||
<function>if (v3 == 0 and v4 == 1) then
|
||||
return (value * v1 ^ 2) - (v2 * 9.81)
|
||||
end
|
||||
return 0</function>
|
||||
<linked_source>/controlsState/curvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
<v2>/liveParameters/roll</v2>
|
||||
<v3>/carState/steeringPressed</v3>
|
||||
<v4>/carControl/latActive</v4>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="Zero">
|
||||
<global></global>
|
||||
<function>return (0)</function>
|
||||
<linked_source>/carState/canValid</linked_source>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_ms^2">
|
||||
<global></global>
|
||||
<function>return value * -9.8</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="desired lat accel">
|
||||
<global></global>
|
||||
<function>return value * v1^2</function>
|
||||
<linked_source>/controlsState/desiredCurvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="engaged_accel_actuator">
|
||||
<global>engage_delay = 5
|
||||
last_bad_time = -engage_delay</global>
|
||||
<function>accel = value
|
||||
brake = v1
|
||||
gas = v2
|
||||
enabled = v3
|
||||
|
||||
if (brake ~= 0 or gas ~= 0 or enabled == 0) then
|
||||
last_bad_time = time
|
||||
end
|
||||
|
||||
if (time > last_bad_time + engage_delay) then
|
||||
return value
|
||||
else
|
||||
return 0
|
||||
end</function>
|
||||
<linked_source>/carControl/actuators/accel</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/brakePressed</v1>
|
||||
<v2>/carState/gasPressed</v2>
|
||||
<v3>/carControl/enabled</v3>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="Angle Error">
|
||||
<global>last_angle_requested = 0</global>
|
||||
<function>angle_error = last_angle_requested - v1
|
||||
|
||||
|
||||
last_angle_requested = value
|
||||
return angle_error</function>
|
||||
<linked_source>/carControl/actuators/steeringAngleDeg</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringAngleDeg</v1>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="carState.vEgo kmh">
|
||||
<global></global>
|
||||
<function>return value * 3.6</function>
|
||||
<linked_source>/carState/vEgo</linked_source>
|
||||
</snippet>
|
||||
<snippet name="engaged_accel_plan">
|
||||
<global>engage_delay = 5
|
||||
last_bad_time = -engage_delay</global>
|
||||
<function>accel = value
|
||||
brake = v1
|
||||
gas = v2
|
||||
enabled = v3
|
||||
|
||||
if (brake ~= 0 or gas ~= 0 or enabled == 0) then
|
||||
last_bad_time = time
|
||||
end
|
||||
|
||||
if (time > last_bad_time + engage_delay) then
|
||||
return value
|
||||
else
|
||||
return 0
|
||||
end</function>
|
||||
<linked_source>/longitudinalPlan/accels/0</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/brakePressed</v1>
|
||||
<v2>/carState/gasPressed</v2>
|
||||
<v3>/carControl/enabled</v3>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="engaged_accel_actual">
|
||||
<global>engage_delay = 5
|
||||
last_bad_time = -engage_delay</global>
|
||||
<function>accel = value
|
||||
brake = v1
|
||||
gas = v2
|
||||
enabled = v3
|
||||
|
||||
if (brake ~= 0 or gas ~= 0 or enabled == 0) then
|
||||
last_bad_time = time
|
||||
end
|
||||
|
||||
if (time > last_bad_time + engage_delay) then
|
||||
return value
|
||||
else
|
||||
return 0
|
||||
end</function>
|
||||
<linked_source>/carState/aEgo</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/brakePressed</v1>
|
||||
<v2>/carState/gasPressed</v2>
|
||||
<v3>/carControl/enabled</v3>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="desired lateral jark">
|
||||
<global>firstX = 0
|
||||
firstY = 0
|
||||
is_first = true
|
||||
secondX = 0
|
||||
secondY = 0
|
||||
is_second = false</global>
|
||||
<function>-- Wait for initial values
|
||||
if (is_first) then
|
||||
is_first = false
|
||||
is_second = true
|
||||
firstX = time
|
||||
firstY = value
|
||||
end
|
||||
|
||||
if (is_second) then
|
||||
is_second = false
|
||||
secondX = time
|
||||
secondY = value
|
||||
end
|
||||
|
||||
-- Central derivative: dy/dx ~= f(x+delta_x)-f(x-delta_x)/(2*delta_x)
|
||||
dx = time - firstX
|
||||
dy = value - firstY
|
||||
-- Increment
|
||||
firstX = secondX
|
||||
firstY = secondY
|
||||
secondX = time
|
||||
secondY = value
|
||||
|
||||
return dy/dx</function>
|
||||
<linked_source>desired lat accel</linked_source>
|
||||
</snippet>
|
||||
<snippet name="engaged curvature plan">
|
||||
<global>engage_delay = 5
|
||||
last_bad_time = -engage_delay</global>
|
||||
<function>curvature = value
|
||||
pressed = v1
|
||||
enabled = v2
|
||||
|
||||
if (pressed == 1 or enabled == 0) then
|
||||
last_bad_time = time
|
||||
end
|
||||
|
||||
if (time > last_bad_time + engage_delay) then
|
||||
return value
|
||||
else
|
||||
return 0
|
||||
end</function>
|
||||
<linked_source>/lateralPlan/curvatures/0</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/enabled</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="abs(ang_cmd)">
|
||||
<global></global>
|
||||
<function>return math.abs(value)</function>
|
||||
<linked_source>/can/1/LFA_ALT/LKAS_ANGLE_CMD</linked_source>
|
||||
</snippet>
|
||||
<snippet name="zero">
|
||||
<global>min=0
|
||||
max=250
|
||||
max_from_speed=96
|
||||
|
||||
rate_lim = 500
|
||||
|
||||
la_deadzone = 0.38
|
||||
|
||||
k1=200
|
||||
k2=20
|
||||
k3=1.0
|
||||
k4=1
|
||||
k5=10
|
||||
|
||||
old = 0
|
||||
|
||||
function sign(number)
|
||||
return number > 0 and 1 or (number == 0 and 0 or -1)
|
||||
end
|
||||
|
||||
function apply_rate_limit(old, new, limit)
|
||||
return math.min(math.max(new, old - limit), old + limit)
|
||||
end
|
||||
|
||||
function apply_deadzone(val, deadzone)
|
||||
if math.abs(val) <= deadzone then
|
||||
return 0.0
|
||||
elseif val < 0.0 then
|
||||
return val + deadzone
|
||||
else
|
||||
return val - deadzone
|
||||
end
|
||||
end</global>
|
||||
<function>return 0</function>
|
||||
<linked_source>/carState/aEgo</linked_source>
|
||||
</snippet>
|
||||
<snippet name="engaged curvature vehicle model">
|
||||
<global>engage_delay = 5
|
||||
last_bad_time = -engage_delay</global>
|
||||
<function>curvature = value
|
||||
pressed = v1
|
||||
enabled = v2
|
||||
|
||||
if (pressed == 1 or enabled == 0) then
|
||||
last_bad_time = time
|
||||
end
|
||||
|
||||
if (time > last_bad_time + engage_delay) then
|
||||
return value
|
||||
else
|
||||
return 0
|
||||
end</function>
|
||||
<linked_source>/controlsState/curvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/enabled</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="Actual lateral accel (roll compensated)">
|
||||
<global></global>
|
||||
<function>return (value * v1 ^ 2) - (v2 * 9.81)</function>
|
||||
<linked_source>/controlsState/curvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
<v2>/liveParameters/roll</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_ms^2_roll_compensated">
|
||||
<global></global>
|
||||
<function>if (v1 == 0 and v2 == 1) then
|
||||
return (value * -9.8) - (v3 * 9.81)
|
||||
end
|
||||
--return 0
|
||||
return (value * -9.8) - (v3 * 9.81)</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
<v3>/liveParameters/roll</v3>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_Ms^2">
|
||||
<global></global>
|
||||
<function>if (v1 == 0 and v2 == 1) then
|
||||
return value * -9.8
|
||||
end
|
||||
return 0</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="engaged curvature yaw">
|
||||
<global>engage_delay = 5
|
||||
last_bad_time = -engage_delay</global>
|
||||
<function>curvature = value / v3
|
||||
pressed = v1
|
||||
enabled = v2
|
||||
|
||||
if (pressed == 1 or enabled == 0) then
|
||||
last_bad_time = time
|
||||
end
|
||||
|
||||
if (time > last_bad_time + engage_delay) then
|
||||
return curvature
|
||||
else
|
||||
return 0
|
||||
end</function>
|
||||
<linked_source>/liveLocationKalman/angularVelocityCalibrated/value/2</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/enabled</v2>
|
||||
<v3>/liveLocationKalman/velocityCalibrated/value/0</v3>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_Ms^3">
|
||||
<global></global>
|
||||
<function>return value * -9.8</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="Desired lateral accel (roll compensated)">
|
||||
<global></global>
|
||||
<function>return (value * v1 ^ 2) - (v2 * 9.81)</function>
|
||||
<linked_source>/controlsState/desiredCurvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
<v2>/liveParameters/roll</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
</customMathEquations>
|
||||
<snippets/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
</root>
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<root>
|
||||
<tabbed_widget name="Main Window" parent="main_window">
|
||||
<Tab containers="1" tab_name="tab1">
|
||||
<Container>
|
||||
<DockSplitter sizes="0.500397;0.499603" count="2" orientation="-">
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" flip_y="false" mode="TimeSeries" style="Lines">
|
||||
<range top="256.250000" left="0.000000" right="421.102293" bottom="-6.250000"/>
|
||||
<limitY/>
|
||||
<curve color="#1ac938" name="/can/1/LFA_ALT/LKAS_ANGLE_MAX_TORQUE"/>
|
||||
<curve color="#17becf" name="max torque(calc)">
|
||||
<transform name="Moving Average" alias="max torque(calc)[Moving Average]">
|
||||
<options compensate_offset="true" value="10"/>
|
||||
</transform>
|
||||
</curve>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" flip_y="false" mode="TimeSeries" style="Lines">
|
||||
<range top="2.776497" left="0.000000" right="421.102293" bottom="-2.918548"/>
|
||||
<limitY/>
|
||||
<curve color="#f14cc1" name="desired lat accel"/>
|
||||
<curve color="#888888" name="zero"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<currentTabIndex index="0"/>
|
||||
</tabbed_widget>
|
||||
<use_relative_time_offset enabled="1"/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<Plugins>
|
||||
<plugin ID="DataLoad CSV">
|
||||
<default time_axis="" delimiter="0"/>
|
||||
</plugin>
|
||||
<plugin ID="DataLoad MCAP"/>
|
||||
<plugin ID="DataLoad Rlog"/>
|
||||
<plugin ID="DataLoad ULog"/>
|
||||
<plugin ID="Cereal Subscriber"/>
|
||||
<plugin ID="UDP Server"/>
|
||||
<plugin ID="WebSocket Server"/>
|
||||
<plugin ID="ZMQ Subscriber"/>
|
||||
<plugin ID="Fast Fourier Transform"/>
|
||||
<plugin ID="Quaternion to RPY"/>
|
||||
<plugin ID="Reactive Script Editor">
|
||||
<library code="--[[ Helper function to create a series from arrays

 new_series: a series previously created with ScatterXY.new(name)
 prefix: prefix of the timeseries, before the index of the array
 suffix_X: suffix to complete the name of the series containing the X value. If [nil], use the index of the array.
 suffix_Y: suffix to complete the name of the series containing the Y value
 timestamp: usually the tracker_time variable
 
 Example:
 
 Assuming we have multiple series in the form:
 
 /trajectory/node.{X}/position/x
 /trajectory/node.{X}/position/y
 
 where {N} is the index of the array (integer). We can create a reactive series from the array with:
 
 new_series = ScatterXY.new("my_trajectory") 
 CreateSeriesFromArray( new_series, "/trajectory/node", "position/x", "position/y", tracker_time );
--]]

function CreateSeriesFromArray( new_series, prefix, suffix_X, suffix_Y, timestamp )
 
 --- clear previous values
 new_series:clear()
 
 --- Append points to new_series
 index = 0
 while(true) do

 x = index;
 -- if not nil, get the X coordinate from a series
 if suffix_X ~= nil then 
 series_x = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_X) )
 if series_x == nil then break end
 x = series_x:atTime(timestamp)	 
 end
 
 series_y = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_Y) )
 if series_y == nil then break end 
 y = series_y:atTime(timestamp)
 
 new_series:push_back(x,y)
 index = index+1
 end
end

--[[ Similar to the built-in function GetSeriesNames(), but select only the names with a give prefix. --]]

function GetSeriesNamesByPrefix(prefix)
 -- GetSeriesNames(9 is a built-in function
 all_names = GetSeriesNames()
 filtered_names = {}
 for i, name in ipairs(all_names) do
 -- check the prefix
 if name:find(prefix, 1, #prefix) then
 table.insert(filtered_names, name);
 end
 end
 return filtered_names
end

--[[ Modify an existing series, applying offsets to all their X and Y values

 series: an existing timeseries, obtained with TimeseriesView.find(name)
 delta_x: offset to apply to each x value
 delta_y: offset to apply to each y value 
 
--]]

function ApplyOffsetInPlace(series, delta_x, delta_y)
 -- use C++ indeces, not Lua indeces
 for index=0, series:size()-1 do
 x,y = series:at(index)
 series:set(index, x + delta_x, y + delta_y)
 end
end
"/>
|
||||
<scripts/>
|
||||
</plugin>
|
||||
<plugin ID="CSV Exporter"/>
|
||||
</Plugins>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<previouslyLoaded_Datafiles>
|
||||
<fileInfo prefix="" filename="../tmpa_e8kwpj.rlog">
|
||||
<selected_datasources value=""/>
|
||||
</fileInfo>
|
||||
</previouslyLoaded_Datafiles>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<customMathEquations>
|
||||
<snippet name="zero">
|
||||
<global>min=0
|
||||
max=250
|
||||
max_from_speed=96
|
||||
|
||||
rate_lim = 500
|
||||
|
||||
la_deadzone = 0.38
|
||||
|
||||
k1=200
|
||||
k2=20
|
||||
k3=1.0
|
||||
k4=1
|
||||
k5=10
|
||||
|
||||
old = 0
|
||||
|
||||
function sign(number)
|
||||
return number > 0 and 1 or (number == 0 and 0 or -1)
|
||||
end
|
||||
|
||||
function apply_rate_limit(old, new, limit)
|
||||
return math.min(math.max(new, old - limit), old + limit)
|
||||
end
|
||||
|
||||
function apply_deadzone(val, deadzone)
|
||||
if math.abs(val) <= deadzone then
|
||||
return 0.0
|
||||
elseif val < 0.0 then
|
||||
return val + deadzone
|
||||
else
|
||||
return val - deadzone
|
||||
end
|
||||
end</global>
|
||||
<function>return 0</function>
|
||||
<linked_source>/carState/aEgo</linked_source>
|
||||
</snippet>
|
||||
<snippet name="max torque lj adj">
|
||||
<global>min=0
|
||||
max=250
|
||||
max_from_speed=96
|
||||
|
||||
k1=200
|
||||
k2=30
|
||||
k3=1
|
||||
k4=1
|
||||
k5=10
|
||||
|
||||
function sign(number)
|
||||
return number > 0 and 1 or (number == 0 and 0 or -1)
|
||||
end</global>
|
||||
<function>return 250 - value * 20</function>
|
||||
<linked_source>desired lateral jark</linked_source>
|
||||
</snippet>
|
||||
<snippet name="ang_cmd rate">
|
||||
<global>firstX = 0
|
||||
firstY = 0
|
||||
is_first = true
|
||||
secondX = 0
|
||||
secondY = 0
|
||||
is_second = false</global>
|
||||
<function>-- Wait for initial values
|
||||
if (is_first) then
|
||||
is_first = false
|
||||
is_second = true
|
||||
firstX = time
|
||||
firstY = value
|
||||
end
|
||||
|
||||
if (is_second) then
|
||||
is_second = false
|
||||
secondX = time
|
||||
secondY = value
|
||||
end
|
||||
|
||||
-- Central derivative: dy/dx ~= f(x+delta_x)-f(x-delta_x)/(2*delta_x)
|
||||
dx = time - firstX
|
||||
dy = value - firstY
|
||||
-- Increment
|
||||
firstX = secondX
|
||||
firstY = secondY
|
||||
secondX = time
|
||||
secondY = value
|
||||
|
||||
return dy/dx</function>
|
||||
<linked_source>/can/1/LFA_ALT/LKAS_ANGLE_CMD</linked_source>
|
||||
</snippet>
|
||||
<snippet name="max torque(calc)">
|
||||
<global>min=0
|
||||
max=250
|
||||
max_from_speed=96
|
||||
|
||||
rate_lim = 500
|
||||
|
||||
la_deadzone = 0.38
|
||||
|
||||
k1=200
|
||||
k2=20
|
||||
k3=1.0
|
||||
k4=1
|
||||
k5=10
|
||||
|
||||
old = 0
|
||||
|
||||
function sign(number)
|
||||
return number > 0 and 1 or (number == 0 and 0 or -1)
|
||||
end
|
||||
|
||||
function apply_rate_limit(old, new, limit)
|
||||
return math.min(math.max(new, old - limit), old + limit)
|
||||
end
|
||||
|
||||
function apply_deadzone(val, deadzone)
|
||||
if math.abs(val) <= deadzone then
|
||||
return 0.0
|
||||
elseif val < 0.0 then
|
||||
return val + deadzone
|
||||
else
|
||||
return val - deadzone
|
||||
end
|
||||
end</global>
|
||||
<function>la = apply_deadzone(v2, la_deadzone)
|
||||
lj = v3
|
||||
|
||||
if la == 0.0 then
|
||||
lj = 0.0
|
||||
end
|
||||
|
||||
fla = math.min(math.abs(k1 * la)^k3, max)
|
||||
flj = math.min(math.abs(k2 * lj)^k4, max)
|
||||
|
||||
out = fla
|
||||
|
||||
flv = math.min(max_from_speed, k5 * v4)
|
||||
|
||||
out = out + flv
|
||||
|
||||
out = math.max(math.min(out, max), min)
|
||||
|
||||
if sign(la) == sign(lj) then
|
||||
out = out - flj
|
||||
else
|
||||
out = out + flj
|
||||
end
|
||||
|
||||
|
||||
if v5 == 1.0 then
|
||||
out = 0.0
|
||||
end
|
||||
|
||||
out = math.max(math.min(out, max), min)
|
||||
out = apply_rate_limit(old, out, rate_lim)
|
||||
old = out
|
||||
|
||||
return out</function>
|
||||
<linked_source>/can/1/LFA_ALT/LKAS_ANGLE_CMD</linked_source>
|
||||
<additional_sources>
|
||||
<v1>ang_cmd rate</v1>
|
||||
<v2>desired lat accel</v2>
|
||||
<v3>desired lateral jark</v3>
|
||||
<v4>/carState/vEgo</v4>
|
||||
<v5>/can/1/LFA_ALT/LKAS_ANGLE_ACTIVE</v5>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="desired lateral jark">
|
||||
<global>firstX = 0
|
||||
firstY = 0
|
||||
is_first = true
|
||||
secondX = 0
|
||||
secondY = 0
|
||||
is_second = false</global>
|
||||
<function>-- Wait for initial values
|
||||
if (is_first) then
|
||||
is_first = false
|
||||
is_second = true
|
||||
firstX = time
|
||||
firstY = value
|
||||
end
|
||||
|
||||
if (is_second) then
|
||||
is_second = false
|
||||
secondX = time
|
||||
secondY = value
|
||||
end
|
||||
|
||||
-- Central derivative: dy/dx ~= f(x+delta_x)-f(x-delta_x)/(2*delta_x)
|
||||
dx = time - firstX
|
||||
dy = value - firstY
|
||||
-- Increment
|
||||
firstX = secondX
|
||||
firstY = secondY
|
||||
secondX = time
|
||||
secondY = value
|
||||
|
||||
return dy/dx</function>
|
||||
<linked_source>desired lat accel</linked_source>
|
||||
</snippet>
|
||||
<snippet name="abs(des la accel)">
|
||||
<global></global>
|
||||
<function>return math.abs(value)</function>
|
||||
<linked_source>desired lat accel</linked_source>
|
||||
</snippet>
|
||||
<snippet name="desired lat accel">
|
||||
<global></global>
|
||||
<function>return value * v1^2</function>
|
||||
<linked_source>/controlsState/desiredCurvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="abs(ang_cmd)">
|
||||
<global></global>
|
||||
<function>return math.abs(value)</function>
|
||||
<linked_source>/can/1/LFA_ALT/LKAS_ANGLE_CMD</linked_source>
|
||||
</snippet>
|
||||
</customMathEquations>
|
||||
<snippets/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
</root>
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<root>
|
||||
<tabbed_widget parent="main_window" name="Main Window">
|
||||
<Tab tab_name="tab1" containers="1">
|
||||
<Container>
|
||||
<DockSplitter sizes="0.25;0.25;0.25;0.25" count="4" orientation="-">
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" style="Lines" flip_y="false" mode="TimeSeries">
|
||||
<range bottom="-3.582051" right="1431.113121" top="5.314632" left="5.322399"/>
|
||||
<limitY/>
|
||||
<curve name="Actual lateral accel (roll compensated)" color="#1ac938"/>
|
||||
<curve name="Desired lateral accel (roll compensated)" color="#ff7f0e"/>
|
||||
<curve name="IMU_LatAccelVal_ms^2" color="#f14cc1"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" style="Lines" flip_y="false" mode="TimeSeries">
|
||||
<range bottom="-3.741271" right="1431.113121" top="3.756006" left="5.322399"/>
|
||||
<limitY/>
|
||||
<curve name="roll compensated lateral acceleration" color="#ff7f0e"/>
|
||||
<curve name="IMU_LatAccelVal_Ms^2" color="#1ac938"/>
|
||||
<curve name="IMU_LatAccelVal_ms^2_roll_compensated" color="#9467bd"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" style="Lines" flip_y="false" mode="TimeSeries">
|
||||
<range bottom="-0.025000" right="1431.113121" top="1.025000" left="5.322399"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/steeringPressed" color="#0097ff"/>
|
||||
<curve name="/carOutput/actuatorsOutput/torque" color="#d62728"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" style="Lines" flip_y="false" mode="TimeSeries">
|
||||
<range bottom="-1.660728" right="1431.113121" top="67.942958" left="5.322399"/>
|
||||
<limitY/>
|
||||
<curve name="/carState/vEgo" color="#f14cc1">
|
||||
<transform name="Scale/Offset" alias="/carState/vEgo[Scale/Offset]">
|
||||
<options value_scale="2.23694" time_offset="0" value_offset="0"/>
|
||||
</transform>
|
||||
</curve>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<Tab tab_name="tab2" containers="1">
|
||||
<Container>
|
||||
<DockSplitter sizes="0.5;0.5" count="2" orientation="-">
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" style="Lines" flip_y="false" mode="TimeSeries">
|
||||
<range bottom="30595.900000" right="1431.113121" top="34884.100000" left="5.322399"/>
|
||||
<limitY/>
|
||||
<curve name="/can/1/IMU_01_10ms/IMU_RollRtVal" color="#17becf"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
<DockArea name="...">
|
||||
<plot flip_x="false" style="Lines" flip_y="false" mode="TimeSeries">
|
||||
<range bottom="-0.058795" right="1431.113121" top="0.072448" left="5.322399"/>
|
||||
<limitY/>
|
||||
<curve name="/liveParameters/roll" color="#bcbd22"/>
|
||||
</plot>
|
||||
</DockArea>
|
||||
</DockSplitter>
|
||||
</Container>
|
||||
</Tab>
|
||||
<currentTabIndex index="1"/>
|
||||
</tabbed_widget>
|
||||
<use_relative_time_offset enabled="1"/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<Plugins>
|
||||
<plugin ID="DataLoad CSV">
|
||||
<default time_axis="" delimiter="0"/>
|
||||
</plugin>
|
||||
<plugin ID="DataLoad MCAP"/>
|
||||
<plugin ID="DataLoad Rlog"/>
|
||||
<plugin ID="DataLoad ULog"/>
|
||||
<plugin ID="Cereal Subscriber"/>
|
||||
<plugin ID="UDP Server"/>
|
||||
<plugin ID="WebSocket Server"/>
|
||||
<plugin ID="ZMQ Subscriber"/>
|
||||
<plugin ID="Fast Fourier Transform"/>
|
||||
<plugin ID="Quaternion to RPY"/>
|
||||
<plugin ID="Reactive Script Editor">
|
||||
<library code="--[[ Helper function to create a series from arrays

 new_series: a series previously created with ScatterXY.new(name)
 prefix: prefix of the timeseries, before the index of the array
 suffix_X: suffix to complete the name of the series containing the X value. If [nil], use the index of the array.
 suffix_Y: suffix to complete the name of the series containing the Y value
 timestamp: usually the tracker_time variable
 
 Example:
 
 Assuming we have multiple series in the form:
 
 /trajectory/node.{X}/position/x
 /trajectory/node.{X}/position/y
 
 where {N} is the index of the array (integer). We can create a reactive series from the array with:
 
 new_series = ScatterXY.new("my_trajectory") 
 CreateSeriesFromArray( new_series, "/trajectory/node", "position/x", "position/y", tracker_time );
--]]

function CreateSeriesFromArray( new_series, prefix, suffix_X, suffix_Y, timestamp )
 
 --- clear previous values
 new_series:clear()
 
 --- Append points to new_series
 index = 0
 while(true) do

 x = index;
 -- if not nil, get the X coordinate from a series
 if suffix_X ~= nil then 
 series_x = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_X) )
 if series_x == nil then break end
 x = series_x:atTime(timestamp)	 
 end
 
 series_y = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_Y) )
 if series_y == nil then break end 
 y = series_y:atTime(timestamp)
 
 new_series:push_back(x,y)
 index = index+1
 end
end

--[[ Similar to the built-in function GetSeriesNames(), but select only the names with a give prefix. --]]

function GetSeriesNamesByPrefix(prefix)
 -- GetSeriesNames(9 is a built-in function
 all_names = GetSeriesNames()
 filtered_names = {}
 for i, name in ipairs(all_names) do
 -- check the prefix
 if name:find(prefix, 1, #prefix) then
 table.insert(filtered_names, name);
 end
 end
 return filtered_names
end

--[[ Modify an existing series, applying offsets to all their X and Y values

 series: an existing timeseries, obtained with TimeseriesView.find(name)
 delta_x: offset to apply to each x value
 delta_y: offset to apply to each y value 
 
--]]

function ApplyOffsetInPlace(series, delta_x, delta_y)
 -- use C++ indeces, not Lua indeces
 for index=0, series:size()-1 do
 x,y = series:at(index)
 series:set(index, x + delta_x, y + delta_y)
 end
end
"/>
|
||||
<scripts/>
|
||||
</plugin>
|
||||
<plugin ID="CSV Exporter"/>
|
||||
</Plugins>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
<customMathEquations>
|
||||
<snippet name="IMU_LatAccelVal_ms^2">
|
||||
<global></global>
|
||||
<function>return value * -9.8</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="roll compensated lateral acceleration">
|
||||
<global></global>
|
||||
<function>if (v3 == 0 and v4 == 1) then
|
||||
return (value * v1 ^ 2) - (v2 * 9.81)
|
||||
end
|
||||
return 0</function>
|
||||
<linked_source>/controlsState/curvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
<v2>/liveParameters/roll</v2>
|
||||
<v3>/carState/steeringPressed</v3>
|
||||
<v4>/carControl/latActive</v4>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_Ms^2">
|
||||
<global></global>
|
||||
<function>if (v1 == 0 and v2 == 1) then
|
||||
return value * -9.8
|
||||
end
|
||||
return 0</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_Ms^3">
|
||||
<global></global>
|
||||
<function>return value * -9.8</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="IMU_LatAccelVal_ms^2_roll_compensated">
|
||||
<global></global>
|
||||
<function>
|
||||
|
||||
if (v1 == 0 and v2 == 1) then
|
||||
return (value * -9.8) - (v3 * 9.81)
|
||||
end
|
||||
return 0</function>
|
||||
<linked_source>/can/1/IMU_01_10ms/IMU_LatAccelVal</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/steeringPressed</v1>
|
||||
<v2>/carControl/latActive</v2>
|
||||
<v3>/liveParameters/roll</v3>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="Actual lateral accel (roll compensated)">
|
||||
<global></global>
|
||||
<function>return (value * v1 ^ 2) - (v2 * 9.81)</function>
|
||||
<linked_source>/controlsState/curvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
<v2>/liveParameters/roll</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
<snippet name="Desired lateral accel (roll compensated)">
|
||||
<global></global>
|
||||
<function>return (value * v1 ^ 2) - (v2 * 9.81)</function>
|
||||
<linked_source>/controlsState/desiredCurvature</linked_source>
|
||||
<additional_sources>
|
||||
<v1>/carState/vEgo</v1>
|
||||
<v2>/liveParameters/roll</v2>
|
||||
</additional_sources>
|
||||
</snippet>
|
||||
</customMathEquations>
|
||||
<snippets/>
|
||||
<!-- - - - - - - - - - - - - - - -->
|
||||
</root>
|
||||
|
||||
Reference in New Issue
Block a user