Compare commits

..

2 Commits

Author SHA1 Message Date
Your Name
cb7eda64d9 wip 2024-05-20 22:17:59 -05:00
Your Name
037b08dd0d wip 2024-05-18 08:42:15 -05:00
8 changed files with 168 additions and 206 deletions

View File

@@ -1,5 +1,20 @@
-----
Latest:
- fix hiding path if disabled
- fix suspend on override behavior - override doesnt happen on always on lateral. need alternative check.
- fix & test lane line narrow on lane change view
- the acc cancel does nothing.
- must simulate actual button presses.
- add radar dist, model dist, radar speed, model speed to debug hud
- add wheel touched, wheel override to hud
- fix always on lateral saying its on when actually fully engaged
Notes on speed limit override:
- we need to capture the original speed and feed it to vtsc and model whule we
are under speed adjustment
------
- fix lane lines
- fix always on lateral detection
- position override under 25 mph suspends assist

View File

@@ -1,3 +1,5 @@
Actual log:
- Pause lateral on lane change
- Updated color scheme
- Updated boot / ready logo
@@ -7,4 +9,121 @@
- Removed nearly everything from onroad ui
- Monitor never fully fatals
- Engage / Disengage sounds silenced
- Removed all 'prime' functionality including map features
- Removed all 'Prime' functionality including "Navigate on Openpilot"
Goal, to be able to say:
ClearPilot
-----------------
ClearPilot is a simplified, enhanced, and opinionated modification of OpenPilot
with a focus on a consistency, privacy, and ease of use. The self driving
behaviors compared to OpenPilot have been reduced and simplified to focus on lane keep assistance,
and to disengage more gracefully on operator override behaviors such as highway lane change or
turning at an intersection. It features a redesigned and customized user interface,
a dashcam module with a frontend for reviewing dashcam footage, and tools for managing
device data via wifi or a self hosted web control panel.
ClearPilot aims to provide a consistent, private, and permanent user experience. Feature updates
will not change or remove existing configured features, or de-select or remove older driving models.
The requirement to be online and periodically check for updates has also been removed - you can install
the software once, and never have to update it or go online again.
-------------------
ClearPilot is based on FrogPilot (link), and has been forked from the "May 1st, 2024 Update for FrogPilot
v0.9.7", which itself is based off of "Feb 27th, 2024 OpenPilot 0.9.6" release. It is designed
for use with Comma 3 / 3X and is not compatable with Comma 2 or older.
ClearPilot is open source software and comes with no guaranteel of mercantability or fitness of any kind.
ClearPilot has some features which may violate local laws or guidelines, or Comma OpenPilot developer
safety guidelines, particularly as it relates to driver monitoring. It is your responsibility to ensure
that the software you run is allowed by local reguilations.
It is your responsibility to test the software in a zero traffic environment to evaluate and understand it's behaviors and limitations,
and to validate it is sutable and for your usage. You are responsible for what your Comma device and veichele
does at all times.
The software was provided as is, without any guarantee or promise that it is able to perform any task at all with
or without issue, and useof the software is at your descression and your own risk. (reword)
We need testers! If you would like to help make your car fully compatable with ClearPilot, please
contact the author at xyz.
-------------------------------
Full Feature Set:
Driving:
- Drastically simplified minimal user interface, with a focus on ease of use for non power users.
- Ability to use a car's stock radar / cruise control functionality, while emulating clicks
on the accel + decel buttons to slow down for detected curves. This is for veicheles which
don't support OpenPilot Longitudial Control, or for users who prefer their veicheles stock
radar cruise control feature over OpenPilot Longitudial Control.
- Special support for some specific HKG and Jeep Veichles
- Speed limit control feature - when over or under speed limit, the system prompts
for you to increase or decrease speed to ideal cruising speed.
- Feature to disable lane keep assistance when making a turn at an intersection or lane change on the
freeway. The standard OpenPilot lane change assistance feature is still available.
- Feature to use paddle shifter button to execute a nudgeless assisted lane change at highway speeds.
- Custom trip recording and dashcam module and playback feature.
- Feature to turn off the screen display via steering wheel button.
- Toggle to show camera feed as monochrome for enhanced ui contrast.
- Feature to relax relax driver monitoring requirements & timeouts 50% never / at night / always.
- Feature to enhance driver engagement by requiring hands on wheel never / at night / always.
- Ability to create a second driver profile with settings menu pin lockout which can have
alternative requirements for driver safety, such as requiring hands on the wheel at all times,
or a maximum amount cruise control speed can be set over the posted speed limit.
- Warning when traffic in the distance is dected to be significantly slower than current speed.
- Ability to set a custom startup logo and customize some aspects of the user experience.
- All telemetry, features, and connectivity related to Comma.AI / Comma Prime removed.
- Requirement to get online to update your software every few weeks removed. Checking for a
new version of the software is only done by user request or by enabling automatic update
checks.
- Ability to set wifi networks as prefered or bandwidth limited. If connected to a bandwidth
limited wifi network and a prefered network becomes available, the system will switch to the
prefered network.
- Various automations for other car features on supported veicheles, such as automatic window
roll up and automatically enable HVAC on startup.
- Wifi accessible control panel for for managing device data including dashcam recordings.
- Available self hosted companion application for backing up and managing device data remotly for
power users. You will be able to host your own ClearPilot installer to ensure you permanently
have a copy of the software for your own use.
- Basic Home Assistant integration.
Full documentation for ClearPilot and each of these features is available (here.)
Hidden features, enable by shell:
- Temporarirly suspend monitoring feature. This mode is canceled whenever a sharp
curve is detected, a lead veichele is detected, or lane line detection is weak.
This feature is disabled by default and must me enabled by modifying a file on
- If ClearPilot disengages due to driver monitoring detection issue, it will allow
re-engagement or driver assistance without a system restart.

