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

基于Openmv的追小球的云台

介绍

在这篇文章,我会先介绍需要用到且需要注意的函数,之后再给出整体代码

在追小球的云台中,比较重要的部分就是云台(实质上就是舵机)的控制以及对识别的色块位置进行处理得到相应信息后控制云台进行运动

1、舵机模块和PID模块的导入

需要注意的是,PID还需要官方提供的PID文件(当然你要是把整体代码全部移植过来也是可以的)

from pyb import PID
from pyb import Servo

2、初始化舵机端口

这里初始化舵机端口,我的理解是就相当于一个宏定义

sp_servo=Servo(1)
cz_servo=Servo(2)

3、校准舵机,设置PWM信号的范围

sp_servo.calibration(500, 2500, 1500)
cz_servo.calibration(500, 2500, 1500)

这里的代码根据之前的初始化舵机端口名字来写,不同名不一样

这里用到的函数是

Servo.calibration([pulse_min,pulse_max,pulse_centre[,pulse_angle_90,pulse_speed_100]])

它后面的两个参数不需要用到,我们只对前三个参数进行说明

pulse_min:设置的最小脉冲宽度

pulse_max:设置的最大脉冲宽度

pulse_centre:中心(90度)\0度对应的位置

4、初始化PID控制器

PID控制器的初始化分为两种情况

情况1是在上机调试时的情况,情况2时在脱机运行时的情况

按道理来说,上机调试时由于数据的传输是需要时间的,也就是实时数据的获取存在延迟;而脱机运行时数据的传输更快,延迟更小

根据实时数据获取的延迟来看,在脱机运行时,由于数据传输的实时性很好,所以PID参数可以采用大一些的值;同理,在上机调试时,由于数据的实时性较差,所以采用更小的PID参数来进行调节

根据我上面的阐述,在设置PID参数时,脱机设置较大值,上机设置较小值;不知道是不是官方给出的代码出现了错误,它给出来的PID参数设置与我上述设置相反(我也不确定到底是谁错了)

 sp_pid = PID(p=0.1, i=0, imax=90)cz_pid = PID(p=0.1, i=0, imax=90)

5、判断最大色块

由于在进行小球的追踪时,肯定会有其他小球之外的色块存在,所以在这个时候,我们只对最大的色块进行处理(默认最大色块为小球)

def find_max(blobs):max_size = 0max_blob = Nonefor blob in blobs:if blob[2] * blob[3] > max_size:max_blob = blobmax_size = blob[2] * blob[3]return max_blob

对于判断最大色块,我们定义了一个函数find_max(blobs)来寻找最大色块

在这判断色块大小是根据色块查找函数find_blobs(thresholds)返回的blob对象列表的值来确定的

在Openmv官方例程和函数库中并没有给出blob对象的值,所以我们我们自己写一个色块寻找程序,并打印出blob对象的值

可以看到blob对象的值如下图所示 

所以blob[2]、[3]分别是blob对象的第3、4个参数,也就是色块的宽度和色块的高度,两个参数相乘即为色块的面积

6、误差的获取

通过用最大色块返回的中心坐标值减去图像中心坐标值,获得误差

sp_error = max_blob.cx() - img.width() / 2
cz_error = max_blob.cy() - img.height() / 2

7、误差的处理

 sp_output = sp_pid.get_pid(sp_error, 1) / 2cz_output = cz_pid.get_pid(cz_error, 1)sp_servo.angle(sp_servo.angle() + sp_output)cz_servo.angle(cz_servo.angle() - cz_output)

对误差的控制引入了PID的控制,在这里我就不对涉及pid.py文件的部分作说明,这两天会再写一篇文章对该文件及PID算法进行说明

8、main.py代码

