第二次任务相对比较易于实现,各位机甲大师们已经很快很好的实现了斐波那契数列的生成、识别和打印,自己也就不在重复了。
本着大疆机甲大师“玩出名堂”的初衷,我考虑到能不能把生成的每个数字读出来呢?经过一番折腾,基本上实现了语音报数。以下分步骤进行详细解释,还真心希望小伙伴们不吝指出存在的不足、错误以及可以进一步完善提高的地方,在此先表示感谢了!
一、任务二介绍
1.随机生成“1、2、3、4、5”中的任意两个数字,作为斐波那契数列的前两项(斐波那契数列:从第三项开始,当前项为前两项数字之和,即F(n)=F(n-1)+F(n-2))。要求:生成的两个初始随机数需要有明显的指示信号(灯光闪烁或者云台摆动等)提示数值是多少。
2.根据上面产生的前两项生成斐波那契数列,要求最后一项小于100。
3.按照下图,以产生的两个数字中较小的一个,作为S1机器人的第一个击打目标,较大的作为第二个击打目标,两个数的和作为第三个击打目标,此后的击打目标按照类似斐波那契数列的规律进行计算。举个栗子,如果初始的两个数分别是2和3,则以2作为第一个击打目标,第二个击打目标为3,2+3 =5作为第三个击打目标,3+5 = 8作为第四个击打目标,以此类推。大于10的击打目标数字,以分别击打(十位和个位)两个数字进行组合完成。例如,数字34,则先击打3后紧接着击打4完成(*请注意,此处有先后顺序);数字55,则连续击打5两次。每完成击打一个数字,需要有明显的提示信号(可自定义)。
4.参照斐波那契数列的规律,依次击打完成100以内的数字,即被认为完成编程任务,完成任务者加5分。
附:数字视觉标签下载地址,
https://dl.djicdn.com/downloads/ ... _44pcs_15_15cm_upda
ted.pdf
二、让机甲大师播放自定义的声音
S1并没有开发自定义声音的播放功能,只能自己想办法了!能不能把 S1的扬声器接到树莓派、arduino等外围智能设备播放呢?.
先拿手机试验一下……
S1的扬声器接口是2.5mm的,需要一个2.5到3.5mm的转换接头,网上几块钱一个,买来接上手机播放音乐基本听不到声音!!!应该是输出功率小了,再找一个PAM8403超微型数字功放板(3W)进行放大,网上几块钱一个,焊接、连接后如下图。注意,S1的2.5mm接头不能全部插到底,否则声音效果不好,可能是左右声道的原因,具体也没搞清楚,还请不吝赐教啊。
加上放大器后,把3.5mm接头插入树莓派,则可以用树莓派随意大声播放了!
如何让S1控制树莓派播放特定声音呢?
1.通信,没有开放!!pwm开放了,那么可以让树莓派GPIO口检测机甲大师的pwm口的高低电平实现简单的S1到树莓派的单向通信。利用5个pwm的高低电平实现2的5次共32种信号,树莓派根据不同的信号播放不同的声音,从而实现语音播报斐波那契数列。
2.具体是通过树莓派3b+的BCM模式的第20/21/23/24/25号GPIO口连接pwm1-5,每秒检测一次各端口的电平状态。程序如下:
(1)树莓派段程序如下(配套的声音文件可以自己录制,只要是MP3格式就行,也可以微信找我要):
import RPi.GPIO as GPIO
import time
import os
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(20,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(21,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(23,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(24,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(25,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
time.sleep(0.5)
while True:
a=GPIO.input(20)
b=GPIO.input(21)
c=GPIO.input(23)
d=GPIO.input(24)
e=GPIO.input(25)
if a==1 and b==0 and c==0 and d==0 and e==0:
os.system('mpg321 ./peiyin/1.mp3 &')
elif a==0 and b==1 and c==0 and d==0 and e==0:
os.system('mpg321 ./peiyin/2.mp3 &')
elif a==1 and b==1 and c==0 and d==0 and e==0:
os.system('mpg321 ./peiyin/3.mp3 &')
elif a==0 and b==0 and c==1 and d==0 and e==0:
os.system('mpg321 ./peiyin/4.mp3 &')
elif a==1 and b==0 and c==1 and d==0 and e==0:
os.system('mpg321 ./peiyin/5.mp3 &')
elif a==0 and b==1 and c==1 and d==0 and e==0:
os.system('mpg321 ./peiyin/6.mp3 &')
elif a==1 and b==1 and c==1 and d==0 and e==0:
os.system('mpg321 ./peiyin/7.mp3 &')
elif a==0 and b==0 and c==0 and d==1 and e==0:
os.system('mpg321 ./peiyin/8.mp3 &')
elif a==1 and b==0 and c==0 and d==1 and e==0:
os.system('mpg321 ./peiyin/9.mp3 &')
elif a==0 and b==1 and c==0 and d==1 and e==0:
os.system('mpg321 ./peiyin/start.mp3 &')
elif a==1 and b==1 and c==0 and d==1 and e==0:
os.system('mpg321 ./peiyin/feibo.mp3 &')
elif a==0 and b==0 and c==1 and d==1 and e==0:
os.system('mpg321 ./peiyin/end.mp3 &')
elif a==1 and b==0 and c==0 and d==0 and e==1:
os.system('mpg321 ./peiyin/10.mp3 &')
elif a==0 and b==1 and c==0 and d==0 and e==1:
os.system('mpg321 ./peiyin/20.mp3 &')
elif a==1 and b==1 and c==0 and d==0 and e==1:
os.system('mpg321 ./peiyin/30.mp3 &')
elif a==0 and b==0 and c==1 and d==0 and e==1:
os.system('mpg321 ./peiyin/40.mp3 &')
elif a==1 and b==0 and c==1 and d==0 and e==1:
os.system('mpg321 ./peiyin/50.mp3 &')
elif a==0 and b==1 and c==1 and d==0 and e==1:
os.system('mpg321 ./peiyin/60.mp3 &')
elif a==1 and b==1 and c==1 and d==0 and e==1:
os.system('mpg321 ./peiyin/70.mp3 &')
elif a==0 and b==0 and c==0 and d==1 and e==1:
os.system('mpg321 ./peiyin/80.mp3 &')
elif a==1 and b==0 and c==0 and d==1 and e==1:
os.system('mpg321 ./peiyin/90.mp3 &')
else:
pass
time.sleep(1)
(2)机甲大师端程序见后续介绍
三、 任务实现
1.控制1-5号pwm输出不同的高低电平,实现与树莓派的单向通信
2.生成斐波那契数列,最大不超过100。
3.识别0-9十个标签,记录各标签的位置(使用了两种方法:一是使用识别并瞄准函数,这种方法对标签的质量要求较低,同等条件下可识别的标签在第二种方法中却不能被识别,缺点是速度慢;二是获取整体识别到的视觉标签信息,优点是速度快,缺点是需要将识别距离调为3m,根据光照条件适当调整曝光值为大或小,我在室内灯光条件下,设置为大曝光值,调整机甲大师的角度防止标签正好在反光的位置实现了10个标签的一次识别)。然后将标签的x、y值转换为云台的航向、俯仰角,从0-9存储到angleList列表中。需要注意的是对标签信息列表,通过index函数分别找到id为10-19的索引位置,将会与第一个10重复,需要先把第一个10值pop掉。
4.射击函数,从斐波那契数列中依次拿出一项,小于10时直接取出angleList中存储的航向、俯仰角,将云台调整到这个位置即可;大于10时通过整取、取余分别取出十位、个位按前方法调整云台位置即可。这里取余时有个BUG:千万不要用%取余符号,有%符号将导致存储的程序再次打开时就空白了,无论是存到云上还是本地、或是生成了dsp文件,统统不行!!可用以下变通方法进行取余:index01=b//10;index02=b-index01*10
import random
angleList=RmList()
feiboList=RmList()
infoList=RmList()
#pwm输出同树莓派通信函数
def output_Pwm(num=0,flag=0):
if num==0:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==1:
chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==2:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==3:
chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==4:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==5:
chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==6:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==7:
chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
chassis_ctrl.set_pwm_value(rm_define.pwm4,0)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==8:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==9:
chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
if flag==0:
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
chassis_ctrl.set_pwm_value(rm_define.pwm5,100)
elif num==10:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
elif num==11:
chassis_ctrl.set_pwm_value(rm_define.pwm1,100)
chassis_ctrl.set_pwm_value(rm_define.pwm2,100)
chassis_ctrl.set_pwm_value(rm_define.pwm3,0)
chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
elif num==12:
chassis_ctrl.set_pwm_value(rm_define.pwm1,0)
chassis_ctrl.set_pwm_value(rm_define.pwm2,0)
chassis_ctrl.set_pwm_value(rm_define.pwm3,100)
chassis_ctrl.set_pwm_value(rm_define.pwm4,100)
chassis_ctrl.set_pwm_value(rm_define.pwm5,0)
else:
pass
#生成斐波那契数列
def make_Feibo():
global feiboList
feiboList.append(random.randint(1,5))
feiboList.append(random.randint(1,5))
output_Pwm(10,0)
time.sleep(1)
output_Pwm(0,0)
time.sleep(2)
output_Pwm(feiboList[1],0)
time.sleep(1)
output_Pwm(feiboList[2],0)
time.sleep(1)
output_Pwm(0,0)
for i in range(3,12):
a=feiboList[i-1]+feiboList[i-2]
if a>100:break
feiboList.append(a)
#存储云台航向、俯仰角函数
def storage_Angle():
global angleList
angleList.append(gimbal_ctrl.get_axis_angle(rm_define.gimbal_axis_yaw))
angleList.append(gimbal_ctrl.get_axis_angle(rm_define.gimbal_axis_pitch))
#方法一:通过识别并瞄准函数获取0-9标签位置信息的函数
def detect_Marker_0to9_by_aim():
vision_ctrl.enable_detection(rm_define.vision_detection_marker)
vision_ctrl.set_marker_detection_distance(2)
gimbal_ctrl.set_rotate_speed(180)
#try to use the number of enum
'''for i in range(10,20):
vision_ctrl.detect_marker_and_aim(i)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)'''
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_zero)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_one)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_two)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_three)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_four)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_five)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_six)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_seven)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_eight)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
vision_ctrl.detect_marker_and_aim(rm_define.marker_number_nine)
time.sleep(0.2)
storage_Angle()
gimbal_ctrl.angle_ctrl(0,0)
#方法二:通过一次整体识别函数获取0-9标签位置信息的函数
def detect_Marker_0to9_by_info():
global infoList
global angleList
vision_ctrl.enable_detection(rm_define.vision_detection_marker)
vision_ctrl.set_marker_detection_distance(3)
media_ctrl.exposure_value_update(rm_define.exposure_value_large)
time.sleep(2)
while len(infoList)!=51:
infoList=RmList(vision_ctrl.get_marker_detection_info())
time.sleep(1)
media_ctrl.play_sound(rm_define.media_sound_scanning)
if len(infoList)==51:
infoList.pop(1)
for i in range(10,20):
indexofi=infoList.index(i)
angleList.append((infoList[indexofi+1]-0.5)*96)
angleList.append((0.5-infoList[indexofi+2])*54)
#射击函数
def shoot():
global feiboList
global angleList
global infoList
output_Pwm(11,0)
time.sleep(1)
output_Pwm(0,0)
time.sleep(2)
for i in range(1,len(feiboList)+1):
b=feiboList[ i ]
print(b)
time.sleep(2)
if b<10:
gimbal_ctrl.angle_ctrl(angleList[b*2+1],angleList[b*2+2])
led_ctrl.gun_led_on()
output_Pwm(b,0)
time.sleep(1)
output_Pwm(0,0)
led_ctrl.gun_led_off()
else:
index01=int(b//10)
index02=b-index01*10
gimbal_ctrl.angle_ctrl(angleList[index01*2+1],angleList[index01*2+2])
output_Pwm(index01,1)
led_ctrl.gun_led_on()
time.sleep(1)
output_Pwm(0,0)
led_ctrl.gun_led_off()
gimbal_ctrl.angle_ctrl(angleList[index02*2+1],angleList[index02*2+2])
output_Pwm(index02,0)
led_ctrl.gun_led_on()
time.sleep(1)
output_Pwm(0,0)
led_ctrl.gun_led_off()
def start():
global feiboList
global angleList
global infoList
media_ctrl.record(1)
robot_ctrl.set_mode(rm_define.robot_mode_free)
make_Feibo()
print(feiboList)
time.sleep(1)
#detect_Marker_0to9_by_aim()
detect_Marker_0to9_by_info()
print(angleList)
time.sleep(1)
shoot()
output_Pwm(12,0)
time.sleep(1)
output_Pwm(0,0)
time.sleep(2)
media_ctrl.record(0)
总结:基本实现了预期效果,但有两方面的缺点:一是为等待树莓派读数,主程序必须加sleep函数等待,造成整体看来比较迟钝;二是pwm输出和树莓派的输入不十分稳定,虽然设置了下拉电阻,但时不时的会有个别意外的信号被捕捉到,尚需改进。
不足之处欢迎批评指正,交流学习!!!微信号:cumtzd