This commit is contained in:
nsubiron 2017-10-27 19:26:05 +02:00
commit 84978ded6c
27 changed files with 1246 additions and 32 deletions

View File

@ -13,7 +13,7 @@ Requires Python 3 and the protobuf module installed, saving images to disk
requires the PIL module too.
$ sudo apt-get install python3 python3-pip
$ sudo pip install protobuf
$ sudo pip3 install protobuf
A sample Python script is provided at `PythonClient/client_example.py`. The
script is well commented explaining how to use the client API.
@ -23,15 +23,18 @@ vehicle and saving images to disk. Run the help command to see options available
$ ./client_example.py --help
A second Python script is provided at `PythonClient/client_manual_control.py`. The
script is pygame dependent and servers as an interactive example where the user controls
the car with a keyboard Run the help command to see options available
$ ./client_manual_control.py --help
Running the server
------------------
IMPORTANT: By default the game starts in networking mode. It will hang until a
client is connected. See below how to run it without client.
IMPORTANT: Semantic segmentation ground-truth is disabled by default due to its
impact on performance. See below how to enable it.
The server can be started by running the `CarlaUE4.sh` script. When run in
networking mode (controlled by the CARLA client), it is highly recommended to
run it at fixed time-step
@ -64,24 +67,6 @@ frame-rate to get a more realistic feeling)
* `-carla-no-networking` Disable networking. Overrides other settings.
* `-carla-no-hud` Do not display the HUD by default.
#### Enable semantic segmentation ground-truth
Semantic segmentation ground-truth is disabled by default due to its impact on
performance. When disabled, semantic segmentation images will display a single
red color for every object. To make the engine draw the right tags we need to
activate the custom depth in the configuration file.
Open the configuration file `CarlaUE4/Saved/Config/LinuxNoEditor/Engine.ini`,
and add the following
```
[/Script/Engine.RendererSettings]
r.CustomDepth=3
```
Now run the game as usual and semantic segmentation images will be produced with
the right tags.
#### In-game controls
The following key bindings are available during game play at the server window.

View File

@ -1,5 +1,5 @@
INSTALL_FOLDER=$(CURDIR)/Unreal/CarlaUE4/Plugins/Carla/CarlaServer
PYTHON_CLIENT_FOLDER=$(CURDIR)/PythonClient/test
PYTHON_CLIENT_FOLDER=$(CURDIR)/Util/TestingClient/test
BASE_BUILD_FOLDER=$(CURDIR)/Util/Build/carlaserver-build
MY_CMAKE_FOLDER=$(CURDIR)/Util/cmake
MY_CMAKE_FLAGS=-B"$(BUILD_FOLDER)" -DCMAKE_INSTALL_PREFIX="$(INSTALL_FOLDER)"

View File

@ -0,0 +1,37 @@
[CARLA/Server]
UseNetworking=true
SynchronousMode = false
SendNonPlayerAgentsInfo= true
[CARLA/LevelSettings]
NumberOfVehicles=10
NumberOfPedestrians=10
WeatherId=1
[CARLA/SceneCapture]
Cameras=RGB,DepthMap,Labels
ImageSizeX=800
ImageSizeY=600
CameraFOV=100
CameraPositionX=200
CameraPositionY=0
CameraPositionZ=140
CameraRotationPitch=-15.0
CameraRotationRoll=0
CameraRotationYaw=0
[CARLA/SceneCapture/RGB]
PostProcessing=SceneFinal
CameraPositionY=0
CameraRotationYaw=0
[CARLA/SceneCapture/DepthMap]
PostProcessing=Depth
CameraPositionY=0
CameraRotationYaw=0
[CARLA/SceneCapture/Labels]
PostProcessing=SemanticSegmentation
CameraPositionY=0
CameraRotationYaw=0

View File

@ -0,0 +1,3 @@
from .carla import CARLA
from .protoc import SceneDescription,EpisodeStart,EpisodeReady,Control,Measurements,RequestNewEpisode

323
PythonClient/carla/carla.py Normal file
View File

