人工智能-樹莓派小車(4)——通過語音玩轉(zhuǎn)智能小車

提示

今年注冊的賬號可能百度,改變了下發(fā)的數(shù)據(jù)格式,不再是文本格式,是以鏈接的形式。具體的我還沒有研究。大家可以看返回的數(shù)據(jù),payload里面是text還是url,是text 的可以用我這個方法,url的暫時還不行,等我有時間看一看如何提取,會再更新的

本文是基于百度的DuerOS Python SDK進(jìn)行的,具體安裝以及實現(xiàn)過程,可以看我的這篇教程:人工智能-樹莓派小車(1)——DuerOS語音喚醒,要實現(xiàn)的功能有:

  1. 語音聊天:可以跟智能小車進(jìn)行對話,詢問現(xiàn)在的天氣,播放想聽的歌曲等等基本對話;
  2. 語音控制:可以通過語音的操作方式控制智能小車的前進(jìn)后退、避障轉(zhuǎn)彎等功能,進(jìn)一步可以擴(kuò)展到家里的臺燈、空調(diào)、窗簾等等家具;
  3. 語音反饋:在你發(fā)出命令后,小車還會給出回應(yīng),與你互動,實現(xiàn)一個良好的反饋。

視頻演示

實現(xiàn)了以上幾個功能,做了一個演示,視頻鏈接:通過語音玩轉(zhuǎn)智能小車

核心代碼

1. 命令讀取

content = u'云端下發(fā)directive:%s' % (directive_content)

content里即為我們要讀取的命令數(shù)據(jù),是一種類JSON格式,所以有兩種辦法將數(shù)據(jù)讀取出來。

  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. 直接將數(shù)據(jù)保存為.txt格式
f = open("ord.txt",'a')
f.write(content)
logging.info(content)

2. 命令判斷

讀取到命令之后要對其進(jìn)行檢測,如果命令中包含一些特定的關(guān)鍵詞,則做出相應(yīng)的動作。

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"關(guān)") !=-1 and command.find(u"大") !=-1 and command.find(u"燈") !=-1:
                print "關(guān)閉前大燈"
                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"進(jìn)") !=-1:
                print "前進(jìn)"
                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"轉(zhuǎn)") !=-1:
                print "左轉(zhuǎn)"
                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"轉(zhuǎn)") !=-1:
                print "右轉(zhuǎn)"
                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接口的設(shè)置以及初始化,見人工智能-樹莓派小車-GPIO控制小車
最后要養(yǎng)成良好習(xí)慣,用完GPIO接口記得清理GPIO口

GPIO.cleanup()

3. 命令文件清空

為避免命令文件堆積,每次識別命令結(jié)束后,進(jìn)行命令文件的清理,代碼很簡單。

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

4. 命令反饋

這部分集成到了第二部分命令判斷中,判斷完立即進(jìn)行反饋。
要注意的是,在第二部分每一條命令都有一條這樣的代碼
GPIO.output(LED_CTR, GPIO.HIGH)
這一步正是屏蔽掉DuerOS原有的語音反饋的關(guān)鍵

  1. 首先錄制好自己想要的話語,然后仿照我的代碼放到對應(yīng)的位置
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_right.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
  1. 接下來是最關(guān)鍵的一步
    sdk/interface里面有一個speech_synthesizer.py文件,這個文件就是控制TTS語音輸出的,在這對代碼進(jìn)行一定修改,就可以實現(xiàn)播放我們自定義的音頻。
    2.1
import RPi.GPIO as GPIO
LED_CTR = 5 #與上面端口一致,用于檢測是否有控制指令發(fā)送

然后在speak函數(shù)加入一條檢測指令

def speak(self, directive):
        '''
        播放TTS(云端directive name方法)
        :param directive: 云端下發(fā)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)——通過語音玩轉(zhuǎn)智能小車
人工智能-樹莓派小車(5)——用微信控制智能小車

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容