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

2023-11-11

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 image
    center_img = io.imread(data_folder + line['center'].strip())
    center_ang = line['steering']
    type2data['center'] = (center_img, center_ang)
    
    # flip image if steering is not 0
    if line['steering']:
        flip_img = center_img[:, ::-1]
        flip_ang = center_ang * -1
        type2data['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 image
    right_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 brightness
    aug_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_ang
    type2data['minus_brightness'] = (aug_img, aug_ang)
    
    # equalize_hist
    aug_img = np.copy(center_img)
    for channel in range(aug_img.shape[2]):
        aug_img[:, :, channel] = exposure.equalize_hist(aug_img[:, :, channel]) * 255
    aug_ang = center_ang
    type2data['equalize_hist'] = (aug_img, aug_ang)
    
    # blur image
    blur_img = img_as_ubyte(np.clip(filters.gaussian(center_img, multichannel=True), -1, 1))
    blur_ang = center_ang
    type2data['blur'] = (blur_img, blur_ang)
    
    # noise image
    noise_img = img_as_ubyte(random_noise(center_img, mode='gaussian'))
    noise_ang = center_ang
    type2data['noise'] = (noise_img, noise_ang)
    
    # crop all images
    for name, (img, ang) in type2data.items():
        img = img[60: -25, ...]
        type2data[name] = (img, ang)
    
    return type2data

def show_data(type2data):
    col = 4
    row = 1 + len(type2data) // 4
    
    f, 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 np

from 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 shutil

import numpy as np
import socketio
import eventlet
import eventlet.wsgi
from PIL import Image
from flask import Flask
from io import BytesIO

from keras.models import load_model
import h5py
from keras import __version__ as keras_version

sio = socketio.Server()
app = Flask(__name__)
model = None
prev_image_array = None


class SimplePIController:
    def __init__(self, Kp, Ki):
        self.Kp = Kp
        self.Ki = Ki
        self.set_point = 0.
        self.error = 0.
        self.integral = 0.

    def set_desired(self, desired):
        self.set_point = desired

    def update(self, measurement):
        # proportional error
        self.error = self.set_point - measurement

        # integral error
        self.integral += self.error

        return self.Kp * self.error + self.Ki * self.integral


controller = 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 car
        steering_angle = data["steering_angle"]
        # The current throttle of the car
        throttle = data["throttle"]
        # The current speed of the car
        speed = data["speed"]
        # The current image from the center camera of the car
        imgString = 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 frame
        if 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 version
    f = 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 middleware
    app = socketio.Middleware(sio, app)

    # deploy as an eventlet WSGI server
    eventlet.wsgi.server(eventlet.listen(('', 4567)), app)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于Udacity模拟器的端到端自动驾驶决策 的相关文章

随机推荐

  • Mental ray 渲染器常用设置

    Mental ray 渲染器常用设置 Mental ray是一个专业的3D渲染引擎 它可以生成令人难以置信的高质量真实感图象 现在你可以在3D Studio的高性能网络渲染中直接控制Mental ray 它在电影领域得到了广泛的应用和认可
  • 用python怎样做学生管理系统用类的形式-Python配置管理的几种方式

    一 为什么要使用配置 如果我们在较复杂的项目中不使用配置文件 我们可能会面临下面的情况 你决定更改你的项目中数据库的 host 因为你要将项目从测试环境转移到实际的上产环境中 如果你的项目中多个位置用到了这个 host 那你不得不一个一个找
  • CS336视觉伺服

    笔记 动力学模型 机械臂动力学的研究方法 拉格朗日 牛顿 欧拉 高斯 凯恩方法 机械臂的动力学主要是两个问题 正向运动学和逆向运动学 视觉伺服 视觉伺服的基本思想 基于视觉的伺服控制方法的目的是最小化一个图像误差 该误差可以定义为 e t
  • Elasticsearch搜索系统线上部署配置规划

    问题导读 1 es安装包的目录结构是怎样的 2 zen discovery集群发现机制的设置规划及其原理是怎样的 3 es默认参数调优如何进行 1 ES部署须知1 1 包结构es安装包的目录结构大致如下 bin 存放es的一些可执行脚本 比
  • Python数据分析之股票数据

    最近股市比较火 我7月初上车了 现在已经下了 中间虽然吃了点肉 但下车的时候都亏进去了 最后连点汤都没喝着 这篇文章我们就用python对股票数据做个简单的分析 数据集是从1999年到2016年上海证券交易所的1095只股票 共1000个文
  • C++实现——排序算法总结

    常见的排序算法有 直接插入 希尔 冒泡 快速 选择 堆排序 归并 基数 下面一一分析 并实现 1 冒泡排序 冒泡排序是最简单的排序算法 冒泡排序的基本思想是从后往前 或从前往后 两两比较相邻元素的值 若为逆序 则交换它们 直到序列比较完毕
  • R语言做面板VAR例子

    面板VAR步骤 1 对各变量做平稳性检验 IPS PP ADF LLC等方法检验 是逐个变量检验 还是一起检验 2 面板数据的最优滞后阶数确定 AIC和SIC方法 3 在PVAR系统中进行Wald Granger检验 4 面板VAR估计 5
  • 蓝桥试题 算法训练 阶乘末尾0的个数(C++)

    资源限制 时间限制 1 0s 内存限制 256 0MB 题目 n 表示为n的阶乘 其中阶乘的定义是这样的 若n为0 则有n 0 1 若n为正整数 则有n n 1 n 例如4 4 3 2 1 24 可以发现阶乘这一运算的数值增长速度是非常快的
  • SpringFramework历史版本

    SpringFramework历史版本 对于Spring而言 迄今已有14年历史了 版本也到达了5 0 作为JavaWEB开发领域的常青树 现在Spirng已不再简单是一个框架了 在Spring的项目中主要有 SpringFramework
  • qt Example Manifest Files

    manifest file 是有qdoc根据example对应的 qdocconf qdoc文件生成的 主要用于在qtcreator 的欢迎 welcome gt 示例 examples 中辅助显示内容项 其文件格式为xml格式 后缀名为
  • hdu 1827 Summer Holiday 强连通分量缩点

    题目 http acm hdu edu cn showproblem php pid 1827 题意 听说lcy帮大家预定了新马泰7日游 Wiskey真是高兴的夜不能寐啊 他想着得快点把这消息告诉大家 虽然他手上有所有人的联系方式 但是一个
  • 使用docker搭建Hadoop

    Hadoop简介 1 Hadoop的整体框架 Hadoop由HDFS MapReduce HBase Hive和ZooKeeper等成员组成 其中最基础最重要元素为底层用于存储集群中所有存储节点文件的文件系统HDFS Hadoop Dist
  • MVC模式 &三层架构思想完成增删改查.

    MVC模式图解 三层架构图解 表现层 业务逻辑层 数据访问层互不干扰 也就是说比如我们表现层更改代码不会干涉到其他两层 com itheima web 这代表的是包名 也就是说最好把表现层或者业务逻辑层放到此对应的包名下 以后会用三大框架封
  • 2014年腾讯,百度,微软等校园招聘笔试题...

    腾讯2014年校园招聘笔试题 2014年阿里巴巴校招笔试题北京站 涉及C JAVA 数据结构
  • 基于SDF的抽骨架之散点图(Projected points)

    span style font family none background color rgb 255 255 255 1 SDF 形状直径函数 span span style font family none background co
  • element-ui表格实现跨页多选

    1 在type selection 的column中添加reserve selection属性 以保留当前所选数据
  • Arduino实验十八 旋转编码器实验

    学习任务 学会使用旋转编码器 关注微信公众号 爱享生活科技 color FF0000 关注微信公众号 爱享生活科技 关注微信公众号 爱享生活科技 组件 Arduion主板 旋转编码器 I2CLCD1602液晶显示器 杜邦线 面包板 下图是旋
  • JS base64与utf8相互转换

    utf8Url utf8编码字符串 let base64URL Buffer from utf8Url toString base64 base64UR base64编码字符串 let utf8Url Buffer from base64U
  • 李开复创业了

    上周五9月4日 一看新闻 头条就是 李开复离开Google 准备创业 等新闻 我吓了一跳 李开复作为全球一流企业的高管 居然都辞职不干了 记得李开复在大学生心目中一直都是导师的身份 他为我们写了7封信了 教导着中国的新生代怎么面对困难 积极
  • 基于Udacity模拟器的端到端自动驾驶决策

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