0

As group project at uni we have been assigned a project, in which we have to implement the same simple traffic scenario, an ego vehicle making a U-turn in some light traffic, using both SUMO and CARLA simulators independently then as a co-simulation, in which every vehicle are controlled by SUMO except the ego vehicle, which is controlled by CARLA. The main objective would be to log some performance metrics to compare the different simulations. We managed to make the independent simulations, but have trouble making doing the co-simulation.

We first made a scenario descriptor function to initialize both simulation, as follows:

class Actor:
    sumo_index = 0

    def __init__(self, pos: tuple, rot: tuple, destionation_pos: tuple, type: str, control: tuple, sensor: bool = False,
                 sens_rel_loc: tuple = None):
        self.pos = pos
        self.destination_pos = destionation_pos
        self.rot = rot
        self.type = type
        self.sumo_id = f'vehicle{Actor.sumo_index}'
        Actor.sumo_index += 1
        self.control = control
        self.sensor = sensor
        self.sens_rel_loc = sens_rel_loc

    def __str__(self):
        print(
            f'Actor type: {self.type}\n '
            f'Actor position: x:{self.pos[0]},y:{self.pos[1]},z:{self.pos[2]}\n '
            f'Actor rotation: pitch:{self.rot[0]},yaw:{self.rot[1]},roll:{self.rot[2]}\n '
            f'Actor control: throttle:{self.control[0]},steer:{self.control[1]},brake:{self.control[2]}')


class ScenarioDescription:
    ego_actor = Actor(
        (-426.5, 30.4, 0.5),
        (0, 0, 0),
        (-438.57, 10.17, -0.00),
        'vehicle.mercedes.coupe_2020',
        (1.0, 0.0, 0.0),
        sensor=True,
        sens_rel_loc=(-5.7, 0, 3.7))
    other_actors = [
        Actor(
            (-426.4, 26.9, 0.5),
            (0, 0, 0),
            (-326.72, 26.91, 0.22),
            'vehicle.audi.a2',
            (0.6, 0.0, 0.0)),
        Actor(
            (-447.2, 37.4, 0.5),
            (0, 0, 0),
            (-220.10, 37.37, 3.68),
            'vehicle.tesla.model3',
            (1.0, 0.0, 0.0)),
        Actor(
            (-298.2, 5.4, 3),
            (0, 180, 0),
            (-446.78, 6.99, -0.02),
            'vehicle.audi.etron',
            (1.0, 0.0, 0.0)),
        Actor(
            (-315.9, 12.7, 3),
            (0, 180, 0),
            (-464.65, 14.54, -0.01),
            'vehicle.tesla.cybertruck',
            (1.0, 0.0, 0.0)),
        Actor(
            (-347.7, 16.1, 3),
            (0, 180, 0),
            (-470.86, 17.06, -0.03),
            'vehicle.dodge.charger_police',
            (1.0, 0.0, 0.0)),
        Actor(
            (-384.5, -8.5, 3),
            (0, 90, 0),
            (-384.50, -8.50, -0.00),
            'vehicle.ford.mustang',
            (0.0, 0.0, 0.0)),
        Actor(
            (-380.7, -7.4, 3),
            (0, 90, 0),
            (-380.70, -7.40, 0.00),
            'vehicle.audi.tt',
            (0.0, 0.0, 0.0)),
    ]
    all_actor = [ego_actor]
    all_actor.extend(other_actors)

def conv2sumoLoc(loc: tuple) -> tuple:
    sumo_loc = (loc[0] + 503.02, -loc[1] + 423.76)
    return sumo_loc

Then we did the SUMO and CARLA:

SUMO

from __future__ import absolute_import
from __future__ import print_function

import os
import sys

from scenario_descriptor import ScenarioDescription as sc
from scenario_descriptor import conv2sumoLoc

# we need to import python modules from the $SUMO_HOME/tools directory
if 'SUMO_HOME' in os.environ:
    tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
    sys.path.append(tools)
else:
    sys.exit("please declare environment variable 'SUMO_HOME'")

from sumolib import checkBinary  # noqa
import traci  # noqa