import sensor,image,time
from pyb import PID
from pyb import Servo#初始化用于平移和倾斜的舵机(我的理解是这里就是做了一个宏定义)
sp_servo=Servo(1)
cz_servo=Servo(2)# 校准舵机,设置PWM信号占空比的范围
sp_servo.calibration(500, 2500, 1500)
cz_servo.calibration(500, 2500, 1500)# 初始化平移和倾斜的PID控制器
# 脱机运行或者禁用图像传输时使用这些PID值
sp_pid = PID(p=0.07, i=0, imax=90)
cz_pid = PID(p=0.05, i=0, imax=90)# 如果在线调试,使用这些PID值,之所以在线调试和脱机调试用不一样的PID参数,是因为在线调试数据有延迟
# pan_pid = PID(p=0.1, i=0, imax=90)
# tilt_pid = PID(p=0.1, i=0, imax=90)sensor.reset()  # 初始化摄像头传感器
sensor.set_pixformat(sensor.RGB565)  # 设置像素格式为RGB565
sensor.set_framesize(sensor.QQVGA)  # 设置分辨率为QQVGA以提高速度
sensor.skip_frames(1000)  # 让新设置生效
sensor.set_auto_whitebal(False)  # 关闭自动白平衡
sensor.set_auto_gain(False)  #关闭自动增益
clock = time.clock()  # 跟踪每秒帧数(FPS)#根据find_blobs()函数返回的blob列表的blob对象的第3、4个参数分别是像素的宽和高
def find_max(blobs):#每次调用该函数都会对参数作初始化max_size = 0max_blob = Nonefor blob in blobs:if blob[2] * blob[3] > max_size:max_blob = blobmax_size = blob[2] * blob[3]return max_blobwhile(True):clock.tick()  # 跟踪每次快照之间经过的毫秒数img = sensor.snapshot()  # 拍照并返回图像blobs = img.find_blobs([red_threshold])#如果识别到了色块if blobs:max_blob = find_max(blobs)#计算水平方向和垂直方向和图像中心的距离作为误差值sp_error = max_blob.cx() - img.width() / 2cz_error = max_blob.cy() - img.height() / 2print("sp_error:", sp_error)print("cz_error:", cz_error)img.draw_rectangle(max_blob.rect())  # 画出矩形img.draw_cross(max_blob.cx(), max_blob.cy())  # 画出十字sp_output = sp_pid.get_pid(sp_error, 1) / 2cz_output = cz_pid.get_pid(cz_error, 1)print("sp_output:", sp_output)print("cz_output:", cz_output)sp_servo.angle(sp_servo.angle() + sp_output)cz_servo.angle(cz_servo.angle() - cz_output)

9、pid.py代码

from pyb import millis  # 导入 pyboard 的 millis 函数,用于获取当前时间(毫秒)
from math import pi, isnan  # 导入 pi 和 isnan 函数class PID:# 定义 PID 控制器的参数和状态变量_kp = _ki = _kd = _integrator = _imax = 0_last_error = _last_derivative = _last_t = 0_RC = 1/(2 * pi * 20)  # RC 低通滤波器的时间常数def __init__(self, p=0, i=0, d=0, imax=0):# 初始化 PID 控制器的参数self._kp = float(p)  # 比例系数self._ki = float(i)  # 积分系数self._kd = float(d)  # 微分系数self._imax = abs(imax)  # 积分限制,防止积分饱和self._last_derivative = float('nan')  # 最后的导数值初始化为 NaNdef get_pid(self, error, scaler):tnow = millis()  # 获取当前时间dt = tnow - self._last_t  # 计算时间差output = 0  # 初始化输出值if self._last_t == 0 or dt > 1000:  # 如果是第一次运行或者时间差大于 1 秒dt = 0  # 重置时间差self.reset_I()  # 重置积分器self._last_t = tnow  # 更新最后时间戳delta_time = float(dt) / float(1000)  # 将时间差转换为秒output += error * self._kp  # 计算比例项if abs(self._kd) > 0 and dt > 0:  # 如果微分系数大于 0 且时间差大于 0if isnan(self._last_derivative):  # 如果最后的导数值为 NaNderivative = 0  # 设置导数为 0self._last_derivative = 0  # 重置最后的导数值else:derivative = (error - self._last_error) / delta_time  # 计算误差的导数# 使用低通滤波器平滑导数值derivative = self._last_derivative + ((delta_time / (self._RC + delta_time)) * (derivative - self._last_derivative))self._last_error = error  # 更新最后的误差值self._last_derivative = derivative  # 更新最后的导数值output += self._kd * derivative  # 计算微分项并加到输出中output *= scaler  # 按比例缩放输出值if abs(self._ki) > 0 and dt > 0:  # 如果积分系数大于 0 且时间差大于 0self._integrator += (error * self._ki) * scaler * delta_time  # 计算积分项并加到积分器中# 限制积分器的值在 -imax 和 imax 之间,防止积分饱和if self._integrator < -self._imax:self._integrator = -self._imaxelif self._integrator > self._imax:self._integrator = self._imaxoutput += self._integrator  # 将积分项加到输出中return output  # 返回计算的 PID 控制器输出值def reset_I(self):self._integrator = 0  # 重置积分器self._last_derivative = float('nan')  # 重置最后的导数值为 NaN

