mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-18 10:23:43 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be63625fa8 |
@@ -2,4 +2,3 @@ Wen
|
|||||||
REGIST
|
REGIST
|
||||||
PullRequest
|
PullRequest
|
||||||
cancelled
|
cancelled
|
||||||
indeces
|
|
||||||
|
|||||||
@@ -18,6 +18,19 @@
|
|||||||
|
|
||||||
venv/
|
venv/
|
||||||
.venv/
|
.venv/
|
||||||
|
**/.idea
|
||||||
|
**/.hypothesis
|
||||||
|
**/.mypy_cache
|
||||||
|
|
||||||
|
**/.venv
|
||||||
|
**/.venv/
|
||||||
|
|
||||||
|
**/.ci_cache
|
||||||
|
**/*.rlog
|
||||||
|
|
||||||
|
**/Dockerfile*
|
||||||
|
**/dockerfile*
|
||||||
|
**/build_output
|
||||||
|
|
||||||
notebooks
|
notebooks
|
||||||
phone
|
phone
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
FROM sunnypilot-base
|
||||||
|
|
||||||
|
ARG RUNNER_DEBUG=0
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV OPENPILOT_SRC_PATH=/tmp/openpilot
|
||||||
|
ENV BUILD_DIR=/data/openpilot
|
||||||
|
ENV OUTPUT_DIR=/output
|
||||||
|
|
||||||
|
RUN sudo apt update && sudo apt install -y rsync
|
||||||
|
|
||||||
|
RUN mkdir -p ${OPENPILOT_SRC_PATH}
|
||||||
|
RUN mkdir -p ${BUILD_DIR}
|
||||||
|
COPY . ${OPENPILOT_SRC_PATH}
|
||||||
|
ENV PYTHONPATH=${BUILD_DIR}
|
||||||
|
|
||||||
|
WORKDIR ${OPENPILOT_SRC_PATH}
|
||||||
|
RUN ./tools/ubuntu_setup.sh
|
||||||
|
|
||||||
|
RUN ./release/release_files.py | sort | uniq | rsync -rRl${RUNNER_DEBUG:+v} --files-from=- . $BUILD_DIR/
|
||||||
|
WORKDIR ${BUILD_DIR}
|
||||||
|
RUN sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py
|
||||||
|
RUN scons --cache-readonly -j$(nproc) --minimal
|
||||||
|
RUN touch ${BUILD_DIR}/prebuilt
|
||||||
|
RUN sudo rm -rf ${OUTPUT_DIR}
|
||||||
|
RUN mkdir -p ${OUTPUT_DIR}
|
||||||
|
|
||||||
|
ENTRYPOINT [\
|
||||||
|
"rsync", \
|
||||||
|
"-am", \
|
||||||
|
"--include=**/panda/board/", \
|
||||||
|
"--include=**/panda/board/obj", \
|
||||||
|
"--include=**/panda/board/obj/panda.bin.signed", \
|
||||||
|
"--include=**/panda/board/obj/panda_h7.bin.signed", \
|
||||||
|
"--include=**/panda/board/obj/bootstub.panda.bin", \
|
||||||
|
"--include=**/panda/board/obj/bootstub.panda_h7.bin", \
|
||||||
|
"--exclude=.sconsign.dblite", \
|
||||||
|
"--exclude=*.a", \
|
||||||
|
"--exclude=*.o", \
|
||||||
|
"--exclude=*.os", \
|
||||||
|
"--exclude=*.pyc", \
|
||||||
|
"--exclude=moc_*", \
|
||||||
|
"--exclude=*.cc", \
|
||||||
|
"--exclude=Jenkinsfile", \
|
||||||
|
"--exclude=supercombo.onnx", \
|
||||||
|
"--exclude=**/panda/board/*", \
|
||||||
|
"--exclude=**/panda/board/obj/**", \
|
||||||
|
"--exclude=**/panda/certs/", \
|
||||||
|
"--exclude=**/panda/crypto/", \
|
||||||
|
"--exclude=**/release/", \
|
||||||
|
"--exclude=**/.github/", \
|
||||||
|
"--exclude=**/selfdrive/ui/replay/", \
|
||||||
|
"--exclude=**/__pycache__/", \
|
||||||
|
"--exclude=**/selfdrive/ui/*.h", \
|
||||||
|
"--exclude=**/selfdrive/ui/**/*.h", \
|
||||||
|
"--exclude=**/selfdrive/ui/qt/offroad/sunnypilot/", \
|
||||||
|
#"--exclude=${SCONS_CACHE_DIR:-}", \
|
||||||
|
"--exclude=**/.git/", \
|
||||||
|
"--exclude=**/SConstruct", \
|
||||||
|
"--exclude=**/SConscript", \
|
||||||
|
"--exclude=**/.venv/", \
|
||||||
|
"--delete-excluded", \
|
||||||
|
"--chown=1000:1000", \
|
||||||
|
"/data/openpilot/", \
|
||||||
|
"/output/" \
|
||||||
|
]
|
||||||
@@ -198,15 +198,4 @@ inline static std::unordered_map<std::string, uint32_t> keys = {
|
|||||||
{"OsmStateTitle", PERSISTENT},
|
{"OsmStateTitle", PERSISTENT},
|
||||||
{"OsmWayTest", PERSISTENT},
|
{"OsmWayTest", PERSISTENT},
|
||||||
{"RoadName", CLEAR_ON_ONROAD_TRANSITION},
|
{"RoadName", CLEAR_ON_ONROAD_TRANSITION},
|
||||||
|
|
||||||
// Tuning keys
|
|
||||||
{"EnableHkgTuningAngleSmoothingFactor", PERSISTENT | BACKUP},
|
|
||||||
{"HkgTuningAngleMinTorqueReductionGain", PERSISTENT | BACKUP},
|
|
||||||
{"HkgTuningAngleMaxTorqueReductionGain", PERSISTENT | BACKUP},
|
|
||||||
{"HkgTuningAngleActiveTorqueReductionGain", PERSISTENT | BACKUP},
|
|
||||||
{"HkgTuningOverridingCycles", PERSISTENT | BACKUP},
|
|
||||||
{"HkgAngleLiveTuning", CLEAR_ON_MANAGER_START},
|
|
||||||
|
|
||||||
{"AdasDrvEcuInterceptorEnabled", PERSISTENT | BACKUP}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
Submodule opendbc_repo updated: 3233a254de...c87940a6b5
+2
-1
@@ -59,7 +59,7 @@ dependencies = [
|
|||||||
"future-fstrings",
|
"future-fstrings",
|
||||||
|
|
||||||
# joystickd
|
# joystickd
|
||||||
"pygame",
|
"inputs",
|
||||||
|
|
||||||
# these should be removed
|
# these should be removed
|
||||||
"psutil",
|
"psutil",
|
||||||
@@ -110,6 +110,7 @@ dev = [
|
|||||||
"opencv-python-headless",
|
"opencv-python-headless",
|
||||||
"parameterized >=0.8, <0.9",
|
"parameterized >=0.8, <0.9",
|
||||||
"pyautogui",
|
"pyautogui",
|
||||||
|
"pygame",
|
||||||
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
|
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
|
||||||
"pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
|
"pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
|
||||||
"pywinctl",
|
"pywinctl",
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# run_openpilot_docker.sh
|
||||||
|
# POSIX-compliant script to run openpilot in Docker for local testing
|
||||||
|
|
||||||
|
# === Configurable Variables ===
|
||||||
|
|
||||||
|
# Base image to use (required)
|
||||||
|
BASE_IMAGE="${BASE_IMAGE:-commaai/openpilot-base:latest}"
|
||||||
|
|
||||||
|
# Working directory inside the container
|
||||||
|
WORKDIR="/tmp/openpilot"
|
||||||
|
|
||||||
|
# Local project path
|
||||||
|
LOCAL_DIR="$PWD"
|
||||||
|
|
||||||
|
# Shared memory size (adjust for large builds/tests)
|
||||||
|
SHM_SIZE="2G"
|
||||||
|
|
||||||
|
# Environment configuration
|
||||||
|
CI=1
|
||||||
|
PYTHONWARNINGS="error"
|
||||||
|
FILEREADER_CACHE=1
|
||||||
|
PYTHONPATH="$WORKDIR"
|
||||||
|
|
||||||
|
# Optional: GitHub Actions env vars — set them only if needed for local mirroring/debug
|
||||||
|
USE_GITHUB_ENV_VARS=false # set to true to enable GitHub-related mounts/envs
|
||||||
|
GITHUB_WORKSPACE="${GITHUB_WORKSPACE:-$HOME/openpilot_ci}" # fallback path
|
||||||
|
|
||||||
|
# === Docker Command ===
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--shm-size "$SHM_SIZE" \
|
||||||
|
-v "$LOCAL_DIR":"$WORKDIR" \
|
||||||
|
-w "$WORKDIR" \
|
||||||
|
-e CI="$CI" \
|
||||||
|
-e PYTHONWARNINGS="$PYTHONWARNINGS" \
|
||||||
|
-e FILEREADER_CACHE="$FILEREADER_CACHE" \
|
||||||
|
-e PYTHONPATH="$PYTHONPATH" \
|
||||||
|
${USE_GITHUB_ENV_VARS:+\
|
||||||
|
-e NUM_JOBS \
|
||||||
|
-e JOB_ID \
|
||||||
|
-e GITHUB_ACTION \
|
||||||
|
-e GITHUB_REF \
|
||||||
|
-e GITHUB_HEAD_REF \
|
||||||
|
-e GITHUB_SHA \
|
||||||
|
-e GITHUB_REPOSITORY \
|
||||||
|
-e GITHUB_RUN_ID \
|
||||||
|
-v "$GITHUB_WORKSPACE/.ci_cache/scons_cache":/tmp/scons_cache \
|
||||||
|
-v "$GITHUB_WORKSPACE/.ci_cache/comma_download_cache":/tmp/comma_download_cache \
|
||||||
|
-v "$GITHUB_WORKSPACE/.ci_cache/openpilot_cache":/tmp/openpilot_cache } \
|
||||||
|
"$BASE_IMAGE" /bin/bash -c "${1:-/bin/bash}"
|
||||||
@@ -13,7 +13,7 @@ cd $ROOT
|
|||||||
|
|
||||||
FAILED=0
|
FAILED=0
|
||||||
|
|
||||||
IGNORED_FILES="uv\.lock|docs\/CARS.md|LICENSE\.md|layouts\/.*\.xml"
|
IGNORED_FILES="uv\.lock|docs\/CARS.md|LICENSE\.md"
|
||||||
IGNORED_DIRS="^third_party.*|^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*"
|
IGNORED_DIRS="^third_party.*|^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*"
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ from openpilot.selfdrive.controls.lib.drive_helpers import clip_curvature
|
|||||||
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
|
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
|
||||||
from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID
|
from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID
|
||||||
from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle, STEER_ANGLE_SATURATION_THRESHOLD
|
from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle, STEER_ANGLE_SATURATION_THRESHOLD
|
||||||
from openpilot.selfdrive.controls.lib.latcontrol_angle_torque import LatControlAngleTorque
|
|
||||||
from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque
|
from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque
|
||||||
from openpilot.selfdrive.controls.lib.longcontrol import LongControl
|
from openpilot.selfdrive.controls.lib.longcontrol import LongControl
|
||||||
from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose
|
from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose
|
||||||
@@ -59,9 +58,7 @@ class Controls(ControlsExt):
|
|||||||
self.LoC = LongControl(self.CP)
|
self.LoC = LongControl(self.CP)
|
||||||
self.VM = VehicleModel(self.CP)
|
self.VM = VehicleModel(self.CP)
|
||||||
self.LaC: LatControl
|
self.LaC: LatControl
|
||||||
if self.CP.steerControlType == car.CarParams.SteerControlType.angle and self.CP.lateralTuning.which() == 'torque':
|
if self.CP.steerControlType == car.CarParams.SteerControlType.angle:
|
||||||
self.LaC = LatControlAngleTorque(self.CP, self.CP_SP, self.CI)
|
|
||||||
elif self.CP.steerControlType == car.CarParams.SteerControlType.angle:
|
|
||||||
self.LaC = LatControlAngle(self.CP, self.CP_SP, self.CI)
|
self.LaC = LatControlAngle(self.CP, self.CP_SP, self.CI)
|
||||||
elif self.CP.lateralTuning.which() == 'pid':
|
elif self.CP.lateralTuning.which() == 'pid':
|
||||||
self.LaC = LatControlPID(self.CP, self.CP_SP, self.CI)
|
self.LaC = LatControlPID(self.CP, self.CP_SP, self.CI)
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque
|
|
||||||
from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle
|
|
||||||
|
|
||||||
|
|
||||||
class LatControlAngleTorque(LatControlTorque, LatControlAngle):
|
|
||||||
def __init__(self, CP, CP_SP, CI):
|
|
||||||
LatControlTorque.__init__(self, CP, CP_SP, CI)
|
|
||||||
LatControlAngle.__init__(self, CP, CP_SP, CI)
|
|
||||||
|
|
||||||
def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited):
|
|
||||||
torque, _, _ = LatControlTorque.update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited)
|
|
||||||
_, angle, angle_log = LatControlAngle.update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited)
|
|
||||||
return torque, angle, angle_log
|
|
||||||
@@ -189,7 +189,7 @@ def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capn
|
|||||||
|
|
||||||
def get_custom_yrel(CP: structs.CarParams, CP_SP: structs.CarParamsSP, lead_dict: dict[str, Any],
|
def get_custom_yrel(CP: structs.CarParams, CP_SP: structs.CarParamsSP, lead_dict: dict[str, Any],
|
||||||
lead_msg: capnp._DynamicStructReader) -> dict[str, Any]:
|
lead_msg: capnp._DynamicStructReader) -> dict[str, Any]:
|
||||||
if CP.brand == "hyundai" and (CP_SP.flags & (HyundaiFlagsSP.ENHANCED_SCC | HyundaiFlagsSP.ADAS_ECU_INTERCEPTOR) or
|
if CP.brand == "hyundai" and (CP_SP.flags & HyundaiFlagsSP.ENHANCED_SCC or
|
||||||
CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)):
|
CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)):
|
||||||
lead_dict['yRel'] = float(-lead_msg.y[0])
|
lead_dict['yRel'] = float(-lead_msg.y[0])
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ lateral_panel_qt_src = [
|
|||||||
"sunnypilot/qt/offroad/settings/lateral/blinker_pause_lateral_settings.cc",
|
"sunnypilot/qt/offroad/settings/lateral/blinker_pause_lateral_settings.cc",
|
||||||
"sunnypilot/qt/offroad/settings/lateral/lane_change_settings.cc",
|
"sunnypilot/qt/offroad/settings/lateral/lane_change_settings.cc",
|
||||||
"sunnypilot/qt/offroad/settings/lateral/mads_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/neural_network_lateral_control.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
ParamControlSP* hkgAngleLiveTuning;
|
|
||||||
};
|
|
||||||
@@ -89,36 +89,6 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) {
|
|||||||
nnlcToggle->updateToggle();
|
nnlcToggle->updateToggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
toggleOffroadOnly = {
|
toggleOffroadOnly = {
|
||||||
madsToggle, nnlcToggle,
|
madsToggle, nnlcToggle,
|
||||||
};
|
};
|
||||||
@@ -129,7 +99,6 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) {
|
|||||||
|
|
||||||
main_layout->addWidget(sunnypilotScreen);
|
main_layout->addWidget(sunnypilotScreen);
|
||||||
main_layout->addWidget(madsWidget);
|
main_layout->addWidget(madsWidget);
|
||||||
main_layout->addWidget(angleTuningWidget);
|
|
||||||
main_layout->addWidget(laneChangeWidget);
|
main_layout->addWidget(laneChangeWidget);
|
||||||
|
|
||||||
setStyleSheet(R"(
|
setStyleSheet(R"(
|
||||||
@@ -180,7 +149,6 @@ void LateralPanel::updateToggles(bool _offroad) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
madsSettingsButton->setEnabled(madsToggle->isToggled());
|
madsSettingsButton->setEnabled(madsToggle->isToggled());
|
||||||
// angleTuningSettingsButton->setEnabled(angleTuningToggle->isToggled());
|
|
||||||
|
|
||||||
blinkerPauseLateralSettings->refresh();
|
blinkerPauseLateralSettings->refresh();
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "selfdrive/ui/sunnypilot/ui.h"
|
#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/blinker_pause_lateral_settings.h"
|
||||||
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_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/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/lane_change_settings.h"
|
||||||
#include "selfdrive/ui/qt/util.h"
|
#include "selfdrive/ui/qt/util.h"
|
||||||
@@ -40,11 +39,8 @@ private:
|
|||||||
bool offroad;
|
bool offroad;
|
||||||
|
|
||||||
ParamControl *madsToggle;
|
ParamControl *madsToggle;
|
||||||
// ParamControl *angleTuningToggle;
|
|
||||||
PushButtonSP *madsSettingsButton;
|
PushButtonSP *madsSettingsButton;
|
||||||
PushButtonSP *angleTuningSettingsButton;
|
|
||||||
MadsSettings *madsWidget = nullptr;
|
MadsSettings *madsWidget = nullptr;
|
||||||
AngleTunningSettings *angleTuningWidget = nullptr;
|
|
||||||
PushButtonSP *laneChangeSettingsButton;
|
PushButtonSP *laneChangeSettingsButton;
|
||||||
LaneChangeSettings *laneChangeWidget = nullptr;
|
LaneChangeSettings *laneChangeWidget = nullptr;
|
||||||
NeuralNetworkLateralControl *nnlcToggle = nullptr;
|
NeuralNetworkLateralControl *nnlcToggle = nullptr;
|
||||||
|
|||||||
@@ -68,13 +68,6 @@ def manager_init() -> None:
|
|||||||
("ModelManager_ModelsCache", ""),
|
("ModelManager_ModelsCache", ""),
|
||||||
("NeuralNetworkLateralControl", "0"),
|
("NeuralNetworkLateralControl", "0"),
|
||||||
("QuietMode", "0"),
|
("QuietMode", "0"),
|
||||||
("EnableHkgTuningAngleSmoothingFactor", "1"),
|
|
||||||
("HkgTuningAngleMinTorqueReductionGain", "10"),
|
|
||||||
("HkgTuningAngleActiveTorqueReductionGain", "60"),
|
|
||||||
("HkgTuningAngleMaxTorqueReductionGain", "100"),
|
|
||||||
("HkgTuningOverridingCycles", "17"),
|
|
||||||
("HkgAngleLiveTuning", "0"),
|
|
||||||
("AdasDrvEcuInterceptorEnabled", "0"),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# device boot mode
|
# device boot mode
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ procs = [
|
|||||||
|
|
||||||
PythonProcess("sensord", "system.sensord.sensord", only_onroad, enabled=not PC),
|
PythonProcess("sensord", "system.sensord.sensord", only_onroad, enabled=not PC),
|
||||||
NativeProcess("ui", "selfdrive/ui", ["./ui"], always_run, watchdog_max_dt=(5 if not PC else None)),
|
NativeProcess("ui", "selfdrive/ui", ["./ui"], always_run, watchdog_max_dt=(5 if not PC else None)),
|
||||||
PythonProcess("soundd", "selfdrive.ui.soundd", and_(only_onroad, not_joystick)),
|
PythonProcess("soundd", "selfdrive.ui.soundd", only_onroad),
|
||||||
PythonProcess("locationd", "selfdrive.locationd.locationd", only_onroad),
|
PythonProcess("locationd", "selfdrive.locationd.locationd", only_onroad),
|
||||||
NativeProcess("_pandad", "selfdrive/pandad", ["./pandad"], always_run, enabled=False),
|
NativeProcess("_pandad", "selfdrive/pandad", ["./pandad"], always_run, enabled=False),
|
||||||
PythonProcess("calibrationd", "selfdrive.locationd.calibrationd", only_onroad),
|
PythonProcess("calibrationd", "selfdrive.locationd.calibrationd", only_onroad),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,6 @@
|
|||||||
With joystick_control, you can connect your laptop to your comma device over the network and debug controls using a joystick or keyboard.
|
With joystick_control, you can connect your laptop to your comma device over the network and debug controls using a joystick or keyboard.
|
||||||
joystick_control uses [inputs](https://pypi.org/project/inputs) which supports many common gamepads and joysticks.
|
joystick_control uses [inputs](https://pypi.org/project/inputs) which supports many common gamepads and joysticks.
|
||||||
|
|
||||||
## Note
|
|
||||||
You might need to install [xow](https://github.com/medusalix/xow) to use the Xbox One controller on comma device.
|
|
||||||
Even though **xone** is recommended on the xow page, **xow** is the one that works with the comma device.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The car must be off, and openpilot must be offroad before starting `joystick_control`.
|
The car must be off, and openpilot must be offroad before starting `joystick_control`.
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ import os
|
|||||||
import argparse
|
import argparse
|
||||||
import threading
|
import threading
|
||||||
import numpy as np
|
import numpy as np
|
||||||
try:
|
from inputs import UnpluggedError, get_gamepad
|
||||||
import pygame as pg
|
|
||||||
except ImportError:
|
|
||||||
print("pygame is not installed. Please install it with 'uv pip install pygame'")
|
|
||||||
|
|
||||||
from cereal import messaging
|
from cereal import messaging
|
||||||
from openpilot.common.params import Params
|
from openpilot.common.params import Params
|
||||||
@@ -14,10 +11,7 @@ from openpilot.common.realtime import Ratekeeper
|
|||||||
from openpilot.system.hardware import HARDWARE
|
from openpilot.system.hardware import HARDWARE
|
||||||
from openpilot.tools.lib.kbhit import KBHit
|
from openpilot.tools.lib.kbhit import KBHit
|
||||||
|
|
||||||
# Set SDL environment variable to avoid using a video driver for headless operation
|
EXPO = 0.4
|
||||||
os.environ["SDL_VIDEODRIVER"] = "dummy"
|
|
||||||
|
|
||||||
EXPO = 0.4 # Exponential factor for joystick response curve
|
|
||||||
|
|
||||||
|
|
||||||
class Keyboard:
|
class Keyboard:
|
||||||
@@ -46,122 +40,60 @@ class Keyboard:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class PyGameJoystick:
|
class Joystick:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Initialize pygame and joystick subsystem
|
# This class supports a PlayStation 5 DualSense controller on the comma 3X
|
||||||
pg.init()
|
# TODO: find a way to get this from API or detect gamepad/PC, perhaps "inputs" doesn't support it
|
||||||
if not pg.joystick.get_init():
|
self.cancel_button = 'BTN_NORTH' # BTN_NORTH=X/triangle
|
||||||
pg.joystick.init()
|
|
||||||
|
|
||||||
# Find connected joysticks
|
|
||||||
joystick_count = pg.joystick.get_count()
|
|
||||||
if joystick_count == 0:
|
|
||||||
print("No joysticks found. Please connect a controller.")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
# Initialize the first joystick
|
|
||||||
self.joystick = pg.joystick.Joystick(0)
|
|
||||||
self.joystick.init()
|
|
||||||
|
|
||||||
print(f"Using joystick: {self.joystick.get_name()}")
|
|
||||||
print(f"Number of axes: {self.joystick.get_numaxes()}")
|
|
||||||
print(f"Number of buttons: {self.joystick.get_numbuttons()}")
|
|
||||||
print(f"Number of hats: {self.joystick.get_numhats()}")
|
|
||||||
|
|
||||||
# This supports PlayStation and Xbox controllers on different platforms
|
|
||||||
if HARDWARE.get_device_type() == 'pc':
|
if HARDWARE.get_device_type() == 'pc':
|
||||||
# Xbox mapping on PC
|
accel_axis = 'ABS_Z'
|
||||||
self.accel_axis = 5 # Right trigger
|
steer_axis = 'ABS_RX'
|
||||||
self.brake_axis = 4 # Left trigger
|
# TODO: once the longcontrol API is finalized, we can replace this with outputting gas/brake and steering
|
||||||
self.steer_axis = 0 # Left stick horizontal
|
self.flip_map = {'ABS_RZ': accel_axis}
|
||||||
self.cancel_button = 3 # Y/Triangle button
|
|
||||||
else:
|
else:
|
||||||
# PlayStation mapping on comma device
|
accel_axis = 'ABS_RX'
|
||||||
self.accel_axis = 5 # R2
|
steer_axis = 'ABS_Z'
|
||||||
self.brake_axis = 4 # L2
|
self.flip_map = {'ABS_RY': accel_axis}
|
||||||
self.steer_axis = 0 # Left stick horizontal
|
|
||||||
self.cancel_button = 3 # Triangle button
|
|
||||||
|
|
||||||
# Configure for adaptive mappings based on detected controller
|
self.min_axis_value = {accel_axis: 0., steer_axis: 0.}
|
||||||
controller_name = self.joystick.get_name().lower()
|
self.max_axis_value = {accel_axis: 255., steer_axis: 255.}
|
||||||
if "xbox" in controller_name:
|
self.axes_values = {accel_axis: 0., steer_axis: 0.}
|
||||||
print("Xbox controller detected, using Xbox mappings")
|
self.axes_order = [accel_axis, steer_axis]
|
||||||
self.accel_axis = 5 # Right trigger (RT)
|
|
||||||
self.brake_axis = 4 # Left trigger (LT)
|
|
||||||
self.cancel_button = 3 # Y button
|
|
||||||
elif "playstation" in controller_name or "dual" in controller_name:
|
|
||||||
print("PlayStation controller detected, using PlayStation mappings")
|
|
||||||
self.accel_axis = 5 # R2
|
|
||||||
self.brake_axis = 4 # L2
|
|
||||||
self.cancel_button = 3 # Triangle
|
|
||||||
|
|
||||||
# Initialize values
|
|
||||||
self.axes_values = {'gb': 0., 'steer': 0.} # Maintain same keys as Keyboard class
|
|
||||||
self.axes_order = ['gb', 'steer'] # Match expected format
|
|
||||||
self.cancel = False
|
self.cancel = False
|
||||||
self.deadzone = 0.03 # 3% deadzone for noisy joysticks
|
|
||||||
|
|
||||||
# Process events once to clear the event queue
|
|
||||||
pg.event.pump()
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
# Process pygame events
|
|
||||||
try:
|
try:
|
||||||
for event in pg.event.get():
|
joystick_event = get_gamepad()[0]
|
||||||
if event.type == pg.JOYDEVICEREMOVED:
|
except (OSError, UnpluggedError):
|
||||||
if event.instance_id == self.joystick.get_instance_id():
|
self.axes_values = dict.fromkeys(self.axes_values, 0.)
|
||||||
print("Joystick disconnected!")
|
|
||||||
self.axes_values = {'gb': 0., 'steer': 0.}
|
|
||||||
return False
|
|
||||||
|
|
||||||
elif event.type == pg.JOYBUTTONDOWN:
|
|
||||||
if event.button == self.cancel_button:
|
|
||||||
self.cancel = True
|
|
||||||
|
|
||||||
elif event.type == pg.JOYBUTTONUP:
|
|
||||||
if event.button == self.cancel_button:
|
|
||||||
self.cancel = False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error processing events: {e}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Read current joystick state directly
|
event = (joystick_event.code, joystick_event.state)
|
||||||
try:
|
|
||||||
if not self.joystick.get_init():
|
|
||||||
print("Joystick not initialized")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Read steering (left stick horizontal)
|
# flip left trigger to negative accel
|
||||||
steer_raw = self.joystick.get_axis(self.steer_axis) * -1
|
if event[0] in self.flip_map:
|
||||||
steer = steer_raw if abs(steer_raw) > self.deadzone else 0.0
|
event = (self.flip_map[event[0]], -event[1])
|
||||||
|
|
||||||
# Read gas (right trigger)
|
if event[0] == self.cancel_button:
|
||||||
accel_raw = self.joystick.get_axis(self.accel_axis)
|
if event[1] == 1:
|
||||||
# Convert from [-1, 1] to [0, 1] range (triggers often start at -1 when not pressed)
|
self.cancel = True
|
||||||
accel = (accel_raw + 1) / 2 if self.accel_axis in [4, 5] else accel_raw
|
elif event[1] == 0: # state 0 is falling edge
|
||||||
accel = accel if accel > self.deadzone else 0.0
|
self.cancel = False
|
||||||
|
elif event[0] in self.axes_values:
|
||||||
|
self.max_axis_value[event[0]] = max(event[1], self.max_axis_value[event[0]])
|
||||||
|
self.min_axis_value[event[0]] = min(event[1], self.min_axis_value[event[0]])
|
||||||
|
|
||||||
# Read brake (left trigger)
|
norm = -float(np.interp(event[1], [self.min_axis_value[event[0]], self.max_axis_value[event[0]]], [-1., 1.]))
|
||||||
brake_raw = self.joystick.get_axis(self.brake_axis)
|
norm = norm if abs(norm) > 0.03 else 0. # center can be noisy, deadzone of 3%
|
||||||
# Convert from [-1, 1] to [0, 1] range (triggers often start at -1 when not pressed)
|
self.axes_values[event[0]] = EXPO * norm ** 3 + (1 - EXPO) * norm # less action near center for fine control
|
||||||
brake = (brake_raw + 1) / 2 if self.brake_axis in [4, 5] else brake_raw
|
else:
|
||||||
brake = brake if brake > self.deadzone else 0.0
|
|
||||||
|
|
||||||
# Apply expo for steering
|
|
||||||
self.axes_values['steer'] = EXPO * steer**3 + (1 - EXPO) * steer # Apply expo for fine control
|
|
||||||
|
|
||||||
# Calculate combined gas/brake value for output [-1, 1] where negative is brake
|
|
||||||
self.axes_values['gb'] = accel - brake
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error reading joystick: {e}")
|
|
||||||
self.axes_values = {'gb': 0., 'steer': 0.}
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def send_thread(joystick):
|
def send_thread(joystick):
|
||||||
pm = messaging.PubMaster(['testJoystick'])
|
pm = messaging.PubMaster(['testJoystick'])
|
||||||
|
|
||||||
rk = Ratekeeper(100, print_delay_threshold=None)
|
rk = Ratekeeper(100, print_delay_threshold=None)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -173,6 +105,7 @@ def send_thread(joystick):
|
|||||||
joystick_msg.testJoystick.axes = [joystick.axes_values[ax] for ax in joystick.axes_order]
|
joystick_msg.testJoystick.axes = [joystick.axes_values[ax] for ax in joystick.axes_order]
|
||||||
|
|
||||||
pm.send('testJoystick', joystick_msg)
|
pm.send('testJoystick', joystick_msg)
|
||||||
|
|
||||||
rk.keep_time()
|
rk.keep_time()
|
||||||
|
|
||||||
|
|
||||||
@@ -184,12 +117,13 @@ def joystick_control_thread(joystick):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
joystick_control_thread(PyGameJoystick())
|
joystick_control_thread(Joystick())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='Publishes events from your joystick to control your car.\n' +
|
parser = argparse.ArgumentParser(description='Publishes events from your joystick to control your car.\n' +
|
||||||
'openpilot must be offroad before starting joystick_control. This tool supports ' +
|
'openpilot must be offroad before starting joystick_control. This tool supports ' +
|
||||||
'PlayStation and Xbox controllers on various platforms.',
|
'a PlayStation 5 DualSense controller on the comma 3X.',
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
parser.add_argument('--keyboard', action='store_true', help='Use your keyboard instead of a joystick')
|
parser.add_argument('--keyboard', action='store_true', help='Use your keyboard instead of a joystick')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@@ -205,12 +139,9 @@ if __name__ == '__main__':
|
|||||||
print('Buttons')
|
print('Buttons')
|
||||||
print('- `R`: Resets axes')
|
print('- `R`: Resets axes')
|
||||||
print('- `C`: Cancel cruise control')
|
print('- `C`: Cancel cruise control')
|
||||||
joystick_control_thread(Keyboard())
|
|
||||||
else:
|
else:
|
||||||
print('Using pygame joystick')
|
print('Using joystick, make sure to run cereal/messaging/bridge on your device if running over the network!')
|
||||||
print('Standard controller mapping:')
|
print('If not running on a comma device, the mapping may need to be adjusted.')
|
||||||
print('- Left stick: Steering')
|
|
||||||
print('- Right trigger (R2): Gas')
|
joystick = Keyboard() if args.keyboard else Joystick()
|
||||||
print('- Left trigger (L2): Brake')
|
joystick_control_thread(joystick)
|
||||||
print('- Triangle/Y button: Cancel')
|
|
||||||
joystick_control_thread(PyGameJoystick())
|
|
||||||
|
|||||||
@@ -19,24 +19,18 @@ def joystickd_thread():
|
|||||||
CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)
|
CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)
|
||||||
VM = VehicleModel(CP)
|
VM = VehicleModel(CP)
|
||||||
|
|
||||||
sm = messaging.SubMaster(['carState', 'onroadEvents', 'liveParameters', 'selfdriveState', 'testJoystick', 'selfdriveStateSP'], frequency=1. / DT_CTRL)
|
sm = messaging.SubMaster(['carState', 'onroadEvents', 'liveParameters', 'selfdriveState', 'testJoystick'], frequency=1. / DT_CTRL)
|
||||||
pm = messaging.PubMaster(['carControl', 'controlsState'])
|
pm = messaging.PubMaster(['carControl', 'controlsState'])
|
||||||
|
|
||||||
rk = Ratekeeper(100, print_delay_threshold=None)
|
rk = Ratekeeper(100, print_delay_threshold=None)
|
||||||
while 1:
|
while 1:
|
||||||
sm.update(0)
|
sm.update(0)
|
||||||
ss_sp = sm['selfdriveStateSP']
|
|
||||||
_lat_active = False
|
|
||||||
if ss_sp.mads.available:
|
|
||||||
_lat_active = ss_sp.mads.active
|
|
||||||
else:
|
|
||||||
_lat_active = sm['selfdriveState'].active
|
|
||||||
|
|
||||||
cc_msg = messaging.new_message('carControl')
|
cc_msg = messaging.new_message('carControl')
|
||||||
cc_msg.valid = True
|
cc_msg.valid = True
|
||||||
CC = cc_msg.carControl
|
CC = cc_msg.carControl
|
||||||
CC.enabled = sm['selfdriveState'].enabled
|
CC.enabled = sm['selfdriveState'].enabled
|
||||||
CC.latActive = _lat_active and not sm['carState'].steerFaultTemporary and not sm['carState'].steerFaultPermanent
|
CC.latActive = sm['selfdriveState'].active and not sm['carState'].steerFaultTemporary and not sm['carState'].steerFaultPermanent
|
||||||
CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in sm['onroadEvents']) and CP.openpilotLongitudinalControl
|
CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in sm['onroadEvents']) and CP.openpilotLongitudinalControl
|
||||||
CC.cruiseControl.cancel = sm['carState'].cruiseState.enabled and (not CC.enabled or not CP.pcmCruise)
|
CC.cruiseControl.cancel = sm['carState'].cruiseState.enabled and (not CC.enabled or not CP.pcmCruise)
|
||||||
CC.hudControl.leadDistanceBars = 2
|
CC.hudControl.leadDistanceBars = 2
|
||||||
|
|||||||
@@ -1,131 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<root>
|
|
||||||
<tabbed_widget parent="main_window" name="Main Window">
|
|
||||||
<Tab tab_name="actuator data" containers="1">
|
|
||||||
<Container>
|
|
||||||
<DockSplitter sizes="0.25;0.25;0.25;0.25" count="4" orientation="-">
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-1.050000" top="1.050000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#17becf" name="/carControl/actuators/torque"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-385.132391" top="536.899115" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1f77b4" name="/carControl/actuators/steeringAngleDeg"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-0.364800" top="14.956815" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#ff7f0e" name="/carState/vEgoRaw"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-0.208517" top="0.149191" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#f14cc1" name="/carControl/actuators/curvature"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
</DockSplitter>
|
|
||||||
</Container>
|
|
||||||
</Tab>
|
|
||||||
<Tab tab_name="steering messages (CAN)" containers="1">
|
|
||||||
<Container>
|
|
||||||
<DockSplitter sizes="0.200218;0.200218;0.199129;0.200218;0.200218" count="5" orientation="-">
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-189.000000" top="189.000000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1ac938" name="/can/2/LKAS_ALT/LKAS_ANGLE_CMD"/>
|
|
||||||
<curve color="#9467bd" name="/can/128/LKAS_ALT/LKAS_ANGLE_CMD"/>
|
|
||||||
<curve color="#ff0e1c" name="/can/192/LKAS_ALT/LKAS_ANGLE_CMD"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-6.200000" top="254.200000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#f14cc1" name="/can/128/LKAS_ALT/LKAS_ANGLE_MAX_TORQUE"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-0.025000" top="1.025000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#d62728" name="/carState/steeringPressed"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="460.325000" top="1874.675000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1f77b4" name="/pandaStates/0/safetyTxBlocked"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-0.025000" top="1.025000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#f14cc1" name="/can/1/CCNC_0x161/DAW_ICON"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
</DockSplitter>
|
|
||||||
</Container>
|
|
||||||
</Tab>
|
|
||||||
<Tab tab_name="Understanding Torque" containers="1">
|
|
||||||
<Container>
|
|
||||||
<DockSplitter sizes="0.5;0.5" count="2" orientation="-">
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-6.175000" top="253.175000" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1f77b4" name="/can/1/LFA_ALT/LKAS_ANGLE_MAX_TORQUE"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot flip_x="false" flip_y="false" style="Lines" mode="TimeSeries">
|
|
||||||
<range bottom="-41.182501" top="42.082498" right="590.696728" left="429.901019"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1ac938" name="/carState/steeringTorqueEps"/>
|
|
||||||
</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/>
|
|
||||||
<snippets/>
|
|
||||||
<!-- - - - - - - - - - - - - - - -->
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<root>
|
|
||||||
<tabbed_widget parent="main_window" name="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 bottom="-1.050000" top="1.050000" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#17becf" name="/carControl/actuators/torque"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-453.043646" top="538.555487" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1f77b4" name="/carControl/actuators/steeringAngleDeg"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-0.647461" top="26.545898" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#ff7f0e" name="/carState/vEgoRaw"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-0.209157" top="0.175448" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#f14cc1" name="/carControl/actuators/curvature"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
</DockSplitter>
|
|
||||||
</Container>
|
|
||||||
</Tab>
|
|
||||||
<Tab tab_name="steering messages (CAN)" 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 bottom="-189.000000" top="189.000000" right="723.115449" left="6.371879"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#b6ff00" name="/can/128/LKAS_ALT/LKAS_ANGLE_CMD"/>
|
|
||||||
<curve color="#00fab2" name="/can/0/LKAS_ALT/LKAS_ANGLE_CMD"/>
|
|
||||||
<curve color="#d62728" name="/can/192/LKAS_ALT/LKAS_ANGLE_CMD"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-6.250000" top="256.250000" right="722.420439" left="6.497277"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#00ffe8" name="/can/128/LKAS_ALT/LKAS_ANGLE_MAX_TORQUE"/>
|
|
||||||
<curve color="#e5fd00" name="/can/0/LKAS_ALT/LKAS_ANGLE_MAX_TORQUE"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-4.399729" top="4.056632" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#ff7f0e" name="IMU_LatAccelVal_ms^2_roll_compensated"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-0.025000" top="1.025000" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#d62728" name="/carState/steeringPressed"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-0.025000" top="1.025000" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#f14cc1" name="/can/1/CCNC_0x161/DAW_ICON"/>
|
|
||||||
</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 bottom="-6.250000" top="256.250000" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1f77b4" name="/can/1/LFA_ALT/LKAS_ANGLE_MAX_TORQUE"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
<DockArea name="...">
|
|
||||||
<plot style="Lines" mode="TimeSeries" flip_x="false" flip_y="false">
|
|
||||||
<range bottom="-42.062501" top="78.162503" right="722.420439" left="0.000000"/>
|
|
||||||
<limitY/>
|
|
||||||
<curve color="#1ac938" name="/carState/steeringTorqueEps"/>
|
|
||||||
</plot>
|
|
||||||
</DockArea>
|
|
||||||
</DockSplitter>
|
|
||||||
</Container>
|
|
||||||
</Tab>
|
|
||||||
<currentTabIndex index="1"/>
|
|
||||||
</tabbed_widget>
|
|
||||||
<use_relative_time_offset enabled="1"/>
|
|
||||||
<!-- - - - - - - - - - - - - - - -->
|
|
||||||
<!-- - - - - - - - - - - - - - - -->
|
|
||||||
<Plugins>
|
|
||||||
<plugin ID="DataLoad CSV">
|
|
||||||
<default delimiter="0" time_axis=""/>
|
|
||||||
</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="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>
|
|
||||||
<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^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">
|
|
||||||
<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="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>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>
|
|
||||||
</customMathEquations>
|
|
||||||
<snippets/>
|
|
||||||
<!-- - - - - - - - - - - - - - - -->
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
<?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>
|
|
||||||
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
<?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