路线规划

此示例在 Carla 模拟环境中,使用 RRT 路径规划和 PID 控制进行自动驾驶车辆的路径跟踪, RRT 算法能够在复杂的环境中快速找到从起点到终点的路径,同时避开障碍物; PID 控制器根据路径的曲率和车辆的位置调整油门、刹车和方向盘,确保车辆能够按照规划的路径行驶。

环境要求

导入CARLA模块

​ 导入CARLA模块,并添加必要的路径。

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])
    import carla
except IndexError:
    pass

RednerObject 类

该类主要用于报错和传递 pygame 对象

class RenderObject(object):
    def __init__(self, width, height):
        init_image = np.random.randint(0, 255, (height, width, 3), dtype='uint8')
        self.surface = pygame.surfarray.make_surface(init_image.swapaxes(0, 1))

pygame_callback 函数

​ 相机传感器回调函数,将相机原始数据转换为2D RGB图像,并应用于 Pygame

def pygame_callback(data, obj):
    img = np.reshape(np.copy(data.raw_data), (data.height, data.width, 4))
    img = img[:, :, :3]
    img = img[:, :, ::-1]
    obj.surface = pygame.surfarray.make_surface(img.swapaxes(0, 1))

CARLA_world 类

该类用于连接 Carla 服务器,设置同步模式,并管理车辆和相机。

class CARLA_world:
    def __init__(self):
        self.client = carla.Client('localhost', 2000)
        self.client.set_timeout(120.0)
        self.carla_world = self.client.get_world()
        self.map = self.carla_world.get_map()

        print("WORLD READY")

        settings = self.carla_world.get_settings()
        settings.synchronous_mode = True
        settings.fixed_delta_seconds = 0.02
        self.carla_world.apply_settings(settings)

        self.spectator = self.carla_world.get_spectator()

        self.vehicles = []
        self.ego_vehicle = None

主程序

初始化 Carla 世界对象

创建 Carla 世界实例,设置车辆的生成点,生成自车和障碍车辆。

CARLA_world = CARLA_world()
spawn_points = CARLA_world.map.get_spawn_points()
target_speed = 3.0
v_obs = 3.0
spawn_point1 = carla.Transform(carla.Location(x=428, y=-51.9, z=0.3), carla.Rotation(yaw=89))
blueprint_library = CARLA_world.carla_world.get_blueprint_library()
bp1 = blueprint_library.filter("model3")[0]
vehicle1 = CARLA_world.carla_world.spawn_actor(bp1, spawn_point1)
CARLA_world.vehicles.append(vehicle1)

spawn_point3 = carla.Transform(carla.Location(x=404, y=-14, z=0.3), carla.Rotation(yaw=0))
bp3 = blueprint_library.filter("model3")[0]
CARLA_world.ego_vehicle = CARLA_world.carla_world.spawn_actor(bp3, spawn_point3)

初始化相机

​ 将相机附加到自车上,并设置回调函数处理相机图像。

camera_init_trans = carla.Transform(carla.Location(x=-10, y=-4, z=3), carla.Rotation(pitch=-20))
camera_bp = CARLA_world.carla_world.get_blueprint_library().find('sensor.camera.rgb')
camera_bp.set_attribute('image_size_x', str(VIEW_WIDTH))
camera_bp.set_attribute('image_size_y', str(VIEW_HEIGHT))
camera_bp.set_attribute('fov', str(VIEW_FOV))
camera = CARLA_world.carla_world.spawn_actor(camera_bp, camera_init_trans, attach_to=CARLA_world.ego_vehicle)
renderObject = RenderObject(VIEW_WIDTH, VIEW_HEIGHT)
camera.listen(lambda image: pygame_callback(image, renderObject))

初始化 Pygame

​ 初始化Pygame窗口,并设置相应标题。

pygame.init()
gameDisplay = pygame.display.set_mode((VIEW_WIDTH, VIEW_HEIGHT), pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption("Camera View")

轨迹规划和控制

​ 使用RRT算法进行轨迹规划,并通过PID控制器进行车辆路径跟踪。

goal = CARLA_world.map.get_waypoint(carla.Location(x=444, y=-14), project_to_road=True)
CARLA_world.carla_world.tick()
trans = CARLA_world.vehicles[0].get_transform()
v_obs = 7.8
obstacles = [trans, v_obs]
RRT_planner = RRT_VO(CARLA_world, goal, obstacles)
RRT_planner.RRT_star(n_pts=1000)
path = RRT_planner.path

path_x = []
path_y = []
trans = CARLA_world.ego_vehicle.get_transform()
thetai = trans.rotation.yaw * math.pi / 180
final_theta = thetai

for i in range(len(path) - 1):
    if i == len(path) - 2:
        thetaf = final_theta
    else:
        x1, y1 = path[i + 1].x, path[i + 1].y
        x2, y2 = path[i + 2].x, path[i + 2].y
        thetaf = math.atan2((y2 - y1), (x2 - x1))

    primitive = motion_primitive(thetai, thetaf, path[i].x,
                                 path[i + 1].x, path[i].y,
                                 path[i + 1].y)
    primitive.cubic_T_Matrix()
    primitive.trajectory()

    pos_x, pos_y = primitive.get_path(0.05)
    path_x += pos_x
    path_y += pos_y
    thetai = thetaf

循环移动

​ 在 Pygame 窗口中显示相机视角,并根据RRT规划的路径控制车辆移动。

controller = VehiclePIDController(CARLA_world.ego_vehicle, [1.0, 0.05, 0.1], [0.5, 0.05, 0.1])
controller_obs = VehiclePIDController(CARLA_world.vehicles[0], [1.0, 0.05, 0.1], [0.5, 0.05, 0.1])
actual_x = []
actual_y = []
ti = time.time()
for i in range(len(path_x) - 1):
    trans = CARLA_world.ego_vehicle.get_transform()
    loc_x, loc_y = trans.location.x, trans.location.y
    w_x, w_y = path_x[i], path_y[i]
    w_x2, w_y2 = path_x[i + 1], path_y[i + 1]
    phi = math.atan2((w_y2 - w_y), (w_x2 - w_x))

    physics = CARLA_world.ego_vehicle.get_physics_control()
    wheels = physics.wheels
    wheel_F_x = (wheels[0].position.x + wheels[1].position.x) / 200
    wheel_F_y = (wheels[0].position.y + wheels[1].position.y) / 200

    while ((wheel_F_x - w_x2) ** 2 + (wheel_F_y - w_y2) ** 2) ** 0.5 >= 0.5:
        control = controller.run_step(RRT_planner.v * 3.6 / 3)
        control_obs = controller_obs.run_step(v_obs * 3.6 / 3)

        p1 = np.array([w_x, w_y])
        p2 = np.array([w_x2, w_y2])
        p3 = np.array([wheel_F_x, wheel_F_y])
        trans = CARLA_world.ego_vehicle.get_transform()
        yaw = trans.rotation.yaw
        phi = math.atan2((w_y2 - w_y), (w_x2 - w_x)) - yaw * (math.pi / 180)
        d = np.cross(p2 - p1, p3 - p1) / np.linalg.norm(p2 - p1)

        kp = 3
        ks = 0.2
        Vel = CARLA_world.ego_vehicle.get_velocity()
        v = math.sqrt(Vel.x ** 2 + Vel.y ** 2)
        control.steer = (-math.atan2(kp * d,

​ 轨迹如下:图中蓝色的曲线表示车辆从起点到终点的行驶路径。从图中可以看出,车辆先是沿着x轴向右行驶,然后检测到障碍物后开始向左下方转弯,最后到达终点。