人工智能-树莓派小车(4)——通过语音玩转智能小车

提示

今年注册的账号可能百度,改变了下发的数据格式,不再是文本格式,是以链接的形式。具体的我还没有研究。大家可以看返回的数据,payload里面是text还是url,是text 的可以用我这个方法,url的暂时还不行,等我有时间看一看如何提取,会再更新的

本文是基于百度的DuerOS Python SDK进行的,具体安装以及实现过程,可以看我的这篇教程:人工智能-树莓派小车(1)——DuerOS语音唤醒,要实现的功能有:

  1. 语音聊天:可以跟智能小车进行对话,询问现在的天气,播放想听的歌曲等等基本对话;
  2. 语音控制:可以通过语音的操作方式控制智能小车的前进后退、避障转弯等功能,进一步可以扩展到家里的台灯、空调、窗帘等等家具;
  3. 语音反馈:在你发出命令后,小车还会给出回应,与你互动,实现一个良好的反馈。

视频演示

实现了以上几个功能,做了一个演示,视频链接:通过语音玩转智能小车

核心代码

1. 命令读取

content = u'云端下发directive:%s' % (directive_content)

content里即为我们要读取的命令数据,是一种类JSON格式,所以有两种办法将数据读取出来。

  1. 采用JSON的字典格式
import json

with open('out.json','a') as f:
        f.write(json.loads(content).decode('unicode-escape').encode('utf-8'))
        f.close()
  1. 直接将数据保存为.txt格式
f = open("ord.txt",'a')
f.write(content)
logging.info(content)

2. 命令判断

读取到命令之后要对其进行检测,如果命令中包含一些特定的关键词,则做出相应的动作。

def recognize():

        file = '/home/pi/Rascar-DuerOS-Python-Client/ord.txt' # 读取文件
        f = open(file,'r')
        out = f.read()
        command = out.decode('unicode-escape').encode('utf-8')
        print command
        GPIO.output(LED_CTR, GPIO.LOW)
        ############################################
        ###############命令识别######################
        ############################################
        
        if command.find(u"开") !=-1 and command.find(u"大") !=-1 and command.find(u"灯") !=-1:
                print "打开前大灯"
                robot.Open_Flight()
                GPIO.output(LED_CTR, GPIO.HIGH)
                shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_on_light.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
                
        elif command.find(u"关") !=-1 and command.find(u"大") !=-1 and command.find(u"灯") !=-1:
                print "关闭前大灯"
                robot.Close_Flight()
                GPIO.output(LED_CTR, GPIO.HIGH)
                shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_off_light.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
                
        elif command.find(u"前") !=-1 and command.find(u"进") !=-1:
                print "前进"
                robot.Motor_Forward()
                time.sleep(2)
                robot.Motor_Stop()
                GPIO.output(LED_CTR, GPIO.HIGH)
                shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/forward.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
                
        elif command.find(u"后") !=-1 and command.find(u"退") !=-1:
                print "后退"
                robot.Motor_Backward()
                time.sleep(2)
                robot.Motor_Stop()
                GPIO.output(LED_CTR, GPIO.HIGH)
                shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/backward.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
                
        elif command.find(u"左") !=-1 and command.find(u"转") !=-1:
                print "左转"
                robot.Motor_TurnLeft()
                p = GPIO.PWM(11, 3)
                p.start(20)
                time.sleep(0.5)
                p.stop()
                robot.Motor_Stop()
                GPIO.output(11, GPIO.LOW)
                GPIO.output(LED_CTR, GPIO.HIGH)
                shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_left.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
                
        elif command.find(u"右") !=-1 and command.find(u"转") !=-1:
                print "右转"
                robot.Motor_TurnRight()
                p = GPIO.PWM(8, 3)
                p.start(20)
                time.sleep(0.5)
                p.stop()
                robot.Motor_Stop()
                GPIO.output(8, GPIO.LOW)
                GPIO.output(LED_CTR, GPIO.HIGH)
                shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_right.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
                
        elif command.find(u"黑") !=-1 and command.find(u"线") !=-1:
                print "黑线"
                robot.TrackLine()
        return 

其中GPIO接口的设置以及初始化,见人工智能-树莓派小车-GPIO控制小车
最后要养成良好习惯,用完GPIO接口记得清理GPIO口

GPIO.cleanup()

3. 命令文件清空

为避免命令文件堆积,每次识别命令结束后,进行命令文件的清理,代码很简单。

f = open("ord.txt",'w')
f.truncate()
f.close()

4. 命令反馈

这部分集成到了第二部分命令判断中,判断完立即进行反馈。
要注意的是,在第二部分每一条命令都有一条这样的代码
GPIO.output(LED_CTR, GPIO.HIGH)
这一步正是屏蔽掉DuerOS原有的语音反馈的关键

  1. 首先录制好自己想要的话语,然后仿照我的代码放到对应的位置
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_right.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
  1. 接下来是最关键的一步
    sdk/interface里面有一个speech_synthesizer.py文件,这个文件就是控制TTS语音输出的,在这对代码进行一定修改,就可以实现播放我们自定义的音频。
    2.1
import RPi.GPIO as GPIO
LED_CTR = 5 #与上面端口一致,用于检测是否有控制指令发送

然后在speak函数加入一条检测指令

def speak(self, directive):
        '''
        播放TTS(云端directive name方法)
        :param directive: 云端下发directive
        :return:
        '''
        # directive from dueros may not have the dialogRequestId
        if 'dialogRequestId' in directive['header']:
            dialog_request_id = directive['header']['dialogRequestId']
            if self.dueros.speech_recognizer.dialog_request_id != dialog_request_id:
                return

        self.token = directive['payload']['token']
        url = directive['payload']['url']
        if url.startswith('cid:'):
            mp3_file = os.path.join(tempfile.gettempdir(), url[4:] + '.mp3')
            if os.path.isfile(mp3_file):
                self.finished.clear()
                # os.system('mpv "{}"'.format(mp3_file))
                if GPIO.input(LED_CTR) == 1 :
                    self.player.play('file://{}'.format('/home/pi/DuerOS-Python-Client/temp.mp3'))
                    os.remove("temp.mp3")
                else :
                    self.player.play('file://{}'.format(mp3_file))
                self.__speech_started()

                self.dueros.state_listener.on_speaking()

                # will be set at SpeechFinished() if the player reaches the End Of Stream or gets a error
                self.finished.wait()

                os.system('rm -rf "{}"'.format(mp3_file))

就可以啦

完整代码

所有的代码都上传到了我的GitHub上
Rascar-DuerOS — a Raspberry intelligent car based on the DuerOS

系列教程

人工智能-树莓派小车(1)——DuerOS语音唤醒
人工智能-树莓派小车(2)——GPIO接口介绍
人工智能-树莓派小车(3)——GPIO控制小车
人工智能-树莓派小车(4)——通过语音玩转智能小车
人工智能-树莓派小车(5)——用微信控制智能小车

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容