@ -0,0 +1,323 @@
#!/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>.
from __future__ import print_function
from .datastream import DataStream
import socket
import time
import os, signal
import sys
import logging
import struct
import re
from .protoc import *
from . import socket_util
def get_image_resolution(data):
return int(re.search('[\n\r].*ImageSizeX\s*=([^\n\r]*)', data).group(1)),int(re.search('[\n\r].*ImageSizeY\s*=([^\n\r]*)', data).group(1))
class CARLA(object):
"""
Normal instanciation of the class, creating also the thread class responsible for receiving data
"""
def __init__(self,host,port):
self._host = host
self._port = port
logging.debug('selected host %s' % host)
logging.debug('selected port %s' % port)
self._port_control = self._port +2
self._port_stream = self._port +1
# Default start. Keep it as class param for eventual restart
self._image_x =0
self._image_y = 0
self._socket_world = socket_util.pers_connect(self._host ,self._port)
print ('Successfully Connected to Carla Server')
logging.debug("Connected to Unreal Server World Socket")
self._socket_stream = 0
self._socket_control = 0
self._latest_start = 0
self._agent_is_running = False
self._episode_requested = False
self._data_stream = None
logging.debug("Started Unreal Client")
"""
Starting the Player Agent. The image stream port
and the control port
Args:
None
Returns:
None
"""
def startAgent(self):
self._data_stream = DataStream(self._image_x,self._image_y)
logging.debug("Going to Connect Stream and start thread")
# Perform persistent connections, try up to 10 times
try:
self._socket_stream = socket_util.pers_connect(self._host ,self._port_stream)
except Exception:
logging.exception("Attempts to connect Stream all failed, restart...")
self.restart()
self._data_stream.start(self._socket_stream)
logging.debug("Streaming Thread Started")
try:
self._socket_control = socket_util.pers_connect(self._host ,self._port_control)
except Exception:
logging.exception("Attempts to connect Agent all failed, restart ...")
self.restart()
logging.debug("Control Socket Connected")
self._agent_is_running = True
def stopAgent(self):
logging.debug("Going to Stop thread and Disconect Stream")
self._data_stream.stop()
logging.debug("Streaming Thread Stoped")
socket_util.disconnect(self._socket_control)
logging.debug("Control Socket DisConnected")
self._agent_is_running = False
# This function requests a new episode and send the string containing this episode configuration file
def receiveSceneConfiguration(self):
try:
logging.debug("Reading for the scene configuration")
data = socket_util.get_message(self._socket_world)
scene = SceneDescription()
scene.ParseFromString(data)
logging.debug("Received Scene Configuration")
return scene.player_start_spots
except Exception as e:
logging.exception("Server not responing when receiving configuration")
return self.restart()
def requestNewEpisode(self,ini_path=None):
if ini_path == None:
ini_file = self._config_path
else:
ini_file = ini_path
self._config_path = ini_path # We just save the last config file in case the client dies
requestEpisode = RequestNewEpisode()
with open (ini_file, "r") as myfile:
data=myfile.read()
try:
self._image_x,self._image_y = get_image_resolution(data)
except Exception as e:
logging.exception("No image resolution found on config file")
logging.debug("Resolution %d , %d",self._image_x,self._image_y)
logging.debug("Set the Init File")
logging.debug("sent %s" % (data))
requestEpisode.ini_file = data.encode('utf-8')
try:
socket_util.send_message(self._socket_world,requestEpisode)
except Exception as e:
logging.exception("Server not responding when requesting new episode")
self.restart()
else:
logging.debug("Successfully sent the new episode Request")
if self._agent_is_running:
self.stopAgent()
self._episode_requested = True
return self.receiveSceneConfiguration()
def loadConfigurationFile(self,ini_path):
return self.requestNewEpisode(ini_path)
def newEpisode(self,start_index):
# Save the latest new episode positon, just in case of crashes
self._latest_start = start_index
if not self._episode_requested:
positions = self.requestNewEpisode(self._config_path)
scene_init = EpisodeStart()
scene_init.player_start_spot_index = start_index
try:
socket_util.send_message(self._socket_world,scene_init)
except Exception:
logging.exception("Server not responding when trying to send episode start confirmation")
self.restart()
else:
logging.debug("Successfully sent the new episode Message")
episode_ready = EpisodeReady()
episode_ready.ready = False
try:
data = socket_util.get_message(self._socket_world)
logging.debug("Got the episode ready message")
episode_ready.ParseFromString(data)
except Exception:
logging.exception("Server not responding when trying to receive episode reading")
self.restart()
else:
logging.debug("Episode is Ready")
self.startAgent()
self._episode_requested = False
""" Measurements
returns
@game time
@wall time
@player measurements
@non_player_agents : vector with all agents present on the game
@image_data
"""
def getMeasurements(self):
while True:
try:
meas_dict = self._data_stream.get_the_latest_data()
logging.debug("Got A new Measurement")
return meas_dict
except AttributeError:
logging.exception("Unitialized DataStream. Tip: Connect and start an episode before requesting measurements")
return None
except Exception:
logging.exception("Got an empty Measurement")
self.restart()
""" Command contains:
Steering: -1 to 1
Acc : -1 to 1
"""
def sendCommand(self,control):
logging.debug("Send Control Comand : throttle -> %f , steer %f, brake %f, hand_brake %d, gear %d" % (control.throttle,control.steer,control.brake,control.hand_brake,control.reverse))
try:
socket_util.send_message(self._socket_control,control)
except Exception:
logging.exception("Problems on sending the commands... restarting")
self.restart() # the mensage is not resend because it likely lost its relevance.
def restart(self):
logging.debug("Trying to close clients")
self.closeConections()
connected = False
if self._data_stream != None:
self._data_stream._running = False
self._agent_is_running = False
while not connected:
try:
logging.debug("Trying to connect to the world thread")
self._socket_world = socket_util.connect(self._host ,self._port)
connected = True
except Exception:
logging.exception("Couldn't connected ... retry in 10 seconds...")
time.sleep(10)
self._data_stream = DataStream(self._image_x,self._image_y)
positions = self.requestNewEpisode()
self.newEpisode(self._latest_start)
logging.debug("restarted the world connection")
return positions
def stop(self):
self.closeConections()
connected = False
self._data_stream._running = False
self._data_stream = DataStream(self._image_x,self._image_y)
def closeConections(self):
try:
self._socket_world.shutdown(socket.SHUT_RDWR)
self._socket_world.close()
logging.debug("Close world")
except Exception as ex:
logging.exception("Exception on closing Connections")
try:
self._socket_stream.shutdown(socket.SHUT_RDWR)
self._socket_stream.close()
logging.debug("Close Stream")
except Exception as ex:
logging.exception("Exception on closing Connections")
try:
self._socket_control.shutdown(socket.SHUT_RDWR)
self._socket_control.close()
logging.debug("Close Control")
except Exception as ex:
logging.exception("Exception on closing Connections")

