基于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

相关文章

基于Python编写一个git自动上传的脚本(打包成exe)

《基于Python编写一个git自动上传的脚本(打包成exe)》这篇文章主要为大家详细介绍了如何基于Python编写一个git自动上传的脚本并打包成exe,文中的示例代码讲解详细,感兴趣的小伙伴可以跟... 目录前言效果如下源码实现利用pyinstaller打包成exe利用ResourceHacker修改e

使用Python将PDF表格自动提取并写入Word文档表格

《使用Python将PDF表格自动提取并写入Word文档表格》在实际办公与数据处理场景中,PDF文件里的表格往往无法直接复制到Word中,本文将介绍如何使用Python从PDF文件中提取表格数据,并将... 目录引言1. 加载 PDF 文件并准备 Word 文档2. 提取 PDF 表格并创建 Word 表格

Apache服务器IP自动跳转域名的问题及解决方案

《Apache服务器IP自动跳转域名的问题及解决方案》本教程将详细介绍如何通过Apache虚拟主机配置实现这一功能,并解决常见问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录​​问题背景​​解决方案​​方法 1:修改 httpd-vhosts.conf(推荐)​​步骤

idea-java序列化serialversionUID自动生成方式

《idea-java序列化serialversionUID自动生成方式》Java的Serializable接口用于实现对象的序列化和反序列化,通过将对象转换为字节流来存储或传输,实现Serializa... 目录简介实现序列化serialVersionUID配置使用总结简介Java.io.Seripyth

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

linux部署NFS和autofs自动挂载实现过程

《linux部署NFS和autofs自动挂载实现过程》文章介绍了NFS(网络文件系统)和Autofs的原理与配置,NFS通过RPC实现跨系统文件共享,需配置/etc/exports和nfs.conf,... 目录(一)NFS1. 什么是NFS2.NFS守护进程3.RPC服务4. 原理5. 部署5.1安装NF

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1