人形机器人全能赛openmv巡线代码

import sensor, image, time
from pyb import LED, millis, UART
from math import pi, isnan
import lcd # PID类
class PID:
_kp = _ki = _kd = _integrator = _imax = 0
_last_error = _last_derivative = _last_t = 0
_RC = 1 / (2 * pi * 20) def __init__(self, p=0, i=0, d=0, imax=0):
self._kp = float(p)
self._ki = float(i)
self._kd = float(d)
self._imax = abs(imax)
self._last_derivative = float('nan') def get_pid(self, error, scaler):
tnow = millis()
dt = tnow - self._last_t
output = 0
if self._last_t == 0 or dt > 1000:
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:
if isnan(self._last_derivative):
derivative = 0
self._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:
self._integrator += (error * self._ki) * scaler * delta_time
if self._integrator < -self._imax:
self._integrator = -self._imax
elif self._integrator > self._imax:
self._integrator = self._imax
output += self._integrator
return output def reset_I(self):
self._integrator = 0
self._last_derivative = float('nan') class RobotControl:
flag = 0 def __init__(self):
# 设置pid的初始值
self.rho_pid = PID(p=0.4, i=0)
self.theta_pid = PID(p=0.001, i=0)
lcd.init()
# 获取三种颜色的灯
self.red_led = LED(1)
self.green_led = LED(2)
self.blue_led = LED(3)
# 图像翻转 #sensor.set_pixformat(sensor.GRAYSCALE) # 读入灰色图片
sensor.reset()
sensor.set_vflip(True)
sensor.set_hmirror(True)
sensor.set_pixformat(sensor.RGB565) # 读入彩色图片
sensor.set_framesize(sensor.QQVGA) # 160x120 设置图像大小
#sensor.set_vflip(True) #纵向旋转
#sensor.set_hmirror(True) # 水平旋转
#sensor.set_framesize(sensor.CIF) # 320×240
# sensor.set_framesize(sensor.HQQQVGA) # 80x40 设置图像大小
sensor.skip_frames(time=2000) # 跳过2000张图片
# 线的阈值
#self.THRESHOLD = (35, 100, -47, 75, -28, 87) # 黑色
self.THRESHOLD = (29, 0, 61, -86, -69, 55) # 黑色0
#self.THRESHOLD = (2, 34, 61, -83, 80, -71) # 灰度的
#黑色识别
#self.THRESHOLD = (43, 100, -48, 127, -54, 127) #黑色
#self.THRESHOLD = (88,255)
# 通信初始化
self.uart = UART(3, 19200) # 注意波特率
# 计算差值
self.middle = 0
# 每次检测区域 (6块) (x, y, w, h)
self.init_roi = [(5, 50, 70, 10), (85, 50, 70, 10),
(5, 70, 70, 10), (85, 70, 70, 10),
(5, 90, 70, 10), (85, 90, 70, 10), ]
self.roi = []
self.py = 5 # 找的正方形的竖向偏差
self.line_to_middle = 10 # 正常情况下边界到中线的距离 要调的
self.img = 0 # 每次的图片存在这,方便操作
self.sleeptime = 0
self.clocktime = 0
self.blinblin = 0 # 关灯
def close_rgb(self):
self.red_led.off()
self.green_led.off()
self.blue_led.off() # 开白灯
def while_rgb(self):
self.close_rgb()
self.red_led.on()
self.green_led.on()
self.blue_led.on() # 开红灯
def red_rgb(self):
self.close_rgb()
self.red_led.on() # 开绿灯
def green_rgb(self):
self.close_rgb()
self.green_led.on() # 开蓝灯
def blue_rgb(self):
self.close_rgb()
self.blue_led.on() def send_message(self, mes):
"""
:param mes: 0 小左 1 左 2 右 3 直走
:param sleeptime: 执行该动作需要睡眠的时间
:return:
"""
# 维护一个睡眠池
sleep_dic = {
0: 3950,
1: 3950,
2: 3950,
3: 3950, } self.uart.write(str(mes) + "\n")
self.blinblin += 1
#print(self.blinblin)
if self.blinblin%2 == 1:
self.green_rgb() # 闪了绿灯代表发送消息了
else:
self.blue_rgb()
print(mes)
self.sleeptime = sleep_dic.get(mes, 1000)
#print(self.sleeptime)
#time.sleep_ms(sleep_dic.get(mes, 1000)) def recv_message(self):
pass # 获取偏差(可能用不上)
def get_output(self, line, img):
output = 0
if (line):
# print(line)
# 中心位置的差值
rho_err = abs(line.rho()) - img.width() / 2
# 计算直线的角度
if line.theta() > 90:
theta_err = line.theta() - 180
else:
theta_err = line.theta()
# 把线画出来
img.draw_line(line.line(), color=127)
print(rho_err, line.magnitude(), theta_err)
if line.magnitude() > 8: # 表示线性回归的效果怎么样
rho_output = self.rho_pid.get_pid(rho_err, 1)
theta_output = self.theta_pid.get_pid(theta_err, 1)
output = rho_output + theta_output
# 缺运动控制
return output # 获取边界点(6个)
def get_dot(self, roi):
most_pixels = 0
max_x = 0
if self.img:
blob0 = self.img.find_blobs([self.THRESHOLD], roi=roi, pixels_threshold=2, area_threshold=2, merge=True)
if blob0:
for n in range(len(blob0)):
if blob0[n].pixels() > most_pixels:
most_pixels = blob0[n].pixels()
max_x = n
# 将矩形标出
self.img.draw_rectangle(blob0[max_x].x(), blob0[max_x].y(), blob0[max_x].w(), blob0[max_x].h(),
color=(0, 0, 255), thickness=1, fill=False)
# 将矩形中点标出
self.img.draw_cross(blob0[max_x].x() + int(blob0[max_x].w() / 2), blob0[max_x].y() + int(
blob0[max_x].h() / 2), color=(0, 0, 255), size=1, thickness=1)
return blob0[max_x].x() + int(blob0[max_x].w() / 2), \
blob0[max_x].y() + int(blob0[max_x].h() / 2) # 矩形中心
else:
return 0
else:
return 0 def get_dx(self):
left_dot_dic = {}
right_dot_dic = {}
middle_dot = []
if not RobotControl.flag:
RobotControl.flag = 1
roi = self.init_roi
else:
roi = self.roi
# 获取边界坐标
for i in range(6):
roii = roi[i]
dot = self.get_dot(roii)
#print(dot)
if dot:
if i % 2 == 0:
left_dot_dic[dot[1]] = dot[0]
else:
right_dot_dic[dot[1]] = dot[0]
# 获取中点坐标
for y1, x1 in left_dot_dic.items():
if right_dot_dic.get(y1, -1) != -1:
x2 = right_dot_dic.get(y1, -1)
middle_dot.append(((x1 + x2) // 2, y1))
# 将路中点标出
self.img.draw_cross((x1 + x2) // 2, y1, color=(0, 255, 0), size=1, thickness=1)
# 中点排个序
middle_dot = sorted(middle_dot, key=lambda x: x[1], reverse=True)
# 清空变动的坐标列表
self.roi = []
if len(middle_dot) == 3:
numy = 3
for y1, x1 in left_dot_dic.items():
x2 = right_dot_dic.get(y1, -1)
if x1 >= 5:
x1 -= 5
else:
x1 = 0
if x2 >= 160 - 70 - 1:
x2 = 89
self.roi.append((x1, y1 - self.py, 60, 10))
self.roi.append((x2, y1 - self.py, 60, 10))
dx = middle_dot[0][0] - middle_dot[2][0]
middle_x = (middle_dot[0][0] + middle_dot[1][0] + middle_dot[2][0])//3
elif len(middle_dot) == 2:
numy = 2
RobotControl.flag = 0
dx = middle_dot[0][0] - middle_dot[1][0]
middle_x = (middle_dot[0][0] + middle_dot[1][0])//2
elif len(middle_dot) == 1:
numy = 1
RobotControl.flag = 0
dx = 0
try:
middle_x = middle_dot[0][0]
except:
middle_x = 80 # 如果没找到中线的话返回中线值即可
else:
RobotControl.flag = 0
numy = 0
middle_x = 0
if not left_dot_dic:
dx = -1
else:
dx = -2 return dx, middle_x, numy def run(self):
while 1:
img = sensor.snapshot().binary([self.THRESHOLD], invert=True)
line1 = img.get_regression([(100, 100)], roi=(0, 0, 80, 120), robust=True)
line2 = img.get_regression([(100, 100)], roi=(80, 0, 80, 120), robust=True)
output1 = self.get_output(img, line1)
output2 = self.get_output(img, line2)
if line1 and line2:
img.draw_line(((line1.x1() + line2.x1()) // 2, (line1.y1() + line2.y1()) // 2,
(line1.x2() + line2.x2()) // 2, (line1.y2() + line2.y2()) // 2),
color=(255, 0, 0))
elif line1:
img.draw_line((line1.x1() + self.middle, line1.y1(), line1.x2() + self.middle, line1.y2()),
color=(255, 0, 0))
elif line2:
img.draw_line((line2.x1() - self.middle, line2.y1(), line2.x2() - self.middle, line2.y2()),
color=(255, 0, 0))
else:
pass def run2(self):
self.clocktime = time.time_ns()
#print(self.clocktime)
while 1:
self.img = sensor.snapshot()
#self.img.rotation_corr(x_rotation=45)
dx, middle_x, numy = self.get_dx()
#print(dx, middle_x, numy)
#print("dx:", dx, "middle_x:", middle_x)
#print(time.time_ns())
#print(self.clocktime) if (time.time_ns() - self.clocktime)*0.000001 >= self.sleeptime - 100:
print((time.time_ns() - self.clocktime)*0.000001)
self.clocktime = time.time_ns()
if numy == 2:
dx *= 2
elif numy == 1 and middle_x <= 80:
self.send_message(1) elif numy == 1 and middle_x >= 80:
self.send_message(3) elif numy == 0:
if dx == -1:
self.send_message(1)
else:
self.send_message(2)
else:
if dx >= 5: # 小左
self.send_message(0)
elif dx <= -10: # 右
self.send_message(2)
else: # 直行
self.send_message(3)
lcd.display(self.img) if __name__ == '__main__':
robot1 = RobotControl()
robot1.run2()

人形机器人全能赛openmv巡线代码的更多相关文章

  1. 画线代码V1.0.0

    画线代码: 最终效果图: 优点: 1.效果还行,计算量也不大(就一点2维直线一般式能有多少运算量). 缺点: 1.每条线怎么也是建模,可能会有点开销. 2.编辑起来很是麻烦. 代码部分: /***** ...

  2. 巡风代码架构简介以及Flask的项目文件结构简介

    一.巡风: 巡风是一款什么东西,想必安全同行都不陌生吧.用它作为内网漏洞扫描管理架构是一种很好的选择,扫描快,开源,还可自己编写符合规则的POC直接放入相应目录来扩展.今天下午趁着有点时间捋了一下巡风 ...

  3. CSS 定义上划线、下划线、删除线代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 机器人可以拥有社交智能吗?——微软雷德蒙研究院院长Eric Horvitz与他的个人虚拟助理之梦

    Horvitz与他的个人虚拟助理之梦" title="机器人可以拥有社交智能吗?--微软雷德蒙研究院院长Eric Horvitz与他的个人虚拟助理之梦">编者按:到 ...

  5. 开启A20线(部分译)

    开启A20线 在查看或编写操作系统内核时一定会遇到A20线这个问题.本人对此一直都是似懂非懂的,查了些资料,决定弄明白于是有了这篇文章.其中前一部分是翻译一篇外国博文,但光有这篇文章依旧不能清楚地说明 ...

  6. NYOJ 123 士兵杀敌4-树状数组的插线求点

    士兵杀敌(四) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编 ...

  7. 2016年如果还没有关注这些机器人公司,你就out了

    芯师爷语据 知名市场研究机构IDC发布报告称,预计到2019年,全球机器人及相关服务上的投入将达到1350亿美元,较2015年的710亿美元增长近一倍.报告称,机器人相关投资预计将以每年17%的速度增 ...

  8. ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse

    ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或ja ...

  9. Python创建微信机器人

    微信,一个日活10亿的超级app,不仅在国内社交独领风骚,在国外社交也同样占有一席之地,今天我们要将便是如何用Python来生成一个微信机器人,突然想起鲁迅先生曾经说过的一句话:因为是微信机器人系列的 ...

  10. SLAM+语音机器人DIY系列:(三)感知与大脑——3.轮式里程计与运动控制

    摘要 在我的想象中机器人首先应该能自由的走来走去,然后应该能流利的与主人对话.朝着这个理想,我准备设计一个能自由行走,并且可以与人语音对话的机器人.实现的关键是让机器人能通过传感器感知周围环境,并通过 ...

随机推荐

  1. manim边学边做--三维图形的场景类

    在Manim中,ThreeDScene是一个专门为三维场景设计的类. 它通过配置三维相机.支持复杂的相机运动以及管理物体与相机的交互关系,为科学可视化.工程仿真.数学教育等领域提供了强大的工具. 典型 ...

  2. Peach-Printer2.0 Web 打印服务解决方案

    Peach-Printer1.0在沉寂许久后迎来了一个使用客户,非常感谢客户的支持和理解. 通过客户的使用反馈本人尝试对1.0版本进行完善修改,但始终打印效果未能实现预期.思索许久后决心更改打印控件的 ...

  3. 深入解析 Druid 连接池:连接有效性检测与 Keep-Alive 机制

    背景 在 Java 程序中,下面是一个经常会碰到的错误. Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communica ...

  4. CISCN&CCB半决赛_2025_PWN_WP

    CISCN&CCB半决赛_2025_PWN_WP 前言: 记录一下第一次打半决赛国赛,总结来说还是自己太菜了,还有check脚本是真的很shi,正规军白给了... typo break edi ...

  5. SpringBoot原理分析-1

    SpringBoot原理分析 作为一个javaer,和boot打交道是很常见的吧.熟悉boot的人都会知道,启动一个springboot应用,就是用鼠标点一下启动main方法,然后等着就行了.我们来看 ...

  6. Pydantic根校验器:构建跨字段验证系统

    title: Pydantic根校验器:构建跨字段验证系统 date: 2025/3/24 updated: 2025/3/24 author: cmdragon excerpt: Pydantic根 ...

  7. Tinyhttpd 源代码初步解读

    Tinyhttpd 是很早以前的一个 web 服务器程序,由 C 语言编写,整个程序十分小巧,源码只有几百行.它一般不适合用于生产环境,因为它很简单,只实现了读取 html 以及 Get / POST ...

  8. RabbitMQ 延迟任务(限时订单) 思路

    一.场景 我们经常会碰见,一个需求就是,发送一条指令(消息),延迟一段时间执行,比如说常见的淘宝当下了一个订单后,订单支付时间为半个小时,如果半个小时没有支付,则关闭该订单.当然实现的方式有几种,今天 ...

  9. 2020年devops的7个发展趋势

    2020年devops的7个发展趋势 2019年对DevOps从业者来说是激动人心的一年,DevOps继续快速增长.大多数组织都在执行或评估他们的DevOps策略.那么,到2020年,DevOps.基 ...

  10. .NET 原生驾驭 AI 新基建实战系列(二):Semantic Kernel 整合对向量数据库的统一支持

    1. 引言 在人工智能(AI)应用开发迅猛发展的今天,向量数据库作为存储和检索高维数据的重要工具,已经成为许多场景(如自然语言处理.推荐系统和语义搜索)的核心组件. 对于.NET生态系统的开发者而言, ...