基于Udacity模拟器的端到端自动驾驶决策

2023-10-29 08:59

本文主要是介绍基于Udacity模拟器的端到端自动驾驶决策,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 端到端自动驾驶决策

端到端自动驾驶决策的输入为车辆的感知信息,如摄像头信息,输出为车辆的前轮转角和摄像头等信息。
在这里插入图片描述
在这里插入图片描述
如上图所示,为英伟达公司的端到端自动驾驶决策框架,其CNN网络如下图所示,其中包括一个归一化层、5个卷积层和3个完全的全连接层。
在这里插入图片描述

2 Udacity 模拟器介绍

Udacity self-driving-car-sim是Udacity开源的一个汽车模拟器,主要用于自动驾驶模拟仿真实验。模拟器内置车辆,可以感知地图的图像和角度等关键信息。‘驾驶员’可以控制车辆的转向、油门和刹车等信息。模拟器内置两个场景,第一个场景为晴天环形公路简单场景,路面全程平整,无障碍物。第二个场景为盘山公路复杂场景,路面起伏,急弯、干扰路段较多,其中包括阴影、逆光、视线等强干扰信息。
在这里插入图片描述
对于第二个场景,弯道约有40个,其中包括小弯、圆弯等;强干扰部分约10处,包括不平整路面加转弯,下坡路面与远处道路造成的实现干扰等。
在这里插入图片描述

3 训练数据采集

  1. 下载模拟器后点击TRAINING MODE(训练模式)
    在这里插入图片描述

  2. 进入TRAINING MODE后点击右上角的RECORD选择训练数据保存的位置
    在这里插入图片描述

  3. 再次点击RECORD,当其变为RECORDING时,即可手动驾驶车辆,手动驾驶两到三圈,点击右上角的RECORDING,即可采集数据,采集的数据格式如下。
    在这里插入图片描述

4 数据预处理

对原始数据进行分析,其中训练道路包含许多弯道,其中转角信息分布如图所示,近似直线行驶的数据即转角信息在0附近的数据占比远大于其他数据,最终导致模型可能更倾向于直线行驶。
导入数据

# load data csv
import pandas as pd
import matplotlib.pyplot as plt
data_folder = 'data/'
drive_log = pd.read_csv(data_folder + 'driving_log.csv')
drive_log.head()

在这里插入图片描述

查看原有数据转角分布

# plot the distribution
plt.hist(drive_log['steering'], bins=100)
plt.show()

在这里插入图片描述
选取百分之20的转角为0的数据

drive_log = drive_log[drive_log['steering'] != 0].append(drive_log[drive_log['steering'] == 0].sample(frac=0.2))
plt.hist(drive_log['steering'], bins=100)
plt.show()

在这里插入图片描述

在选取百分之20的转向角数据后,根据左右相机头像用于角度校正和数据论证。