结语

如果大家发现有什么不对的地方,请斧正!

相关文章:

基于Openmv的追小球的云台

介绍 在这篇文章&#xff0c;我会先介绍需要用到且需要注意的函数&#xff0c;之后再给出整体代码 在追小球的云台中&#xff0c;比较重要的部分就是云台&#xff08;实质上就是舵机&#xff09;的控制以及对识别的色块位置进行处理得到相应信息后控制云台进行运动 1、舵机模…...

关于scrapy模块中setting.py文件的介绍

作用 在Scrapy框架中&#xff0c;settings.py 文件起着非常重要的作用&#xff0c;它用于配置和控制整个Scrapy爬虫项目的行为、性能和功能。 setting.py文件的介绍 # Scrapy settings for haodaifu project # # For simplicity, this file contains only settings consider…...

laravel Blade 指令的趣味性

首先&#xff0c;我们通过几个要点来解释 Blade 引擎的工作原理。 您选择一个 Blade 模板进行渲染。引擎使用一系列正则表达式来解析和编译模板。该引擎生成一个普通的 PHP 文件并将其写入磁盘&#xff08;以便将其缓存以供将来渲染&#xff09;。包含 PHP 文件并使用输出缓冲…...

【面试题】等保(等级保护)的工作流程

等保&#xff08;等级保护&#xff09;的工作流程主要包括以下几个步骤&#xff0c;以下将详细分点介绍&#xff1a; 系统定级&#xff1a; 确定定级对象&#xff1a;根据《信息系统等级保护管理办法》和《信息系统等级保护定级指南》的要求&#xff0c;确定需要进行等级保护的…...

python调用麦克风和扬声器,并调用阿里云实时语音转文字

import time import queue import sounddevice as sd import numpy as np import nls import sys# 阿里云配置信息 URL "wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1" TOKEN "XXXX" # 参考https://help.aliyun.com/document_detail/450255.html获…...

描述在React中集成第三方库(如Redux或React Router)的常见模式。

在React中集成第三方库&#xff0c;如状态管理库Redux或路由库React Router&#xff0c;通常遵循一些常见的模式和最佳实践。下面是一些集成这些库的步骤和模式&#xff1a; 集成Redux 安装Redux及相关包: 安装Redux及其中间件&#xff08;如redux-thunk或redux-saga&#xf…...

JavaScript语法特性篇-空值合并运算符(??)

1、基本使用 空值合并运算符&#xff08;??&#xff09;英文名称为 Nullish coalescing operator&#xff0c;是一个逻辑运算符。 特性&#xff1a;当左侧的操作数为 null 或者 undefined 时&#xff0c;返回其右侧操作数&#xff0c;否则返回左侧操作数。 const foo nul…...

rancher快照备份至S3

巧用rancher的S3快照备份功能&#xff0c;快速实现集群复制、集群转移、完全崩溃后的极限修复 1.进入集群管理&#xff0c;在对应的集群菜单后&#xff0c;点击编辑配置 2.选择ETCD&#xff0c;启用&#xff0c;Backup Snapshots to S3选项 并填入你的minio 3 配置成功后 手…...

ChatGPT API教程在线对接OpenAI APIKey技术教程