View File

@ -0,0 +1,221 @@
#!/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>.
"""Basic CARLA client example."""
import sys
is_py2 = sys.version[0] == '2'
if is_py2:
import Queue as Queue
else:
import queue as Queue
from threading import Thread
import time
import random
from PIL import Image
from .socket_util import *
import io
import sys
import numpy as np
import logging
from .protoc import *
def threaded(fn):
def wrapper(*args, **kwargs):
thread = Thread(target=fn, args=args, kwargs=kwargs)
thread.setDaemon(True)
thread.start()
return thread
return wrapper
class DataStream(object):
def __init__(self,image_x=640,image_y=480):
self._data_buffer = Queue.Queue(1)
self._image_x = image_x
self._image_y = image_y
self._socket = 0
self._running = True
def _read_image(self,imagedata,pointer):
width = struct.unpack('<L',imagedata[pointer:(pointer+4)])[0]
pointer +=4
height = struct.unpack('<L',imagedata[pointer:(pointer+4)])[0]
pointer +=4
im_type = struct.unpack('<L',imagedata[pointer:(pointer+4)])[0]
pointer +=4
image_size = width*height*4
image_bytes = imagedata[pointer:(pointer+image_size)]
dt = np.dtype("uint8")
new_image =np.frombuffer(image_bytes,dtype=dt)
new_image = np.reshape(new_image,(self._image_y,self._image_x,4)) # TODO: make this generic
pointer += image_size
return new_image,im_type,pointer
def receive_data(self):
depths = []
# First we get the message of the google protocol
capture_time = time.time()
try:
data = get_message(self._socket)
except Exception:
if self._running:
logging.exception("Error on Datastream, Raise Again")
raise Exception
return [] # return something empty, since it is not running anymore
measurements = Measurements()
measurements.ParseFromString(data)
player_measures = measurements.player_measurements
non_player_agents = measurements.non_player_agents
try:
logging.debug(" Trying to get the image")
imagedata = get_message(self._socket)
except Exception:
if self._running:
logging.exception("Error on Datastream, Raise Again")
raise Exception
return [] # return something empty, since it is not running anymore
meas_dict ={}
meas_dict.update({'RAW_BGRA':[]})
meas_dict.update({'BGRA':[]})
meas_dict.update({'Depth':[]})
meas_dict.update({'Labels':[]})
pointer = 0
while pointer < len(imagedata):
image,im_type,pointer = self._read_image(imagedata,pointer)
if im_type == 0:
meas_dict['RAW_BGRA'].append(image)
logging.debug("RECEIVED rgb_raw")
if im_type == 1:
meas_dict['BGRA'].append(image)
logging.debug("RECEIVED rgb")
if im_type == 2:
meas_dict['Depth'].append(image)
logging.debug("RECEIVED depht")
if im_type == 3:
meas_dict['Labels'].append(image)
logging.debug("RECEIVED scene_seg")
meas_dict.update({'WallTime':measurements.platform_timestamp})
meas_dict.update({'GameTime':measurements.game_timestamp})
meas_dict.update({'PlayerMeasurements':player_measures})
meas_dict.update({'Agents':non_player_agents})
return meas_dict
def get_the_latest_data(self):
try:
data = self._data_buffer.get(timeout=20)
except Queue.Empty:
logging.exception("ERROR: No Data in 20 seconds, disconecting and reconecting from server ")
self._running = False
raise Queue.Empty
except Exception:
logging.exception("Other error on getting queue")
raise Exception
else:
self._data_buffer.task_done()
return data
def start(self,socket):
self._socket = socket
self.run()
def stop(self):
self._running = False
disconnect(self._socket)
self.clean()
# We clean the buffer so that no old data is going to be used
def clean(self):
while True:
try:
aux=self._data_buffer.get(False)
except Queue.Empty:
return
@threaded
def run(self):
try:
while self._running:
try:
self._data_buffer.put(self.receive_data(),timeout=20)
except Queue.Full:
logging.exception("ERROR: Queue Full for more than 20 seconds...")
except Exception as e:
logging.exception("Some internal Socket error ")
self._running = False
except RuntimeError:
logging.exception("Unexpected RuntimeError")
self._running = False
finally:
logging.debug("We Are finishing the datastream thread ")

