人形机器人全能赛openmv巡线代码
人形机器人全能赛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巡线代码的更多相关文章
- 画线代码V1.0.0
画线代码: 最终效果图: 优点: 1.效果还行,计算量也不大(就一点2维直线一般式能有多少运算量). 缺点: 1.每条线怎么也是建模,可能会有点开销. 2.编辑起来很是麻烦. 代码部分: /***** ...
- 巡风代码架构简介以及Flask的项目文件结构简介
一.巡风: 巡风是一款什么东西,想必安全同行都不陌生吧.用它作为内网漏洞扫描管理架构是一种很好的选择,扫描快,开源,还可自己编写符合规则的POC直接放入相应目录来扩展.今天下午趁着有点时间捋了一下巡风 ...
- CSS 定义上划线、下划线、删除线代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 机器人可以拥有社交智能吗?——微软雷德蒙研究院院长Eric Horvitz与他的个人虚拟助理之梦
Horvitz与他的个人虚拟助理之梦" title="机器人可以拥有社交智能吗?--微软雷德蒙研究院院长Eric Horvitz与他的个人虚拟助理之梦">编者按:到 ...
- 开启A20线(部分译)
开启A20线 在查看或编写操作系统内核时一定会遇到A20线这个问题.本人对此一直都是似懂非懂的,查了些资料,决定弄明白于是有了这篇文章.其中前一部分是翻译一篇外国博文,但光有这篇文章依旧不能清楚地说明 ...
- NYOJ 123 士兵杀敌4-树状数组的插线求点
士兵杀敌(四) 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编 ...
- 2016年如果还没有关注这些机器人公司,你就out了
芯师爷语据 知名市场研究机构IDC发布报告称,预计到2019年,全球机器人及相关服务上的投入将达到1350亿美元,较2015年的710亿美元增长近一倍.报告称,机器人相关投资预计将以每年17%的速度增 ...
- ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse
ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或ja ...
- Python创建微信机器人
微信,一个日活10亿的超级app,不仅在国内社交独领风骚,在国外社交也同样占有一席之地,今天我们要将便是如何用Python来生成一个微信机器人,突然想起鲁迅先生曾经说过的一句话:因为是微信机器人系列的 ...
- SLAM+语音机器人DIY系列:(三)感知与大脑——3.轮式里程计与运动控制
摘要 在我的想象中机器人首先应该能自由的走来走去,然后应该能流利的与主人对话.朝着这个理想,我准备设计一个能自由行走,并且可以与人语音对话的机器人.实现的关键是让机器人能通过传感器感知周围环境,并通过 ...
随机推荐
- 应急响应靶场之vulntarget-n
vulntarget-n 用户名密码:root/Vulntarget@123 一.分析history命令 1.先将历史命令导出 history > 1.txt 2.分析history 1)篡改网 ...
- FastAPI 核心机制:分页参数的实现与最佳实践
title: FastAPI 核心机制:分页参数的实现与最佳实践 date: 2025/3/13 updated: 2025/3/13 author: cmdragon excerpt: 在构建现代W ...
- 事务及mysql中的隔离级别
事务,一个或一组sql语句组成的执行单元,是最小的执行单元,要么全执行,要么全不执行.如果单元中某条sql语句执行失败,整个单元将会回滚,所有受影响的数据返回到事务开始前的状态. 事务具有ACID四个 ...
- mdn拾遗-- 纯html+css实现的input的验证
关于input的验证,其实从很古老的前端时代开始就一直采用一种比较可靠的方式,就是js操作dom,今天浏览mdn时发现了h5的验证方法,很是兴奋.感觉值得一记. 说在前面的话,着重就是配合h5 + c ...
- 面试官:工作中优化MySQL的手段有哪些?
MySQL 是面试中必问的模块,而 MySQL 中的优化内容又是常见的面试题,所以本文来看"工作中优化MySQL的手段有哪些?". 工作中常见的 MySQL 优化手段分为以下五大类 ...
- 从上下文切换谈thread_local工作原理
从上下文切换谈thread_local工作原理 thread_local是什么 熟悉多线程编程的小伙伴一定对thread_local不陌生,thread_local 是 C++11 引入的一种存储类说 ...
- BUUCTF---传感器
题目 5555555595555A65556AA696AA6666666955 这是某压力传感器无线数据包解调后但未解码的报文(hex) 已知其ID为0xFED31F,请继续将报文完整解码,提交hex ...
- RMQ 和 LCA 问题
# Part 1 RMQ RMQ,即区间信息维护问题 如最大值,最小值,GCD 等 RMQ 算法实现很多 具体有线段树,树状数组和 ST 表 但综合时间复杂度最好的是 ST 表 查询 O(1),预处理 ...
- Scanner的进阶使用——数字的输入
1.用Scanner输入数字(整数和小数) 1.定义一个整数变量 2.建立扫描器 3.使用if 4.建立电脑接收数据 5.设置else(那么)语法 6.关闭Scanner
- Netty源码—10.Netty工具之时间轮
大纲 1.什么是时间轮 2.HashedWheelTimer是什么 3.HashedWheelTimer的使用 4.HashedWheelTimer的运行流程 5.HashedWheelTimer的核 ...