from dataclasses import dataclass , field
from enum import StrEnum , IntFlag
from opendbc . car import Bus , CarSpecs , DbcDict , PlatformConfig , Platforms , structs , uds
from opendbc . car . docs_definitions import CarHarness , CarDocs , CarParts , Device
from opendbc . car . fw_query_definitions import FwQueryConfig , Request , StdQueries , p16
from opendbc . car . vin import Vin
class WMI ( StrEnum ) :
RIVIAN_TRUCK = " 7FC "
RIVIAN_MPV = " 7PD "
class ModelLine ( StrEnum ) :
R1T = " T " # R1T 4-door Pickup Truck
R1S = " S " # R1S 4-door MPV
class ModelYear ( StrEnum ) :
N_2022 = " N "
P_2023 = " P "
R_2024 = " R "
S_2025 = " S "
@dataclass
class RivianCarDocs ( CarDocs ) :
package : str = " All "
car_parts : CarParts = field ( default_factory = CarParts ( [ Device . threex_angled_mount , CarHarness . rivian ] ) )
setup_video_link : str = " https://youtu.be/uaISd1j7Z4U "
@dataclass
class RivianPlatformConfig ( PlatformConfig ) :
dbc_dict : DbcDict = field ( default_factory = lambda : { Bus . pt : ' rivian_primary_actuator ' , Bus . radar : ' rivian_mando_front_radar_generated ' } )
wmis : set [ WMI ] = field ( default_factory = set )
lines : set [ ModelLine ] = field ( default_factory = set )
years : set [ ModelYear ] = field ( default_factory = set )
class CAR ( Platforms ) :
RIVIAN_R1_GEN1 = RivianPlatformConfig (
# TODO: verify this
[
RivianCarDocs ( " Rivian R1S 2022-24 " ) ,
RivianCarDocs ( " Rivian R1T 2022-24 " ) ,
] ,
CarSpecs ( mass = 3206. , wheelbase = 3.08 , steerRatio = 15.2 ) ,
wmis = { WMI . RIVIAN_TRUCK , WMI . RIVIAN_MPV } ,
lines = { ModelLine . R1T , ModelLine . R1S } ,
years = { ModelYear . N_2022 , ModelYear . P_2023 , ModelYear . R_2024 } ,
)
def match_fw_to_car_fuzzy ( live_fw_versions , vin , offline_fw_versions ) - > set [ str ] :
# Rivian VIN reference: https://www.rivianforums.com/forum/threads/rivian-vin-decoder.1546
vin_obj = Vin ( vin )
line = vin_obj . vds [ : 1 ]
year = vin_obj . vis [ : 1 ]
candidates = set ( )
for platform in CAR :
if vin_obj . wmi in platform . config . wmis and line in platform . config . lines and year in platform . config . years :
candidates . add ( platform )
return { str ( c ) for c in candidates }
RIVIAN_VERSION_REQUEST = bytes ( [ uds . SERVICE_TYPE . READ_DATA_BY_IDENTIFIER ] ) + \
p16 ( 0xf1a0 )
RIVIAN_VERSION_RESPONSE = bytes ( [ uds . SERVICE_TYPE . READ_DATA_BY_IDENTIFIER + 0x40 ] )
FW_QUERY_CONFIG = FwQueryConfig (
requests = [
Request (
[ StdQueries . TESTER_PRESENT_REQUEST , StdQueries . SUPPLIER_SOFTWARE_VERSION_REQUEST ] ,
[ StdQueries . TESTER_PRESENT_RESPONSE , StdQueries . SUPPLIER_SOFTWARE_VERSION_RESPONSE ] ,
rx_offset = 0x40 ,
bus = 0 ,
) ,
Request (
[ StdQueries . TESTER_PRESENT_REQUEST , StdQueries . MANUFACTURER_ECU_HARDWARE_NUMBER_REQUEST ] ,
[ StdQueries . TESTER_PRESENT_RESPONSE , StdQueries . MANUFACTURER_ECU_HARDWARE_NUMBER_RESPONSE ] ,
rx_offset = 0x40 ,
bus = 0 ,
logging = True ,
) ,
Request (
[ StdQueries . TESTER_PRESENT_REQUEST , RIVIAN_VERSION_REQUEST ] ,
[ StdQueries . TESTER_PRESENT_RESPONSE , RIVIAN_VERSION_RESPONSE ] ,
rx_offset = 0x40 ,
bus = 0 ,
logging = True ,
) ,
] ,
match_fw_to_car_fuzzy = match_fw_to_car_fuzzy ,
)
GEAR_MAP = {
0 : structs . CarState . GearShifter . unknown ,
1 : structs . CarState . GearShifter . park ,
2 : structs . CarState . GearShifter . reverse ,
3 : structs . CarState . GearShifter . neutral ,
4 : structs . CarState . GearShifter . drive ,
}
class CarControllerParams :
# The R1T 2023 and R1S 2023 we tested on achieves slightly more lateral acceleration going left vs. right
# and lateral acceleration falls linearly as speed decreases from 38 mph to 20 mph. These values are set
# conservatively to reach a maximum of 3.0 m/s^2 turning left at 80 mph
# These refer to turning left:
# 250 is ~2.8 m/s^2 above 17 m/s, then linearly ramps to ~1.6 m/s^2 from 17 m/s to 9 m/s
# TODO: it is theorized older models have different steering racks and achieve down to half the
# lateral acceleration referenced here at all speeds. detect this and ship a torque increase for those models
STEER_MAX = 250 # 350 is intended to maintain lateral accel, not increase it
STEER_MAX_LOOKUP = [ 9 , 17 ] , [ 350 , 250 ]
STEER_STEP = 1
STEER_DELTA_UP = 3 # torque increase per refresh
STEER_DELTA_DOWN = 5 # torque decrease per refresh
STEER_DRIVER_ALLOWANCE = 100 # allowed driver torque before start limiting
STEER_DRIVER_MULTIPLIER = 2 # weight driver torque
STEER_DRIVER_FACTOR = 100
ACCEL_MIN = - 3.5 # m/s^2
ACCEL_MAX = 2.0 # m/s^2
def __init__ ( self , CP ) :
pass
class RivianSafetyFlags ( IntFlag ) :
LONG_CONTROL = 1
DBC = CAR . create_dbc_map ( )