(3-8-01)速度控制算法:基于Carla的十字路口车的辆控制程序

Carla是一个用于自动驾驶研究的开源模拟器,本项目的主要功能是在Carla中的控制四轮车辆的速度。本项目实现了在Carla仿真环境中控制车辆的功能,包括使用油门和刹车进行速度控制,并展示了不同速度阶段的仿真过程。通过实现车辆控制系统和提供可视化结果,该项目为研究和测试车辆控制算法提供了基础框架。

在本项目中,文件multiple_vehicle_control.py是基于CARLA仿真平台的十字路口车辆控制程序,通过定义 类VehicleControl和 multiple_vehicle_control 函数,实现了对多辆车辆的纯追踪控制,包括速度控制、安全距离考虑、遵守交通灯等功能,通过CARLA提供的仿真环境模拟车辆在十字路口的行为。

实例3-10:基于Carla的车速控制系统(源码路径:codes\3\speed\Carla-Speed-Control

文件multiple_vehicle_control.py的具体是流程如下所示。

(1)定义一个名为 VehicleControl 的类,该类用于控制CARLA仿真环境中的车辆。该类的构造函数 __init__ 接收三个参数:env 表示CARLA环境,vehicle_config 表示车辆的配置信息,delta_seconds 表示仿真步长。车辆配置信息包括车辆的唯一标识符、行驶命令、轨迹、参考速度列表等。类的属性包括PI控制器和纯追踪模型的常数、存储状态空间值和速度信息的队列、离散步长等。还包括一些用于可视化的存储速度、节流阀和参考速度的列表。

# 颜色定义,用于调试
red = carla.Color(255, 0, 0)
green = carla.Color(0, 255, 0)
blue = carla.Color(47, 210, 231)
cyan = carla.Color(0, 255, 255)
yellow = carla.Color(255, 255, 0)
orange = carla.Color(255, 162, 0)
white = carla.Color(255, 255, 255)

class VehicleControl(object):
    def __init__(self, env, vehicle_config, delta_seconds):
        '''
        初始化方法

        Parameters
        ----------
        env : CARLA_ENV
            CARLA仿真环境的自定义类
        
        vehicle_config : ConfigObj
            车辆的配置文件,由交叉口的add_vehicle函数创建。
            包含车辆的轨迹和速度参考信息。配置文件还应指示该车辆是否应该行驶。

        delta_seconds : float
            两个相邻仿真步骤之间的时间。用于创建离散控制器

        Returns
        -------
        None.
        '''
        
        self.env = env
        self.vehicle_config = vehicle_config
        self.model_uniquename = self.vehicle_config["uniquename"]
        self.command = self.vehicle_config["command"]
        self.trajectory = self.vehicle_config["trajectory"]
        self.ref_speed_list = self.vehicle_config["ref_speed_list"]
        self.obey_traffic_lights = self.vehicle_config["obey_traffic_lights"]
        self.run = self.vehicle_config["run"]
        self.safety_distance = self.vehicle_config["safety_distance"]
        self.stop_choice = self.vehicle_config["stop_choice"]
        self.penetrate_distance = self.vehicle_config["penetrate_distance"]
        self.stop_ref_point = self.vehicle_config["stop_ref_point"]
        
        # 离散步长
        self.delta_seconds = delta_seconds
        
        # PI控制器常数
        self.KI = 0.02
        self.KP = 0.5
        
        # 纯追踪模型常数
        self.k = 0.1  # 前瞻的系数
        self.Lfc = 4.0  # 前瞻距离
        self.L = self.vehicle_config["bounding_box"].x  # 车辆轴距
        
        # 控制器所需的关键存储
        self.init_values = deque(maxlen=2)  # 系统状态空间值的存储队列
        self.ref_speeds = deque(maxlen=2)  # 参考/目标速度的存储队列
        self.curr_speeds = deque(maxlen=2)  # 车辆测得的速度的存储队列
        
        # 用于可视化参考速度、节流阀和测得速度的存储
        self.speed = []
        self.throttles = []
        self.reference_speed = []
    
        # 初始化存储的初始值,假设车辆从静止开始,没有初始速度或加速度
        self.init_values.append(0) 
        self.ref_speeds.append(0)
        self.curr_speeds.append(0)
    
        self.current_ref_speed = 0
        self.index = 0
        
        # 获取车辆的PI控制器
        self._get_PI_controller()
        
        # 启用绘制车辆轨迹的调试
        self.debug_vehicle = True
        self.vehicle_pose = deque(maxlen=2)
        
        # 指示车辆是否在红绿灯处停止
        self.blocked_by_light = False

(2)函数get_vehicle_transform的功能是获取车辆在3D环境中的变换矩阵。

def get_vehicle_transform(self):
    '''
    获取车辆的变换矩阵
    '''
    transform = self.env.get_transform_3d(self.model_uniquename)
    return transform

(3)函数_get_PI_controller(self)的功能是创建离散状态空间的PI(比例-积分)控制器,通过设置比例和积分常数,生成状态空间模型,用于控制车辆速度。    

def _get_PI_controller(self):

    '''

    创建一个离散状态空间PI控制器

    '''

    num_pi = [self.KP, self.KI] # PI控制器传递函数的分子(KP * s + KI)

    den_pi = [1.0, 0.01 * self.KI / self.KP] # PI控制器传递函数的分母(s + 0.01 * KI/KP)

    

    sys = control.tf(num_pi, den_pi) # 获取PI控制器的传递函数(由于分母有一个小项0.01 * KI/KP,实际上是一个滞后补偿器)

    sys = control.sample_system(sys, self.delta_seconds) # 将传递函数离散化(从连续的s域到离散的z域)

                                                        # 由于我们的仿真是离散的

    sys = control.tf2ss(sys) # 将传递函数转换为状态空间形式。

    self.sys = sys  # 为此车辆创建系统

(4)函数speed_control(self)的功能是基于参考速度和当前速度计算差值,将其作为PI控制器的输入,获取新的油门控制量,实现速度控制。    

def speed_control(self):
    '''
    获取参考速度、当前(测得的)速度和初始值
    使用差值 e = ref_speeds - curr_speeds 作为PI控制器的输入,得到新的节流阀
    
    Parameters
    ----------
    self.sys : control.ss 
        状态空间控制器 
    self.ref_speeds : list of float
        我们需要的目标速度
    self.curr_speeds : list of float
        当前速度
    self.init_values : the initial_values of the system
        系统的初始值。

    Returns
    -------
    throttle : float type
        节流阀的值。

    '''
    U0 = np.array(self.ref_speeds) - np.array(self.curr_speeds)
    _, y0, x0 = control.forced_response(self.sys, U=U0, X0=self.init_values[0]) 
    # y0是下一个值,x0是状态演化,详见 https://python-control.readthedocs.io/en/0.8.3/generated/control.forced_response.html#control.forced_response 
    self.init_values.append(x0[-1])
    throttle = y0[-1]
    return throttle

(5)函数get_target_index(self, location_2d, current_forward_speed, trajectory)的功能是根据当前车辆位置、速度和轨迹,获取车辆需要导航至的目标点索引,同时判断是否到达轨迹终点。

def get_target_index(self, location_2d, current_forward_speed, trajectory):
    '''
    获取车辆导航到的目标
    
    Parameters
    ----------
    location_2d : (x,y)
        车辆的当前位置。
    current_forward_speed : float
        车辆的当前速度。
    trajectory : numpy 2d array
        插值得到的路径点。

    Returns
    -------
    ind : TYPE
        描述。
    end_trajectory : TYPE
        描述。

    '''
    distance = np.sum((trajectory - location_2d) ** 2, axis=1) ** 0.5
    ind = np.argmin(distance)
    l0 = 0.0
    Lf = self.k * current_forward_speed + self.Lfc
    while Lf > l0 and (ind + 1) < len(trajectory):
        delta_d = sum((trajectory[ind + 1] - trajectory[ind]) ** 2) ** 0.5
        l0 += delta_d
        ind += 1
    if ind >= len(trajectory) - 1:
        end_trajectory = True
    else:
        end_trajectory = False
    return ind, end_trajectory

(6)函数pure_pursuit_control的功能是根据车辆当前位置、速度、轨迹和参考速度列表,计算并返回车辆的转向角、当前参考速度、目标索引以及是否接近目标。

def pure_pursuit_control(self, vehicle_pos_2d, current_forward_speed, trajectory, ref_speed_list, prev_index):
    '''
    控制车辆的航向角
    
    Parameters
    ----------
    vehicle_pos_2d : (location_2d, yaw)
        二维车辆位置和航向的元组。
        location_2d : (x, y),x和y均以米为单位
        yaw:偏航角 **注意** yaw以度为单位
    current_forward_speed : float
        车辆的当前速度。
    trajectory : numpy 2d array
        插值得到的路径点。
    ref_speed_list : list
        每个路径点对应的参考速度
    prev_index : int
        先前的索引

    Returns
    -------
    delta : float
        车辆的转向角。
    current_ref_speed : the reference speed
        描述。
    index : int
        目标的索引。
    end_trajectory : boolean
        是否已经足够接近目的地。

    '''
    location_2d, yaw = vehicle_pos_2d
    yaw = np.deg2rad(yaw) # 将角度转换为弧度
    index, end_trajectory = self.get_target_index(location_2d, current_forward_speed, trajectory)
    if prev_index >= index:
        index = prev_index
    if index < len(trajectory):
        tx = trajectory[index][0]
        ty = trajectory[index][1]
    else:
        tx = trajectory[-1][0]
        ty = trajectory[-1][1] 
    alpha = math.atan2(ty - location_2d[1], tx - location_2d[0]) - yaw
    if current_forward_speed < 0: #后退,在我们的情况下不应该发生
        alpha = math.pi - alpha
    Lf = self.k * current_forward_speed + self.Lfc
    delta = math.atan2(2.0 * self.L * math.sin(alpha) / Lf, 1.0)
    current_ref_speed = ref_speed_list[index]
    return delta, current_ref_speed, index, end_trajectory

未完待续

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
强化学习是一种机器学习方法,它通过试错来学习如何在特定环境中采取行动以最大化奖励。CARLA是一个开源的自动驾驶仿真平台,可以用于测试和评估自动驾驶算法。下面是使用强化学习在CARLA中实现自动驾驶的一些步骤: 1. 安装CARLAPython API ```shell # 安装CARLA wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/CARLA_0.9.11.tar.gz tar -xvf CARLA_0.9.11.tar.gz # 安装Python API pip install pygame numpy networkx scipy matplotlib git clone https://github.com/carla-simulator/carla.git cd carla/PythonAPI/carla/dist easy_install carla-0.9.11-py3.7-linux-x86_64.egg ``` 2. 创建CARLA环境 ```python import carla # 连接到CARLA服务器 client = carla.Client('localhost', 2000) client.set_timeout(10.0) # 获取CARLA世界 world = client.get_world() # 设置天气和时间 weather = carla.WeatherParameters(cloudiness=10.0, precipitation=10.0, sun_altitude_angle=70.0) world.set_weather(weather) world.set_sun_position(carla.Location(x=0.0, y=0.0, z=0.0)) # 创建车辆和摄像头 blueprint_library = world.get_blueprint_library() vehicle_bp = blueprint_library.filter('vehicle.tesla.model3')[0] spawn_point = carla.Transform(carla.Location(x=50.0, y=0.0, z=2.0), carla.Rotation(yaw=180.0)) vehicle = world.spawn_actor(vehicle_bp, spawn_point) 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=vehicle) ``` 3. 实现强化学习算法 这里我们以Deep Q-Network (DQN)为例,使用Keras实现神经网络。 ```python import keras from keras.models import Sequential from keras.layers import Dense, Flatten from keras.optimizers import Adam class DQNAgent: def __init__(self, state_size, action_size): self.state_size = state_size self.action_size = action_size self.memory = deque(maxlen=2000) self.gamma = 0.95 self.epsilon = 1.0 self.epsilon_min = 0.01 self.epsilon_decay = 0.995 self.learning_rate = 0.001 self.model = self._build_model() def _build_model(self): model = Sequential() model.add(Flatten(input_shape=(1,) + self.state_size)) model.add(Dense(24, activation='relu')) model.add(Dense(24, activation='relu')) model.add(Dense(self.action_size, activation='linear')) model.compile(loss='mse', optimizer=Adam(lr=self.learning_rate)) return model def remember(self, state, action, reward, next_state, done): self.memory.append((state, action, reward, next_state, done)) def act(self, state): if np.random.rand() <= self.epsilon: return random.randrange(self.action_size) act_values = self.model.predict(state) return np.argmax(act_values[0]) def replay(self, batch_size): minibatch = random.sample(self.memory, batch_size) for state, action, reward, next_state, done in minibatch: target = reward if not done: target = (reward + self.gamma * np.amax(self.model.predict(next_state)[0])) target_f = self.model.predict(state) target_f[0][action] = target self.model.fit(state, target_f, epochs=1, verbose=0) if self.epsilon > self.epsilon_min: self.epsilon *= self.epsilon_decay # 初始化DQNAgent state_size = (800, 600, 3) action_size = 3 agent = DQNAgent(state_size, action_size) # 训练DQNAgent for e in range(EPISODES): state = env.reset() state = np.reshape(state, [1, 1] + list(state_size)) for time in range(500): action = agent.act(state) next_state, reward, done, _ = env.step(action) next_state = np.reshape(next_state, [1, 1] + list(state_size)) agent.remember(state, action, reward, next_state, done) state = next_state if done: break if len(agent.memory) > batch_size: agent.replay(batch_size) ``` 4. 运行CARLA仿真 ```shell ./CarlaUE4.sh -windowed -carla-server -benchmark -fps=20 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值