View File

@@ -21,21 +21,21 @@ const SteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = {
const CanMsg HYUNDAI_CANFD_HDA2_TX_MSGS[] = {
{0x50, 0, 16}, // LKAS
{0x1CF, 1, 8}, // CRUISE_BUTTON
{426, 1, 16}, // CRUISE_BUTTONS_ALT
{0x1AA, 1, 16}, // CRUISE_BUTTONS_ALT
{0x2A4, 0, 24}, // CAM_0x2A4
};
const CanMsg HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS[] = {
{0x110, 0, 32}, // LKAS_ALT
{0x1CF, 1, 8}, // CRUISE_BUTTON
{426, 1, 16}, // CRUISE_BUTTONS_ALT
{0x1AA, 1, 16}, // CRUISE_BUTTONS_ALT
{0x362, 0, 32}, // CAM_0x362
};
const CanMsg HYUNDAI_CANFD_HDA2_LONG_TX_MSGS[] = {
{0x50, 0, 16}, // LKAS
{0x1CF, 1, 8}, // CRUISE_BUTTON
{426, 1, 16}, // CRUISE_BUTTONS_ALT
{0x1AA, 1, 16}, // CRUISE_BUTTONS_ALT
{0x2A4, 0, 24}, // CAM_0x2A4
{0x51, 0, 32}, // ADRV_0x51
{0x730, 1, 8}, // tester present for ADAS ECU disable
@@ -73,8 +73,8 @@ const CanMsg HYUNDAI_CANFD_HDA1_TX_MSGS[] = {
#define HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(pt_bus) \
{.msg = {{0x1aa, (pt_bus), 16, .check_checksum = false, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
#define HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(pt_bus) \
{.msg = {{0x1aa, (pt_bus), 16, .check_checksum = false, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
// #define HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(pt_bus) \
// {.msg = {{0x1aa, (pt_bus), 16, .check_checksum = false, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
// SCC_CONTROL (from ADAS unit or camera)
#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \

View File

@@ -132,7 +132,10 @@ class CarController(CarControllerBase):
can_sends.extend(hyundaicanfd.create_spas_messages(self.packer, self.CAN, self.frame, CC.leftBlinker, CC.rightBlinker))
# params_memory = Params("/dev/shm/params")
# if params_memory.get_bool("CPTLkasButtonAction"):
if params_memory.get_bool("CPTLkasButtonAction"):
if self.frame % 10 == 0:
for _ in range(20):
can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.SET_DECEL))
# can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
# can_sends.append(hyundaicanfd.create_acc_set_speed(self.packer, self.CP, self.CAN, CS.cruise_info, 50))
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
@@ -197,7 +200,6 @@ class CarController(CarControllerBase):
can_sends = []
if use_clu11:
if CC.cruiseControl.cancel:
print("Cancel button go")
can_sends.append(hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.CANCEL, self.CP))
CS.lkas_trigger_result = 5
elif CC.cruiseControl.resume:
@@ -210,17 +212,18 @@ class CarController(CarControllerBase):
else:
if (self.frame - self.last_button_frame) * DT_CTRL > 0.25:
params_memory = Params("/dev/shm/params")
if params_memory.get_bool("CPTLkasButtonAction"):
params_memory.put_bool("CPTLkasButtonAction", False)
CC.cruiseControl.cancel = True
print("Debug cancel executed")
# if params_memory.get_bool("CPTLkasButtonAction"):
# params_memory.put_bool("CPTLkasButtonAction", False)
# CC.cruiseControl.cancel = True
# print("Debug cancel executed")
# cruise cancel
if CC.cruiseControl.cancel:
if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
# pass
can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
# can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.CANCEL))
print("Yes2")
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
for _ in range(20):
can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.CANCEL))
print("Try Cancel Button Alt")
self.last_button_frame = self.frame
CS.lkas_trigger_result = 1
else:

View File

@@ -673,9 +673,9 @@ class Controls:
if model_v2.meta.laneChangeState == LaneChangeState.laneChangeStarting and clearpilot_disable_lat_on_lane_change:
CC.latActive = False
self.params_memory.put_int("no_lat_lane_change", 1)
self.params_memory.put_bool("no_lat_lane_change", True)
else:
self.params_memory.put_int("no_lat_lane_change", 0)
self.params_memory.put_bool("no_lat_lane_change", False)
if CS.leftBlinker or CS.rightBlinker:
self.last_blinker_frame = self.sm.frame

View File

@@ -75,7 +75,7 @@ void OnroadWindow::updateState(const UIState &s) {
nvg->updateState(s);
QColor bgColor = bg_colors[s.status];
if (paramsMemory.getInt("no_lat_lane_change") == 1) {
if (paramsMemory.getBool("no_lat_lane_change") == 1) {
bgColor = bg_colors[STATUS_DISENGAGED];
}
@@ -355,9 +355,6 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* par
top_right_layout->setSpacing(0);
top_right_layout->addLayout(buttons_layout);
pedal_icons = new PedalIcons(this);
// top_right_layout->addWidget(pedal_icons, 0, Qt::AlignRight);
main_layout->addLayout(top_right_layout, 0);
main_layout->setAlignment(top_right_layout, Qt::AlignTop | Qt::AlignRight);
@@ -530,13 +527,13 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
// }
// }
void AnnotatedCameraWidget::drawSpeedWidget(QPainter &p, int x, int y, const QString &title, const QString &speedLimitStr, QColor colorSpeed) {
void AnnotatedCameraWidget::drawSpeedWidget(QPainter &p, int x, int y, const QString &title, const QString &speedLimitStr, QColor colorSpeed, int width = 176) {
// Draw outer box + border to contain set speed and speed limit
const int sign_margin = 12;
const int us_sign_height = 186;
const int eu_sign_size = 176;
const int eu_sign_size = width;
const QSize default_size = {172, 204};
const QSize default_size = {width, 204};
QSize set_speed_size = default_size;
if (is_metric || has_eu_speed_limit) set_speed_size.rwidth() = 200;
if (has_us_speed_limit && speedLimitStr.size() >= 3) set_speed_size.rwidth() = 223;
@@ -560,9 +557,9 @@ void AnnotatedCameraWidget::drawSpeedWidget(QPainter &p, int x, int y, const QSt
p.setFont(InterFont(90, QFont::Bold));
p.setPen(colorSpeed);
p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, speedLimitStr);
}
void AnnotatedCameraWidget::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
QRect real_rect = p.fontMetrics().boundingRect(text);
real_rect.moveCenter({x, y - real_rect.height() / 2});
@@ -622,19 +619,19 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
// paint center lane path
// QColor bg_colors[CHANGE_LANE_PATH_COLOR];
// int is_no_lat_lane_change = paramsMemory.getInt("no_lat_lane_change");
bool is_no_lat_lane_change = paramsMemory.getBool("no_lat_lane_change");
QColor center_lane_color;
// if (is_no_lat_lane_change) {
// center_lane_color = bg_colors[CHANGE_LANE_PATH_COLOR];
// } else {
if (is_no_lat_lane_change) {
center_lane_color = bg_colors[CHANGE_LANE_PATH_COLOR];
} else {
center_lane_color = bg_colors[CENTER_LANE_COLOR];
// }
}
QLinearGradient path_gradient(0, height(), 0, 0);
// if (edgeColor != bg_colors[STATUS_DISENGAGED] || is_no_lat_lane_change) {
if (edgeColor != bg_colors[STATUS_DISENGAGED] || is_no_lat_lane_change) {
if (scene.acceleration_path) {
// The first half of track_vertices are the points for the right side of the path
// and the indices match the positions of accel from uiPlan
@@ -684,7 +681,7 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
painter.setBrush(path_gradient);
painter.drawPolygon(scene.track_vertices);
// }
}
// Paint path edges ,Use current background color
if (edgeColor != bg_colors[STATUS_DISENGAGED]) {
@@ -924,8 +921,6 @@ void AnnotatedCameraWidget::showEvent(QShowEvent *event) {
void AnnotatedCameraWidget::initializeFrogPilotWidgets() {
bottom_layout = new QHBoxLayout();
distance_btn = new DistanceButton(this);
// bottom_layout->addWidget(distance_btn);
// QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
// bottom_layout->addItem(spacer);
@@ -983,8 +978,6 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets() {
obstacleDistance = scene.obstacle_distance;
obstacleDistanceStock = scene.obstacle_distance_stock;
onroadDistanceButton = scene.onroad_distance_button;
roadNameUI = scene.road_name_ui;
speedLimitController = scene.speed_limit_controller;
@@ -1042,91 +1035,10 @@ void AnnotatedCameraWidget::paintFrogPilotWidgets(QPainter &p) {
drawSLCConfirmation(p);
}
// bool enableDistanceButton = onroadDistanceButton && !hideBottomIcons;
// distance_btn->setVisible(enableDistanceButton);
// if (enableDistanceButton) {
// distance_btn->updateState();
// bottom_layout->setAlignment(distance_btn, (rightHandDM ? Qt::AlignRight : Qt::AlignLeft));
// }
// bool enablePedalIcons = scene.pedals_on_ui && !bigMapOpen;
// pedal_icons->setVisible(enablePedalIcons);
// if (enablePedalIcons) {
// pedal_icons->updateState();
// }
// recorder_btn->setVisible(scene.screen_recorder && !mapOpen);
recorder_btn->setVisible(false);
}
DistanceButton::DistanceButton(QWidget *parent) : QPushButton(parent), scene(uiState()->scene) {
// setFixedSize(btn_size * 1.5, btn_size * 1.5);
// profile_data = {
// {QPixmap("../frogpilot/assets/other_images/traffic.png"), "Traffic"},
// {QPixmap("../frogpilot/assets/other_images/aggressive.png"), "Aggressive"},
// {QPixmap("../frogpilot/assets/other_images/standard.png"), "Standard"},
// {QPixmap("../frogpilot/assets/other_images/relaxed.png"), "Relaxed"}
// };
// profile_data_kaofui = {
// {QPixmap("../frogpilot/assets/other_images/traffic_kaofui.png"), "Traffic"},
// {QPixmap("../frogpilot/assets/other_images/aggressive_kaofui.png"), "Aggressive"},
// {QPixmap("../frogpilot/assets/other_images/standard_kaofui.png"), "Standard"},
// {QPixmap("../frogpilot/assets/other_images/relaxed_kaofui.png"), "Relaxed"}
// };
// transitionTimer.start();
// connect(this, &QPushButton::pressed, this, &DistanceButton::buttonPressed);
// connect(this, &QPushButton::released, this, &DistanceButton::buttonReleased);
}
void DistanceButton::buttonPressed() {
// paramsMemory.putBool("OnroadDistanceButtonPressed", true);
}
void DistanceButton::buttonReleased() {
// paramsMemory.putBool("OnroadDistanceButtonPressed", false);
}
void DistanceButton::updateState() {
// if (trafficModeActive != scene.traffic_mode_active || personality != static_cast<int>(scene.personality) && !trafficModeActive) {
// transitionTimer.restart();
// }
// personality = static_cast<int>(scene.personality);
trafficModeActive = scene.traffic_mode_active;
}
void DistanceButton::paintEvent(QPaintEvent *event) {
// QPainter p(this);
// p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
// constexpr qreal fadeDuration = 1000.0;
// constexpr qreal textDuration = 3000.0;
// int elapsed = transitionTimer.elapsed();
// qreal textOpacity = qBound(0.0, 1.0 - ((elapsed - textDuration) / fadeDuration), 1.0);
// qreal imageOpacity = qBound(0.0, (elapsed - textDuration) / fadeDuration, 1.0);
// int profile = trafficModeActive ? 0 : personality + 1;
// auto &[profileImage, profileText] = scene.use_kaofui_icons ? profile_data_kaofui[profile] : profile_data[profile];
// if (textOpacity != 0.0) {
// p.setOpacity(textOpacity);
// p.setFont(InterFont(40, QFont::Bold));
// p.setPen(Qt::white);
// QRect textRect(-25, 0, width(), height() + 95);
// p.drawText(textRect, Qt::AlignCenter, profileText);
// }
// if (imageOpacity != 0.0) {
// drawIcon(p, QPoint((btn_size / 2) * 1.25, btn_size / 2 + 95), profileImage, Qt::transparent, imageOpacity);
// }
}
void AnnotatedCameraWidget::drawLeadInfo(QPainter &p) {
static QElapsedTimer timer;
static bool isFiveSecondsPassed = false;
@@ -1241,43 +1153,6 @@ void AnnotatedCameraWidget::drawLeadInfo(QPainter &p) {
p.restore();
}
PedalIcons::PedalIcons(QWidget *parent) : QWidget(parent), scene(uiState()->scene) {
setFixedSize(btn_size, btn_size);
brake_pedal_img = loadPixmap("../frogpilot/assets/other_images/brake_pedal.png", QSize(img_size, img_size));
gas_pedal_img = loadPixmap("../frogpilot/assets/other_images/gas_pedal.png", QSize(img_size, img_size));
}
void PedalIcons::updateState() {
// acceleration = scene.acceleration;
// accelerating = acceleration > 0.25;
// decelerating = acceleration < -0.25;
// if (accelerating || decelerating) {
// update();
// }
}
void PedalIcons::paintEvent(QPaintEvent *event) {
// QPainter p(this);
// p.setRenderHint(QPainter::Antialiasing);
// int totalWidth = 2 * img_size;
// int startX = (width() - totalWidth) / 2;
// int brakeX = startX + img_size / 2;
// int gasX = startX + img_size;
// float brakeOpacity = scene.standstill ? 1.0f : decelerating ? std::max(0.25f, std::abs(acceleration)) : 0.25f;
// float gasOpacity = accelerating ? std::max(0.25f, acceleration) : 0.25f;
// p.setOpacity(brakeOpacity);
// p.drawPixmap(brakeX, (height() - img_size) / 2, brake_pedal_img);
// p.setOpacity(gasOpacity);
// p.drawPixmap(gasX, (height() - img_size) / 2, gas_pedal_img);
}
void AnnotatedCameraWidget::drawSLCConfirmation(QPainter &p) {
p.save();

View File

@@ -38,53 +38,6 @@ private:
UIScene &scene;
};
class DistanceButton : public QPushButton {
public:
explicit DistanceButton(QWidget *parent = nullptr);
void buttonPressed();
void buttonReleased();
void updateState();
protected:
void paintEvent(QPaintEvent *event) override;
private:
Params paramsMemory{"/dev/shm/params"};
UIScene &scene;
bool trafficModeActive;
// int personality;
QElapsedTimer transitionTimer;
QVector<std::pair<QPixmap, QString>> profile_data;
QVector<std::pair<QPixmap, QString>> profile_data_kaofui;
};
class PedalIcons : public QWidget {
Q_OBJECT
public:
explicit PedalIcons(QWidget *parent = 0);
void updateState();
private:
void paintEvent(QPaintEvent *event) override;
QPixmap brake_pedal_img;
QPixmap gas_pedal_img;
UIScene &scene;
bool accelerating;
bool decelerating;
float acceleration;
};
// container window for the NVG UI
class AnnotatedCameraWidget : public CameraWidget {
@@ -97,7 +50,7 @@ public:
private:
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
void drawSpeedWidget(QPainter &p, int x, int y, const QString &title, const QString &speedLimitStr, QColor colorSpeed);
void drawSpeedWidget(QPainter &p, int x, int y, const QString &title, const QString &speedLimitStr, QColor colorSpeed, int width = 172);
QVBoxLayout *main_layout;
QPixmap dm_img;
@@ -135,8 +88,6 @@ private:
Params paramsMemory{"/dev/shm/params"};
UIScene &scene;
DistanceButton *distance_btn;
PedalIcons *pedal_icons;
ScreenRecorder *recorder_btn;
QHBoxLayout *bottom_layout;
@@ -146,7 +97,6 @@ private:
bool blindSpotRight;
bool experimentalMode;
bool leadInfo;
bool onroadDistanceButton;
bool roadNameUI;
bool showAlwaysOnLateralStatusBar;
bool showConditionalExperimentalStatusBar;

View File

@@ -116,7 +116,7 @@ void update_model(UIState *s,
// update path
float path;
if (paramsMemory.getInt("no_lat_lane_change")) {
if (paramsMemory.getBool("no_lat_lane_change")) {
path = (float)LANE_CHANGE_NO_LAT_PATH_WIDTH / 20; // Release: better calc for EU users
} else {
path = (float)CENTER_LANE_WIDTH / 20; // Release: better calc for EU users