Carla设置同步模式

1. 目的

默认情况下,Carla运行在异步模式下。服务器与客户端以各自的速度运行。当客户端请求到来时,服务器相应请求,处理结束之后继续运行,并不等待客户端处理完成服务器返回的数据。

存在的问题是,当保存相机传感器在Carla中获取的场景数据时,保存的数据有可能不连续,即缺帧。

在使用Carla获取训练数据时,设置Carla的同步模式很有必要。

When you want to start producing training data or deploying an agent within the simulation, it is advised that you use the synchronous mode since this will give you more control and predictability

2. 时间步长

在设置Carla同步模式前,需要先了解Carla中的时间步长。
在Carla中,定义时间步长为服务器状态变化需要的时间。时间步长分为可变时间步长与固定时间步长。
可变时间步长中,服务器每次状态变化所需要的时间都不固定。

#在代码中设置
settings = world.get_settings()
settings.fixed_delta_seconds = None # Set a variable time-step
world.apply_settings(settings)

#使用.py文件设置
cd PythonAPI/util && python3 config.py --delta-seconds 0

固定时间步长中,服务器每次状态变化需要的时间都相同,如果服务器实际所需的时间小于用户设置的时间步长,那么服务器将进入等待。

#在代码中设置
settings = world.get_settings()
settings.fixed_delta_seconds = 0.05
world.apply_settings(settings)

#使用.py文件设置
cd PythonAPI/util && python3 config.py --delta-seconds 0.05

设置固定时间步长为0.05,表示在1秒钟的时间内,服务器状态改变1/0.05=20次。

在同步模式下,Carla官方建议使用固定时间步长

Using the same time increment on each step is the best way to gather data from the simulation.

3.设置同步

Carla中,使用布尔值表示同步模式与异步模式,True表示同步模式,False表示异步模式。

settings = world.get_settings()
settings.synchronous_mode = True # 同步模式
settings.fixed_delta_seconds = 0.05 # 固定时间步长
world.apply_settings(settings)

设置异步模式只需要修改布尔值为False

#在代码中设置
settings = world.get_settings()
settings.synchronous_mode = False# Enables synchronous mode
settings.fixed_delta_seconds = None # 可变时间步长
world.apply_settings(settings)

#使用.py文件设置
cd PythonAPI/util && python3 config.py --no-sync # Disables synchronous mode

需要注意的是,无法通过上述.py文件将Carla设置为同步模式。
虽然Carla服务器可以连接多个客户端,但在连接的客户端中,只能有一个客户端设置Carla为同步模式。

4. 完整代码

代码来自 小飞自动驾驶系列分享[四]

import glob
import os
import sys
import random
import os
from queue import Queue
from queue import Empty
import numpy as np

try:
    sys.path.append(glob.glob('../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

import carla



def sensor_callback(sensor_data, sensor_queue, sensor_name):
    if 'lidar' in sensor_name:
         sensor_data.save_to_disk(os.path.join('../outputs/output_synchronized', '%06d.ply' % sensor_data.frame))
    if 'camera' in sensor_name:
         sensor_data.save_to_disk(os.path.join('../outputs/output_synchronized', '%06d.png' % sensor_data.frame))
    sensor_queue.put((sensor_data.frame, sensor_name))


def main():
    actor_list = []
    sensor_list = []
    try:
        # 连接Carla服务器
        client = carla.Client('localhost', 2000)
        client.set_timeout(10.0)
        world = client.get_world()
        
        blueprint_library = world.get_blueprint_library()

        # 设置同步模式
        original_settings = world.get_settings()
        settings = world.get_settings()
        settings.fixed_delta_seconds = 0.05
        settings.synchronous_mode = True
        world.apply_settings(settings)

        traffic_manager = client.get_trafficmanager()
        traffic_manager.set_synchronous_mode(True)

        sensor_queue = Queue()
        # 创建车辆
        ego_vehicle_bp = blueprint_library.find('vehicle.mercedes-benz.coupe')
        ego_vehicle_bp.set_attribute('color', '0, 0, 0')
        transform = random.choice(world.get_map().get_spawn_points())
        ego_vehicle = world.spawn_actor(ego_vehicle_bp, transform)
        ego_vehicle.set_autopilot(True)
        actor_list.append(ego_vehicle)

        # 指定传感器数据的保存目录
        output_path = '../outputs/output_synchronized'
        if not os.path.exists(output_path):
             os.makedirs(output_path)

        # 创建相机传感器
        camera_bp = blueprint_library.find('sensor.camera.rgb')
        camera_transform = carla.Transform(carla.Location(x=1.5, z=2.4))
        camera = world.spawn_actor(camera_bp, camera_transform, attach_to=ego_vehicle)
        # 注册回调函数
        camera.listen(lambda image: sensor_callback(image, sensor_queue, "camera"))
        sensor_list.append(camera)

        # 创建LiDAR传感器
        lidar_bp = blueprint_library.find('sensor.lidar.ray_cast')
        lidar_bp.set_attribute('channels', str(32))
        lidar_bp.set_attribute('points_per_second', str(90000))
        lidar_bp.set_attribute('rotation_frequency', str(40))
        lidar_bp.set_attribute('range', str(20))
        lidar_location = carla.Location(0, 0, 2)
        lidar_rotation = carla.Rotation(0, 0, 0)
        lidar_transform = carla.Transform(lidar_location, lidar_rotation)
        lidar = world.spawn_actor(lidar_bp, lidar_transform, attach_to=ego_vehicle)
        lidar.listen(
            lambda point_cloud: sensor_callback(point_cloud, sensor_queue, "lidar"))
        sensor_list.append(lidar)

        while True:
            world.tick()
            # 使用queue.get()函数,在数据处理完成之前,阻止程序的推进
            try:
                for i in range(0, len(sensor_list)):
                    s_frame = sensor_queue.get(True, 1.0)
                    print("    Frame: %d   Sensor: %s" % (s_frame[0], s_frame[1]))

            except Empty:
                print("   Some of the sensor information is missed")

    finally:
        # 恢复异步模式,否则退出之后Carla将卡死
        world.apply_settings(original_settings)
        print('destroying actors')
        client.apply_batch([carla.command.DestroyActor(x) for x in actor_list])
        for sensor in sensor_list:
            sensor.destroy()
        for actor in actor_list:
            actor.destroy()
        print('done.')


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print(' - Exited by user.')

参考:

Carla官方文档
小飞自动驾驶系列分享
史上最全Carla教程 |(四)同步模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值