View File

@ -0,0 +1,2 @@
from .carla_server_pb2 import SceneDescription,EpisodeStart,EpisodeReady,Control,Measurements,RequestNewEpisode

View File

@ -0,0 +1,114 @@
#!/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>.
import binascii
import socket
import struct
import logging
import time
import select
def int2bytes(i):
hex_string = '%x' % i
n = len(hex_string)
return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
def bytes2int(str):
return int(str.encode('hex'), 16)
def connect(host,port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(100)
except socket.error:
logginge.exception("Error Creating Socket World")
sock.connect((host,port))
logging.debug("connected to %s port %d" %(host,port))
return sock
def pers_connect(host,port):
for attempt in range(10):
try:
sock = connect(host,port)
return sock
except Exception as e:
logging.exception("Failure on connection")
time.sleep(1)
continue
else:
break
raise socket.error
def disconnect(sock):
sock.shutdown(socket.SHUT_RDWR)
sock.close()
def send_message(sock, message):
""" Send a serialized message (protobuf Message interface)
to a socket, prepended by its length packed in 4
bytes (big endian).
"""
s = message.SerializeToString()
packed_len =struct.pack('<L', len(s)) #int2bytes(len(s))
logging.debug( "SOCKET Send: %d bytes" % int(len(s)))
sock.sendall(packed_len + s)
def get_message(sock):
""" Read a message from a socket.
"""
len_buf = socket_read_n(sock, 4)
msg_len = struct.unpack('<L', len_buf)[0]
logging.debug( "SOCKET RECEIVED: %d bytes" % msg_len)
msg_buf = socket_read_n(sock, msg_len)
return msg_buf
def socket_read_n(sock,n):
""" Read exactly n bytes from the socket.
Raise RuntimeError if the connection closed before
n bytes were read.
"""
buf = b''
while n > 0:
sock.setblocking(0)
ready = select.select([sock], [], [], 3)
if ready[0]:
try:
data = sock.recv(n)
if data == b'':
raise RuntimeError('unexpected connection close')
buf += data
n -= len(data)
except socket.error:
raise socket.error
sock.setblocking(1)
return buf

View File

@ -0,0 +1,241 @@
#!/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>.
"""Basic CARLA client example."""
from __future__ import print_function
# General Imports
import numpy as np
from PIL import Image
import random
import time
import sys
import argparse
import logging
import os
# Carla imports, Everything can be imported directly from "carla" package
from carla import CARLA
from carla import Control
from carla import Measurements
# Constant that set how offten the episodes are reseted
RESET_FREQUENCY = 100
"""
Print function, prints all the measurements saving
the images into a folder. WARNING just prints the first BGRA image
Args:
param1: The measurements dictionary to be printed
param2: The iterations
Returns:
None
Raises:
None
"""
def print_pack(measurements,i,write_images):
if write_images:
image_result = Image.fromarray( measurements['BGRA'][0])
b, g, r,a = image_result.split()
image_result = Image.merge("RGBA", (r, g, b,a))
if not os.path.exists('images'):
os.mkdir('images')
image_result.save('images/image' + str(i) + '.png')
print ('Pack ',i)
print (' Wall Time: ',measurements['WallTime'])
print (' Game Time: ',measurements['GameTime'])
print (' Player Measurements ')
print (' Position: (%f,%f,%f)' % (measurements['PlayerMeasurements'].\
transform.location.x,measurements['PlayerMeasurements'].transform.location.y,\
measurements['PlayerMeasurements'].transform.location.z ))
print (' Orientation: (%f,%f,%f)' % (measurements['PlayerMeasurements'].\
transform.orientation.x,measurements['PlayerMeasurements'].transform.orientation.y,\
measurements['PlayerMeasurements'].transform.orientation.z ))
print (' Acceleration: (%f,%f,%f)' % (measurements['PlayerMeasurements'].\
acceleration.x,measurements['PlayerMeasurements'].acceleration.y,measurements['PlayerMeasurements'].acceleration.z ))
print (' Speed: ',measurements['PlayerMeasurements'].forward_speed)
print (' Collision Vehicles (Acum. Impact): ',measurements['PlayerMeasurements'].collision_vehicles)
print (' Collision Pedestrians (Acum. Impact): ',measurements['PlayerMeasurements'].collision_pedestrians)
print (' Collision Other (Acum. Impact): ',measurements['PlayerMeasurements'].collision_other)
print (' Intersection Opposite Lane (% Volume): ',measurements['PlayerMeasurements'].intersection_otherlane)
print (' Intersection Opposite Sidewalk (% Volume): ',measurements['PlayerMeasurements'].intersection_offroad)
print (' ',len(measurements['Agents']),' Agents (Positions not printed)')
print (' ',end='')
for agent in measurements['Agents']:
if agent.HasField('vehicle'):
print ('Car',end='')
elif agent.HasField('pedestrian'):
print ('Pedestrian',end='')
elif agent.HasField('traffic_light'):
print ('Traffic Light',end='')
elif agent.HasField('speed_limit_sign'):
print ('Speed Limit Sign',end='')
print(',',end='')
print('')
def use_example(ini_file,port = 2000, host ='127.0.0.1',print_measurements =False,images_to_disk=False):
# We assume the CARLA server is already waiting for a client to connect at
# host:port. To create a connection we can use the CARLA
# constructor, it creates a CARLA client object and starts the
# connection. It will throw an exception if something goes wrong.
carla =CARLA(host,port)
""" As a first step, Carla must have a configuration file loaded. This will load a map in the server
with the properties specified by the ini file. It returns all the posible starting positions on the map
in a vector.
"""
positions = carla.loadConfigurationFile(ini_file)
"""
Ask Server for a new episode starting on position of index zero in the positions vector
"""
carla.newEpisode(0)
capture = time.time()
# General iteratior
i = 1
# Iterator that will go over the positions on the map after each episode
iterator_start_positions = 1
while True:
try:
"""
User get the measurements dictionary from the server.
Measurements contains:
* WallTime: Current time on Wall from server machine.
* GameTime: Current time on Game. Restarts at every episode
* PlayerMeasurements : All information and events that happens to player
* Agents : All non-player agents present on the map information such as cars positions, traffic light states
* BRGA : BGRA optical images
* Depth : Depth Images
* Labels : Images containing the semantic segmentation. NOTE: the semantic segmentation must be
previously activated on the server. See documentation for that.
"""
measurements = carla.getMeasurements()
# Print all the measurements... Will write images to disk
if print_measurements:
print_pack(measurements,i,images_to_disk)
"""
Sends a control command to the server
This control structue contains the following fields:
* throttle : goes from 0 to -1
* steer : goes from -1 to 1
* brake : goes from 0 to 1
* hand_brake : Activate or desactivate the Hand Brake.
* reverse: Activate or desactive the reverse gear.
"""
control = Control()
control.throttle = 0.9
control.steer = (random.random() * 2) - 1
carla.sendCommand(control)
i+=1
if i % RESET_FREQUENCY ==0:
print ('Fps for this episode : ',(1.0/((time.time() -capture)/100.0)))
"""
Starts another new episode, the episode will have the same configuration as the previous
one. In order to change configuration, the loadConfigurationFile could be called at any
time.
"""
if iterator_start_positions < len(positions):
carla.newEpisode(iterator_start_positions)
iterator_start_positions+=1
else :
carla.newEpisode(0)
iterator_start_positions = 1
print("Now Starting on Position: ",iterator_start_positions-1)
capture = time.time()
except Exception as e:
logging.exception('Exception raised to the top')
time.sleep(1)
if __name__ == "__main__" :
parser = argparse.ArgumentParser(description='Run the carla client example that connects to a server')
parser.add_argument('host', metavar='HOST', type=str, help='host to connect to')
parser.add_argument('port', metavar='PORT', type=int, help='port to connect to')
parser.add_argument("-c", "--config", help="the path for the server ini file that the client sends",type=str,default="CarlaSettings.ini")
parser.add_argument("-l", "--log", help="activate the log file",action="store_true")
parser.add_argument("-lv", "--log_verbose", help="activate log and put the log file to screen",action="store_true")
parser.add_argument("-pm", "--print", help=" prints the game measurements",action="store_true")
parser.add_argument(
'-i', '--images-to-disk',
action='store_true',
help='save images to disk')
args = parser.parse_args()
if args.log or args.log_verbose:
LOG_FILENAME = 'log_manual_control.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
if args.log_verbose: # set of functions to put the logging to screen
root = logging.getLogger()
root.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)
else:
sys.tracebacklimit=0 # Avoid huge exception messages out of debug mode
use_example(args.config,port=args.port, host=args.host,print_measurements=args.print,images_to_disk= args.images_to_disk)

