#!/usr/bin/env python
import zmq
from common . realtime import sec_since_boot
import selfdrive . messaging as messaging
from selfdrive . services import service_list
from selfdrive . controls . lib . drive_helpers import create_event , EventTypes as ET
from selfdrive . controls . lib . pathplanner import PathPlanner
from selfdrive . controls . lib . adaptivecruise import AdaptiveCruise
from selfdrive . controls . lib . fcw import ForwardCollisionWarning
_DT = 0.01 # 100Hz
class Planner ( object ) :
def __init__ ( self , CP ) :
context = zmq . Context ( )
self . CP = CP
self . live20 = messaging . sub_sock ( context , service_list [ ' live20 ' ] . port )
self . model = messaging . sub_sock ( context , service_list [ ' model ' ] . port )
self . plan = messaging . pub_sock ( context , service_list [ ' plan ' ] . port )
self . last_md_ts = 0
self . last_l20_ts = 0
self . last_model = 0.
self . last_l20 = 0.
self . model_dead = True
self . radar_dead = True
self . radar_errors = [ ]
self . PP = PathPlanner ( )
self . AC = AdaptiveCruise ( )
self . FCW = ForwardCollisionWarning ( _DT )
# this runs whenever we get a packet that can change the plan
def update ( self , CS , LoC ) :
cur_time = sec_since_boot ( )
md = messaging . recv_sock ( self . model )
if md is not None :
self . last_md_ts = md . logMonoTime
self . last_model = cur_time
self . model_dead = False
if cur_time - self . last_model > 0.5 :
self . model_dead = True
l20 = messaging . recv_sock ( self . live20 )
if l20 is not None :
self . last_l20_ts = l20 . logMonoTime
self . last_l20 = cur_time
self . radar_dead = False
self . radar_errors = list ( l20 . live20 . radarErrors )
if cur_time - self . last_l20 > 0.5 :
self . radar_dead = True
self . PP . update ( CS . vEgo , md )
# LoC.v_pid -> CS.vEgo
# TODO: is this change okay?
self . AC . update ( CS . vEgo , CS . steeringAngle , LoC . v_pid , self . CP , l20 )
# **** send the plan ****
plan_send = messaging . new_message ( )
plan_send . init ( ' plan ' )
events = [ ]
if self . model_dead :
events . append ( create_event ( ' modelCommIssue ' , [ ET . NO_ENTRY , ET . IMMEDIATE_DISABLE ] ) )
if self . radar_dead or ' commIssue ' in self . radar_errors :
events . append ( create_event ( ' radarCommIssue ' , [ ET . NO_ENTRY , ET . IMMEDIATE_DISABLE ] ) )
if ' fault ' in self . radar_errors :
events . append ( create_event ( ' radarFault ' , [ ET . NO_ENTRY , ET . IMMEDIATE_DISABLE ] ) )
plan_send . plan . events = events
plan_send . plan . mdMonoTime = self . last_md_ts
plan_send . plan . l20MonoTime = self . last_l20_ts
# lateral plan
plan_send . plan . lateralValid = not self . model_dead
plan_send . plan . dPoly = map ( float , self . PP . d_poly )
plan_send . plan . laneWidth = float ( self . PP . lane_width )
# longitudal plan
plan_send . plan . longitudinalValid = not self . radar_dead
plan_send . plan . vTarget = float ( self . AC . v_target_lead )
plan_send . plan . aTargetMin = float ( self . AC . a_target [ 0 ] )
plan_send . plan . aTargetMax = float ( self . AC . a_target [ 1 ] )
plan_send . plan . jerkFactor = float ( self . AC . jerk_factor )
plan_send . plan . hasLead = self . AC . has_lead
# compute risk of collision events: fcw
self . FCW . process ( CS , self . AC )
plan_send . plan . fcw = bool ( self . FCW . active )
self . plan . send ( plan_send . to_bytes ( ) )
return plan_send