initial version ptv-vissim co-simulation

This commit is contained in:
Joel Moriana 2020-03-26 20:33:34 +01:00 committed by bernat
parent 9dfbb14276
commit f3bc87928e
8 changed files with 846 additions and 0 deletions

7
Co-Simulation/PTV-Vissim/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
venv
# Vissim files
*.results
*.inp0
*.layx
*.err

View File

@ -0,0 +1,43 @@
{
"100": [
"vehicle.audi.a2",
"vehicle.audi.tt",
"vehicle.bmw.grandtourer",
"vehicle.citroen.c3",
"vehicle.jeep.wrangler_rubicon",
"vehicle.lincoln.mkz2017",
"vehicle.mercedes-benz.coupe",
"vehicle.mini.cooperst",
"vehicle.mustang.mustang",
"vehicle.nissan.micra",
"vehicle.nissan.patrol",
"vehicle.seat.leon",
"vehicle.volkswagen.t2",
"vehicle.toyota.prius",
"vehicle.tesla.model3",
"vehicle.audi.etron"
],
"200": [
"vehicle.carlamotors.carlacola"
],
"300": [],
"400": [],
"510": [],
"520": [],
"610": [
"vehicle.yamaha.yzf",
"vehicle.harley-davidson.low_rider",
"vehicle.kawasaki.ninja",
"vehicle.gazelle.omafiets",
"vehicle.diamondback.century",
"vehicle.bh.crossbike"
],
"620": [
"vehicle.yamaha.yzf",
"vehicle.harley-davidson.low_rider",
"vehicle.kawasaki.ninja",
"vehicle.gazelle.omafiets",
"vehicle.diamondback.century",
"vehicle.bh.crossbike"
]
}

View File