def run():
    step = 0
    vehic_num = 0
    start_edge_ego, _, start_lane_ego = traci.simulation.convertRoad(*conv2sumoLoc(sc.ego_actor.pos))
    des_edge_ego, _, des_lane_ego = traci.simulation.convertRoad(*conv2sumoLoc(sc.ego_actor.destination_pos))
    traci.route.add(f'trip{vehic_num}', [f'{start_edge_ego}', f'{des_edge_ego}'])
    traci.vehicle.add(sc.ego_actor.sumo_id, f'trip{vehic_num}', typeID=sc.ego_actor.type.split('_')[0])
    traci.vehicle.moveToXY(sc.ego_actor.sumo_id, f'{start_edge_ego}', f'{start_lane_ego}',
                           *conv2sumoLoc(sc.ego_actor.pos), keepRoute=1)
    vehic_num += 1
    for actor in sc.other_actors:
        start_edge_actor, _, start_lane_actor = traci.simulation.convertRoad(*conv2sumoLoc(actor.pos))
        des_edge_actor, _, des_lane_actor = traci.simulation.convertRoad(*conv2sumoLoc(actor.destination_pos))
        traci.route.add(f'trip{vehic_num}', [f'{start_edge_actor}', f'{des_edge_actor}'])
        traci.vehicle.add(actor.sumo_id, f'trip{vehic_num}', typeID=actor.type)
        traci.vehicle.moveToXY(actor.sumo_id, f'{start_edge_actor}', f'{start_lane_actor}',
                               *conv2sumoLoc(actor.pos), keepRoute=1)
        vehic_num += 1
    while step < 1000:
        traci.simulationStep()
        step += 1
    traci.close()

if __name__ == '__main__':
    sumoBinary = checkBinary('sumo-gui')

    traci.start([sumoBinary, '-c', 'D:\Carla_bullshit\WindowsNoEditor\Co-Simulation\Sumo\examples\Town04.sumocfg',
                 '--step-length', '0.023'])
    run()

CARLA

import os
import time

import carla
import numpy as np
import pandas as pd
import pygame

from scenario_descriptor import ScenarioDescription as sc

CAMERA_WIDTH = 1280
CAMERA_HEIGHT = 720

# Pygame Setup
pygame.init()
screen = pygame.display.set_mode((CAMERA_WIDTH, CAMERA_HEIGHT))

actor_list = []
metrics_df = pd.DataFrame(
    columns=['actor_type', 'sumo_id', 'velocity', 'travelled_distance', 'throttle', 'steer', 'brake', 'acceleration',
             'acc_x', 'acc_y', 'loc_x', 'loc_y', 'heading', 'time_step'])


def visualize_image(image):
    image.convert(carla.ColorConverter.Raw)
    array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8"))
    array = np.reshape(array, (image.height, image.width, 4))
    array = array[:, :, :3]
    array = array[:, :, ::-1]
    surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
    screen.blit(surface, (0, 0))


def log_metrics(path: str = None, last_tick = False):
    global metrics_df
    if path is None:
        path = os.getcwd()
    path = os.path.join(path, 'logs')
    if not os.path.exists(path):
        os.mkdir(path)
    filepath = os.path.join(path, f'logged_metrics_{time.time()}.csv')
    for ac in actor_list:
        sc_actor = [sc_ac for sc_ac in sc.all_actor if sc_ac.type == ac.type_id][0]
        actor_type = ac.type_id
        sumo_id = sc_actor.sumo_id
        vel = ac.get_velocity().length()
        time_step = world.get_snapshot().timestamp.delta_seconds
        travelled_dis = vel * time_step
        try:
            type_df = metrics_df.loc[metrics_df['actor_type'] == ac.type_id]
            travelled_dis = travelled_dis + type_df.iloc[-1,3]
        except IndexError:
            pass
        control = ac.get_control()
        throttle = control.throttle
        steer = control.steer
        brake = control.brake
        acc_x = ac.get_acceleration().x
        acc_y = ac.get_acceleration().y
        acceleration = (acc_x ** 2 + acc_y ** 2) ** (1 / 2)
        loc_x = ac.get_location().x
        loc_y = ac.get_location().y
        heading = ac.get_transform().rotation.yaw
        new_row = {'actor_type': actor_type, 'sumo_id': sumo_id, 'velocity': vel, 'travelled_distance': travelled_dis,
                   'throttle': throttle, 'steer': steer, 'brake': brake, 'acceleration': acceleration, 'acc_x': acc_x,
                   'acc_y': acc_y,'loc_x':loc_x,'loc_y':loc_y,'heading':heading,'time_step':time_step }
        metrics_df = metrics_df.append(new_row,ignore_index=True)

        if last_tick:
            metrics_df.to_csv(filepath,index=False)

