题记:这是一场因为规则审慎问题,导致取消成绩的失败方案,但并不是完全没有一些参考的意义和价值。以车会友,一直是智能车比赛的初衷,也是我们一直奋斗的目标。这个方案稳定度高,并且获得(470,500)的还算不错的成绩。

总览

整个车成本约1800上下:这里选用了四个脉轮,以及2mm钢板作为底板,确保强度,亚克力/铝板的话可能强度不够,重就重些吧。
在家里打线上赛的大佬去美团打工,并在考虑edgeboard这个开发所需要时间和算力的情况下,我们选择让edgeboard,利用opencv,进行一个基础的识别,也就是这里,和卓老师个人公众号内容有所冲突,导致了最后的违规。

结构框图

概述

本次比赛主要就是巡线、抓物块、打靶子、放球,亮亮灯。

巡线

巡线这里不得不提到主办方精妙的设计,如果你利用OpenCV进行处理,他的黄色色块、宿营地、甚至地面上米黄色的城墙图,都会在不同亮度的情况下,对整个视觉产生巨大影响。
在这个场地中,如果摄像头不进行近处扫描,则四轮的脉轮会因为过早扫到前面的赛道进行漂移,如果扫的过近,则会V字弯道、U形弯道过不去。十字弯道如果盲目补线,则有可能打靶姿势不好纠正,连续双打靶,应该就是为了看你在丢失视野的情况下可不可以自己纠错,这篇需要好好写一下,将会交由我队友写的博客来进行详解。
见博客链接,代码均在此处
队友博客链接:(https://www.shinenet.cn/archives/198.html)

打靶子

打靶子这块可以说十分简单,靶子高17,于是我们把笔尖固定在17cm高度,那么靶子就只需要做横向处理就行。抓住靶子特征,红色,原型。很好,openMV直接在靶心附近扫描红色圆心色块中心,并且设定一定的弧度、大小,来去除干扰,然后通过脉轮前后微调,使得这个圆心设定在屏幕中心,啪,打上去了。
这个采取的步进电机的方式,主控给设备命令,步进电机转动,把笔伸出去缩回来,又快又好,步进电机驱动可以购买,小步进电机也是(买个好的,防烧毁),然后openmv可以给个pwm波进行控制,搞定。

举旗子

说实在举旗子这个方针,我们用了个三百六十度舵机,使他能够让三个旗子通过一个舵机来控制。

底部识别

这里涉及比赛漏洞之一,既然大致顺序是定的,我们就只要识别出白色色块就行,唯一变化的城池顺序,是吧,写个菜单,能用按键按下去就能换代码中config顺序,然后config九个内容,每次识别到一个就+1,执行下一个任务,很好,底部识别没了,变成识别白色块了。打灯,搞个led灯光带,蒙张纸,然他漫反射,减少环境光源影响。openMV识别白色块,调调阈值,参数啥的,好了,又快又稳的底部识别完成了。到对应的位置,还可以通过色块中心点微调一下位置,稳稳当当的完成任务识别。

抓物块

爪子大一些,两舵机,一个控制下抓角度,一个抓取就行

控制好距离、抓取角度、抓取位置,一抓即中。
利用edgeboard侧面识别赛道线相对距离,从而控制每次抓取时的固定位置。

放球

同理,通过底部openmv大致校准后,用edgeboard的侧边距离控制好,角度锁死,结束。

驱动

驱动直接用iic与树莓派通信,就时不时掉线有点烦。直接pid写死在驱动板上,然后就靠iic给他传数值,然后他执行转速即可。自己画个驱动板就行,后续挣得队友同意会把pcb放上去。




结论

分析到这里,整个比赛已经没什么难度了。
巡线部分由于赛道很有水平,等我队友睡醒了会详细写如何处理赛道中各种线各种情况,到时候会附上链接。
代码和3d建模,PCB,将会在征得队友同意后一起奉上。
希望这个思路,能给大家一定的参考。
感谢在比赛场上鼓励我的车友,以及和我一起靠兴趣做车的队友们。

附录

利用openMV进行亮灯、打靶子、寻找靶心的程序

THRESHOLD = (24, 48, 28, 72, -8, 60)
import sensor, image, time
from ws2812 import WS2812
import utime
import pyb
from pyb import Pin,Timer
from pyb import USB_VCPring = WS2812(spi_bus=2, led_count=8)
sensor.reset()
sensor.set_vflip(True)
sensor.set_hmirror(True)
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # 80x60 (4,800 pixels) - O(N^2) max = 2,3040,000.
#sensor.set_windowing([0,20,80,40])
sensor.skip_frames(time = 2000)     # WARNING: If you use QQVGA it may take seconds
clock = time.clock()                # to process a frame sometimes.#clock = time.clock()                # to process a frame sometimes.
usb = USB_VCP()count = 0
now_x = 0
temp = 0data = [(18, 6, 0),(15, 9, 0),(12, 12, 0),(9, 15, 0),(6, 18, 0),(3, 21, 0),(0, 24, 0),(8, 8, 8),
]
# red
data1 = [(255, 0, 0),(255, 0, 0),(255, 0, 0),(255, 0, 0),(255, 0, 0),(255, 0, 0),(255, 0, 0),(255, 0, 0),
]
# Green
data2= [(0, 255, 0),(0, 255, 0),(0, 255, 0),(0, 255, 0),(0, 255, 0),(0, 255, 0),(0, 255, 0),(0, 255, 0),
]
# Blue
data3= [(0, 0, 255),(0, 0, 255),(0, 0, 255),(0, 0, 255),(0, 0, 255),(0, 0, 255),(0, 0, 255),(0, 0, 255),
]
# 前进代码
def Gun_shoot_forward():tim = Timer(4, freq=40000) # Frequency in Hz# p0p = pyb.Pin("P8", pyb.Pin.OUT_PP)p.high()# 生成1kHZ方波,使用TIM4,channels 1 and 2分别是 50% 和 75% 占空比。ch1 = tim.channel(1, Timer.PWM, pin=Pin("P7"), pulse_width_percent=50)# 旋转多少s之后,停止伸缩time.sleep_ms(1000)# 关闭pwm波ch1 = tim.channel(1, Timer.PWM, pin=Pin("P7"), pulse_width_percent=50)# 回退代码
def Gun_shoot_back():tim = Timer(4, freq=40000) # Frequency in Hz# p0p = pyb.Pin("P8", pyb.Pin.OUT_PP)p.low()# 生成1kHZ方波,使用TIM4,channels 1 and 2分别是 50% 和 75% 占空比。ch1 = tim.channel(1, Timer.PWM, pin=Pin("P7"), pulse_width_percent=50)# 旋转多少s之后,停止伸缩time.sleep_ms(1000)# 关闭pwm波ch1 = tim.channel(1, Timer.PWM, pin=Pin("P7"), pulse_width_percent=50)# 扫描靶心
def Scan_target():while True:clock.tick()img = sensor.snapshot().lens_corr(1.8) #.binary([THRESHOLD]).negate()thr = (0, 128)blobs = img.find_blobs([THRESHOLD],merge=True)flag = Falseoutput_str="P1"if not usb.debug_mode_enabled():usb.write(output_str + "\n")for blob in blobs:if(blob.cx()>40 and blob.cx() < 120 and blob.cy()>20 and blob.cy() < 100 and blob.roundness() > 0.44):img.draw_cross(blob.cx(), blob.cy(), color = 127)temp = blob.cx()else:count = 0now_x = 0temp = 0flag = Truebreakif flag or len(blobs) == 0:continueif(count < 5):now_x = now_x + tempcount = count + 1else:now_x = now_x/5if now_x/5 <= 81 and now_x >= 79:output_str="ST"if not usb.debug_mode_enabled():usb.write(output_str + "\n")returnelse:output_str="[%d]" % (now_x)if not usb.debug_mode_enabled():usb.write(output_str + "\n")count = 0now_x = 0continue
def Led_show(status):if status == 1: # 红灯ring.show(data1)sleep_ms(1000)ring.show(data)sleep_ms(500)ring.show(data1)sleep_ms(1000)ring.show(data)sleep_ms(500)ring.show(data1)elif status == 2: # 绿灯ring.show(data2)sleep_ms(1000)ring.show(data)sleep_ms(500)ring.show(data2)sleep_ms(1000)ring.show(data)sleep_ms(500)ring.show(data2)elif status == 3: # 蓝灯ring.show(data3)sleep_ms(1000)ring.show(data)sleep_ms(500)ring.show(data3)sleep_ms(1000)ring.show(data)sleep_ms(500)ring.show(data3)else : # 异常数据则回归正常白灯ring.show(data)# 完成任务也是正常的白灯ring.show(data)if __name__=='__main__':while True:# print("1: " + str(time.time()))if(usb.any( )):Status_type = usb.recv(1, timeout=5000)if not usb.debug_mode_enabled():usb.send("Status") # 接收到状态机if Status_type == b'R':Led_show(1)    # 亮红灯elif Status_type == b'G':Led_show(2)    # 亮绿灯elif Status_type == b'B':Led_show(3)    # 亮蓝灯elif Status_type == b'S':Scan_target()  # 扫描靶心进行移动elif Status_type == b'X':Gun_shoot_forward() # 当车停稳定后开始进行打靶Gun_shoot_back()else:continuetime.sleep_ms(10)# print("2: " + str(time.time()))

这部分用了一个亮灯的库,ws2812,可以简单搜一下,为了方便大家,这里我也粘贴上去。

import gc
try:import pyb
except ImportError:import machine as pybclass WS2812:"""Driver for WS2812 RGB LEDs. May be used for controlling single LED or chainof LEDs.Example of use:chain = WS2812(spi_bus=1, led_count=4)data = [(255, 0, 0),    # red(0, 255, 0),    # green(0, 0, 255),    # blue(85, 85, 85),   # white]chain.show(data)Version: 1.0"""buf_bytes = (0x88, 0x8e, 0xe8, 0xee)def __init__(self, spi_bus=1, led_count=1, intensity=1):"""Params:* spi_bus = SPI bus ID (1 or 2)* led_count = count of LEDs* intensity = light intensity (float up to 1)"""self.led_count = led_countself.intensity = intensity# prepare SPI data buffer (4 bytes for each color)self.buf_length = self.led_count * 3 * 4self.buf = bytearray(self.buf_length)# SPI init#self.spi = pyb.SPI(spi_bus, pyb.SPI.MASTER, baudrate=3200000, polarity=0, phase=1)self.spi = pyb.SPI(spi_bus, pyb.SPI.MASTER, baudrate=6400000, polarity=0, phase=1)# turn LEDs offself.show([])def show(self, data):"""Show RGB data on LEDs. Expected data = [(R, G, B), ...] where R, G and Bare intensities of colors in range from 0 to 255. One RGB tuple for eachLED. Count of tuples may be less than count of connected LEDs."""self.fill_buf(data)self.send_buf()def send_buf(self):"""Send buffer over SPI."""self.spi.send(self.buf)gc.collect()def update_buf(self, data, start=0):"""Fill a part of the buffer with RGB data.Order of colors in buffer is changed from RGB to GRB because WS2812 LEDhas GRB order of colors. Each color is represented by 4 bytes in buffer(1 byte for each 2 bits).Returns the index of the first unfilled LEDNote: If you find this function ugly, it's because speed optimisationsbeated purity of code."""buf = self.bufbuf_bytes = self.buf_bytesintensity = self.intensitymask = 0x03index = start * 12for red, green, blue in data:red = int(red * intensity)green = int(green * intensity)blue = int(blue * intensity)buf[index] = buf_bytes[green >> 6 & mask]buf[index+1] = buf_bytes[green >> 4 & mask]buf[index+2] = buf_bytes[green >> 2 & mask]buf[index+3] = buf_bytes[green & mask]buf[index+4] = buf_bytes[red >> 6 & mask]buf[index+5] = buf_bytes[red >> 4 & mask]buf[index+6] = buf_bytes[red >> 2 & mask]buf[index+7] = buf_bytes[red & mask]buf[index+8] = buf_bytes[blue >> 6 & mask]buf[index+9] = buf_bytes[blue >> 4 & mask]buf[index+10] = buf_bytes[blue >> 2 & mask]buf[index+11] = buf_bytes[blue & mask]index += 12return index // 12def fill_buf(self, data):"""Fill buffer with RGB data.All LEDs after the data are turned off."""end = self.update_buf(data)# turn off the rest of the LEDsbuf = self.bufoff = self.buf_bytes[0]for index in range(end * 12, self.buf_length):buf[index] = offindex += 1

底部白色色块扫描代码

# THRESHOLD = (68, 84, -7, 10, -19, 8)
THRESHOLD = (68, 83, -11, 10, -6, 23) # Grayscale threshold for dark things...
# THRESHOLD = (65, 83, -24, 9, -13, 29)
# THRESHOLD = (29, 100, 45, 127, 5, 127)
import sensor, image, time
sensor.reset()
sensor.set_vflip(True)
sensor.set_hmirror(True)
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # 120x160 (4,800 pixels) - O(N^2) max = 2,3040,000.
#sensor.set_windowing([0,20,80,40])
sensor.skip_frames(time = 2000)     # WARNING: If you use QQVGA it may take seconds
clock = time.clock()                # to process a frame sometimes.
from pyb import UART
from pyb import USB_VCP
usb = USB_VCP()
count = 0
now_x = 0
now_y = 0
temp = 0
temp1 = 0
# uart = UART(3, 19200)
output_str="openmv_basic"
if not usb.debug_mode_enabled() and usb.isconnected():usb.write(output_str)
while True:clock.tick()img = sensor.snapshot().lens_corr(1.8) #.binary([THRESHOLD]).negate()thr = (0, 128)blobs = img.find_blobs([THRESHOLD],merge=True)#  and blob.area()>4000 and blob.area() < 7500SeeFlag = Falseif(usb.any( )):Ask = usb.recv(1, timeout=5000)if not usb.debug_mode_enabled():if Ask == b'W': # 询问型号answer = "openmv_basic"usb.write(answer) # 返回说明是底部openmvfor blob in blobs:if(blob.cx()>10 and blob.cx() < 160 and blob.cy()>10 and blob.cy() < 110  and blob.area()>3500 and blob.area()<8500 and blob.density() > 0.35):# if(blob.cx()>10 and blob.cx() < 160 and blob.cy()>10 and blob.cy() < 110 and blob.area()>3500):# print(blob.density())# print(blob.area())# print(blob.density())img.draw_cross(blob.cx(), blob.cy(), color = 127)temp = blob.cx()SeeFlag = Truetemp1 = blob.cy()if not SeeFlag:now_x = 0now_y = 0temp = 0temp1 = 0count = 0continue# 将反应速度提到3if(count < 3):now_x = now_x + tempnow_y = now_y + temp1count = count + 1else:now_x = now_x/3now_y = now_y/3#print(now_x,now_y)#output_str="[%d,%d]" % (now_x,now_y)#uart.write(output_str)# 因为摄像头横过来了,将x,y呼唤,所以将中线x变成60,y中线变成80output_str="[%d,%d]" % (now_y,now_x)if not usb.debug_mode_enabled() and usb.isconnected():usb.write(output_str)else:print(output_str)count = 0now_x = 0now_y = 0continue

这部分主要和openmv还有车速有关,车速越快,取均值次数就要少些,当然,如果有钱换openmv4,那么算力会大幅度提升。

电机驱动链接开源

因为用不起主办方的网盘,所以只能用csdn自带的了,点击下载

github源码

edgeboard与树莓派源码

第16届百度智能车比赛-方案制定与选择(技术报告)相关推荐

  1. 第七届cuit智能车比赛总结

    作为大一小白,第一次参加比赛,感受到了比赛的氛围,也收获了许多宝贵的经验. (1)电磁杆              电磁杆的作用是感应漆包线的位置,给单片机传入数据,使车维持在一定范围内,他的感应部分 ...

  2. 第十六届全国大学生智能车比赛掠影

    §01 比赛现场 ■ 提问: 态度好不认真. . ▲ 图1.1 标错的比赛信息 应该是全向行进组 ▲ 图3.1 车在跑,边裁在看手机 卓大大 这是我们昨天在华东赛场拍摄到的赛道铺设问题,车库里铺了电磁 ...

  3. 第七届飞思卡尔智能车比赛的赛道边缘提取-----第一篇博客

    园龄有11个月了??.这么快...因为参加飞思卡尔的智能车比赛,所以申请开通了这个博客,想不到这么容易就通过了. 看过这么多博客了,感觉写博客都是 在各种方面很有实力的人,包括软件,硬件. 但,永远不 ...

  4. RT-Thread与智能车比赛

      在第十六届全国大学生智能汽车竞赛中引入了多种MCU类型应用于不同的赛题组,包括有Infineon, STC, WCH, MindMotion,NXP等.在智能车控制系统开发过程中中引入实时嵌入式操 ...

  5. 【资料分享】智能车比赛 - 硬件调教

    资料作用 我是参加了第十五届全国大学生智能车比赛的选手,这里指的智能车比赛,名字我现在也说不准确,恩智浦.飞思卡尔.英飞凌等待赞助商,比赛项目是分组别的,四轮组.双车组等等,如果你一开始看到这里,明白 ...

  6. 独立、原创、总结、分享、行动——由海滨学生參观实验室及“飞思卡尔”杯智能车比赛想到的...

    题记:下面内容,都是老师在和学生交流过程中发现的现象,这里主要指出了存在的问题和可能的解决方法.事实上同学们也有非常多的长处.这里没有一一叙述.本着"有则改之,无则加勉"的态度分享 ...

  7. 独立、原创、总结、分享、行动——由海滨学生参观实验室及“飞思卡尔”杯智能车比赛想到的

    题记:以下内容,都是老师在和学生交流过程中发现的现象,这里主要指出了存在的问题和可能的解决方法.其实同学们也有很多的优点,这里没有一一叙述.本着"有则改之,无则加勉"的态度分享自己 ...

  8. 第七届CUIT智能车竞赛(电磁循迹)

    第七届CUIT智能车竞赛 作为一名大一新生,我和几名队友一起组队参加了CUIT第七届智能车竞赛(四轮组),比赛一共花了大概一个多月的样子,再加上前期对一些东西的提前学习,也算是花了挺长时间的了,现在比 ...

  9. “大一新生如何参加智能车比赛”帖子回复

      在论坛水了两三年了,见到了不少大佬非常厉害的开源设计,也算是这个论坛( ZNCZZ )的忠实受益者之一.   这篇帖子是搬运我在知乎一个问题,"大一新生如何参加智能车比赛"下面 ...

最新文章

  1. 网站降权可从两方面着手分析
  2. 用vs2008打开vs2012项目
  3. 《糖豆人:终极淘汰赛》成功背后蕴含了何种设计?
  4. [译]提案:在Go语言中增加对持久化内存的支持
  5. 移植U-BOOT之裁剪和修改默认参数(易用性)启动内核,以及对uboot进行分区
  6. C++实现调用C#(CLI)方法
  7. 带文本的标签自动生成font标签
  8. 面向对象之魔术方法_call
  9. 基于有赞微小店+有赞云实现的个人微信和支付宝扫码在线支付收款
  10. python风格logo_Python十分钟制作属于你自己的个性logo
  11. Chrome 扩展是什么?我们如何建造它?
  12. VTK:交互与拾取——点拾取
  13. “青山无墨千年画,流水无弦万古琴。 有人说:生活可以有底线的随心
  14. weblogic 启动常见错误解决
  15. 机器人学——姿态描述方法(欧拉角,固定角,D-H法,绕定轴旋转)
  16. Android正确的保活方案,不要掉进保活需求死循环陷进
  17. RFID无线射频识别技术基本原理FAQ
  18. NKOJ-6118 Bunny的平均数
  19. 001_图形学里的变换
  20. 其实我不仅会 Spring Security,Shiro 也略懂一二!

热门文章

  1. 张学友MTV全集[DVD]
  2. 微博相互关注互粉mysql表实现_相互关注互粉mysql实现
  3. Python dataframe.pivot()用法解析
  4. 只有偏执狂才能生存-Oracle开始对Red Hat Linux用户提供服务支持
  5. 直升机空气动力学基础---001 直升机的一般介绍
  6. 魔兽怎样利用编辑器制作一个能够利用漂浮文字显示伤害的功能
  7. python 网格交易源码_网格交易策略源码(MT4.0源码)
  8. RT-Thread实时操作系统简介
  9. 洛谷P1365 WJMZBMR打osu 题解
  10. 怎么查找计算机里的金蝶账套,金蝶软件 账套如何从一台电脑转到另一台电脑...