Skip to content

Commit

Permalink
Vision Turn Speed Controller
Browse files Browse the repository at this point in the history
Added toggles for "Vision Turn Speed Control" along with aggressiveness for the speed and sensitivity for the curve itself.

Credit goes to Pfeiferj!

https: //github.com/pfeiferj
Co-Authored-By: Jacob Pfeifer <jacob@pfeifer.dev>
  • Loading branch information
FrogAi and pfeiferj committed Jan 30, 2024
1 parent 5ba41e8 commit 55de3b3
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 6 deletions.
1 change: 1 addition & 0 deletions cereal/custom.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct FrogPilotPlan @0x80ae746ee2596b11 {
slcSpeedLimit @10 :Float64;
slcSpeedLimitOffset @11 :Float32;
stoppedEquivalenceFactor @12 :Int16;
vtscControllingCurve @13 :Bool;
}

struct CustomReserved5 @0xa5cd762cd951a455 {
Expand Down
3 changes: 3 additions & 0 deletions common/params.cc
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"Compass", PERSISTENT},
{"ConditionalExperimental", PERSISTENT},
{"CurrentRandomEvent", PERSISTENT},
{"CurveSensitivity", PERSISTENT},
{"CustomColors", PERSISTENT},
{"CustomIcons", PERSISTENT},
{"CustomPersonalities", PERSISTENT},
Expand Down Expand Up @@ -363,13 +364,15 @@ std::unordered_map<std::string, uint32_t> keys = {
{"StoppingDistance", PERSISTENT},
{"TetheringEnabled", PERSISTENT},
{"TSS2Tune", PERSISTENT},
{"TurnAggressiveness", PERSISTENT},
{"TurnDesires", PERSISTENT},
{"UnlimitedLength", PERSISTENT},
{"Updated", PERSISTENT},
{"UpdateSchedule", PERSISTENT},
{"UpdateTime", PERSISTENT},
{"UseSI", PERSISTENT},
{"UseVienna", PERSISTENT},
{"VisionTurnControl", PERSISTENT},
{"WheelIcon", PERSISTENT},
};

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 38 additions & 4 deletions selfdrive/frogpilot/functions/frogpilot_planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from openpilot.selfdrive.frogpilot.functions.map_turn_speed_controller import MapTurnSpeedController
from openpilot.selfdrive.frogpilot.functions.speed_limit_controller import SpeedLimitController

# VTSC variables
MIN_TARGET_V = 5 # m/s
TARGET_LAT_A = 1.9 # m/s^2

class FrogPilotPlanner:
def __init__(self, params, params_memory):
self.cem = ConditionalExperimentalMode()
Expand All @@ -23,6 +27,7 @@ def __init__(self, params, params_memory):
self.mtsc_target = 0
self.slc_target = 0
self.v_cruise = 0
self.vtsc_target = 0

self.accel_limits = [A_CRUISE_MIN, get_max_accel(0)]

Expand All @@ -34,7 +39,7 @@ def update(self, carState, controlsState, modelData, mpc, sm, v_cruise, v_ego):
road_curvature = FrogPilotFunctions.road_curvature(modelData, v_ego)

# Acceleration profiles
v_cruise_changed = (self.mtsc_target) + 1 < v_cruise # Use stock acceleration profiles to handle MTSC more precisely
v_cruise_changed = (self.mtsc_target or self.vtsc_target) + 1 < v_cruise # Use stock acceleration profiles to handle MTSC/VTSC more precisely
if v_cruise_changed:
self.accel_limits = [A_CRUISE_MIN, get_max_accel(v_ego)]
elif self.acceleration_profile == 1:
Expand All @@ -48,10 +53,11 @@ def update(self, carState, controlsState, modelData, mpc, sm, v_cruise, v_ego):
if self.conditional_experimental_mode and enabled:
self.cem.update(carState, sm['frogpilotNavigation'], modelData, mpc, sm['radarState'], road_curvature, carState.standstill, v_ego)

if enabled:
if v_ego > MIN_TARGET_V:
self.v_cruise = self.update_v_cruise(carState, controlsState, modelData, enabled, v_cruise, v_ego)
else:
self.mtsc_target = v_cruise
self.vtsc_target = v_cruise
self.v_cruise = v_cruise

