carla-simulator / carla

Open-source simulator for autonomous driving research.
http://carla.org
MIT License
10.84k stars 3.49k forks source link

Can not run CARLA Simulattor while running the following script for improvised traffic manager #7761

Open mev5644 opened 1 month ago

mev5644 commented 1 month ago

Version : 9.0.14 OS: Windows Problem: The main problem is when I am trying to run my code, CARLA is crashing and it is not showing any results which I wanted to see.

Expect to happen: I am expecting to see the result of my script which I am trying to simulate for running the traffic light states based on traffic density near the traffic lights. For example, if no of vehicles are more than thresold value (6 or more cars) then the traffic lights gould turn green for a specified time duration of 10 seconds to optimize the traffic flow. In simple terms, I am overriding traffic manager by working according to traffic density near to the traffic lights.

Any help would be greatful!!

Below is my whole script:

import carla
import random
import time

# Connect to the client and retrieve the world object
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)  # Set a timeout for client commands
world = client.get_world()

# Set up the simulator in synchronous mode
settings = world.get_settings()
settings.synchronous_mode = True  # Enables synchronous mode
settings.fixed_delta_seconds = 0.02
world.apply_settings(settings)

# Set up the TM in synchronous mode
traffic_manager = client.get_trafficmanager()
traffic_manager.set_synchronous_mode(True)

# Set a seed so behaviour can be repeated if necessary
traffic_manager.set_random_device_seed(0)
random.seed(0)

actors = world.get_actors()

def get_traffic_density(traffic_light, radius=50):
    vehicles = world.get_actors().filter('vehicle.*')
    density = 0
    for vehicle in vehicles:
        if vehicle.get_location().distance(traffic_light.get_location()) < radius:
            density += 1
    return density

def set_traffic_light_state(traffic_light, state, duration):
    traffic_light.set_state(state)
    traffic_light.set_green_time(duration if state == carla.TrafficLightState.Green else 0)
    traffic_light.set_yellow_time(3.0)
    traffic_light.set_red_time(duration if state == carla.TrafficLightState.Red else 0)

def control_traffic_lights(traffic_lights, check_interval=20, density_threshold=5, green_duration=10):
    while True:
        world.tick()  # Advance the simulation by one tick
        for traffic_light in traffic_lights:
            density = get_traffic_density(traffic_light, radius=50)
            if density > density_threshold:
                set_traffic_light_state(traffic_light, carla.TrafficLightState.Green, green_duration)
                print(
                    f"Traffic light at {traffic_light.get_location()} turned green for {green_duration} seconds due "
                    f"to high traffic density.")
                time.sleep(green_duration + 3.0)  # Include the yellow light duration
                set_traffic_light_state(traffic_light, carla.TrafficLightState.Red, green_duration)
            else:
                set_traffic_light_state(traffic_light, carla.TrafficLightState.Red, green_duration)
                world.tick()
        time.sleep(check_interval)

traffic_lights = world.get_actors().filter('traffic.traffic_light')

# We will also set up the spectator
spectator = world.get_spectator()

spawn_points = world.get_map().get_spawn_points()

# Select some models from the blueprint library
models = ['dodge', 'audi', 'model3', 'mini', 'mustang', 'lincoln', 'prius', 'nissan', 'crown', 'impala']
blueprints = []
for vehicle in world.get_blueprint_library().filter('*vehicle*'):
    if any(model in vehicle.id for model in models):
        blueprints.append(vehicle)

# Assign vehicle counts to each route
route_vehicle_counts = [10, 10, 20, 10]
total_vehicles = sum(route_vehicle_counts)

# Set a max number of vehicles and prepare a list for those we spawn
max_vehicles = total_vehicles
max_vehicles = min([max_vehicles, len(spawn_points)])
vehicles = []

# Take a random sample of the spawn points and spawn some vehicles
for i, spawn_point in enumerate(random.sample(spawn_points, max_vehicles)):
    temp = world.try_spawn_actor(random.choice(blueprints), spawn_point)
    if temp is not None:
        vehicles.append(temp)

