fixing codacy warnings

This commit is contained in:
Joel Moriana 2020-03-05 16:49:16 +01:00 committed by Marc Garcia Puig
parent d429a22978
commit 708f3ccfe3
7 changed files with 406 additions and 349 deletions

View File

@ -10,9 +10,17 @@
Script to integrate CARLA and SUMO simulations
"""
# ==============================================================================
# -- find carla module ---------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import argparse
import logging
import time
# ==================================================================================================
# -- find carla module -----------------------------------------------------------------------------
# ==================================================================================================
import glob
import os
@ -26,34 +34,33 @@ try:
except IndexError:
pass
# ==============================================================================
# -- find traci module ---------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- find traci module -----------------------------------------------------------------------------
# ==================================================================================================
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
# ==============================================================================
# -- imports -------------------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- sumo integration importants -------------------------------------------------------------------
# ==================================================================================================
import argparse
import logging
import time
from sumo_integration.bridge_helper import BridgeHelper # pylint: disable=wrong-import-position
from sumo_integration.carla_simulation import CarlaSimulation # pylint: disable=wrong-import-position
from sumo_integration.constants import INVALID_ACTOR_ID # pylint: disable=wrong-import-position
from sumo_integration.sumo_simulation import SumoSimulation # pylint: disable=wrong-import-position
from sumo_integration.bridge_helper import BridgeHelper
from sumo_integration.carla_simulation import CarlaSimulation
from sumo_integration.constants import *
from sumo_integration.sumo_simulation import SumoSimulation
# ==================================================================================================
# -- simulation synchro ----------------------------------------------------------------------------
# ==================================================================================================
# ==============================================================================
# -- simulation synchro --------------------------------------------------------
# ==============================================================================
def main(args):
"""
Entry point sumo-carla co-simulation.
"""
sumo = SumoSimulation(args)
carla = CarlaSimulation(args)
@ -61,8 +68,8 @@ def main(args):
sumo2carla_ids = {} # Contains only actors controlled by sumo.
carla2sumo_ids = {} # Contains only actors controlled by carla.
BridgeHelper._blueprint_library = carla.world.get_blueprint_library()
BridgeHelper._offset = sumo.get_net_offset()
BridgeHelper.blueprint_library = carla.world.get_blueprint_library()
BridgeHelper.offset = sumo.get_net_offset()
try:
while True:
@ -81,7 +88,8 @@ def main(args):
carla_blueprint = BridgeHelper.get_carla_blueprint(sumo_actor)
if carla_blueprint is not None:
carla_transform = BridgeHelper.get_carla_transform(sumo_actor.transform, sumo_actor.extent)
carla_transform = BridgeHelper.get_carla_transform(
sumo_actor.transform, sumo_actor.extent)
carla_actor_id = carla.spawn_actor(carla_blueprint, carla_transform)
if carla_actor_id != INVALID_ACTOR_ID:
@ -101,9 +109,11 @@ def main(args):
sumo_actor = sumo.get_actor(sumo_actor_id)
carla_actor = carla.get_actor(carla_actor_id)
carla_transform = BridgeHelper.get_carla_transform(sumo_actor.transform, sumo_actor.extent)
carla_transform = BridgeHelper.get_carla_transform(sumo_actor.transform,
sumo_actor.extent)
if args.sync_vehicle_lights:
carla_lights = BridgeHelper.get_carla_lights_state(carla_actor.get_light_state(), sumo_actor.signals)
carla_lights = BridgeHelper.get_carla_lights_state(
carla_actor.get_light_state(), sumo_actor.signals)
else:
carla_lights = None
@ -138,11 +148,13 @@ def main(args):
carla_actor = carla.get_actor(carla_actor_id)
sumo_actor = sumo.get_actor(sumo_actor_id)
sumo_transform = BridgeHelper.get_sumo_transform(carla_actor.get_transform(), carla_actor.bounding_box.extent)
sumo_transform = BridgeHelper.get_sumo_transform(carla_actor.get_transform(),
carla_actor.bounding_box.extent)
if args.sync_vehicle_lights:
carla_lights = carla.get_actor_light_state(carla_actor_id)
if carla_lights is not None:
sumo_lights = BridgeHelper.get_sumo_lights_state(sumo_actor.signals, carla_lights)
sumo_lights = BridgeHelper.get_sumo_lights_state(
sumo_actor.signals, carla_lights)
else:
sumo_lights = None
else:
@ -158,9 +170,6 @@ def main(args):
except KeyboardInterrupt:
logging.info('Cancelled by user.')
except Exception as error:
logging.error('Synchronization failed. {}'.format(error))
finally:
logging.info('Cleaning up synchronization')
@ -180,68 +189,49 @@ def main(args):
# Closing sumo client.
sumo.close()
if __name__ == '__main__':
argparser = argparse.ArgumentParser(
description=__doc__
)
argparser.add_argument(
'--carla-host',
metavar='H',
default='127.0.0.1',
help='IP of the carla host server (default: 127.0.0.1)'
)
argparser.add_argument(
'--carla-port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)'
)
argparser.add_argument(
'--sumo-host',
metavar='H',
default=None,
help='IP of the sumo host server (default: 127.0.0.1)'
)
argparser.add_argument(
'--sumo-port',
metavar='P',
default=None,
type=int,
help='TCP port to liston to (default: 8813)'
)
argparser.add_argument(
'-c', '--sumo-cfg-file',
default=None,
type=str,
help='sumo configuration file'
)
argparser.add_argument(
'--sumo-gui',
default=True,
help='run the gui version of sumo (default: True)'
)
argparser.add_argument(
'--step-length',
default=0.05,
type=float,
help='set fixed delta seconds (default: 0.05s)'
)
argparser = argparse.ArgumentParser(description=__doc__)
argparser.add_argument('--carla-host',
metavar='H',
default='127.0.0.1',
help='IP of the carla host server (default: 127.0.0.1)')
argparser.add_argument('--carla-port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)')
argparser.add_argument('--sumo-host',
metavar='H',
default=None,
help='IP of the sumo host server (default: 127.0.0.1)')
argparser.add_argument('--sumo-port',
metavar='P',
default=None,
type=int,
help='TCP port to liston to (default: 8813)')
argparser.add_argument('-c',
'--sumo-cfg-file',
default=None,
type=str,
help='sumo configuration file')
argparser.add_argument('--sumo-gui',
default=True,
help='run the gui version of sumo (default: True)')
argparser.add_argument('--step-length',
default=0.05,
type=float,
help='set fixed delta seconds (default: 0.05s)')
argparser.add_argument(
'--sync-vehicle-lights',
action='store_true',
help='synchronize vehicle lights state between simulations (default: False)'
)
argparser.add_argument(
'--debug',
action='store_true',
help='enable debug messages'
)
args = argparser.parse_args()
help='synchronize vehicle lights state between simulations (default: False)')
argparser.add_argument('--debug', action='store_true', help='enable debug messages')
arguments = argparser.parse_args()
if args.debug:
if arguments.debug:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
else:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
main(args)
main(arguments)

View File

@ -6,38 +6,44 @@
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
# ==============================================================================
# -- imports -------------------------------------------------------------------
# ==============================================================================
""" This module provides a helper for the co-simulation between sumo and carla ."""
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import json
import logging
import math
import random
import carla
import traci
import carla # pylint: disable=import-error
import traci # pylint: disable=import-error
from .sumo_simulation import SumoVehSignal
# ==============================================================================
# -- Bridge helper (SUMO <=> CARLA) --------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- Bridge helper (SUMO <=> CARLA) ----------------------------------------------------------------
# ==================================================================================================
class BridgeHelper(object):
"""
BridgeHelper provides methos to ease the co-simulation between sumo and carla.
"""
_blueprint_library = None
_offset = (0, 0)
blueprint_library = []
offset = (0, 0)
with open('data/vtypes.json') as f:
_VTYPES = json.load(f)['carla_blueprints']
@staticmethod
def get_carla_transform(in_sumo_transform, extent):
"""Returns carla transform based on sumo transform.
"""
offset = BridgeHelper._offset
Returns carla transform based on sumo transform.
"""
offset = BridgeHelper.offset
in_location = in_sumo_transform.location
in_rotation = in_sumo_transform.rotation
@ -45,93 +51,80 @@ class BridgeHelper(object):
# (http://sumo.sourceforge.net/userdoc/Purgatory/Vehicle_Values.html#angle)
yaw = -1 * in_rotation.yaw + 90
length = 2.0 * extent.x
out_location = (
in_location.x - math.cos(math.radians(yaw)) * (length / 2.0),
in_location.y - math.sin(math.radians(yaw)) * (length / 2.0),
in_location.z
)
out_location = (in_location.x - math.cos(math.radians(yaw)) * (length / 2.0),
in_location.y - math.sin(math.radians(yaw)) * (length / 2.0), in_location.z)
out_rotation = (in_rotation.pitch, in_rotation.yaw, in_rotation.roll)
# Applying offset sumo-carla net.
out_location = (
out_location[0] - offset[0],
out_location[1] - offset[1],
out_location[2]
)
out_rotation = out_rotation
out_location = (out_location[0] - offset[0], out_location[1] - offset[1], out_location[2])
# Transform to carla reference system (left-handed system).
return carla.Transform(
carla.Location(out_location[0], -out_location[1], out_location[2]),
carla.Rotation(out_rotation[0], out_rotation[1] - 90, out_rotation[2])
)
carla.Rotation(out_rotation[0], out_rotation[1] - 90, out_rotation[2]))
@staticmethod
def get_sumo_transform(in_carla_transform, extent):
"""Returns sumo transform based on carla transform.
"""
offset = BridgeHelper._offset
Returns sumo transform based on carla transform.
"""
offset = BridgeHelper.offset
in_location = in_carla_transform.location
in_rotation = in_carla_transform.rotation
# From center to front-center-bumper (carla reference system).
yaw = -1 * in_rotation.yaw
length = 2.0 * extent.x
out_location = (
in_location.x + math.cos(math.radians(yaw)) * (length / 2.0),
in_location.y - math.sin(math.radians(yaw)) * (length / 2.0),
in_location.z
)
out_location = (in_location.x + math.cos(math.radians(yaw)) * (length / 2.0),
in_location.y - math.sin(math.radians(yaw)) * (length / 2.0), in_location.z)
out_rotation = (in_rotation.pitch, in_rotation.yaw, in_rotation.roll)
# Applying offset carla-sumo net
out_location = (
out_location[0] + offset[0],
out_location[1] - offset[1],
out_location[2]
)
out_rotation = out_rotation
out_location = (out_location[0] + offset[0], out_location[1] - offset[1], out_location[2])
# Transform to sumo reference system.
return carla.Transform(
carla.Location(out_location[0], -out_location[1], out_location[2]),
carla.Rotation(out_rotation[0], out_rotation[1] + 90, out_rotation[2])
)
carla.Rotation(out_rotation[0], out_rotation[1] + 90, out_rotation[2]))
@staticmethod
def _get_recommended_carla_blueprint(sumo_actor):
"""Returns an appropriate blueprint based on the given sumo actor.
"""
Returns an appropriate blueprint based on the given sumo actor.
"""
vclass = sumo_actor.vclass.value
blueprints = []
for blueprint in BridgeHelper._blueprint_library:
for blueprint in BridgeHelper.blueprint_library:
if blueprint.id in BridgeHelper._VTYPES and \
BridgeHelper._VTYPES[blueprint.id]['vClass'] == vclass:
blueprints.append(blueprint)
if len(blueprints) == 0:
if not blueprints:
return None
return random.choice(blueprints)
@staticmethod
def get_carla_blueprint(sumo_actor):
"""Returns an appropriate blueprint based on the received sumo actor.
"""
blueprint_library = BridgeHelper._blueprint_library
Returns an appropriate blueprint based on the received sumo actor.
"""
blueprint_library = BridgeHelper.blueprint_library
type_id = sumo_actor.type_id
if type_id in [bp.id for bp in blueprint_library]:
blueprint = blueprint_library.filter(type_id)[0]
logging.debug('[BridgeHelper] sumo vtype {} found in carla blueprints'.format(type_id))
logging.debug('[BridgeHelper] sumo vtype %s found in carla blueprints', type_id)
else:
blueprint = BridgeHelper._get_recommended_carla_blueprint(sumo_actor)
if blueprint is not None:
logging.warning(
'sumo vtype {} not found in carla blueprints. The following blueprint will be used: {}'.format(type_id, blueprint.id))
'sumo vtype %s not found in carla. The following blueprint will be used: %s'
, type_id, blueprint.id)
else:
logging.error('sumo vtype {} not supported. No vehicle will be spawned in carla'.format(type_id))
logging.error(
'sumo vtype %s not supported. No vehicle will be spawned in carla', type_id)
return None
if blueprint.has_attribute('color'):
@ -139,26 +132,23 @@ class BridgeHelper(object):
blueprint.set_attribute('color', color)
if blueprint.has_attribute('driver_id'):
driver_id = random.choice(
blueprint.get_attribute('driver_id').recommended_values)
driver_id = random.choice(blueprint.get_attribute('driver_id').recommended_values)
blueprint.set_attribute('driver_id', driver_id)
blueprint.set_attribute('role_name', 'sumo_driver')
logging.debug('''[BridgeHelper] sumo vtype {vtype} will be spawned in carla with the following attributes:
\tblueprint: {bp_id:}
\tcolor: {color:}'''.format(
vtype=type_id,
bp_id=blueprint.id,
color=sumo_actor.color if blueprint.has_attribute('color') else (-1, -1, -1)
)
)
logging.debug(
'''[BridgeHelper] sumo vtype %s will be spawned in carla with the following attributes:
\tblueprint: %s
\tcolor: %s''', type_id, blueprint.id,
sumo_actor.color if blueprint.has_attribute('color') else (-1, -1, -1))
return blueprint
@staticmethod
def _create_sumo_vtype(carla_actor):
"""Creates an appropriate vtype based on the given carla_actor.
"""
Creates an appropriate vtype based on the given carla_actor.
"""
type_id = carla_actor.type_id
attrs = carla_actor.attributes
@ -186,47 +176,46 @@ class BridgeHelper(object):
traci.vehicletype.setWidth(type_id, 2.0 * extent.y)
traci.vehicletype.setHeight(type_id, 2.0 * extent.z)
logging.debug('''[BridgeHelper] blueprint{bp_id} not found in sumo vtypes
\tdefault vtype: {dvtype:}
\tvtype: {vtype:}
\tclass: {_class:}
\tshape: {shape:}
\tcolor: {color:}
\tlenght: {lenght:}
\twidth: {width:}
\theight: {height:}'''.format(
bp_id=type_id,
dvtype='DEFAULT_BIKETYPE' if int(attrs['number_of_wheels']) == 2 else 'DEFAULT_VEHTYPE',
vtype=type_id,
_class=traci.vehicletype.getVehicleClass(type_id),
shape=traci.vehicletype.getShapeClass(type_id),
color=traci.vehicletype.getColor(type_id),
lenght=traci.vehicletype.getLength(type_id),
width=traci.vehicletype.getWidth(type_id),
height=traci.vehicletype.getHeight(type_id)
)
)
logging.debug(
'''[BridgeHelper] blueprint %s not found in sumo vtypes
\tdefault vtype: %s
\tvtype: %s
\tclass: %s
\tshape: %s
\tcolor: %s
\tlenght: %s
\twidth: %s
\theight: %s''', type_id,
'DEFAULT_BIKETYPE' if int(attrs['number_of_wheels']) == 2 else 'DEFAULT_VEHTYPE',
type_id, traci.vehicletype.getVehicleClass(type_id),
traci.vehicletype.getShapeClass(type_id), traci.vehicletype.getColor(type_id),
traci.vehicletype.getLength(type_id), traci.vehicletype.getWidth(type_id),
traci.vehicletype.getHeight(type_id))
return type_id
@staticmethod
def get_sumo_vtype(carla_actor):
"""Returns an appropriate vtype based on the type id and attributes.
"""
Returns an appropriate vtype based on the type id and attributes.
"""
type_id = carla_actor.type_id
if not type_id.startswith('vehicle'):
logging.error('[BridgeHelper] Blueprint {} not supported. No vehicle will be spawned in sumo'.format(type_id))
logging.error(
'[BridgeHelper] Blueprint %s not supported. No vehicle will be spawned in sumo',
type_id)
return None
if type_id in traci.vehicletype.getIDList():
logging.debug('[BridgeHelper] blueprint {} found in sumo vtypes'.format(type_id))
logging.debug('[BridgeHelper] blueprint %s found in sumo vtypes', type_id)
return type_id
return BridgeHelper._create_sumo_vtype(carla_actor)
@staticmethod
def get_carla_lights_state(current_carla_lights, sumo_lights):
"""Returns carla vehicle light state based on sumo signals.
"""
Returns carla vehicle light state based on sumo signals.
"""
current_lights = current_carla_lights
@ -280,7 +269,8 @@ class BridgeHelper(object):
@staticmethod
def get_sumo_lights_state(current_sumo_lights, carla_lights):
"""Returns sumo signals based on carla vehicle light state.
"""
Returns sumo signals based on carla vehicle light state.
"""
current_lights = current_sumo_lights

View File

@ -6,32 +6,34 @@
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
# ==============================================================================
# -- imports -------------------------------------------------------------------
# ==============================================================================
""" This module is responsible for the management of the carla simulation. """
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import logging
import carla
SpawnActor = carla.command.SpawnActor
FutureActor = carla.command.FutureActor
SetSimulatePhysics = carla.command.SetSimulatePhysics
import carla # pylint: disable=import-error
from .constants import *
from .constants import INVALID_ACTOR_ID, SPAWN_OFFSET_Z
# ==============================================================================
# -- carla simulation ----------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- carla simulation ------------------------------------------------------------------------------
# ==================================================================================================
class CarlaSimulation(object):
"""
CarlaSimulation is responsible for the management of the carla simulation.
"""
def __init__(self, args):
self.args = args
self.host = args.carla_host
self.port = args.carla_port
self.step_length = args.step_length
host = args.carla_host
port = args.carla_port
self.client = carla.Client(self.host, self.port)
self.client = carla.Client(host, port)
self.client.set_timeout(2.0)
self.world = self.client.get_world()
@ -40,7 +42,7 @@ class CarlaSimulation(object):
# Configuring carla simulation in sync mode.
settings = self.world.get_settings()
settings.synchronous_mode = True
settings.fixed_delta_seconds = self.step_length
settings.fixed_delta_seconds = args.step_length
self.world.apply_settings(settings)
# The following sets contain updated information for the current frame.
@ -49,12 +51,20 @@ class CarlaSimulation(object):
self.destroyed_actors = set()
def get_actor(self, actor_id):
"""
Accessor for carla actor.
"""
return self.world.get_actor(actor_id)
# This is a workaround to fix synchronization issues when other carla
# clients remove an actor in carla without waiting for tick (e.g.,
# running sumo co-simulation and manual control at the same time)
def get_actor_light_state(self, actor_id):
"""
Accessor for carla actor light state.
If the actor is not alive, returns None.
"""
try:
actor = self.get_actor(actor_id)
return actor.get_light_state()
@ -62,30 +72,46 @@ class CarlaSimulation(object):
return None
def spawn_actor(self, blueprint, transform):
"""Spawns a new actor.
"""
Spawns a new actor.
:param blueprint: blueprint of the actor to be spawned.
:param transform: transform where the actor will be spawned.
:return: actor id if the actor is successfully spawned. Otherwise, INVALID_ACTOR_ID.
"""
transform = carla.Transform(
transform.location + carla.Location(0, 0, SPAWN_OFFSET_Z),
transform.rotation)
batch = [
SpawnActor(blueprint,transform)
.then(SetSimulatePhysics(FutureActor, False))
carla.command.SpawnActor(blueprint, transform)
.then(carla.command.SetSimulatePhysics(carla.command.FutureActor, False))
]
response = self.client.apply_batch_sync(batch, True)[0]
if response.error:
logging.error('Spawn carla actor failed. {}'.format(response.error))
logging.error('Spawn carla actor failed. %s', response.error)
return INVALID_ACTOR_ID
else:
return response.actor_id
return response.actor_id
def destroy_actor(self, actor_id):
"""
Destroys the given actor.
"""
actor = self.world.get_actor(actor_id)
if actor is not None:
return actor.destroy()
return False
def synchronize_vehicle(self, vehicle_id, transform, lights=None):
"""
Updates vehicle state.
:param vehicle_id: id of the actor to be updated.
:param transform: new vehicle transform (i.e., position and rotation).
:param lights: new vehicle light state.
:return: True if successfully updated. Otherwise, False.
"""
vehicle = self.world.get_actor(vehicle_id)
if vehicle is None:
return False
@ -93,11 +119,12 @@ class CarlaSimulation(object):
vehicle.set_transform(transform)
if lights is not None and self.args.sync_vehicle_lights:
vehicle.set_light_state(carla.VehicleLightState(lights))
def synchronize_walker(self, walker_id, transform):
pass
return True
def tick(self):
"""
Tick to carla simulation.
"""
self.world.tick()
# Update data structures for the current frame.

