端到端自动驾驶——cnn网络搭建

论文参考:https://arxiv.org/abs/1604.07316
demo
在这里插入图片描述

今天主要来看一个如何通过图像直接到控制的自动驾驶端到端的项目,首先需要配置好我的仿真环境,下载软件udacity:
https://d17h27t6h515a5.cloudfront.net/topher/2016/November/5831f3a4_simulator-windows-64/simulator-windows-64.zip

现在好的解压即可
在这里插入图片描述
运行时打开终端,然后将文件拖入终端中运行
在这里插入图片描述
选择合适的窗口大小
在这里插入图片描述
成功进入界面
在这里插入图片描述
然后配置一下python环境,对于已经有conda环境后,直接

conda create -n cnn python=3.8
conda activate cnn

安装以下依赖:

astor==0.8.1
bidict==0.21.2
certifi==2021.5.30
charset-normalizer==2.0.4
click==8.0.1
colorama==0.4.4
cycler==0.10.0
decorator==5.0.9
dnspython==1.16.0
eventlet==0.31.1
Flask==2.0.1
gast==0.3.3
greenlet==1.1.0
idna==3.2
itsdangerous==2.0.1
Jinja2==3.0.1
joblib==1.0.1
kiwisolver==1.3.1
MarkupSafe==2.0.1
matplotlib==3.4.2
numpy==1.19.3
opencv-python==4.5.3.56
paddlepaddle==2.1.2
pandas==1.3.1
Pillow==8.3.1
protobuf==3.17.3
pyparsing==2.4.7
python-dateutil==2.8.2
python-engineio==3.13.0
python-socketio==4.6.1
pytz==2021.1
requests==2.26.0
scikit-learn==0.24.2
scipy==1.7.1
six==1.16.0
threadpoolctl==2.2.0
urllib3==1.26.6
Werkzeug==2.0.1

代码

git clone https://github.com/chan-yuu/end_to_end_ws.git

数据集可以自己驾驶udacity的车辆收集,也可以直接下载下来训练师需要指定文件夹的路径,这里我使用的是一个csv文件来指定我的文件夹
主要文件放置的结构要写入csv文件中,分别是左中右的摄像头图片路径,方向盘,油门,刹车,速度信息。
打开仿真环境,进入training模式
在这里插入图片描述
通过键盘即可控制车辆运行。
可以点击record记录这个过程中的数据,之后就能自动生成需要的数据集内容

python train

python train.py -d xxx.csv

我仔细研读了一下这个代码

import paddle
import argparse
import numpy as np
import paddle.nn as nnfrom paddle.optimizer import Adam
from paddle.callbacks import ModelCheckpoint, EarlyStoppingfrom car.model import build_model
from car.utils import CarDataset, load_data# 设置随机种子,确保结果可复现
np.random.seed(0)def train_model(model, args, X_train, X_valid, y_train, y_valid):"""Train the model"""# 创建一个模型检查点回调,用于在训练过程中保存模型checkpoint = ModelCheckpoint(save_dir=args.save_dir)# 创建一个早停回调,当监控的指标(这里是损失值)在一定轮数(patience)内没有改善时,停止训练earlystopping = EarlyStopping(monitor='loss',mode='min',  # 监控损失值,希望其越小越好patience=10,  # 允许损失值在 10 个 epoch 内没有改善verbose=1,  # 打印早停信息min_delta=0,  # 损失值的最小改善量baseline=None,  # 基线值,这里不使用save_best_model=True)  # 保存最佳模型# 根据命令行参数决定是否使用早停回调if args.early_stop:cbs = [checkpoint, earlystopping]else:cbs = [checkpoint]# 创建 Adam 优化器,用于更新模型的参数opt = Adam(learning_rate=args.learning_rate, parameters=model.parameters())# 将模型包装为 paddle.Model 对象,方便进行训练和评估model = paddle.Model(model)# 配置模型的损失函数和优化器model.prepare(loss=nn.MSELoss(), optimizer=opt)# 创建训练数据集对象train_dataset = CarDataset(args.data_dir, X_train, y_train, True)# 创建验证数据集对象val_dataset = CarDataset(args.data_dir, X_valid, y_valid, False)# 开始训练模型model.fit(train_data=train_dataset,  # 训练数据集eval_data=val_dataset,  # 验证数据集epochs=args.nb_epoch,  # 训练的轮数batch_size=args.batch_size,  # 每个批次的样本数量save_dir=args.save_dir,  # 模型保存的目录callbacks=cbs,  # 回调函数列表verbose=1)  # 打印训练进度信息def s2b(s):"""Converts a string to boolean value"""# 将字符串转换为小写s = s.lower()# 判断字符串是否表示真return s == 'true' or s == 'yes' or s == 'y' or s == '1'def main():"""Load train/validation data set and train the model"""# 创建命令行参数解析器parser = argparse.ArgumentParser(description='Behavioral Cloning Training Program')# 添加数据目录参数,默认值为 'data'parser.add_argument('-d',help='data directory',dest='data_dir',type=str,default='data')# 添加模型保存目录参数,默认值为 'save'parser.add_argument('-s',help='save directory',dest='save_dir',type=str,default='save')# 添加测试集大小比例参数,默认值为 0.2parser.add_argument('-t',help='test size fraction',dest='test_size',type=float,default=0.2)# 添加 Dropout 概率参数,默认值为 0.5parser.add_argument('-k',help='drop out probability',dest='keep_prob',type=float,default=0.5)# 添加训练轮数参数,默认值为 100parser.add_argument('-n',help='number of epochs',dest='nb_epoch',type=int,default=100)# 添加批次大小参数,默认值为 40parser.add_argument('-b',help='batch size',dest='batch_size',type=int,default=40)# 添加学习率参数,默认值为 1.0e-4parser.add_argument('-l',help='learning rate',dest='learning_rate',type=float,default=1.0e-4)# 添加早停参数,默认值为 Falseparser.add_argument('-e',help='early stop',dest='early_stop',type=bool,default=False)# 解析命令行参数args = parser.parse_args()print('-' * 30)print('Parameters')print('-' * 30)# 打印所有命令行参数for key, value in vars(args).items():print('{:<20} := {}'.format(key, value))print('-' * 30)# 加载训练数据和验证数据data = load_data(args)# 构建模型model = build_model(args.keep_prob)# 调用训练函数进行模型训练train_model(model, args, *data)if __name__ == '__main__':# 程序入口,调用 main 函数main()

