137 lines
4.8 KiB
Python
137 lines
4.8 KiB
Python
#!/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, 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)
|
|
|
|
# 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()
|
|
except RuntimeError:
|
|
return None
|
|
|
|
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, 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, True)[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, 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 lights is not None and self.args.sync_vehicle_lights:
|
|
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
|