无人驾驶中识别颜色并跟踪的优化(加入PID算法控制)

news2024/11/24 8:55:37

我们了解到无人驾驶是如何去识别颜色的,以及无人车能够跟随颜色目标的演示。回到现实中我们发现,无人车的速度控制是很关键的,这个涉及到安全问题,比如等待红绿灯时,该减速或加速超车等这样很常见的情形,在上节没有体现,这里我们一起来了解下,无人驾驶中是如何自动平稳进行加速和减速的。我们可以先来看一个视频:无人驾驶的速度自动调节

1、实例化摄像头

导入相关的库,然后将摄像头做初始化,如果出现实例化错误的情况,可以查阅:无人车的摄像头的实时捕获图片以及widgets小部件的相关操作

from jetbotmini import Camera
from jetbotmini import bgr8_to_jpeg
from jetbotmini import Robot
import torch
import torchvision
import cv2
import traitlets
import ipywidgets.widgets as widgets
from IPython.display import display
import numpy as np

camera = Camera.instance(width=300, height=300)
global color_lower
global color_upperv
color_lower=np.array([100,43,46])
color_upper = np.array([124, 255, 255])

2、机器人实例化

然后就是将Robot实例化,并导入PID控制算法,用来控制无人车速度快慢的。
关于PID这里再次介绍下:

PID(Proportional-Integral-Derivative)是一种控制器算法,常用于控制工业过程和机器的行为。PID控制器通过测量实际值与期望值之间的差异,并使用比例P、积分I和微分D,这三个系数来计算控制信号,以最小化这个差异。
PID控制器的目的就是通过调整控制信号来使实际输出值与期望输出值保持一致。其中控制信号是通过对误差进行计算得出的,误差是实际输出值与期望输出值之间的差异。

robot = Robot()

import PID

follow_speed = 0.5
turn_gain = 1.7
follow_speed_pid_model = 1
#follow_speed_pid = PID.PositionalPID(3, 0, 0)
follow_speed_pid = PID.PositionalPID(1.5, 0, 0.05)
turn_gain_pid = PID.PositionalPID(0.15, 0, 0.05)

需要注意的是,PID不一定都要出现,可以是PI和PD的组合,也可以只有P这个比例都是可以的,看实际场景来设定。

3、PID算法

我们知道PID是比例,积分与微分,而PID控制器就是通过调整这三者的系数,以平衡响应速度、稳定性和准确性。三者的作用分别如下:

比例系数:调整控制信号的强度,以使系统更快地响应误差。
积分系数:减少系统的稳态误差,使系统更准确地跟踪期望值。
微分系数:用于提高系统的动态性能,使系统更快地响应变化。

在本文将用到的是位置式PID,代码如下:

PID.py

class PositionalPID:
    def __init__(self, P, I, D):
        self.Kp = P
        self.Ki = I
        self.Kd = D
 
        self.SystemOutput = 0.0
        self.ResultValueBack = 0.0
        self.PidOutput = 0.0
        self.PIDErrADD = 0.0
        self.ErrBack = 0.0
    
    #设置PID控制器参数
    def SetStepSignal(self,StepSignal):
        Err = StepSignal - self.SystemOutput
        KpWork = self.Kp * Err
        KiWork = self.Ki * self.PIDErrADD
        KdWork = self.Kd * (Err - self.ErrBack)
        self.PidOutput = KpWork + KiWork + KdWork
        self.PIDErrADD += Err
        self.ErrBack = Err
 
    #设置一阶惯性环节系统  其中InertiaTime为惯性时间常数
    def SetInertiaTime(self, InertiaTime,SampleTime):
        self.SystemOutput = (InertiaTime * self.ResultValueBack + SampleTime * self.PidOutput) / (SampleTime + InertiaTime)
        self.ResultValueBack = self.SystemOutput

还有增量式PID,关于PID的更详细介绍,有兴趣的可以查阅:Jetbotmini中的PID驱动算法控制与代码实现

4、颜色检测与跟踪

这里除了前面移植过来的颜色检测与跟踪之外,还使用了PID控制算法,让无人车对于检测目标的距离来改变车速,当无人车越靠近检测目标速度就会变慢,距离越远速度就会越快,当然这个快也是在一个限速范围内。

image_widget = widgets.Image(format='jpeg', width=300, height=300)

display(widgets.VBox([
    widgets.HBox([image_widget]),
]))

width = int(image_widget.width)
height = int(image_widget.height)
        