import numpy as np
from skimage import io, color, exposure, filters, img_as_ubyte
from skimage.transform import resize
from skimage.util import random_noise
data_folder = ''
def generate_data(line):type2data = {}# center imagecenter_img = io.imread(data_folder + line['center'].strip())center_ang = line['steering']type2data['center'] = (center_img, center_ang)# flip image if steering is not 0if line['steering']:flip_img = center_img[:, ::-1]flip_ang = center_ang * -1type2data['flip'] = (flip_img, flip_ang)# left image left_img = io.imread(data_folder + line['left'].strip())left_ang = center_ang + .2+ .05 * np.random.random()left_ang = min(left_ang, 1)type2data['left_camera'] = (left_img, left_ang)# right imageright_img = io.imread(data_folder + line['right'].strip())right_ang = center_ang - .2 - .05 * np.random.random()right_ang = max(right_ang, -1)type2data['right_camera'] = (right_img, right_ang)# minus brightnessaug_img = color.rgb2hsv(center_img)aug_img[:, :, 2] *= .5 + .4 * np.random.uniform()aug_img = img_as_ubyte(color.hsv2rgb(aug_img))aug_ang = center_angtype2data['minus_brightness'] = (aug_img, aug_ang)# equalize_histaug_img = np.copy(center_img)for channel in range(aug_img.shape[2]):aug_img[:, :, channel] = exposure.equalize_hist(aug_img[:, :, channel]) * 255aug_ang = center_angtype2data['equalize_hist'] = (aug_img, aug_ang)# blur imageblur_img = img_as_ubyte(np.clip(filters.gaussian(center_img, multichannel=True), -1, 1))blur_ang = center_angtype2data['blur'] = (blur_img, blur_ang)# noise imagenoise_img = img_as_ubyte(random_noise(center_img, mode='gaussian'))noise_ang = center_angtype2data['noise'] = (noise_img, noise_ang)# crop all imagesfor name, (img, ang) in type2data.items():img = img[60: -25, ...]type2data[name] = (img, ang)return type2datadef show_data(type2data):col = 4row = 1 + len(type2data) // 4f, axarr = plt.subplots(2, col, figsize=(16, 4))for idx, (name, (img, ang)) in enumerate(type2data.items()):axarr[idx//col, idx%col].set_title('{}:{:f}'.format(name, ang))axarr[idx//col, idx%col].imshow(img)plt.show()type2data = generate_data(drive_log.iloc[0])
show_data(type2data)

在这里插入图片描述
保存训练数据

import warnings
with warnings.catch_warnings():warnings.simplefilter("ignore")X_train, y_train = [], []for idx, row in drive_log.iterrows():type2data = generate_data(row)for img, ang in type2data.values():X_train.append(img)y_train.append(ang)X_train = np.array(X_train)
y_train = np.array(y_train)
np.save('X_train', X_train)
np.save('y_train', y_train)

训练数据分布

plt.hist(y_train, bins=100)
plt.show()

在这里插入图片描述

模型训练

import numpy as npfrom keras.models import Sequential
from keras.layers import Flatten, Dense, Lambda, Dropout, Conv2D# Define model
model = Sequential()
model.add(Lambda(lambda x: x / 255.0 - 0.5, input_shape=(75, 320, 3)))
model.add(Conv2D(24, (5, 5), strides=(2, 2), activation="elu"))
model.add(Conv2D(36, (5, 5), strides=(2, 2), activation="elu"))
model.add(Conv2D(48, (5, 5), strides=(2, 2), activation="elu"))
model.add(Conv2D(64, (3, 3), activation="elu"))
model.add(Conv2D(64, (3, 3), activation="elu"))
model.add(Dropout(0.8))
model.add(Flatten())
model.add(Dense(100))
model.add(Dense(50))
model.add(Dense(10))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')# Train model
X_train = np.load('X_train.npy')
y_train = np.load('y_train.npy')
model.fit(X_train, y_train, epochs=5, validation_split=0.1)# Save model
model.save('model.h5')

在这里插入图片描述

模型测试