训练结束后可以得到对应的模型
在这里插入图片描述
使用这个模型进行测试
打开仿真软件的auto模式
在这里插入图片描述

此时是无法记录的,然后我可以加载模型并驾驶车辆

python drive.py ./pretrained_models/model_paddle_test2.pdparams

同样,自己写一边这个代码更容易理解:

import os
import base64
import paddle
import shutil
import argparse
import socketio
import eventlet
import numpy
import eventlet.wsgi
from PIL import Imagefrom io import BvtesIO
from flask import Flask
from datatime import datatime
from car.model import build_model
from car.utils import preprocess# 创建一个socket.IO服务器
sio = socket.Server()
app = Flask(__name__)
# 初始化模型变量,用于后续加载模型
model = None
# 初始化上一帧图像数组变量,用于记录上一帧的图像数据
prev_image_array = None# 定义最大速度和最小速度
MAX_SPEED = 25
MIN_SPEED = 10# 初始化速度限制为最大速度
speed_limit = MAX_SPEED# 定义一个事件处理函数,当接收到 'telemetry' 事件时触发
@sio.on('telemetry')
def telemetry(sid, data):if data:# 从接收到的数据中提取当前汽车的转向角度steering_angle = float(data["steering_angle"])# 从接收到的数据中提取当前汽车的油门值throttle = float(data["throttle"])# 从接收到的数据中提取当前汽车的速度speed = float(data["speed"])# 从接收到的数据中提取当前汽车中心摄像头的图像,并将其解码为 PIL 图像对象image = Image.open(BytesIO(base64.b64decode(data["image"])))# 如果指定了图像保存文件夹,则保存当前帧图像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)# 保存图像为 JPEG 格式image.save('{}.jpg'.format(image_filename))try:# 将 PIL 图像对象转换为 NumPy 数组image = np.asarray(image)# 对图像进行预处理,例如裁剪、归一化等操作image = preprocess(image)# 为图像数组添加一个维度,使其成为 4D 数组,以满足模型输入要求image = np.array([image])# 使用模型对图像进行预测,得到转向角度的预测值steering_angle = model(image.astype('float32') / 127.5 - 1.0).item()# 根据当前速度调整速度限制和油门值global speed_limitif speed > speed_limit:# 如果当前速度超过速度限制,则将速度限制降低到最小速度,以减速speed_limit = MIN_SPEEDelse:# 如果当前速度低于速度限制,则将速度限制恢复到最大速度speed_limit = MAX_SPEED# 根据转向角度和速度计算油门值throttle = 1.0 - steering_angle**2 - (speed / speed_limit)**2# 打印当前的转向角度、油门值和速度print(f'steering_angle={steering_angle:.3f}, throttle={throttle:.3f}, speed={speed:.3f}')# 发送控制指令,包括转向角度和油门值send_control(steering_angle, throttle)except Exception as e:# 打印异常信息print(e)else:# 如果没有接收到数据,则发送手动控制指令sio.emit('manual', data={}, skip_sid=True)# 定义一个事件处理函数,当有新的客户端连接时触发
@sio.on('connect')
def connect(sid, environ):# 打印连接信息print("connect ", sid)# 发送初始控制指令,将转向角度和油门值都设为 0send_control(0, 0)# 定义一个函数,用于发送控制指令
def send_control(steering_angle, throttle):# 向客户端发送 'steer' 事件,包含转向角度和油门值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()# 构建模型model = build_model()# 加载模型的参数params = paddle.load(args.model)# 将加载的参数设置到模型中model.set_dict(params)# 将模型转换为静态图模式,以提高推理速度model = paddle.jit.to_static(model)# 将模型设置为评估模式model.eval()# 如果指定了图像保存文件夹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 ...")# 使用 Socket.IO 中间件包装 Flask 应用app = socketio.Middleware(sio, app)# 使用 eventlet 启动一个 WSGI 服务器,监听 4567 端口eventlet.wsgi.server(eventlet.listen(('', 4567)), app)

在这里插入图片描述

即可实现基于视觉的自动驾驶功能。后面这篇文章还会继续完善论文中的一些观点和代码的一些学习过程。
https://github.com/naokishibuya/car-behavioral-cloning?tab=readme-ov-file

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/27732.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自己的网页加一个搜索框,调用deepseek的API

一切源于一个学习黑马程序员视频的突发奇想 在网页悬浮一个搜索按钮&#xff0c;点击可以实现调用deepseek文本模型回答你的问题 前端实现 前端使用vue实现的 首先是整体页面&#xff1a;AIWidget.vue <template><div><!-- 悬浮 AI 按钮 --><el-button c…

第五天 Labview数据记录(5.3 CSV文件读写)

5.3 CSV文件读写 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff09;文件是一种常见的文本文件格式&#xff0c;用于存储表格数据。它在程序中具有重要的作用&#xff0c;主要体现在以下几个方面&#xff1a; 1. 数据存储与交换 &#xff1b;2. 跨平台…

250301-OpenWebUI配置DeepSeek-火山方舟+硅基流动+联网搜索+推理显示

A. 最终效果 B. 火山方舟配置&#xff08;一定要点击添加&#xff09; C. 硅基流动配置&#xff08;最好要点击添加&#xff0c;否则会自动弹出所有模型&#xff09; D. 联网搜索配置 E. 推理过程显示 默认是没有下面的推理过程的显示的 F. SearXNG配置 注意&#xff1a;此…

阿里云物联网获取设备属性api接口:QueryDevicePropertyData

阿里云物联网接口&#xff1a;QueryDevicePropertyData 说明&#xff1a;调用该接口查询指定设备或数字孪生节点&#xff0c;在指定时间段内&#xff0c;单个属性的数据 比如提取上传到物联网的温度数据 api文档&#xff1a;QueryDevicePropertyData_物联网平台_API文档-阿里…

算法系列之动态规划

动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种用于解决复杂问题的算法设计技术。它通过将问题分解为更小的子问题&#xff0c;并存储这些子问题的解来避免重复计算&#xff0c;从而提高算法的效率。本文将介绍动态规划的基本概念、适用场景、复…

Linux系列:如何用 C#调用 C方法造成内存泄露

一&#xff1a;背景 1. 讲故事 好久没写文章了&#xff0c;还是来写一点吧&#xff0c;今年准备多写一点 Linux平台上的东西&#xff0c;这篇从 C# 调用 C 这个例子开始。在 windows 平台上&#xff0c;我们常常在 C 代码中用 extern "C" 导出 C风格 的函数&#x…

1.2.3 使用Spring Initializr方式构建Spring Boot项目

本实战概述介绍了如何使用Spring Initializr创建Spring Boot项目&#xff0c;并进行基本配置。首先&#xff0c;通过Spring Initializr生成项目骨架&#xff0c;然后创建控制器HelloController&#xff0c;定义处理GET请求的方法hello&#xff0c;返回HTML字符串。接着&#xf…

【音视频】H265解码Nalu后封装rtp包