@ -0,0 +1,224 @@
#!/usr/bin/env python
# Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
"""
Script to co-simulate CARLA and PTV-Vissim.
"""
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import argparse
import json
import logging
import random
import time
# ==================================================================================================
# -- 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
# ==================================================================================================
# -- vissim integration imports --------------------------------------------------------------------
# ==================================================================================================
from vissim_integration.bridge_helper import BridgeHelper
from vissim_integration.carla_simulation import CarlaSimulation
from vissim_integration.vissim_simulation import PTVVissimSimulation
from vissim_integration.constants import INVALID_ACTOR_ID
# ==================================================================================================
# -- synchronization_loop --------------------------------------------------------------------------
# ==================================================================================================
class SimulationSynchronization(object):
"""
SimulationSynchronization class is responsible for the synchronization of ptv-vissim and carla
simulations.
"""
def __init__(self, args):
self.args = args
self.vissim = PTVVissimSimulation(args)
self.carla = CarlaSimulation(args)
# Mapped actor ids.
self.vissim2carla_ids = {} # Contains only actors controlled by vissim.
self.carla2vissim_ids = {} # Contains only actors controlled by carla.
BridgeHelper.blueprint_library = self.carla.world.get_blueprint_library()
dir_path = os.path.dirname(os.path.realpath(__file__))
with open(os.path.join(dir_path, 'data', 'vtypes.json')) as f:
BridgeHelper.vtypes = json.load(f)
def tick(self):
"""
Tick to simulation synchronization
"""
# -------------------
# vissim-->carla sync
# -------------------
self.vissim.tick()
# Spawning vissim controlled vehicles in carla.
vissim_spawned_actors = self.vissim.spawned_vehicles - set(self.carla2vissim_ids.values())
for vissim_actor_id in vissim_spawned_actors:
vissim_actor = self.vissim.get_actor(vissim_actor_id)
carla_blueprint = BridgeHelper.get_carla_blueprint(vissim_actor)
if carla_blueprint is not None:
carla_transform = BridgeHelper.get_carla_transform(vissim_actor.get_transform())
carla_actor_id = self.carla.spawn_actor(carla_blueprint, carla_transform)
if carla_actor_id != INVALID_ACTOR_ID:
self.vissim2carla_ids[vissim_actor_id] = carla_actor_id
# Destroying vissim controlled vehicles in carla.
for vissim_actor_id in self.vissim.destroyed_vehicles:
if vissim_actor_id in self.vissim2carla_ids:
self.vissim.destroy_actor(self.vissim2carla_ids.pop(vissim_actor_id))
# Updating vissim controlled vehicles in carla.
for vissim_actor_id in self.vissim2carla_ids:
carla_actor_id = self.vissim2carla_ids[vissim_actor_id]
vissim_actor = self.vissim.get_actor(vissim_actor_id)
carla_actor = self.carla.get_actor(carla_actor_id)
carla_transform = BridgeHelper.get_carla_transform(vissim_actor.get_transform())
carla_velocity = BridgeHelper.get_carla_velocity(vissim_actor.get_velocity())
self.carla.synchronize_vehicle(carla_actor_id, carla_transform, carla_velocity)
# -------------------
# carla-->vissim sync
# -------------------
self.carla.tick()
# Spawning carla controlled vehicles in vissim. This also takes into account carla vehicles
# that could not be spawned in vissim in previous time steps.
carla_spawned_actors = self.carla.spawned_actors - set(self.vissim2carla_ids.values())
carla_spawned_actors.update(
[c_id for c_id, v_id in self.carla2vissim_ids.items() if v_id == INVALID_ACTOR_ID])
for carla_actor_id in carla_spawned_actors:
carla_actor = self.carla.get_actor(carla_actor_id)
vissim_transform = BridgeHelper.get_vissim_transform(carla_actor.get_transform())
vissim_actor_id = self.vissim.spawn_actor(vissim_transform)
# Add the vissim_actor_id even if it was not possible to spawn it (INVALID_ACTOR_ID) to
# try to spawn it again in next time steps.
self.carla2vissim_ids[carla_actor_id] = vissim_actor_id
# Destroying carla controlled vehicles in vissim.
for carla_actor_id in self.carla.destroyed_actors:
if carla_actor_id in self.carla2vissim_ids:
self.vissim.destroy_actor(self.carla2vissim_ids.pop(carla_actor_id))
# Updating carla controlled vehicles in vissim.
for carla_actor_id in self.carla2vissim_ids:
vissim_actor_id = self.carla2vissim_ids[carla_actor_id]
if vissim_actor_id != INVALID_ACTOR_ID:
carla_actor = self.carla.get_actor(carla_actor_id)
vissim_transform = BridgeHelper.get_vissim_transform(carla_actor.get_transform())
vissim_velocity = BridgeHelper.get_vissim_velocity(carla_actor.get_velocity())
self.vissim.synchronize_vehicle(vissim_actor_id, vissim_transform, vissim_velocity)
def close(self):
"""
Cleans synchronization.
"""
# Configuring carla simulation in async mode.
settings = self.carla.world.get_settings()
settings.synchronous_mode = False
settings.fixed_delta_seconds = None
self.carla.world.apply_settings(settings)
# Destroying synchronized actors.
for carla_actor_id in self.vissim2carla_ids.values():
self.carla.destroy_actor(carla_actor_id)
# Closing PTV-Vissim connection.
self.vissim.close()
def synchronization_loop(args):
"""
Entry point for vissim-carla co-simulation.
"""
try:
synchronization = SimulationSynchronization(args)
while True:
start = time.time()
synchronization.tick()
end = time.time()
elapsed = end - start
if elapsed < args.step_length:
time.sleep(args.step_length - elapsed)
except KeyboardInterrupt:
logging.info('Cancelled by user.')
finally:
logging.info('Cleaning synchronization')
synchronization.close()
# ==================================================================================================
# -- main ------------------------------------------------------------------------------------------
# ==================================================================================================
if __name__ == '__main__':
argparser = argparse.ArgumentParser(description=__doc__)
argparser.add_argument('vissim_network', type=str, help='vissim network file')
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('--vissim-version',
default=2020,
type=int,
help='ptv-vissim version (default: 2020)')
argparser.add_argument('--step-length',
default=0.05,
type=float,
help='set fixed delta seconds (default: 0.05s)')
argparser.add_argument('--simulator-vehicles',
default=1,
type=int,
help='number of simulator vehicles to be passed to vissim (default: 1)')
argparser.add_argument('--debug', action='store_true', help='enable debug messages')
arguments = argparser.parse_args()
if arguments.debug:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
else:
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
synchronization_loop(arguments)

View File

