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.
		
		
		
		
			
				
					109 lines
				
				3.5 KiB
			
		
		
			
		
	
	
					109 lines
				
				3.5 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								#!/usr/bin/env python3
							 | 
						||
| 
								 | 
							
								import subprocess
							 | 
						||
| 
								 | 
							
								import time
							 | 
						||
| 
								 | 
							
								import unittest
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								import os
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								from multiprocessing import Queue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from cereal import messaging
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								from common.basedir import BASEDIR
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								from selfdrive.manager.helpers import unblock_stdout
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								from tools.sim import bridge
							 | 
						||
| 
								 | 
							
								from tools.sim.bridge import CarlaBridge
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								CI = "CI" in os.environ
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								SIM_DIR = os.path.join(BASEDIR, "tools/sim")
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								class TestCarlaIntegration(unittest.TestCase):
							 | 
						||
| 
								 | 
							
								  """
							 | 
						||
| 
								 | 
							
								  Tests need Carla simulator to run
							 | 
						||
| 
								 | 
							
								  """
							 | 
						||
| 
								 | 
							
								  processes = None
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  carla_process = None
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  def setUp(self):
							 | 
						||
| 
								 | 
							
								    self.processes = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								    if not CI:
							 | 
						||
| 
								 | 
							
								      # We want to make sure that carla_sim docker isn't still running.
							 | 
						||
| 
								 | 
							
								      subprocess.run("docker rm -f carla_sim", shell=True, stderr=subprocess.PIPE, check=False)
							 | 
						||
| 
								 | 
							
								      self.carla_process = subprocess.Popen("./start_carla.sh", cwd=SIM_DIR)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    # Too many lagging messages in bridge.py can cause a crash. This prevents it.
							 | 
						||
| 
								 | 
							
								    unblock_stdout()
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    # Wait 10 seconds to startup carla
							 | 
						||
| 
								 | 
							
								    time.sleep(10)
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  def test_engage(self):
							 | 
						||
| 
								 | 
							
								    # Startup manager and bridge.py. Check processes are running, then engage and verify.
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								    p_manager = subprocess.Popen("./launch_openpilot.sh", cwd=SIM_DIR)
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    self.processes.append(p_manager)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sm = messaging.SubMaster(['controlsState', 'carEvents', 'managerState'])
							 | 
						||
| 
								 | 
							
								    q = Queue()
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    carla_bridge = CarlaBridge(bridge.parse_args([]))
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								    p_bridge = carla_bridge.run(q, retries=10)
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    self.processes.append(p_bridge)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											3 years ago
										 
									 | 
							
								    max_time_per_step = 60
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Wait for bridge to startup
							 | 
						||
| 
								 | 
							
								    start_waiting = time.monotonic()
							 | 
						||
| 
								 | 
							
								    while not carla_bridge.started and time.monotonic() < start_waiting + max_time_per_step:
							 | 
						||
| 
								 | 
							
								      time.sleep(0.1)
							 | 
						||
| 
								 | 
							
								    self.assertEqual(p_bridge.exitcode, None, f"Bridge process should be running, but exited with code {p_bridge.exitcode}")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    start_time = time.monotonic()
							 | 
						||
| 
								 | 
							
								    no_car_events_issues_once = False
							 | 
						||
| 
								 | 
							
								    car_event_issues = []
							 | 
						||
| 
								 | 
							
								    not_running = []
							 | 
						||
| 
								 | 
							
								    while time.monotonic() < start_time + max_time_per_step:
							 | 
						||
| 
								 | 
							
								      sm.update()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      not_running = [p.name for p in sm['managerState'].processes if not p.running and p.shouldBeRunning]
							 | 
						||
| 
								 | 
							
								      car_event_issues = [event.name for event in sm['carEvents'] if any([event.noEntry, event.softDisable, event.immediateDisable])]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if sm.all_alive() and len(car_event_issues) == 0 and len(not_running) == 0:
							 | 
						||
| 
								 | 
							
								        no_car_events_issues_once = True
							 | 
						||
| 
								 | 
							
								        break
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    self.assertTrue(no_car_events_issues_once, f"Failed because no messages received, or CarEvents '{car_event_issues}' or processes not running '{not_running}'")
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								    start_time = time.monotonic()
							 | 
						||
| 
								 | 
							
								    min_counts_control_active = 100
							 | 
						||
| 
								 | 
							
								    control_active = 0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while time.monotonic() < start_time + max_time_per_step:
							 | 
						||
| 
								 | 
							
								      sm.update()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      q.put("cruise_up")  # Try engaging
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if sm.all_alive() and sm['controlsState'].active:
							 | 
						||
| 
								 | 
							
								        control_active += 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if control_active == min_counts_control_active:
							 | 
						||
| 
								 | 
							
								          break
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    self.assertEqual(min_counts_control_active, control_active, f"Simulator did not engage a minimal of {min_counts_control_active} steps was {control_active}")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def tearDown(self):
							 | 
						||
| 
								 | 
							
								    print("Test shutting down. CommIssues are acceptable")
							 | 
						||
| 
								 | 
							
								    for p in reversed(self.processes):
							 | 
						||
| 
								 | 
							
								      p.terminate()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for p in reversed(self.processes):
							 | 
						||
| 
								 | 
							
								      if isinstance(p, subprocess.Popen):
							 | 
						||
| 
								 | 
							
								        p.wait(15)
							 | 
						||
| 
								 | 
							
								      else:
							 | 
						||
| 
								 | 
							
								        p.join(15)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    # Stop carla simulator by removing docker container
							 | 
						||
| 
								 | 
							
								    subprocess.run("docker rm -f carla_sim", shell=True, stderr=subprocess.PIPE, check=False)
							 | 
						||
| 
								 | 
							
								    if self.carla_process is not None:
							 | 
						||
| 
								 | 
							
								      self.carla_process.wait()
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if __name__ == "__main__":
							 | 
						||
| 
								 | 
							
								  unittest.main()
							 |