スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


にほんブログ村 その他趣味ブログ LEGO・ブロックへ

Androidの音声認識でアルファレックスを動かす - プログラミング編2

こんばんは、matkです。

まず音声認識部分ですが、このサイトを参考にしました。こんな感じで超簡潔に書けます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import android

droid = android.Android()
while True:
    word = droid.recognizeSpeech().result
    print word.encode('utf-8')
    if word == u'右に':
        turn_right()

はじめは音声認識だけでなく、傾きなどでも操作できるようにしていましたが、なかなか敏感で子供には操作が難しそうなので途中でやめました。センサーの値の取得の仕方は、これらのサイトが詳しいです([1,2,3])。

さて、今回のフェンダー(≒アルファレックス)のプログラムですが、以下になりました。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from time import sleep
import math
import thread
import sys
import android
from nxt.sensor import *
from nxt.motor import *
import nxt.locator

b = nxt.locator.find_one_brick()
m_face = nxt.Motor(b, nxt.PORT_A)
m_walk = nxt.Motor(b, nxt.PORT_B)
m_wave = nxt.Motor(b, nxt.PORT_C)
m_forward = nxt.SynchronizedMotors(m_walk, m_wave, 0)
t_walk = Touch(b, PORT_1)
t_wave = Touch(b, PORT_4)
color  = Color20(b, PORT_2)
irseeker = HTIRSeekerv2(b, PORT_3)

def wave_one_unit(ini_wait=1):
    m_wave.run(127)
    sleep(ini_wait)
    while t_wave.get_sample():
        sleep(0.05)
    sleep(0.37)
    m_wave.brake()
    sleep(0.5)

def walk_one_unit(ini_wait=0.5):
    m_walk.run(127)
    sleep(ini_wait)
    while not t_walk.get_sample():
        sleep(0.05)
    sleep(0.15)
    m_walk.brake()
    sleep(0.5)

def go_forward():
    for i in range(0,4):
        thread.start_new_thread(m_face.turn, (127, 1080))
        thread.start_new_thread(wave_one_unit, ())
        walk_one_unit()

def turn_left():
    for i in range(0,4):
        thread.start_new_thread(m_face.turn, (127, 1080))
        walk_one_unit()

def turn_right():
    m_forward.turn(127, 460)
    thread.start_new_thread(m_face.turn, (127, 1080*4))
    m_walk.turn(127, 1080*4)
    thread.start_new_thread(wave_one_unit, (0,))
    walk_one_unit(0)

def nanana():
    for i in range(0,2):
        wave_one_unit()
    b.play_sound_file(0,"nanana.rso")
    sleep(4)

def turn_to_me():
    dirix = irseeker.get_sample().direction
    print dirix
    if dirix in [0,5,6]:
        return
    sign = +1 if dirix - 5.5 > 0 else -1
    if sign == 1:
        m_forward.turn(127, 460)
        sleep(0.5)
    while math.fabs(dirix - 5.5) > 1:
        thread.start_new_thread(m_face.turn, (127, 1080))
        walk_one_unit()
        dirix = irseeker.get_sample().direction
        sleep(0.5)
        new_sign = +1 if dirix - 5.5 > 0 else -1
        if new_sign * sign < 0:
            break
    if sign == 1:
        thread.start_new_thread(wave_one_unit, (0,))
        walk_one_unit(0)
    sleep(1)

def voice_event_loop():
    droid = android.Android()
    while True:
        word = droid.recognizeSpeech().result
        print word.encode('utf-8')
        if word == u'右に':
            turn_right()
        elif word == u'左に':
            turn_left()
        elif word == u'アルク':
            go_forward()
        elif word == u'こっち向いて':
            turn_to_me()


thread.start_new_thread(voice_event_loop, ())
while True:
    #1:black/none, 2:blue, 3:green, 4:yellow, 5:red, 6:white/pink
    colorix = color.get_sample()
    if colorix == 2:
        nanana()
    elif colorix == 4:
        b.play_sound_file(0, "Goodbye.rso")
        sleep(2)
        sys.exit()
    elif colorix == 5:
        b.play_sound_file(0, "Red.rso")
        sleep(2)
プログラムの簡単な説明をします。
このアルファレックスは一アクション終えると常に右足が一歩前に出るように(左足に重心があるように)プログラムされています。ロジックを簡潔にするためです。
・turn_left()は足をバタバタさせる(walk_one_unit()を何回か呼ぶ)だけでOKです。
・turn_right()は半歩歩いて、右足に重心を移したのちに、足をバタバタさせています。
・nanana()はDVD中の腰振りダンスです。声とダンスを同時にすると、声がモーター音にかきけされますので、わざとずらしてあります。
・turn_to_me()は赤外線ボールの方を向きます。センサーの値が5,6はほぼ真正面を意味しますので、この数字を目標にしています(5.5を使っています)。

102行目からはメインです。
音声認識のループとカラーセンサーで行動を変える部分を別スレッドで走らせています。モーターの制御が変にバッティングしなければ、これぐらいルーズな並列化でOKと思います。正直pythonはまだまだ未熟ですので、もっと良い方法、もっとこう書くべき、というのがありましたらコメントで教えてくださいまし。

ちなみにnxt-pythonのせいなのか自分のカラーセンサーのせいなのかわかりませんが、緑色の識別がなかなかうまく行きません。緑は黒になりやすく、ピンクは白と判定されます。ちなみに指などは赤です。

音声認識の方は、「左」「アルク」は大丈夫ですが、「右」と「こっち」はかなり認識されにくいです。短い単語や撥音が含まれていると認識率が下がるようです。はじめは、以下のようにこれでもOKリストというのを作っていました。さすがに負けてる気がしてやめました。
migi_list = [u'右', 'muji', 'wiki', u'ネギ', 'mm', 'mugi', u'水着']
kocchi_list = [u'こっち', u'ごち', 'watch', u'東風', u'1', u'ぼっち', u'バッチ', u'腰', u'高知']
Googleの音声認識は学習データが共通で、万人向けの1つの判別器を作ろうとしているからこのようになるのだと思います。個人的には10時間ぐらい用意された文章を淡々と読む気力はありますので、個々人の判別器を作る方法というのを用意して欲しいと思います。カーナビもそうです。
スポンサーサイト


にほんブログ村 その他趣味ブログ LEGO・ブロックへ

コメントの投稿

非公開コメント

No title

音声認識の部分はどうなっているんだろう、と思っていたのですが、えらい簡潔でビビリましたwこれで認識してくれちゃうんですねぇ。

音声で操れるロボットが作ってみたいな~と思っていたのですが、これを使えば出来ちゃいそうですね。今年のGW辺りに一気に作ってみたいところです。

Re: No title

音声で操るのは思ってた以上に楽しいです!これで見た目も可愛ければほんと言うことなしに癒してくれそうです。

あとは足をキャタピラみたいにして安定走行できるようにしたら、色々雑用をこなしてくれそうです。掃除、お茶入れ、・・・うーん何がいいですかねぇw
リンク
フリーエリア
プロフィール

tsukuba.lego

Author:tsukuba.lego
●主な登場人物
koba : 会長. RCX, WeDo, NXT1.0, NXT2.0を持つ.
matk : 副会長. 2010年夏にNXT2.0を購入, 20年来のレゴ熱復活.
●会員募集中です!小学生から歓迎. 近日月1ぐらいで集まる予定.
mail:tsukuba.lego@gmail.com
YouTube (tsukubalego)
Twitter(tsukubalego)

カテゴリ
最新記事
最新コメント
月別アーカイブ
検索フォーム
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
最新トラックバック
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。