Improved python client, ported to python 3
This commit is contained in:
parent
45d78645a9
commit
1d7e5ec769
12
Makefile
12
Makefile
|
@ -71,13 +71,13 @@ run_test_release:
|
|||
@-LD_LIBRARY_PATH=$(INSTALL_FOLDER)/shared $(INSTALL_FOLDER)/bin/test_carlaserver --gtest_shuffle $(GTEST_ARGS)
|
||||
|
||||
launch_test_clients:
|
||||
@echo "Launch echo_client.py"
|
||||
@python $(PYTHON_CLIENT_FOLDER)/echo_client.py -p 4000 & echo $$! > echo_client.pid
|
||||
@echo "Launch carla_client.py"
|
||||
@python $(PYTHON_CLIENT_FOLDER)/carla_client.py -p 2000 & echo $$! > carla_client.pid
|
||||
@echo "Launch echo client"
|
||||
@python3 $(PYTHON_CLIENT_FOLDER)/client_test.py --echo -p 4000 --log echo_client.log & echo $$! > echo_client.pid
|
||||
@echo "Launch carla client"
|
||||
@python3 $(PYTHON_CLIENT_FOLDER)/client_test.py -p 2000 --log carla_client.log & echo $$! > carla_client.pid
|
||||
|
||||
kill_test_clients:
|
||||
@echo "Kill echo_client.py"
|
||||
@echo "Kill echo client"
|
||||
@kill `cat echo_client.pid` && rm echo_client.pid
|
||||
@echo "Kill carla_client.py"
|
||||
@echo "Kill carla client"
|
||||
@kill `cat carla_client.pid` && rm carla_client.pid
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
set PROTOBUF_SRC_DIR=Proto
|
||||
set PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server
|
||||
set PROTOBUF_PY_OUT_DIR=PythonClient/lib
|
||||
set PROTOBUF_PY_OUT_DIR=PythonClient/carla
|
||||
set PROTO_BASENAME=carla_server
|
||||
|
||||
if "%1" == "--clean" (
|
||||
|
|
|
@ -7,7 +7,7 @@ pushd "$SCRIPT_DIR" >/dev/null
|
|||
|
||||
PROTOBUF_SRC_DIR=Proto
|
||||
PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server
|
||||
PROTOBUF_PY_OUT_DIR=PythonClient/lib
|
||||
PROTOBUF_PY_OUT_DIR=PythonClient/carla
|
||||
PROTO_BASENAME=carla_server
|
||||
|
||||
if [ "$1" == "--clean" ]; then
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
*.py[cod]
|
||||
*_pb2.py
|
||||
__pycache__
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
"""CARLA Client."""
|
||||
|
||||
from . import tcp
|
||||
|
||||
from . import carla_server_pb2 as carla_protocol
|
||||
|
||||
|
||||
class CarlaClient(object):
|
||||
def __init__(self, host, world_port, timeout=15):
|
||||
self._world_client = tcp.TCPClient(host, world_port, timeout)
|
||||
self._stream_client = tcp.TCPClient(host, world_port + 1, timeout)
|
||||
self._control_client = tcp.TCPClient(host, world_port + 2, timeout)
|
||||
|
||||
def connect(self):
|
||||
self._world_client.connect()
|
||||
|
||||
def disconnect(self):
|
||||
self._control_client.disconnect()
|
||||
self._stream_client.disconnect()
|
||||
self._world_client.disconnect()
|
||||
|
||||
def request_new_episode(self, carla_settings):
|
||||
"""Request a new episode. carla_settings object must be convertible to
|
||||
a str holding a CarlaSettings.ini.
|
||||
|
||||
Returns a protobuf object holding the scene description.
|
||||
"""
|
||||
# Disconnect agent clients.
|
||||
self._stream_client.disconnect()
|
||||
self._control_client.disconnect()
|
||||
# Send new episode request.
|
||||
pb_message = carla_protocol.RequestNewEpisode()
|
||||
pb_message.ini_file = str(carla_settings)
|
||||
self._world_client.write(pb_message.SerializeToString())
|
||||
# Read scene description.
|
||||
data = self._world_client.read()
|
||||
if not data:
|
||||
raise RuntimeError('failed to read data from server')
|
||||
pb_message = carla_protocol.SceneDescription()
|
||||
pb_message.ParseFromString(data)
|
||||
if len(pb_message.player_start_spots) < 1:
|
||||
raise RuntimeError("received 0 player start spots")
|
||||
return pb_message
|
||||
|
||||
def start_episode(self, player_start_index):
|
||||
"""Start the new episode at the player start given by the
|
||||
player_start_index. The list of player starts is retrieved by
|
||||
request_new_episode().
|
||||
|
||||
This function waits until the server answers with an EpisodeReady.
|
||||
"""
|
||||
pb_message = carla_protocol.EpisodeStart()
|
||||
pb_message.player_start_spot_index = player_start_index
|
||||
self._world_client.write(pb_message.SerializeToString())
|
||||
# Wait for EpisodeReady.
|
||||
data = self._world_client.read()
|
||||
if not data:
|
||||
raise RuntimeError('failed to read data from server')
|
||||
pb_message = carla_protocol.EpisodeReady()
|
||||
pb_message.ParseFromString(data)
|
||||
if not pb_message.ready:
|
||||
raise RuntimeError('cannot start episode: server failed to start episode')
|
||||
# We can start the agent clients now.
|
||||
self._stream_client.connect()
|
||||
self._control_client.connect()
|
||||
|
||||
def read_measurements(self):
|
||||
"""Read measuremnts of current frame. The episode must be started.
|
||||
Return the protobuf object with the measurements followed by the raw
|
||||
data with the images.
|
||||
"""
|
||||
# Read measurements.
|
||||
data = self._stream_client.read()
|
||||
if not data:
|
||||
raise RuntimeError('failed to read data from server')
|
||||
pb_message = carla_protocol.Measurements()
|
||||
pb_message.ParseFromString(data)
|
||||
# Read images.
|
||||
images_raw_data = self._stream_client.read()
|
||||
return pb_message, images_raw_data
|
||||
|
||||
def send_control(self, **kwargs):
|
||||
"""Send vehicle control for the current frame."""
|
||||
pb_message = carla_protocol.Control()
|
||||
pb_message.steer = kwargs.get('steer', 0.0)
|
||||
pb_message.throttle = kwargs.get('throttle', 0.0)
|
||||
pb_message.brake = kwargs.get('brake', 0.0)
|
||||
pb_message.hand_brake = kwargs.get('hand_brake', False)
|
||||
pb_message.reverse = kwargs.get('reverse', False)
|
||||
pb_message.autopilot = kwargs.get('autopilot', False)
|
||||
self._control_client.write(pb_message.SerializeToString())
|
|
@ -1,11 +1,9 @@
|
|||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
|
||||
"""CARLA Settings"""
|
||||
|
||||
|
||||
import ConfigParser
|
||||
import StringIO
|
||||
import configparser
|
||||
import io
|
||||
import random
|
||||
|
||||
|
||||
|
@ -13,6 +11,7 @@ MAX_NUMBER_OF_WEATHER_IDS = 14
|
|||
|
||||
|
||||
class Camera(object):
|
||||
"""Camera description. To be added to CarlaSettings."""
|
||||
def __init__(self, name, **kwargs):
|
||||
self.CameraName = name
|
||||
self.PostProcessing = 'SceneFinal'
|
||||
|
@ -28,7 +27,7 @@ class Camera(object):
|
|||
self.set(**kwargs)
|
||||
|
||||
def set(self, **kwargs):
|
||||
for key, value in kwargs.iteritems():
|
||||
for key, value in kwargs.items():
|
||||
if not hasattr(self, key):
|
||||
raise ValueError('CarlaSettings.Camera: no key named %r' % key)
|
||||
setattr(self, key, value)
|
||||
|
@ -49,6 +48,7 @@ class Camera(object):
|
|||
|
||||
|
||||
class CarlaSettings(object):
|
||||
"""CARLA settings object. Convertible to str as CarlaSettings.ini."""
|
||||
def __init__(self, **kwargs):
|
||||
# [CARLA/Server]
|
||||
self.SynchronousMode = False
|
||||
|
@ -57,14 +57,15 @@ class CarlaSettings(object):
|
|||
self.PlayerVehicle = None
|
||||
self.NumberOfVehicles = 20
|
||||
self.NumberOfPedestrians = 30
|
||||
self.WeatherId = random.randint(-1, MAX_NUMBER_OF_WEATHER_IDS)
|
||||
self.WeatherId = -1
|
||||
self.SeedVehicles = None
|
||||
self.SeedPedestrians = None
|
||||
self.randomize_weather()
|
||||
self.set(**kwargs)
|
||||
self._cameras = []
|
||||
|
||||
def set(self, **kwargs):
|
||||
for key, value in kwargs.iteritems():
|
||||
for key, value in kwargs.items():
|
||||
if not hasattr(self, key):
|
||||
raise ValueError('CarlaSettings: no key named %r' % key)
|
||||
setattr(self, key, value)
|
||||
|
@ -74,9 +75,18 @@ class CarlaSettings(object):
|
|||
return 0
|
||||
return self.NumberOfVehicles + self.NumberOfPedestrians
|
||||
|
||||
def get_images_byte_size(self):
|
||||
size = 0
|
||||
for camera in self._cameras:
|
||||
size += 3 + int(camera.ImageSizeX) * int(camera.ImageSizeY)
|
||||
return 4 * size
|
||||
|
||||
def randomize_seeds(self):
|
||||
self.SeedVehicles = random.getrandbits(64)
|
||||
self.SeedPedestrians = random.getrandbits(64)
|
||||
self.SeedVehicles = random.getrandbits(32)
|
||||
self.SeedPedestrians = random.getrandbits(32)
|
||||
|
||||
def randomize_weather(self):
|
||||
self.WeatherId = random.randint(-1, MAX_NUMBER_OF_WEATHER_IDS)
|
||||
|
||||
def add_camera(self, camera):
|
||||
if not isinstance(camera, Camera):
|
||||
|
@ -84,7 +94,7 @@ class CarlaSettings(object):
|
|||
self._cameras.append(camera)
|
||||
|
||||
def __str__(self):
|
||||
ini = ConfigParser.RawConfigParser()
|
||||
ini = configparser.ConfigParser()
|
||||
ini.optionxform=str
|
||||
S_SERVER = 'CARLA/Server'
|
||||
S_LEVEL = 'CARLA/LevelSettings'
|
||||
|
@ -95,7 +105,7 @@ class CarlaSettings(object):
|
|||
if hasattr(obj, key) and getattr(obj, key) is not None:
|
||||
if not ini.has_section(section):
|
||||
ini.add_section(section)
|
||||
ini.set(section, key, getattr(obj, key))
|
||||
ini.set(section, key, str(getattr(obj, key)))
|
||||
|
||||
add_section(S_SERVER, self, [
|
||||
'SynchronousMode',
|
||||
|
@ -123,20 +133,6 @@ class CarlaSettings(object):
|
|||
'CameraRotationRoll',
|
||||
'CameraRotationYaw'])
|
||||
|
||||
text = StringIO.StringIO()
|
||||
text = io.StringIO()
|
||||
ini.write(text)
|
||||
return text.getvalue().replace(' = ', '=')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
settings = CarlaSettings(NumberOfVehicles=200, SendNonPlayerAgentsInfo=True)
|
||||
settings.randomize_seeds()
|
||||
camera1 = Camera('Camera1')
|
||||
camera1.set_image_size(1920, 1080)
|
||||
camera1.set_position(20, 0, 100)
|
||||
settings.add_camera(camera1)
|
||||
camera2 = Camera('Camera2')
|
||||
camera2.set(CameraFOV=120, PostProcessing='Depth')
|
||||
settings.add_camera(camera2)
|
||||
print(settings)
|
|
@ -1,13 +1,11 @@
|
|||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
"""Basic TCP client."""
|
||||
|
||||
import logging
|
||||
import socket
|
||||
import struct
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from util import to_hex_str
|
||||
|
||||
|
||||
class TCPClient(object):
|
||||
def __init__(self, host, port, timeout):
|
||||
|
@ -23,29 +21,27 @@ class TCPClient(object):
|
|||
|
||||
def disconnect(self):
|
||||
if self._socket is not None:
|
||||
self._log('disconnecting...')
|
||||
self._socket.close()
|
||||
|
||||
def write(self, message):
|
||||
header = struct.pack('<L', len(message))
|
||||
# self._log('sending (%d bytes) = {%s %s}', len(message), to_hex_str(header), to_hex_str(message))
|
||||
self._socket.sendall(header + message)
|
||||
|
||||
def read(self):
|
||||
header = self._read_n(4)
|
||||
if header == '':
|
||||
return ''
|
||||
if not header:
|
||||
raise RuntimeError('%s:%s connection closed' % (self._host, self._port))
|
||||
length = struct.unpack('<L', header)[0]
|
||||
# self._log('received header: %s (%d)', to_hex_str(header), length)
|
||||
data = self._read_n(length)
|
||||
# self._log('received data: %s', to_hex_str(data))
|
||||
return data
|
||||
|
||||
def _read_n(self, length):
|
||||
buf = ''
|
||||
buf = bytes()
|
||||
while length > 0:
|
||||
data = self._socket.recv(length)
|
||||
if data == '':
|
||||
raise RuntimeError('connection closed')
|
||||
if not data:
|
||||
raise RuntimeError('%s:%s connection closed' % (self._host, self._port))
|
||||
buf += data
|
||||
length -= len(data)
|
||||
return buf
|
|
@ -10,8 +10,8 @@ def to_hex_str(header):
|
|||
|
||||
|
||||
@contextmanager
|
||||
def make_client(client_type, *args, **kwargs):
|
||||
"""Context manager to create a client."""
|
||||
def make_connection(client_type, *args, **kwargs):
|
||||
"""Context manager to create and connect a networking object."""
|
||||
client = None
|
||||
try:
|
||||
client = client_type(*args, **kwargs)
|
|
@ -1,65 +0,0 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
|
||||
"""Basic CARLA client for testing."""
|
||||
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
|
||||
|
||||
from lib.carla_util import TestCarlaClientBase
|
||||
from lib.util import make_client
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description=__doc__)
|
||||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
help='print debug information to console instead of log file')
|
||||
argparser.add_argument(
|
||||
'-d', '--debug',
|
||||
action='store_true',
|
||||
help='print debug extra information to log')
|
||||
argparser.add_argument(
|
||||
'--host',
|
||||
metavar='H',
|
||||
default='127.0.0.1',
|
||||
help='IP of the host server')
|
||||
argparser.add_argument(
|
||||
'-p', '--port',
|
||||
metavar='P',
|
||||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
logging_config = {
|
||||
'format': 'carla_client:%(levelname)s: %(message)s',
|
||||
'level': logging.DEBUG if args.debug else logging.INFO
|
||||
}
|
||||
if not args.verbose:
|
||||
logging_config['filename'] = 'carla_client.log'
|
||||
logging_config['filemode'] = 'w+'
|
||||
logging.basicConfig(**logging_config)
|
||||
|
||||
while True:
|
||||
try:
|
||||
with make_client(TestCarlaClientBase, args) as client:
|
||||
while True:
|
||||
client.start_episode()
|
||||
client.loop_on_agent_client(iterations=10)
|
||||
|
||||
except Exception as exception:
|
||||
logging.error('exception: %s', exception)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
main()
|
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
"""Basic CARLA client."""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import random
|
||||
import time
|
||||
|
||||
import carla
|
||||
|
||||
from carla.client import CarlaClient
|
||||
from carla.settings import CarlaSettings, Camera
|
||||
from carla.tcp import TCPClient
|
||||
from carla.util import make_connection
|
||||
|
||||
|
||||
def run_carla_server(host, port):
|
||||
with make_connection(CarlaClient, host, port, timeout=15) as client:
|
||||
logging.info('CarlaClient connected')
|
||||
frames_per_episode = 300
|
||||
while True:
|
||||
settings = CarlaSettings()
|
||||
settings.set(SendNonPlayerAgentsInfo=True)
|
||||
settings.randomize_seeds()
|
||||
settings.add_camera(Camera('DefaultCamera'))
|
||||
|
||||
logging.debug('sending CarlaSettings:\n%s', settings)
|
||||
logging.info('new episode requested')
|
||||
|
||||
scene = client.request_new_episode(settings)
|
||||
|
||||
number_of_player_starts = len(scene.player_start_spots)
|
||||
player_start = random.randint(0, max(0, number_of_player_starts - 1))
|
||||
logging.info(
|
||||
'start episode at %d/%d player start (%d frames)',
|
||||
player_start,
|
||||
number_of_player_starts,
|
||||
frames_per_episode)
|
||||
|
||||
client.start_episode(player_start)
|
||||
|
||||
autopilot = (random.random() < 0.5)
|
||||
reverse = (random.random() < 0.2)
|
||||
|
||||
for _ in range(0, frames_per_episode):
|
||||
logging.debug('reading measurements...')
|
||||
measurements, images = client.read_measurements()
|
||||
|
||||
logging.debug('received data of %d agents', len(measurements.non_player_agents))
|
||||
logging.debug('received %d bytes of images', len(images))
|
||||
|
||||
logging.debug('sending control...')
|
||||
client.send_control(
|
||||
steer=random.uniform(-1.0, 1.0),
|
||||
throttle=0.3,
|
||||
reverse=reverse,
|
||||
autopilot=autopilot)
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description=__doc__)
|
||||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
dest='debug',
|
||||
help='print debug information')
|
||||
argparser.add_argument(
|
||||
'--log',
|
||||
metavar='LOG_FILE',
|
||||
default=None,
|
||||
help='print output to file')
|
||||
argparser.add_argument(
|
||||
'--host',
|
||||
metavar='H',
|
||||
default='127.0.0.1',
|
||||
help='IP of the host server (default: 127.0.0.1)')
|
||||
argparser.add_argument(
|
||||
'-p', '--port',
|
||||
metavar='P',
|
||||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to (default: 2000)')
|
||||
argparser.add_argument(
|
||||
'--echo',
|
||||
action='store_true',
|
||||
help='start a client that just echoes what the server sends')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
name = 'echo_client: ' if args.echo else 'carla_client: '
|
||||
logging_config = {
|
||||
'format': name + '%(levelname)s: %(message)s',
|
||||
'level': logging.DEBUG if args.debug else logging.INFO
|
||||
}
|
||||
if args.log:
|
||||
logging_config['filename'] = args.log
|
||||
logging_config['filemode'] = 'w+'
|
||||
logging.basicConfig(**logging_config)
|
||||
|
||||
logging.info('listening to server %s:%s', args.host, args.port)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
||||
if args.echo:
|
||||
|
||||
with make_connection(TCPClient, args.host, args.port, timeout=15) as client:
|
||||
while True:
|
||||
logging.info('reading...')
|
||||
data = client.read()
|
||||
if not data:
|
||||
raise RuntimeError('failed to read data from server')
|
||||
logging.info('writing...')
|
||||
client.write(data)
|
||||
|
||||
else:
|
||||
|
||||
run_carla_server(args.host, args.port)
|
||||
|
||||
except Exception as exception:
|
||||
logging.error('exception: %s', exception)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print('\nCancelled by user. Bye!')
|
|
@ -1,70 +0,0 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
|
||||
"""Implements TCP client that connects, reads, and sends back what it receives."""
|
||||
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
|
||||
from lib.tcp_client import TCPClient
|
||||
from lib.util import make_client
|
||||
|
||||
|
||||
def launch_echo_client(host, port):
|
||||
while True:
|
||||
try:
|
||||
logging.debug('connecting...')
|
||||
with make_client(TCPClient, host, port, timeout=20) as client:
|
||||
while True:
|
||||
logging.debug('reading...')
|
||||
data = client.read()
|
||||
if data == '':
|
||||
logging.debug('no data received!')
|
||||
break
|
||||
# logging.info('received: %s', data)
|
||||
logging.debug('writing...')
|
||||
client.write(data)
|
||||
except Exception as e:
|
||||
logging.error('exception: %s', e)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description=__doc__)
|
||||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
help='print debug information to console instead of log file')
|
||||
argparser.add_argument(
|
||||
'--host',
|
||||
metavar='H',
|
||||
default='127.0.0.1',
|
||||
help='IP of the host server')
|
||||
argparser.add_argument(
|
||||
'-p', '--port',
|
||||
metavar='P',
|
||||
default=4000,
|
||||
type=int,
|
||||
help='TCP port to listen to')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
logging_config = {
|
||||
'format': 'echo_client:%(levelname)s: %(message)s',
|
||||
'level': logging.DEBUG
|
||||
}
|
||||
if not args.verbose:
|
||||
logging_config['filename'] = 'echo_client.log'
|
||||
logging_config['filemode'] = 'w+'
|
||||
logging.basicConfig(**logging_config)
|
||||
|
||||
launch_echo_client(args.host, args.port)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
main()
|
|
@ -1,81 +0,0 @@
|
|||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
|
||||
"""CARLA Client."""
|
||||
|
||||
|
||||
from tcp_client import TCPClient
|
||||
|
||||
import carla_server_pb2 as carla_protocol
|
||||
|
||||
|
||||
class CarlaClient(object):
|
||||
def __init__(self, host, world_port, timeout):
|
||||
self._world_client = TCPClient(host, world_port, timeout)
|
||||
self._stream_client = TCPClient(host, world_port + 1, timeout)
|
||||
self._control_client = TCPClient(host, world_port + 2, timeout)
|
||||
|
||||
def connect_world_client(self):
|
||||
self._world_client.connect()
|
||||
|
||||
def disconnect_all(self):
|
||||
self.disconnect_agent_client()
|
||||
self._world_client.disconnect()
|
||||
|
||||
def connect_agent_client(self):
|
||||
self._stream_client.connect()
|
||||
self._control_client.connect()
|
||||
|
||||
def disconnect_agent_client(self):
|
||||
self._stream_client.disconnect()
|
||||
self._control_client.disconnect()
|
||||
|
||||
def write_request_new_episode(self, ini_file):
|
||||
pb_message = carla_protocol.RequestNewEpisode()
|
||||
pb_message.ini_file = ini_file
|
||||
self._world_client.write(pb_message.SerializeToString())
|
||||
|
||||
def read_scene_description(self):
|
||||
data = self._world_client.read()
|
||||
if not data:
|
||||
return None
|
||||
pb_message = carla_protocol.SceneDescription()
|
||||
pb_message.ParseFromString(data)
|
||||
return pb_message
|
||||
|
||||
def write_episode_start(self, player_start_location_index):
|
||||
pb_message = carla_protocol.EpisodeStart()
|
||||
pb_message.player_start_spot_index = player_start_location_index
|
||||
self._world_client.write(pb_message.SerializeToString())
|
||||
|
||||
def read_episode_ready(self):
|
||||
data = self._world_client.read()
|
||||
if not data:
|
||||
return None
|
||||
pb_message = carla_protocol.EpisodeReady()
|
||||
pb_message.ParseFromString(data)
|
||||
return pb_message
|
||||
|
||||
def read_measurements(self):
|
||||
data = self._stream_client.read()
|
||||
if not data:
|
||||
return None
|
||||
pb_message = carla_protocol.Measurements()
|
||||
pb_message.ParseFromString(data)
|
||||
return pb_message
|
||||
|
||||
def read_images(self):
|
||||
data = self._stream_client.read()
|
||||
if not data:
|
||||
return None
|
||||
return data
|
||||
|
||||
def write_control(self, **kwargs):
|
||||
pb_message = carla_protocol.Control()
|
||||
pb_message.steer = kwargs.get('steer', 0.0)
|
||||
pb_message.throttle = kwargs.get('throttle', 0.0)
|
||||
pb_message.brake = kwargs.get('brake', 0.0)
|
||||
pb_message.hand_brake = kwargs.get('hand_brake', False)
|
||||
pb_message.reverse = kwargs.get('reverse', False)
|
||||
pb_message.autopilot = kwargs.get('autopilot', False)
|
||||
self._control_client.write(pb_message.SerializeToString())
|
|
@ -1,162 +0,0 @@
|
|||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
|
||||
"""Test suite for CARLA Client."""
|
||||
|
||||
|
||||
import logging
|
||||
import random
|
||||
|
||||
|
||||
from carla_client import CarlaClient
|
||||
|
||||
|
||||
MAX_NUMBER_OF_WEATHER_IDS = 14
|
||||
|
||||
|
||||
def _get_settings_dict(**kwargs):
|
||||
return {
|
||||
'SynchronousMode': kwargs.get('SynchronousMode', False),
|
||||
'SendNonPlayerAgentsInfo': kwargs.get('SendNonPlayerAgentsInfo', False),
|
||||
'NumberOfVehicles': max(0, int(kwargs.get('NumberOfVehicles', 20))),
|
||||
'NumberOfPedestrians': max(0, int(kwargs.get('NumberOfPedestrians', 30))),
|
||||
'WeatherId': int(kwargs.get('WeatherId', random.randint(-1, MAX_NUMBER_OF_WEATHER_IDS))),
|
||||
}
|
||||
|
||||
|
||||
def get_carla_settings(**kwargs):
|
||||
"""Create a CarlaSettings.ini based in the arguments provided"""
|
||||
return """
|
||||
[CARLA/Server]
|
||||
ServerTimeOut=10000
|
||||
SynchronousMode={SynchronousMode}
|
||||
SendNonPlayerAgentsInfo={SendNonPlayerAgentsInfo}
|
||||
|
||||
[CARLA/LevelSettings]
|
||||
PlayerVehicle=
|
||||
NumberOfVehicles={NumberOfVehicles}
|
||||
NumberOfPedestrians={NumberOfPedestrians}
|
||||
WeatherId={WeatherId}
|
||||
SeedVehicles=123456789
|
||||
SeedPedestrians=123456789
|
||||
|
||||
[CARLA/SceneCapture]
|
||||
Cameras=MyCamera
|
||||
|
||||
[CARLA/SceneCapture/MyCamera]
|
||||
PostProcessing=SceneFinal
|
||||
ImageSizeX=800
|
||||
ImageSizeY=600
|
||||
CameraFOV=90
|
||||
CameraPositionX=15
|
||||
CameraPositionY=0
|
||||
CameraPositionZ=123
|
||||
CameraRotationPitch=8
|
||||
CameraRotationRoll=0
|
||||
CameraRotationYaw=0
|
||||
""".format(**_get_settings_dict(**kwargs))
|
||||
|
||||
|
||||
def get_number_of_agents(**kwargs):
|
||||
settings = _get_settings_dict(**kwargs)
|
||||
if not settings['SendNonPlayerAgentsInfo']:
|
||||
return 0
|
||||
else:
|
||||
return settings['NumberOfVehicles'] + settings['NumberOfPedestrians']
|
||||
|
||||
|
||||
class TestCarlaClientBase(object):
|
||||
def __init__(self, args):
|
||||
"""Create a TestCarlaClientBase and initialize the CarlaClient"""
|
||||
self.args = args
|
||||
self.number_of_agents = 0
|
||||
logging.info('connecting carla client to %s:%d', self.args.host, self.args.port)
|
||||
self.client = CarlaClient(self.args.host, self.args.port, timeout=15)
|
||||
|
||||
def connect(self):
|
||||
self.client.connect_world_client()
|
||||
|
||||
def disconnect(self):
|
||||
if self.client is not None:
|
||||
self.client.disconnect_all()
|
||||
|
||||
def request_new_episode(self, **kwargs):
|
||||
"""Create and send a CarlaSettigns.ini"""
|
||||
self.client.disconnect_agent_client()
|
||||
logging.info('requesting new episode')
|
||||
carla_settings = get_carla_settings(**kwargs)
|
||||
self.number_of_agents = get_number_of_agents(**kwargs)
|
||||
logging.debug(carla_settings)
|
||||
self.client.write_request_new_episode(carla_settings)
|
||||
|
||||
def start_episode(self, **kwargs):
|
||||
"""Start a default episode and launch the agent client"""
|
||||
self.request_new_episode(**kwargs)
|
||||
logging.debug('waiting for the scene description')
|
||||
data = self.client.read_scene_description()
|
||||
if data is None:
|
||||
raise RuntimeError("received empty scene description")
|
||||
number_of_start_spots = len(data.player_start_spots)
|
||||
if number_of_start_spots == 0:
|
||||
raise RuntimeError("received 0 player start spots")
|
||||
logging.debug('received %d player start locations', number_of_start_spots)
|
||||
if self.args.debug:
|
||||
for spot in data.player_start_spots:
|
||||
logging.debug(spot)
|
||||
|
||||
logging.debug('sending a random episode start')
|
||||
self.client.write_episode_start(random.randint(0, max(0, number_of_start_spots - 1)))
|
||||
|
||||
logging.debug('waiting for episode to be ready')
|
||||
data = self.client.read_episode_ready()
|
||||
if not data.ready:
|
||||
raise RuntimeError('received episode not ready')
|
||||
|
||||
logging.info('connecting secondary clients')
|
||||
self.client.connect_agent_client()
|
||||
|
||||
def loop_on_agent_client(self, iterations=100, autopilot=None, control=None):
|
||||
"""
|
||||
Loop on receive measurements and send control. If autopilot or control
|
||||
are None they will be chosen at random.
|
||||
"""
|
||||
if control is not None:
|
||||
autopilot = False
|
||||
if autopilot is None:
|
||||
autopilot = random.choice([True, False])
|
||||
|
||||
reverse = (random.random() < 0.2)
|
||||
|
||||
logging.info('running episode with %d iterations', iterations)
|
||||
|
||||
for x in xrange(0, iterations):
|
||||
logging.debug('waiting for measurements')
|
||||
data = self.client.read_measurements()
|
||||
if not data:
|
||||
raise RuntimeError('received empty measurements')
|
||||
if not data.IsInitialized():
|
||||
raise RuntimeError('received non-initialized measurements')
|
||||
else:
|
||||
logging.debug('received valid measurements')
|
||||
number_of_agents = len(data.non_player_agents)
|
||||
logging.debug('received data of %d agents', number_of_agents)
|
||||
if number_of_agents > self.number_of_agents or number_of_agents + 10 < self.number_of_agents:
|
||||
raise RuntimeError('received data for %d agents, but %d was requested' % (number_of_agents, self.number_of_agents))
|
||||
if self.args.debug:
|
||||
for agent in data.non_player_agents:
|
||||
logging.debug(agent)
|
||||
logging.debug('waiting for images')
|
||||
data = self.client.read_images()
|
||||
logging.debug('received %d bytes of images', len(data) if data is not None else 0)
|
||||
|
||||
logging.debug('sending control')
|
||||
if autopilot:
|
||||
self.client.write_control(autopilot=True)
|
||||
else:
|
||||
if control is None:
|
||||
self.client.write_control(
|
||||
steer=random.uniform(-1.0, 1.0),
|
||||
throttle=0.3,
|
||||
reverse=reverse)
|
||||
else:
|
||||
self.client.write_control(**control)
|
|
@ -1,40 +1,99 @@
|
|||
import test
|
||||
|
||||
import logging
|
||||
import random
|
||||
|
||||
from lib.carla_util import TestCarlaClientBase
|
||||
from lib.util import make_client
|
||||
import carla
|
||||
|
||||
from carla.client import CarlaClient
|
||||
from carla.settings import CarlaSettings, Camera
|
||||
from carla.util import make_connection
|
||||
|
||||
|
||||
class UseCase(test.CarlaServerTest):
|
||||
class _BasicTestBase(test.CarlaServerTest):
|
||||
def run_carla_client(self, carla_settings, number_of_episodes, number_of_frames):
|
||||
with make_connection(CarlaClient, self.args.host, self.args.port, timeout=15) as client:
|
||||
logging.info('CarlaClient connected, running %d episodes', number_of_episodes)
|
||||
for _ in range(0, number_of_episodes):
|
||||
carla_settings.randomize_seeds()
|
||||
carla_settings.randomize_weather()
|
||||
logging.debug('sending CarlaSettings:\n%s', carla_settings)
|
||||
logging.info('new episode requested')
|
||||
scene = client.request_new_episode(carla_settings)
|
||||
number_of_player_starts = len(scene.player_start_spots)
|
||||
player_start = random.randint(0, max(0, number_of_player_starts - 1))
|
||||
logging.info(
|
||||
'start episode at %d/%d player start (%d frames)',
|
||||
player_start,
|
||||
number_of_player_starts,
|
||||
number_of_frames)
|
||||
client.start_episode(player_start)
|
||||
autopilot = (random.random() < 0.5)
|
||||
reverse = (random.random() < 0.2)
|
||||
for _ in range(0, number_of_frames):
|
||||
logging.debug('reading measurements...')
|
||||
measurements, images = client.read_measurements()
|
||||
number_of_agents = len(measurements.non_player_agents)
|
||||
expected_number_of_agents = carla_settings.get_number_of_agents()
|
||||
logging.debug('received data of %d/%d agents', number_of_agents, expected_number_of_agents)
|
||||
logging.debug('received %d bytes of images', len(images))
|
||||
if number_of_agents > expected_number_of_agents or number_of_agents + 10 < expected_number_of_agents:
|
||||
raise RuntimeError('received data for %d agents, but %d was requested' % (number_of_agents, expected_number_of_agents))
|
||||
if len(images) != carla_settings.get_images_byte_size():
|
||||
raise RuntimeError('received %d bytes of images, expected %d' % (len(images), carla_settings.get_images_byte_size()))
|
||||
logging.debug('sending control...')
|
||||
client.send_control(
|
||||
steer=random.uniform(-1.0, 1.0),
|
||||
throttle=0.3,
|
||||
reverse=reverse,
|
||||
autopilot=autopilot)
|
||||
|
||||
|
||||
class UseCase(_BasicTestBase):
|
||||
def run(self):
|
||||
with make_client(TestCarlaClientBase, self.args) as client:
|
||||
for x in xrange(0, 5):
|
||||
client.start_episode()
|
||||
client.loop_on_agent_client(iterations=200)
|
||||
settings = CarlaSettings()
|
||||
settings.add_camera(Camera('DefaultCamera'))
|
||||
self.run_carla_client(settings, 5, 200)
|
||||
|
||||
|
||||
class SynchronousMode(test.CarlaServerTest):
|
||||
class NoCamera(_BasicTestBase):
|
||||
def run(self):
|
||||
with make_client(TestCarlaClientBase, self.args) as client:
|
||||
for x in xrange(0, 3):
|
||||
client.start_episode(SynchronousMode=True)
|
||||
client.loop_on_agent_client(iterations=200)
|
||||
settings = CarlaSettings()
|
||||
self.run_carla_client(settings, 3, 200)
|
||||
|
||||
|
||||
class GetAgentsInfo(test.CarlaServerTest):
|
||||
class TwoCameras(_BasicTestBase):
|
||||
def run(self):
|
||||
with make_client(TestCarlaClientBase, self.args) as client:
|
||||
for x in xrange(0, 3):
|
||||
client.start_episode(
|
||||
SynchronousMode=True,
|
||||
SendNonPlayerAgentsInfo=True,
|
||||
NumberOfVehicles=60,
|
||||
NumberOfPedestrians=90)
|
||||
client.loop_on_agent_client(iterations=100)
|
||||
settings = CarlaSettings()
|
||||
settings.add_camera(Camera('DefaultCamera'))
|
||||
camera2 = Camera('Camera2')
|
||||
camera2.set(PostProcessing='Depth', CameraFOV=120)
|
||||
camera2.set_image_size(1924, 1028)
|
||||
settings.add_camera(camera2)
|
||||
self.run_carla_client(settings, 3, 100)
|
||||
|
||||
|
||||
class LongEpisode(test.CarlaServerTest):
|
||||
class SynchronousMode(_BasicTestBase):
|
||||
def run(self):
|
||||
with make_client(TestCarlaClientBase, self.args) as client:
|
||||
client.start_episode()
|
||||
client.loop_on_agent_client(iterations=2000)
|
||||
settings = CarlaSettings(SynchronousMode=True)
|
||||
settings.add_camera(Camera('DefaultCamera'))
|
||||
self.run_carla_client(settings, 3, 200)
|
||||
|
||||
|
||||
class GetAgentsInfo(_BasicTestBase):
|
||||
def run(self):
|
||||
settings = CarlaSettings()
|
||||
settings.set(
|
||||
SynchronousMode=True,
|
||||
SendNonPlayerAgentsInfo=True,
|
||||
NumberOfVehicles=60,
|
||||
NumberOfPedestrians=90)
|
||||
settings.add_camera(Camera('DefaultCamera'))
|
||||
self.run_carla_client(settings, 3, 100)
|
||||
|
||||
|
||||
class LongEpisode(_BasicTestBase):
|
||||
def run(self):
|
||||
settings = CarlaSettings()
|
||||
settings.add_camera(Camera('DefaultCamera'))
|
||||
self.run_carla_client(settings, 1, 2000)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
|
||||
"""Test suite for testing CARLAUE4."""
|
||||
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import imp
|
||||
|
@ -16,15 +14,14 @@ import random
|
|||
import time
|
||||
|
||||
|
||||
from lib.carla_util import TestCarlaClientBase
|
||||
from lib.util import StopWatch
|
||||
from lib.util import make_client
|
||||
import carla
|
||||
|
||||
from carla.util import StopWatch
|
||||
|
||||
from test import CarlaServerTest
|
||||
|
||||
# Modified by command-line args.
|
||||
VERBOSE = False
|
||||
LOGGING_TO_FILE = False
|
||||
|
||||
# Output.
|
||||
GREEN = '\x1b[0;32m%s\x1b[0m'
|
||||
|
@ -43,7 +40,7 @@ FAILED = RED % '[ FAILED ]'
|
|||
def log_test(prep, message, *args):
|
||||
message = prep + ' ' + message % args
|
||||
print(message)
|
||||
if not VERBOSE:
|
||||
if LOGGING_TO_FILE:
|
||||
logging.info(message)
|
||||
|
||||
|
||||
|
@ -72,14 +69,15 @@ def iterate_tests():
|
|||
folder = os.path.join(os.path.dirname(__file__), 'test')
|
||||
modules = glob.glob(os.path.join(folder, "*.py"))
|
||||
|
||||
for module_name in set(strip_ext(m) for m in modules if not m.endswith('__init__.py')):
|
||||
for module_name in set(strip_ext(m) for m in modules if not m.startswith('_')):
|
||||
logging.debug('parsing module %r', module_name)
|
||||
try:
|
||||
module_info = imp.find_module(module_name, [folder])
|
||||
# This do a reload if already imported.
|
||||
module = imp.load_module(module_name, *module_info)
|
||||
for name, declaration in inspect.getmembers(module, is_valid):
|
||||
yield TestProxy(name, declaration, module_name)
|
||||
if not name.startswith('_'):
|
||||
yield TestProxy(name, declaration, module_name)
|
||||
except Exception as exception:
|
||||
logging.error('failed to load module %r: %s', module_name, exception)
|
||||
finally:
|
||||
|
@ -135,41 +133,48 @@ def main():
|
|||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
help='print debug information to console instead of log file')
|
||||
dest='debug',
|
||||
help='print debug information')
|
||||
argparser.add_argument(
|
||||
'-d', '--debug',
|
||||
action='store_true',
|
||||
help='print debug extra information to log')
|
||||
'--log',
|
||||
metavar='LOG_FILE',
|
||||
default=None,
|
||||
help='print output to file')
|
||||
argparser.add_argument(
|
||||
'--host',
|
||||
metavar='H',
|
||||
default='127.0.0.1',
|
||||
help='IP of the host server (default 127.0.0.1)')
|
||||
help='IP of the host server (default: 127.0.0.1)')
|
||||
argparser.add_argument(
|
||||
'-p', '--port',
|
||||
metavar='P',
|
||||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to (default 2000)')
|
||||
help='TCP port to listen to (default: 2000)')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
global VERBOSE
|
||||
VERBOSE = args.verbose
|
||||
global LOGGING_TO_FILE
|
||||
LOGGING_TO_FILE = args.log is not None
|
||||
|
||||
logging_config = {
|
||||
'format': '%(levelname)s: %(message)s',
|
||||
'level': logging.DEBUG if args.debug else logging.INFO
|
||||
}
|
||||
if not args.verbose:
|
||||
logging_config['filename'] = 'test_suite.log'
|
||||
if args.log:
|
||||
logging_config['filename'] = args.log
|
||||
logging_config['filemode'] = 'w+'
|
||||
logging.basicConfig(**logging_config)
|
||||
|
||||
logging.info('listening to server %s:%s', args.host, args.port)
|
||||
|
||||
print('Running the CARLAUE4 test suite (looks like GTest but is not).')
|
||||
do_the_tests(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print('\nCancelled by user. Bye!')
|
||||
|
|
Loading…
Reference in New Issue