carla/PythonClient/manual_control.py

272 lines
8.2 KiB
Python
Raw Normal View History

2017-10-26 20:48:22 +08:00
#!/usr/bin/env python3
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB), and the INTEL Visual Computing Lab.
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
# Keyboard controlling for carla. Please refer to client_example for a simpler
# and more documented example.
2017-10-26 20:48:22 +08:00
"""
Welcome to CARLA manual control.
2017-10-26 20:48:22 +08:00
Use ARROWS or WASD keys for control.
2017-10-26 20:48:22 +08:00
W : throttle
S : brake
AD : steer
Q : toggle reverse
Space : hand-brake
2017-10-26 20:48:22 +08:00
R : restart level
STARTING in a moment...
"""
from __future__ import print_function
2017-10-26 20:48:22 +08:00
import argparse
import logging
import random
import sys
import time
2017-10-26 20:48:22 +08:00
try:
import pygame
from pygame.locals import *
except ImportError:
raise RuntimeError('cannot import pygame, make sure pygame package is installed')
2017-10-26 20:48:22 +08:00
try:
import numpy as np
except ImportError:
raise RuntimeError('cannot import numpy, make sure numpy package is installed')
from carla import image_converter
from carla.client import make_carla_client, VehicleControl
from carla.settings import CarlaSettings, Camera
from carla.tcp import TCPConnectionError
from carla.util import print_over_same_line
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
MINI_WINDOW_WIDTH = 320
MINI_WINDOW_HEIGHT = 180
def make_carla_settings():
settings = CarlaSettings()
settings.set(
SynchronousMode=False,
NumberOfVehicles=15,
NumberOfPedestrians=30,
WeatherId=random.choice([1, 3, 7, 8, 14]))
settings.randomize_seeds()
camera0 = Camera('CameraRGB')
camera0.set_image_size(WINDOW_WIDTH, WINDOW_HEIGHT)
camera0.set_position(200, 0, 140)
camera0.set_rotation(0.0, 0.0, 0.0)
settings.add_camera(camera0)
camera1 = Camera('CameraDepth', PostProcessing='Depth')
camera1.set_image_size(MINI_WINDOW_WIDTH, MINI_WINDOW_HEIGHT)
camera1.set_position(200, 0, 140)
camera1.set_rotation(0.0, 0.0, 0.0)
settings.add_camera(camera1)
camera2 = Camera('CameraSemSeg', PostProcessing='SemanticSegmentation')
camera2.set_image_size(MINI_WINDOW_WIDTH, MINI_WINDOW_HEIGHT)
camera2.set_position(200, 0, 140)
camera2.set_rotation(0.0, 0.0, 0.0)
settings.add_camera(camera2)
return settings
class Timer(object):
def __init__(self):
2017-10-26 20:48:22 +08:00
self.step = 0
self._lap_step = 0
self._lap_time = time.time()
2017-10-26 20:48:22 +08:00
def tick(self):
2017-10-26 20:48:22 +08:00
self.step += 1
def lap(self):
self._lap_step = self.step
self._lap_time = time.time()
def ticks_per_second(self):
return float(self.step - self._lap_step) / self.elapsed_seconds_since_lap()
def elapsed_seconds_since_lap(self):
return time.time() - self._lap_time
class CarlaGame(object):
def __init__(self, carla_client):
self.client = carla_client
self._timer = None
self._display = None
self._main_image = None
self._mini_view_image1 = None
self._mini_view_image2 = None
self._is_on_reverse = False
def execute(self):
pygame.init()
self._initialize_game()
try:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
self._on_loop()
self._on_render()
finally:
pygame.quit()
def _initialize_game(self):
self._display = pygame.display.set_mode(
(WINDOW_WIDTH, WINDOW_HEIGHT),
pygame.HWSURFACE | pygame.DOUBLEBUF)
logging.debug('pygame started')
self._on_new_episode()
def _on_new_episode(self):
print('Requesting new episode...')
2017-11-20 22:50:49 +08:00
scene = self.client.load_carla_settings(make_carla_settings())
number_of_player_starts = len(scene.player_start_spots)
player_start = np.random.randint(number_of_player_starts)
self.client.start_episode(player_start)
self._timer = Timer()
2017-11-19 01:34:42 +08:00
self._is_on_reverse = False
def _on_loop(self):
self._timer.tick()
measurements, images = self.client.read_measurements()
self._main_image = images[0]
self._mini_view_image1 = images[1]
self._mini_view_image2 = images[2]
# Print measurements every second.
if self._timer.elapsed_seconds_since_lap() > 1.0:
self._print_player_measurements(measurements.player_measurements)
self._timer.lap()
control = self._get_keyboard_control(pygame.key.get_pressed())
if control is None:
self._on_new_episode()
else:
self.client.send_control(control)
def _get_keyboard_control(self, keys):
"""
Return a VehicleControl message based on the pressed keys. Return None
if a new episode was requested.
"""
if keys[K_r]:
return None
control = VehicleControl()
if keys[K_LEFT] or keys[K_a]:
control.steer = -1.0
if keys[K_RIGHT] or keys[K_d]:
control.steer = 1.0
if keys[K_UP] or keys[K_w]:
control.throttle = 1.0
if keys[K_DOWN] or keys[K_s]:
control.brake = 1.0
if keys[K_SPACE]:
control.hand_brake = True
if keys[K_q]:
self._is_on_reverse = not self._is_on_reverse
control.reverse = self._is_on_reverse
return control
def _print_player_measurements(self, player_measurements):
message = 'Step {step} ({fps:.1f} FPS): '
message += '{speed:.2f} km/h, '
message += '{other_lane:.0f}% other lane, {offroad:.0f}% off-road'
message = message.format(
step=self._timer.step,
fps=self._timer.ticks_per_second(),
speed=player_measurements.forward_speed,
other_lane=100 * player_measurements.intersection_otherlane,
offroad=100 * player_measurements.intersection_offroad)
print_over_same_line(message)
def _on_render(self):
gap_x = (WINDOW_WIDTH - 2 * MINI_WINDOW_WIDTH) / 3
mini_image_y = WINDOW_HEIGHT - MINI_WINDOW_HEIGHT - gap_x
if self._main_image is not None:
array = image_converter.to_rgb_array(self._main_image)
surface = pygame.surfarray.make_surface(array)
self._display.blit(surface, (0, 0))
if self._mini_view_image1 is not None:
array = image_converter.depth_to_grayscale(self._mini_view_image1)
surface = pygame.surfarray.make_surface(array)
self._display.blit(surface, (gap_x, mini_image_y))
if self._mini_view_image2 is not None:
array = image_converter.labels_to_cityscapes_palette(self._mini_view_image2)
surface = pygame.surfarray.make_surface(array)
self._display.blit(surface, (2 * gap_x + MINI_WINDOW_WIDTH, mini_image_y))
2017-10-26 20:48:22 +08:00
pygame.display.flip()
def main():
2017-11-19 01:34:42 +08:00
argparser = argparse.ArgumentParser(description='CARLA Manual Control Client')
argparser.add_argument(
'-v', '--verbose',
action='store_true',
dest='debug',
help='print debug information')
argparser.add_argument(
'--host',
metavar='H',
default='localhost',
help='IP of the host server (default: localhost)')
argparser.add_argument(
'-p', '--port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)')
args = argparser.parse_args()
log_level = logging.DEBUG if args.debug else logging.INFO
logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level)
2017-10-26 20:48:22 +08:00
logging.info('listening to server %s:%s', args.host, args.port)
2017-10-26 20:48:22 +08:00
print(__doc__)
2017-10-26 20:48:22 +08:00
while True:
try:
2017-10-26 20:48:22 +08:00
with make_carla_client(args.host, args.port) as client:
game = CarlaGame(client)
game.execute()
break
2017-10-26 20:48:22 +08:00
except TCPConnectionError as error:
logging.error(error)
time.sleep(1)
except Exception as exception:
logging.exception(exception)
sys.exit(1)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nCancelled by user. Bye!')