概述 基于ZLM流媒体框架以及简单RTSP服务器开源项目分析总结&#xff0c;相关源码参考以下链接 H265-rtp提取Nalu逻辑 通过rtsp流地址我们可以获取视频流中的多个rtp包&#xff0c;其中每个RTP包中又会包含一个或者多个Nalu&#xff0c;将其提取处理 总体逻辑分析 核心逻辑在…

03.03 QT

1.在注册登录的练习里面&#xff0c;追加一个QListwidget 项目列表 要求:点击注册之后&#xff0c;将账号显示到 1istwidget上面去 以及&#xff0c;在listwidget中双击某个账号的时候&#xff0c;将该账号删除 Widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWi…

【星云 Orbit • STM32F4】04.一触即发:GPIO 外部中断

【星云 Orbit- • STM32F4】04. 一触即发&#xff1a;外部中断控制 摘要 本文详细介绍了如何使用STM32F407微控制器的HAL库实现外部中断功能。通过配置GPIO引脚作为外部中断源&#xff0c;并在中断回调函数中处理按键事件&#xff0c;实现了按键控制LED状态翻转的功能。本文旨…

(新版本onenet)stm32+esp8266/01s mqtt连接onenet上报温湿度和远程控制(含小程序)

物联网实践教程&#xff1a;微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——汇总 前言 之前在学校获得了一个新玩意&#xff1a;ESP-01sWIFI模块&#xff0c;去搜了一下这个小东西很有玩点&#xff0c;远程控制LED啥的&#xff0c;然后我就想…

并发编程(线程基础)面试题及原理

1. 进程与线程 1.1 进程 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至CPU&#xff0c;数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理IO的。 当一个程序被运…

基于开源库编写MQTT通讯

目录 1. MQTT是什么&#xff1f;2. 开发交互UI3. 服务器核心代码4. 客户端核心代码5. 消息订阅与发布6. 通讯测试7. MQTT与PLC通讯最后. 核心总结 1. MQTT是什么&#xff1f; MQTT&#xff08;Message Queuing Terlemetry Transport&#xff09;消息队列遥测协议&#xff1b;是…

vector习题

完数和盈数 题目 完数VS盈数_牛客题霸_牛客网 一个数如果恰好等于它的各因子(该数本身除外)之和&#xff0c;如&#xff1a;6321。则称其为“完数”&#xff1b;若因子之和大于该数&#xff0c;则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。 输入描述&#xff…

vscode通过ssh远程连接(linux系统)不能跳转问题

1.问题描述 unbantu中的vscode能够通过函数跳转到函数定义&#xff0c;而windows通过ssh连接unbantu的vscode却无法跳转 2.原因&#xff1a; 主要原因是这里缺少插件&#xff0c;这里是unbantu给主机的服务器&#xff0c;与ubantu本地vscode插件相互独立&#xff0c;能否跳转…

神经网络 - 激活函数(Swish函数、GELU函数)

一、Swish 函数 Swish 函数是一种较新的激活函数&#xff0c;由 Ramachandran 等人在 2017 年提出&#xff0c;其数学表达式通常为 其中 σ(x) 是 Sigmoid 函数&#xff08;Logistic 函数&#xff09;。 如何理解 Swish 函数 自门控特性 Swish 函数可以看作是对输入 x 进行“…

安全运营的“黄金4小时“:如何突破告警疲劳困局

在当今复杂多变的网络安全环境中&#xff0c;安全团队面临着前所未有的挑战。尤其是面对高级持续性威胁&#xff08;APT&#xff09;时&#xff0c;最初的“黄金4小时”成为决定成败的关键窗口。在这段时间内&#xff0c;快速而准确地响应可以极大地降低损失&#xff0c;然而&a…

【Pytest】setup和teardown的四个级别

文章目录 1.setup和teardown简介2.模块级别的 setup 和 teardown3.函数级别的 setup 和 teardown4.方法级别的 setup 和 teardown5.类级别的 setup 和 teardown 1.setup和teardown简介 在 pytest 中&#xff0c;setup 和 teardown 用于在测试用例执行前后执行一些准备和清理操…

傅里叶分析

傅里叶分析之掐死教程&#xff08;完整版&#xff09;更新于2014.06.06 要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析不仅仅是一个数学工具&#xff0c;更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是&#xff0c;傅里叶分析的公式看起来太复…

matlab 四维数据可视化(已解决)

虽然这不是传统意义上的“4维可视化”&#xff0c;但你可以通过在三维空间中表示两个维度来间接展示4维数据。例如&#xff0c;你可以使用颜色来表示第四个维度。 clc clear close all% 假设X, Y, Z为你的三维数据&#xff0c;C为第四维数据 X rand(100, 1); Y rand(100, 1);…