diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 2584618ebd..468b17ba85 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -56,50 +56,78 @@ HYUNDAI_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x4 TOYOTA_VERSION_REQUEST = b'\x1a\x88\x01' TOYOTA_VERSION_RESPONSE = b'\x5a\x88\x01' +VOLKSWAGEN_VERSION_REQUEST_MULTI = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_SPARE_PART_NUMBER) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_SOFTWARE_VERSION_NUMBER) + \ + p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION) +VOLKSWAGEN_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + OBD_VERSION_REQUEST = b'\x09\x04' OBD_VERSION_RESPONSE = b'\x49\x04' +DEFAULT_RX_OFFSET = 0x8 +VOLKSWAGEN_RX_OFFSET = 0x6a -# supports subaddressing, request, response +# brand, request, response, response offset REQUESTS = [ - # Hundai + # Hyundai ( "hyundai", [HYUNDAI_VERSION_REQUEST_SHORT], [HYUNDAI_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, ), ( "hyundai", [HYUNDAI_VERSION_REQUEST_LONG], [HYUNDAI_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, ), ( "hyundai", [HYUNDAI_VERSION_REQUEST_MULTI], [HYUNDAI_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, ), # Honda ( "honda", [UDS_VERSION_REQUEST], [UDS_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, ), # Toyota ( "toyota", [SHORT_TESTER_PRESENT_REQUEST, TOYOTA_VERSION_REQUEST], [SHORT_TESTER_PRESENT_RESPONSE, TOYOTA_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, ), ( "toyota", [SHORT_TESTER_PRESENT_REQUEST, OBD_VERSION_REQUEST], [SHORT_TESTER_PRESENT_RESPONSE, OBD_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, ), ( "toyota", [TESTER_PRESENT_REQUEST, DEFAULT_DIAGNOSTIC_REQUEST, EXTENDED_DIAGNOSTIC_REQUEST, UDS_VERSION_REQUEST], [TESTER_PRESENT_RESPONSE, DEFAULT_DIAGNOSTIC_RESPONSE, EXTENDED_DIAGNOSTIC_RESPONSE, UDS_VERSION_RESPONSE], - ) + DEFAULT_RX_OFFSET, + ), + # Volkswagen + ( + "volkswagen", + [VOLKSWAGEN_VERSION_REQUEST_MULTI], + [VOLKSWAGEN_VERSION_RESPONSE], + VOLKSWAGEN_RX_OFFSET, + ), + ( + "volkswagen", + [VOLKSWAGEN_VERSION_REQUEST_MULTI], + [VOLKSWAGEN_VERSION_RESPONSE], + DEFAULT_RX_OFFSET, + ), ] @@ -173,12 +201,12 @@ def get_fw_versions(logcan, sendcan, bus, extra=None, timeout=0.1, debug=False, fw_versions = {} for i, addr in enumerate(tqdm(addrs, disable=not progress)): for addr_chunk in chunks(addr): - for brand, request, response in REQUESTS: + for brand, request, response, response_offset in REQUESTS: try: addrs = [(a, s) for (b, a, s) in addr_chunk if b in (brand, 'any')] if addrs: - query = IsoTpParallelQuery(sendcan, logcan, bus, addrs, request, response, debug=debug) + query = IsoTpParallelQuery(sendcan, logcan, bus, addrs, request, response, response_offset, debug=debug) t = 2 * timeout if i == 0 else timeout fw_versions.update(query.get_data(t)) except Exception: diff --git a/selfdrive/car/isotp_parallel_query.py b/selfdrive/car/isotp_parallel_query.py index c5185dec5c..c95ef2c715 100644 --- a/selfdrive/car/isotp_parallel_query.py +++ b/selfdrive/car/isotp_parallel_query.py @@ -9,7 +9,7 @@ from panda.python.uds import CanClient, IsoTpMessage, FUNCTIONAL_ADDRS, get_rx_a class IsoTpParallelQuery(): - def __init__(self, sendcan, logcan, bus, addrs, request, response, functional_addr=False, debug=False): + def __init__(self, sendcan, logcan, bus, addrs, request, response, response_offset=0x8, functional_addr=False, debug=False): self.sendcan = sendcan self.logcan = logcan self.bus = bus @@ -25,7 +25,7 @@ class IsoTpParallelQuery(): else: self.real_addrs.append((a, None)) - self.msg_addrs = {tx_addr: get_rx_addr_for_tx_addr(tx_addr[0]) for tx_addr in self.real_addrs} + self.msg_addrs = {tx_addr: get_rx_addr_for_tx_addr(tx_addr[0], rx_offset=response_offset) for tx_addr in self.real_addrs} self.msg_buffer = defaultdict(list) def rx(self): diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index aeae5314dd..1a0755206d 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -25,41 +25,46 @@ class CarInterface(CarInterfaceBase): # VW port is a community feature, since we don't own one to test ret.communityFeature = True - if candidate in [CAR.GOLF, CAR.AUDI_A3]: + if True: # pylint: disable=using-constant-test # Set common MQB parameters that will apply globally ret.carName = "volkswagen" ret.radarOffCan = True ret.safetyModel = car.CarParams.SafetyModel.volkswagen - - # Additional common MQB parameters that may be overridden per-vehicle - ret.steerRateCost = 1.0 - ret.steerActuatorDelay = 0.05 # Hopefully all MQB racks are similar here - ret.steerLimitTimer = 0.4 - - ret.lateralTuning.pid.kpBP = [0.] - ret.lateralTuning.pid.kiBP = [0.] - + ret.steerActuatorDelay = 0.05 + + if 0xAD in fingerprint[0]: + # Getriebe_11 detected: traditional automatic or DSG gearbox + ret.transmissionType = TransmissionType.automatic + elif 0x187 in fingerprint[0]: + # EV_Gearshift detected: e-Golf or similar direct-drive electric + ret.transmissionType = TransmissionType.direct + else: + # No trans message at all, must be a true stick-shift manual + ret.transmissionType = TransmissionType.manual + cloudlog.info("Detected transmission type: %s", ret.transmissionType) + + # Global tuning defaults, can be overridden per-vehicle + + ret.steerRateCost = 1.0 + ret.steerLimitTimer = 0.4 + ret.steerRatio = 15.6 # Let the params learner figure this out + tire_stiffness_factor = 1.0 # Let the params learner figure this out + ret.lateralTuning.pid.kpBP = [0.] + ret.lateralTuning.pid.kiBP = [0.] + ret.lateralTuning.pid.kf = 0.00006 + ret.lateralTuning.pid.kpV = [0.6] + ret.lateralTuning.pid.kiV = [0.2] + + # Per-chassis tuning values, override tuning defaults here if desired + + if candidate in [CAR.AUDI_A3, CAR.GOLF]: + # Temporarily carry forward old tuning values while we test vehicle identification ret.mass = 1500 + STD_CARGO_KG ret.wheelbase = 2.64 - ret.centerToFront = ret.wheelbase * 0.45 - ret.steerRatio = 15.6 - ret.lateralTuning.pid.kf = 0.00006 - ret.lateralTuning.pid.kpV = [0.6] - ret.lateralTuning.pid.kiV = [0.2] - tire_stiffness_factor = 1.0 - ret.enableCamera = True # Stock camera detection doesn't apply to VW + ret.centerToFront = ret.wheelbase * 0.45 - if 0xAD in fingerprint[0]: - # Getriebe_11 detected: traditional automatic or DSG gearbox - ret.transmissionType = TransmissionType.automatic - elif 0x187 in fingerprint[0]: - # EV_Gearshift detected: e-Golf or similar direct-drive electric - ret.transmissionType = TransmissionType.direct - else: - # No trans message at all, must be a true stick-shift manual - ret.transmissionType = TransmissionType.manual - cloudlog.info("Detected transmission type: %s", ret.transmissionType) + ret.enableCamera = True # Stock camera detection doesn't apply to VW # TODO: get actual value, for now starting with reasonable value for # civic and scaling by mass and wheelbase diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index de7cb35dd5..146f2690c7 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -1,7 +1,8 @@ # flake8: noqa -from cereal import car from selfdrive.car import dbc_dict +from cereal import car +Ecu = car.CarParams.Ecu class CarControllerParams: HCA_STEP = 2 # HCA_01 message frequency 50Hz @@ -49,9 +50,13 @@ MQB_LDW_MESSAGES = { "laneAssistDeactivated": 10, # "Lane Assist deactivated." silent with persistent icon afterward } +# Check the 7th and 8th characters of the VIN before adding a new CAR. If the +# chassis code is already listed below, don't add a new CAR, just add to the +# FW_VERSIONS for that existing CAR. + class CAR: - GOLF = "VOLKSWAGEN GOLF" - AUDI_A3 = "AUDI A3" + GOLF = "VOLKSWAGEN GOLF" # Chassis 5G/AU/BA/BE, Mk7 VW Golf and variants + AUDI_A3 = "AUDI A3" # Chassis 8V/FF, Mk3 Audi A3 and variants FINGERPRINTS = { CAR.GOLF: [{ @@ -62,6 +67,43 @@ FINGERPRINTS = { }], } +FW_VERSIONS = { + CAR.AUDI_A3: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x875G0906259L \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870D9300013B \xf1\x894931', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\023121111111211--261117141112231291163221', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\00521G00807A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x875Q0907572G \xf1\x890571', + ], + }, + CAR.GOLF: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x878V0906259P \xf1\x890001', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870GC300012A \xf1\x891403', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13271212111312--071104171838103891131211', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571A0JA15A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x875Q0907572J \xf1\x890654', + ], + } +} + DBC = { CAR.GOLF: dbc_dict('vw_mqb_2010', None), CAR.AUDI_A3: dbc_dict('vw_mqb_2010', None),