agents code updated
This commit is contained in:
parent
1bb2ccff10
commit
b85b006ad5
|
@ -1,3 +1,5 @@
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
max-line-length=120
|
||||||
[MASTER]
|
[MASTER]
|
||||||
disable=I0011,E1121
|
disable=I0011,E1121
|
||||||
[TYPECHECK]
|
[TYPECHECK]
|
||||||
|
|
|
@ -35,6 +35,8 @@ class Agent(object):
|
||||||
:param vehicle: actor to apply to local planner logic onto
|
:param vehicle: actor to apply to local planner logic onto
|
||||||
"""
|
"""
|
||||||
self._vehicle = vehicle
|
self._vehicle = vehicle
|
||||||
|
self._proximity_threshold = 10.0 # meters
|
||||||
|
self._local_planner = None
|
||||||
self._world = self._vehicle.get_world()
|
self._world = self._vehicle.get_world()
|
||||||
self._map = self._vehicle.get_world().get_map()
|
self._map = self._vehicle.get_world().get_map()
|
||||||
self._last_traffic_light = None
|
self._last_traffic_light = None
|
||||||
|
@ -46,11 +48,13 @@ class Agent(object):
|
||||||
:return: control
|
:return: control
|
||||||
"""
|
"""
|
||||||
control = carla.VehicleControl()
|
control = carla.VehicleControl()
|
||||||
control.steer = 0.0
|
|
||||||
control.throttle = 0.0
|
if debug:
|
||||||
control.brake = 0.0
|
control.steer = 0.0
|
||||||
control.hand_brake = False
|
control.throttle = 0.0
|
||||||
control.manual_gear_shift = False
|
control.brake = 0.0
|
||||||
|
control.hand_brake = False
|
||||||
|
control.manual_gear_shift = False
|
||||||
|
|
||||||
return control
|
return control
|
||||||
|
|
||||||
|
@ -96,7 +100,7 @@ class Agent(object):
|
||||||
if is_within_distance_ahead(loc, ego_vehicle_location,
|
if is_within_distance_ahead(loc, ego_vehicle_location,
|
||||||
self._vehicle.get_transform().rotation.yaw,
|
self._vehicle.get_transform().rotation.yaw,
|
||||||
self._proximity_threshold):
|
self._proximity_threshold):
|
||||||
if traffic_light.state == carla.libcarla.TrafficLightState.Red:
|
if traffic_light.state == carla.TrafficLightState.Red:
|
||||||
return (True, traffic_light)
|
return (True, traffic_light)
|
||||||
|
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
@ -119,9 +123,8 @@ class Agent(object):
|
||||||
# It is too late. Do not block the intersection! Keep going!
|
# It is too late. Do not block the intersection! Keep going!
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
if self._local_planner._target_waypoint is not None:
|
if self._local_planner.target_waypoint is not None:
|
||||||
if self._local_planner._target_waypoint.is_intersection:
|
if self._local_planner.target_waypoint.is_intersection:
|
||||||
potential_lights = []
|
|
||||||
min_angle = 180.0
|
min_angle = 180.0
|
||||||
sel_magnitude = 0.0
|
sel_magnitude = 0.0
|
||||||
sel_traffic_light = None
|
sel_traffic_light = None
|
||||||
|
@ -142,7 +145,7 @@ class Agent(object):
|
||||||
if self._last_traffic_light is None:
|
if self._last_traffic_light is None:
|
||||||
self._last_traffic_light = sel_traffic_light
|
self._last_traffic_light = sel_traffic_light
|
||||||
|
|
||||||
if self._last_traffic_light.state == carla.libcarla.TrafficLightState.Red:
|
if self._last_traffic_light.state == carla.TrafficLightState.Red:
|
||||||
return (True, self._last_traffic_light)
|
return (True, self._last_traffic_light)
|
||||||
else:
|
else:
|
||||||
self._last_traffic_light = None
|
self._last_traffic_light = None
|
||||||
|
|
|
@ -15,9 +15,9 @@ import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import carla
|
import carla
|
||||||
from agents.navigation.agent import *
|
from agents.navigation.agent import Agent, AgentState
|
||||||
from agents.navigation.local_planner import LocalPlanner
|
from agents.navigation.local_planner import LocalPlanner
|
||||||
from agents.navigation.local_planner import compute_connection, RoadOption
|
from agents.navigation.local_planner import RoadOption
|
||||||
from agents.navigation.global_route_planner import GlobalRoutePlanner
|
from agents.navigation.global_route_planner import GlobalRoutePlanner
|
||||||
from agents.navigation.global_route_planner_dao import GlobalRoutePlannerDAO
|
from agents.navigation.global_route_planner_dao import GlobalRoutePlannerDAO
|
||||||
from agents.tools.misc import vector
|
from agents.tools.misc import vector
|
||||||
|
|
|
@ -14,7 +14,7 @@ import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import carla
|
import carla
|
||||||
from agents.tools.misc import distance_vehicle, get_speed
|
from agents.tools.misc import get_speed
|
||||||
|
|
||||||
class VehiclePIDController():
|
class VehiclePIDController():
|
||||||
"""
|
"""
|
||||||
|
@ -22,9 +22,7 @@ class VehiclePIDController():
|
||||||
low level control a vehicle from client side
|
low level control a vehicle from client side
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, vehicle,
|
def __init__(self, vehicle, args_lateral=None, args_longitudinal=None):
|
||||||
args_lateral={'K_P': 1.0, 'K_D': 0.0, 'K_I': 0.0},
|
|
||||||
args_longitudinal={'K_P': 1.0, 'K_D': 0.0, 'K_I': 0.0}):
|
|
||||||
"""
|
"""
|
||||||
:param vehicle: actor to apply to local planner logic onto
|
:param vehicle: actor to apply to local planner logic onto
|
||||||
:param args_lateral: dictionary of arguments to set the lateral PID controller using the following semantics:
|
:param args_lateral: dictionary of arguments to set the lateral PID controller using the following semantics:
|
||||||
|
@ -37,12 +35,15 @@ class VehiclePIDController():
|
||||||
K_D -- Differential term
|
K_D -- Differential term
|
||||||
K_I -- Integral term
|
K_I -- Integral term
|
||||||
"""
|
"""
|
||||||
|
if not args_lateral:
|
||||||
|
args_lateral = {'K_P': 1.0, 'K_D': 0.0, 'K_I': 0.0}
|
||||||
|
if not args_longitudinal:
|
||||||
|
args_longitudinal = {'K_P': 1.0, 'K_D': 0.0, 'K_I': 0.0}
|
||||||
|
|
||||||
self._vehicle = vehicle
|
self._vehicle = vehicle
|
||||||
self._world = self._vehicle.get_world()
|
self._world = self._vehicle.get_world()
|
||||||
self._lon_controller = PIDLongitudinalController(
|
self._lon_controller = PIDLongitudinalController(self._vehicle, **args_longitudinal)
|
||||||
self._vehicle, **args_longitudinal)
|
self._lat_controller = PIDLateralController(self._vehicle, **args_lateral)
|
||||||
self._lat_controller = PIDLateralController(
|
|
||||||
self._vehicle, **args_lateral)
|
|
||||||
|
|
||||||
def run_step(self, target_speed, waypoint):
|
def run_step(self, target_speed, waypoint):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -40,7 +40,7 @@ class LocalPlanner(object):
|
||||||
# total distance)
|
# total distance)
|
||||||
MIN_DISTANCE_PERCENTAGE = 0.9
|
MIN_DISTANCE_PERCENTAGE = 0.9
|
||||||
|
|
||||||
def __init__(self, vehicle, opt_dict={}):
|
def __init__(self, vehicle, opt_dict=None):
|
||||||
"""
|
"""
|
||||||
:param vehicle: actor to apply to local planner logic onto
|
:param vehicle: actor to apply to local planner logic onto
|
||||||
:param opt_dict: dictionary of arguments with the following semantics:
|
:param opt_dict: dictionary of arguments with the following semantics:
|
||||||
|
@ -60,20 +60,20 @@ class LocalPlanner(object):
|
||||||
self._vehicle = vehicle
|
self._vehicle = vehicle
|
||||||
self._map = self._vehicle.get_world().get_map()
|
self._map = self._vehicle.get_world().get_map()
|
||||||
|
|
||||||
self._dt = None
|
|
||||||
self._target_speed = None
|
|
||||||
self._sampling_radius = None
|
|
||||||
self._min_distance = None
|
|
||||||
self._current_waypoint = None
|
|
||||||
self._target_road_option = None
|
|
||||||
self._next_waypoints = None
|
|
||||||
self._target_waypoint = None
|
|
||||||
self._vehicle_controller = None
|
|
||||||
self._global_plan = None
|
|
||||||
# queue with tuples of (waypoint, RoadOption)
|
|
||||||
self._waypoints_queue = deque(maxlen=600)
|
|
||||||
self._buffer_size = 5
|
self._buffer_size = 5
|
||||||
self._waypoint_buffer = deque(maxlen=self._buffer_size)
|
self.dt = None
|
||||||
|
self.target_speed = None
|
||||||
|
self.sampling_radius = None
|
||||||
|
self.min_distance = None
|
||||||
|
self.current_waypoint = None
|
||||||
|
self.target_road_option = None
|
||||||
|
self.next_waypoints = None
|
||||||
|
self.target_waypoint = None
|
||||||
|
self.vehicle_controller = None
|
||||||
|
self.global_plan = None
|
||||||
|
# queue with tuples of (waypoint, RoadOption)
|
||||||
|
self.waypoints_queue = deque(maxlen=600)
|
||||||
|
self.waypoint_buffer = deque(maxlen=self._buffer_size)
|
||||||
|
|
||||||
# initializing controller
|
# initializing controller
|
||||||
self.init_controller(opt_dict)
|
self.init_controller(opt_dict)
|
||||||
|
@ -96,45 +96,46 @@ class LocalPlanner(object):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# default params
|
# default params
|
||||||
self._dt = 1.0 / 20.0
|
self.dt = 1.0 / 20.0
|
||||||
self._target_speed = 20.0 # Km/h
|
self.target_speed = 20.0 # Km/h
|
||||||
self._sampling_radius = self._target_speed * 0.5 / 3.6 # 0.5 seconds horizon
|
self.sampling_radius = self.target_speed * 0.5 / 3.6 # 0.5 seconds horizon
|
||||||
self._min_distance = self._sampling_radius * self.MIN_DISTANCE_PERCENTAGE
|
self.min_distance = self.sampling_radius * self.MIN_DISTANCE_PERCENTAGE
|
||||||
args_lateral_dict = {
|
args_lateral_dict = {
|
||||||
'K_P': 1.95,
|
'K_P': 1.95,
|
||||||
'K_D': 0.01,
|
'K_D': 0.01,
|
||||||
'K_I': 1.4,
|
'K_I': 1.4,
|
||||||
'dt': self._dt}
|
'dt': self.dt}
|
||||||
args_longitudinal_dict = {
|
args_longitudinal_dict = {
|
||||||
'K_P': 1.0,
|
'K_P': 1.0,
|
||||||
'K_D': 0,
|
'K_D': 0,
|
||||||
'K_I': 1,
|
'K_I': 1,
|
||||||
'dt': self._dt}
|
'dt': self.dt}
|
||||||
|
|
||||||
# parameters overload
|
# parameters overload
|
||||||
if 'dt' in opt_dict:
|
if opt_dict:
|
||||||
self._dt = opt_dict['dt']
|
if 'dt' in opt_dict:
|
||||||
if 'target_speed' in opt_dict:
|
self.dt = opt_dict['dt']
|
||||||
self._target_speed = opt_dict['target_speed']
|
if 'target_speed' in opt_dict:
|
||||||
if 'sampling_radius' in opt_dict:
|
self.target_speed = opt_dict['target_speed']
|
||||||
self._sampling_radius = self._target_speed * \
|
if 'sampling_radius' in opt_dict:
|
||||||
opt_dict['sampling_radius'] / 3.6
|
self.sampling_radius = self.target_speed * \
|
||||||
if 'lateral_control_dict' in opt_dict:
|
opt_dict['sampling_radius'] / 3.6
|
||||||
args_lateral_dict = opt_dict['lateral_control_dict']
|
if 'lateral_control_dict' in opt_dict:
|
||||||
if 'longitudinal_control_dict' in opt_dict:
|
args_lateral_dict = opt_dict['lateral_control_dict']
|
||||||
args_longitudinal_dict = opt_dict['longitudinal_control_dict']
|
if 'longitudinal_control_dict' in opt_dict:
|
||||||
|
args_longitudinal_dict = opt_dict['longitudinal_control_dict']
|
||||||
|
|
||||||
self._current_waypoint = self._map.get_waypoint(
|
self.current_waypoint = self._map.get_waypoint(self._vehicle.get_location())
|
||||||
self._vehicle.get_location())
|
self.vehicle_controller = VehiclePIDController(self._vehicle,
|
||||||
self._vehicle_controller = VehiclePIDController(self._vehicle,
|
|
||||||
args_lateral=args_lateral_dict,
|
args_lateral=args_lateral_dict,
|
||||||
args_longitudinal=args_longitudinal_dict)
|
args_longitudinal=args_longitudinal_dict)
|
||||||
|
|
||||||
self._global_plan = False
|
self.global_plan = False
|
||||||
|
|
||||||
# compute initial waypoints
|
# compute initial waypoints
|
||||||
self._waypoints_queue.append( (self._current_waypoint.next(self._sampling_radius)[0], RoadOption.LANEFOLLOW))
|
self.waypoints_queue.append( (self.current_waypoint.next(self.sampling_radius)[0], RoadOption.LANEFOLLOW))
|
||||||
self._target_road_option = RoadOption.LANEFOLLOW
|
|
||||||
|
self.target_road_option = RoadOption.LANEFOLLOW
|
||||||
# fill waypoint trajectory queue
|
# fill waypoint trajectory queue
|
||||||
self._compute_next_waypoints(k=200)
|
self._compute_next_waypoints(k=200)
|
||||||
|
|
||||||
|
@ -146,7 +147,7 @@ class LocalPlanner(object):
|
||||||
:param speed: new target speed in Km/h
|
:param speed: new target speed in Km/h
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
self._target_speed = speed
|
self.target_speed = speed
|
||||||
|
|
||||||
def _compute_next_waypoints(self, k=1):
|
def _compute_next_waypoints(self, k=1):
|
||||||
"""
|
"""
|
||||||
|
@ -156,12 +157,12 @@ class LocalPlanner(object):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# check we do not overflow the queue
|
# check we do not overflow the queue
|
||||||
available_entries = self._waypoints_queue.maxlen - len(self._waypoints_queue)
|
available_entries = self.waypoints_queue.maxlen - len(self.waypoints_queue)
|
||||||
k = min(available_entries, k)
|
k = min(available_entries, k)
|
||||||
|
|
||||||
for _ in range(k):
|
for _ in range(k):
|
||||||
last_waypoint = self._waypoints_queue[-1][0]
|
last_waypoint = self.waypoints_queue[-1][0]
|
||||||
next_waypoints = list(last_waypoint.next(self._sampling_radius))
|
next_waypoints = list(last_waypoint.next(self.sampling_radius))
|
||||||
|
|
||||||
if len(next_waypoints) == 1:
|
if len(next_waypoints) == 1:
|
||||||
# only one option available ==> lanefollowing
|
# only one option available ==> lanefollowing
|
||||||
|
@ -175,15 +176,15 @@ class LocalPlanner(object):
|
||||||
next_waypoint = next_waypoints[road_options_list.index(
|
next_waypoint = next_waypoints[road_options_list.index(
|
||||||
road_option)]
|
road_option)]
|
||||||
|
|
||||||
self._waypoints_queue.append((next_waypoint, road_option))
|
self.waypoints_queue.append((next_waypoint, road_option))
|
||||||
|
|
||||||
|
|
||||||
def set_global_plan(self, current_plan):
|
def set_global_plan(self, current_plan):
|
||||||
self._waypoints_queue.clear()
|
self.waypoints_queue.clear()
|
||||||
for elem in current_plan:
|
for elem in current_plan:
|
||||||
self._waypoints_queue.append(elem)
|
self.waypoints_queue.append(elem)
|
||||||
self._target_road_option = RoadOption.LANEFOLLOW
|
self.target_road_option = RoadOption.LANEFOLLOW
|
||||||
self._global_plan = True
|
self.global_plan = True
|
||||||
|
|
||||||
def run_step(self, debug=True):
|
def run_step(self, debug=True):
|
||||||
"""
|
"""
|
||||||
|
@ -195,11 +196,11 @@ class LocalPlanner(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# not enough waypoints in the horizon? => add more!
|
# not enough waypoints in the horizon? => add more!
|
||||||
if len(self._waypoints_queue) < int(self._waypoints_queue.maxlen * 0.5):
|
if len(self.waypoints_queue) < int(self.waypoints_queue.maxlen * 0.5):
|
||||||
if not self._global_plan:
|
if not self.global_plan:
|
||||||
self._compute_next_waypoints(k=100)
|
self._compute_next_waypoints(k=100)
|
||||||
|
|
||||||
if len(self._waypoints_queue) == 0:
|
if len(self.waypoints_queue) == 0:
|
||||||
control = carla.VehicleControl()
|
control = carla.VehicleControl()
|
||||||
control.steer = 0.0
|
control.steer = 0.0
|
||||||
control.throttle = 0.0
|
control.throttle = 0.0
|
||||||
|
@ -210,35 +211,35 @@ class LocalPlanner(object):
|
||||||
return control
|
return control
|
||||||
|
|
||||||
# Buffering the waypoints
|
# Buffering the waypoints
|
||||||
if not self._waypoint_buffer:
|
if not self.waypoint_buffer:
|
||||||
for i in range(self._buffer_size):
|
for i in range(self._buffer_size):
|
||||||
if self._waypoints_queue:
|
if self.waypoints_queue:
|
||||||
self._waypoint_buffer.append(
|
self.waypoint_buffer.append(
|
||||||
self._waypoints_queue.popleft())
|
self.waypoints_queue.popleft())
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
# current vehicle waypoint
|
# current vehicle waypoint
|
||||||
self._current_waypoint = self._map.get_waypoint(self._vehicle.get_location())
|
self.current_waypoint = self._map.get_waypoint(self._vehicle.get_location())
|
||||||
# target waypoint
|
# target waypoint
|
||||||
self._target_waypoint, self._target_road_option = self._waypoint_buffer[0]
|
self.target_waypoint, self.target_road_option = self.waypoint_buffer[0]
|
||||||
# move using PID controllers
|
# move using PID controllers
|
||||||
control = self._vehicle_controller.run_step(self._target_speed, self._target_waypoint)
|
control = self.vehicle_controller.run_step(self.target_speed, self.target_waypoint)
|
||||||
|
|
||||||
# purge the queue of obsolete waypoints
|
# purge the queue of obsolete waypoints
|
||||||
vehicle_transform = self._vehicle.get_transform()
|
vehicle_transform = self._vehicle.get_transform()
|
||||||
max_index = -1
|
max_index = -1
|
||||||
|
|
||||||
for i, (waypoint, _) in enumerate(self._waypoint_buffer):
|
for i, (waypoint, _) in enumerate(self.waypoint_buffer):
|
||||||
if distance_vehicle(
|
if distance_vehicle(
|
||||||
waypoint, vehicle_transform) < self._min_distance:
|
waypoint, vehicle_transform) < self.min_distance:
|
||||||
max_index = i
|
max_index = i
|
||||||
if max_index >= 0:
|
if max_index >= 0:
|
||||||
for i in range(max_index + 1):
|
for i in range(max_index + 1):
|
||||||
self._waypoint_buffer.popleft()
|
self.waypoint_buffer.popleft()
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
draw_waypoints(self._vehicle.get_world(), [self._target_waypoint], self._vehicle.get_location().z + 1.0)
|
draw_waypoints(self._vehicle.get_world(), [self.target_waypoint], self._vehicle.get_location().z + 1.0)
|
||||||
|
|
||||||
return control
|
return control
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,7 @@
|
||||||
""" This module implements an agent that roams around a track following random waypoints and avoiding other vehicles.
|
""" This module implements an agent that roams around a track following random waypoints and avoiding other vehicles.
|
||||||
The agent also responds to traffic lights. """
|
The agent also responds to traffic lights. """
|
||||||
|
|
||||||
from enum import Enum
|
from agents.navigation.agent import Agent, AgentState
|
||||||
|
|
||||||
import carla
|
|
||||||
from agents.navigation.agent import *
|
|
||||||
from agents.navigation.local_planner import LocalPlanner
|
from agents.navigation.local_planner import LocalPlanner
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -90,13 +90,13 @@ def distance_vehicle(waypoint, vehicle_transform):
|
||||||
return math.sqrt(dx * dx + dy * dy)
|
return math.sqrt(dx * dx + dy * dy)
|
||||||
|
|
||||||
def vector(location_1, location_2):
|
def vector(location_1, location_2):
|
||||||
"""
|
"""
|
||||||
Returns the unit vector from location_1 to location_2
|
Returns the unit vector from location_1 to location_2
|
||||||
location_1, location_2 : carla.Location objects
|
location_1, location_2: carla.Location objects
|
||||||
"""
|
"""
|
||||||
x = location_2.x - location_1.x
|
x = location_2.x - location_1.x
|
||||||
y = location_2.y - location_1.y
|
y = location_2.y - location_1.y
|
||||||
z = location_2.z - location_1.z
|
z = location_2.z - location_1.z
|
||||||
norm = np.linalg.norm([x, y, z])
|
norm = np.linalg.norm([x, y, z])
|
||||||
|
|
||||||
return [x/norm, y/norm, z/norm]
|
return [x/norm, y/norm, z/norm]
|
||||||
|
|
|
@ -53,6 +53,8 @@ try:
|
||||||
from pygame.locals import K_r
|
from pygame.locals import K_r
|
||||||
from pygame.locals import K_s
|
from pygame.locals import K_s
|
||||||
from pygame.locals import K_w
|
from pygame.locals import K_w
|
||||||
|
from pygame.locals import K_MINUS
|
||||||
|
from pygame.locals import K_EQUALS
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise RuntimeError('cannot import pygame, make sure pygame package is installed')
|
raise RuntimeError('cannot import pygame, make sure pygame package is installed')
|
||||||
|
|
||||||
|
@ -83,8 +85,8 @@ except IndexError:
|
||||||
|
|
||||||
import carla
|
import carla
|
||||||
from carla import ColorConverter as cc
|
from carla import ColorConverter as cc
|
||||||
from agents.navigation.roaming_agent import *
|
from agents.navigation.roaming_agent import RoamingAgent
|
||||||
from agents.navigation.basic_agent import *
|
from agents.navigation.basic_agent import BasicAgent
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,54 +111,53 @@ def get_actor_display_name(actor, truncate=250):
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
class World(object):
|
class World(object):
|
||||||
def __init__(self, carla_world, hud):
|
def __init__(self, carla_world, hud, actor_filter):
|
||||||
self.world = carla_world
|
self.world = carla_world
|
||||||
self.map = self.world.get_map()
|
self.map = self.world.get_map()
|
||||||
self.hud = hud
|
self.hud = hud
|
||||||
self.vehicle = None
|
self.player = None
|
||||||
self.collision_sensor = None
|
self.collision_sensor = None
|
||||||
self.lane_invasion_sensor = None
|
self.lane_invasion_sensor = None
|
||||||
|
self.gnss_sensor = None
|
||||||
self.camera_manager = None
|
self.camera_manager = None
|
||||||
self._weather_presets = find_weather_presets()
|
self._weather_presets = find_weather_presets()
|
||||||
self._weather_index = 0
|
self._weather_index = 0
|
||||||
|
self._actor_filter = actor_filter
|
||||||
self.restart()
|
self.restart()
|
||||||
self.world.on_tick(hud.on_world_tick)
|
self.world.on_tick(hud.on_world_tick)
|
||||||
|
self.recording_enabled = False
|
||||||
|
self.recording_start = 0
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
# Keep same camera config if the camera manager exists.
|
# Keep same camera config if the camera manager exists.
|
||||||
cam_index = self.camera_manager._index if self.camera_manager is not None else 0
|
cam_index = self.camera_manager.index if self.camera_manager is not None else 0
|
||||||
cam_pos_index = self.camera_manager._transform_index if self.camera_manager is not None else 0
|
cam_pos_index = self.camera_manager.transform_index if self.camera_manager is not None else 0
|
||||||
|
# Get a random blueprint.
|
||||||
blueprint = self.world.get_blueprint_library().find('vehicle.lincoln.mkz2017')
|
blueprint = random.choice(self.world.get_blueprint_library().filter(self._actor_filter))
|
||||||
blueprint.set_attribute('role_name', 'hero')
|
blueprint.set_attribute('role_name', 'hero')
|
||||||
if blueprint.has_attribute('color'):
|
if blueprint.has_attribute('color'):
|
||||||
color = random.choice(blueprint.get_attribute('color').recommended_values)
|
color = random.choice(blueprint.get_attribute('color').recommended_values)
|
||||||
blueprint.set_attribute('color', color)
|
blueprint.set_attribute('color', color)
|
||||||
|
# Spawn the player.
|
||||||
# Spawn the vehicle.
|
if self.player is not None:
|
||||||
if self.vehicle is not None:
|
spawn_point = self.player.get_transform()
|
||||||
spawn_point = self.vehicle.get_transform()
|
|
||||||
spawn_point.location.z += 2.0
|
spawn_point.location.z += 2.0
|
||||||
spawn_point.rotation.roll = 0.0
|
spawn_point.rotation.roll = 0.0
|
||||||
spawn_point.rotation.pitch = 0.0
|
spawn_point.rotation.pitch = 0.0
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
self.player = self.world.try_spawn_actor(blueprint, spawn_point)
|
||||||
|
while self.player is None:
|
||||||
spawn_points = self.map.get_spawn_points()
|
spawn_points = self.map.get_spawn_points()
|
||||||
spawn_point = spawn_points[1]
|
spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform()
|
||||||
self.vehicle = self.world.spawn_actor(blueprint, spawn_point)
|
self.player = self.world.try_spawn_actor(blueprint, spawn_point)
|
||||||
|
|
||||||
while self.vehicle is None:
|
|
||||||
spawn_points = self.map.get_spawn_points()
|
|
||||||
spawn_point = spawn_points[1]
|
|
||||||
self.vehicle = self.world.spawn_actor(blueprint, spawn_point)
|
|
||||||
|
|
||||||
# Set up the sensors.
|
# Set up the sensors.
|
||||||
self.collision_sensor = CollisionSensor(self.vehicle, self.hud)
|
self.collision_sensor = CollisionSensor(self.player, self.hud)
|
||||||
self.lane_invasion_sensor = LaneInvasionSensor(self.vehicle, self.hud)
|
self.lane_invasion_sensor = LaneInvasionSensor(self.player, self.hud)
|
||||||
self.camera_manager = CameraManager(self.vehicle, self.hud)
|
self.gnss_sensor = GnssSensor(self.player)
|
||||||
self.camera_manager._transform_index = cam_pos_index
|
self.camera_manager = CameraManager(self.player, self.hud)
|
||||||
|
self.camera_manager.transform_index = cam_pos_index
|
||||||
self.camera_manager.set_sensor(cam_index, notify=False)
|
self.camera_manager.set_sensor(cam_index, notify=False)
|
||||||
actor_type = get_actor_display_name(self.vehicle)
|
actor_type = get_actor_display_name(self.player)
|
||||||
self.hud.notification(actor_type)
|
self.hud.notification(actor_type)
|
||||||
|
|
||||||
def next_weather(self, reverse=False):
|
def next_weather(self, reverse=False):
|
||||||
|
@ -164,7 +165,7 @@ class World(object):
|
||||||
self._weather_index %= len(self._weather_presets)
|
self._weather_index %= len(self._weather_presets)
|
||||||
preset = self._weather_presets[self._weather_index]
|
preset = self._weather_presets[self._weather_index]
|
||||||
self.hud.notification('Weather: %s' % preset[1])
|
self.hud.notification('Weather: %s' % preset[1])
|
||||||
self.vehicle.get_world().set_weather(preset[0])
|
self.player.get_world().set_weather(preset[0])
|
||||||
|
|
||||||
def tick(self, clock):
|
def tick(self, clock):
|
||||||
self.hud.tick(self, clock)
|
self.hud.tick(self, clock)
|
||||||
|
@ -173,30 +174,43 @@ class World(object):
|
||||||
self.camera_manager.render(display)
|
self.camera_manager.render(display)
|
||||||
self.hud.render(display)
|
self.hud.render(display)
|
||||||
|
|
||||||
|
def destroy_sensors(self):
|
||||||
|
self.camera_manager.sensor.destroy()
|
||||||
|
self.camera_manager.sensor = None
|
||||||
|
self.camera_manager.index = None
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
actors = [
|
actors = [
|
||||||
self.camera_manager.sensor,
|
self.camera_manager.sensor,
|
||||||
self.collision_sensor.sensor,
|
self.collision_sensor.sensor,
|
||||||
self.lane_invasion_sensor.sensor,
|
self.lane_invasion_sensor.sensor,
|
||||||
self.vehicle]
|
self.gnss_sensor.sensor,
|
||||||
|
self.player]
|
||||||
for actor in actors:
|
for actor in actors:
|
||||||
if actor is not None:
|
if actor is not None:
|
||||||
actor.destroy()
|
actor.destroy()
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# -- KeyboardControl -----------------------------------------------------------
|
# -- KeyboardControl -----------------------------------------------------------
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
class KeyboardControl(object):
|
class KeyboardControl(object):
|
||||||
def __init__(self, world, start_in_autopilot):
|
def __init__(self, world, start_in_autopilot):
|
||||||
self._autopilot_enabled = start_in_autopilot
|
self._autopilot_enabled = start_in_autopilot
|
||||||
self._control = carla.VehicleControl()
|
if isinstance(world.player, carla.Vehicle):
|
||||||
|
self._control = carla.VehicleControl()
|
||||||
|
world.player.set_autopilot(self._autopilot_enabled)
|
||||||
|
elif isinstance(world.player, carla.Walker):
|
||||||
|
self._control = carla.WalkerControl()
|
||||||
|
self._autopilot_enabled = False
|
||||||
|
self._rotation = world.player.get_transform().rotation
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Actor type not supported")
|
||||||
self._steer_cache = 0.0
|
self._steer_cache = 0.0
|
||||||
world.vehicle.set_autopilot(self._autopilot_enabled)
|
|
||||||
world.hud.notification("Press 'H' or '?' for help.", seconds=4.0)
|
world.hud.notification("Press 'H' or '?' for help.", seconds=4.0)
|
||||||
|
|
||||||
def parse_events(self, world, clock):
|
def parse_events(self, client, world, clock):
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
return True
|
return True
|
||||||
|
@ -219,28 +233,72 @@ class KeyboardControl(object):
|
||||||
world.camera_manager.next_sensor()
|
world.camera_manager.next_sensor()
|
||||||
elif event.key > K_0 and event.key <= K_9:
|
elif event.key > K_0 and event.key <= K_9:
|
||||||
world.camera_manager.set_sensor(event.key - 1 - K_0)
|
world.camera_manager.set_sensor(event.key - 1 - K_0)
|
||||||
elif event.key == K_r:
|
elif event.key == K_r and not (pygame.key.get_mods() & KMOD_CTRL):
|
||||||
world.camera_manager.toggle_recording()
|
world.camera_manager.toggle_recording()
|
||||||
elif event.key == K_q:
|
elif event.key == K_r and (pygame.key.get_mods() & KMOD_CTRL):
|
||||||
self._control.gear = 1 if self._control.reverse else -1
|
if (world.recording_enabled):
|
||||||
elif event.key == K_m:
|
client.stop_recorder()
|
||||||
self._control.manual_gear_shift = not self._control.manual_gear_shift
|
world.recording_enabled = False
|
||||||
self._control.gear = world.vehicle.get_control().gear
|
world.hud.notification("Recorder is OFF")
|
||||||
world.hud.notification(
|
else:
|
||||||
'%s Transmission' % ('Manual' if self._control.manual_gear_shift else 'Automatic'))
|
client.start_recorder("manual_recording.rec")
|
||||||
elif self._control.manual_gear_shift and event.key == K_COMMA:
|
world.recording_enabled = True
|
||||||
self._control.gear = max(-1, self._control.gear - 1)
|
world.hud.notification("Recorder is ON")
|
||||||
elif self._control.manual_gear_shift and event.key == K_PERIOD:
|
elif event.key == K_p and (pygame.key.get_mods() & KMOD_CTRL):
|
||||||
self._control.gear = self._control.gear + 1
|
# stop recorder
|
||||||
elif event.key == K_p:
|
client.stop_recorder()
|
||||||
self._autopilot_enabled = not self._autopilot_enabled
|
world.recording_enabled = False
|
||||||
world.vehicle.set_autopilot(self._autopilot_enabled)
|
# work around to fix camera at start of replaying
|
||||||
world.hud.notification('Autopilot %s' % ('On' if self._autopilot_enabled else 'Off'))
|
currentIndex = world.camera_manager.index
|
||||||
|
world.destroy_sensors()
|
||||||
|
# disable autopilot
|
||||||
|
self._autopilot_enabled = False
|
||||||
|
world.player.set_autopilot(self._autopilot_enabled)
|
||||||
|
world.hud.notification("Replaying file 'manual_recording.rec'")
|
||||||
|
# replayer
|
||||||
|
client.replay_file("manual_recording.rec", world.recording_start, 0, 0)
|
||||||
|
world.camera_manager.set_sensor(currentIndex)
|
||||||
|
elif event.key == K_MINUS and (pygame.key.get_mods() & KMOD_CTRL):
|
||||||
|
if pygame.key.get_mods() & KMOD_SHIFT:
|
||||||
|
world.recording_start -= 10
|
||||||
|
else:
|
||||||
|
world.recording_start -= 1
|
||||||
|
world.hud.notification("Recording start time is %d" % (world.recording_start))
|
||||||
|
elif event.key == K_EQUALS and (pygame.key.get_mods() & KMOD_CTRL):
|
||||||
|
if pygame.key.get_mods() & KMOD_SHIFT:
|
||||||
|
world.recording_start += 10
|
||||||
|
else:
|
||||||
|
world.recording_start += 1
|
||||||
|
world.hud.notification("Recording start time is %d" % (world.recording_start))
|
||||||
|
if isinstance(self._control, carla.VehicleControl):
|
||||||
|
if event.key == K_q:
|
||||||
|
self._control.gear = 1 if self._control.reverse else -1
|
||||||
|
elif event.key == K_m:
|
||||||
|
self._control.manual_gear_shift = not self._control.manual_gear_shift
|
||||||
|
self._control.gear = world.player.get_control().gear
|
||||||
|
world.hud.notification('%s Transmission' % (
|
||||||
|
'Manual' if self._control.manual_gear_shift else 'Automatic'))
|
||||||
|
elif self._control.manual_gear_shift and event.key == K_COMMA:
|
||||||
|
self._control.gear = max(-1, self._control.gear - 1)
|
||||||
|
elif self._control.manual_gear_shift and event.key == K_PERIOD:
|
||||||
|
self._control.gear = self._control.gear + 1
|
||||||
|
elif event.key == K_p and not (pygame.key.get_mods() & KMOD_CTRL):
|
||||||
|
self._autopilot_enabled = not self._autopilot_enabled
|
||||||
|
world.player.set_autopilot(self._autopilot_enabled)
|
||||||
|
world.hud.notification(
|
||||||
|
'Autopilot %s' % ('On' if self._autopilot_enabled else 'Off'))
|
||||||
if not self._autopilot_enabled:
|
if not self._autopilot_enabled:
|
||||||
self._parse_keys(pygame.key.get_pressed(), clock.get_time())
|
if isinstance(self._control, carla.VehicleControl):
|
||||||
self._control.reverse = self._control.gear < 0
|
keys = pygame.key.get_pressed()
|
||||||
|
if sum(keys) > 0:
|
||||||
|
self._parse_vehicle_keys(keys, clock.get_time())
|
||||||
|
self._control.reverse = self._control.gear < 0
|
||||||
|
world.player.apply_control(self._control)
|
||||||
|
elif isinstance(self._control, carla.WalkerControl):
|
||||||
|
self._parse_walker_keys(pygame.key.get_pressed(), clock.get_time())
|
||||||
|
world.player.apply_control(self._control)
|
||||||
|
|
||||||
def _parse_keys(self, keys, milliseconds):
|
def _parse_vehicle_keys(self, keys, milliseconds):
|
||||||
self._control.throttle = 1.0 if keys[K_UP] or keys[K_w] else 0.0
|
self._control.throttle = 1.0 if keys[K_UP] or keys[K_w] else 0.0
|
||||||
steer_increment = 5e-4 * milliseconds
|
steer_increment = 5e-4 * milliseconds
|
||||||
if keys[K_LEFT] or keys[K_a]:
|
if keys[K_LEFT] or keys[K_a]:
|
||||||
|
@ -254,13 +312,28 @@ class KeyboardControl(object):
|
||||||
self._control.brake = 1.0 if keys[K_DOWN] or keys[K_s] else 0.0
|
self._control.brake = 1.0 if keys[K_DOWN] or keys[K_s] else 0.0
|
||||||
self._control.hand_brake = keys[K_SPACE]
|
self._control.hand_brake = keys[K_SPACE]
|
||||||
|
|
||||||
|
def _parse_walker_keys(self, keys, milliseconds):
|
||||||
|
self._control.speed = 0.0
|
||||||
|
if keys[K_DOWN] or keys[K_s]:
|
||||||
|
self._control.speed = 0.0
|
||||||
|
if keys[K_LEFT] or keys[K_a]:
|
||||||
|
self._control.speed = .01
|
||||||
|
self._rotation.yaw -= 0.08 * milliseconds
|
||||||
|
if keys[K_RIGHT] or keys[K_d]:
|
||||||
|
self._control.speed = .01
|
||||||
|
self._rotation.yaw += 0.08 * milliseconds
|
||||||
|
if keys[K_UP] or keys[K_w]:
|
||||||
|
self._control.speed = 5.556 if pygame.key.get_mods() & KMOD_SHIFT else 2.778
|
||||||
|
self._control.jump = keys[K_SPACE]
|
||||||
|
self._rotation.yaw = round(self._rotation.yaw, 1)
|
||||||
|
self._control.direction = self._rotation.get_forward_vector()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_quit_shortcut(key):
|
def _is_quit_shortcut(key):
|
||||||
return (key == K_ESCAPE) or (key == K_q and pygame.key.get_mods() & KMOD_CTRL)
|
return (key == K_ESCAPE) or (key == K_q and pygame.key.get_mods() & KMOD_CTRL)
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# -- HUD -----------------------------------------------------------------
|
# -- HUD -----------------------------------------------------------------------
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,11 +362,12 @@ class HUD(object):
|
||||||
self.simulation_time = timestamp.elapsed_seconds
|
self.simulation_time = timestamp.elapsed_seconds
|
||||||
|
|
||||||
def tick(self, world, clock):
|
def tick(self, world, clock):
|
||||||
|
self._notifications.tick(world, clock)
|
||||||
if not self._show_info:
|
if not self._show_info:
|
||||||
return
|
return
|
||||||
t = world.vehicle.get_transform()
|
t = world.player.get_transform()
|
||||||
v = world.vehicle.get_velocity()
|
v = world.player.get_velocity()
|
||||||
c = world.vehicle.get_control()
|
c = world.player.get_control()
|
||||||
heading = 'N' if abs(t.rotation.yaw) < 89.5 else ''
|
heading = 'N' if abs(t.rotation.yaw) < 89.5 else ''
|
||||||
heading += 'S' if abs(t.rotation.yaw) > 90.5 else ''
|
heading += 'S' if abs(t.rotation.yaw) > 90.5 else ''
|
||||||
heading += 'E' if 179.5 > t.rotation.yaw > 0.5 else ''
|
heading += 'E' if 179.5 > t.rotation.yaw > 0.5 else ''
|
||||||
|
@ -304,40 +378,48 @@ class HUD(object):
|
||||||
collision = [x / max_col for x in collision]
|
collision = [x / max_col for x in collision]
|
||||||
vehicles = world.world.get_actors().filter('vehicle.*')
|
vehicles = world.world.get_actors().filter('vehicle.*')
|
||||||
self._info_text = [
|
self._info_text = [
|
||||||
'Server: % 16d FPS' % self.server_fps,
|
'Server: % 16.0f FPS' % self.server_fps,
|
||||||
|
'Client: % 16.0f FPS' % clock.get_fps(),
|
||||||
'',
|
'',
|
||||||
'Vehicle: % 20s' % get_actor_display_name(world.vehicle, truncate=20),
|
'Vehicle: % 20s' % get_actor_display_name(world.player, truncate=20),
|
||||||
'Map: % 20s' % world.map.name,
|
'Map: % 20s' % world.map.name,
|
||||||
'Simulation time: % 12s' % datetime.timedelta(seconds=int(self.simulation_time)),
|
'Simulation time: % 12s' % datetime.timedelta(seconds=int(self.simulation_time)),
|
||||||
'',
|
'',
|
||||||
'Speed: % 15.0f km/h' % (3.6 * math.sqrt(v.x**2 + v.y**2 + v.z**2)),
|
'Speed: % 15.0f km/h' % (3.6 * math.sqrt(v.x ** 2 + v.y ** 2 + v.z ** 2)),
|
||||||
u'Heading:% 16.0f\N{DEGREE SIGN} % 2s' % (t.rotation.yaw, heading),
|
u'Heading:% 16.0f\N{DEGREE SIGN} % 2s' % (t.rotation.yaw, heading),
|
||||||
'Location:% 20s' % ('(% 5.1f, % 5.1f)' % (t.location.x, t.location.y)),
|
'Location:% 20s' % ('(% 5.1f, % 5.1f)' % (t.location.x, t.location.y)),
|
||||||
|
'GNSS:% 24s' % ('(% 2.6f, % 3.6f)' % (world.gnss_sensor.lat, world.gnss_sensor.lon)),
|
||||||
'Height: % 18.0f m' % t.location.z,
|
'Height: % 18.0f m' % t.location.z,
|
||||||
'',
|
'']
|
||||||
('Throttle:', c.throttle, 0.0, 1.0),
|
if isinstance(c, carla.VehicleControl):
|
||||||
('Steer:', c.steer, -1.0, 1.0),
|
self._info_text += [
|
||||||
('Brake:', c.brake, 0.0, 1.0),
|
('Throttle:', c.throttle, 0.0, 1.0),
|
||||||
('Reverse:', c.reverse),
|
('Steer:', c.steer, -1.0, 1.0),
|
||||||
('Hand brake:', c.hand_brake),
|
('Brake:', c.brake, 0.0, 1.0),
|
||||||
('Manual:', c.manual_gear_shift),
|
('Reverse:', c.reverse),
|
||||||
'Gear: %s' % {-1: 'R', 0: 'N'}.get(c.gear, c.gear),
|
('Hand brake:', c.hand_brake),
|
||||||
|
('Manual:', c.manual_gear_shift),
|
||||||
|
'Gear: %s' % {-1: 'R', 0: 'N'}.get(c.gear, c.gear)]
|
||||||
|
elif isinstance(c, carla.WalkerControl):
|
||||||
|
self._info_text += [
|
||||||
|
('Speed:', c.speed, 0.0, 5.556),
|
||||||
|
('Jump:', c.jump)]
|
||||||
|
self._info_text += [
|
||||||
'',
|
'',
|
||||||
'Collision:',
|
'Collision:',
|
||||||
collision,
|
collision,
|
||||||
'',
|
'',
|
||||||
'Number of vehicles: % 8d' % len(vehicles)
|
'Number of vehicles: % 8d' % len(vehicles)]
|
||||||
]
|
|
||||||
if len(vehicles) > 1:
|
if len(vehicles) > 1:
|
||||||
self._info_text += ['Nearby vehicles:']
|
self._info_text += ['Nearby vehicles:']
|
||||||
distance = lambda l: math.sqrt((l.x - t.location.x)**2 + (l.y - t.location.y)**2 + (l.z - t.location.z)**2)
|
distance = lambda l: math.sqrt(
|
||||||
vehicles = [(distance(x.get_location()), x) for x in vehicles if x.id != world.vehicle.id]
|
(l.x - t.location.x) ** 2 + (l.y - t.location.y) ** 2 + (l.z - t.location.z) ** 2)
|
||||||
|
vehicles = [(distance(x.get_location()), x) for x in vehicles if x.id != world.player.id]
|
||||||
for d, vehicle in sorted(vehicles):
|
for d, vehicle in sorted(vehicles):
|
||||||
if d > 200.0:
|
if d > 200.0:
|
||||||
break
|
break
|
||||||
vehicle_type = get_actor_display_name(vehicle, truncate=22)
|
vehicle_type = get_actor_display_name(vehicle, truncate=22)
|
||||||
self._info_text.append('% 4dm %s' % (d, vehicle_type))
|
self._info_text.append('% 4dm %s' % (d, vehicle_type))
|
||||||
self._notifications.tick(world, clock)
|
|
||||||
|
|
||||||
def toggle_info(self):
|
def toggle_info(self):
|
||||||
self._show_info = not self._show_info
|
self._show_info = not self._show_info
|
||||||
|
@ -379,18 +461,18 @@ class HUD(object):
|
||||||
rect = pygame.Rect((bar_h_offset, v_offset + 8), (f * bar_width, 6))
|
rect = pygame.Rect((bar_h_offset, v_offset + 8), (f * bar_width, 6))
|
||||||
pygame.draw.rect(display, (255, 255, 255), rect)
|
pygame.draw.rect(display, (255, 255, 255), rect)
|
||||||
item = item[0]
|
item = item[0]
|
||||||
if item: # At this point has to be a str.
|
if item: # At this point has to be a str.
|
||||||
surface = self._font_mono.render(item, True, (255, 255, 255))
|
surface = self._font_mono.render(item, True, (255, 255, 255))
|
||||||
display.blit(surface, (8, v_offset))
|
display.blit(surface, (8, v_offset))
|
||||||
v_offset += 18
|
v_offset += 18
|
||||||
self._notifications.render(display)
|
self._notifications.render(display)
|
||||||
self.help.render(display)
|
self.help.render(display)
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# -- FadingText ----------------------------------------------------------------
|
# -- FadingText ----------------------------------------------------------------
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
class FadingText(object):
|
class FadingText(object):
|
||||||
def __init__(self, font, dim, pos):
|
def __init__(self, font, dim, pos):
|
||||||
self.font = font
|
self.font = font
|
||||||
|
@ -449,9 +531,9 @@ class HelpText(object):
|
||||||
class CollisionSensor(object):
|
class CollisionSensor(object):
|
||||||
def __init__(self, parent_actor, hud):
|
def __init__(self, parent_actor, hud):
|
||||||
self.sensor = None
|
self.sensor = None
|
||||||
self._history = []
|
self.history = []
|
||||||
self._parent = parent_actor
|
self._parent = parent_actor
|
||||||
self._hud = hud
|
self.hud = hud
|
||||||
world = self._parent.get_world()
|
world = self._parent.get_world()
|
||||||
bp = world.get_blueprint_library().find('sensor.other.collision')
|
bp = world.get_blueprint_library().find('sensor.other.collision')
|
||||||
self.sensor = world.spawn_actor(bp, carla.Transform(), attach_to=self._parent)
|
self.sensor = world.spawn_actor(bp, carla.Transform(), attach_to=self._parent)
|
||||||
|
@ -462,7 +544,7 @@ class CollisionSensor(object):
|
||||||
|
|
||||||
def get_collision_history(self):
|
def get_collision_history(self):
|
||||||
history = collections.defaultdict(int)
|
history = collections.defaultdict(int)
|
||||||
for frame, intensity in self._history:
|
for frame, intensity in self.history:
|
||||||
history[frame] += intensity
|
history[frame] += intensity
|
||||||
return history
|
return history
|
||||||
|
|
||||||
|
@ -472,23 +554,23 @@ class CollisionSensor(object):
|
||||||
if not self:
|
if not self:
|
||||||
return
|
return
|
||||||
actor_type = get_actor_display_name(event.other_actor)
|
actor_type = get_actor_display_name(event.other_actor)
|
||||||
self._hud.notification('Collision with %r, id = %d' % (actor_type, event.other_actor.id))
|
self.hud.notification('Collision with %r' % actor_type)
|
||||||
impulse = event.normal_impulse
|
impulse = event.normal_impulse
|
||||||
intensity = math.sqrt(impulse.x ** 2 + impulse.y ** 2 + impulse.z ** 2)
|
intensity = math.sqrt(impulse.x ** 2 + impulse.y ** 2 + impulse.z ** 2)
|
||||||
self._history.append((event.frame_number, intensity))
|
self.history.append((event.frame_number, intensity))
|
||||||
if len(self._history) > 4000:
|
if len(self.history) > 4000:
|
||||||
self._history.pop(0)
|
self.history.pop(0)
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# -- LaneInvasionSensor --------------------------------------------------------
|
# -- LaneInvasionSensor --------------------------------------------------------
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
class LaneInvasionSensor(object):
|
class LaneInvasionSensor(object):
|
||||||
def __init__(self, parent_actor, hud):
|
def __init__(self, parent_actor, hud):
|
||||||
self.sensor = None
|
self.sensor = None
|
||||||
self._parent = parent_actor
|
self._parent = parent_actor
|
||||||
self._hud = hud
|
self.hud = hud
|
||||||
world = self._parent.get_world()
|
world = self._parent.get_world()
|
||||||
bp = world.get_blueprint_library().find('sensor.other.lane_detector')
|
bp = world.get_blueprint_library().find('sensor.other.lane_detector')
|
||||||
self.sensor = world.spawn_actor(bp, carla.Transform(), attach_to=self._parent)
|
self.sensor = world.spawn_actor(bp, carla.Transform(), attach_to=self._parent)
|
||||||
|
@ -503,25 +585,53 @@ class LaneInvasionSensor(object):
|
||||||
if not self:
|
if not self:
|
||||||
return
|
return
|
||||||
text = ['%r' % str(x).split()[-1] for x in set(event.crossed_lane_markings)]
|
text = ['%r' % str(x).split()[-1] for x in set(event.crossed_lane_markings)]
|
||||||
self._hud.notification('Crossed line %s' % ' and '.join(text))
|
self.hud.notification('Crossed line %s' % ' and '.join(text))
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# -- GnssSensor --------------------------------------------------------
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
class GnssSensor(object):
|
||||||
|
def __init__(self, parent_actor):
|
||||||
|
self.sensor = None
|
||||||
|
self._parent = parent_actor
|
||||||
|
self.lat = 0.0
|
||||||
|
self.lon = 0.0
|
||||||
|
world = self._parent.get_world()
|
||||||
|
bp = world.get_blueprint_library().find('sensor.other.gnss')
|
||||||
|
self.sensor = world.spawn_actor(bp, carla.Transform(carla.Location(x=1.0, z=2.8)),
|
||||||
|
attach_to=self._parent)
|
||||||
|
# We need to pass the lambda a weak reference to self to avoid circular
|
||||||
|
# reference.
|
||||||
|
weak_self = weakref.ref(self)
|
||||||
|
self.sensor.listen(lambda event: GnssSensor._on_gnss_event(weak_self, event))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _on_gnss_event(weak_self, event):
|
||||||
|
self = weak_self()
|
||||||
|
if not self:
|
||||||
|
return
|
||||||
|
self.lat = event.latitude
|
||||||
|
self.lon = event.longitude
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# -- CameraManager -------------------------------------------------------------
|
# -- CameraManager -------------------------------------------------------------
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
class CameraManager(object):
|
class CameraManager(object):
|
||||||
def __init__(self, parent_actor, hud):
|
def __init__(self, parent_actor, hud):
|
||||||
self.sensor = None
|
self.sensor = None
|
||||||
self._surface = None
|
self.surface = None
|
||||||
self._parent = parent_actor
|
self._parent = parent_actor
|
||||||
self._hud = hud
|
self.hud = hud
|
||||||
self._recording = False
|
self.recording = False
|
||||||
self._camera_transforms = [
|
self._camera_transforms = [
|
||||||
carla.Transform(carla.Location(x=-5.5, z=2.8), carla.Rotation(pitch=-15)),
|
carla.Transform(carla.Location(x=-5.5, z=2.8), carla.Rotation(pitch=-15)),
|
||||||
carla.Transform(carla.Location(x=1.6, z=1.7))]
|
carla.Transform(carla.Location(x=1.6, z=1.7))]
|
||||||
self._transform_index = 1
|
self.transform_index = 1
|
||||||
self._sensors = [
|
self.sensors = [
|
||||||
['sensor.camera.rgb', cc.Raw, 'Camera RGB'],
|
['sensor.camera.rgb', cc.Raw, 'Camera RGB'],
|
||||||
['sensor.camera.depth', cc.Raw, 'Camera Depth (Raw)'],
|
['sensor.camera.depth', cc.Raw, 'Camera Depth (Raw)'],
|
||||||
['sensor.camera.depth', cc.Depth, 'Camera Depth (Gray Scale)'],
|
['sensor.camera.depth', cc.Depth, 'Camera Depth (Gray Scale)'],
|
||||||
|
@ -532,75 +642,77 @@ class CameraManager(object):
|
||||||
['sensor.lidar.ray_cast', None, 'Lidar (Ray-Cast)']]
|
['sensor.lidar.ray_cast', None, 'Lidar (Ray-Cast)']]
|
||||||
world = self._parent.get_world()
|
world = self._parent.get_world()
|
||||||
bp_library = world.get_blueprint_library()
|
bp_library = world.get_blueprint_library()
|
||||||
for item in self._sensors:
|
for item in self.sensors:
|
||||||
bp = bp_library.find(item[0])
|
bp = bp_library.find(item[0])
|
||||||
if item[0].startswith('sensor.camera'):
|
if item[0].startswith('sensor.camera'):
|
||||||
bp.set_attribute('image_size_x', str(hud.dim[0]))
|
bp.set_attribute('image_size_x', str(hud.dim[0]))
|
||||||
bp.set_attribute('image_size_y', str(hud.dim[1]))
|
bp.set_attribute('image_size_y', str(hud.dim[1]))
|
||||||
|
elif item[0].startswith('sensor.lidar'):
|
||||||
|
bp.set_attribute('range', '5000')
|
||||||
item.append(bp)
|
item.append(bp)
|
||||||
self._index = None
|
self.index = None
|
||||||
|
|
||||||
def toggle_camera(self):
|
def toggle_camera(self):
|
||||||
self._transform_index = (self._transform_index + 1) % len(self._camera_transforms)
|
self.transform_index = (self.transform_index + 1) % len(self._camera_transforms)
|
||||||
self.sensor.set_transform(self._camera_transforms[self._transform_index])
|
self.sensor.set_transform(self._camera_transforms[self.transform_index])
|
||||||
|
|
||||||
def set_sensor(self, index, notify=True):
|
def set_sensor(self, index, notify=True):
|
||||||
index = index % len(self._sensors)
|
index = index % len(self.sensors)
|
||||||
needs_respawn = True if self._index is None \
|
needs_respawn = True if self.index is None \
|
||||||
else self._sensors[index][0] != self._sensors[self._index][0]
|
else self.sensors[index][0] != self.sensors[self.index][0]
|
||||||
if needs_respawn:
|
if needs_respawn:
|
||||||
if self.sensor is not None:
|
if self.sensor is not None:
|
||||||
self.sensor.destroy()
|
self.sensor.destroy()
|
||||||
self._surface = None
|
self.surface = None
|
||||||
self.sensor = self._parent.get_world().spawn_actor(
|
self.sensor = self._parent.get_world().spawn_actor(
|
||||||
self._sensors[index][-1],
|
self.sensors[index][-1],
|
||||||
self._camera_transforms[self._transform_index],
|
self._camera_transforms[self.transform_index],
|
||||||
attach_to=self._parent)
|
attach_to=self._parent)
|
||||||
# We need to pass the lambda a weak reference to self to avoid
|
# We need to pass the lambda a weak reference to self to avoid
|
||||||
# circular reference.
|
# circular reference.
|
||||||
weak_self = weakref.ref(self)
|
weak_self = weakref.ref(self)
|
||||||
self.sensor.listen(lambda image: CameraManager._parse_image(weak_self, image))
|
self.sensor.listen(lambda image: CameraManager._parse_image(weak_self, image))
|
||||||
if notify:
|
if notify:
|
||||||
self._hud.notification(self._sensors[index][2])
|
self.hud.notification(self.sensors[index][2])
|
||||||
self._index = index
|
self.index = index
|
||||||
|
|
||||||
def next_sensor(self):
|
def next_sensor(self):
|
||||||
self.set_sensor(self._index + 1)
|
self.set_sensor(self.index + 1)
|
||||||
|
|
||||||
def toggle_recording(self):
|
def toggle_recording(self):
|
||||||
self._recording = not self._recording
|
self.recording = not self.recording
|
||||||
self._hud.notification('Recording %s' % ('On' if self._recording else 'Off'))
|
self.hud.notification('Recording %s' % ('On' if self.recording else 'Off'))
|
||||||
|
|
||||||
def render(self, display):
|
def render(self, display):
|
||||||
if self._surface is not None:
|
if self.surface is not None:
|
||||||
display.blit(self._surface, (0, 0))
|
display.blit(self.surface, (0, 0))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_image(weak_self, image):
|
def _parse_image(weak_self, image):
|
||||||
self = weak_self()
|
self = weak_self()
|
||||||
if not self:
|
if not self:
|
||||||
return
|
return
|
||||||
if self._sensors[self._index][0].startswith('sensor.lidar'):
|
if self.sensors[self.index][0].startswith('sensor.lidar'):
|
||||||
points = np.frombuffer(image.raw_data, dtype=np.dtype('f4'))
|
points = np.frombuffer(image.raw_data, dtype=np.dtype('f4'))
|
||||||
points = np.reshape(points, (int(points.shape[0] / 3), 3))
|
points = np.reshape(points, (int(points.shape[0] / 3), 3))
|
||||||
lidar_data = np.array(points[:, :2])
|
lidar_data = np.array(points[:, :2])
|
||||||
lidar_data *= min(self._hud.dim) / 100.0
|
lidar_data *= min(self.hud.dim) / 100.0
|
||||||
lidar_data += (0.5 * self._hud.dim[0], 0.5 * self._hud.dim[1])
|
lidar_data += (0.5 * self.hud.dim[0], 0.5 * self.hud.dim[1])
|
||||||
lidar_data = np.fabs(lidar_data)
|
lidar_data = np.fabs(lidar_data) # pylint: disable=E1111
|
||||||
lidar_data = lidar_data.astype(np.int32)
|
lidar_data = lidar_data.astype(np.int32)
|
||||||
lidar_data = np.reshape(lidar_data, (-1, 2))
|
lidar_data = np.reshape(lidar_data, (-1, 2))
|
||||||
lidar_img_size = (self._hud.dim[0], self._hud.dim[1], 3)
|
lidar_img_size = (self.hud.dim[0], self.hud.dim[1], 3)
|
||||||
lidar_img = np.zeros(lidar_img_size)
|
lidar_img = np.zeros(lidar_img_size)
|
||||||
lidar_img[tuple(lidar_data.T)] = (255, 255, 255)
|
lidar_img[tuple(lidar_data.T)] = (255, 255, 255)
|
||||||
self._surface = pygame.surfarray.make_surface(lidar_img)
|
self.surface = pygame.surfarray.make_surface(lidar_img)
|
||||||
else:
|
else:
|
||||||
image.convert(self._sensors[self._index][1])
|
image.convert(self.sensors[self.index][1])
|
||||||
array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8"))
|
array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8"))
|
||||||
array = np.reshape(array, (image.height, image.width, 4))
|
array = np.reshape(array, (image.height, image.width, 4))
|
||||||
array = array[:, :, :3]
|
array = array[:, :, :3]
|
||||||
array = array[:, :, ::-1]
|
array = array[:, :, ::-1]
|
||||||
self._surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
|
self.surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
|
||||||
if self._recording:
|
if self.recording:
|
||||||
image.save_to_disk('_out/%08d' % image.frame_number)
|
image.save_to_disk('_out/%08d' % image.frame_number)
|
||||||
|
|
||||||
|
|
||||||
|
@ -622,13 +734,13 @@ def game_loop(args):
|
||||||
pygame.HWSURFACE | pygame.DOUBLEBUF)
|
pygame.HWSURFACE | pygame.DOUBLEBUF)
|
||||||
|
|
||||||
hud = HUD(args.width, args.height)
|
hud = HUD(args.width, args.height)
|
||||||
world = World(client.get_world(), hud)
|
world = World(client.get_world(), hud, args.filter)
|
||||||
controller = KeyboardControl(world, False)
|
controller = KeyboardControl(world, False)
|
||||||
|
|
||||||
if args.agent == "Roaming":
|
if args.agent == "Roaming":
|
||||||
agent = RoamingAgent(world.vehicle)
|
agent = RoamingAgent(world.player)
|
||||||
else:
|
else:
|
||||||
agent = BasicAgent(world.vehicle)
|
agent = BasicAgent(world.player)
|
||||||
spawn_point = world.map.get_spawn_points()[0]
|
spawn_point = world.map.get_spawn_points()[0]
|
||||||
agent.set_destination((spawn_point.location.x,
|
agent.set_destination((spawn_point.location.x,
|
||||||
spawn_point.location.y,
|
spawn_point.location.y,
|
||||||
|
@ -636,7 +748,7 @@ def game_loop(args):
|
||||||
|
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
while True:
|
while True:
|
||||||
if controller.parse_events(world, clock):
|
if controller.parse_events(client, world, clock):
|
||||||
return
|
return
|
||||||
|
|
||||||
# as soon as the server is ready continue!
|
# as soon as the server is ready continue!
|
||||||
|
@ -647,7 +759,8 @@ def game_loop(args):
|
||||||
world.render(display)
|
world.render(display)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
control = agent.run_step()
|
control = agent.run_step()
|
||||||
world.vehicle.apply_control(control)
|
control.manual_gear_shift = False
|
||||||
|
world.player.apply_control(control)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if world is not None:
|
if world is not None:
|
||||||
|
@ -685,7 +798,11 @@ def main():
|
||||||
metavar='WIDTHxHEIGHT',
|
metavar='WIDTHxHEIGHT',
|
||||||
default='1280x720',
|
default='1280x720',
|
||||||
help='window resolution (default: 1280x720)')
|
help='window resolution (default: 1280x720)')
|
||||||
|
argparser.add_argument(
|
||||||
|
'--filter',
|
||||||
|
metavar='PATTERN',
|
||||||
|
default='vehicle.*',
|
||||||
|
help='actor filter (default: "vehicle.*")')
|
||||||
argparser.add_argument("-a", "--agent", type=str,
|
argparser.add_argument("-a", "--agent", type=str,
|
||||||
choices=["Roaming", "Basic"],
|
choices=["Roaming", "Basic"],
|
||||||
help="select which agent to run",
|
help="select which agent to run",
|
||||||
|
@ -707,10 +824,7 @@ def main():
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print('\nCancelled by user. Bye!')
|
print('\nCancelled by user. Bye!')
|
||||||
except Exception as error:
|
|
||||||
logging.exception(error)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in New Issue