carla/Co-Simulation/Sumo/sumo_integration/carla_simulation.py

185 lines
6.6 KiB
Python
Raw Normal View History

2020-03-05 01:55:33 +08:00
#!/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>.
2020-03-05 23:49:16 +08:00
""" This module is responsible for the management of the carla simulation. """
# ==================================================================================================
# -- imports ---------------------------------------------------------------------------------------
# ==================================================================================================
2020-03-05 01:55:33 +08:00
import logging
2020-03-05 23:49:16 +08:00
import carla # pylint: disable=import-error
2020-03-05 01:55:33 +08:00
2020-03-05 23:49:16 +08:00
from .constants import INVALID_ACTOR_ID, SPAWN_OFFSET_Z
2020-03-05 01:55:33 +08:00
2020-03-05 23:49:16 +08:00
# ==================================================================================================
# -- carla simulation ------------------------------------------------------------------------------
# ==================================================================================================
2020-03-05 01:55:33 +08:00
class CarlaSimulation(object):
2020-03-05 23:49:16 +08:00
"""
CarlaSimulation is responsible for the management of the carla simulation.
"""
2020-04-10 00:45:34 +08:00
def __init__(self, host, port, step_length):
2020-03-05 23:49:16 +08:00
self.client = carla.Client(host, port)
2020-03-05 01:55:33 +08:00
self.client.set_timeout(2.0)
self.world = self.client.get_world()
self.blueprint_library = self.world.get_blueprint_library()
2020-04-10 23:50:33 +08:00
self.step_length = step_length
2020-03-05 01:55:33 +08:00
# The following sets contain updated information for the current frame.
self._active_actors = set()
self.spawned_actors = set()
self.destroyed_actors = set()
2020-04-08 21:06:57 +08:00
# Set traffic lights.
self._tls = {} # {landmark_id: traffic_ligth_actor}
2020-04-10 16:11:11 +08:00
tmp_map = self.world.get_map()
for landmark in tmp_map.get_all_landmarks_of_type('1000001'):
if landmark.id != '':
traffic_ligth = self.world.get_traffic_light(landmark)
if traffic_ligth is not None:
self._tls[landmark.id] = traffic_ligth
else:
logging.warning('Landmark %s is not linked to any traffic light', landmark.id)
2020-04-08 21:06:57 +08:00
2020-03-05 01:55:33 +08:00
def get_actor(self, actor_id):
2020-03-05 23:49:16 +08:00
"""
Accessor for carla actor.
"""
2020-03-05 01:55:33 +08:00
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):
2020-03-05 23:49:16 +08:00
"""
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
2020-04-08 21:06:57 +08:00
@property
def traffic_light_ids(self):
return set(self._tls.keys())
def get_traffic_light_state(self, landmark_id):
"""
Accessor for traffic light state.
If the traffic ligth does not exist, returns None.
"""
if landmark_id not in self._tls:
return None
return self._tls[landmark_id].state
def switch_off_traffic_lights(self):
"""
Switch off all traffic lights.
"""
for actor in self.world.get_actors():
if actor.type_id == 'traffic.traffic_light':
actor.freeze(True)
# We set the traffic light to 'green' because 'off' state sets the traffic light to
# 'red'.
actor.set_state(carla.TrafficLightState.Green)
2020-03-05 01:55:33 +08:00
def spawn_actor(self, blueprint, transform):
2020-03-05 23:49:16 +08:00
"""
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.
2020-03-05 01:55:33 +08:00
"""
2020-04-08 21:06:57 +08:00
transform = carla.Transform(transform.location + carla.Location(0, 0, SPAWN_OFFSET_Z),
transform.rotation)
2020-03-05 01:55:33 +08:00
batch = [
2020-04-08 21:06:57 +08:00
carla.command.SpawnActor(blueprint, transform).then(
carla.command.SetSimulatePhysics(carla.command.FutureActor, False))
2020-03-05 01:55:33 +08:00
]
response = self.client.apply_batch_sync(batch, False)[0]
2020-03-05 01:55:33 +08:00
if response.error:
2020-03-05 23:49:16 +08:00
logging.error('Spawn carla actor failed. %s', response.error)
2020-03-05 01:55:33 +08:00
return INVALID_ACTOR_ID
2020-03-05 23:49:16 +08:00
return response.actor_id
2020-03-05 01:55:33 +08:00
def destroy_actor(self, actor_id):
2020-03-05 23:49:16 +08:00
"""
Destroys the given actor.
"""
2020-03-05 01:55:33 +08:00
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):
2020-03-05 23:49:16 +08:00
"""
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.
"""
2020-03-05 01:55:33 +08:00
vehicle = self.world.get_actor(vehicle_id)
if vehicle is None:
return False
vehicle.set_transform(transform)
2020-04-10 00:45:34 +08:00
if lights is not None:
2020-03-05 01:55:33 +08:00
vehicle.set_light_state(carla.VehicleLightState(lights))
2020-03-05 23:49:16 +08:00
return True
2020-03-05 01:55:33 +08:00
2020-04-08 21:06:57 +08:00
def synchronize_traffic_light(self, landmark_id, state):
"""
Updates traffic light state.
:param landmark_id: id of the landmark to be updated.
:param state: new traffic light state.
:return: True if successfully updated. Otherwise, False.
"""
if not landmark_id in self._tls:
logging.warning('Landmark %s not found in carla', landmark_id)
return False
traffic_light = self._tls[landmark_id]
traffic_light.set_state(state)
return True
2020-03-05 01:55:33 +08:00
def tick(self):
2020-03-05 23:49:16 +08:00
"""
Tick to carla simulation.
"""
2020-03-05 01:55:33 +08:00
self.world.tick()
# Update data structures for the current frame.
2020-04-08 21:06:57 +08:00
current_actors = set(
[vehicle.id for vehicle in self.world.get_actors().filter('vehicle.*')])
2020-03-05 01:55:33 +08:00
self.spawned_actors = current_actors.difference(self._active_actors)
self.destroyed_actors = self._active_actors.difference(current_actors)
2020-03-05 23:49:16 +08:00
self._active_actors = current_actors
2020-04-08 21:06:57 +08:00
def close(self):
"""
Closes carla client.
"""
for actor in self.world.get_actors():
if actor.type_id == 'traffic.traffic_light':
actor.freeze(False)