# Routes with their respective spawn points and indices
routes = [
    ([32], [129, 28, 137, 101, 57, 58, 154, 147]),
    ([149], [21, 105, 134, 52, 86, 120, 4, 121]),
    ([147], [72, 146, 126, 99, 108, 68, 24]),
    ([106], [85, 1, 104, 67, 140, 10, 143])
]

# Prepare route locations
route_locations = []
for spawn_point, indices in routes:
    route = [spawn_points[spawn_point[0]].location]
    for ind in indices:
        route.append(spawn_points[ind].location)
    route_locations.append(route)

# Assign vehicles to routes
assigned_vehicles = {
    0: [],  # Vehicles for route 1
    1: [],  # Vehicles for route 2
    2: [],  # Vehicles for route 3
    3: []  # Vehicles for route 4
}

vehicle_idx = 0
for route_idx, count in enumerate(route_vehicle_counts):
    for _ in range(count):
        if vehicle_idx < len(vehicles):
            assigned_vehicles[route_idx].append(vehicles[vehicle_idx])
            vehicle_idx += 1

# Assign routes to vehicles
for route_idx, vehicle_list in assigned_vehicles.items():
    for vehicle in vehicle_list:
        traffic_manager.set_path(vehicle, route_locations[route_idx])
        vehicle.set_autopilot(True)
        # Randomly set the probability that a vehicle will ignore traffic lights
        traffic_manager.ignore_lights_percentage(vehicle, random.randint(0, 50))

# Set delay to create gap between spawn times
spawn_delay = 20
counter = spawn_delay

try:
    control_traffic_lights(traffic_lights, check_interval=20, density_threshold=5, green_duration=10)
except KeyboardInterrupt:
    print("Traffic control interrupted")

Thanks for contributing to CARLA!

If you are reporting an issue, please use the following outline:

CARLA version: Platform/OS: Problem you have experienced: What you expected to happen: Steps to reproduce: Other information (documentation you consulted, workarounds you tried):

If you are asking a question please make sure your question was not asked before by searching among the existing issues and checking the CARLA forum https://github.com/carla-simulator/carla/discussions. Also make sure you have read ourdocumentation and FAQ at http://carla.readthedocs.io.

If your question is about creating content (assets, levels) you'll most likely have all the info you need in the Unreal Engine's documentation https://docs.unrealengine.com

Please, keep the threads focused and single-themed. Make them easy to find for everyone.

-->

joel-mb commented 1 month ago

Cloud you share the complete crash log (client and server side)? Your script is running without crashes in Ubuntu with CARLA 0.9.15.

Also, it seems there is a misunderstanding in your code with simulation time and real time when running in sync mode. Using time.sleep within you main loop does not affect to the simulation time. See me comments below:

def control_traffic_lights(traffic_lights, check_interval=20, density_threshold=5, green_duration=10):
    while True:
        world.tick()  # Advance the simulation by one tick
        for traffic_light in traffic_lights:
            density = get_traffic_density(traffic_light, radius=50)
            if density > density_threshold:
                set_traffic_light_state(traffic_light, carla.TrafficLightState.Green, green_duration)
                print(
                    f"Traffic light at {traffic_light.get_location()} turned green for {green_duration} seconds due "
                    f"to high traffic density.")

                # WARNING: This will freeze the server for the (green duration + 3.0) interval. The does not affect to the simulation time which will remain at the same time-step!!! 
                time.sleep(green_duration + 3.0)  # Include the yellow light duration
                set_traffic_light_state(traffic_light, carla.TrafficLightState.Red, green_duration)
            else:
                set_traffic_light_state(traffic_light, carla.TrafficLightState.Red, green_duration)
                world.tick()

        # WARNING: This will freeze the server for the check_interval duration. The does not affect to the simulation time which will remain at the same time-step!!! 
        time.sleep(check_interval)

For more information please check the documentation: https://carla.readthedocs.io/en/latest/adv_synchrony_timestep/

mev5644 commented 1 month ago

Thank you for your insights however, the problem is when I am running the script, it is running fine with outcomes of when the green light is changing and with location but the CARLA in the back is not opening then I have to shut down the engine by manually with task manager :>end task for CARLA to reopen again!