def execute(change):
    global follow_speed
    global turn_gain
    global follow_speed_pid
    target_value_speed = 0
    
    #-------------颜色识别处理------------------------------
    frame = camera.value
    frame = 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)
            #控制将机器人向前移动,并控制成比例的目标与中心的x距离
            center = (150 - color_x)/150

            #跟随速度PID调节
            follow_speed_pid.SystemOutput = 90000 * (color_radius/200)
            follow_speed_pid.SetStepSignal(10000)
            follow_speed_pid.SetInertiaTime(0.2, 0.1)

            #转向增益PID调节
            turn_gain_pid.SystemOutput = center
            turn_gain_pid.SetStepSignal(0)
            turn_gain_pid.SetInertiaTime(0.2, 0.1)

            #将转向增益限制在有效范围内
            target_value_turn_gain = 0.2 + abs(turn_gain_pid.SystemOutput)
            if target_value_turn_gain < 0:
                target_value_turn_gain = 0
            elif target_value_turn_gain > 2:
                target_value_turn_gain = 2

            #将输出电机速度保持在有效行驶范围内
            target_value_speed = 0.8 + follow_speed_pid.SystemOutput / 90000
            target_value_speedl = target_value_speed - target_value_turn_gain * center
            target_value_speedr = target_value_speed + target_value_turn_gain * center
            if target_value_speedl<0.3:
                target_value_speedl=0
            elif target_value_speedl>1:
                target_value_speedl = 1
            if target_value_speedr<0.3:
                target_value_speedr=0
            elif target_value_speedr>1:
                target_value_speedr = 1

            robot.set_motors(target_value_speedl, target_value_speedr)
    # 没有检测到目标
    else:
        robot.forward(float(follow_speed))
        #robot.stop()
        
    # 更新图像显示至小部件
    image_widget.value = bgr8_to_jpeg(frame)

execute({'new': camera.value})

这里的实现原理就是当检测目标距离越远的时候,标注的圆圈就变小了,也就是半径小了,同理,当距离越近的时候,圆圈就变得越大,圆圈半径就越大,就是根据这个半径的大小来控制车速,如下图:

5、实时更新

然后使用camera.observe来调用execute这个回调函数,实时的更新画面,这样就做到了跟踪颜色目标的效果了。

camera.unobserve_all()
camera.observe(execute, names='value')

需要断开摄像头与停止机器人的时候,执行下面代码即可:

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

从上面我们可以看到,和前面的比较,我们的优化是加了一个关键应用,增加了PID控制方法,在本文是使用了位置式PID(Positional PID),其余代码跟上节是一样的。这样就会让无人车在行驶过程中,遇到障碍等都会平稳减速,另外需要加速也不会突然加速,这样乘坐体验会好很多。

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

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

相关文章

论文笔记--OpenPrompt: An Open-source Framework for Prompt-learning

论文笔记--OpenPrompt: An Open-source Framework for Prompt-learning 1. 文章简介2. 文章概括3 文章重点技术4. 文章亮点5. 原文传送门 1. 文章简介 标题&#xff1a;OpenPrompt: An Open-source Framework for Prompt-learning作者&#xff1a;Ning Ding, Shengding Hu, We…

基于Java+SpringBoot+vue前后端分离在线视频教育平台设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Leecode316: 去除重复字母

下面这里使用有序map——TreeMap来实现Map接口&#xff0c;但是相对顺序是不能改变的&#xff01;这样会使得后面的跑到前面去&#xff0c;所以有问题 最简单的思想肯定是暴力思想&#xff0c;就是从前往后寻找&#xff0c;一旦遇到存在的情况就. 重点在于明确两点&#xff1a…

HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 五)

Styles装饰器&#xff1a;定义组件重用样式 如果每个组件的样式都需要单独设置&#xff0c;在开发过程中会出现大量代码在进行重复样式设置&#xff0c;虽然可以复制粘贴&#xff0c;但为了代码简洁性和后续方便维护&#xff0c;我们推出了可以提炼公共样式进行复用的装饰器St…

【LLM】self-instruct 构建指令微调数据集

文章目录 一、self-instruct流程二、具体过程1. 指令生成2. 分类任务识别3. 实例生成4. 过滤和后处理 三、其他部分1. 验证数据质量2. GPT3SELF-INSTRUCT生成数据的词性分析3. Rouge-L指标 Reference 一、self-instruct流程 四部曲&#xff1a;指令生成&#xff1b;分类任务识别…

Oracle 的视图

Oracle 的视图 源数据&#xff1a; -- Create table create table STU_INFO (id NUMBER not null,name VARCHAR2(8),score NUMBER(4,1),class VARCHAR2(2) ) tablespace STUDENTpctfree 10initrans 1maxtrans 255storage(initial 64Knext 1Mminextents 1maxextents unlim…

最多变的混合模式-实色混合HardMix

最多变的混合模式-实色混合HardMix 之前写过一篇介绍27种图层混合模式的非常详细&#xff0c;如果你想完全了解底层的原理&#xff0c;这篇文章不会让你失望。 PS图层混合模式超详细解答-图层混合模式的原理 - 王先生的副业的文章 - 知乎 https://zhuanlan.zhihu.com/p/64396…

从小白到大神之路之学习运维第63天--------zabbix企业级监控(概述、单台服务器监控本身安装部署)

第三阶段基础 时 间&#xff1a;2023年7月18日 参加人&#xff1a;全班人员 内 容&#xff1a; zabbix企业级监控 目录 一、Zabbix概述 &#xff08;一&#xff09;Zabbix简介 &#xff08;二&#xff09;Zabbix运行条件&#xff1a; &#xff08;三&#xff09;Zab…