try:
    # Client
    client = carla.Client('localhost', 2000)
    client.set_timeout(10.0)
    client.load_world('Town04')

    # World
    world = client.get_world()
    default_settings = world.get_settings()
    settings = world.get_settings()
    settings.synchronous_mode = True
    settings.fixed_delta_seconds = 0.023
    world.apply_settings(settings)
    world.set_weather(carla.WeatherParameters.ClearNoon)
    blueprint_library = world.get_blueprint_library()

    # Ego vehicle with camera attached to it's back

    vehicle_bp = blueprint_library.find(sc.ego_actor.type)
    camera_bp = blueprint_library.find('sensor.camera.rgb')
    camera_bp.set_attribute('image_size_x', str(CAMERA_WIDTH))
    camera_bp.set_attribute('image_size_y', str(CAMERA_HEIGHT))
    ego_vehicle_location = carla.Transform(carla.Location(*sc.ego_actor.pos), carla.Rotation(*sc.ego_actor.rot))
    ego_vehicle = world.try_spawn_actor(vehicle_bp, ego_vehicle_location)
    ego_vehicle.apply_control(carla.VehicleControl(*sc.ego_actor.control))
    camera_relative_loc = carla.Transform(carla.Location(*sc.ego_actor.sens_rel_loc), carla.Rotation(pitch=-15))
    camera = world.spawn_actor(camera_bp, camera_relative_loc, attach_to=ego_vehicle)
    camera.listen(lambda data: visualize_image(data))
    actor_list.append(ego_vehicle)

    for actor in sc.other_actors:
        vehicle_bp = blueprint_library.find(actor.type)
        vehicle_location = carla.Transform(carla.Location(*actor.pos), carla.Rotation(*actor.rot))
        vehicle = world.try_spawn_actor(vehicle_bp, vehicle_location)
        vehicle.apply_control(carla.VehicleControl(*actor.control))
        actor_list.append(vehicle)

    world.tick()

    # Spectator
    spectator = world.get_spectator()
    spectator_location = carla.Transform(
        carla.Location(x=-445.9, y=24.23, z=44.5), carla.Rotation(pitch=-47.0, yaw=0.0, roll=0.0))
    spectator.set_transform(spectator_location)

    running = True
    screen.fill((0, 0, 0))
    pygame.display.flip()

    distance = 0.0
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        world.tick()
        current_location = ego_vehicle.get_transform().location
        distance += ego_vehicle_location.location.distance(current_location)
        ego_vehicle_location.location = current_location

        # set Traffic Lights
        actors = world.get_actors().filter('traffic.traffic_light')
        for actor in actors:
            state = carla.TrafficLightState.Red
            light_dis = actor.get_location().distance(current_location)
            if light_dis < 55:
                state = carla.TrafficLightState.Yellow
            if light_dis < 45:
                state = carla.TrafficLightState.Green
            actor.set_state(state)

        if distance > 20:
            ego_vehicle.apply_control(carla.VehicleControl(brake=0.2, steer=0.0))
            [a for a in actor_list if a.type_id == 'vehicle.audi.a2'][0].apply_control(
                carla.VehicleControl(throttle=1.0, steer=0.0))
        if distance > 34:
            ego_vehicle.apply_control(carla.VehicleControl(throttle=1.0, steer=-0.3))
        if distance > 67:
            ego_vehicle.apply_control(carla.VehicleControl(throttle=4.0, steer=0.0))
        if distance > 83:
            ego_vehicle.apply_control(carla.VehicleControl(throttle=1.0, steer=0.07))
        if distance > 87:
            ego_vehicle.apply_control(carla.VehicleControl(throttle=1.0, steer=0.0))
        pygame.display.flip()
        log_metrics(last_tick=not running)

finally:
    world.apply_settings(default_settings)
    world.tick()
    for actor in actor_list:
        actor.destroy()
    camera.destroy()
    pygame.quit()

Both work just fine, but we have no clue how to stitch them together to make the co-simulation, note that we had no lectures nor practice on the software to teach us how to use them so we were figuring out as we went. Unfortunately we are now stuck, please help us.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • You are aware of this: https://carla.readthedocs.io/en/latest/adv_sumo/ ? – Michael Jun 04 '23 at 15:40
  • No, I did not found the documentation page provided by CARLA on the co-simulation, in like 5 seconds, for a matter of fact never heard of it... Like, come on, is this really a serious question? – Kristof Papp Jun 05 '23 at 12:07
  • I did not want to offend you but there is a whole bunch of scripts referred to by the docs doing the Co-Simulation e.g. https://github.com/carla-simulator/carla/blob/master/Co-Simulation/Sumo/run_synchronization.py and you did not even mention that in your question. – Michael Jun 06 '23 at 06:22

0 Answers0