If it is running with Ubanu, please tell me whether it is functioning fine with overriding traffic light states according to traffic density. (I mean is it changing automatically when there are more vehicles)

Thank you again and I will share the screenshot where I am crashing the CARLA until tomorrow!

mev5644 commented 1 month ago

Screenshot (4)

This was the issue that I was telling you about! As you can see the script is running but the CARLA is crashing!

joel-mb commented 1 month ago

@mev5644 From what I can see your script is running as expected in your end. Please, read carefully the documentation about synchronous mode (https://carla.readthedocs.io/en/latest/adv_synchrony_timestep/) as your issue is just a misunderstanding of this concept.

On one side, the time.sleep(x) lines are not working as you think. During this time you are not calling world.tick() so the simulation time does not advance! This time.sleep(x) is just freezing the simulation completely for that interval. You should instead call world.tick() repeatedly until this time passes in simulation time. You can check the simulation time in different ways:

timestamp = world.get_snapshot().timestamp

timestamp.elapsed_seconds  # Simulated seconds elapsed since the beginning of the current episode. 
timestamp.delta_seconds  # Simulated seconds elapsed since the previous frame. In your case 0.02 as you fixed_delta_seconds is set to that value.

On the other side, when closing the script you are leaving the server in synchronous mode. As no client is ticking the world, the server freezes and therefore the process is set to Not responding by the OS. To avoid this you should reconfigure the server to asynchronous mode again before closing the script. This is done always for our scripts. For instance: https://github.com/carla-simulator/carla/blob/dev/PythonAPI/examples/manual_control.py#L1294

mev5644 commented 4 weeks ago

Hi Joel,

Thank you for your feedback and I updated some settings as you said however, I still need your help on the simulation as whenI am trying to run the script in Pycharm, it is running and showing at which locations the green lights are turning green according to the traffic density but on the other side, in CARLA environment the signals are not turning green and it is staying red as it is!!

I can share some screenshots for your reference.

I hope you will get my question correctly.. Simulation CARLA_Simulation

joel-mb commented 3 weeks ago

@mev5644 Take into account that the duration times your are setting in set_traffic_light_state are being overwritten by your main loop in control_traffic_lights. The issue probably comes due to your code changing traffic light states every tick based on your traffic density metric.

mev5644 commented 3 weeks ago

@joel-mb Understood, thanks. However, if I am not defining the set_traffic_light_state function in my script then it won't call the control_traffic_lights as it will not defined the function itself that is why I have to insert that function, however, my approach is to set the traffic light state to Green as sson as the traffic density is increasing and that is why I am slo separating 4 different routes using waypoints, which follows the vehicles and the traffic controller (My API) should work according to logic where traffic flow goes easily. That is also my thesis topic and I am really stuck into the situation as it is not working as I expected.

I did some changes in my script and can share with you as well, could you please help me to figure out what mistake which I am still not be able to find out, I will be greateful from your help and your support!

import carla
import random
import time
import pandas as pd

# Connect to the client and retrieve the world object
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)  # Set a timeout for client commands
client.reload_world()

world = client.get_world()

# Set up the simulator in synchronous mode
settings = world.get_settings()
settings.synchronous_mode = True  # Enables synchronous mode
# settings.fixed_delta_seconds = 0.01
world.apply_settings(settings)

# traffic_lights = world.get_actors().filter('traffic.traffic_light')

# Set up the TM in synchronous mode
traffic_manager = client.get_trafficmanager()
traffic_manager.set_synchronous_mode(True)

# # Set a seed so behaviour can be repeated if necessary
# traffic_manager.set_random_device_seed(0)
# random.seed(0)

actors = world.get_actors()

def get_traffic_lights(world):
    actors = world.get_actors()
    traffic_lights = actors.filter('traffic.traffic_light')
    return traffic_lights

def get_traffic_density(traffic_light, radius=50):
    vehicles = world.get_actors().filter('vehicle.*')
    density = 0
    for vehicle in vehicles:
        if vehicle.get_location().distance(traffic_light.get_location()) < radius:
            density += 1
    return density