@ -0,0 +1,136 @@
#!/usr/bin/env python
# Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
""" This module provides a helper for the co-simulation between vissim and carla. """
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import logging
import random
import carla # pylint: disable=import-error
# ==================================================================================================
# -- Bridge helper (VISSIM <=> CARLA) --------------------------------------------------------------
# ==================================================================================================
class BridgeHelper(object):
"""
BridgeHelper provides methos to ease the co-simulation between vissim and carla.
"""
blueprint_library = []
vtypes = {}
@staticmethod
def get_carla_transform(in_vissim_transform):
"""
Returns carla transform based on vissim transform.
"""
in_location = in_vissim_transform.location
in_rotation = in_vissim_transform.rotation
# Transform to carla reference system (left-handed system).
out_location = (in_location.x, -in_location.y, in_location.z)
out_rotation = (in_rotation.pitch, -in_rotation.yaw, in_rotation.roll)
out_transform = carla.Transform(
carla.Location(out_location[0], out_location[1], out_location[2]),
carla.Rotation(out_rotation[0], out_rotation[1], out_rotation[2]))
return out_transform
@staticmethod
def get_vissim_transform(in_carla_transform):
"""
Returns vissim transform based on carla transform.
"""
in_location = in_carla_transform.location
in_rotation = in_carla_transform.rotation
# Transform to vissim reference system (right-handed system).
out_location = (in_location.x, -in_location.y, in_location.z)
out_rotation = (in_rotation.pitch, -in_rotation.yaw, in_rotation.roll)
out_transform = carla.Transform(
carla.Location(out_location[0], out_location[1], out_location[2]),
carla.Rotation(out_rotation[0], out_rotation[1], out_rotation[2]))
return out_transform
@staticmethod
def _flip_y(in_vector):
"""
Flips y coordinate of the given vector.
"""
return carla.Vector3D(in_vector.x, -in_vector.y, in_vector.z)
@staticmethod
def get_carla_velocity(in_vissim_velocity):
"""
Returns carla velocity based on vissim velocity.
"""
return BridgeHelper._flip_y(in_vissim_velocity)
@staticmethod
def get_vissim_velocity(in_carla_velocity):
"""
Returns vissim velocity based on carla velocity.
"""
return BridgeHelper._flip_y(in_carla_velocity)
@staticmethod
def _get_recommended_carla_blueprint(vissim_actor):
"""
Returns an appropriate blueprint based on the given vissim actor.
"""
blueprint = BridgeHelper.blueprint_library.filter('vehicle.seat.leon')[0]
color = random.choice(blueprint.get_attribute('color').recommended_values)
blueprint.set_attribute('color', color)
return blueprint
@staticmethod
def get_carla_blueprint(vissim_actor):
"""
Returns an appropriate blueprint based on the received vissim actor.
"""
type_id = str(vissim_actor.type)
if type_id in BridgeHelper.vtypes:
candidates = BridgeHelper.vtypes[type_id]
if candidates:
blueprint_id = random.choice(candidates)
else:
logging.error(
'vissim type %s not supported. No vehicle will be spawned in carla', type_id)
return None
blueprint = BridgeHelper.blueprint_library.filter(blueprint_id)
if not blueprint:
logging.error(
'carla blueprint %s unknown. No vehicle will be spawned', blueprint_id)
return None
blueprint = blueprint[0]
if blueprint.has_attribute('color'):
color = random.choice(blueprint.get_attribute('color').recommended_values)
blueprint.set_attribute('color', color)
if blueprint.has_attribute('driver_id'):
driver_id = random.choice(blueprint.get_attribute('driver_id').recommended_values)
blueprint.set_attribute('driver_id', driver_id)
blueprint.set_attribute('role_name', 'vissim_driver')
return blueprint
else:
logging.error(
'vissim type %s unknown. No vehicle will be spawned in carla', type_id)
return None

View File

