ロボットとお話しよう2(音声でラジコン操作)
の続き
[Raspberry Pi]USBマイクと音声認識ソフトJuliusを使って音声認識を試す(2) : 工作と競馬
[Raspberry Pi]USBマイクと音声認識ソフトJuliusを使って音声認識を試す(3) ~ フルカラーLEDを音声で操作 ~ : 工作と競馬
をとても参考にさせていただきました。 感謝です。
目標
声を使ってラジコンを操作
準備
dictation-kit-v4.3.1-linuxからmodelファイルをコピーしてこれから作業するフォルダにおく
手順
- teleop.dic(utf-8で作成)ファイルの作成
右 m i g i 左 h i d a r i 前 m a e 後ろ u sh i r o 停止 t e i sh i
- juliusの設定ファイルのteleop.jconfの作成
-w teleop.dic #単語辞書ファイル #-v model/lang_m/bccwj.60k.htkdic #N-gram、または文法用の単語辞書ファイルを指定$ -h model/phone_m/jnas-tri-3k16-gid.binhmm #使用するHMM定義ファイル -hlist model/phone_m/logicalTri #HMMlistファイルを指定する -n 5 #n個の文仮説数が見つかるまで検索を行う -output 1 #見つかったN-best候補のうち、結果として出力する個数 -input mic #-demo #マイク使用 -zmeanframe -rejectshort 600 #検出された入力が閾値以下なら棄却 #-charconv euc-jp utf8 #入出力エンコード指定(内部euc-jp, 出力utf-8) -lv 1000 #入力の振幅レベルの閾値(0~32767)
- juliusを起動するシェルスクリプトrun_teleop.shの作成
#! /bin/sh export ALSADEV=“plughw:1,0” julius -C teleop.jconf -demo -input alsa -nostrip -module > /dev/null & echo $! sleep 3
- juliusから送られるコマンドを受け取りarduinoに送る
以下com_julius_arduino.pyを作成。 これを実行すると音声入力に対し、cmd_velがpubされる。
#!/usr/bin/python # coding:utf-8 import rospy from sensor_msgs.msg import Joy from geometry_msgs.msg import Twist import socket import subprocess import xml.etree.ElementTree as ET HOST = "localhost" PORT = 10500 teleop_cmd = [ u"右" , \ u"左" , \ u"前" , \ u"後ろ" , \ u"停止" ] class RosSet(object): def __init__(self): rospy.init_node('voice_twist') self.twist_pub = rospy.Publisher('cmd_vel', Twist, queue_size=100) self.twist = Twist() def sendCmd(self, cmdName): if cmdName==u"前": self.twist.linear.x = 10 self.twist.angular.z = 0 elif cmdName==u"後ろ": self.twist.linear.x = -10 self.twist.angular.z = 0 elif cmdName==u"右": self.twist.linear.x = 0 self.twist.angular.z = -10 elif cmdName==u"左": self.twist.linear.x = 0 self.twist.angular.z = 10 elif cmdName==u"停止": self.twist.linear.x = 0 self.twist.angular.z = 0 rospy.loginfo(self.twist) self.twist_pub.publish(self.twist) def main(): rosset = RosSet() p = subprocess.Popen(["sh run_teleop.sh"], stdout=subprocess.PIPE, shell=True) pid = p.stdout.read() # juliusのプロセスIDを取得 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) try: data = "" while 1: if "</RECOGOUT>\n." in data: root = ET.fromstring('<?xml version="1.0"?>\n' + data[data.find("<RECOGOUT>"):].replace("\n.", "")) for whypo in root.findall("./SHYPO/WHYPO"): if whypo.get("WORD") in teleop_cmd: # 判別した言葉を表示する print whypo.get("WORD") rosset.sendCmd(whypo.get("WORD")) else: print "Unknown" data = "" else: try: data = data + client.recv(1024) except: print "ps kill." p.kill() # subprocess.call(["kill " + pid], shell=True) client.close() break except KeyboardInterrupt: print "KeyboardInterrupt occured." p.kill() # subprocess.call(["kill " + pid], shell=True) client.close() if __name__ == "__main__": main()
参考: