端到端自动驾驶——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 nn

from paddle.optimizer import Adam
from paddle.callbacks import ModelCheckpoint, EarlyStopping

from 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.2
    parser.add_argument('-t',
                        help='test size fraction',
                        dest='test_size',
                        type=float,
                        default=0.2)
    # 添加 Dropout 概率参数,默认值为 0.5
    parser.add_argument('-k',
                        help='drop out probability',
                        dest='keep_prob',
                        type=float,
                        default=0.5)
    # 添加训练轮数参数,默认值为 100
    parser.add_argument('-n',
                        help='number of epochs',
                        dest='nb_epoch',
                        type=int,
                        default=100)
    # 添加批次大小参数,默认值为 40
    parser.add_argument('-b',
                        help='batch size',
                        dest='batch_size',
                        type=int,
                        default=40)
    # 添加学习率参数,默认值为 1.0e-4
    parser.add_argument('-l',
                        help='learning rate',
                        dest='learning_rate',
                        type=float,
                        default=1.0e-4)
    # 添加早停参数,默认值为 False
    parser.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 Image

from 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_limit
            if speed > speed_limit:
                # 如果当前速度超过速度限制,则将速度限制降低到最小速度,以减速
                speed_limit = MIN_SPEED
            else:
                # 如果当前速度低于速度限制,则将速度限制恢复到最大速度
                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)
    # 发送初始控制指令,将转向角度和油门值都设为 0
    send_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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL-labs13-16闯关记录

http://127.0.0.1/sqli-labs/less-13/ 基于POST单引号双注入变形 1&#xff0c;依然是一个登录框&#xff0c;POST型SQL注入 2&#xff0c;挂上burpsuite&#xff0c;然后抓取请求&#xff0c;构造请求判断漏洞类型和闭合条件 admin 发生了报错&#xff0c;根据提示闭合方式是(…

2025年渗透测试面试题总结- 阿某云安全实习(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 阿里云安全实习 一、代码审计经验与思路 二、越权漏洞原理与审计要点 三、SSRF漏洞解析与防御 四、教…

Zookeeper 及 基于ZooKeeper实现的分布式锁

1 ZooKeeper 1.1 ZooKeeper 介绍 ZooKeeper是一个开源的分布式协调服务&#xff0c;它的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来&#xff0c;构成一个高效可靠的原语集&#xff0c;并以一系列简单易用的接口提供给用户使用。 原语&#xff1a;操作系统或…

开放鸿蒙OpenHarmony 5.0.0 Release 兼容性测试实战经验分享

OpenHarmony 5.0版本的发布时间是2024年12月20日至21日。这个版本带来了许多新特性和改进。现在5.0出了两个release 版本&#xff0c;分别是5.0.0和5.0.1。 就在5.0版本发布不到2周的时间内&#xff0c;2025年01月01日起&#xff0c;不支持新产品基于老分支&#xff08;OpenHar…

DeepSeek开源周Day6:DeepSeek V3、R1 推理系统深度解析,技术突破与行业启示

DeepSeek 在开源周第六天再次发文&#xff0c;中文原文、官方号在知乎 DeepSeek - 知乎DeepSeek-V3 / R1 推理系统概览 - 知乎deepseek-ai/open-infra-index: Production-tested AI infrastructure tools for efficient AGI development and community-driven innovation 引言 …

springBoot集成emqx 实现mqtt消息的发送订阅

介绍 我们可以想象这么一个场景&#xff0c;我们java应用想要采集到电表a的每小时的用电信息&#xff0c;我们怎么拿到电表的数据&#xff1f;一般我们会想 直接 java 后台发送请求给电表&#xff0c;然后让电表返回数据就可以了&#xff0c;事实上&#xff0c;我们java应用发…

Docker安装milvus及其基本使用说明

简介 Milvus 是一款开源的高性能、高可用的向量数据库&#xff0c;专为大规模机器学习和深度学习应用设计&#xff0c;旨在高效管理和检索高维向量数据。随着AI技术的飞速发展&#xff0c;向量数据库在图像识别、语音识别、自然语言处理、推荐系统等领域扮演着越来越重要的角色…

ssm_mysql_小型企业人事管理系统

收藏关注不迷路&#xff01;&#xff01; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff08;免费咨询指导选题&#xff09;&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多…

25年第四本【认知觉醒】

《认知觉醒》&#xff1a;一场与大脑的深度谈判 在信息爆炸的焦虑时代&#xff0c;我们像被抛入湍流的溺水者&#xff0c;拼命抓取各种自我提升的浮木&#xff0c;却在知识的漩涡中越陷越深。这不是一本简单的成功学指南&#xff0c;而是一场关于人类认知系统的深度对话&#…

盘古信息携手艾罗能源启动IMS数字化智能制造工厂项目,共筑新能源行业数字化标杆

在政策扶持下成长的新能源行业&#xff0c;如今已逐步进入商业化阶段。相比传统制造行业&#xff0c;新能源行业离散度高、自动化程度高。 面对迅疾的市场变化&#xff0c;在大环境中一枝独秀的新能源行业&#xff0c;亟需突破传统架构的限制&#xff0c;通过构建智能化生产体…

32.C++二叉树进阶1(二叉搜索树)

⭐上篇文章&#xff1a;31.C多态4&#xff08;静态多态&#xff0c;动态多态&#xff0c;虚函数表的存储位置&#xff09;-CSDN博客 ⭐本篇代码&#xff1a;c学习/18.二叉树进阶-二叉搜索树 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) ⭐标⭐是比较重要的部分…

图论基础算法: 二分图的判定(C++)

二分图的基本概念 什么是二分图? 二分图(Bipartite Graph)是指一个图的顶点集可以被分割为两个互不相交的子集 U U U 和 V V V, 并且图中的每一条边都连接 U U U 中的一个顶点和 V V V 中的一个顶点. 换句话说, 二分图中的顶点可以被分成两组, 组内的顶点之间没有边相连…

pyside6学习专栏(九):在PySide6中使用PySide6.QtCharts绘制6种不同的图表的示例代码

PySide6的QtCharts类支持绘制各种型状的图表&#xff0c;如面积区域图、饼状图、折线图、直方图、线条曲线图、离散点图等&#xff0c;下面的代码是采用示例数据绘制这6种图表的示例代码,并可实现动画显示效果&#xff0c;实际使用时参照代码中示例数据的格式将实际数据替换即可…

爬虫逆向实战小记——解决webpack实记

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; aHR0cHM6Ly9wbW9zLnhqLnNnY2MuY29tLmNuOjIwMDgwL3B4Zi1zZXR0bGVtZW50LW91dG5ldHB1Yi8jL3B4Zi1zZXR0bGVtZW5…

Hive-优化(语法优化篇)

列裁剪与分区裁剪 在生产环境中&#xff0c;会面临列很多或者数据量很大时&#xff0c;如果使用select * 或者不指定分区进行全列或者全表扫描时效率很低。Hive在读取数据时&#xff0c;可以只读取查询中所需要的列&#xff0c;忽视其他的列&#xff0c;这样做可以节省读取开销…

【三维生成】StarGen:基于视频扩散模型的可扩展的时空自回归场景生成

标题&#xff1a;《StarGen: A Spatiotemporal Autoregression Framework with Video Diffusion Model for Scalable and Controllable Scene Generation》 项目&#xff1a;https://zju3dv.github.io/StarGen 来源&#xff1a;商汤科技、浙大CAD、Tetras.AI 文章目录 摘要一、…

vue2(笔记)4.0vueRouter.声明式/编程式导航以及跳转传参.重定向

---vueRouter 五个步骤: 两个核心: {path:路径,component:组件} 二级路由: 1.在主页路由对象中,添加children配置项 2.准备路由出口 示例代码: {path: /,component: layout,redirect: home,children: [{path: /home,component: home},{path: /card,component: card}]}, 在l…

内网渗透信息收集linuxkali扫描ip段,收集脚本(web安全)

内网ip段扫描↓ 工具1↓ nmap -sn 192.168.128.0/24工具2↓ nbtscan 192.168.128.0/24 工具↓3 arp-scan -t 1000 192.168.128.0/24 cmd命令扫描↓ for /L %I in (1,1,255) Do ping -w 1 -n 1 192.168.128.%I | findstr "TTL" 这个命令在Windows命令提示符下使…

DeepSeek崛起:如何在云端快速部署你的专属AI助手

在2025年春节的科技盛宴上&#xff0c;DeepSeek因其在AI领域的卓越表现成为焦点&#xff0c;其开源的推理模型DeepSeek-R1擅长处理多种复杂任务&#xff0c;支持多语言处理&#xff0c;并通过搜索引擎获取实时信息。DeepSeek因其先进的自然语言处理技术、广泛的知识库和高性价比…

python-leetcode 48.二叉树的最近公共祖先

题目&#xff1a; 给定一个二叉树&#xff0c;找到该树中两个指定节点的最近公共祖先 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff0…