openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
5.0 KiB

1 month ago
import os
from cereal import car, log
import cereal.messaging as messaging
from panda.python import PANDA_BUS_CNT
SPOOFING_STARTED = os.getenv("STARTED") == "1"
LEC_ERROR_CODE = {
"No error": 0, "Stuff error": 1, "Form error": 2, "AckError": 3,
"Bit1Error": 4, "Bit0Error": 5, "CRCError": 6, "NoChange": 7,
}
class PandaStateManager:
def __init__(self, pandas, hw_types):
self.pandas = pandas
self.hw_types = hw_types
self.is_comma_three_red = (
len(pandas) == 2 and
self.hw_types[0] == log.PandaState.PandaType.dos and
self.hw_types[1] == log.PandaState.PandaType.redPanda
)
def process(self, engaged, pm) -> bool:
msg = messaging.new_message('pandaStates', len(self.pandas))
msg.valid = True
panda_states = msg.pandaStates
ignition = False
for i, panda in enumerate(self.pandas):
health = panda.health() or {}
if SPOOFING_STARTED:
health['ignition_line'] = 1
# on comma three setups with a red panda, the dos can
# get false positive ignitions due to the harness box
# without a harness connector, so ignore it
if self.is_comma_three_red and i == 0:
health['ignition_line'] = 0
ignition |= bool(health['ignition_line']) or bool(health['ignition_can'])
ps = panda_states[i]
self._fill_state(ps, self.hw_types[i], health)
# Fill can state
for j in range(PANDA_BUS_CNT):
can_health = panda.can_health(j)
can_state = ps.init(f'canState{j}')
self._fill_can_state(can_state, can_health)
# Set faults
fault_bits = int(health.get('faults', 0))
faults_list = [f for f in range(log.PandaState.FaultType.relayMalfunction,
log.PandaState.FaultType.heartbeatLoopWatchdog + 1)
if fault_bits & (1 << f)]
faults = ps.init('faults', len(faults_list))
for idx, fault in enumerate(faults_list):
faults[idx] = fault
for panda, ps in zip(self.pandas, panda_states, strict=False):
if ps.safetyModel == car.CarParams.SafetyModel.silent or (
not ignition and ps.safetyModel != car.CarParams.SafetyModel.noOutput):
panda.set_safety_mode(car.CarParams.SafetyModel.noOutput)
if ps.powerSaveEnabled != (not ignition):
panda.set_power_save(not ignition)
panda.send_heartbeat(engaged)
pm.send("pandaStates", msg)
return ignition
def _fill_state(self, ps, hw_type, health):
ps.voltage = health['voltage']
ps.current = health['current']
ps.uptime = health['uptime']
ps.safetyTxBlocked = health['safety_tx_blocked']
ps.safetyRxInvalid = health['safety_rx_invalid']
ps.ignitionLine = bool(health['ignition_line'])
ps.ignitionCan = bool(health['ignition_can'])
ps.controlsAllowed = bool(health['controls_allowed'])
ps.txBufferOverflow = health['tx_buffer_overflow']
ps.rxBufferOverflow = health['rx_buffer_overflow']
ps.pandaType = hw_type
ps.safetyModel = health['safety_mode']
ps.safetyParam = health['safety_param']
ps.faultStatus = health['fault_status']
ps.powerSaveEnabled = bool(health['power_save_enabled'])
ps.heartbeatLost = bool(health['heartbeat_lost'])
ps.alternativeExperience = health['alternative_experience']
ps.harnessStatus = health['car_harness_status']
ps.interruptLoad = health['interrupt_load']
ps.fanPower = health['fan_power']
ps.safetyRxChecksInvalid = bool(health['safety_rx_checks_invalid'])
ps.spiErrorCount = health['spi_error_count']
ps.sbu1Voltage = health['sbu1_voltage_mV'] / 1000.0
ps.sbu2Voltage = health['sbu2_voltage_mV'] / 1000.0
def _fill_can_state(self, cs, can_health):
cs.busOff = bool(can_health['bus_off'])
cs.busOffCnt = can_health['bus_off_cnt']
cs.errorWarning = bool(can_health['error_warning'])
cs.errorPassive = bool(can_health['error_passive'])
cs.lastError = LEC_ERROR_CODE[can_health['last_error']]
cs.lastStoredError = LEC_ERROR_CODE[can_health['last_stored_error']]
cs.lastDataError = LEC_ERROR_CODE[can_health['last_data_error']]
cs.lastDataStoredError = LEC_ERROR_CODE[can_health['last_data_stored_error']]
cs.receiveErrorCnt = can_health['receive_error_cnt']
cs.transmitErrorCnt = can_health['transmit_error_cnt']
cs.totalErrorCnt = can_health['total_error_cnt']
cs.totalTxLostCnt = can_health['total_tx_lost_cnt']
cs.totalRxLostCnt = can_health['total_rx_lost_cnt']
cs.totalTxCnt = can_health['total_tx_cnt']
cs.totalRxCnt = can_health['total_rx_cnt']
cs.totalFwdCnt = can_health['total_fwd_cnt']
cs.canSpeed = can_health['can_speed']
cs.canDataSpeed = can_health['can_data_speed']
cs.canfdEnabled = bool(can_health['canfd_enabled'])
cs.brsEnabled = bool(can_health['brs_enabled'])
cs.canfdNonIso = bool(can_health['canfd_non_iso'])
cs.irq0CallRate = can_health['irq0_call_rate']
cs.irq1CallRate = can_health['irq1_call_rate']
cs.irq2CallRate = can_health['irq2_call_rate']
cs.canCoreResetCnt = can_health['can_core_reset_count']