import argparse
import base64
from datetime import datetime
import os
import shutilimport numpy as np
import socketio
import eventlet
import eventlet.wsgi
from PIL import Image
from flask import Flask
from io import BytesIOfrom keras.models import load_model
import h5py
from keras import __version__ as keras_versionsio = socketio.Server()
app = Flask(__name__)
model = None
prev_image_array = Noneclass SimplePIController:def __init__(self, Kp, Ki):self.Kp = Kpself.Ki = Kiself.set_point = 0.self.error = 0.self.integral = 0.def set_desired(self, desired):self.set_point = desireddef update(self, measurement):# proportional errorself.error = self.set_point - measurement# integral errorself.integral += self.errorreturn self.Kp * self.error + self.Ki * self.integralcontroller = SimplePIController(0.1, 0.002)
set_speed = 30
controller.set_desired(set_speed)@sio.on('telemetry')
def telemetry(sid, data):if data:# The current steering angle of the carsteering_angle = data["steering_angle"]# The current throttle of the carthrottle = data["throttle"]# The current speed of the carspeed = data["speed"]# The current image from the center camera of the carimgString = data["image"]image = Image.open(BytesIO(base64.b64decode(imgString)))image_array = np.asarray(image)image_array = image_array[60:-25, :, :]steering_angle = float(model.predict(image_array[None, ...], batch_size=1))throttle = controller.update(float(speed))print(steering_angle, throttle)send_control(steering_angle, throttle)# save frameif args.image_folder != '':timestamp = datetime.utcnow().strftime('%Y_%m_%d_%H_%M_%S_%f')[:-3]image_filename = os.path.join(args.image_folder, timestamp)image.save('{}.jpg'.format(image_filename))else:# NOTE: DON'T EDIT THIS.sio.emit('manual', data={}, skip_sid=True)@sio.on('connect')
def connect(sid, environ):print("connect ", sid)send_control(0, 0)def send_control(steering_angle, throttle):sio.emit("steer",data={'steering_angle': steering_angle.__str__(),'throttle': throttle.__str__()},skip_sid=True)if __name__ == '__main__':parser = argparse.ArgumentParser(description='Remote Driving')parser.add_argument('model',type=str,help='Path to model h5 file. Model should be on the same path.')parser.add_argument('image_folder',type=str,nargs='?',default='',help='Path to image folder. This is where the images from the run will be saved.')args = parser.parse_args()# check that model Keras version is same as local Keras versionf = h5py.File(args.model, mode='r')model_version = f.attrs.get('keras_version')keras_version = str(keras_version).encode('utf8')if model_version != keras_version:print('You are using Keras version ', keras_version,', but the model was built using ', model_version)model = load_model(args.model)if args.image_folder != '':print("Creating image folder at {}".format(args.image_folder))if not os.path.exists(args.image_folder):os.makedirs(args.image_folder)else:shutil.rmtree(args.image_folder)os.makedirs(args.image_folder)print("RECORDING THIS RUN ...")else:print("NOT RECORDING THIS RUN ...")# wrap Flask application with engineio's middlewareapp = socketio.Middleware(sio, app)# deploy as an eventlet WSGI servereventlet.wsgi.server(eventlet.listen(('', 4567)), app)

这篇关于基于Udacity模拟器的端到端自动驾驶决策的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/299588

相关文章

Java如何根据文件名前缀自动分组图片文件

《Java如何根据文件名前缀自动分组图片文件》一大堆文件(比如图片)堆在一个目录下,它们的命名规则遵循一定的格式,混在一起很难管理,所以本文小编就和大家介绍一下如何使用Java根据文件名前缀自动分组图... 目录需求背景分析思路实现代码输出结果知识扩展需求一大堆文件(比如图片)堆在一个目录下,它们的命名规

使用Python实现实时金价监控并自动提醒功能

《使用Python实现实时金价监控并自动提醒功能》在日常投资中,很多朋友喜欢在一些平台买点黄金,低买高卖赚点小差价,但黄金价格实时波动频繁,总是盯着手机太累了,于是我用Python写了一个实时金价监控... 目录工具能干啥?手把手教你用1、先装好这些"食材"2、代码实现讲解1. 用户输入参数2. 设置无头浏

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

pytorch自动求梯度autograd的实现

《pytorch自动求梯度autograd的实现》autograd是一个自动微分引擎,它可以自动计算张量的梯度,本文主要介绍了pytorch自动求梯度autograd的实现,具有一定的参考价值,感兴趣... autograd是pytorch构建神经网络的核心。在 PyTorch 中,结合以下代码例子,当你

Python如何自动生成环境依赖包requirements

《Python如何自动生成环境依赖包requirements》:本文主要介绍Python如何自动生成环境依赖包requirements问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录生成当前 python 环境 安装的所有依赖包1、命令2、常见问题只生成当前 项目 的所有依赖包1、

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

idea中创建新类时自动添加注释的实现

《idea中创建新类时自动添加注释的实现》在每次使用idea创建一个新类时,过了一段时间发现看不懂这个类是用来干嘛的,为了解决这个问题,我们可以设置在创建一个新类时自动添加注释,帮助我们理解这个类的用... 目录前言:详细操作:步骤一:点击上方的 文件(File),点击&nbmyHIgsp;设置(Setti