# def savedata():
#     density_data = []
#     start_time = time.time()
#     for traffic_light in traffic_lights:
#         density = get_traffic_density(traffic_light)
#         elapse_time = time.time() - start_time
#         density_data.append({'Time': elapse_time, 'Traffic Light': traffic_light.id, 'Density': density})
#
#     df = pd.DataFrame(density_data)
#     df.to_excel('Traffic_light_density_data.xlsx', index=False)

# def set_traffic_light_state(traffic_light, state, green_duration=20):
#     # traffic_light.set_state(state)
#     # traffic_light.set_green_time(duration if state == carla.TrafficLightState.Green else 0)
#     # traffic_light.set_green_time(duration)
#     # traffic_light.set_yellow_time(3.0)
#     # traffic_light.set_red_time(duration if state == carla.TrafficLightState.Red else 0)
#     traffic_light.set_state(state)
#     if state == carla.TrafficLightState.Green:
#         traffic_light.set_green_time(green_duration)
#         traffic_light.set_yellow_time(3.0)
#         traffic_light.set_red_time(1.0)
#     else:
#         traffic_light.set_green_time(0)
#         traffic_light.set_yellow_time(0)
#         traffic_light.set_red_time(green_duration + 3.0)
def set_traffic_light_state(traffic_light, state, duration=20):
    traffic_light.set_state(state)
    # traffic_light.set_green_time(duration if state == carla.TrafficLightState.Green else 0)
    traffic_light.set_green_time(duration)

def savedata(density_data):
    df = pd.DataFrame(density_data)
    df.to_excel('Traffic_light_density_data.xlsx', index=False)

def control_traffic_lights(world, check_interval=20, density_threshold=5, green_duration=20):
    traffic_lights = get_traffic_lights(world)
    density_data = []
    start_time = time.time()

    try:
        while True:
            world.tick()
            for traffic_light in traffic_lights:
                density = get_traffic_density(traffic_light, radius=50)
                elapsed_time = time.time() - start_time
                density_data.append({'Time': elapsed_time, 'Traffic Light': traffic_light.id, 'Density': density})

                if density > density_threshold:
                    # if (traffic_light.)
                    set_traffic_light_state(traffic_light, carla.TrafficLightState.Green, green_duration)
                    print(
                        f"Traffic light at {traffic_light.get_location()} turned green for {green_duration} seconds due "
                        f"to high traffic density.")
                    # world.debug.draw_point(traffic_light.get_location(), 0.1)
                    # # time.sleep(green_duration + 1.0)  # Include the yellow light duration
                    # set_traffic_light_state(traffic_light, carla.TrafficLightState.Red, green_duration)
                else:
                    set_traffic_light_state(traffic_light, carla.TrafficLightState.Red, 10)
                    print(
                        f"Traffic light at {traffic_light.get_location()} turned red")
            # time.sleep(check_interval)
    except KeyboardInterrupt:
        print("Terminating the control loop")
        savedata(density_data)
        for i in vehicles:
            i.destroy()
            # world.tick()
        # time.sleep(0.02)
    # time.sleep(check_interval)

# We will also set up the spectator
spectator = world.get_spectator()

spawn_points = world.get_map().get_spawn_points()

# Select some models from the blueprint library
models = ['dodge', 'audi', 'model3', 'mini', 'mustang', 'lincoln', 'prius', 'nissan', 'crown', 'impala']
blueprints = []
# blueprints = world.get_blueprint_library().filter('vehicle.*')
for vehicle in world.get_blueprint_library().filter('vehicle.*'):
    if any(model in vehicle.id for model in models):
        blueprints.append(vehicle)

# Routes with their respective spawn points and indices
routes = [
    ([32], [129, 28, 137, 101, 57, 58, 154, 147]),
    ([149], [21, 105, 134, 52, 86, 120, 4, 121]),
    ([147], [72, 146, 126, 99, 108, 68, 24]),
    ([106], [85, 1, 104, 67, 140, 10, 143])
]

# Assign vehicle counts to each route
route_vehicle_counts = [30, 25, 20, 15]
total_vehicles = sum(route_vehicle_counts)

# Set a max number of vehicles and prepare a list for those we spawn
# max_vehicles = total_vehicles
max_vehicles = min([total_vehicles, len(spawn_points)])
vehicles = []

