#!/usr/bin/env python3
import unittest
import numpy as np
from cereal import log
import cereal . messaging as messaging
from selfdrive . config import Conversions as CV
from selfdrive . controls . lib . lead_mpc_lib . lead_mpc import desired_follow_distance , LeadMpc
class FakePubMaster ( ) :
def send ( self , s , data ) :
assert data
def run_following_distance_simulation ( v_lead , t_end = 200.0 ) :
dt = 0.2
t = 0.
x_lead = 200.0
x_ego = 0.0
v_ego = v_lead
a_ego = 0.0
mpc = LeadMpc ( 0 )
first = True
while t < t_end :
# Setup CarState
CS = messaging . new_message ( ' carState ' )
CS . carState . vEgo = float ( v_ego )
CS . carState . aEgo = float ( a_ego )
# Setup model packet
radarstate = messaging . new_message ( ' radarState ' )
lead = log . RadarState . LeadData . new_message ( )
lead . modelProb = .75
lead . dRel = x_lead - x_ego
lead . vLead = v_lead
lead . aLeadK = 0.0
lead . status = True
radarstate . radarState . leadOne = lead
# Run MPC
mpc . set_cur_state ( v_ego , a_ego )
if first : # Make sure MPC is converged on first timestep
for _ in range ( 20 ) :
mpc . update ( CS . carState , radarstate . radarState , 0 )
mpc . update ( CS . carState , radarstate . radarState , 0 )
# Choose slowest of two solutions
v_ego , a_ego = float ( mpc . v_solution [ 5 ] ) , float ( mpc . a_solution [ 5 ] )
# Update state
x_lead + = v_lead * dt
x_ego + = v_ego * dt
t + = dt
first = False
return x_lead - x_ego
class TestFollowingDistance ( unittest . TestCase ) :
def test_following_distanc ( self ) :
for speed_mph in np . linspace ( 10 , 100 , num = 10 ) :
v_lead = float ( speed_mph * CV . MPH_TO_MS )
simulation_steady_state = run_following_distance_simulation ( v_lead )
correct_steady_state = desired_follow_distance ( v_lead , v_lead )
self . assertAlmostEqual ( simulation_steady_state , correct_steady_state , delta = .2 )
if __name__ == " __main__ " :
unittest . main ( )