View File

@ -6,9 +6,11 @@
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
# ==============================================================================
# -- constants -----------------------------------------------------------------
# ==============================================================================
""" This module defines constants used for the sumo-carla co-simulation. """
# ==================================================================================================
# -- constants -------------------------------------------------------------------------------------
# ==================================================================================================
INVALID_ACTOR_ID = -1
SPAWN_OFFSET_Z = 5.0 # meters

View File

@ -6,28 +6,32 @@
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
# ==============================================================================
# -- imports -------------------------------------------------------------------
# ==============================================================================
""" This module is responsible for the management of the sumo simulation. """
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import collections
import enum
import logging
import carla
import sumolib
import traci
import carla # pylint: disable=import-error
import sumolib # pylint: disable=import-error
import traci # pylint: disable=import-error
from .constants import *
from .constants import INVALID_ACTOR_ID
# ==============================================================================
# -- sumo definitions ----------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- sumo definitions ------------------------------------------------------------------------------
# ==================================================================================================
# Sumo vehicle signals.
# https://sumo.dlr.de/docs/TraCI/Vehicle_Signalling.html
class SumoVehSignal(object):
"""
SumoVehSignal contains the different sumo vehicle signals.
"""
BLINKER_RIGHT = 1 << 0
BLINKER_LEFT = 1 << 1
BLINKER_EMERGENCY = 1 << 2
@ -46,6 +50,9 @@ class SumoVehSignal(object):
# https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#abstract_vehicle_class
class SumoActorClass(enum.Enum):
"""
SumoActorClass enumerates the different sumo actor classes.
"""
IGNORING = "ignoring"
PRIVATE = "private"
EMERGENCY = "emergency"
@ -84,13 +91,16 @@ SumoActor = collections.namedtuple(
class SumoSimulation(object):
"""
SumoSimulation is responsible for the management of the sumo simulation.
"""
def __init__(self, args):
self.args = args
self.host = args.sumo_host
self.port = args.sumo_port
host = args.sumo_host
port = args.sumo_port
self.sumo_gui = args.sumo_gui
if self.sumo_gui is True:
if args.sumo_gui is True:
sumo_binary = sumolib.checkBinary('sumo-gui')
else:
sumo_binary = sumolib.checkBinary('sumo')
@ -105,11 +115,11 @@ class SumoSimulation(object):
'--collision.check-junctions'
])
if self.sumo_gui:
if args.sumo_gui:
logging.info('Remember to press the play button to start the simulation')
else:
logging.info('Connection to sumo server. Host: {} Port: {}'.format(self.host, self.port))
traci.init(host=self.host, port=self.port)
logging.info('Connection to sumo server. Host: %s Port: %s', host, port)
traci.init(host=host, port=port)
# Structures to keep track of the spawned and destroyed vehicles at each time step.
self.spawned_actors = set()
@ -123,6 +133,19 @@ class SumoSimulation(object):
@staticmethod
def subscribe(actor_id):
"""
Subscribe the given actor to the following variables:
* Type.
* Vehicle class.
* Color.
* Length, Width, Height.
* Position3D (i.e., x, y, z).
* Angle, Slope.
* Speed.
* Lateral speed.
* Signals.
"""
traci.vehicle.subscribe(actor_id, [
traci.constants.VAR_TYPE, traci.constants.VAR_VEHICLECLASS,
traci.constants.VAR_COLOR, traci.constants.VAR_LENGTH,
@ -134,16 +157,28 @@ class SumoSimulation(object):
@staticmethod
def unsubscribe(actor_id):
"""
Unsubscribe the given actor from receiving updated information each step.
"""
traci.vehicle.unsubscribe(actor_id)
def get_net_offset(self):
"""
Accessor for sumo net offset.
"""
offset = traci.simulation.convertGeo(0, 0)
return (-offset[0], -offset[1])
def get_step_length(self):
"""
Accessor for sumo simulation step length.
"""
return traci.simulation.getDeltaT()
def get_actor(self, actor_id):
"""
Accessor for sumo actor.
"""
results = traci.vehicle.getSubscriptionResults(actor_id)
type_id = results[traci.constants.VAR_TYPE]
@ -169,39 +204,57 @@ class SumoSimulation(object):
return SumoActor(type_id, vclass, transform, signals, extent, color)
def spawn_actor(self, type_id, attrs={}):
"""Spawns a new actor based on given type.
def spawn_actor(self, type_id, attrs=None):
"""
Spawns a new actor.
:param type_id: vtype to be spawned.
:param attrs: dictionary with additional attributes for this specific actor.
:return: actor id if the actor is successfully spawned. Otherwise, INVALID_ACTOR_ID.
"""
actor_id = 'carla' + str(self._sequential_id)
try:
traci.vehicle.add(actor_id, 'carla_route', typeID=type_id)
except Exception as error:
logging.error('Spawn sumo actor failed: {}'.format(error))
except traci.exceptions.TraCIException as error:
logging.error('Spawn sumo actor failed: %s', error)
return INVALID_ACTOR_ID
if 'color' in attrs:
color = attrs['color'].split(',')
traci.vehicle.setColor(actor_id, color)
if attrs is not None:
if 'color' in attrs:
color = attrs['color'].split(',')
traci.vehicle.setColor(actor_id, color)
self._sequential_id += 1
return actor_id
def destroy_actor(self, actor_id):
"""
Destroys the given actor.
"""
traci.vehicle.remove(actor_id)
def synchronize_vehicle(self, vehicle_id, transform, signals=None):
x, y = transform.location.x, transform.location.y
"""
Updates vehicle state.
:param vehicle_id: id of the actor to be updated.
:param transform: new vehicle transform (i.e., position and rotation).
:param signals: new vehicle signals.
:return: True if successfully updated. Otherwise, False.
"""
loc_x, loc_y = transform.location.x, transform.location.y
yaw = transform.rotation.yaw
traci.vehicle.moveToXY(vehicle_id, "", 0, x, y, angle=yaw, keepRoute=2)
traci.vehicle.moveToXY(vehicle_id, "", 0, loc_x, loc_y, angle=yaw, keepRoute=2)
if signals is not None and self.args.sync_vehicle_lights:
traci.vehicle.setSignals(vehicle_id, signals)
def synchronize_walker(self, walker_id, transform):
pass
return True
def tick(self):
"""
Tick to sumo simulation.
"""
traci.simulationStep()
# Update data structures for the current frame.
@ -209,4 +262,7 @@ class SumoSimulation(object):
self.destroyed_actors = set(traci.simulation.getArrivedIDList())
def close(self):
"""
Closes traci client.
"""
traci.close()

View File

@ -10,37 +10,38 @@
Script to create sumo vtypes based on carla blueprints.
"""
# ==============================================================================
# -- find carla module ---------------------------------------------------------
# ==============================================================================
import glob
import os
import sys
try:
sys.path.append(glob.glob('../../../PythonAPI/carla/dist/carla-*%d.%d-%s.egg' % (
sys.version_info.major,
sys.version_info.minor,
'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0])
except IndexError:
pass
# ==============================================================================
# -- imports -------------------------------------------------------------------
# ==============================================================================
import carla
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import argparse
import glob
import datetime
import json
import logging
import lxml.etree as ET
import os
import sys
# ==============================================================================
# -- load specs definition -----------------------------------------------------
# ==============================================================================
import lxml.etree as ET # pylint: disable=import-error
# ==================================================================================================
# -- find carla module -----------------------------------------------------------------------------
# ==================================================================================================
try:
sys.path.append(
glob.glob('../../../PythonAPI/carla/dist/carla-*%d.%d-%s.egg' %
(sys.version_info.major, sys.version_info.minor,
'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0])
except IndexError:
pass
import carla # pylint: disable=import-error, wrong-import-position
# ==================================================================================================
# -- load specs definition -------------------------------------------------------------------------
# ==================================================================================================
with open('../data/vtypes.json') as f:
SPECS = json.load(f)
@ -49,19 +50,20 @@ with open('../data/vtypes.json') as f:
DEFAULT_WHEELED_VEHICLE = SPECS['DEFAULT_WHEELED_VEHICLE']
CARLA_BLUEPRINTS_SPECS = SPECS['carla_blueprints']
# ==============================================================================
# -- main ----------------------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- main ------------------------------------------------------------------------------------------
# ==================================================================================================
def write_vtype_xml(filename, vtypes):
"""
Write route xml file.
"""
root = ET.Element('routes')
root.addprevious(ET.Comment(
'generated on {date:%Y-%m-%d %H:%M:%S} by {script:}'.format(
date=datetime.datetime.now(),
script=os.path.basename(__file__))
)
)
root.addprevious(
ET.Comment('generated on {date:%Y-%m-%d %H:%M:%S} by {script:}'.format(
date=datetime.datetime.now(), script=os.path.basename(__file__))))
for vtype in vtypes:
ET.SubElement(root, 'vType', vtype)
@ -69,6 +71,7 @@ def write_vtype_xml(filename, vtypes):
tree = ET.ElementTree(root)
tree.write(filename, pretty_print=True, encoding='UTF-8', xml_declaration=True)
def generate_vtype(vehicle):
"""Generates sumo vtype specification for a given carla vehicle.
@ -80,23 +83,21 @@ def generate_vtype(vehicle):
if type_id not in CARLA_BLUEPRINTS_SPECS:
number_of_wheels = int(vehicle.attributes['number_of_wheels'])
if number_of_wheels == 2:
logging.warning('type id {id:} not mapped to any sumo vtype. Using default specification for two-wheeled vehicles: {specs:}'.format(
id=type_id,
specs=DEFAULT_2_WHEELED_VEHICLE)
)
logging.warning(
'''type id %s not mapped to any sumo vtype.
\tUsing default specification for two-wheeled vehicles: %s''', type_id,
DEFAULT_2_WHEELED_VEHICLE)
user_specs = DEFAULT_2_WHEELED_VEHICLE
else:
logging.warning('type id {id:} not mapped to any sumo vtype. Using default specification for wheeled vehicles: {specs:}'.format(
id=type_id,
specs=DEFAULT_WHEELED_VEHICLE)
)
logging.warning(
'''type id %s not mapped to any sumo vtype.
\tUsing default specification for wheeled vehicles: %s''', type_id,
DEFAULT_WHEELED_VEHICLE)
user_specs = DEFAULT_WHEELED_VEHICLE
else:
logging.info('type id {id:} mapped to the following specifications: {specs:}'.format(
id=type_id,
specs=CARLA_BLUEPRINTS_SPECS[type_id])
)
logging.info('type id %s mapped to the following specifications: %s', type_id,
CARLA_BLUEPRINTS_SPECS[type_id])
user_specs = CARLA_BLUEPRINTS_SPECS[type_id]
specs = {
@ -109,7 +110,11 @@ def generate_vtype(vehicle):
specs.update(user_specs)
return specs
def main(args):
"""
Main method.
"""
client = carla.Client(args.carla_host, args.carla_port)
client.set_timeout(2.0)
@ -122,14 +127,15 @@ def main(args):
vtypes = []
for blueprint in vehicle_blueprints:
logging.info('processing vtype for {}'.format(blueprint.id))
logging.info('processing vtype for %s', blueprint.id)
vehicle = world.spawn_actor(blueprint, transform)
vtype = generate_vtype(vehicle)
if vtype:
vtypes.append(vtype)
else:
logging.error('type id {id:} could no be mapped to any vtype'.format(id=vehicle.type_id))
logging.error(
'type id %s could no be mapped to any vtype', vehicle.type_id)
vehicle.destroy()
@ -138,37 +144,32 @@ def main(args):
finally:
logging.info('done')
if __name__ == '__main__':
# Define arguments that will be received and parsed.
argparser = argparse.ArgumentParser(
description=__doc__)
argparser = argparse.ArgumentParser(description=__doc__)
argparser.add_argument('--carla-host',
metavar='H',
default='127.0.0.1',
help='IP of the host server (default: 127.0.0.1)')
argparser.add_argument('--carla-port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)')
argparser.add_argument(
'--carla-host',
metavar='H',
default='127.0.0.1',
help='IP of the host server (default: 127.0.0.1)')
argparser.add_argument(
'--carla-port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)')
argparser.add_argument(
'--output-file', '-o',
'--output-file',
'-o',
metavar='FILE',
default='carlavtypes.rou.xml',
type=str,
help='the generated vtypes will be written to FILE (default: carlavtypes.rou.xml)')
argparser.add_argument(
'--verbose', '-v',
action='store_true',
help='increase output verbosity'
)
args = argparser.parse_args()
argparser.add_argument('--verbose', '-v', action='store_true', help='increase output verbosity')
arguments = argparser.parse_args()
if args.verbose:
if arguments.verbose:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
else:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.WARNING)
main(args)
main(arguments)

View File

@ -10,29 +10,33 @@
Script to modify automatically vtypes to carla type ids in sumo route files.
"""
# ==============================================================================
# -- imports -------------------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import argparse
import fnmatch
import json
import logging
import lxml.etree as ET
import random
# ==============================================================================
# -- load vtypes ---------------------------------------------------------------
# ==============================================================================
import lxml.etree as ET # pylint: disable=import-error
# ==================================================================================================
# -- load vtypes -----------------------------------------------------------------------------------
# ==================================================================================================
with open('../data/vtypes.json') as f:
VTYPES = json.load(f)['carla_blueprints'].keys()
# ==============================================================================
# -- main ----------------------------------------------------------------------
# ==============================================================================
# ==================================================================================================
# -- main ------------------------------------------------------------------------------------------
# ==================================================================================================
def main(route_files, vtypes, _random=False):
"""
Main method to automatically modify vtypes to carla type ids in sumo route files.
"""
for filename in route_files:
tree = ET.parse(filename)
root = tree.getroot()
@ -54,39 +58,26 @@ def main(route_files, vtypes, _random=False):
tree = ET.ElementTree(root)
tree.write(filename, pretty_print=True, encoding='UTF-8', xml_declaration=True)
logging.info('modified {counter:} vtype(s) in {file:}'.format(
counter=counter,
file=filename
))
logging.info('modified %d vtype(s) in %s', counter, filename)
if __name__ == '__main__':
# Define arguments that will be received and parsed.
argparser = argparse.ArgumentParser(
description=__doc__
)
argparser.add_argument(
'--route-files', '-r',
metavar='FILES',
nargs='+',
default=[],
help='sumo route files'
)
argparser.add_argument(
'--random',
action='store_true',
help='apply vtypes randomly or sequentially'
)
argparser.add_argument(
'--filterv',
metavar='PATTERN',
default='vehicle.*',
help='vehicles filter (default: "vehicle.*")'
)
argparser.add_argument(
'--verbose', '-v',
action='store_true',
help='increase output verbosity'
)
argparser = argparse.ArgumentParser(description=__doc__)
argparser.add_argument('--route-files',
'-r',
metavar='FILES',
nargs='+',
default=[],
help='sumo route files')
argparser.add_argument('--random',
action='store_true',
help='apply vtypes randomly or sequentially')
argparser.add_argument('--filterv',
metavar='PATTERN',
default='vehicle.*',
help='vehicles filter (default: "vehicle.*")')
argparser.add_argument('--verbose', '-v', action='store_true', help='increase output verbosity')
args = argparser.parse_args()
if args.verbose:
@ -94,5 +85,5 @@ if __name__ == '__main__':
else:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.WARNING)
vtypes = [vtype for vtype in VTYPES if fnmatch.fnmatch(vtype, args.filterv)]
main(args.route_files, vtypes, args.random)
filtered_vtypes = [vtype for vtype in VTYPES if fnmatch.fnmatch(vtype, args.filterv)]
main(args.route_files, filtered_vtypes, args.random)