import copy
from opendbc . can . parser import CANParser
from opendbc . car import Bus , structs
from opendbc . car . interfaces import CarStateBase
from opendbc . car . rivian . values import DBC , GEAR_MAP
from opendbc . car . common . conversions import Conversions as CV
GearShifter = structs . CarState . GearShifter
class CarState ( CarStateBase ) :
def __init__ ( self , CP ) :
super ( ) . __init__ ( CP )
self . last_speed = 30
self . acm_lka_hba_cmd = None
self . sccm_wheel_touch = None
self . vdm_adas_status = None
def update ( self , can_parsers ) - > structs . CarState :
cp = can_parsers [ Bus . pt ]
cp_cam = can_parsers [ Bus . cam ]
cp_adas = can_parsers [ Bus . adas ]
ret = structs . CarState ( )
# Vehicle speed
ret . vEgoRaw = cp . vl [ " ESP_Status " ] [ " ESP_Vehicle_Speed " ] * CV . KPH_TO_MS
ret . vEgo , ret . aEgo = self . update_speed_kf ( ret . vEgoRaw )
ret . standstill = abs ( ret . vEgoRaw ) < 0.01
# Gas pedal
pedal_status = cp . vl [ " VDM_PropStatus " ] [ " VDM_AcceleratorPedalPosition " ]
ret . gas = pedal_status / 100.0
ret . gasPressed = pedal_status > 0
# Brake pedal
ret . brake = cp . vl [ " ESPiB3 " ] [ " ESPiB3_pMC1 " ] / 250.0 # pressure in Bar
ret . brakePressed = cp . vl [ " iBESP2 " ] [ " iBESP2_BrakePedalApplied " ] == 1
# Steering wheel
ret . steeringAngleDeg = cp . vl [ " EPAS_AdasStatus " ] [ " EPAS_InternalSas " ]
ret . steeringRateDeg = cp . vl [ " EPAS_AdasStatus " ] [ " EPAS_SteeringAngleSpeed " ]
ret . steeringTorque = cp . vl [ " EPAS_SystemStatus " ] [ " EPAS_TorsionBarTorque " ]
ret . steeringPressed = self . update_steering_pressed ( abs ( ret . steeringTorque ) > 1.0 , 5 )
ret . steerFaultTemporary = cp . vl [ " EPAS_AdasStatus " ] [ " EPAS_EacErrorCode " ] != 0
# Cruise state
speed = min ( int ( cp_adas . vl [ " ACM_tsrCmd " ] [ " ACM_tsrSpdDisClsMain " ] ) , 85 )
self . last_speed = speed if speed != 0 else self . last_speed
ret . cruiseState . enabled = cp_cam . vl [ " ACM_Status " ] [ " ACM_FeatureStatus " ] == 1
# TODO: find cruise set speed on CAN
ret . cruiseState . speed = self . last_speed * CV . MPH_TO_MS # detected speed limit
if not self . CP . openpilotLongitudinalControl :
ret . cruiseState . speed = - 1
ret . cruiseState . available = True # cp.vl["VDM_AdasSts"]["VDM_AdasInterfaceStatus"] == 1
ret . cruiseState . standstill = cp . vl [ " VDM_AdasSts " ] [ " VDM_AdasAccelRequestAcknowledged " ] == 1
# TODO: log ACM_Unkown2=3 as a fault. need to filter it at the start and end of routes though
# ACM_FaultStatus hasn't been seen yet
ret . accFaulted = ( cp_cam . vl [ " ACM_Status " ] [ " ACM_FaultStatus " ] == 1 or
# VDM_AdasFaultStatus=Brk_Intv is the default for some reason
# VDM_AdasFaultStatus=Imps_Cmd was seen when sending it rapidly changing ACC enable commands
# VDM_AdasFaultStatus=Cntr_Fault isn't fully understood, but we've seen it in the wild
cp . vl [ " VDM_AdasSts " ] [ " VDM_AdasFaultStatus " ] in ( 3 , ) ) # 3=Imps_Cmd
# Gear
ret . gearShifter = GEAR_MAP . get ( int ( cp . vl [ " VDM_PropStatus " ] [ " VDM_Prndl_Status " ] ) , GearShifter . unknown )
# Doors
ret . doorOpen = any ( cp_adas . vl [ " IndicatorLights " ] [ door ] != 2 for door in ( " RearDriverDoor " , " FrontPassengerDoor " , " DriverDoor " , " RearPassengerDoor " ) )
# Blinkers
ret . leftBlinker = cp_adas . vl [ " IndicatorLights " ] [ " TurnLightLeft " ] in ( 1 , 2 )
ret . rightBlinker = cp_adas . vl [ " IndicatorLights " ] [ " TurnLightRight " ] in ( 1 , 2 )
# Seatbelt
ret . seatbeltUnlatched = cp . vl [ " RCM_Status " ] [ " RCM_Status_IND_WARN_BELT_DRIVER " ] != 0
# Blindspot
# ret.leftBlindspot = False
# ret.rightBlindspot = False
# AEB
ret . stockAeb = cp_cam . vl [ " ACM_AebRequest " ] [ " ACM_EnableRequest " ] != 0
# Messages needed by carcontroller
self . acm_lka_hba_cmd = copy . copy ( cp_cam . vl [ " ACM_lkaHbaCmd " ] )
self . sccm_wheel_touch = copy . copy ( cp . vl [ " SCCM_WheelTouch " ] )
self . vdm_adas_status = copy . copy ( cp . vl [ " VDM_AdasSts " ] )
return ret
@staticmethod
def get_can_parsers ( CP ) :
pt_messages = [
# sig_address, frequency
( " ESP_Status " , 50 ) ,
( " VDM_PropStatus " , 50 ) ,
( " iBESP2 " , 50 ) ,
( " ESPiB3 " , 50 ) ,
( " EPAS_AdasStatus " , 100 ) ,
( " EPAS_SystemStatus " , 100 ) ,
( " RCM_Status " , 8 ) ,
( " VDM_AdasSts " , 100 ) ,
( " SCCM_WheelTouch " , 20 ) ,
]
cam_messages = [
( " ACM_longitudinalRequest " , 100 ) ,
( " ACM_AebRequest " , 100 ) ,
( " ACM_Status " , 100 ) ,
( " ACM_lkaHbaCmd " , 100 )
]
adas_messages = [
( " IndicatorLights " , 10 ) ,
( " ACM_tsrCmd " , 10 ) ,
]
return {
Bus . pt : CANParser ( DBC [ CP . carFingerprint ] [ Bus . pt ] , pt_messages , 0 ) ,
Bus . adas : CANParser ( DBC [ CP . carFingerprint ] [ Bus . pt ] , adas_messages , 1 ) ,
Bus . cam : CANParser ( DBC [ CP . carFingerprint ] [ Bus . pt ] , cam_messages , 2 ) ,
}