MG: add ZS (ICE) support

This commit is contained in:
Rick Lan
2026-06-18 14:08:53 +08:00
parent d4eb1429ec
commit e93d6dd227
18 changed files with 939 additions and 1 deletions
+1
View File
@@ -635,6 +635,7 @@ struct CarParams {
fcaGiorgio @32;
rivian @33;
volkswagenMeb @34;
mg @35;
}
enum SteerControlType {
@@ -144,6 +144,7 @@ class CarHarness(EnumBase):
tesla_a = BaseCarHarness("Tesla A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable])
tesla_b = BaseCarHarness("Tesla B connector", parts=[Accessory.harness_box, Cable.long_obdc_cable])
psa_a = BaseCarHarness("PSA A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable])
mg_a = BaseCarHarness("MG A connector")
class Device(EnumBase):
@@ -0,0 +1,38 @@
from opendbc.can.packer import CANPacker
from opendbc.car import Bus
from opendbc.car.lateral import apply_driver_steer_torque_limits
from opendbc.car.interfaces import CarControllerBase
from opendbc.car.mg import mgcan
from opendbc.car.mg.values import CarControllerParams
class CarController(CarControllerBase):
def __init__(self, dbc_names, CP):
super().__init__(dbc_names, CP)
self.packer = CANPacker(dbc_names[Bus.pt])
self.apply_torque_last = 0
def update(self, CC, CS, now_nanos):
actuators = CC.actuators
can_sends = []
# steering command
if self.frame % CarControllerParams.STEER_STEP == 0:
if CC.latActive:
# calculate steer and also set limits due to driver torque
new_torque = int(round(actuators.torque * CarControllerParams.STEER_MAX))
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, CarControllerParams)
else:
apply_torque = 0
can_sends.append(mgcan.create_lka_steering(self.packer, (self.frame // CarControllerParams.STEER_STEP) % 16, apply_torque, CC.latActive))
self.apply_torque_last = apply_torque
new_actuators = actuators.as_builder()
new_actuators.torque = self.apply_torque_last / CarControllerParams.STEER_MAX
new_actuators.torqueOutputCan = self.apply_torque_last
self.frame += 1
return new_actuators, can_sends
+83
View File
@@ -0,0 +1,83 @@
from opendbc.can.parser import CANParser
from opendbc.car import Bus, structs
from opendbc.car.interfaces import CarStateBase
from opendbc.car.mg.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)
def update(self, can_parsers) -> structs.CarState:
cp = can_parsers[Bus.pt]
cp_cam = can_parsers[Bus.cam]
ret = structs.CarState()
# Vehicle speed
ret.vEgoRaw = cp.vl["SCS_HSC2_FrP19"]["VehSpdAvgHSC2"] * CV.KPH_TO_MS
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
ret.standstill = ret.vEgoRaw < 0.01
# Gas pedal
ret.gasPressed = cp.vl["Tester_HSC2_ECM_FrP00"]["AccelActuPosHSC2"] > 0
# Brake pedal
ret.brake = 0
ret.brakePressed = cp.vl["SCS_HSC2_FrP09"]["BrkPdlDrvrAppdPrsHSC2"] > 0
# Steering wheel
ret.steeringAngleDeg = cp.vl["SAS_HSC2_FrP00"]["StrgWhlAngHSC2"]
ret.steeringRateDeg = cp.vl["SAS_HSC2_FrP00"]["StrgWhlAngGrdHSC2"]
ret.steeringTorque = cp.vl["EPS_HSC2_FrP03"]["DrvrStrgDlvrdToqHSC2"]
ret.steeringTorqueEps = cp.vl["EPS_HSC2_FrP03"]["ChLKARespToqHSC2"]
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > 1.0, 5)
ret.steerFaultTemporary = cp_cam.vl["FVCM_HSC2_FrP02"]["LDWSysFltStsHSC2"] != 0 # TODO: validate
# Cruise state
ret.cruiseState.available = cp.vl["RADAR_HSC2_FrP00"]["ACCSysSts_RadarHSC2"] != 0 # main on (any non-Off state)
ret.cruiseState.enabled = cp.vl["RADAR_HSC2_FrP00"]["ACCSysSts_RadarHSC2"] in (2, 3) # Active, Override
ret.cruiseState.standstill = cp.vl["RADAR_HSC2_FrP00"]["ACCSysSts_RadarHSC2"] in (5, 6) # Standstill Active / Wait
ret.cruiseState.speed = cp.vl["RADAR_HSC2_FrP02"]["ACCDrvrSelTrgtSpd_RadarHSC2"] * CV.KPH_TO_MS
ret.accFaulted = cp_cam.vl["FVCM_HSC2_FrP02"]["TJAICASysFltStsHSC2"] != 0 # TODO: validate
# Gear
ret.gearShifter = GEAR_MAP.get(int(cp.vl["GW_HSC2_ECM_FrP04"]["TrShftLvrPos_h1HSC2"]), GearShifter.unknown)
# Doors
ret.doorOpen = any([cp.vl["GW_HSC2_BCM_FrP04"]["DrvrDoorOpenSts_H1_Safety"],
cp.vl["GW_HSC2_BCM_FrP04"]["FrtPsngDoorOpenSts_H1_Safety"]])
# Blinkers
ret.leftBlinker = bool(cp.vl["GW_HSC2_BCM_FrP04"]["BlinkerLeft"])
ret.rightBlinker = bool(cp.vl["GW_HSC2_BCM_FrP04"]["BlinkerRight"])
# Seatbelt
ret.seatbeltUnlatched = cp.vl["GW_HSC2_SDM_FrP00"]["DrvrSbltAtcHSC2"] != 1
# Blindspot
ret.leftBlindspot = cp.vl["RDA_HSC1_P02"]["LBSDAndLCAWrnng_HS"] > 0
ret.rightBlindspot = cp.vl["RDA_HSC1_P02"]["RBSDAndLCAWrnng_HS"] > 0
# FCW
ret.stockFcw = cp.vl["RADAR_HSC2_FrP02"]["FCWrnngSts_RadarHSC2"] != 0
# AEB
ret.stockAeb = cp.vl["RADAR_HSC2_FrP02"]["AEBMsgReqHSC2"] != 0
# dp - ALKA: lane keep available whenever the ACC main switch is on
self.lkas_on = ret.cruiseState.available
return ret
@staticmethod
def get_can_parsers(CP):
return {
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0),
Bus.radar: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 1),
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2),
}
@@ -0,0 +1,16 @@
# FW query is disabled for MG for now (see values.py): the MG ZS has no captured
# FW versions yet and no CAN fingerprint, so it is identified by forced car
# selection only. Leaving FW_VERSIONS undefined keeps MG out of the FW-query path
# (get_interface_attr uses ignore_none). Restore once we can query FW on the MG ZS:
#
# from opendbc.car.structs import CarParams
# from opendbc.car.mg.values import CAR
#
# Ecu = CarParams.Ecu
#
# FW_VERSIONS = {
# CAR.MG_ZS: {
# # populate via tools/car_porting/auto_fingerprint.py once a route with FW
# # query enabled is captured on the 2025 MG ZS
# },
# }
+36
View File
@@ -0,0 +1,36 @@
from opendbc.car import get_safety_config, structs
from opendbc.car.interfaces import CarInterfaceBase
from opendbc.car.mg.carcontroller import CarController
from opendbc.car.mg.carstate import CarState
from opendbc.car.mg.values import CAR, MgSafetyFlags
class CarInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams:
ret.brand = "mg"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.mg)]
if candidate == CAR.MG_ZS:
ret.safetyConfigs[0].safetyParam |= MgSafetyFlags.NON_EV.value
ret.steerActuatorDelay = 0.3
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
ret.steerControlType = structs.CarParams.SteerControlType.torque
ret.radarUnavailable = True
ret.alphaLongitudinalAvailable = False
if alpha_long:
ret.openpilotLongitudinalControl = True
ret.safetyConfigs[0].safetyParam |= MgSafetyFlags.LONG_CONTROL.value
ret.longitudinalActuatorDelay = 0.35
ret.vEgoStopping = 0.25
ret.stopAccel = 0
return ret
+29
View File
@@ -0,0 +1,29 @@
def calc_checksum(values):
lka_req_toq = values['LKAReqToqHSC2'] + 1024
lka_req_toq_sts = values['LKAReqToqStsHSC2']
lka_req_toq_v = values['LKAReqToqVHSC2']
lka_alv_rc = values['LKAAlvRCHSC2']
combined = ((lka_req_toq << 1) | (lka_req_toq_sts << 12) | lka_req_toq_v) & 0x3FFF
with_counter = (combined + lka_alv_rc) & 0x3FFF
checksum = ((~with_counter) + 1) & 0x3FFF
return checksum
def create_lka_steering(packer, counter, apply_torque, active):
values = {
"LKAReqToqHSC2": apply_torque,
"LKAReqToqVHSC2": 0,
"LKAAlvRCHSC2": counter,
"LDWLKAVbnLvlReqHSC2": 0, # TODO: vibration level?
"LKASysStsHSC2": 0,
"LKAReqToqStsHSC2": active,
"LKASysFltStsHSC2": 0,
"LKADrvrTkovReqHSC2": 0,
"LKAReqToqPVHSC2": 0
}
values["LKAReqToqPVHSC2"] = calc_checksum(values)
return packer.make_can_msg("FVCM_HSC2_FrP03", 0, values)
+82
View File
@@ -0,0 +1,82 @@
from dataclasses import dataclass, field
from enum import IntFlag
from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, structs
from opendbc.car.docs_definitions import CarHarness, CarDocs, CarParts
# FW query disabled for MG for now (see below) - restore when we can query FW on the MG ZS
# from opendbc.car import uds
# from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
@dataclass
class MgCarDocs(CarDocs):
package: str = "All"
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.mg_a]))
@dataclass
class MgPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'mg', Bus.radar: 'mg'})
class CAR(Platforms):
MG_ZS = MgPlatformConfig(
[
MgCarDocs("MG ZS 2025"),
],
CarSpecs(mass=1295., wheelbase=2.58, steerRatio=15.8),
)
# FW query is disabled for MG for now: the MG ZS has no captured FW versions yet
# and no CAN fingerprint, so it is identified by forced car selection only.
# Defining FW_QUERY_CONFIG would put MG in the FW-query path with zero ECUs, which
# crashes fingerprinting and fails the fingerprint tests. Restore this (and
# FW_VERSIONS in fingerprints.py) once we figure out how to query FW on the MG ZS.
#
# MG_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
# p16(0xf1a0)
# MG_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40])
#
# FW_QUERY_CONFIG = FwQueryConfig(
# requests=[
# Request(
# [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_ECU_HARDWARE_NUMBER_REQUEST],
# [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_ECU_HARDWARE_NUMBER_RESPONSE],
# bus=1,
# ),
# ],
# )
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:
STEER_STEP = 2 # FVCM_HSC2_FrP03 message frequency 50Hz
STEER_MAX = 300
STEER_DELTA_UP = 10 # torque increase per refresh
STEER_DELTA_DOWN = 15 # 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 MgSafetyFlags(IntFlag):
LONG_CONTROL = 1
ALT_BRAKE = 2
NON_EV = 4
DBC = CAR.create_dbc_map()
+4
View File
@@ -16,6 +16,7 @@ from opendbc.car.values import Platform
from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN
from opendbc.car.body.values import CAR as COMMA
from opendbc.car.psa.values import CAR as PSA
from opendbc.car.mg.values import CAR as MG
# FIXME: add routes for these cars
non_tested_cars = [
@@ -34,6 +35,9 @@ non_tested_cars = [
TOYOTA.TOYOTA_COROLLA,
TOYOTA.TOYOTA_RAV4H,
# MG: no verified routes in this repo yet
MG.MG_ZS,
]
@@ -108,3 +108,6 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
# Manually checked
"HONDA_CIVIC_2022" = [2.5, 1.2, 0.15]
"HONDA_HRV_3G" = [2.5, 1.2, 0.2]
# MG (guess)
"MG_ZS" = [1.2, 2.5, 0.18]
+2 -1
View File
@@ -6,6 +6,7 @@ from opendbc.car.gm.values import CAR as GM
from opendbc.car.honda.values import CAR as HONDA
from opendbc.car.hyundai.values import CAR as HYUNDAI
from opendbc.car.mazda.values import CAR as MAZDA
from opendbc.car.mg.values import CAR as MG
from opendbc.car.mock.values import CAR as MOCK
from opendbc.car.nissan.values import CAR as NISSAN
from opendbc.car.psa.values import CAR as PSA
@@ -15,7 +16,7 @@ from opendbc.car.tesla.values import CAR as TESLA
from opendbc.car.toyota.values import CAR as TOYOTA
from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN
Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MOCK | NISSAN | PSA | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN
Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MG | MOCK | NISSAN | PSA | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN
BRANDS = get_args(Platform)
PLATFORMS: dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in brand}
+332
View File
@@ -0,0 +1,332 @@
VERSION "HSCAN2"
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: FVCM GW Diagnostics EPS SCSABS Tester
BO_ 175 GW_HSC2_HCU_FrP00: 8 GW
SG_ EPTAccelActuPosHSC2 : 7|8@0+ (0.392157,0) [0|100] "%" FVCM
SG_ EPTAccelActuPosVHSC2 : 43|1@0+ (1,0) [0|1] "" FVCM
SG_ EPTBrkPdlDscrtInptStsHSC2 : 31|1@0+ (1,0) [0|1] "" FVCM
SG_ EPTBrkPdlDscrtInptStsVHSC2 : 16|1@0+ (1,0) [0|1] "" FVCM
SG_ EPTStCmdOn_h1HSC2 : 17|1@0+ (1,0) [0|1] "" FVCM
BO_ 201 Tester_HSC2_ECM_FrP00: 8 Tester
SG_ AccelActuPosHSC2 : 39|8@0+ (0.392157,0) [0|100] "%" FVCM
SG_ AccelActuPosVHSC2 : 31|1@0+ (1,0) [0|1] "" FVCM
BO_ 251 GW_HSC2_ECM_FrP27: 8 GW
SG_ ACCStsHSC2 : 2|1@0+ (1,0) [0|1] "" XXX
SG_ SpdAstMdECMHSC2 : 52|2@0+ (1,0) [0|3] "" FVCM
SG_ SpdAstSysStsECMHSC2 : 18|3@0+ (1,0) [0|7] "" FVCM
SG_ SpdAstSysTrgtSpdHSC2 : 30|15@0+ (0.015625,0) [0|511.984] "" FVCM
SG_ TrgtSpdSrcStsHSC2 : 23|2@0+ (1,0) [0|3] "" FVCM
BO_ 355 GW_HSC2_SDM_FrP00: 8 GW
SG_ AirbagDplHSC2 : 11|1@0+ (1,0) [0|1] "" FVCM
SG_ AirbagDplInvsnHSC2 : 10|1@0+ (1,0) [0|1] "" FVCM
SG_ DrvrSbltAtcHSC2 : 12|1@0+ (1,0) [0|1] "" FVCM
SG_ DrvrSbltAtcVHSC2 : 13|1@0+ (1,0) [0|1] "" FVCM
SG_ SDMRCHSC2 : 1|2@0+ (1,0) [0|3] "" FVCM
BO_ 359 FVCM_HSC2_FrP02: 8 FVCM
SG_ AutoMainBeamLghtReqHSC2 : 15|2@0+ (1,0) [0|3] "" GW
SG_ DistSinceTrgtCamrHSC2 : 7|8@0+ (8.235,-100) [-100|1999.92] "m" GW
SG_ FVCMCalPrgsReqHSC2 : 36|3@0+ (1,0) [0|7] "" GW
SG_ HandOffStrgWhlDetnStaHSC2 : 44|2@0+ (1,0) [0|3] "" GW
SG_ HandOffStrgWhlDetnStaVHSC2 : 45|1@0+ (1,0) [0|1] "" GW
SG_ LDWLKADspCmdHSC2 : 50|3@0+ (1,0) [0|7] "" GW
SG_ LDWLKAHapticWrnngDspCmdHSC2 : 63|2@0+ (1,0) [0|3] "" GW
SG_ LDWLKALVsulznReqHSC2 : 53|3@0+ (1,0) [0|7] "" GW
SG_ LDWLKARVsulznReqHSC2 : 42|3@0+ (1,0) [0|7] "" GW
SG_ LDWSysFltStsHSC2 : 39|3@0+ (1,0) [0|7] "" GW
SG_ SpdAstReqStsCamrHSC2 : 13|2@0+ (1,0) [0|3] "" GW
SG_ TJAICADspCmdHSC2 : 55|2@0+ (1,0) [0|3] "" GW
SG_ TJAICASysFltStsHSC2 : 61|3@0+ (1,0) [0|7] "" GW,EPS
SG_ TJAICASysStsHSC2 : 58|3@0+ (1,0) [0|7] "" GW,EPS
SG_ TrgtSpdReqCamrHSC2 : 22|15@0+ (0.015625,0) [0|511.984] "" GW
BO_ 404 GW_HSC2_ECM_FrP04: 8 GW
SG_ TrEstdGearHSC2 : 3|4@0+ (1,0) [0|15] "" FVCM
SG_ TrEstdGearVHSC2 : 4|1@0+ (1,0) [0|1] "" FVCM
SG_ TrShftLvrPosV_h1HSC2 : 28|1@0+ (1,0) [0|1] "" FVCM
SG_ TrShftLvrPos_h1HSC2 : 27|4@0+ (1,0) [0|15] "" FVCM
BO_ 438 EHBS_HSC2_FrP00: 8 EHBS
SG_ BrkPdlAppdChksmHSC2 : 63|8@0+ (1,0) [0|255] "" FVCM
SG_ IbstrDiagMdAHSC2 : 55|1@0+ (1,0) [0|1] "" FVCM
SG_ RnotPrsStsHSC2 : 53|2@0+ (1,0) [0|3] "" FVCM
SG_ HydBstrCmpstnReqHSC2 : 54|1@0+ (1,0) [0|1] "" FVCM
SG_ BrkPdlAppdRCHSC2 : 51|4@0+ (1,0) [0|15] "" FVCM
SG_ RnotPrsHSC2 : 47|8@0+ (1,0) [0|250] "bar" FVCM
SG_ BrkPdlAppdHSC2 : 10|1@0+ (1,0) [0|1] "" FVCM
SG_ BrkPdlAppdVHSC2 : 9|2@0+ (1,0) [0|3] "" FVCM
BO_ 485 SAS_HSC2_FrP00: 8 EPS
SG_ StrgWhlAngHSC2 : 15|16@0+ (0.0625,-2048) [-2048|2047.88] "degree" FVCM
SG_ StrgWhlAngAlvRCHSC2 : 31|4@0+ (1,0) [0|15] "" FVCM
SG_ StrgWhlAngExtdPVHSC2 : 47|16@0+ (1,0) [0|65535] "" FVCM
SG_ StrgWhlAngGrdHSC2 : 27|12@0+ (1,-2048) [-2048|2046] "degree/s" FVCM
SG_ StrgWhlAngSnsrCalStsHSC2 : 6|2@0+ (1,0) [0|3] "" FVCM
SG_ StrgWhlAngSnsrChksmHSC2 : 63|8@0+ (1,0) [0|255] "" FVCM
SG_ StrgWhlAngSnsrFltHSC2 : 0|1@0+ (1,0) [0|1] "" FVCM
SG_ StrgWhlAngSnsrInidHSC2 : 2|1@0+ (1,0) [0|1] "" FVCM
SG_ StrgWhlAngSnsrMultCapbHSC2 : 1|1@0+ (1,0) [0|1] "" FVCM
SG_ StrgWhlAngVHSC2 : 7|1@0+ (1,0) [0|1] "" FVCM
BO_ 481 GW_HSC2_FrP04: 7 GW
SG_ CCSwStsSwDataIntgty_h2HSC2 : 1|2@0+ (1,0) [0|3] "" FDR
SG_ CCSwStsSpdDecSwA_h2HSC2 : 2|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsSpdIncSwA_h2HSC2 : 3|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsSetSwA_h2HSC2 : 4|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsRsmSwA_h2HSC2 : 5|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsOnSwA_h2HSC2 : 6|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsCanclSwA_h2HSC2 : 7|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsPV_h2HSC2 : 15|8@0+ (1,0) [0|255] "" FDR
SG_ CCSwStsAlvRC_h2HSC2 : 17|2@0+ (1,0) [0|3] "" FDR
SG_ CCSwStsDistDecSwA_h2HSC2 : 18|1@0+ (1,0) [0|1] "" FDR
SG_ CCSwStsDistIncSwA_h2HSC2 : 19|1@0+ (1,0) [0|1] "" FDR
BO_ 492 EPS_HSC2_FrP03: 8 EPS
SG_ ChLKAAlvRCHSC2 : 7|4@0+ (1,0) [0|15] "" FVCM
SG_ ChLKACtrlStsHSC2 : 54|3@0+ (1,0) [0|7] "" FVCM
SG_ ChLKARespToqHSC2 : 2|11@0+ (0.01,-10.24) [-10.24|10.23] "Nm" FVCM
SG_ ChLKARespToqPVHSC2 : 22|15@0+ (1,0) [0|32767] "" FVCM
SG_ ChLKARespToqVHSC2 : 3|1@0+ (1,0) [0|1] "" FVCM
SG_ DrvrStrgDlvrdToqHSC2 : 34|11@0+ (0.01,-10.24) [-10.24|10.23] "Nm" FVCM
SG_ DrvrStrgDlvrdToqVHSC2 : 55|1@0+ (1,0) [0|1] "" FVCM
BO_ 509 FVCM_HSC2_FrP03: 8 FVCM
SG_ LDWLKAVbnLvlReqHSC2 : 23|2@0+ (1,0) [0|3] "" GW,EPS
SG_ LKAAlvRCHSC2 : 7|4@0+ (1,0) [0|15] "" EPS
SG_ LKADrvrTkovReqHSC2 : 46|1@0+ (1,0) [0|1] "" GW,EPS
SG_ LKAReqToqHSC2 : 2|11@0+ (1,-1024) [-1024|1023] "Nm" EPS
SG_ LKAReqToqPVHSC2 : 21|14@0+ (1,0) [0|16383] "" EPS
SG_ LKAReqToqStsHSC2 : 36|2@0+ (1,0) [0|3] "" EPS
SG_ LKAReqToqVHSC2 : 3|1@0+ (1,0) [0|1] "" EPS
SG_ LKASysFltStsHSC2 : 39|3@0+ (1,0) [0|7] "" GW,EPS
SG_ LKASysStsHSC2 : 34|3@0+ (1,0) [0|7] "" GW,EPS
BO_ 516 RDA_HSC1_P02: 8 RDA
SG_ LBSDAndLCAWrnng_HS : 7|2@0+ (1,0) [0|3] "" FVCM
SG_ RBSDAndLCAWrnng_HS : 5|2@0+ (1,0) [0|3] "" FVCM
SG_ RDASysSta_HS : 23|5@0+ (1,0) [0|31] "" FVCM
BO_ 532 SCS_HSC2_FrP09: 6 SCSABS
SG_ BrkPdlDrvrAppdPrsHSC2 : 15|8@0+ (75,0) [0|19125] "kPa" FVCM
SG_ BrkPdlDrvrAppdPrsAlvRCHSC2 : 2|2@0+ (1,0) [0|3] "" FVCM
SG_ BrkPdlDrvrAppdPrsVHSC2 : 0|1@0+ (1,0) [0|1] "" FVCM
BO_ 572 SCS_HSC2_FrP19: 8 SCSABS
SG_ VehSpdAvgHSC2 : 22|15@0+ (0.015625,0) [0|511.984] "km/h" FVCM,FDR
SG_ VehSpdAvgAlvRCHSC2 : 39|4@0+ (1,0) [0|15] "" FVCM,FDR
SG_ VehSpdAvgPVHSC2 : 7|16@0+ (1,0) [0|65535] "" FVCM,FDR
SG_ VehSpdAvgVHSC2 : 23|1@0+ (1,0) [0|1] "" FVCM,FDR
BO_ 578 RADAR_HSC2_FrP00: 8 FDR
SG_ ACCAccReqValHSC2 : 2|11@0+ (0.005,-7.22) [-7.22|3.015] "" SCSABS
SG_ ACCSysAlvRlngCtr_SCSHSC2 : 6|4@0+ (1,0) [0|15] "" SCSABS
SG_ ACCMinBrkReqStsHSC2 : 7|1@0+ (1,0) [0|1] "" SCSABS
SG_ ACCAccReqValTolMaxHSC2 : 22|7@0+ (0.025,0) [0|3.175] "" SCSABS
SG_ ACCReqBrkPrfrdHSC2 : 23|1@0+ (1,0) [0|1] "" SCSABS
SG_ ACCAccReqStsHSC2 : 29|2@0+ (1,0) [0|3] "" GW,SCSABS
SG_ ACCGoReqHSC2 : 30|1@0+ (1,0) [0|1] "" SCSABS
SG_ ACCSysFltSts_SCSHSC2 : 42|3@0+ (1,0) [0|7] "" SCSABS
SG_ ACCSysSts_RadarHSC2 : 45|3@0+ (1,0) [0|7] "" GW,SCSABS
SG_ ChACCShtdwnMdHSC2 : 47|2@0+ (1,0) [0|3] "" SCSABS
SG_ ACCAccReqValTolMinHSC2 : 54|7@0+ (0.025,0) [0|3.175] "" SCSABS
SG_ ACCSdslReq_RadarHSC2 : 55|1@0+ (1,0) [0|1] "" SCSABS
SG_ ACCSysChksm_SCSHSC2 : 63|8@0+ (1,0) [0|255] "" SCSABS
BO_ 582 RADAR_HSC2_FrP02: 8 FDR
SG_ ACCDrvrSelTrgtSpd_RadarHSC2 : 6|15@0+ (0.015625,0) [0|511.984] "" GW
SG_ ACCObjDet_RadarHSC2 : 7|1@0+ (1,0) [0|1] "" GW
SG_ AEBMsgReqHSC2 : 19|4@0+ (1,0) [0|15] "" GW
SG_ ACCMsgReqHSC2 : 23|4@0+ (1,0) [0|15] "" GW
SG_ ACCDetObjDistLvl_RadarHSC2 : 26|3@0+ (1,0) [0|7] "" GW
SG_ ACCDrvrSeldTrgtDistLvl_RadarHSC2 : 29|3@0+ (1,0) [0|7] "" GW
SG_ ACCSysCanclReq_RadarHSC2 : 31|2@0+ (1,0) [0|3] "" GW
SG_ RdrCalPrgsReqHSC2 : 34|3@0+ (1,0) [0|7] "" GW
SG_ ACCGoNotfr_RadarHSC2 : 35|1@0+ (1,0) [0|1] "" GW
SG_ ACCSysFltSts_RadarHSC2 : 38|3@0+ (1,0) [0|7] "" GW
SG_ ACCDrvrTkovReqHSC2 : 39|1@0+ (1,0) [0|1] "" GW
SG_ FCWSysFltSts_RadarHSC2 : 42|3@0+ (1,0) [0|7] "" GW
SG_ FCWSnstvtLvl_RadarHSC2 : 45|3@0+ (1,0) [0|7] "" GW
SG_ AEBPedtrnDspCmdHSC2 : 47|2@0+ (1,0) [0|3] "" GW
SG_ FCWrnngSts_RadarHSC2 : 51|3@0+ (1,0) [0|7] "" GW
SG_ FCWDspCmd_RadarHSC2 : 53|2@0+ (1,0) [0|3] "" GW
SG_ AEBDspCmd_RadarHSC2 : 55|2@0+ (1,0) [0|3] "" GW
BO_ 588 SCS_HSC2_FrP22: 8 SCSABS
SG_ BrkDiscTemStsHSC2 : 6|1@0+ (1,0) [0|1] "" FDR
SG_ BrkPdlDrvrAppdPrsAlvRC_RadarHSC2 : 13|2@0+ (1,0) [0|3] "" FDR
SG_ BrkPdlDrvrAppdPrsV_RadarHSC2 : 7|1@0+ (1,0) [0|1] "" FDR
SG_ BrkPdlDrvrAppdPrs_RadarHSC2 : 23|8@0+ (75,0) [0|19125] "kPa" FDR
SG_ LDrvnWhlRotlDircnHSC2 : 15|2@0+ (1,0) [0|3] "" FDR,FVCM
SG_ RDrvnWhlRotlDircnHSC2 : 2|2@0+ (1,0) [0|3] "" FDR,FVCM
SG_ WhlBrkPrsStsHSC2 : 5|1@0+ (1,0) [0|1] "" FDR
SG_ WhlGndVelDrvnChksm_RadarHSC2 : 63|8@0+ (1,0) [0|255] "" FDR
SG_ WhlGndVelDrvnRC_RadarHSC2 : 11|4@0+ (1,0) [0|15] "" FDR
SG_ WhlGndVelLDrvnV_RadarHSC2 : 3|1@0+ (1,0) [0|1] "" FDR
SG_ WhlGndVelLDrvn_RadarHSC2 : 45|14@0+ (0.03125,0) [0|511.969] "km/h" FDR
SG_ WhlGndVelRDrvnV_RadarHSC2 : 4|1@0+ (1,0) [0|1] "" FDR
SG_ WhlGndVelRDrvn_RadarHSC2 : 29|14@0+ (0.03125,0) [0|511.969] "km/h" FDR
BO_ 593 SCS_HSC2_FrP24: 8 SCSABS
SG_ ChACCAccReqRespHSC2 : 5|3@0+ (1,0) [0|7] "" FDR
SG_ ChACCAEBAlvRlngCtr_RadarHSC2 : 20|4@0+ (1,0) [0|15] "" FDR
SG_ ChACCAEBBrkJerkReqRespHSC2 : 10|3@0+ (1,0) [0|7] "" FDR
SG_ ChACCAEBChksm_RadarHSC2 : 63|8@0+ (1,0) [0|255] "" FDR
SG_ ChACCReqFlrStsHSC2 : 15|2@0+ (1,0) [0|3] "" FDR
SG_ ChAEBDclReqRespHSC2 : 23|3@0+ (1,0) [0|7] "" FDR
SG_ ChAEBHydBrkAstReqRespHSC2 : 2|3@0+ (1,0) [0|7] "" FDR
SG_ ChAEBPrflReqRespHSC2 : 13|3@0+ (1,0) [0|7] "" FDR
SG_ VehSdslStsHSC2 : 7|2@0+ (1,0) [0|3] "" FDR
SG_ VehTrgtLongtAccHSC2 : 31|8@0+ (0.05,-7) [-7|5.75] "" FDR
BO_ 851 SCS_HSC2_FrP15: 8 SCSABS
SG_ VehSpdAvgDrvnHSC2 : 6|15@0+ (0.015625,0) [0|511.984] "km/h" FVCM
SG_ VehSpdAvgDrvnVHSC2 : 7|1@0+ (1,0) [0|1] "" FVCM
SG_ VehSpdAvgNonDrvnHSC2 : 38|15@0+ (0.015625,0) [0|511.984] "km/h" FVCM
SG_ VehSpdAvgNonDrvnVHSC2 : 39|1@0+ (1,0) [0|1] "" FVCM
BO_ 1130 GW_HSC2_BCM_FrP04: 8 GW
SG_ BlinkerBulbLeft : 37|1@0+ (1,0) [0|1] "" XXX
SG_ BlinkerBulbRight : 38|1@0+ (1,0) [0|1] "" XXX
SG_ BlinkerLeft : 59|1@0+ (1,0) [0|1] "" XXX
SG_ BlinkerRight : 60|1@0+ (1,0) [0|1] "" XXX
SG_ DipdBeamLghtOnHSC2 : 13|1@0+ (1,0) [0|1] "" FVCM
SG_ DircnIndLampSwStsHSC2 : 3|2@0+ (1,0) [0|3] "" FVCM
SG_ DspMeasSysHSC2 : 44|1@0+ (1,0) [0|1] "" FVCM
SG_ FrtFogLghtOnHSC2 : 14|1@0+ (1,0) [0|1] "" FVCM
SG_ FrtWiperParkPosAHSC2 : 52|1@0+ (1,0) [0|1] "" FVCM
SG_ FrtWshrPumpAHSC2 : 55|1@0+ (1,0) [0|1] "" FVCM
SG_ LDircnIndLghtFHSC2 : 10|1@0+ (1,0) [0|1] "" FVCM
SG_ LDircnIOHSC2 : 11|1@0+ (1,0) [0|1] "" FVCM
SG_ MainBeamLghtOnHSC2 : 15|1@0+ (1,0) [0|1] "" FVCM
SG_ RDircnIndLghtFHSC2 : 48|1@0+ (1,0) [0|1] "" FVCM
SG_ RDircnIOHSC2 : 9|1@0+ (1,0) [0|1] "" FVCM
SG_ RrFogLghtOnHSC2 : 8|1@0+ (1,0) [0|1] "" FVCM
SG_ VehSideLghtStsHSC2 : 57|2@0+ (1,0) [0|3] "" FVCM
SG_ DrvrDoorOpenSts_H1_Safety : 47|2@0+ (1,0) [0|3] "" xxx
SG_ FrtPsngDoorOpenSts_H1_Safety : 43|2@0+ (1,0) [0|3] "" xxx
SG_ RRDoorOpenSts_Safety : 41|2@0+ (1,0) [0|3] "" xxx
VAL_ 355 AirbagDplInvsnHSC2 1 "No Airbag Deployed" 0 "Airbag Deployed";
VAL_ 355 AirbagDplHSC2 1 "True" 0 "False";
VAL_ 355 DrvrSbltAtcHSC2 1 "True" 0 "False";
VAL_ 355 DrvrSbltAtcVHSC2 1 "Invalid" 0 "Valid";
VAL_ 404 TrEstdGearHSC2 15 "Park Gear" 14 "Reverse Gear" 13 "Neutral Gear" 8 "Eighth Gear" 7 "Seventh Gear" 6 "Sixth Gear" 5 "Fifth Gear" 4 "Fourth Gear" 3 "Third Gear" 2 "Second Gear" 1 "First Gear" 0 "Not Supported";
VAL_ 404 TrEstdGearVHSC2 1 "Invalid" 0 "Valid";
VAL_ 404 TrShftLvrPos_h1HSC2 15 "Lever Position Unknown" 11 "Forward Range H" 10 "Forward Range G" 9 "Forward Range F" 8 "Forward Range E" 7 "Forward Range D" 6 "Forward Range C" 5 "Forward Range B" 4 "Forward Range A" 3 "Neutral Range" 2 "Reverse Range" 1 "Park Range" 0 "Between Ranges";
VAL_ 404 TrShftLvrPosV_h1HSC2 1 "Invalid" 0 "Valid";
VAL_ 438 RnotPrsStsHSC2 2 "Faulty" 1 "Normal" 0 "Init" ;
VAL_ 438 HydBstrCmpstnReqHSC2 1 "HBC active" 0 "HBC inactive" ;
VAL_ 438 BrkPdlAppdHSC2 1 "brake pedal applied" 0 "brake pedal not applied" ;
VAL_ 438 BrkPdlAppdVHSC2 2 "Faulty" 1 "Normal" 0 "Init" ;
VAL_ 481 CCSwStsSwDataIntgty_h2HSC2 3 "Illegal Range" 2 "Failure Detected" 1 "Data Invalid" 0 "Data Valid";
VAL_ 481 CCSwStsSpdDecSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsSpdIncSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsSetSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsRsmSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsOnSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsCanclSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsDistDecSwA_h2HSC2 1 "True" 0 "False";
VAL_ 481 CCSwStsDistIncSwA_h2HSC2 1 "True" 0 "False";
VAL_ 509 LKAReqToqVHSC2 1 "Invalid" 0 "Valid";
VAL_ 509 LDWLKAVbnLvlReqHSC2 3 "Level 3" 2 "Level 2" 1 "Level 1" 0 "no request";
VAL_ 509 LKASysStsHSC2 3 "Override" 2 "Active" 1 "Stand by" 0 "Off";
VAL_ 509 LKAReqToqStsHSC2 3 "reserved" 2 "reserved" 1 "torque request" 0 "no request";
VAL_ 509 LKASysFltStsHSC2 3 "service required" 2 "system temporary unavailable" 1 "performance degradation" 0 "no error";
VAL_ 509 LKADrvrTkovReqHSC2 1 "True" 0 "False";
VAL_ 578 ACCMinBrkReqStsHSC2 1 "no demand" 0 "demand";
VAL_ 578 ACCReqBrkPrfrdHSC2 1 "no demand" 0 "demand";
VAL_ 578 ACCAccReqStsHSC2 1 "ACC Acceleration Request" 0 "No Request";
VAL_ 578 ACCGoReqHSC2 1 "Request" 0 "No Request";
VAL_ 578 ACCSysFltSts_SCSHSC2 7 "Reserved" 6 "Reserved" 5 "Reserved" 4 "Reserved" 3 "Service Required" 2 "System Temporary Unvailable" 1 "Performance Degradation" 0 "No Error";
VAL_ 578 ACCSysSts_RadarHSC2 7 "Reserved" 6 "Standstill Wait" 5 "Standstill Active" 4 "Brake Only" 3 "Override" 2 "Active" 1 "Stand By" 0 "Off";
VAL_ 578 ChACCShtdwnMdHSC2 3 "immediate off" 2 "initial" 1 "fast off" 0 "soft off";
VAL_ 578 ACCSdslReq_RadarHSC2 1 "request" 0 "no request";
VAL_ 582 ACCObjDet_RadarHSC2 1 "TRUE" 0 "FALSE";
VAL_ 582 AEBMsgReqHSC2 7 "reserved" 6 "Radar Error" 5 "AEB is switched off" 4 "AEB is switched on" 3 "AEB is in error mode" 2 "Active" 1 "unable to active AEB" 0 "No display";
VAL_ 582 ACCMsgReqHSC2 15 "Reserved" 14 "Reserved" 13 "Reserved" 12 "Reserved" 11 "Reserved" 10 "Reserved" 9 "Radar Error" 8 "depress acceleration pedal or press resume switch to go" 7 "Driver Takeover Request" 6 "ACC is switched off" 5 "ACC is switched on" 4 "ACC is in error mode" 3 "Active" 2 "ACC is cancelled" 1 "unable to active ACC" 0 "No display";
VAL_ 582 ACCDetObjDistLvl_RadarHSC2 7 "reserved" 6 "reserved" 5 "distance level5" 4 "distance level4" 3 "distance level3" 2 "distance level2" 1 "distance level1" 0 "no gap set";
VAL_ 582 ACCDrvrSeldTrgtDistLvl_RadarHSC2 7 "reserved" 6 "reserved" 5 "distance level5" 4 "distance level4" 3 "distance level3" 2 "distance level2" 1 "distance level1" 0 "no gap set";
VAL_ 582 ACCSysCanclReq_RadarHSC2 3 "Reserved" 2 "ACC Condition Dissatisfy" 1 "Manual Cancel" 0 "No Cancel";
VAL_ 582 RdrCalPrgsReqHSC2 5 "calibration failure" 4 "Calibration Finished, need Adjust" 3 "Calibration Finished, Succesful" 2 "Calibration in progress" 1 "Calibration Started" 0 "no request";
VAL_ 582 ACCGoNotfr_RadarHSC2 1 "TRUE" 0 "FALSE";
VAL_ 582 ACCSysFltSts_RadarHSC2 7 "Reserved" 6 "Reserved" 5 "Reserved" 4 "Reserved" 3 "Service Required" 2 "System Temporary Unvailable" 1 "Performance Degradation" 0 "No Error";
VAL_ 582 ACCDrvrTkovReqHSC2 1 "True" 0 "False";
VAL_ 582 FCWSysFltSts_RadarHSC2 7 "Reserved" 6 "Reserved" 5 "Reserved" 4 "Reserved" 3 "Service required" 2 "System temporary unvailable" 1 "Performance degradation" 0 "No error";
VAL_ 582 FCWSnstvtLvl_RadarHSC2 7 "reserved" 6 "reserved" 5 "reserved" 4 "reserved" 3 "level3" 2 "level2" 1 "level1" 0 "Unavailable";
VAL_ 582 AEBPedtrnDspCmdHSC2 3 "reserved" 2 "on" 1 "off" 0 "unavailable";
VAL_ 582 FCWrnngSts_RadarHSC2 7 "reserved" 6 "reserved" 5 "reserved" 4 "reserved" 3 "level 3" 2 "level 2" 1 "level 1" 0 "no request";
VAL_ 582 FCWDspCmd_RadarHSC2 3 "reserved" 2 "on" 1 "off" 0 "unavailable";
VAL_ 582 AEBDspCmd_RadarHSC2 3 "reserved" 2 "on" 1 "off" 0 "unavailable";
VAL_ 588 BrkDiscTemStsHSC2 1 "Temperature too high" 0 "Not high" ;
VAL_ 588 BrkPdlDrvrAppdPrsV_RadarHSC2 1 "Invalid" 0 "Valid" ;
VAL_ 588 LDrvnWhlRotlDircnHSC2 3 "Initial/Invalid" 2 "Backward" 1 "Forward" 0 "Unknown" ;
VAL_ 588 RDrvnWhlRotlDircnHSC2 3 "Initial/Invalid" 2 "Backward" 1 "Forward" 0 "Unknown" ;
VAL_ 588 WhlBrkPrsStsHSC2 1 "No brake force" 0 "Exist brake force" ;
VAL_ 588 WhlGndVelLDrvnV_RadarHSC2 1 "Invalid" 0 "Valid" ;
VAL_ 588 WhlGndVelRDrvnV_RadarHSC2 1 "Invalid" 0 "Valid" ;
VAL_ 593 ChACCAccReqRespHSC2 7 "reserved" 6 "reserved" 4 "pre-condition not satisfied" 3 "control not allowed for error" 2 "lost arbitration" 1 "request honored" 0 "no request" ;
VAL_ 593 ChACCAEBBrkJerkReqRespHSC2 7 "reserve" 6 "reserve" 4 "pre-condition not satisfied" 3 "control not allowed for error" 2 "lost arbitration" 1 "request honored" 0 "no request" ;
VAL_ 593 ChACCReqFlrStsHSC2 3 "not defined" 2 "irreversible error" 1 "reversible error" 0 "No error" ;
VAL_ 593 ChAEBDclReqRespHSC2 7 "reserved" 6 "reserved" 4 "pre-condition not satisfied" 3 "control not allowed for error" 2 "lost arbitration" 1 "request honored" 0 "no request" ;
VAL_ 593 ChAEBHydBrkAstReqRespHSC2 7 "reserve" 6 "reserve" 4 "pre-condition not satisfied" 3 "control not allowed for error" 2 "lost arbitration" 1 "request honored" 0 "no request" ;
VAL_ 593 ChAEBPrflReqRespHSC2 7 "reserve" 6 "reserve" 4 "pre-condition not satisfied" 3 "control not allowed for error" 2 "lost arbitration" 1 "request honored" 0 "no request" ;
VAL_ 593 VehSdslStsHSC2 3 "reserved" 2 "invalid (short unavailability, max 3s)" 1 "standstill" 0 "not standstill" ;
VAL_ 851 VehSpdAvgDrvnVHSC2 1 "Invalid" 0 "Valid" ;
VAL_ 851 VehSpdAvgNonDrvnVHSC2 1 "Invalid" 0 "Valid" ;
VAL_ 1130 BntOpenStsHSC2 3 "Reserved" 2 "Bonnet Switch Disconnect" 1 "Bonnet Open" 0 "Bonnet Closed" ;
VAL_ 1130 DipdBeamLghtOnHSC2 1 "True" 0 "False" ;
VAL_ 1130 DircnIndLampSwStsHSC2 3 "reserve" 2 "Right on" 1 "Left on" 0 "off" ;
VAL_ 1130 DrvrDoorOpenStsHSC2 3 "Driver Door Full Open" 2 "Driver Door Ajar" 1 "Driver Door Open(For latch switch can't detect door ajar status)" 0 "Driver Door Closed" ;
VAL_ 1130 DspMeasSysHSC2 1 "mph" 0 "kph" ;
VAL_ 1130 FrtFogLghtOnHSC2 1 "True" 0 "False" ;
VAL_ 1130 FrtPsngDoorOpenStsHSC2 3 "Front Passenger Door Full Open" 2 "Front Passenger Door Ajar" 1 "Front Passenger Open(latch switch cann¡®t detect door ajar statu" 0 "Front Passenger Door Closed" ;
VAL_ 1130 FrtWiperParkPosAHSC2 1 "True" 0 "False" ;
VAL_ 1130 FrtWshrPumpAHSC2 1 "True" 0 "False" ;
VAL_ 1130 KeyDetIndxHSC2 7 "error" 6 "key 6 is detected" 5 "key 5 is detected" 4 "key 4 is detected" 3 "key 3 is detected" 2 "key 2 is detected" 1 "key 1 is detected" 0 "non key is detected" ;
VAL_ 1130 LDircnIndLghtFHSC2 1 "True" 0 "False" ;
VAL_ 1130 LDircnIOHSC2 1 "True" 0 "False" ;
VAL_ 1130 LdspcOpenStsHSC2 3 "Reserved" 2 "Reserved" 1 "Load Space Open" 0 "Load Space Closed" ;
VAL_ 1130 MainBeamLghtOnHSC2 1 "True" 0 "False" ;
VAL_ 1130 RDircnIndLghtFHSC2 1 "True" 0 "False" ;
VAL_ 1130 RDircnIOHSC2 1 "True" 0 "False" ;
VAL_ 1130 RLDoorOpenStsHSC2 3 "Rear Left Door Full Open" 2 "Rear Left Door Ajar" 1 "Rear Left Door Open(latch switch cann't detect door ajar status" 0 "Rear Left Door Closed" ;
VAL_ 1130 RRDoorOpenStsHSC2 3 "Rear Right Door Full Open" 2 "Rear Right Door Ajar" 1 "Rear Right Door Open(latch switch cann't detect door ajar status" 0 "Rear Right Door Closed" ;
VAL_ 1130 RrFogLghtOnHSC2 1 "True" 0 "False" ;
VAL_ 1130 VehSideLghtStsHSC2 3 "All side light and license plate light on" 2 "Right side light on only" 1 "Left side light on only" 0 "No side light on " ;
@@ -34,6 +34,7 @@
#define SAFETY_PSA 31U
#define SAFETY_RIVIAN 33U
#define SAFETY_VOLKSWAGEN_MEB 34U
#define SAFETY_MG 35U
#define GET_BIT(msg, b) ((bool)!!(((msg)->data[((b) / 8U)] >> ((b) % 8U)) & 0x1U))
#define GET_FLAG(value, mask) (((value) & (mask)) == (mask))
+134
View File
@@ -0,0 +1,134 @@
#pragma once
#include "opendbc/safety/declarations.h"
static bool mg_zs_ev_brake = false;
static bool mg_non_ev = false;
static void mg_rx_hook(const CANPacket_t *msg) {
if (msg->bus == 0U) {
// Vehicle speed
if (msg->addr == 0x23cU) {
float speed = (((msg->data[2] & 0x7FU) << 8) | msg->data[3]) * 0.015625;
vehicle_moving = speed > 0.0;
UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS);
}
// Gas pressed
if (mg_non_ev) {
if (msg->addr == 0xc9U) {
gas_pressed = msg->data[4] != 0U;
}
} else {
if (msg->addr == 0xafU) {
gas_pressed = msg->data[0] != 0U;
}
}
// Driver torque
if (msg->addr == 0x1ecU) {
int torque_driver_new = (((msg->data[4] & 0x7U) << 8) | msg->data[5]) - 1024U;
update_sample(&torque_driver, torque_driver_new);
}
// Brake pressed
if (mg_non_ev) {
if (msg->addr == 0x214U) {
brake_pressed = msg->data[1] != 0U;
}
} else if (mg_zs_ev_brake) {
if (msg->addr == 0xafU) {
brake_pressed = GET_BIT(msg, 31U);
}
} else {
if (msg->addr == 0x1b6U) {
brake_pressed = GET_BIT(msg, 10U);
}
}
// Cruise state
if (msg->addr == 0x242U) {
int cruise_state = (msg->data[5] & 0x38U) >> 3;
bool cruise_engaged = (cruise_state == 2) || // Active
(cruise_state == 3); // Override
pcm_cruise_check(cruise_engaged);
// dp - ALKA: ACC main on (any non-Off state) enables lane keep without engagement
if (alka_allowed && ((alternative_experience & ALT_EXP_ALKA) != 0)) {
lkas_on = cruise_state != 0;
}
}
}
}
static bool mg_tx_hook(const CANPacket_t *msg) {
const TorqueSteeringLimits MG_STEERING_LIMITS = {
.max_torque = 300,
.max_rate_up = 10,
.max_rate_down = 15,
.max_rt_delta = 125,
.driver_torque_multiplier = 2,
.driver_torque_allowance = 100,
.type = TorqueDriverLimited,
};
bool tx = true;
bool violation = false;
// Steering control
if (msg->addr == 0x1fdU) {
int desired_torque = (((msg->data[0] & 0x7U) << 8) | msg->data[1]) - 1024U;
bool steer_req = GET_BIT(msg, 35U);
violation |= steer_torque_cmd_checks(desired_torque, steer_req, MG_STEERING_LIMITS);
}
if (violation) {
tx = false;
}
return tx;
}
#define MG_COMMON_RX_CHECKS \
{.msg = {{0x23c, 0, 8, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* SCS_HSC2_FrP19 */ \
{.msg = {{0x1ec, 0, 8, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* EPS_HSC2_FrP03 */ \
{.msg = {{0x242, 0, 8, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* RADAR_HSC2_FrP00 */
static safety_config mg_init(uint16_t param) {
alka_allowed = true; // dp - ALKA enabled for MG
static const CanMsg MG_TX_MSGS[] = {{0x1fd, 0, 8, .check_relay = true}};
static RxCheck mg_rx_checks[] = {
MG_COMMON_RX_CHECKS
{.msg = {{0xaf, 0, 8, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // GW_HSC2_HCU_FrP00 (gas pedal)
{.msg = {{0x1b6, 0, 8, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EHBS_HSC2_FrP00 (brake pedal)
};
static RxCheck mg_rx_checks_non_ev[] = {
MG_COMMON_RX_CHECKS
{.msg = {{0xc9, 0, 8, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // Tester_HSC2_ECM_FrP00 (gas pedal)
{.msg = {{0x214, 0, 6, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // SCS_HSC2_FrP09 (brake pressure)
};
const uint16_t MG_PARAM_ALT_BRAKE = 2;
const uint16_t MG_PARAM_NON_EV = 4;
mg_zs_ev_brake = GET_FLAG(param, MG_PARAM_ALT_BRAKE);
mg_non_ev = GET_FLAG(param, MG_PARAM_NON_EV);
safety_config ret;
SET_TX_MSGS(MG_TX_MSGS, ret);
if (mg_non_ev) {
SET_RX_CHECKS(mg_rx_checks_non_ev, ret);
} else {
SET_RX_CHECKS(mg_rx_checks, ret);
}
return ret;
}
const safety_hooks mg_hooks = {
.init = mg_init,
.rx = mg_rx_hook,
.tx = mg_tx_hook,
};
+2
View File
@@ -27,6 +27,7 @@
#include "opendbc/safety/modes/elm327.h"
#include "opendbc/safety/modes/body.h"
#include "opendbc/safety/modes/psa.h"
#include "opendbc/safety/modes/mg.h"
#ifdef CANFD
#include "opendbc/safety/modes/hyundai_canfd.h"
@@ -459,6 +460,7 @@ int set_safety_hooks(uint16_t mode, uint16_t param) {
{SAFETY_BODY, &body_hooks},
{SAFETY_FORD, &ford_hooks},
{SAFETY_RIVIAN, &rivian_hooks},
{SAFETY_MG, &mg_hooks},
{SAFETY_TESLA, &tesla_hooks},
#ifdef CANFD
{SAFETY_HYUNDAI_CANFD, &hyundai_canfd_hooks},
@@ -858,5 +858,96 @@ class TestALKALatControlAllowed(unittest.TestCase):
f"alka_flag={alka_flag}, lkas_on={lkas_on}, vehicle_moving={vehicle_moving}")
class TestALKAMG(TestALKABase):
"""Test ALKA functionality for MG (MG ZS)."""
def setUp(self):
self.packer = CANPackerSafety("mg")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.mg, 4) # NON_EV (MG ZS)
self.safety.init_tests()
self.safety.set_alternative_experience(ALTERNATIVE_EXPERIENCE.ALKA)
def _speed_msg(self, speed):
values = {"VehSpdAvgHSC2": speed * 3.6}
return self.packer.make_can_msg_safety("SCS_HSC2_FrP19", 0, values)
def _set_vehicle_moving(self, moving: bool):
speed = 10.0 if moving else 0.0
for _ in range(6):
self._rx(self._speed_msg(speed))
def _torque_cmd_msg(self, torque, steer_req=1):
values = {"LKAReqToqHSC2": torque, "LKAReqToqStsHSC2": steer_req}
return self.packer.make_can_msg_safety("FVCM_HSC2_FrP03", 0, values)
def _torque_driver_msg(self, torque):
values = {"DrvrStrgDlvrdToqHSC2": torque}
return self.packer.make_can_msg_safety("EPS_HSC2_FrP03", 0, values)
def _acc_main_msg(self, main_on):
# ACCSysSts: 0 = Off, 1 = Stand By (main on); any non-zero = main on
values = {"ACCSysSts_RadarHSC2": 1 if main_on else 0}
return self.packer.make_can_msg_safety("RADAR_HSC2_FrP00", 0, values)
def _set_prev_torque(self, t):
self.safety.set_desired_torque_last(t)
self.safety.set_rt_torque_last(t)
def test_alka_allowed_for_mg(self):
"""alka_allowed is set in MG safety init."""
self.assertTrue(self.safety.get_alka_allowed())
def test_alka_lkas_on_from_acc_main(self):
"""lkas_on tracks the ACC main state (any non-Off ACCSysSts)."""
self._rx(self._acc_main_msg(0))
self.assertFalse(self.safety.get_lkas_on())
self._rx(self._acc_main_msg(1))
self.assertTrue(self.safety.get_lkas_on())
self._rx(self._acc_main_msg(0))
self.assertFalse(self.safety.get_lkas_on())
def test_alka_lat_control_allowed_conditions(self):
"""lat_control_allowed requires ALKA flag + lkas_on + vehicle_moving."""
self._reset_safety_hooks()
self.safety.set_controls_allowed(False)
# No ALKA flag -> follows controls_allowed (False)
self.safety.set_alternative_experience(ALTERNATIVE_EXPERIENCE.DEFAULT)
self._rx(self._acc_main_msg(1))
self._set_vehicle_moving(True)
self.assertFalse(self.safety.get_lat_control_allowed())
# ALKA flag but not moving
self.safety.set_alternative_experience(ALTERNATIVE_EXPERIENCE.ALKA)
self._set_vehicle_moving(False)
self.assertFalse(self.safety.get_lat_control_allowed())
# Moving but main off (lkas_on false)
self._set_vehicle_moving(True)
self._rx(self._acc_main_msg(0))
self.assertFalse(self.safety.get_lat_control_allowed())
# All conditions met
self._rx(self._acc_main_msg(1))
self._set_vehicle_moving(True)
self.assertTrue(self.safety.get_lat_control_allowed())
def test_alka_allows_steering_without_controls_allowed(self):
"""Torque TX is allowed via ALKA even when controls_allowed=False."""
self._reset_safety_hooks()
self.safety.set_alternative_experience(ALTERNATIVE_EXPERIENCE.ALKA)
self._rx(self._acc_main_msg(1))
self._set_vehicle_moving(True)
self.safety.set_controls_allowed(False)
self._set_prev_torque(0)
for _ in range(6):
self._rx(self._torque_driver_msg(0))
self.assertTrue(self._tx(self._torque_cmd_msg(10, steer_req=1)))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
import unittest
from opendbc.car.structs import CarParams
from opendbc.safety.tests.libsafety import libsafety_py
import opendbc.safety.tests.common as common
from opendbc.safety.tests.common import CANPackerSafety
class TestMGSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest):
TX_MSGS = [[0x1fd, 0], ]
RELAY_MALFUNCTION_ADDRS = {0: (0x1fd,)}
FWD_BLACKLISTED_ADDRS = {2: [0x1fd,]}
MAX_RATE_UP = 10
MAX_RATE_DOWN = 15
MAX_TORQUE_LOOKUP = [0], [300]
MAX_RT_DELTA = 125
DRIVER_TORQUE_ALLOWANCE = 100
DRIVER_TORQUE_FACTOR = 2
def setUp(self):
self.packer = CANPackerSafety("mg")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.mg, 0)
self.safety.init_tests()
def _torque_cmd_msg(self, torque, steer_req=1):
values = {"LKAReqToqHSC2": torque, "LKAReqToqStsHSC2": steer_req}
return self.packer.make_can_msg_safety("FVCM_HSC2_FrP03", 0, values)
def _speed_msg(self, speed):
values = {"VehSpdAvgHSC2": speed * 3.6}
return self.packer.make_can_msg_safety("SCS_HSC2_FrP19", 0, values)
def _torque_driver_msg(self, torque):
values = {"DrvrStrgDlvrdToqHSC2": torque * 0.01}
return self.packer.make_can_msg_safety("EPS_HSC2_FrP03", 0, values)
def _user_brake_msg(self, brake):
values = {"BrkPdlAppdHSC2": 1 if brake else 0}
return self.packer.make_can_msg_safety("EHBS_HSC2_FrP00", 0, values)
def _user_gas_msg(self, gas):
values = {"EPTAccelActuPosHSC2": 100 if gas else 0}
return self.packer.make_can_msg_safety("GW_HSC2_HCU_FrP00", 0, values)
def _pcm_status_msg(self, enable):
values = {"ACCSysSts_RadarHSC2": 2 if enable else 1}
return self.packer.make_can_msg_safety("RADAR_HSC2_FrP00", 0, values)
class TestMGAltBrakeSafety(TestMGSafety):
def setUp(self):
self.packer = CANPackerSafety("mg")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.mg, 2)
self.safety.init_tests()
def _user_brake_msg(self, brake):
values = {"EPTBrkPdlDscrtInptStsHSC2": 1 if brake else 0}
return self.packer.make_can_msg_safety("GW_HSC2_HCU_FrP00", 0, values)
class TestMGNonEvSafety(TestMGSafety):
def setUp(self):
self.packer = CANPackerSafety("mg")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.mg, 4)
self.safety.init_tests()
def _user_brake_msg(self, brake):
values = {"BrkPdlDrvrAppdPrsHSC2": 150 if brake else 0}
return self.packer.make_can_msg_safety("SCS_HSC2_FrP09", 0, values)
def _user_gas_msg(self, gas):
values = {"AccelActuPosHSC2": 50 if gas else 0}
return self.packer.make_can_msg_safety("Tester_HSC2_ECM_FrP00", 0, values)
if __name__ == "__main__":
unittest.main()