Skip to content

Commit

Permalink
Map based speed limit improvements (commaai#146)
Browse files Browse the repository at this point in the history
* fixed double pull didn't set acc/pcc speed to current speed when you were driving on a road with unknown speed limit (used the last known limit)
* fixed fleet speed, pcc, acc and IC did not work with the same speed limit data, causing potential differences between displayed and driven speed
* improved speed limit detection for sometimes earlier info, so we can start to accelerate or slow down before the sign
* better detection for low speed limit vs unknown speed limit (enables speed limit based adjustments below 10kph)
* removed redundant code
* fix CC stalk up could cause alternating target speed
  • Loading branch information
neon-dev authored Jan 21, 2020
1 parent 60fffb5 commit 9a66380
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 120 deletions.
24 changes: 12 additions & 12 deletions opendbc/tesla_can.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -284,16 +284,15 @@ BO_ 643 BODY_R1: 8 GTW
SG_ VTA_Alm_Actv : 13|1@0+ (1,0) [0|1] "" NEO
SG_ WprOutsdPkPosn : 29|1@0+ (1,0) [0|1] "" NEO

BO_ 760 MCU_gpsVehicleSpeed: 8 GTW
SG_ MCU_gpsHDOP : 0|8@1+ (0.1,0) [0|25.5] "1" DAS
SG_ MCU_gpsVehicleHeading : 8|16@1+ (0.0078125,0) [0|511.9921875] "deg" DAS
SG_ MCU_gpsVehicleSpeed : 24|16@1+ (0.00390625,0) [0|250.996] "km/hr" DAS
SG_ MCU_userSpeedOffset : 40|6@1+ (1,-30) [-30|33] "kph/mph" DAS
SG_ MCU_mapSpeedLimitUnits : 46|1@1+ (1,0) [0|1] "" DAS
SG_ MCU_userSpeedOffsetUnits : 47|1@1+ (1,0) [0|1] "" DAS
SG_ MCU_mppSpeedLimit : 48|5@1+ (5,0) [0|155] "kph/mph" DAS
SG_ MCU_gpsNmeaMIA : 53|1@1+ (1,0) [0|0] "" DAS
SG_ MCU_gpsAntennaDisconnected : 54|1@1+ (1,0) [0|0] "" DAS
BO_ 760 UI_gpsVehicleSpeed: 8 GTW
SG_ UI_gpsHDOP : 0|8@1+ (0.1,0) [0|25.5] "1" DAS
SG_ UI_gpsVehicleHeading : 8|16@1+ (0.0078125,0) [0|511.9921875] "deg" DAS
SG_ UI_gpsVehicleSpeed : 24|16@1+ (0.00390625,0) [0|250.996] "km/hr" Vector__XXX
SG_ UI_userSpeedOffset : 40|6@1+ (1,-30) [-30|33] "kph/mph" DAS
SG_ UI_mapSpeedLimitUnits : 46|1@1+ (1,0) [0|1] "" DAS
SG_ UI_userSpeedOffsetUnits : 47|1@1+ (1,0) [0|1] "" DAS
SG_ UI_mppSpeedLimit : 48|5@1+ (5,0) [0|155] "kph/mph" DAS
SG_ UI_gpsNmeaMIA : 53|1@1+ (1,0) [0|0] "" DAS

BO_ 536 MCU_chassisControl: 8 GTW
SG_ MCU_dasDebugEnable : 0|1@1+ (1,0) [0|0] "" NEO
Expand Down Expand Up @@ -665,8 +664,9 @@ VAL_ 309 ESP_absFaultLamp 0 "OFF" 1 "ON" ;
VAL_ 309 ESP_espOffLamp 0 "OFF" 1 "ON" ;
VAL_ 309 ESP_stabilityControlSts 2 "ENGAGED" 3 "FAULTED" 5 "INIT" 4 "NOT_CONFIGURED" 0 "OFF" 1 "ON" ;
VAL_ 309 ESP_tcLampFlash 1 "FLASH" 0 "OFF" ;
VAL_ 760 MCU_speedLimitUnits 1 "KPH" 0 "MPH" ;
VAL_ 760 MCU_userSpeedOffsetUnits 1 "KPH" 0 "MPH" ;
VAL_ 568 UI_mapSpeedLimit 31 "SNA" 30 "UNLIMITED" 29 "LESS_OR_EQ_160" 28 "LESS_OR_EQ_150" 27 "LESS_OR_EQ_140" 26 "LESS_OR_EQ_130" 25 "LESS_OR_EQ_120" 24 "LESS_OR_EQ_115" 23 "LESS_OR_EQ_110" 22 "LESS_OR_EQ_105" 21 "LESS_OR_EQ_100" 20 "LESS_OR_EQ_95" 19 "LESS_OR_EQ_90" 18 "LESS_OR_EQ_85" 17 "LESS_OR_EQ_80" 16 "LESS_OR_EQ_75" 15 "LESS_OR_EQ_70" 14 "LESS_OR_EQ_65" 13 "LESS_OR_EQ_60" 12 "LESS_OR_EQ_55" 11 "LESS_OR_EQ_50" 10 "LESS_OR_EQ_45" 9 "LESS_OR_EQ_40" 8 "LESS_OR_EQ_35" 7 "LESS_OR_EQ_30" 6 "LESS_OR_EQ_25" 5 "LESS_OR_EQ_20" 4 "LESS_OR_EQ_15" 3 "LESS_OR_EQ_10" 2 "LESS_OR_EQ_7" 1 "LESS_OR_EQ_5" 0 "UNKNOWN" ;
VAL_ 760 UI_mapSpeedLimitUnits 1 "KPH" 0 "MPH" ;
VAL_ 760 UI_userSpeedOffsetUnits 1 "KPH" 0 "MPH" ;
VAL_ 643 AirTemp_Insd 255 "SNA" ;
VAL_ 643 AirTemp_Outsd 254 "INIT" 255 "SNA" ;
VAL_ 643 Bckl_Sw_RL_Stat_SAM_R 2 "FLT" 1 "NOT" 0 "OK" 3 "SNA" ;
Expand Down
24 changes: 12 additions & 12 deletions opendbc/tesla_can1916.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -284,16 +284,15 @@ BO_ 643 BODY_R1: 8 GTW
SG_ VTA_Alm_Actv : 13|1@0+ (1,0) [0|1] "" NEO
SG_ WprOutsdPkPosn : 29|1@0+ (1,0) [0|1] "" NEO

BO_ 760 MCU_gpsVehicleSpeed: 8 GTW
SG_ MCU_gpsHDOP : 0|8@1+ (0.1,0) [0|25.5] "1" DAS
SG_ MCU_gpsVehicleHeading : 8|16@1+ (0.0078125,0) [0|511.9921875] "deg" DAS
SG_ MCU_gpsVehicleSpeed : 24|16@1+ (0.00390625,0) [0|250.996] "km/hr" DAS
SG_ MCU_userSpeedOffset : 40|6@1+ (1,-30) [-30|33] "kph/mph" DAS
SG_ MCU_mapSpeedLimitUnits : 46|1@1+ (1,0) [0|1] "" DAS
SG_ MCU_userSpeedOffsetUnits : 47|1@1+ (1,0) [0|1] "" DAS
SG_ MCU_mppSpeedLimit : 48|5@1+ (5,0) [0|155] "kph/mph" DAS
SG_ MCU_gpsNmeaMIA : 53|1@1+ (1,0) [0|0] "" DAS
SG_ MCU_gpsAntennaDisconnected : 54|1@1+ (1,0) [0|0] "" DAS
BO_ 760 UI_gpsVehicleSpeed: 8 GTW
SG_ UI_gpsHDOP : 0|8@1+ (0.1,0) [0|25.5] "1" DAS
SG_ UI_gpsVehicleHeading : 8|16@1+ (0.0078125,0) [0|511.9921875] "deg" DAS
SG_ UI_gpsVehicleSpeed : 24|16@1+ (0.00390625,0) [0|250.996] "km/hr" Vector__XXX
SG_ UI_userSpeedOffset : 40|6@1+ (1,-30) [-30|33] "kph/mph" DAS
SG_ UI_mapSpeedLimitUnits : 46|1@1+ (1,0) [0|1] "" DAS
SG_ UI_userSpeedOffsetUnits : 47|1@1+ (1,0) [0|1] "" DAS
SG_ UI_mppSpeedLimit : 48|5@1+ (5,0) [0|155] "kph/mph" DAS
SG_ UI_gpsNmeaMIA : 53|1@1+ (1,0) [0|0] "" DAS

BO_ 536 MCU_chassisControl: 8 GTW
SG_ MCU_dasDebugEnable : 0|1@1+ (1,0) [0|0] "" NEO
Expand Down Expand Up @@ -665,8 +664,9 @@ VAL_ 309 ESP_absFaultLamp 0 "OFF" 1 "ON" ;
VAL_ 309 ESP_espOffLamp 0 "OFF" 1 "ON" ;
VAL_ 309 ESP_stabilityControlSts 2 "ENGAGED" 3 "FAULTED" 5 "INIT" 4 "NOT_CONFIGURED" 0 "OFF" 1 "ON" ;
VAL_ 309 ESP_tcLampFlash 1 "FLASH" 0 "OFF" ;
VAL_ 760 MCU_speedLimitUnits 1 "KPH" 0 "MPH" ;
VAL_ 760 MCU_userSpeedOffsetUnits 1 "KPH" 0 "MPH" ;
VAL_ 568 UI_mapSpeedLimit 31 "SNA" 30 "UNLIMITED" 29 "LESS_OR_EQ_160" 28 "LESS_OR_EQ_150" 27 "LESS_OR_EQ_140" 26 "LESS_OR_EQ_130" 25 "LESS_OR_EQ_120" 24 "LESS_OR_EQ_115" 23 "LESS_OR_EQ_110" 22 "LESS_OR_EQ_105" 21 "LESS_OR_EQ_100" 20 "LESS_OR_EQ_95" 19 "LESS_OR_EQ_90" 18 "LESS_OR_EQ_85" 17 "LESS_OR_EQ_80" 16 "LESS_OR_EQ_75" 15 "LESS_OR_EQ_70" 14 "LESS_OR_EQ_65" 13 "LESS_OR_EQ_60" 12 "LESS_OR_EQ_55" 11 "LESS_OR_EQ_50" 10 "LESS_OR_EQ_45" 9 "LESS_OR_EQ_40" 8 "LESS_OR_EQ_35" 7 "LESS_OR_EQ_30" 6 "LESS_OR_EQ_25" 5 "LESS_OR_EQ_20" 4 "LESS_OR_EQ_15" 3 "LESS_OR_EQ_10" 2 "LESS_OR_EQ_7" 1 "LESS_OR_EQ_5" 0 "UNKNOWN" ;
VAL_ 760 UI_mapSpeedLimitUnits 1 "KPH" 0 "MPH" ;
VAL_ 760 UI_userSpeedOffsetUnits 1 "KPH" 0 "MPH" ;
VAL_ 643 AirTemp_Insd 255 "SNA" ;
VAL_ 643 AirTemp_Outsd 254 "INIT" 255 "SNA" ;
VAL_ 643 Bckl_Sw_RL_Stat_SAM_R 2 "FLT" 1 "NOT" 0 "OK" 3 "SNA" ;
Expand Down
17 changes: 9 additions & 8 deletions selfdrive/car/tesla/ACC_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,17 @@ def _update_max_acc_speed(self, CS):
self.acc_speed_kph = min(self.acc_speed_kph, 170)
self.acc_speed_kph = max(self.acc_speed_kph, 0)

# Decide which cruise control buttons to simluate to get the car to the
# desired speed.
def update_acc(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_kph, speed_limit_valid, set_speed_limit_active, speed_limit_offset):
# Decide which cruise control buttons to simluate to get the car to the desired speed.
def update_acc(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_kph, set_speed_limit_active, speed_limit_offset):
# Adaptive cruise control
self.prev_speed_limit_kph = self.speed_limit_kph
if speed_limit_valid and set_speed_limit_active and (speed_limit_kph >= 10):
self.speed_limit_kph = speed_limit_kph + speed_limit_offset
if not (int(self.prev_speed_limit_kph) == int(self.speed_limit_kph)):
if set_speed_limit_active and speed_limit_kph > 0:
self.speed_limit_kph = speed_limit_kph + speed_limit_offset
if int(self.prev_speed_limit_kph) != int(self.speed_limit_kph):
self.acc_speed_kph = self.speed_limit_kph
self.fleet_speed.reset_averager()
else: # reset internal speed limit, so double pull doesn't set higher speed than current (e.g. after leaving the highway)
self.speed_limit_kph = 0.
current_time_ms = _current_time_millis()
if CruiseButtons.should_be_throttled(CS.cruise_buttons):
self.human_cruise_action_time = current_time_ms
Expand Down Expand Up @@ -231,7 +232,7 @@ def update_acc(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_kph,
# and speed more directly.
# Bring in the lead car distance from the radarState feed

button_to_press = self._calc_follow_button(CS, lead_1, speed_limit_kph, speed_limit_valid, set_speed_limit_active, speed_limit_offset, frame)
button_to_press = self._calc_follow_button(CS, lead_1, speed_limit_kph, set_speed_limit_active, speed_limit_offset, frame)
if button_to_press:
self.automated_cruise_action_time = current_time_ms
# If trying to slow below the min cruise speed, just cancel cruise.
Expand All @@ -247,7 +248,7 @@ def update_acc(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_kph,
return button_to_press

# function to calculate the cruise button based on a safe follow distance
def _calc_follow_button(self, CS, lead_car, speed_limit_kph, speed_limit_valid, set_speed_limit_active, speed_limit_offset, frame):
def _calc_follow_button(self, CS, lead_car, speed_limit_kph, set_speed_limit_active, speed_limit_offset, frame):
if lead_car is None:
return None
# Desired gap (in seconds) between cars.
Expand Down
24 changes: 12 additions & 12 deletions selfdrive/car/tesla/PCC_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,18 +261,16 @@ def update_stat(self, CS, frame):
# Handle pressing up and down buttons.
elif (self.enable_pedal_cruise
and CS.cruise_buttons != self.prev_cruise_buttons):
# Real stalk command while PCC is already enabled. Adjust the max PCC
# speed if necessary.
actual_speed_kph = CS.v_ego * CV.MS_TO_KPH
# Real stalk command while PCC is already enabled. Adjust the max PCC speed if necessary.
# We round the target speed in the user's units of measurement to avoid jumpy speed readings
actual_speed_kph_uom_rounded = int(CS.v_ego * CV.MS_TO_KPH / speed_uom_kph + 0.5) * speed_uom_kph
if CS.cruise_buttons == CruiseButtons.RES_ACCEL:
self.pedal_speed_kph = max(self.pedal_speed_kph, actual_speed_kph) + speed_uom_kph
self.pedal_speed_kph = max(self.pedal_speed_kph, actual_speed_kph_uom_rounded) + speed_uom_kph
elif CS.cruise_buttons == CruiseButtons.RES_ACCEL_2ND:
self.pedal_speed_kph = max(self.pedal_speed_kph, actual_speed_kph) + 5 * speed_uom_kph
self.pedal_speed_kph = max(self.pedal_speed_kph, actual_speed_kph_uom_rounded) + 5 * speed_uom_kph
elif CS.cruise_buttons == CruiseButtons.DECEL_SET:
#self.pedal_speed_kph = max(self.pedal_speed_kph, actual_speed_kph) - speed_uom_kph
self.pedal_speed_kph =self.pedal_speed_kph - speed_uom_kph
self.pedal_speed_kph = self.pedal_speed_kph - speed_uom_kph
elif CS.cruise_buttons == CruiseButtons.DECEL_2ND:
#self.pedal_speed_kph = max(self.pedal_speed_kph, actual_speed_kph) - 5 * speed_uom_kph
self.pedal_speed_kph = self.pedal_speed_kph - 5 * speed_uom_kph
# Clip PCC speed between 0 and 170 KPH.
self.pedal_speed_kph = clip(self.pedal_speed_kph, MIN_PCC_V_KPH, MAX_PCC_V_KPH)
Expand Down Expand Up @@ -310,7 +308,7 @@ def update_stat(self, CS, frame):

return can_sends

def update_pdl(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_ms, speed_limit_valid, set_speed_limit_active, speed_limit_offset,alca_enabled):
def update_pdl(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_ms, set_speed_limit_active, speed_limit_offset,alca_enabled):
idx = self.pedal_idx

self.prev_speed_limit_kph = self.speed_limit_kph
Expand All @@ -331,12 +329,14 @@ def update_pdl(self, enabled, CS, frame, actuators, pcm_speed, speed_limit_ms, s
#print ("Torque level at detection %s" % (CS.torqueLevel))
#print ("Speed level at detection %s" % (CS.v_ego * CV.MS_TO_MPH))

if speed_limit_valid and set_speed_limit_active and (speed_limit_ms > 2.7):
self.speed_limit_kph = (speed_limit_ms + speed_limit_offset) * CV.MS_TO_KPH
if not (int(self.prev_speed_limit_kph) == int(self.speed_limit_kph)):
if set_speed_limit_active and speed_limit_ms > 0:
self.speed_limit_kph = (speed_limit_ms + speed_limit_offset) * CV.MS_TO_KPH
if int(self.prev_speed_limit_kph) != int(self.speed_limit_kph):
self.pedal_speed_kph = self.speed_limit_kph
# reset MovingAverage for fleet speed when speed limit changes
self.fleet_speed.reset_averager()
else: # reset internal speed limit, so double pull doesn't set higher speed than current (e.g. after leaving the highway)
self.speed_limit_kph = 0.
self.pedal_idx = (self.pedal_idx + 1) % 16

if not self.pcc_available or not enabled:
Expand Down
45 changes: 10 additions & 35 deletions selfdrive/car/tesla/carcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ def __init__(self, dbc_name):
self.icCarLR = messaging.sub_sock('uiIcCarLR', conflate=True)
self.alcaState = messaging.sub_sock('alcaState', conflate=True)
self.gpsLocationExternal = None
self.speedlimit_ms = 0.
self.speedlimit_valid = False
self.speedlimit_units = 0
self.opState = 0 # 0-disabled, 1-enabled, 2-disabling, 3-unavailable, 5-warning
self.accPitch = 0.
self.accRoll = 0.
Expand All @@ -120,7 +117,7 @@ def __init__(self, dbc_name):
self.gyroYaw = 0.
self.set_speed_limit_active = False
self.speed_limit_offset = 0.
self.speed_limit_for_cc = 0.
self.speed_limit_ms = 0.

# for warnings
self.warningCounter = 0
Expand Down Expand Up @@ -325,16 +322,14 @@ def update(self, enabled, CS, frame, actuators, \
if CS.hasTeslaIcIntegration:
self.set_speed_limit_active = True
self.speed_limit_offset = CS.userSpeedLimitOffsetKph
self.speed_limit_for_cc = CS.userSpeedLimitKph
#print self.speed_limit_for_cc
else:
self.set_speed_limit_active = (self.params.get("SpeedLimitOffset") is not None) and (self.params.get("LimitSetSpeed") == "1")
if self.set_speed_limit_active:
self.speed_limit_offset = float(self.params.get("SpeedLimitOffset"))
if not self.isMetric:
self.speed_limit_offset = self.speed_limit_offset * CV.MPH_TO_MS
else:
self.speed_limit_offset = 0.
if not self.isMetric:
self.speed_limit_offset = self.speed_limit_offset * CV.MPH_TO_MS
if CS.useTeslaGPS and (frame % 10 == 0):
if self.gpsLocationExternal is None:
self.gpsLocationExternal = messaging.pub_sock('gpsLocationExternal')
Expand Down Expand Up @@ -417,21 +412,8 @@ def update(self, enabled, CS, frame, actuators, \
# DAS_acc_speed_limit (8),
# DAS_speed_limit_units(8)
#send fake_das data as 0x553
# TODO: forward collission warning
# TODO: forward collision warning

if CS.hasTeslaIcIntegration:
self.set_speed_limit_active = True
self.speed_limit_offset = CS.userSpeedLimitOffsetKph
# only change the speed limit when we have a valid vaue
if CS.userSpeedLimitKph >= 10:
self.speed_limit_for_cc = CS.userSpeedLimitKph

if CS.useTeslaMapData:
self.speedlimit_ms = CS.speedLimitKph * CV.KPH_TO_MS
self.speedlimit_valid = True
if self.speedlimit_ms == 0:
self.speedlimit_valid = False
self.speedlimit_units = self.speedUnits(fromMetersPerSecond = self.speedlimit_ms)
if frame % 10 == 0:
speedlimitMsg = None
if self.speedlimit is not None:
Expand All @@ -444,13 +426,11 @@ def update(self, enabled, CS, frame, actuators, \
trafficeventsMsgs = None
if self.trafficevents is not None:
trafficeventsMsgs = messaging.recv_sock(self.trafficevents)
if CS.hasTeslaIcIntegration:
self.speed_limit_ms = CS.speed_limit_ms
if (speedlimitMsg is not None) and not CS.useTeslaMapData:
#get speed limit
lmd = speedlimitMsg.liveMapData
self.speedlimit_ms = lmd.speedLimit
self.speedlimit_valid = lmd.speedLimitValid
self.speedlimit_units = self.speedUnits(fromMetersPerSecond = self.speedlimit_ms)
self.speed_limit_for_cc = self.speedlimit_ms * CV.MS_TO_KPH
self.speed_limit_ms = lmd.speedLimit if lmd.speedLimitValid else 0
if icLeadsMsg is not None:
self.icLeadsData = tesla.ICLeads.from_bytes(icLeadsMsg)
if radarStateMsg is not None:
Expand Down Expand Up @@ -480,7 +460,6 @@ def update(self, enabled, CS, frame, actuators, \
forward_collision_warning = 1
#cruise state: 0 unavailable, 1 available, 2 enabled, 3 hold
cc_state = 1
speed_limit_to_car = int(self.speedlimit_units)
alca_state = 0x00

speed_override = 0
Expand Down Expand Up @@ -608,7 +587,7 @@ def update(self, enabled, CS, frame, actuators, \
self.blinker.override_direction,forward_collision_warning, adaptive_cruise, hands_on_state, \
cc_state, 1 if self.PCC.pcc_available else 0, alca_state, \
CS.v_cruise_pcm,
CS.speedLimitToIc, #speed_limit_to_car,
CS.DAS_fusedSpeedLimit,
apply_angle,
1 if enable_steer_control else 0,
park_brake_request))
Expand All @@ -632,7 +611,7 @@ def update(self, enabled, CS, frame, actuators, \
can_sends.append(teslacan.create_enabled_eth_msg(1))
if (not self.PCC.pcc_available) and frame % 5 == 0: # acc processed at 20Hz
cruise_btn = self.ACC.update_acc(enabled, CS, frame, actuators, pcm_speed, \
self.speed_limit_for_cc, self.speedlimit_valid, \
self.speed_limit_ms * CV.MS_TO_KPH,
self.set_speed_limit_active, self.speed_limit_offset)
if cruise_btn:
cruise_msg = teslacan.create_cruise_adjust_msg(
Expand All @@ -644,7 +623,7 @@ def update(self, enabled, CS, frame, actuators, \
apply_accel = 0.
if self.PCC.pcc_available and frame % 5 == 0: # pedal processed at 20Hz
apply_accel, accel_needed, accel_idx = self.PCC.update_pdl(enabled, CS, frame, actuators, pcm_speed, \
self.speed_limit_for_cc * CV.KPH_TO_MS, self.speedlimit_valid, \
self.speed_limit_ms,
self.set_speed_limit_active, self.speed_limit_offset * CV.KPH_TO_MS, self.alca_enabled)
can_sends.append(teslacan.create_pedal_command_msg(apply_accel, int(accel_needed), accel_idx))
self.last_angle = apply_angle
Expand Down Expand Up @@ -815,10 +794,6 @@ def handleTrafficEvents(self, trafficEventsMsgs):
messages.append(teslacan.create_fake_DAS_sign_msg(self.roadSignType,self.roadSignStopDist,self.roadSignColor,self.roadSignControlActive))
return messages

# Returns speed as it needs to be displayed on the IC
def speedUnits(self, fromMetersPerSecond):
return fromMetersPerSecond * (CV.MS_TO_KPH if self.isMetric else CV.MS_TO_MPH) + 0.5

def _should_ldw(self, CS, frame):
if not CS.enableLdw:
return False
Expand Down
Loading

0 comments on commit 9a66380

Please sign in to comment.