View File

@ -0,0 +1,268 @@
#!/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 carla_use_example for a simpler and more
documented example.
"""
from __future__ import print_function
from carla import CARLA
#from scene_parameters import SceneParams
from PIL import Image
import numpy as np
import random
import time
import sys
import argparse
import logging
from socket import error as socket_error
import matplotlib.pyplot as plt
from carla import Control,Measurements
import pygame
from pygame.locals import *
def join_classes(labels_image):
classes_join = {0:[0,0,0],1:[64,64,64],2:[96,96,96],3:[255,255,255],5:[128,128,128],12:2,9:[0,255,0],\
11:[32,32,32],4:[255,0,0],10:[0,0,255],8:[255,0,255],6:[196,196,196],7:[128,0,128]}
compressed_labels_image = np.zeros((labels_image.shape[0],labels_image.shape[1],3))
for key,value in classes_join.iteritems():
compressed_labels_image[np.where(labels_image==key)] = value
return compressed_labels_image
# Function for making colormaps
def grayscale_colormap(img,colormap):
cmap = plt.get_cmap(colormap)
rgba_img = cmap(img)
rgb_img = np.delete(rgba_img, 3, 2)
return rgb_img
# Function to convert depth to human readable format
def convert_depth(depth):
depth = depth.astype(np.float32)
gray_depth = ((depth[:,:,0] + depth[:,:,1]*256.0 + depth[:,:,2]*256.0*256.0)/(256.0*256.0*256.0 ))
color_depth =grayscale_colormap(gray_depth,'jet')*255
return color_depth
class App:
def __init__(self, port=2000, host='127.0.0.1', config='./CarlaSettings.ini',\
resolution=(2400,600),verbose=True):
self._running = True
self._display_surf = None
self.port = port
self.host = host
self.config = config
self.verbose = verbose
self.resolution = resolution
self.size = self.weight, self.height = resolution
def on_init(self):
pygame.init()
print (" \n \n \n Welcome to CARLA manual control \n USE ARROWS for control \n Press R for reset \n"\
+"STARTING in a few seconds...")
time.sleep(3)
self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
logging.debug('Started the PyGame Library')
self._running = True
self.step = 0
self.prev_step = 0
self.prev_time = time.time()
self.carla =CARLA(self.host, self.port)
positions = self.carla.loadConfigurationFile(self.config)
self.num_pos = len(positions)
print ("Staring Episode on Position ",self.num_pos)
self.carla.newEpisode(np.random.randint(self.num_pos))
self.prev_restart_time = time.time()
def on_event(self, event):
if event.type == pygame.QUIT:
self._running = False
def on_loop(self):
self.step += 1
keys=pygame.key.get_pressed()
gas = 0
steer = 0
restart = False
pressed_keys = []
if keys[K_LEFT]:
steer = -1.
pressed_keys.append('left')
if keys[K_RIGHT]:
pressed_keys.append('right')
steer = 1.
if keys[K_UP]:
pressed_keys.append('up')
gas = 1.
if keys[K_DOWN]:
pressed_keys.append('down')
gas = -1.
if keys[K_r]:
pressed_keys.append('r')
if time.time() - self.prev_restart_time > 2.:
self.prev_restart_time = time.time()
restart = True
if time.time() - self.prev_restart_time < 2.:
gas = 0.
steer = 0.
control = Control()
control.throttle = gas
control.steer = steer
self.carla.sendCommand(control)
measurements = self.carla.getMeasurements()
pack = measurements['PlayerMeasurements']
self.img_vec = measurements['BGRA']
self.depth_vec = measurements['Depth']
self.labels_vec = measurements['Labels']
if time.time() - self.prev_time > 1.:
print('Step', self.step, 'FPS', float(self.step - self.prev_step) / (time.time() - self.prev_time))
print('speed', pack.forward_speed, 'collision', pack.collision_other, \
'collision_car', pack.collision_vehicles, 'colision_ped', pack.collision_pedestrians, 'pressed:', pressed_keys)
self.prev_step = self.step
self.prev_time = time.time()
if restart:
print('\n *** RESTART *** \n')
player_pos = np.random.randint(self.num_pos)
print(' Player pos %d \n' % (player_pos))
self.carla.newEpisode(player_pos)
"""
The render method plots the First RGB, the First Depth and First Semantic Segmentation Camera
"""
def on_render(self):
pos_x =0
if len(self.depth_vec) > 0:
self.depth_vec[0] = self.depth_vec[0][:,:,:3]
self.depth_vec[0] = self.depth_vec[0][:,:,::-1]
self.depth_vec[0] = convert_depth(self.depth_vec[0])
surface = pygame.surfarray.make_surface(np.transpose(self.depth_vec[0], (1,0,2)))
self._display_surf.blit(surface,(pos_x,0))
pos_x += self.depth_vec[0].shape[1]
if len(self.img_vec) > 0:
self.img_vec[0] = self.img_vec[0][:,:,:3]
self.img_vec[0] = self.img_vec[0][:,:,::-1]
surface = pygame.surfarray.make_surface(np.transpose(self.img_vec[0], (1,0,2)))
self._display_surf.blit(surface,(pos_x,0))
pos_x += self.img_vec[0].shape[1]
if len(self.labels_vec) > 0:
self.labels_vec[0] = join_classes(self.labels_vec[0][:,:,2])
surface = pygame.surfarray.make_surface(np.transpose(self.labels_vec[0], (1,0,2)))
self._display_surf.blit(surface,(pos_x,0))
pos_x += self.labels_vec[0].shape[1]
pygame.display.flip()
def on_cleanup(self):
self.carla.closeConections()
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
try:
for event in pygame.event.get():
self.on_event(event)
self.on_loop()
self.on_render()
except Exception as e:
logging.exception(e)
self._running = False
break
self.on_cleanup()
if __name__ == "__main__" :
parser = argparse.ArgumentParser(description='Run the carla client manual that connects to CARLA server')
parser.add_argument('host', metavar='HOST', type=str, help='host to connect to')
parser.add_argument('port', metavar='PORT', type=int, help='port to connect to')
parser.add_argument("-c", "--config", help="the path for the server .ini config file that the client sends",type=str,default="./CarlaSettings.ini")
parser.add_argument("-l", "--log", help="activate the log file",action="store_true")
parser.add_argument("-lv", "--log_verbose", help="put the log file to screen",action="store_true")
args = parser.parse_args()
print(args)
if args.log or args.log_verbose:
LOG_FILENAME = 'log_manual_control.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
if args.log_verbose: # set of functions to put the logging to screen
root = logging.getLogger()
root.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)
theApp = App(port=args.port, host=args.host, config=args.config)
theApp.on_execute()

View File

@ -167,7 +167,7 @@ popd >/dev/null
popd >/dev/null
# ==============================================================================
# -- Copy CarlaSettings.ini ----------------------------------------------------
# -- Other CARLA files ---------------------------------------------------------
# ==============================================================================
popd >/dev/null
@ -178,6 +178,8 @@ if [[ ! -f $CARLA_SETTINGS_FILE ]]; then
cp -v ./Docs/Example.CarlaSettings.ini $CARLA_SETTINGS_FILE
fi
./Util/Protoc.sh
# ==============================================================================
# -- ...and we are done --------------------------------------------------------
# ==============================================================================

View File

@ -20,7 +20,7 @@ r.DefaultFeature.Bloom=False
r.DefaultFeature.AmbientOcclusion=False
r.DefaultFeature.AmbientOcclusionStaticFraction=False
r.DefaultFeature.AutoExposure=False
r.CustomDepth=1
r.CustomDepth=3
[/Script/AIModule.AISense_Sight]
bAutoRegisterAllPawnsAsSources=False

View File

@ -4,4 +4,4 @@
#
# You can direct download with https://drive.google.com/open?id=PUT_FILE_ID_HERE
0.5.4: 0B2HFV-VuKn3PRm1zYmxnWlY0ZWM
0.5.4: 0B2HFV-VuKn3PeS11cjFyLWhzS2M

View File

@ -2,14 +2,16 @@
set PROTOBUF_SRC_DIR=Proto
set PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server
set PROTOBUF_PY_OUT_DIR=../PythonClient/carla
set PROTOBUF_PY_OUT_DIR0=../PythonClient/carla/protoc
set PROTOBUF_PY_OUT_DIR1=TestingClient/carla
set PROTO_BASENAME=carla_server
if "%1" == "--clean" (
rem Delete existing ones.
rm -f %PROTOBUF_CPP_OUT_DIR%/carla_server.pb.h
rm -f %PROTOBUF_CPP_OUT_DIR%/carla_server.pb.cc
rm -f %PROTOBUF_PY_OUT_DIR%/carla_server_pb2.py
rm -f %PROTOBUF_PY_OUT_DIR0%/carla_server_pb2.py
rm -f %PROTOBUF_PY_OUT_DIR1%/carla_server_pb2.py
goto end
)
@ -22,7 +24,8 @@ if exist %PROTOC% (
%PROTOC% ^
-I=%PROTOBUF_SRC_DIR% ^
--cpp_out=%PROTOBUF_CPP_OUT_DIR% ^
--python_out=%PROTOBUF_PY_OUT_DIR% ^
--python_out=%PROTOBUF_PY_OUT_DIR0% ^
--python_out=%PROTOBUF_PY_OUT_DIR1% ^
%PROTOBUF_SRC_DIR%/%PROTO_BASENAME%.proto
echo done.

View File

@ -7,13 +7,15 @@ pushd "$SCRIPT_DIR" >/dev/null
PROTOBUF_SRC_DIR=Proto
PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server
PROTOBUF_PY_OUT_DIR=../PythonClient/carla
PROTOBUF_PY_OUT_DIR0=../PythonClient/carla/protoc
PROTOBUF_PY_OUT_DIR1=TestingClient/carla
PROTO_BASENAME=carla_server
if [ "$1" == "--clean" ]; then
# Delete existing ones.
rm -f ${PROTOBUF_CPP_OUT_DIR}/*.pb.h ${PROTOBUF_CPP_OUT_DIR}/*.pb.cc
rm -f ${PROTOBUF_PY_OUT_DIR}/*_pb2.py
rm -f ${PROTOBUF_PY_OUT_DIR0}/*_pb2.py
rm -f ${PROTOBUF_PY_OUT_DIR1}/*_pb2.py
exit 0
fi
@ -31,7 +33,8 @@ echo "Compiling ${PROTO_BASENAME}.proto..."
${PROTOC} \
-I=${PROTOBUF_SRC_DIR} \
--cpp_out=${PROTOBUF_CPP_OUT_DIR} \
--python_out=${PROTOBUF_PY_OUT_DIR} \
--python_out=${PROTOBUF_PY_OUT_DIR0} \
--python_out=${PROTOBUF_PY_OUT_DIR1} \
${PROTOBUF_SRC_DIR}/${PROTO_BASENAME}.proto
popd >/dev/null

View File

@ -0,0 +1,12 @@
CARLA Client for Testing
========================
Requires Python 3 and the protobuf module installed, saving images to disk
requires the PIL module too.
$ sudo apt-get install python3 python3-pip
$ sudo pip3 install protobuf
A sample Python script explaining how to use the client API is provided
$ ./client_example.py --help

View File