一、OpenAI基本库介绍 您可以通过 HTTP 请求与 API 进行交互&#xff0c;这可以通过任何编程语言实现。我们提供官方的 Python 绑定、官方的 Node.js 库&#xff0c;以及由社区维护的库。 要安装官方的 Python 绑定&#xff0c;请运行以下命令&#xff1a; pip install open…...

随心而遇,跟着感觉走

分数限制下&#xff0c;选好专业还是选好学校&#xff1f; 24年高考结束&#xff0c;很多学生犹豫选择专业还是好学校&#xff0c;我的建议是&#xff0c;选择好学校。 本人体验来说&#xff0c;电子&#xff0c;工地&#xff0c;计科&#xff0c;数学&#xff0c;工科相关的…...

LeetCode题练习与总结:只出现一次的数字--136

一、题目描述 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且该算法只使用常量额外空间。 示例 1 &#xff1a; …...

常见的中间件都在解决什么问题?

常见的中间件都在解决什么问题 RocketMQ RocketMQ 是一款功能强大的分布式消息系统。 RocketMQ 源码地址&#xff1a;https://github.com/apache/rocketmq(opens new window) RocketMQ 官方网站&#xff1a;https://rocketmq.apache.org 什么场景下用 RocketMQ&#xff1f…...

微信小程序-scroll-view实现上拉加载和下拉刷新

一.scroll-view实现上拉加载 scroll-view组件通过自身一些属性实现上拉加载的功能。 lower-threshold“100"属性表示距离底部多少px就会实现触发下拉加载的事件。 类似于在.json文件里面配置"onReachBottomDistance”: 100 bindscrolltolower"getMore"属…...

TS中interface和type的区别

在 TypeScript 中&#xff0c;interface 和 type 都可以用来定义对象的类型&#xff0c;但它们之间存在一些差异。 以下是 interface 和 type 的主要区别&#xff1a; 扩展&#xff08;Extending&#xff09;: interface 可以通过 extends 关键字来扩展其他 interface。interfa…...

Hightec编译器系列之高级调试技巧精华总结

Hightec编译器系列之高级调试技巧精华总结 小T为了便于大家理解&#xff0c;本文的思维导图大纲如下&#xff1a; 之前可能很多小伙伴没有使用过Hightec编译器&#xff0c;大家可以参考小T之前的文章《Hightec编译器系列之白嫖就是爽》可以下载一年试用版本。 小T使用过适配英…...

【论文笔记】LoRA LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS

题目&#xff1a;LoRA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS 来源: ICLR 2022 模型名称: LoRA 论文链接: https://arxiv.org/abs/2106.09685 项目链接: https://github.com/microsoft/LoRA 文章目录 摘要引言问题定义现有方法的问题方法将 LORA 应用于 Transformer 实…...

【Sa-Token|4】Sa-Token微服务项目应用

若微服务数量多&#xff0c;如果每个服务都改动&#xff0c;工作量大&#xff0c;则可以只在网关和用户中心进行改动&#xff0c;也是可以实现服务之间的跳转。 这种方式可以通过在网关服务中生成和验证 Sa-Token&#xff0c;并将其与现有的 Token关联存储在 Redis 中。用户中心…...

鸿蒙开发系统基础能力:【@ohos.hilog (日志打印)】

日志打印 hilog日志系统&#xff0c;使应用/服务可以按照指定级别、标识和格式字符串输出日志内容&#xff0c;帮助开发者了解应用/服务的运行状态&#xff0c;更好地调试程序。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用…...

SpringMVC系列十: 中文乱码处理与JSON处理

文章目录 中文乱码处理自定义中文乱码过滤器Spring提供的过滤器处理中文 处理json和HttpMessageConverter<T>处理JSON-ResponseBody处理JSON-RequestBody处理JSON-注意事项和细节HttpMessageConverter<T\>文件下载-ResponseEntity<T\>作业布置 上一讲, 我们学…...

使用MyBatisPlus进行字段的自动填充

使用MyBatisPlus进行字段的自动填充 需求场景 当我们往数据库里面插入一条数据&#xff0c;或者是更新一条数据时&#xff0c;一般都需要标记创建时间create_time和更新时间update_time的值&#xff0c;但是如果我们每张表的每个请求&#xff0c;在执行sql语句的时候我们都手…...

