mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-15 03:53:58 +08:00
openpilot v0.8.8 release
This commit is contained in:
@@ -23,7 +23,8 @@ from selfdrive.controls.lib.events import Events, ET
|
||||
from selfdrive.controls.lib.alertmanager import AlertManager
|
||||
from selfdrive.controls.lib.vehicle_model import VehicleModel
|
||||
from selfdrive.locationd.calibrationd import Calibration
|
||||
from selfdrive.hardware import HARDWARE, TICI
|
||||
from selfdrive.hardware import HARDWARE, TICI, EON
|
||||
from selfdrive.manager.process_config import managed_processes
|
||||
|
||||
LDW_MIN_SPEED = 31 * CV.MPH_TO_MS
|
||||
LANE_DEPARTURE_THRESHOLD = 0.1
|
||||
@@ -32,7 +33,11 @@ STEER_ANGLE_SATURATION_THRESHOLD = 2.5 # Degrees
|
||||
|
||||
SIMULATION = "SIMULATION" in os.environ
|
||||
NOSENSOR = "NOSENSOR" in os.environ
|
||||
IGNORE_PROCESSES = set(["rtshield", "uploader", "deleter", "loggerd", "logmessaged", "tombstoned", "logcatd", "proclogd", "clocksd", "updated", "timezoned", "manage_athenad"])
|
||||
IGNORE_PROCESSES = {"rtshield", "uploader", "deleter", "loggerd", "logmessaged", "tombstoned",
|
||||
"logcatd", "proclogd", "clocksd", "updated", "timezoned", "manage_athenad"} | \
|
||||
{k for k, v in managed_processes.items() if not v.enabled}
|
||||
|
||||
ACTUATOR_FIELDS = set(car.CarControl.Actuators.schema.fields.keys())
|
||||
|
||||
ThermalStatus = log.DeviceState.ThermalStatus
|
||||
State = log.ControlsState.OpenpilotState
|
||||
@@ -196,6 +201,9 @@ class Controls:
|
||||
# TODO: make tici threshold the same
|
||||
if self.sm['deviceState'].memoryUsagePercent > (90 if TICI else 65) and not SIMULATION:
|
||||
self.events.add(EventName.lowMemory)
|
||||
cpus = list(self.sm['deviceState'].cpuUsagePercent)[:(-1 if EON else None)]
|
||||
if max(cpus, default=0) > 95:
|
||||
self.events.add(EventName.highCpuUsage)
|
||||
|
||||
# Alert if fan isn't spinning for 5 seconds
|
||||
if self.sm['pandaState'].pandaType in [PandaType.uno, PandaType.dos]:
|
||||
@@ -497,6 +505,12 @@ class Controls:
|
||||
if left_deviation or right_deviation:
|
||||
self.events.add(EventName.steerSaturated)
|
||||
|
||||
# Ensure no NaNs/Infs
|
||||
for p in ACTUATOR_FIELDS:
|
||||
if not math.isfinite(getattr(actuators, p)):
|
||||
cloudlog.error(f"actuators.{p} not finite {actuators.to_dict()}")
|
||||
setattr(actuators, p, 0.0)
|
||||
|
||||
return actuators, lac_log
|
||||
|
||||
def publish_logs(self, CS, start_time, actuators, lac_log):
|
||||
|
||||
@@ -240,6 +240,8 @@ def joystick_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) ->
|
||||
EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, bool], Alert]]]] = {
|
||||
# ********** events with no alerts **********
|
||||
|
||||
EventName.stockFcw: {},
|
||||
|
||||
# ********** events only containing alerts displayed in all states **********
|
||||
|
||||
EventName.joystickDebug: {
|
||||
@@ -357,15 +359,6 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
ET.NO_ENTRY: NoEntryAlert("Stock AEB: Risk of Collision"),
|
||||
},
|
||||
|
||||
EventName.stockFcw: {
|
||||
ET.PERMANENT: Alert(
|
||||
"BRAKE!",
|
||||
"Stock FCW: Risk of Collision",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 1., 2., 2.),
|
||||
ET.NO_ENTRY: NoEntryAlert("Stock FCW: Risk of Collision"),
|
||||
},
|
||||
|
||||
EventName.fcw: {
|
||||
ET.PERMANENT: Alert(
|
||||
"BRAKE!",
|
||||
@@ -423,7 +416,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"KEEP EYES ON ROAD: Driver Distracted",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1),
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1),
|
||||
},
|
||||
|
||||
EventName.promptDriverDistracted: {
|
||||
@@ -488,34 +481,34 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
|
||||
EventName.preLaneChangeLeft: {
|
||||
ET.WARNING: Alert(
|
||||
"Steer Left to Start Lane Change",
|
||||
"Monitor Other Vehicles",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
"Steer Left to Start Lane Change Once Safe",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
},
|
||||
|
||||
EventName.preLaneChangeRight: {
|
||||
ET.WARNING: Alert(
|
||||
"Steer Right to Start Lane Change",
|
||||
"Monitor Other Vehicles",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
"Steer Right to Start Lane Change Once Safe",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
},
|
||||
|
||||
EventName.laneChangeBlocked: {
|
||||
ET.WARNING: Alert(
|
||||
"Car Detected in Blindspot",
|
||||
"Monitor Other Vehicles",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, .1, .1, .1),
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimePrompt, .1, .1, .1),
|
||||
},
|
||||
|
||||
EventName.laneChange: {
|
||||
ET.WARNING: Alert(
|
||||
"Changing Lane",
|
||||
"Monitor Other Vehicles",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1),
|
||||
"Changing Lanes",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1),
|
||||
},
|
||||
|
||||
EventName.steerSaturated: {
|
||||
@@ -736,7 +729,14 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Low Memory: Reboot Your Device"),
|
||||
ET.PERMANENT: NormalPermanentAlert("Low Memory", "Reboot your Device"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device",
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
},
|
||||
|
||||
EventName.highCpuUsage: {
|
||||
#ET.SOFT_DISABLE: SoftDisableAlert("System Malfunction: Reboot Your Device"),
|
||||
#ET.PERMANENT: NormalPermanentAlert("System Malfunction", "Reboot your Device"),
|
||||
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device",
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
},
|
||||
|
||||
EventName.accFaulted: {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from common.numpy_fast import interp
|
||||
import numpy as np
|
||||
from cereal import log
|
||||
from common.filter_simple import FirstOrderFilter
|
||||
from common.numpy_fast import interp
|
||||
from common.realtime import DT_MDL
|
||||
from selfdrive.hardware import EON, TICI
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from cereal import log
|
||||
|
||||
|
||||
TRAJECTORY_SIZE = 33
|
||||
@@ -24,8 +26,8 @@ class LanePlanner:
|
||||
self.ll_x = np.zeros((TRAJECTORY_SIZE,))
|
||||
self.lll_y = np.zeros((TRAJECTORY_SIZE,))
|
||||
self.rll_y = np.zeros((TRAJECTORY_SIZE,))
|
||||
self.lane_width_estimate = 3.7
|
||||
self.lane_width_certainty = 1.0
|
||||
self.lane_width_estimate = FirstOrderFilter(3.7, 9.95, DT_MDL)
|
||||
self.lane_width_certainty = FirstOrderFilter(1.0, 0.95, DT_MDL)
|
||||
self.lane_width = 3.7
|
||||
|
||||
self.lll_prob = 0.
|
||||
@@ -79,12 +81,12 @@ class LanePlanner:
|
||||
r_prob *= r_std_mod
|
||||
|
||||
# Find current lanewidth
|
||||
self.lane_width_certainty += 0.05 * (l_prob * r_prob - self.lane_width_certainty)
|
||||
self.lane_width_certainty.update(l_prob * r_prob)
|
||||
current_lane_width = abs(self.rll_y[0] - self.lll_y[0])
|
||||
self.lane_width_estimate += 0.005 * (current_lane_width - self.lane_width_estimate)
|
||||
self.lane_width_estimate.update(current_lane_width)
|
||||
speed_lane_width = interp(v_ego, [0., 31.], [2.8, 3.5])
|
||||
self.lane_width = self.lane_width_certainty * self.lane_width_estimate + \
|
||||
(1 - self.lane_width_certainty) * speed_lane_width
|
||||
self.lane_width = self.lane_width_certainty.x * self.lane_width_estimate.x + \
|
||||
(1 - self.lane_width_certainty.x) * speed_lane_width
|
||||
|
||||
clipped_lane_width = min(4.0, self.lane_width)
|
||||
path_from_left_lane = self.lll_y + clipped_lane_width / 2.0
|
||||
|
||||
@@ -2,10 +2,11 @@ import math
|
||||
import numpy as np
|
||||
|
||||
from cereal import log
|
||||
from common.realtime import DT_CTRL
|
||||
from common.filter_simple import FirstOrderFilter
|
||||
from common.numpy_fast import clip, interp
|
||||
from selfdrive.car.toyota.values import CarControllerParams
|
||||
from common.realtime import DT_CTRL
|
||||
from selfdrive.car import apply_toyota_steer_torque_limits
|
||||
from selfdrive.car.toyota.values import CarControllerParams
|
||||
from selfdrive.controls.lib.drive_helpers import get_steer_max
|
||||
|
||||
|
||||
@@ -43,6 +44,7 @@ class LatControlINDI():
|
||||
|
||||
self.sat_count_rate = 1.0 * DT_CTRL
|
||||
self.sat_limit = CP.steerLimitTimer
|
||||
self.steer_filter = FirstOrderFilter(0., self.RC, DT_CTRL)
|
||||
|
||||
self.reset()
|
||||
|
||||
@@ -63,9 +65,9 @@ class LatControlINDI():
|
||||
return interp(self.speed, self._inner_loop_gain[0], self._inner_loop_gain[1])
|
||||
|
||||
def reset(self):
|
||||
self.delayed_output = 0.
|
||||
self.steer_filter.x = 0.
|
||||
self.output_steer = 0.
|
||||
self.sat_count = 0.0
|
||||
self.sat_count = 0.
|
||||
self.speed = 0.
|
||||
|
||||
def _check_saturation(self, control, check_saturation, limit):
|
||||
@@ -96,14 +98,14 @@ class LatControlINDI():
|
||||
if CS.vEgo < 0.3 or not active:
|
||||
indi_log.active = False
|
||||
self.output_steer = 0.0
|
||||
self.delayed_output = 0.0
|
||||
self.steer_filter.x = 0.0
|
||||
else:
|
||||
|
||||
rate_des = VM.get_steer_from_curvature(-curvature_rate, CS.vEgo)
|
||||
|
||||
# Expected actuator value
|
||||
alpha = 1. - DT_CTRL / (self.RC + DT_CTRL)
|
||||
self.delayed_output = self.delayed_output * alpha + self.output_steer * (1. - alpha)
|
||||
self.steer_filter.update_alpha(self.RC)
|
||||
self.steer_filter.update(self.output_steer)
|
||||
|
||||
# Compute acceleration error
|
||||
rate_sp = self.outer_loop_gain * (steers_des - self.x[0]) + rate_des
|
||||
@@ -121,12 +123,12 @@ class LatControlINDI():
|
||||
# Enforce rate limit
|
||||
if self.enforce_rate_limit:
|
||||
steer_max = float(CarControllerParams.STEER_MAX)
|
||||
new_output_steer_cmd = steer_max * (self.delayed_output + delta_u)
|
||||
new_output_steer_cmd = steer_max * (self.steer_filter.x + delta_u)
|
||||
prev_output_steer_cmd = steer_max * self.output_steer
|
||||
new_output_steer_cmd = apply_toyota_steer_torque_limits(new_output_steer_cmd, prev_output_steer_cmd, prev_output_steer_cmd, CarControllerParams)
|
||||
self.output_steer = new_output_steer_cmd / steer_max
|
||||
else:
|
||||
self.output_steer = self.delayed_output + delta_u
|
||||
self.output_steer = self.steer_filter.x + delta_u
|
||||
|
||||
steers_max = get_steer_max(CP, CS.vEgo)
|
||||
self.output_steer = clip(self.output_steer, -steers_max, steers_max)
|
||||
@@ -135,7 +137,7 @@ class LatControlINDI():
|
||||
indi_log.rateSetPoint = float(rate_sp)
|
||||
indi_log.accelSetPoint = float(accel_sp)
|
||||
indi_log.accelError = float(accel_error)
|
||||
indi_log.delayedOutput = float(self.delayed_output)
|
||||
indi_log.delayedOutput = float(self.steer_filter.x)
|
||||
indi_log.delta = float(delta_u)
|
||||
indi_log.output = float(self.output_steer)
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ class LateralPlanner():
|
||||
self.lane_change_direction = LaneChangeDirection.none
|
||||
self.lane_change_timer = 0.0
|
||||
self.lane_change_ll_prob = 1.0
|
||||
self.keep_pulse_timer = 0.0
|
||||
self.prev_one_blinker = False
|
||||
self.desire = log.LateralPlan.Desire.none
|
||||
|
||||
@@ -157,6 +158,16 @@ class LateralPlanner():
|
||||
|
||||
self.desire = DESIRES[self.lane_change_direction][self.lane_change_state]
|
||||
|
||||
# Send keep pulse once per second during LaneChangeStart.preLaneChange
|
||||
if self.lane_change_state in [LaneChangeState.off, LaneChangeState.laneChangeStarting]:
|
||||
self.keep_pulse_timer = 0.0
|
||||
elif self.lane_change_state == LaneChangeState.preLaneChange:
|
||||
self.keep_pulse_timer += DT_MDL
|
||||
if self.keep_pulse_timer > 1.0:
|
||||
self.keep_pulse_timer = 0.0
|
||||
elif self.desire in [log.LateralPlan.Desire.keepLeft, log.LateralPlan.Desire.keepRight]:
|
||||
self.desire = log.LateralPlan.Desire.none
|
||||
|
||||
# Turn off lanes during lane change
|
||||
if self.desire == log.LateralPlan.Desire.laneChangeRight or self.desire == log.LateralPlan.Desire.laneChangeLeft:
|
||||
self.LP.lll_prob *= self.lane_change_ll_prob
|
||||
|
||||
@@ -45,12 +45,14 @@ class LongitudinalMpc():
|
||||
self.cur_state[0].v_ego = v_safe
|
||||
self.cur_state[0].a_ego = a_safe
|
||||
|
||||
def update(self, carstate, model, v_cruise):
|
||||
def update(self, carstate, radarstate, v_cruise):
|
||||
v_cruise_clipped = np.clip(v_cruise, self.cur_state[0].v_ego - 10., self.cur_state[0].v_ego + 10.0)
|
||||
poss = v_cruise_clipped * np.array(T_IDXS[:LON_MPC_N+1])
|
||||
speeds = v_cruise_clipped * np.ones(LON_MPC_N+1)
|
||||
accels = np.zeros(LON_MPC_N+1)
|
||||
self.update_with_xva(poss, speeds, accels)
|
||||
|
||||
def update_with_xva(self, poss, speeds, accels):
|
||||
# Calculate mpc
|
||||
self.libmpc.run_mpc(self.cur_state, self.mpc_solution,
|
||||
list(poss), list(speeds), list(accels),
|
||||
|
||||
@@ -72,7 +72,7 @@ class LongControl():
|
||||
def update(self, active, CS, CP, long_plan):
|
||||
"""Update longitudinal control. This updates the state machine and runs a PID loop"""
|
||||
# Interp control trajectory
|
||||
# TODO estimate car specific lag, use .5s for now
|
||||
# TODO estimate car specific lag, use .15s for now
|
||||
if len(long_plan.speeds) == CONTROL_N:
|
||||
v_target = interp(DEFAULT_LONG_LAG, T_IDXS[:CONTROL_N], long_plan.speeds)
|
||||
v_target_future = long_plan.speeds[-1]
|
||||
|
||||
@@ -105,7 +105,7 @@ class Planner():
|
||||
for key in self.mpcs:
|
||||
self.mpcs[key].set_cur_state(self.v_desired, self.a_desired)
|
||||
self.mpcs[key].update(sm['carState'], sm['radarState'], v_cruise)
|
||||
if self.mpcs[key].status and self.mpcs[key].a_solution[5] < next_a:
|
||||
if self.mpcs[key].status and self.mpcs[key].a_solution[5] < next_a: # picks slowest solution from accel in ~0.2 seconds
|
||||
self.longitudinalPlanSource = key
|
||||
self.v_desired_trajectory = self.mpcs[key].v_solution[:CONTROL_N]
|
||||
self.a_desired_trajectory = self.mpcs[key].a_solution[:CONTROL_N]
|
||||
|
||||
@@ -132,11 +132,11 @@ class Cluster():
|
||||
|
||||
def get_RadarState_from_vision(self, lead_msg, v_ego):
|
||||
return {
|
||||
"dRel": float(lead_msg.xyva[0] - RADAR_TO_CAMERA),
|
||||
"yRel": float(-lead_msg.xyva[1]),
|
||||
"vRel": float(lead_msg.xyva[2]),
|
||||
"vLead": float(v_ego + lead_msg.xyva[2]),
|
||||
"vLeadK": float(v_ego + lead_msg.xyva[2]),
|
||||
"dRel": float(lead_msg.x[0] - RADAR_TO_CAMERA),
|
||||
"yRel": float(-lead_msg.y[0]),
|
||||
"vRel": float(lead_msg.v[0] - v_ego),
|
||||
"vLead": float(lead_msg.v[0]),
|
||||
"vLeadK": float(lead_msg.v[0]),
|
||||
"aLeadK": float(0),
|
||||
"aLeadTau": _LEAD_ACCEL_TAU,
|
||||
"fcw": False,
|
||||
|
||||
@@ -38,12 +38,12 @@ def laplacian_cdf(x, mu, b):
|
||||
|
||||
def match_vision_to_cluster(v_ego, lead, clusters):
|
||||
# match vision point to best statistical cluster match
|
||||
offset_vision_dist = lead.xyva[0] - RADAR_TO_CAMERA
|
||||
offset_vision_dist = lead.x[0] - RADAR_TO_CAMERA
|
||||
|
||||
def prob(c):
|
||||
prob_d = laplacian_cdf(c.dRel, offset_vision_dist, lead.xyvaStd[0])
|
||||
prob_y = laplacian_cdf(c.yRel, -lead.xyva[1], lead.xyvaStd[1])
|
||||
prob_v = laplacian_cdf(c.vRel, lead.xyva[2], lead.xyvaStd[2])
|
||||
prob_d = laplacian_cdf(c.dRel, offset_vision_dist, lead.xStd[0])
|
||||
prob_y = laplacian_cdf(c.yRel, -lead.y[0], lead.yStd[0])
|
||||
prob_v = laplacian_cdf(c.vRel + v_ego, lead.v[0], lead.vStd[0])
|
||||
|
||||
# This is isn't exactly right, but good heuristic
|
||||
return prob_d * prob_y * prob_v
|
||||
@@ -53,7 +53,7 @@ def match_vision_to_cluster(v_ego, lead, clusters):
|
||||
# if no 'sane' match is found return -1
|
||||
# stationary radar points can be false positives
|
||||
dist_sane = abs(cluster.dRel - offset_vision_dist) < max([(offset_vision_dist)*.25, 5.0])
|
||||
vel_sane = (abs(cluster.vRel - lead.xyva[2]) < 10) or (v_ego + cluster.vRel > 3)
|
||||
vel_sane = (abs(cluster.vRel + v_ego - lead.v[0]) < 10) or (v_ego + cluster.vRel > 3)
|
||||
if dist_sane and vel_sane:
|
||||
return cluster
|
||||
else:
|
||||
@@ -166,9 +166,9 @@ class RadarD():
|
||||
radarState.carStateMonoTime = sm.logMonoTime['carState']
|
||||
|
||||
if enable_lead:
|
||||
if len(sm['modelV2'].leads) > 1:
|
||||
radarState.leadOne = get_lead(self.v_ego, self.ready, clusters, sm['modelV2'].leads[0], low_speed_override=True)
|
||||
radarState.leadTwo = get_lead(self.v_ego, self.ready, clusters, sm['modelV2'].leads[1], low_speed_override=False)
|
||||
if len(sm['modelV2'].leadsV3) > 1:
|
||||
radarState.leadOne = get_lead(self.v_ego, self.ready, clusters, sm['modelV2'].leadsV3[0], low_speed_override=True)
|
||||
radarState.leadTwo = get_lead(self.v_ego, self.ready, clusters, sm['modelV2'].leadsV3[1], low_speed_override=False)
|
||||
return dat
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user