深入解析 YAML 配置文件:从语法到最佳实践

一、认识YAML YAML&#xff08;YAML Aint Markup Language&#xff09;是一种人类可读的数据序列化语言。它的设计目标是使数据在不同编程语言之间交换和共享变得简单。YAML采用了一种简洁、直观的语法&#xff0c;以易于阅读和编写的方式表示数据结构。YAML广泛应用于配置文件…

探索开源图片编辑工具:定制化编辑,激发想象

图片编辑是现代生活中广泛使用的技术&#xff0c;它不仅能够改善照片和图像的质量&#xff0c;还能创造出令人赞叹的视觉效果。随着开源文化的兴起&#xff0c;越来越多的开源工具涌现出来&#xff0c;为我们提供了实用且灵活的图片编辑功能。这些开源工具的出现为个人、设计师…

想用vivo手机设置一个5天后提醒我的闹铃,怎么设置?

在生活和工作中有很多待办事项&#xff0c;都不是需要当前立刻就去完成的&#xff0c;而且需要我们提前记住&#xff0c;并且在未来的某个指定日期去完成&#xff0c;例如两天后提交项目报告、下周五的重要会议、考试报名时间等。如果担心自己忘记这些待办事项&#xff0c;应该…

android APP外包开发的三种方式

开发android APP有三种方式&#xff0c;分别是原生开发、混合开发和无代码开发&#xff0c;原生开发对开发者有一定要求&#xff0c;但用户体验好&#xff1b;混合开发是使用H5开发&#xff0c;对开发者要求相对较低&#xff1b;而无代码开发则是通过操作界面搭建APP&#xff0…

openGauss学习笔记-13 openGauss 简单数据管理-DELETE语句

文章目录 openGauss学习笔记-13 openGauss 简单数据管理-DELETE语句13.1 语法格式13.2 参数说明13.3 示例 openGauss学习笔记-13 openGauss 简单数据管理-DELETE语句 DELETE语句可以从指定的表里删除满足WHERE子句的行。如果WHERE子句不存在&#xff0c;将删除表中所有行&…

传输层协议—网络

文章目录 1.TCP1.1TCP协议段格式1.2可靠机制1.2.1确认应答机制1.2.2超时重传机制1.2.3连接管理机制1.2.4流量控制机制1.2.5拥塞控制机制 1.3效率机制1.3.1滑动窗口机制1.3.2延迟应答机制1.3.3捎带应答机制 1.4粘包问题&#xff08;tcp问题&#xff0c;应用层的数据包&#xff0…

JMeter 性能测试实例分析

一、性能测试分类&#xff1a; 1、基准测试 2、并发测试 3、负载测试 4、压力测试 1、基准测试&#xff1a; 也是单用户测试&#xff0c;测试环境确定以后&#xff0c;对业务模型中的重要业务做单独的测试&#xff0c;获取单用户运行时的各项性能指标&#xff0c;为多用户…

C# 细说async/await的用法

目录 一&#xff0c;引言 二&#xff0c;实例演示 2.1 多线程同步执行下载任务&#xff0c;任务完成后通知 2.2 异步执行下载任务&#xff0c;任务完成后通知 三&#xff0c;async/await的用法 3.1 跨线程修改UI控件 3.2 异步获取数据 一&#xff0c;引言 首先先来区分…

【Go】实现一个代理Kerberos环境部分组件控制台的Web服务

实现一个代理Kerberos环境部分组件控制台的Web服务 背景安全措施引入的问题SSO单点登录 过程整体设计路由反向代理登录会话组件代理YarnHbase 结果 背景 首先要说明下我们目前有部分集群的环境使用的是HDP-3.1.5.0的大数据集群&#xff0c;除了集成了一些自定义的服务以外&…

python opencv 级联Haar多目标检测

一、基于OpenCV的haar分类器实现笑脸检测 1、Haar分类器介绍 &#x1f680;Haar分类器是一种基于机器学习的目标检测算法&#xff0c;它使用Haar特征描述图像中的目标。Haar特征是基于图像亮度的局部差异计算得出的&#xff0c;可以用来描述目标的边缘、角落和线条等特征。 使用…

Jenkins (一)

Jenkins (一) Docker Jenkins 部署 一. 安装 jenkins $ mkdir -p /home/tester/data/docker/jenkins $ vim jenkins:lts-jdk11.sh./jenkins:lts-jdk11.sh 内容 #! /bin/bash mkdir -p /home/tester/data/docker/jenkins/jenkins_homesudo chown -R 1000:1000 /home/tester/da…

利用LightHouse进行合理的页面性能优化,看这一篇就够了!

利用LightHouse进行合理的页面性能优化&#xff0c;看这一篇就够了&#xff01; 前言一. Lighthouse下载1.1 相关指标概念1.2 Lighthouse 优化建议 二. 跟着 Lighthouse 进行性能优化2.1 Enable text compression 开启文本压缩2.2 Resize images 重新设定合适大小的图片2.3 Eli…