python爬虫之aiohttp多任务异步爬虫

python爬虫之aiohttp多任务异步爬虫 爬取的flash服务如下&#xff1a; from flask import Flask import timeapp Flask(__name__)app.route(/bobo) def index_bobo():time.sleep(2)return Hello boboapp.route(/jay) def index_jay():time.sleep(2)return Hello jayapp.rout…...

1964springboot VUE小程序在线学习管理系统开发mysql数据库uniapp开发java编程计算机网页源码maven项目

一、源码特点 springboot VUE uniapp 小程序 在线学习管理系统是一套完善的完整信息管理类型系统&#xff0c;结合springboot框架uniapp和VUE完成本系统&#xff0c;对理解vue java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;…...

【前端项目笔记】3 用户管理

用户管理相关功能实现 涉及表单、对话框、Ajax数据请求 基本页面 用户列表开发 在router.js中导入Users.vue 解决用户列表小问题 选中&#xff08;激活&#xff09;子菜单后刷新不显示高亮 给二级菜单绑定单击事件&#xff0c;点击链接时把对应的地址保存到sessionSto…...

【文献及模型、制图分享】基于SSP-RCP不同情景的京津冀地区土地覆被变化模拟

公众号新功能 目前公众号新增以下等功能 1、处理GIS出图、Python制图、区位图、土地利用现状图、土地利用动态度和重心迁移图等等 2、核密度分析、网络od分析、地形分析、空间分析等等 3、地理加权回归、地理探测器、生态环境质量指数、地理加权回归模型影响因素分析、计算…...

基于单片机的智能台灯控制系统

摘要&#xff1a; 文章设计一款单片机智能台灯控制系统&#xff0c;实现对台灯的手动和自动控制功能&#xff0c;以 STC89C52 单片机作为多功能智能台灯的主控制器&#xff0c;光电检测模块检测坐姿&#xff0c;红外传感器检测人体&#xff0c;光敏电阻检测光强&#xff0c;同…...

PrestaShop的一些使用介绍

目录 PrestaShop 是一个功能丰富的开源电子商务解决方案。 1. 以下是其基本概念和架构的一些要点&#xff1a; 2. PrestaShop 的模块开发是扩展其功能的重要方式。以下是对 PrestaShop 模块开发的详细介绍&#xff1a; 开发环境准备&#xff1a; 3. PrestaShop 的模块开发允…...

零基础女生如何入门人工智能,从哪里下手?学习时间大概要多久?

作为一个理工科早期毕业生&#xff0c;出于近乎本能的敏感&#xff0c;格外关注全网热议的ChatGPT。 本来国内就业环境就不好&#xff0c;各行各业内卷越来越严重&#xff0c;加上人工智能的异军突起&#xff0c;各行各业势必将迎来科技进步跨时代的巨大冲击&#xff0c;在此情…...

简答分享python学习进修网站

一、网战推荐 CodeCombat 是一款网页编程游戏。这款编程游戏借鉴了游戏很多设计元素&#xff0c;游戏剧情十分丰富。Codecombat能够学习Python多种语言&#xff0c;这些语言能够运用到游戏设计、网页应用、app的开发上。 Checkio 是一个基于浏览器的游戏&#xff0c;你需要使…...

linux高级编程(I/O)

fputc int fputc(int c, FILE *stream); 功能: 向流中写入一个字符 参数: c:要写入的字符 stream:文件流指针 返回值: 成功返回写入的字符ASCII码值 失败返回EOF fgetc int fgetc(FILE *stream); 功能: 从流中读取一个字符 参数: stream:文件流…...

Java面试——认证与授权

X、常见面试题汇总 1、Shiro与SpringSecutity对比 1&#xff09;Shiro的特点&#xff1a; Shiro 是 Apache 下的项目&#xff0c;相对简单、轻巧&#xff0c;更容易上手使用。 Shiro 权限功能基本都能满足&#xff0c;单点登录都可以实现。且不用与任何的框架或者容器绑定, 可…...