@ -0,0 +1,120 @@
#!/usr/bin/env python
# Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
""" This module is responsible for the management of the carla simulation. """
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import logging
import carla # pylint: disable=import-error
from .constants import INVALID_ACTOR_ID, CARLA_SPAWN_OFFSET_Z
# ==================================================================================================
# -- carla simulation ------------------------------------------------------------------------------
# ==================================================================================================
class CarlaSimulation(object):
"""
CarlaSimulation is responsible for the management of the carla simulation.
"""
def __init__(self, args):
self.args = args
host = args.carla_host
port = args.carla_port
self.client = carla.Client(host, port)
self.client.set_timeout(2.0)
self.world = self.client.get_world()
self.blueprint_library = self.world.get_blueprint_library()
# Configuring carla simulation in sync mode.
settings = self.world.get_settings()
settings.synchronous_mode = True
settings.fixed_delta_seconds = args.step_length
self.world.apply_settings(settings)
# The following sets contain updated information for the current frame.
self._active_actors = set()
self.spawned_actors = set()
self.destroyed_actors = set()
def get_actor(self, actor_id):
"""
Accessor for carla actor.
"""
return self.world.get_actor(actor_id)
def spawn_actor(self, blueprint, transform):
"""
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, CARLA_SPAWN_OFFSET_Z),
transform.rotation)
batch = [
carla.command.SpawnActor(blueprint, transform).then(
carla.command.SetSimulatePhysics(carla.command.FutureActor, False))
]
response = self.client.apply_batch_sync(batch, False)[0]
if response.error:
logging.error('Spawn carla actor failed. %s', response.error)
return INVALID_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, velocity, 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
vehicle.set_transform(transform)
if velocity is not None:
vehicle.set_velocity(velocity)
if lights is not None:
vehicle.set_light_state(carla.VehicleLightState(lights))
return True
def tick(self):
"""
Tick to carla simulation.
"""
self.world.tick()
# Update data structures for the current frame.
current_actors = set(
[vehicle.id for vehicle in self.world.get_actors().filter('vehicle.*')])
self.spawned_actors = current_actors.difference(self._active_actors)
self.destroyed_actors = self._active_actors.difference(current_actors)
self._active_actors = current_actors

View File

@ -0,0 +1,33 @@
#!/usr/bin/env python
# Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
""" This module defines constants used for the vissim-carla co-simulation. """
# ==================================================================================================
# -- constants -------------------------------------------------------------------------------------
# ==================================================================================================
INVALID_ACTOR_ID = -1
CARLA_SPAWN_OFFSET_Z = 25.0 # meters
# Maximum distance of a Vissim veh/ped from a simulator veh/ped to be seen by the simulator (<=0
# means unlimited radius).
VISSIM_VISIBILITY_RADIUS = 0.0
# Maximum number of simulator vehicles/pedestrians/detectors (to be passed to Vissim).
VISSIM_MAX_SIMULATOR_VEH = 5000
VISSIM_MAX_SIMULATOR_PED = 5000
VISSIM_MAX_SIMULATOR_DET = 500
# Maximum number of vissim vehicles/pedestrians/signal groups (to be passed to the simulator).
VISSIM_MAX_VISSIM_VEH = 5000
VISSIM_MAX_VISSIM_PED = 5000
VISSIM_MAX_VISSIM_SIGGRP = 5000
# VISSIM Vehicle data constants.
NAME_MAX_LENGTH = 100
MAX_UDA = 16

View File

@ -0,0 +1,283 @@
#!/usr/bin/env python
# Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
""" This module is responsible for the management of the ptv-vissim simulation. """
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
import collections
import enum
import logging
import math
import sys
import carla # pylint: disable=import-error
from ctypes import *
from . import constants
# ==================================================================================================
# -- vissim definitions ----------------------------------------------------------------------------
# ==================================================================================================
class Simulator_Veh_Data(Structure):
"""
Structure to hold the data sent to vissim about the status of the simulator vehicles (i.e.,
carla vehicles).
"""
_fields_ = [
('Position_X', c_double), # front center of the vehicle in m
('Position_Y', c_double), # front center of the vehicle in m
('Position_Z', c_double), # front center of the vehicle in m
('Orient_Heading', c_double), # in radians, eastbound = zero, northbound = +Pi/2 */
('Orient_Pitch', c_double), # in radians, uphill = positive
('Speed', c_double), # in m/s
('ControlledByVissim', c_bool), # affects next time step
('RoutingDecisionNo', c_long), # used once if ControlledByVissim changed from false to true
('RouteNo', c_long) # used once if ControlledByVissim changed from false to true
]
class VISSIM_Veh_Data(Structure):
"""
Structure to hold the data received from vissim about the status of the traffic vehicles (i.e.,
vissim vehicles).
"""
_fields_ = [
('VehicleID', c_long),
('VehicleType', c_long), # vehicle type number from Vissim
('ModelFileName', c_char * constants.NAME_MAX_LENGTH), # .v3d
('color', c_long), # RGB
('Position_X', c_double), # front center of the vehicle in m
('Position_Y', c_double), # front center of the vehicle in m
('Position_Z', c_double), # front center of the vehicle in m
('Orient_Heading', c_double), # in radians, eastbound = zero, northbound = +Pi/2 */
('Orient_Pitch', c_double), # in radians, uphill = positive
('Speed', c_double), # in m/s
('LeadingVehicleID', c_long), # relevant vehicle in front
('TrailingVehicleID', c_long), # next vehicle back on the same lane
('LinkID', c_long), # Vissim link attribute “Number”
('LinkName', c_char * constants.NAME_MAX_LENGTH), # empty if “Name” not set in Vissim
('LinkCoordinate', c_double), # in m
('LaneIndex', c_int), # 0 = rightmost
('TurningIndicator', c_int), # 1 = left, 0 = none, -1 = right
('PreviousIndex', c_long), # for interpolation: index in the array in the previous Vissim time step, < 0 = new in the visibility area
('NumUDAs', c_long), # the number of UDA values in the following array
('UDA', c_double * constants.MAX_UDA) # the first MAX_UDA user-defined numeric vehicle attributes
]
class VissimLightState(enum.Enum):
"""
VissimLightState contains the different vissim indicator states.
"""
LEFT = 1
NONE = 0
RIGHT = -1
class VissimVehicle(object):
"""
VissimVehicle holds the data relative to traffic vehicles in vissim.
"""
def __init__(self,
id,
type,
model_filename,
color,
location,
rotation,
velocity,
lights_state=VissimLightState.NONE):
# Static parameters.
self.id = id
self.type = type
self.model_filename = model_filename
self.color = color
# Dynamic attributes.
loc = carla.Location(location[0], location[1], location[2])
rot = carla.Rotation(math.degrees(rotation[0]), math.degrees(rotation[1]),
math.degrees(rotation[2]))
self._transform = carla.Transform(loc, rot)
self._velocity = carla.Vector3D(
velocity * math.cos(math.radians(rot.yaw)) * math.cos(math.radians(rot.pitch)),
velocity * math.sin(math.radians(rot.yaw)) * math.cos(math.radians(rot.pitch)),
velocity * math.sin(math.radians(rot.pitch)))
self._lights_state = lights_state
def get_velocity(self):
"""
Returns the vehicle's velocity.
"""
return self._velocity
def get_transform(self):
"""
Returns carla transform.
"""
return self._transform
# ==================================================================================================
# -- vissim simulation -----------------------------------------------------------------------------
# ==================================================================================================
class PTVVissimSimulation(object):
"""
PTVVissimSimulation is responsible for the management of the vissim simulation.
"""
def __init__(self, args):
# Maximum number of simulator vehicles to be tracked by the driving simulator interface.
self._max_simulator_vehicles = args.simulator_vehicles
# Loading driving simulator proxy library.
logging.info('Loading DrivingSimulatorProxy library...')
self.ds_proxy = cdll.LoadLibrary('DrivingSimulatorProxy.dll')
# Connection to vissim simulator.
logging.info('Establishing a connection with a GUI version of PTV-Vissim')
self.ds_proxy.VISSIM_Connect(args.vissim_version, args.vissim_network,
int(1. / args.step_length),
c_double(constants.VISSIM_VISIBILITY_RADIUS),
c_ushort(constants.VISSIM_MAX_SIMULATOR_VEH),
c_ushort(constants.VISSIM_MAX_SIMULATOR_PED),
c_ushort(constants.VISSIM_MAX_SIMULATOR_DET),
c_ushort(constants.VISSIM_MAX_VISSIM_VEH),
c_ushort(constants.VISSIM_MAX_VISSIM_PED),
c_ushort(constants.VISSIM_MAX_VISSIM_SIGGRP))
# Structures to keep track of the simulation state at each time step.
self._vissim_vehicles = {} # vissim_actor_id: VissimVehicle (only vissim traffic)
self._simulator_vehicles = {} # vissim_actor_id: Simulator_Veh_Data
self.spawned_vehicles = set()
self.destroyed_vehicles = set()
def _get_next_actor_id(self):
"""
Returns an available actor id. Otherwise, returns INVALID_ACTOR_ID.
"""
all_ids = set(range(1, self._max_simulator_vehicles + 1))
used_ids = set(self._simulator_vehicles.keys())
available_ids = all_ids - used_ids
if len(available_ids):
return available_ids.pop()
else:
return constants.INVALID_ACTOR_ID
def get_actor(self, actor_id):
"""
Accessor for vissim actor.
"""
return self._vissim_vehicles[actor_id]
def spawn_actor(self, transform):
"""
Spawns a new actor.
Warning: When the maximum number of simulator vehicles being tracked at the same time is
reached, no new vehicles are spawned.
"""
# Checks number of simulator vehicles currently being tracked.
if (len(self._simulator_vehicles) < self._max_simulator_vehicles):
actor_id = self._get_next_actor_id()
self._simulator_vehicles[actor_id] = Simulator_Veh_Data(
transform.location.x, transform.location.y, transform.location.z,
math.radians(transform.rotation.yaw), math.radians(transform.rotation.pitch), 0.0,
False, 0, 0)
return actor_id
else:
logging.warning(
'Maximum number of simulator vehicles reached. No vehicle will be spawned.')
return constants.INVALID_ACTOR_ID
def destroy_actor(self, actor_id):
"""
Destroys the given actor.
:param actor_id: id of the vehicle to be destroyed.
:return: True if successfully destroyed. Otherwise, False.
"""
if actor_id in self._simulator_vehicles:
del self._simulator_vehicles[actor_id]
return True
return False
def synchronize_vehicle(self, vehicle_id, transform, velocity):
"""
Updates vehicle state.
:param int vehicle_id: id of the vehicle to be updated.
:param carla.Transform transform: new vehicle transform (i.e., position and rotation).
:param carla.Vector3D velocity: new vehicle velocity.
:return: True if successfully updated. Otherwise, False.
"""
assert vehicle_id in self._simulator_vehicles
self._simulator_vehicles[vehicle_id] = Simulator_Veh_Data(
transform.location.x, transform.location.y, transform.location.z,
math.radians(transform.rotation.yaw), math.radians(transform.rotation.pitch),
math.sqrt(velocity.x**2 + velocity.y**2 + velocity.z**2), False, 0, 0)
return True
def _get_simulator_veh_data(self):
"""
Returns list of Simulator_Veh_Data structures ready to be sent to the driving simulator
interface.
"""
data = []
for i in range(1, self._max_simulator_vehicles + 1):
if i in self._simulator_vehicles:
data.append(self._simulator_vehicles[i])
else:
# Invalid Simulator_Veh_Data to set the position of simulator vehicles in vissim
# that are not yet in carla.
data.append(
Simulator_Veh_Data(float('inf'), float('inf'), float('inf'), 0.0, 0.0, 0.0,
False, 0, 0))
return data
def tick(self):
"""
Tick to vissim simulation.
"""
# Updating simulator vehicles data.
arr = (Simulator_Veh_Data * self._max_simulator_vehicles)(*self._get_simulator_veh_data())
self.ds_proxy.VISSIM_SetDriverVehicles(self._max_simulator_vehicles, byref(arr))
# Retrieving vissim traffic data.
num_vehicles = c_int(0)
traffic_data = POINTER(VISSIM_Veh_Data)()
self.ds_proxy.VISSIM_GetTrafficVehicles(byref(num_vehicles), byref(traffic_data))
vehicles = {}
for i in range(num_vehicles.value):
vehicle_data = traffic_data[i]
assert vehicle_data.VehicleID > self._max_simulator_vehicles
vehicles[vehicle_data.VehicleID] = VissimVehicle(
vehicle_data.VehicleID, vehicle_data.VehicleType, vehicle_data.ModelFileName,
vehicle_data.color,
[vehicle_data.Position_X, vehicle_data.Position_Y, vehicle_data.Position_Z],
[vehicle_data.Orient_Pitch, vehicle_data.Orient_Heading, 0.0], vehicle_data.Speed,
vehicle_data.TurningIndicator)
# Update data structures for the current time step.
active_vehicles = set(self._vissim_vehicles.keys())
current_vehicles = set(vehicles.keys())
self.spawned_vehicles = current_vehicles.difference(active_vehicles)
self.destroyed_vehicles = active_vehicles.difference(current_vehicles)
self._vissim_vehicles = vehicles
def close(self):
self.ds_proxy.VISSIM_Disconnect()