孩子小时候,我哼得最多的曲子,最多三遍,一定睡着
S1新加入了播放音符的功能,看了一些机友的视频,大家都用scratch写的吧,逐个音符输入很累吧。
本程序用python编写,采用了一些技术手段,可以把你从繁琐的输入中解放出来,轻轻松松播放各种曲子
首先,那个长长的define非常不友好,rm_define.media_sound_solmization_1C,一个音符就这么长,敲键盘要敲多久啊。那个1C,要想一想才知道是低音1。要是看简谱录入,你还是要反应一下,用scratch的话,你还要人工做唱名到钢琴键之间的映射,太麻烦了
其次,一句一句地写media_ctrl.play_sound(),太累了,用scratch的话,一个一个调用播放音符模块,同样太累了,要是输错了一个音符,你就慢慢找吧
于是,我先定义了一个编码,11-17表示低音1-7,21-27表示中音1-7,31-37表示高音1-7,至于升半音,那就加0.5,比如23.5表示中音3#,特别地,0表示休止符。代码如下
global note
note = [\
rm_define.media_sound_solmization_1C,rm_define.media_sound_solmization_1CSharp,\
rm_define.media_sound_solmization_1D,rm_define.media_sound_solmization_1DSharp,\
rm_define.media_sound_solmization_1E,\
rm_define.media_sound_solmization_1F,rm_define.media_sound_solmization_1FSharp,\
rm_define.media_sound_solmization_1G,rm_define.media_sound_solmization_1GSharp,\
rm_define.media_sound_solmization_1A,rm_define.media_sound_solmization_1ASharp,\
rm_define.media_sound_solmization_1B,\
rm_define.media_sound_solmization_2C,rm_define.media_sound_solmization_2CSharp,\
rm_define.media_sound_solmization_2D,rm_define.media_sound_solmization_2DSharp,\
rm_define.media_sound_solmization_2E,\
rm_define.media_sound_solmization_2F,rm_define.media_sound_solmization_2FSharp,\
rm_define.media_sound_solmization_2G,rm_define.media_sound_solmization_2GSharp,\
rm_define.media_sound_solmization_2A,rm_define.media_sound_solmization_2ASharp,\
rm_define.media_sound_solmization_2B,\
rm_define.media_sound_solmization_3C,rm_define.media_sound_solmization_3CSharp,\
rm_define.media_sound_solmization_3D,rm_define.media_sound_solmization_3DSharp,\
rm_define.media_sound_solmization_3E,\
rm_define.media_sound_solmization_3F,rm_define.media_sound_solmization_3FSharp,\
rm_define.media_sound_solmization_3G,rm_define.media_sound_solmization_3GSharp,\
rm_define.media_sound_solmization_3A,rm_define.media_sound_solmization_3ASharp,\
rm_define.media_sound_solmization_3B]
def play_note(x):
a = x // 10 - 1
b = x * 2 % 20 - 2
if b > 5:
b -= 1
n = int(a * 12 + b)
if x != 0:
media_ctrl.play_sound(note[n])
函数play_note(x) 直接播放我定义的编码对应的音符,至于这个函数怎么写的,比较难说明白,大家当黑匣子就好
然后,定义一个数组,用两个数表示一个音,第一个数就是上述编码,第二个数是音长,简单粗暴一点,1表示四分音符,0.5表示八分音符,0.25表示十六分音符,1.5表示附点四分音符,呵呵,总之就是1代表1拍,对应实际时间1秒。比如勃拉姆斯的摇篮曲,代码如下,直接照着简谱抄,童叟无欺:
music = [\
23,0.5, 23,0.5, 25,1.5, 23,0.5, 23,1, 25,1, 0,1, 23,0.5, 25,0.5, 31,1, 27,1.5, 26,0.5, 26,1, 25,1, 22,0.5, 23,0.5,\
24,1, 22,1, 22,0.5, 23,0.5, 24,1, 0,1, 22,0.5, 24,0.5, 27,0.5, 26,0.5, 25,1, 27,1, 31,1, 0,1, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,1, 25,1, 26,1, 23,0.25, 25,1.75, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,0.5, 25,0.25, 24,0.25, 23,1, 22,1, 21,2]
我写的时候,故意把两个数写得紧凑,而每两个数之间加了一个空格,这样有什么问题好查
播放就很简单了,一个循环,读数组,播音符,over
def start():
global note
global music
for i in range(0,len(music)//2):
play_note(music[2*i])
time.sleep(music[2*i+1])
简单吧,要播放其他音乐,换music数组就好,程序不动,动的只是数据
DJI要是再支持文件读写就更爽了,音乐写在文件里,读文件播放,源代码都可以不动
播放音乐搞定了,现在要加上动作,怎么加呢?很遗憾,DJI还没有支持多线程,需要有一个变通的办法
怎么做呢?就是在上面time.sleep()函数这里做文章。我玩过很多种机器人,对于几乎所有的机器人,sleep,wait之类的函数都非常坑爹,要想编出高级程序,必须放弃这一类函数
具体做法,用计时器,代码框架是这样的
for i in range(0,len(music)//2):
play_note(music[2*i])
t0 = tools.timer_current()
t = t0
while t < t0 + music[2*i+1]:
t = tools.timer_current()
#这里插入你要做的事情
播放音符是一个非阻塞功能,执行了之后,后台就播放去了,前台交到你手里
这时,用变量t0记录当前时间,再用循环反复检查(当前时间-t0)有没有达到你期望的延迟,就可以实现sleep函数的效果,但是你获得了做你自己的事情的机会
具体到这个曲子,既然是摇篮曲,那就模拟摇摇篮的动作吧,用一个周期函数控制速度,做一个圆弧运动就好。代码如下:
for i in range(0,len(music)//2):
play_note(music[2*i])
t0 = tools.timer_current()
t = t0
while t < t0 + music[2*i+1]:
t = tools.timer_current()
v = 0.5*math.cos(t*1.5)
chassis_ctrl.move_with_speed(v,0,v/math.pi*180)
chassis_ctrl.stop()
再配合一下灯效,用呼吸灯。可惜呼吸灯不能调周期,没法与音乐融为一体,是个遗憾
led_ctrl.set_bottom_led(rm_define.armor_bottom_all, 69, 215, 255, rm_define.effect_breath)
led_ctrl.set_top_led(rm_define.armor_top_all, 69, 215, 255, rm_define.effect_breath)
再让云台摆个姿势,就当是一位父亲抱着小宝宝,哼着摇篮曲,轻轻摇动:D
robot_ctrl.set_mode(rm_define.robot_mode_free)
gimbal_ctrl.set_rotate_speed(270)
gimbal_ctrl.angle_ctrl(90, -15)
视频如下:
S1新加入了播放音符的功能,看了一些机友的视频,大家都用scratch写的吧,逐个音符输入很累吧。
本程序用python编写,采用了一些技术手段,可以把你从繁琐的输入中解放出来,轻轻松松播放各种曲子
首先,那个长长的define非常不友好,rm_define.media_sound_solmization_1C,一个音符就这么长,敲键盘要敲多久啊。那个1C,要想一想才知道是低音1。要是看简谱录入,你还是要反应一下,用scratch的话,你还要人工做唱名到钢琴键之间的映射,太麻烦了
其次,一句一句地写media_ctrl.play_sound(),太累了,用scratch的话,一个一个调用播放音符模块,同样太累了,要是输错了一个音符,你就慢慢找吧
于是,我先定义了一个编码,11-17表示低音1-7,21-27表示中音1-7,31-37表示高音1-7,至于升半音,那就加0.5,比如23.5表示中音3#,特别地,0表示休止符。代码如下
global note
note = [\
rm_define.media_sound_solmization_1C,rm_define.media_sound_solmization_1CSharp,\
rm_define.media_sound_solmization_1D,rm_define.media_sound_solmization_1DSharp,\
rm_define.media_sound_solmization_1E,\
rm_define.media_sound_solmization_1F,rm_define.media_sound_solmization_1FSharp,\
rm_define.media_sound_solmization_1G,rm_define.media_sound_solmization_1GSharp,\
rm_define.media_sound_solmization_1A,rm_define.media_sound_solmization_1ASharp,\
rm_define.media_sound_solmization_1B,\
rm_define.media_sound_solmization_2C,rm_define.media_sound_solmization_2CSharp,\
rm_define.media_sound_solmization_2D,rm_define.media_sound_solmization_2DSharp,\
rm_define.media_sound_solmization_2E,\
rm_define.media_sound_solmization_2F,rm_define.media_sound_solmization_2FSharp,\
rm_define.media_sound_solmization_2G,rm_define.media_sound_solmization_2GSharp,\
rm_define.media_sound_solmization_2A,rm_define.media_sound_solmization_2ASharp,\
rm_define.media_sound_solmization_2B,\
rm_define.media_sound_solmization_3C,rm_define.media_sound_solmization_3CSharp,\
rm_define.media_sound_solmization_3D,rm_define.media_sound_solmization_3DSharp,\
rm_define.media_sound_solmization_3E,\
rm_define.media_sound_solmization_3F,rm_define.media_sound_solmization_3FSharp,\
rm_define.media_sound_solmization_3G,rm_define.media_sound_solmization_3GSharp,\
rm_define.media_sound_solmization_3A,rm_define.media_sound_solmization_3ASharp,\
rm_define.media_sound_solmization_3B]
def play_note(x):
a = x // 10 - 1
b = x * 2 % 20 - 2
if b > 5:
b -= 1
n = int(a * 12 + b)
if x != 0:
media_ctrl.play_sound(note[n])
函数play_note(x) 直接播放我定义的编码对应的音符,至于这个函数怎么写的,比较难说明白,大家当黑匣子就好
然后,定义一个数组,用两个数表示一个音,第一个数就是上述编码,第二个数是音长,简单粗暴一点,1表示四分音符,0.5表示八分音符,0.25表示十六分音符,1.5表示附点四分音符,呵呵,总之就是1代表1拍,对应实际时间1秒。比如勃拉姆斯的摇篮曲,代码如下,直接照着简谱抄,童叟无欺:
music = [\
23,0.5, 23,0.5, 25,1.5, 23,0.5, 23,1, 25,1, 0,1, 23,0.5, 25,0.5, 31,1, 27,1.5, 26,0.5, 26,1, 25,1, 22,0.5, 23,0.5,\
24,1, 22,1, 22,0.5, 23,0.5, 24,1, 0,1, 22,0.5, 24,0.5, 27,0.5, 26,0.5, 25,1, 27,1, 31,1, 0,1, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,1, 25,1, 26,1, 23,0.25, 25,1.75, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,0.5, 25,0.25, 24,0.25, 23,1, 22,1, 21,2]
我写的时候,故意把两个数写得紧凑,而每两个数之间加了一个空格,这样有什么问题好查
播放就很简单了,一个循环,读数组,播音符,over
def start():
global note
global music
for i in range(0,len(music)//2):
play_note(music[2*i])
time.sleep(music[2*i+1])
简单吧,要播放其他音乐,换music数组就好,程序不动,动的只是数据
DJI要是再支持文件读写就更爽了,音乐写在文件里,读文件播放,源代码都可以不动
播放音乐搞定了,现在要加上动作,怎么加呢?很遗憾,DJI还没有支持多线程,需要有一个变通的办法
怎么做呢?就是在上面time.sleep()函数这里做文章。我玩过很多种机器人,对于几乎所有的机器人,sleep,wait之类的函数都非常坑爹,要想编出高级程序,必须放弃这一类函数
具体做法,用计时器,代码框架是这样的
for i in range(0,len(music)//2):
play_note(music[2*i])
t0 = tools.timer_current()
t = t0
while t < t0 + music[2*i+1]:
t = tools.timer_current()
#这里插入你要做的事情
播放音符是一个非阻塞功能,执行了之后,后台就播放去了,前台交到你手里
这时,用变量t0记录当前时间,再用循环反复检查(当前时间-t0)有没有达到你期望的延迟,就可以实现sleep函数的效果,但是你获得了做你自己的事情的机会
具体到这个曲子,既然是摇篮曲,那就模拟摇摇篮的动作吧,用一个周期函数控制速度,做一个圆弧运动就好。代码如下:
for i in range(0,len(music)//2):
play_note(music[2*i])
t0 = tools.timer_current()
t = t0
while t < t0 + music[2*i+1]:
t = tools.timer_current()
v = 0.5*math.cos(t*1.5)
chassis_ctrl.move_with_speed(v,0,v/math.pi*180)
chassis_ctrl.stop()
再配合一下灯效,用呼吸灯。可惜呼吸灯不能调周期,没法与音乐融为一体,是个遗憾
led_ctrl.set_bottom_led(rm_define.armor_bottom_all, 69, 215, 255, rm_define.effect_breath)
led_ctrl.set_top_led(rm_define.armor_top_all, 69, 215, 255, rm_define.effect_breath)
再让云台摆个姿势,就当是一位父亲抱着小宝宝,哼着摇篮曲,轻轻摇动:D
robot_ctrl.set_mode(rm_define.robot_mode_free)
gimbal_ctrl.set_rotate_speed(270)
gimbal_ctrl.angle_ctrl(90, -15)
视频如下: