Files
github-actions[bot] 6f34f74e9b sunnypilot v2026.001.000 release
date: 2026-04-10T22:07:44
master commit: 4ba0c4b574bff994e9a8f7266b4969b39380a8b1
2026-04-10 22:07:52 +08:00

112 lines
3.8 KiB
Python

"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import time
import cereal.messaging as messaging
from cereal import log, custom
from opendbc.car import structs
from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog
from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
from openpilot.sunnypilot.selfdrive.controls.lib.blinker_pause_lateral import BlinkerPauseLateral
from openpilot.sunnypilot.selfdrive.controls.lib.latcontrol_torque_v0 import LatControlTorque as LatControlTorqueV0
class ControlsExt(ModelStateBase):
def __init__(self, CP: structs.CarParams, params: Params):
ModelStateBase.__init__(self)
self.CP = CP
self.params = params
self._param_update_time: float = 0.0
self.blinker_pause_lateral = BlinkerPauseLateral()
cloudlog.info("controlsd_ext is waiting for CarParamsSP")
self.CP_SP = messaging.log_from_bytes(params.get("CarParamsSP", block=True), custom.CarParamsSP)
cloudlog.info("controlsd_ext got CarParamsSP")
self.sm_services_ext = ['radarState', 'selfdriveStateSP']
self.pm_services_ext = ['carControlSP']
def initialize_lateral_control(self, lac, CI, dt):
enforce_torque_control = self.params.get_bool("EnforceTorqueControl")
torque_versions = self.params.get("TorqueControlTune")
if not enforce_torque_control:
return lac
if torque_versions == 0.0: # v0
return LatControlTorqueV0(self.CP, self.CP_SP, CI, dt)
else:
return lac
def get_params_sp(self, sm: messaging.SubMaster) -> None:
if time.monotonic() - self._param_update_time > PARAMS_UPDATE_PERIOD:
self.blinker_pause_lateral.get_params()
if self.CP.lateralTuning.which() == 'torque':
self.lat_delay = get_lat_delay(self.params, sm["liveDelay"].lateralDelay)
self._param_update_time = time.monotonic()
def get_lat_active(self, sm: messaging.SubMaster) -> bool:
if self.blinker_pause_lateral.update(sm['carState']):
return False
ss_sp = sm['selfdriveStateSP']
if ss_sp.mads.available:
return bool(ss_sp.mads.active)
# MADS not available, use stock state to engage
return bool(sm['selfdriveState'].active)
@staticmethod
def get_lead_data(ld: log.RadarState.LeadData) -> dict:
return {
"dRel": ld.dRel,
"yRel": ld.yRel,
"vRel": ld.vRel,
"aRel": ld.aRel,
"vLead": ld.vLead,
"dPath": ld.dPath,
"vLat": ld.vLat,
"vLeadK": ld.vLeadK,
"aLeadK": ld.aLeadK,
"fcw": ld.fcw,
"status": ld.status,
"aLeadTau": ld.aLeadTau,
"modelProb": ld.modelProb,
"radar": ld.radar,
"radarTrackId": ld.radarTrackId,
}
def state_control_ext(self, sm: messaging.SubMaster) -> custom.CarControlSP:
CC_SP = custom.CarControlSP.new_message()
CC_SP.leadOne = self.get_lead_data(sm['radarState'].leadOne)
CC_SP.leadTwo = self.get_lead_data(sm['radarState'].leadTwo)
# MADS state
CC_SP.mads = sm['selfdriveStateSP'].mads
CC_SP.intelligentCruiseButtonManagement = sm['selfdriveStateSP'].intelligentCruiseButtonManagement
return CC_SP
@staticmethod
def publish_ext(CC_SP: custom.CarControlSP, sm: messaging.SubMaster, pm: messaging.PubMaster) -> None:
cc_sp_send = messaging.new_message('carControlSP')
cc_sp_send.valid = sm['carState'].canValid
cc_sp_send.carControlSP = CC_SP
pm.send('carControlSP', cc_sp_send)
def run_ext(self, sm: messaging.SubMaster, pm: messaging.PubMaster) -> None:
CC_SP = self.state_control_ext(sm)
self.publish_ext(CC_SP, sm, pm)