端到端自动驾驶——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.mzph.cn/diannao/72336.shtml

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

相关文章

蓝桥杯试题:二分查找

一、问题描述 给定 n 个数形成的一个序列 a&#xff0c;现定义如果一个连续子序列包含序列 a 中所有不同元素&#xff0c;则该连续子序列便为蓝桥序列&#xff0c;现在问你&#xff0c;该蓝桥序列长度最短为多少&#xff1f; 例如 1 2 2 2 3 2 2 1&#xff0c;包含 3 个不同的…

网络空间安全(7)攻防环境搭建

一、搭建前的准备 硬件资源&#xff1a;至少需要两台计算机&#xff0c;一台作为攻击机&#xff0c;用于执行攻击操作&#xff1b;另一台作为靶机&#xff0c;作为被攻击的目标。 软件资源&#xff1a; 操作系统&#xff1a;如Windows、Linux等&#xff0c;用于安装在攻击机和…

DeepSpeek服务器繁忙?这几种替代方案帮你流畅使用!(附本地部署教程)

作者&#xff1a;后端小肥肠 目录 1. 前言 2. 解决方案 2.1. 纳米AI搜索&#xff08;第三方平台&#xff09; 2.2. Github&#xff08;第三方平台&#xff09; 2.3. 硅基流动&#xff08;第三方API&#xff09; 3. 本地部署详细步骤 3.1. 运行配置需求 3.2. 部署教程 4…

prisma+supabase报错无法查询数据

解决方案&#xff0c;在DATABASE_URL后面增加?pgbouncertrue

c语言中return 数字代表的含义

return 数字的含义&#xff1a;表示函数返回一个整数值&#xff0c;通常用于向调用者&#xff08;如操作系统或其他程序&#xff09;传递程序的执行状态或结果。 核心规则&#xff1a; return 0&#xff1a; 含义&#xff1a;表示程序或函数正常结束。 示例&#xff1a; int m…

Spark内存迭代计算

一、宽窄依赖 窄依赖&#xff1a;父RDD的一个分区数据全部发往子RDD的一个分区 宽依赖&#xff1a;父RDD的一个分区数据发往子RDD的多个分区&#xff0c;也称为shuffle 二、Spark是如何进行内存计算的&#xff1f;DAG的作用&#xff1f;Stage阶段划分的作用&#xff1f; &a…

Linux知识-第一天

Linux的目录机构为一个树型结构 其没有盘符这个概念&#xff0c;只有一个根目录&#xff0c;所有文件均在其之下 在Linux系统中&#xff0c;路径之间的层级关系 使用 / 开头表示根目录&#xff0c;后面的表示层级关系 Linux命令入门 Linux命令基础 Linux命令通用格式 comman…

QT实现单个控制点在曲线上的贝塞尔曲线

最终效果: 一共三个文件 main.cpp #include <QApplication> #include "SplineBoard.h" int main(int argc,char** argv) {QApplication a(argc, argv);SplineBoard b;b.setWindowTitle("标准的贝塞尔曲线");b.show();SplineBoard b2(0.0001);b2.sh…

绘制思维导图画布选型

在实现思维导图/知识图谱的绘制时&#xff0c;选择合适的「画布」技术方案至关重要。以下是不同技术路线的对比分析和推荐方案&#xff1a; 一、技术方案对比 技术类型实现方式优点缺点适用场景普通DOM元素使用<div>CSS布局&#x1f539; 开发简单&#x1f539; 天然支持…

运维Splunk面试题及参考答案

目录 通过转发器导入数据的优势有哪些(如带宽控制、负载均衡等) 描述 Universal Forwarder 与 Heavy Forwarder 的差异 如何配置转发器实现数据的过滤与预处理 转发器的本地缓存机制如何保证数据可靠性 如何通过部署服务器统一管理多个转发器的配置 什么是 “查找表(L…

年后寒假总结及计划安排

年后寒假总结 年后主要学习了微服务&#xff0c;nacos (服务注册中心)&#xff0c;feign&#xff08;远程调用&#xff09;&#xff0c;网关&#xff0c;双token&#xff08;相较于之前更加规范&#xff0c;更加符合企业级&#xff09;&#xff0c;配置管理 &#xff0c;mybati…

word中交叉引用多篇参考文献格式[1-2]或[1-4]操作

划重点 更改左域名&#xff0c;输入 \#"[0" 更改中间域名&#xff0c;输入\#"" 更改右域名&#xff0c;输入 \#"0]" 1.[2-3]格式 首先点击交叉引用&#xff0c;引用参考文献 右击鼠标&#xff0c;点击切换域代码&#xff0c;对于左域名 删除 * …

【银河麒麟高级服务器操作系统】服务器测试业务耗时问题分析及处理全流程分享

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…

opencv 模板匹配方法汇总

在OpenCV中&#xff0c;模板匹配是一种在较大图像中查找特定模板图像位置的技术。OpenCV提供了多种模板匹配方法&#xff0c;通过cv2.matchTemplate函数实现&#xff0c;该函数支持的匹配方式主要有以下6种&#xff0c;下面详细介绍每种方法的原理、特点和适用场景。 1. cv2.T…

NAT,代理服务,内网穿透

NAT 把报文的源IP替换为途径路由器的WAN口IP NAPT 如何将数据从公网转回给内网的主机&#xff1f;通过NAPT&#xff08;转换表&#xff09;来实现&#xff0c;每次从内网到公网&#xff0c;公网到内网都会根据转换表来进行 细节&#xff1a; NAT转换时&#xff0c;值替换源…

大模型分布式训练和优化

1. 分布式训练概述 随着语言模型参数量和所需训练数据量的急速增长,单个机器上有限的资源已无法满足大语言模型训练的要求。因此,设计分布式训练(Distributed Training)系统来解决海量的计算和内存资源需求问题变得至关重要。 分布式训练是指将机器学习或深度学习模型训练任…

第三方机构有哪些接口?

1&#xff0c;网银接口。2&#xff0c;代扣接口。3&#xff0c;POS接口。4&#xff0c;快捷支付接口 1.网银接口 第三方支付平台连接网银接口&#xff0c;进行支付跳转时&#xff0c;第三方支付平台充当了一个网关的角色&#xff0c;或者充当了银行的代 理。 2.代扣接口 银…

JUnit 版本影响 Bean 找不到

JUnit 版本影响 Bean 找不到 在为实现类编写测试类时&#xff0c;在测试类中使用构造器注入 Bean 时&#xff0c;提示找不到 Bean&#xff0c;代码如下&#xff1a; Service public class WeChatServiceImpl implements IWeChatService {Overridepublic String getNumber(Str…

夸父工具箱(安卓版) 手机超强工具箱

如今&#xff0c;人们的互联网活动日益频繁&#xff0c;导致手机内存即便频繁清理&#xff0c;也会莫名其妙地迅速填满&#xff0c;许多无用的垃圾信息悄然占据空间。那么&#xff0c;如何有效应对这一难题呢&#xff1f;答案就是今天新推出的这款工具软件&#xff0c;它能从根…

《深度学习进阶》第7集:深度实战 通过训练一个智能体玩游戏 来洞察 强化学习(RL)与决策系统

深度学习进阶 | 第7集&#xff1a;深度实战 通过训练一个智能体玩游戏 来洞察 强化学习&#xff08;RL&#xff09;与决策系统 在深度学习的广阔领域中&#xff0c;强化学习&#xff08;Reinforcement Learning, RL&#xff09;是一种独特的范式&#xff0c;它通过智能体与环境…