Merge branch 'master' of https://github.com/carla-simulator/carla
This commit is contained in:
commit
84978ded6c
|
@ -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.
|
||||
|
|
2
Makefile
2
Makefile
|
@ -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)"
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
from .carla import CARLA
|
||||
from .protoc import SceneDescription,EpisodeStart,EpisodeReady,Control,Measurements,RequestNewEpisode
|
||||
|
|
@ -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")
|
|
@ -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 ")
|
|
@ -0,0 +1,2 @@
|
|||
from .carla_server_pb2 import SceneDescription,EpisodeStart,EpisodeReady,Control,Measurements,RequestNewEpisode
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
|
@ -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()
|
||||
|
||||
|
||||
|
||||
|
4
Setup.sh
4
Setup.sh
|
@ -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 --------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue