当前位置: 首页 > news >正文

无人车沿着指定线路自动驾驶与远程控制的实践应用

有了前面颜色识别跟踪的基础之后,我们就可以设定颜色路径,让无人车沿着指定线路做自动驾驶了,视频:PID控制无人车自动驾驶

有了前几章的知识铺垫,就比较简单了,也是属于颜色识别的一种应用,主要是掌握自动驾驶中的一些基础知识,这样就可以进一步去了解在无人驾驶当中遇到的各种问题

1、导入库并初始化

from jetbotmini import Camera
from jetbotmini import bgr8_to_jpeg
from IPython.display import display
from jetbotmini import Robot
import numpy as np
import torch
import torchvision
import cv2
import traitlets
import ipywidgets.widgets as widgets
import numpy as np#初始化摄像头
camera = Camera.instance(width=300, height=300)
#初始化机器人马达
robot = Robot()#使用PID控制
import PIDturn_gain = 1.7
turn_gain_pid = PID.PositionalPID(0.15, 0, 0.05)

这部分很简单,依然是初始化摄像头用来颜色识别,机器人也叫马达,用来驱动轮子的运动,加一个PID控制,让无人车更加的平稳。

2、显示部件

# 红色数组
color_lower=np.array([156,43,46])
color_upper = np.array([180, 255, 255])image_widget = widgets.Image(format='jpeg', width=300, height=300)
speed_widget = widgets.FloatSlider(value=0.4, min=0.0, max=1.0, description='speed')display(widgets.VBox([widgets.HBox([image_widget]),speed_widget,
]))width = int(image_widget.width)
height = int(image_widget.height)def execute(change):global turn_gaintarget_value_speed = 0#更新图片值frame = camera.valueframe = cv2.resize(frame, (300, 300))frame = cv2.GaussianBlur(frame,(5,5),0)                    hsv =cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)mask=cv2.inRange(hsv,color_lower,color_upper)  mask=cv2.erode(mask,None,iterations=2)mask=cv2.dilate(mask,None,iterations=2)mask=cv2.GaussianBlur(mask,(3,3),0)     cnts=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2] # 检测到目标if len(cnts)>0:cnt = max (cnts,key=cv2.contourArea)(color_x,color_y),color_radius=cv2.minEnclosingCircle(cnt)if color_radius > 10:# 将检测到的颜色标记出来cv2.circle(frame,(int(color_x),int(color_y)),int(color_radius),(255,0,255),2)  # 中心偏移量center = (150 - color_x)/150#转向增益PID调节turn_gain_pid.SystemOutput = centerturn_gain_pid.SetStepSignal(0)turn_gain_pid.SetInertiaTime(0.2, 0.1)#将转向增益限制在有效范围内target_value_turn_gain = 0.15 + abs(turn_gain_pid.SystemOutput)if target_value_turn_gain < 0:target_value_turn_gain = 0elif target_value_turn_gain > 2:target_value_turn_gain = 2#将输出电机速度保持在有效行驶范围内target_value_speedl = speed_widget.value - target_value_turn_gain * centertarget_value_speedr = speed_widget.value + target_value_turn_gain * centerif target_value_speedl<0.3:target_value_speedl=0elif target_value_speedl>1:target_value_speedl = 1if target_value_speedr<0.3:target_value_speedr=0elif target_value_speedr>1:target_value_speedr = 1#设置马达速度robot.set_motors(target_value_speedl, target_value_speedr)# 没有检测到目标else:robot.stop()# 更新图像显示至小部件image_widget.value = bgr8_to_jpeg(frame)

这里是关键部分,检测目标(这里是红颜色),然后通过其检测的位置来控制左右马达的速度,驱动无人车的行驶与转弯,后台通过图像部件来显示无人车的跟踪情况,方便看到无人车在整个行驶过程中的各种状态。

3、调用并执行

execute({'new': camera.value})
camera.unobserve_all()
camera.observe(execute, names='value')

这里就是前面介绍的,通过调用observer方法来更新摄像头的数据,使用的是一个上面定义的execute的一个回调方法。

4、停止无人车

import time
camera.unobserve_all()
time.sleep(1.0)
robot.stop()

5、倒车

前面介绍的是向前行驶和转弯,还缺少一个能倒车的功能,恩,很简单,调用backward函数即可

robot.backward(0.8)
time.sleep(0.5)
robot.stop()

6、调节颜色数组

我这里是用红色的胶带粘贴在地板上,所以使用的是红色的数组,当然这里我们可以显示mask来测试颜色数组是否设置的比较恰当,代码如下

from  matplotlib import pyplot as plt
%matplotlib inline
from IPython import displayfor i in range(10):frame = camera.valueframe = cv2.resize(frame, (300, 300))frame_=cv2.GaussianBlur(frame,(5,5),0)                    hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)mask=cv2.inRange(hsv,color_lower,color_upper) # 颜色数组的取值范围mask=cv2.erode(mask,None,iterations=2)mask=cv2.dilate(mask,None,iterations=2)mask=cv2.GaussianBlur(mask,(3,3),0)  plt.imshow(mask)plt.show()#display.clear_output(wait=True)

这里我将display.clear_output(wait=True)注释,将会连续生成10张图片,全部在Jupyter中展示出来。我们也可以去掉注释,这样每次的生成将会清除上一次的图片,这样便于更好地观察。10张连续图片也做成了动图便于大家了解:

 如果这里没有出现mask或者比较少的情况,就需要调节颜色数组,让其更好地匹配线路。

7、模拟方向盘

有些时候不想要自动驾驶来控制,而且很多场景更需要人来远程控制,比如在矿山等危险地方,最好的方法就是能够远程去控制工程车去进行作业。
有了上面的向前向后和转弯的了解后,我们就可以制作一个模拟方向盘来控制无人车了。

7.1、按钮部件

# 创建按钮
button_layout = widgets.Layout(width='100px', height='80px', align_self='center')
stop_button = widgets.Button(description='停止', button_style='danger', layout=button_layout)
forward_button = widgets.Button(description='向前', layout=button_layout)
backward_button = widgets.Button(description='向后', layout=button_layout)
left_button = widgets.Button(description='向左', layout=button_layout)
right_button = widgets.Button(description='向右', layout=button_layout)# 显示按钮
middle_box = widgets.HBox([left_button, stop_button, right_button], layout=widgets.Layout(align_self='center'))
controls_box = widgets.VBox([forward_button, middle_box, backward_button])
display(controls_box)

如图:

方向盘的布局,通过widgets.Layout创建层,在这个上面通过widgets.Button创建按钮,然后将按钮通过widgets.HBoxwidgets.VBox进行横向和垂直的排版即可。Horizontal:水平的,横向。Vertical:垂直的

7.2、方向控制方法

def stop(change):robot.stop()def step_forward(change):robot.forward(0.8)time.sleep(0.5)robot.stop()def step_backward(change):robot.backward(0.8)time.sleep(0.5)robot.stop()def step_left(change):robot.left(0.6)time.sleep(0.5)robot.stop()def step_right(change):robot.right(0.6)time.sleep(0.5)robot.stop()

前后左右加停止按钮的方法,方法体很简单,就是控制左右马达的速度。

7.3、按钮动作

定义好了各自方法之后,只需要将方法绑定到各自的按钮就可以了。

stop_button.on_click(stop)
forward_button.on_click(step_forward)
backward_button.on_click(step_backward)
left_button.on_click(step_left)
right_button.on_click(step_right)

这样就可以点击按钮,远程控制无人车了。

8、心跳开关

最后就是介绍下心跳开关,检测无人车与浏览器的连接是否还存在的一种简单方法。可以通过下面显示的滑块调整心跳周期(以秒为单位),如果两次心跳之内不能在浏览器之间往返通信的,那么心跳的status(状态)属性值将会设置为dead,一旦连接恢复连接,status属性将设置为alive

from jetbotmini import Heartbeatheartbeat = Heartbeat()# 这个函数将在心跳状态改变时被调用
def handle_heartbeat_status(change):if change['new'] == Heartbeat.Status.dead:robot.stop()heartbeat.observe(handle_heartbeat_status, names='status')period_slider = widgets.FloatSlider(description='period', min=0.001, max=0.5, step=0.01, value=0.5)
traitlets.dlink((period_slider, 'value'), (heartbeat, 'period'))display(period_slider, heartbeat.pulseout)

 自动驾驶的相关知识点介绍完毕,有错误之处,请指正,一起学习与进步!

相关文章:

无人车沿着指定线路自动驾驶与远程控制的实践应用

有了前面颜色识别跟踪的基础之后&#xff0c;我们就可以设定颜色路径&#xff0c;让无人车沿着指定线路做自动驾驶了&#xff0c;视频&#xff1a;PID控制无人车自动驾驶 有了前几章的知识铺垫&#xff0c;就比较简单了&#xff0c;也是属于颜色识别的一种应用&#xff0c;主要…...

C++ 多态性——纯虚函数与抽象类

抽象类是一种特殊的类&#xff0c;它为一个类族提供统一的操作界面。抽象类是为了抽象和设计的目的而建立的。可以说&#xff0c;建立抽象类&#xff0c;就是为了通过它多态地使用其中的成员函数。抽象类处于类层次的上层&#xff0c;一个抽象类自身无法实例化&#xff0c;也就…...

小程序如何使用防抖和节流?

防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;都是用来优化函数执行频率的技术&#xff0c;特别在处理用户输入、滚动等频繁触发的情况下&#xff0c;它们可以有效减少函数的执行次数&#xff0c;从而提升性能和用户体验。但它们的工作方式和应…...

计算机三级网络技术(持续更新)

BGP考点 A S&#xff1a;自治系统 BGP: Border Gateway Protocol&#xff08;当前使用的版本是 BGP-4&#xff09;外部网关协议 动态路由协议可以按照工作范围分为IGP以及EGP。IGP工作在同一个AS内&#xff0c;主要用来发现和计算路由&#xff0c;为AS内提供路由信息的交换&…...

Django Rest_Framework(二)

文章目录 1. http请求响应1.1. 请求与响应1.1.1 Request1.1.1.1 常用属性1&#xff09;.data2&#xff09;.query_params3&#xff09;request._request 基本使用 1.1.2 Response1.1.2.1 构造方式1.1.2.2 response对象的属性1&#xff09;.data2&#xff09;.status_code3&…...

Kotlin~Visitor访问者模式

概念 将数据结构和操作分离&#xff0c;使操作集合可以独立于数据结构变化。 角色介绍 Visitor&#xff1a;抽象访问者&#xff0c;为对象结构每个具体元素类声明一个访问操作。Element&#xff1a;抽象元素&#xff0c;定义一个accept方法ConcreteElement&#xff1a;具体元…...

LVS-DR模式集群构建过程演示

一、工作原理 LVS的工作原理 1.当用户向负载均衡调度器&#xff08;Director Server&#xff09;发起请求&#xff0c;调度器将请求发往至内核空间 2.PREROUTING链首先会接收到用户请求&#xff0c;判断目标IP确定是本机IP&#xff0c;将数据包发往INPUT链 3.IPVS是工作在IN…...

UML-A 卷-知识考卷

UML-A 卷-知识考卷 UML有多少种图&#xff0c;请列出每种图的名字&#xff1a; 常用的几种UML图&#xff1a; 类图&#xff08;Class Diagram&#xff09;&#xff1a;类图是描述类、接口、关联关系和继承关系的图形化表示。它展示了系统中各个类之间的静态结构和关系。时序…...

BpBinder与PPBinder调用过程——Android开发Binder IPC通信技术

在Android系统中&#xff0c;进程间通信&#xff08;IPC&#xff09;是一个非常重要的话题。Android系统通过Binder IPC机制实现进程间通信&#xff0c;而Binder IPC通信技术则是Android系统中最为重要的进程间通信技术之一。本文将介绍Binder IPC通信技术的原理&#xff0c;并…...

篇十五:模板方法模式:固定算法的步骤

篇十五&#xff1a;"模板方法模式&#xff1a;固定算法的步骤" 设计模式是软件开发中的重要知识&#xff0c;模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为型设计模式&#xff0c;用于定义一个算法的骨架&#xff0c;将算法中一些步骤的具…...

web-ssrf

目录 ssrf介绍 以pikachu靶场为例 curl 访问外网链接 利用file协议查看本地文件 利用dict协议扫描内网主机开放端口 file_get_content 利用file协议查看本地文件&#xff1a; fsockopen() 防御方式: ssrf介绍 服务器端请求伪造&#xff0c;是一种由攻击者构造形成…...

【HarmonyOS】【续集】实现从视频提取音频并保存到pcm文件功能(API6 Java)

【关键字】 视频提取类Extractor、视频编解码、保存pcm文件、getAudioTime 【背景和问题】 上篇中介绍了从视频提取音频并保存到pcm文件功能&#xff0c;请参考文档&#xff1a;https://developer.huawei.com/consumer/cn/forum/topic/0209125665541017202?fid0101591351254…...

MySQL为什么要使用 B+Tree 作为索引结构?

MySQL为什么要使用 BTree 作为索引结构&#xff1f; 基本情况 常规的数据库存储引擎 &#xff0c;一般都是采用 B 树或者 B树来实现索引的存储。B树是一种多路平衡树&#xff0c;用这种存储结构来存储大量数据&#xff0c;它的整个高度 会相比二叉树来说 &#xff0c;会矮很多…...

Three.js阴影

目录 Three.js入门 Three.js光源 Three.js阴影 使用灯光后&#xff0c;场景中就会产生阴影。物体的背面确实在黑暗中&#xff0c;这称为核心阴影&#xff08;core shadow&#xff09;。我们缺少的是落下的阴影&#xff08;drop shadow&#xff09;&#xff0c;即对象在其他…...

VSCode Remote-SSH (Windows)

1. VSCode 安装 VSCode 2. 安装扩展 Remote SSH Getting started Follow the step-by-step tutorial or if you have a simple SSH host setup, connect to it as follows: Press F1 and run the Remote-SSH: Open SSH Host… command.Enter your user and host/IP in the …...

现代C++中的从头开始深度学习【1/8】:基础知识

一、说明 提及机器学习框架与研究和工业的相关性。现在很少有项目不使用Google TensorFlow或Meta PyTorch&#xff0c;在于它们的可扩展性和灵活性。也就是说&#xff0c;花时间从头开始编码机器学习算法似乎违反直觉&#xff0c;即没有任何基本框架。然而&#xff0c;事实并非…...

Jwt(Json web token)——使用token的权限验证方法 用户+角色+权限表设计 SpringBoot项目应用

目录 引出使用token的权限验证方法流程 用户、角色、权限表设计权限表角色表角色-权限关联表用户表查询用户的权限&#xff08;四表联查&#xff09;数据库的视图 项目中的应用自定义注解拦截器controller层DTO返回给前端枚举类型的json化日期json问题 实体类-DAO 总结 引出 1.…...

SpringWeb项目核心功能总结

SpringWeb项目核心功能总结 文章目录 SpringWeb项目核心功能总结1.浏览器与Java程序的连接&#xff08;个人偏好使用RequestMapping&#xff09;2.参数的传入3.结果的返回请求转发和请求重定向的区别 核心功能用到的注解&#xff1a; RestControllerControllerResponseBodyRequ…...

Django------信号

Django 框架包含了一个信号机制&#xff0c;它允许若干个发送者&#xff08;sender&#xff09;通知一组接收者&#xff08;receiver&#xff09;某些特定操作或事件(events)已经发生了&#xff0c; 接收者收到指令信号(signals)后再去执行特定的操作。本文主要讲解Django信号(…...

HTML5 中新增了哪些表单元素?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ HTML5 中新增了的表单元素⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...