人形机器人全能赛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. k8s node节点报错 dial tcp 127.0.0.1:8080: connect: connection refused

    前言 在搭建好 kubernetes 环境后,master 节点拥有 control-plane 权限,可以正常使用 kubectl. 但其他 node 节点无法使用 kubectl 命令,即使同步过 ...

  2. mac brew 安装

    Homebrew国内源 知乎文章地址:https://zhuanlan.zhihu.com/p/111014448 苹果电脑安装脚本: /bin/zsh -c "$(curl -fsSL h ...

  3. 一文速通Python并行计算:03 Python多线程编程-多线程同步(上)—基于互斥锁、递归锁和信号量

    一文速通 Python 并行计算:03 Python 多线程编程-多线程同步(上)-基于互斥锁.递归锁和信号量 摘要: 在 Python 多线程编程中,线程同步是确保多个线程安全访问共享资源的关键技术 ...

  4. 汇编概念辨析(Intel/AT&T syntax、GAS、NASM)

    写在前面 本文并不详细介绍Intel syntax.AT&T syntax.GAS.NASM的具体内容和具体区别,而是从概念辨析的角度说明这些专有名词的含义,以便为初学者扫清疑惑.有兴趣深入了 ...

  5. 【Java】枚举类和注解

    一.枚举类的使用 1. 枚举类的说明: 枚举类的理解:类的对象只有有限个,确定的.我们称此类为枚举类 当需要定义一组常量时,强烈建议使用枚举类 枚举类的实现: JDK 5.0以前需要自定义 JDK 5 ...

  6. 再说【把postgreSQL的表导入SQLite 】

    为这个问题,百度了一大圈.确实答案就在手边. 这个短语认识一下:[Extract-Transfrom-Load]其意义:     ETL,是英文 Extract-Transform-Load 的缩写, ...

  7. Linux centos8 VPS基本配置之SSH

    Linux centos8 VPS基本配置之SSH 最近在使用阿里云的时候,需要安装一些nodejs模块,但是总是安装失败,我已经使用了淘宝镜像cnpm加速,查看了具体原因是有github的依赖. 阿 ...

  8. 如何在 MySQL 中避免单点故障?

    如何在 MySQL 中避免单点故障? 在 MySQL 中避免单点故障(SPOF, Single Point of Failure)是确保数据库高可用性和系统稳定性的关键.通过采取以下几种策略,可以最大 ...

  9. json导出csv

    let data = [] let keys = ['name', 'town', 'village', 'address', 'update_time_label', 'manager'] let ...

  10. qwen3 惊喜发布,用 ollama + solon ai (java) 尝个鲜

    qwen3 惊喜发布了,帅!我们用 ollama 和 solon ai (java) 也来尝个鲜. 1.先用 ollama 拉取模型 听说,在个人电脑上用 4b 的参数,效果就很好了. ollama ...