Add image parser to client

This commit is contained in:
nsubiron 2017-09-19 14:42:37 +02:00
parent 1d7e5ec769
commit 25a4f0411c
5 changed files with 84 additions and 18 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ Util/Install
*.log *.log
*.pid *.pid
_*

View File

@ -2,6 +2,10 @@
"""CARLA Client.""" """CARLA Client."""
import logging
import os
import struct
from . import tcp from . import tcp
from . import carla_server_pb2 as carla_protocol from . import carla_server_pb2 as carla_protocol
@ -79,7 +83,7 @@ class CarlaClient(object):
pb_message.ParseFromString(data) pb_message.ParseFromString(data)
# Read images. # Read images.
images_raw_data = self._stream_client.read() images_raw_data = self._stream_client.read()
return pb_message, images_raw_data return pb_message, CarlaImage.parse_raw_data(images_raw_data)
def send_control(self, **kwargs): def send_control(self, **kwargs):
"""Send vehicle control for the current frame.""" """Send vehicle control for the current frame."""
@ -91,3 +95,49 @@ class CarlaClient(object):
pb_message.reverse = kwargs.get('reverse', False) pb_message.reverse = kwargs.get('reverse', False)
pb_message.autopilot = kwargs.get('autopilot', False) pb_message.autopilot = kwargs.get('autopilot', False)
self._control_client.write(pb_message.SerializeToString()) self._control_client.write(pb_message.SerializeToString())
class CarlaImage(object):
@staticmethod
def parse_raw_data(raw_data):
getval = lambda index: struct.unpack('<L', raw_data[index*4:index*4+4])[0]
images = []
total_size = len(raw_data) / 4
index = 0
while index < total_size:
width = getval(index)
height = getval(index + 1)
image_type = getval(index + 2)
begin = index + 3
end = begin + width * height
images.append(CarlaImage(width, height, image_type, raw_data[begin*4:end*4]))
index = end
return images
def __init__(self, width, height, image_type, raw_data):
logging.debug('parsed image %dx%d type %d (%d bytes)', width, height, image_type, len(raw_data))
assert len(raw_data) == 4 * width * height
self.width = width
self.height = height
self.image_type = image_type
self.raw = raw_data
def save_to_disk(self, filename):
try:
from PIL import Image
except ImportError:
raise RuntimeError('cannot import PIL, make sure pillow package is installed')
image = Image.frombytes(
mode='RGBA',
size=(self.width, self.height),
data=self.raw,
decoder_name='raw')
b, g, r, a = image.split()
image = Image.merge("RGB", (r, g, b))
folder = os.path.dirname(filename)
if not os.path.isdir(folder):
os.makedirs(folder)
logging.debug('saving image to %r...', filename)
image.save(filename)

View File

@ -75,12 +75,6 @@ class CarlaSettings(object):
return 0 return 0
return self.NumberOfVehicles + self.NumberOfPedestrians 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): def randomize_seeds(self):
self.SeedVehicles = random.getrandbits(32) self.SeedVehicles = random.getrandbits(32)
self.SeedPedestrians = random.getrandbits(32) self.SeedPedestrians = random.getrandbits(32)

View File

@ -17,15 +17,20 @@ from carla.tcp import TCPClient
from carla.util import make_connection from carla.util import make_connection
def run_carla_server(host, port): def run_carla_server(args):
with make_connection(CarlaClient, host, port, timeout=15) as client: with make_connection(CarlaClient, args.host, args.port, timeout=15) as client:
logging.info('CarlaClient connected') logging.info('CarlaClient connected')
filename = '_images/episode_{:0>3d}/image_{:0>5d}.png'
frames_per_episode = 300 frames_per_episode = 300
episode = 0
while True: while True:
episode += 1
settings = CarlaSettings() settings = CarlaSettings()
settings.set(SendNonPlayerAgentsInfo=True) settings.set(SendNonPlayerAgentsInfo=True,SynchronousMode=args.synchronous)
settings.randomize_seeds() settings.randomize_seeds()
settings.add_camera(Camera('DefaultCamera')) camera = Camera('DefaultCamera')
camera.set_image_size(300, 200)
settings.add_camera(camera)
logging.debug('sending CarlaSettings:\n%s', settings) logging.debug('sending CarlaSettings:\n%s', settings)
logging.info('new episode requested') logging.info('new episode requested')
@ -45,12 +50,16 @@ def run_carla_server(host, port):
autopilot = (random.random() < 0.5) autopilot = (random.random() < 0.5)
reverse = (random.random() < 0.2) reverse = (random.random() < 0.2)
for _ in range(0, frames_per_episode): for frame in range(0, frames_per_episode):
logging.debug('reading measurements...') logging.debug('reading measurements...')
measurements, images = client.read_measurements() measurements, images = client.read_measurements()
logging.debug('received data of %d agents', len(measurements.non_player_agents)) logging.debug('received data of %d agents', len(measurements.non_player_agents))
logging.debug('received %d bytes of images', len(images)) assert len(images) == 1
assert (images[0].width, images[0].height) == (camera.ImageSizeX, camera.ImageSizeY)
if args.images_to_disk:
images[0].save_to_disk(filename.format(episode, frame))
logging.debug('sending control...') logging.debug('sending control...')
client.send_control( client.send_control(
@ -83,6 +92,14 @@ def main():
default=2000, default=2000,
type=int, type=int,
help='TCP port to listen to (default: 2000)') help='TCP port to listen to (default: 2000)')
argparser.add_argument(
'-s', '--synchronous',
action='store_true',
help='enable synchronous mode')
argparser.add_argument(
'-i', '--images-to-disk',
action='store_true',
help='save images to disk')
argparser.add_argument( argparser.add_argument(
'--echo', '--echo',
action='store_true', action='store_true',
@ -118,11 +135,15 @@ def main():
else: else:
run_carla_server(args.host, args.port) run_carla_server(args)
except Exception as exception: except AssertionError as assertion:
raise assertion
except ConnectionRefusedError as exception:
logging.error('exception: %s', exception) logging.error('exception: %s', exception)
time.sleep(1) time.sleep(1)
except Exception as exception:
raise exception
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -36,11 +36,11 @@ class _BasicTestBase(test.CarlaServerTest):
number_of_agents = len(measurements.non_player_agents) number_of_agents = len(measurements.non_player_agents)
expected_number_of_agents = carla_settings.get_number_of_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 data of %d/%d agents', number_of_agents, expected_number_of_agents)
logging.debug('received %d bytes of images', len(images)) logging.debug('received %d images', len(images))
if number_of_agents > expected_number_of_agents or number_of_agents + 10 < expected_number_of_agents: 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)) 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(): if len(images) != len(carla_settings._cameras):
raise RuntimeError('received %d bytes of images, expected %d' % (len(images), carla_settings.get_images_byte_size())) raise RuntimeError('received %d images, expected %d' % (len(images), len(carla_settings._cameras)))
logging.debug('sending control...') logging.debug('sending control...')
client.send_control( client.send_control(
steer=random.uniform(-1.0, 1.0), steer=random.uniform(-1.0, 1.0),