てきめんラジコンを声で指示することができるようになりました。
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > てきめんラジコンを声で指示することができるようになりました。
声でラジコンを命令しよう
声でラジコンを命令することができるようになると、面白いんじゃないかと思ったので作った。
つくるために必要なもの
SpeechRecognizer
Androidでは、SpeechRecognizerというAPIが存在しており、コレを利用すると喋った内容が文字列として出てくる。
インタプリタ
デザインパターンにもInterpreterパターンとして出てくるが、インタプリタを作ったことのある身、文字列に対して再帰的下向き構文解析を行えば、色々な命令を行うことができそうだ。とはいえ、今現在は仕様を絞っておくのが懸命だろう。
仕様
あとから決めたものもあるけど、とりあえずは以下の命令ができればOK。
- 前
- 後
- 左
- 右
- 止
さらに深めていけば、これを秒数で指定できるようにする。それを実現できるように以下のとおりの構文にする。
前2
これで、前に2秒間走ったあとで停止するようになる。
処理のロジック
Androidが内容をもしも正しく「前2」と認識したら、以下の構文はどう処理されるのか。
前2
字句解析
まず、最初に一文字ずつバラしてトークンに変換する。この作業を「字句解析」といい、「LexicalAnalyzer」というずばりそのもののクラスが存在する。それを「TokenStorage」というクラスが、トークンの種類と、数字であれば数値の内容を保存するようにしておく。
構文解析
トークンに変換した内容を組み合わせて構文を解析することを「構文解析」といい、「CodeAnalyzer」というクラスが存在する。CodeAnalyzerでは、構文解析の処理を総合的にまとめている。構文解析を実際に行うのは「Expression」という抽象クラスを継承したクラスであり、現在のところは「SecondExpressionImpl」、「CalculateExpressionImpl」という2つのクラスがある。Expressionの抽象クラスは、Decoratorパターンに対応している。その理由として、構文解析に使われる再帰的下向き構文解析との相性が良いためである。
ラジコンの操作データとして保存する
構文解析によってどのような処理が行われるのかがわかったら、ラジコンへの命令に変換しなければならない。幸い、レコーディング機能をつけているので、そこで使用したMoveRecorderを再利用しよう。「前」という構文を処理する「CalculateExpressionImpl」には0ミリ秒後に「511,511」の命令を保存しておく。「2」という構文を処理する「SecondExpressionImpl」には2000ミリ秒後に「256,256」の命令を保存しておく。
このような処理を経て、ラジコンは前へ2秒進み、止まることができるようになる。
さらなる命令
例えば、前に1秒動かしたとして、更に右に1秒動かしたいとする。そうなると、命令は以下の様な構文になる。
前1右1
この場合、前に1秒進んだあと、停止の命令を送ってしまうと、同じ秒数に命令を行う「右」とごっちゃになってしまう。そうなるとラジコンは意味不明な動きをすることになる。それは困るので、「前1」という構文を解析したあとで、その命令が終わっていいるかどうか(EOL: End Of Line)を一つ次のトークンから調べる。この場合はEOLではなく、RIGHTというトークンなので、内部の秒数だけ進ませて実際のコマンドは行わせない。「右1」というコマンドの後でEOLが出てくるので、そこで「1秒後に256,256」という停止命令を送ることになる。
当然、更に命令を送る場合でも同じである。ただ、SpeechRecognizerの精度がどんどん悪くなっていくので、短く済ませたほうが正確なコマンドになりやすい。ここはループ文を追加するべきだろう。
というわけでできました!
Androidがアタマ、Arduinoが手足となるのがこのラジコンのコンセプト。Arduinoが高度な動きをしているように見えて、実はAndroidが高度な動きを指示しているからこそできる。ぼくの理想にどんどんちかづいてるぞー!