# Take a random sample of the spawn points and spawn some vehicles
for i, spawn_point in enumerate(random.sample(spawn_points, max_vehicles)):
    temp = world.try_spawn_actor(random.choice(blueprints), spawn_point)
    if temp is not None:
        vehicles.append(temp)

route_1 = []
route_2 = []
route_3 = []
route_4 = []

# Prepare route locations
# route_locations = []
count = 0
for spawn_point, indices in routes:
    if count == 0:
        route_1.append(spawn_points[spawn_point[0]].location)
        # route = [spawn_points[spawn_point[0]].location]
        for ind in indices:
            route_1.append(spawn_points[ind].location)
    if count == 1:
        route_2.append(spawn_points[spawn_point[0]].location)
        # route = [spawn_points[spawn_point[0]].location]
        for ind in indices:
            route_2.append(spawn_points[ind].location)
    if count == 2:
        route_3.append(spawn_points[spawn_point[0]].location)
        # route = [spawn_points[spawn_point[0]].location]
        for ind in indices:
            route_3.append(spawn_points[ind].location)
    if count == 3:
        route_4.append(spawn_points[spawn_point[0]].location)
        # route = [spawn_points[spawn_point[0]].location]
        for ind in indices:
            route_4.append(spawn_points[ind].location)
    count += 1
    # route_locations.append(route)

# Assign vehicles to routes
assigned_vehicles = {
    0: [],  # Vehicles for route 1
    1: [],  # Vehicles for route 2
    2: [],  # Vehicles for route 3
    3: []  # Vehicles for route 4
}

vehicle_idx = 0
for route_idx, count in enumerate(route_vehicle_counts):
    for _ in range(count):
        if vehicle_idx < len(vehicles):
            assigned_vehicles[route_idx].append(vehicles[vehicle_idx])
            vehicle_idx += 1
    vehicle_idx = 0

print(route_1)

# Assign routes to vehicles
for route_idx, vehicle_list in assigned_vehicles.items():
    if route_idx == 0:
        for vehicle in vehicle_list:
            traffic_manager.set_path(vehicle, route_1)
            vehicle.set_autopilot(True)
            # Randomly set the probability that a vehicle will ignore traffic lights
            # traffic_manager.ignore_lights_percentage(vehicle, random.randint(0, 50))
    elif route_idx == 1:
        for vehicle in vehicle_list:
            traffic_manager.set_path(vehicle, route_2)
            vehicle.set_autopilot(True)
    elif route_idx == 2:
        for vehicle in vehicle_list:
            traffic_manager.set_path(vehicle, route_3)
            vehicle.set_autopilot(True)
    elif route_idx == 3:
        for vehicle in vehicle_list:
            traffic_manager.set_path(vehicle, route_4)
            vehicle.set_autopilot(True)
# while True:
#     world.tick()  # Advance the simulation by one tick

# if __name__ == '__main__':
#     main()
# try:
#     control_traffic_lights(traffic_lights, density_threshold=5, green_duration=20)
# except KeyboardInterrupt:
#     for i in vehicles:
#         i.destroy()

control_traffic_lights(world)
joel-mb commented 2 weeks ago

@mev5644 From what I see your code has the same issue as before. In your control_traffic_lights method you are overwriting every tick the traffic light state set in the previous iteration. You should see traffic lights in green state but not for the duration you are setting. Your traffic lights will be set to red as soon as your density check threshold becomes false.

Moreover, I think your code is setting to green more than one traffic light for the same controller/intersection. I highly doubt this is intentional as this will probably produce problems in the traffic manager.

mev5644 commented 1 week ago

Yes, you are indeed right about this structure of my coding. But you see, my goal is to first install the traffic manager then it should call the traffic lights after that I am giving instructions to the traffic manager by overriding traffic signals to the green with predefined timing (let's say 20 seconds) to simulate the traffic manager functionality based on number of vehicles (density of vehicles) and for that reason I also add different routes using way points which vehicles are following on autopilot mode as you can see from my code.

However, if you have any small solution? or any other helping hand for me then I would be grateful for that.

Thank you again for your guidance.