# Lane detection
Expand Down Expand Up @@ -101,15 +107,36 @@ def update_v_cruise(self, carState, controlsState, modelData, enabled, v_cruise,
self.overriden_speed = 0
self.slc_target = v_cruise

# Pfeiferj's Vision Turn Controller
if self.vision_turn_controller:
# Set the curve sensitivity
orientation_rate = np.array(np.abs(modelData.orientationRate.z)) * self.curve_sensitivity
velocity = np.array(modelData.velocity.x)

# Get the maximum lat accel from the model
max_pred_lat_acc = np.amax(orientation_rate * velocity)

# Get the maximum curve based on the current velocity
max_curve = max_pred_lat_acc / (v_ego**2)

# Set the target lateral acceleration
adjusted_target_lat_a = TARGET_LAT_A * self.turn_aggressiveness

# Get the target velocity for the maximum curve
self.vtsc_target = (adjusted_target_lat_a / max_curve)**0.5
self.vtsc_target = np.clip(self.vtsc_target, MIN_TARGET_V, v_cruise)
else:
self.vtsc_target = v_cruise

v_ego_diff = max(carState.vEgoRaw - carState.vEgoCluster, 0)
return min(v_cruise, self.mtsc_target, self.slc_target) - v_ego_diff
return min(v_cruise, self.mtsc_target, self.slc_target, self.vtsc_target) - v_ego_diff

def publish(self, sm, pm, mpc):
frogpilot_plan_send = messaging.new_message('frogpilotPlan')
frogpilot_plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState'])
frogpilotPlan = frogpilot_plan_send.frogpilotPlan

frogpilotPlan.adjustedCruise = self.mtsc_target * (CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH)
frogpilotPlan.adjustedCruise = float(min(self.mtsc_target, self.vtsc_target) * (CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH))
frogpilotPlan.conditionalExperimental = self.cem.experimental_mode

frogpilotPlan.desiredFollowDistance = mpc.safe_obstacle_distance - mpc.stopped_equivalence_factor
Expand All @@ -127,6 +154,8 @@ def publish(self, sm, pm, mpc):
frogpilotPlan.slcSpeedLimit = float(self.slc_target)
frogpilotPlan.slcSpeedLimitOffset = SpeedLimitController.offset

frogpilotPlan.vtscControllingCurve = bool(self.mtsc_target > self.vtsc_target)

pm.send('frogpilotPlan', frogpilot_plan_send)

def update_frogpilot_params(self, params, params_memory):
Expand Down Expand Up @@ -165,3 +194,8 @@ def update_frogpilot_params(self, params, params_memory):
if self.speed_limit_controller:
self.speed_limit_controller_override = params.get_int("SLCOverride")
SpeedLimitController.update_frogpilot_params()

self.vision_turn_controller = params.get_bool("VisionTurnControl")
if self.vision_turn_controller:
self.curve_sensitivity = params.get_int("CurveSensitivity") / 100
self.turn_aggressiveness = params.get_int("TurnAggressiveness") / 100
18 changes: 17 additions & 1 deletion selfdrive/frogpilot/ui/control_settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
{"SLCOverride", "Override Method", "Choose your preferred method to override the current speed limit.", ""},

{"TurnDesires", "Use Turn Desires", "Use turn desires for enhanced precision in turns below the minimum lane change speed.", "../assets/navigation/direction_continue_right.png"},

{"VisionTurnControl", "Vision Turn Speed Controller", "Slow down for detected road curvature for smoother curve handling.", "../frogpilot/assets/toggle_icons/icon_vtc.png"},
{"CurveSensitivity", "Curve Detection Sensitivity", "Set curve detection sensitivity. Higher values prompt earlier responses, lower values lead to smoother but later reactions.", ""},
{"TurnAggressiveness", "Turn Speed Aggressiveness", "Set turn speed aggressiveness. Higher values result in faster turns, lower values yield gentler turns.", ""},
};

for (const auto &[param, title, desc, icon] : controlToggles) {
Expand Down Expand Up @@ -368,6 +372,18 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
slscPriorityButton->setValue(initialPriorities.join(", "));
addItem(slscPriorityButton);

} else if (param == "VisionTurnControl") {
FrogPilotParamManageControl *visionTurnControlToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(visionTurnControlToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
parentToggleClicked();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(visionTurnControlKeys.find(key.c_str()) != visionTurnControlKeys.end());
}
});
toggle = visionTurnControlToggle;
} else if (param == "CurveSensitivity" || param == "TurnAggressiveness") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 200, std::map<int, QString>(), this, false, "%");

} else {
toggle = new ParamControl(param, title, desc, icon, this);
}
Expand Down Expand Up @@ -409,7 +425,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
mtscKeys = {"MTSCAggressiveness"};
qolKeys = {"DisableOnroadUploads", "HigherBitrate", "NavChill", "PauseLateralOnSignal", "ReverseCruise", "SetSpeedOffset"};
speedLimitControllerKeys = {"Offset1", "Offset2", "Offset3", "Offset4", "SLCFallback", "SLCOverride", "SLCPriority"};
visionTurnControlKeys = {};
visionTurnControlKeys = {"CurveSensitivity", "TurnAggressiveness"};

QObject::connect(uiState(), &UIState::offroadTransition, this, [this](bool offroad) {
if (!offroad) {
Expand Down
3 changes: 2 additions & 1 deletion selfdrive/ui/qt/onroad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,8 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size);
if (is_cruise_set && cruiseAdjustment) {
float transition = qBound(0.0f, 4.0f * (cruiseAdjustment / setSpeed), 1.0f);
QColor min = whiteColor(75), max = greenColor(75);
QColor min = whiteColor(75);
QColor max = scene.vtsc_controlling_curve ? redColor(75) : greenColor(75);

p.setPen(QPen(QColor::fromRgbF(
min.redF() + transition * (max.redF() - min.redF()),
Expand Down
1 change: 1 addition & 0 deletions selfdrive/ui/ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ static void update_state(UIState *s) {
scene.speed_limit_overridden_speed = frogpilotPlan.getSlcOverriddenSpeed();
}
scene.adjusted_cruise = frogpilotPlan.getAdjustedCruise();
scene.vtsc_controlling_curve = frogpilotPlan.getVtscControllingCurve();
}
if (sm.updated("liveLocationKalman")) {
auto liveLocationKalman = sm["liveLocationKalman"].getLiveLocationKalman();
Expand Down
1 change: 1 addition & 0 deletions selfdrive/ui/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ typedef struct UIScene {
bool unlimited_road_ui_length;
bool use_si;
bool use_vienna_slc_sign;
bool vtsc_controlling_curve;
float adjusted_cruise;
float lane_line_width;
float lane_width_left;
Expand Down

0 comments on commit 55de3b3

Please sign in to comment.