RaspberryPI3にアキバで買ってきたUSB DACと片側12.5Wのステレオアンプをつないで音を出してみた。
コマンドラインは、
$ aplay -D plughw:2,0 test.wav
でないとダメだった。DACとアンプをつないだ後、デバイスの指定がplughw:2,0でなければ、ならなかった。
音量調整は、
$ alsamixer -c 2
でする。家でやる限りは、10%程度でよかった。12.5Wのパワーはすごかった。大きなパワーにすると、少し音が割れ気味なのは、スピーカのせいか。
足郎2のスタンバイモード
足郎2、再開!!
Twitter APIの活かし方についてのメモ
(足郎2も中断していて、これも年末から年明けにかけてのR-1用に仕上げたいのだが、そちらも滞ってしまっている)
基本的に、やりたいことは、劇場などで、お客さんにお題をハッシュタグ付きでツイートしてもらって、ロボットがそれをストリーミングで受け取って、いろいろ答えて行くというシステムだ。
理想的には、NaoQiの自前のライブラリの一つに組み込んで行くことだが、それはC++で書かなければならない。curlのライブラリで、ツイートするところまでは難なくできたのだが、ストリーミングでつまづいた。
そこで、javaでやろうと思った。開発はjavaの方が圧倒的に楽なので。javaでは、ツイートもストリーミング受信も問題なかった。twitterライブラリも使わなくてうまくいった。それというのも、twitterのjavaライブラリ、tweet4jがロボット(nao)の32ビットOSでつまづいているようだったから、それを使わない方向にした。ところが、パソコン上で開発したライブラリ抜きのjavaのツイッタープログラムが、ただのtweetでは、問題なくロボットのos、linuxのgentooでは、ツイートはできるのだが、ストリーミングがうまくいかない。いくら考えても、理由がわからない。
まだ、試みることはあるかもしれないが、当面の課題があるので、ここは一旦止めることにしたのだ。
一旦移したサイトを戻しました
このサイトを、外部の私のレンタルサーバーに移したのですが、そこの速さがあまりに遅いので、こちらに戻しました。
TwitterStreamingによるツイートイベントの取得
Twitter Botの前の記事の仕様では、bot側から@aigeininへのツイートを取得しなければならなかった。そのために、お題が投稿されたタイミングがわからないから、15秒おきにツイートを取りに行っていた。これが面倒だった。
そこで、TwitterStreamingAPIを使って、投稿のイベントを取得することにした。
twitter4jのサンプルにちょっとだけ手を加えたものは次のようになる
public static void main(String[] args) throws TwitterException { TwitterStream twitterStream = new TwitterStreamFactory().getInstance(); twitterStream.setOAuthConsumer(consumerKey, consumerSecret); twitterStream.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret)); AiGeininBot2 aig = new AiGeininBot2(); StatusListener listener = new StatusListener() { // フィルターをかけたツイートが取れると、このリスナーが呼び出される @Override public void onStatus(Status status) { // ツイート内容がStatusで与えられる System.out.println("@" + status.getUser().getScreenName() + " - " + status.getText()); // statusを与えて、次のメソッドで処理する aig.execNazokake(status); } @Override public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) { System.out.println("Got a status deletion notice id:" + statusDeletionNotice.getStatusId()); } @Override public void onTrackLimitationNotice(int numberOfLimitedStatuses) { System.out.println("Got track limitation notice:" + numberOfLimitedStatuses); } @Override public void onScrubGeo(long userId, long upToStatusId) { System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId); } @Override public void onStallWarning(StallWarning warning) { System.out.println("Got stall warning:" + warning); } @Override public void onException(Exception ex) { } }; twitterStream.addListener(listener); // ここで @aigeinin 向けたツイート、リプライだけを取得するためのフィルターを作る final String[] TRACK = { "@aigeinin" }; FilterQuery filter = new FilterQuery(); filter.track(TRACK); // ここでフィルターを組み込む twitterStream.filter(filter); }
javaでツイッターbotの作成
サリーのネタは、お客さんからもらったお題に、即座に謎かけで答えるというものだが、このデータを作っているうちに、どうせなら、twitterのbotも作成しようという気になって、javaで作成した。
その要点を記録しておこうと思う。javaで全てのことができるのが素晴らしい!!
アカウントは、 @aigeinin で、このアカウントを作成すると、それに伴って開発者サイトにログインできる。そのサイトで、作成するbotのアプリケーションを登録すると、4つのキー文字列がもらえる。私の場合、javaで作成するので、twitter4jのライブラリを使ってアプリを作成する。
twitter4jは、以下のサイトからダウンロードできる。
http://twitter4j.org/ja/index.html
初歩的な使い方、作り方はネットにたくさん情報があるので、ここでは記載しない。
まず、ツイッターオブジェクトを作成する。
Twitter twitter = new TwitterFactory().getInstance();
4つのキーをセットする(それぞれの文字変数に入れておく)
twitter.setOAuthConsumer(consumerKey, consumerSecret);
twitter.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
ツイートを最新の20個取得する。
List<Status> statuses = twitter.getMentionsTimeline();
statusとは、以下よく出てくるが、ツイート(返信も含む)のことだ。statusesを一個一個表示(一部の内容だけ)させると以下のようになる。
for (Status status : statuses) { System.out..println( "《Statusの表示》\n" + "getName > " + status.getUser().getName() + " : \n" + "getScreenName > " + status.getUser().getScreenName() + " : \n" + "getInReplyToScreenName > " + status.getInReplyToScreenName() + " : \n" + "getInReplyToStatusId > " + status.getInReplyToStatusId() + " : \n" // 返信じゃない -1 + "getInReplyToUserId > " + status.getInReplyToUserId() + " : \n" + "getCreatedAt > " + status.getCreatedAt().toString() + " : \n" + "getText > " + status.getText() + " : \n" + "getId > " + status.getId() ); }
status IDが大事だ。全てのツイートは、このIDを持っている。もしこのツイートが、他のツイートの返信ならば、getInReplyToStatusId()にその元ツイートのIDが入っている。新規ツイートならば、この値は-1だ。このことはとても重要。
getScreenName()が、@で始まる、いわゆるユーザーIDだ。ツイートの内容は、その全体が、getText()で取得できる。
ツイートのStatus IDがわかると、twitterオブジェクトから、
twitter.showStatus(statusID)
で、そのもとツイートがstatusで取得できる。showなのだが、statusそのものが取り出せるところが、最初戸惑った。
新規のツイートは、tweetにツイートすべきテキストを入れて、
twitter.updateStatus(tweet);
でできる。
リプライ(リプ、返信)は、まず、返信の内容を、tweetにテキストで入れて、StatusUpdateオブジェクトを作成する。
StatusUpdate supd = new StatusUpdate(tweet);
そのオブジェクトに返信の対象となったもとツイートのIDをセットする。
supd.inReplyToStatusId(status.getId());
そして、オブジェクトを引数にツイートさせる
twitter.updateStatus(supd);
となる。
リプライのところは、詳しいマニュアルがないので、勘でやったらうまくいったという感じだ。
これだけで、ツイッターbotのほとんどのことができるはずだ。
足郎2が進まない
本当は、ハード的には組み上がった足郎2を本格的に動かしていなければならない状況なのだが、予想外の事態が発生したために、そちらは全く進まなくなった。
というのは、私的ロボットのサリーと私のコンビ(サリーと教授)が漫才グランプリのM-1の一回戦に合格してしまったのだ。それ嬉しいことだが、合格するとは正直思っていなかった。そもそも、ロボットのコンビで漫才と言えるのかどうか、それすら怪しかった。が、演芸ロボットを普及していかなければならないという使命感で、出たのだ。
普通、二人でやる漫才で、着飾ったロボットを抱えて順番待ちするのは恥ずかしかったが、まあ、一度だけだと思った。合格を知ったときは、腰を抜かすほど驚いた。プロでも落ちるM-1なのだ。
10月に2回戦があるので、そのために、ネタのデータやプログラムを改定していかなければならない。それに忙殺されている。だから、足郎には手が回らないというわけだ。
COSMの改訂
足郎2を動かす前に、足郎制御言語cosmとそのインタープリターを改訂する。実際に動かし始めるとそれに集中したいからだ。
(1)サーボグループの角度定義に配列を設定できる。
ロボットのある一連のサーボを現在の状態から別の状態に変化させるのは、%defangles で、その角度群を定義するのだが、同じグループを連続で滑らかに変化させる場合に、いちいちそれを定義し直していくのは面倒なので、角度名の後に連続で定義し、配列に入れる。
(2)全ての定義の中で、空白を無視するようにする
今までは、定義の中では、空白は使えなかったが不便なので。
例えば、結局以下のように定義できる。
%defangles right_invpen[3] { #右に傾ける動きをする [0] [1] [2] RightUpperRight: -$righ, $righ2, $righ3; RightUpperLeft: +$right, $righ2_1, $righ3; LeftUpperRight: -$left, $left2, $left3; LeftUpperLeft: $left, $left2, $left3_1; LeftKneeFront: -$bent, $bent2_1, $bent3; LeftKneeBack: $bent, $bent2_2, $bent3; RightLowerRight: $right, $righ2, $righ3; RightLowerLeft: -$right, $righ2, $righ3_1; LeftLowerRight: $left, $left2_2, $left3; LeftLowerLeft: -$left, $left2, $left3_2; }
垂直直立の確認
朝から、足郎2の垂直直立の調整をやっている。
これまで、三角定規なのでやっていたが、足郎2は背が高いので、オモリをぶら下げた紐で確認するのがいい。紐に電池をぶら下げて垂直を見ている。前後左右に確認しなければならない。その度に、サーボからのリードの長さを変える。
単に一つのリードの長さで、一つの垂直が決まるのではない。そこに足郎2の複雑さがある。膝の関節は単純だが、他は色々関連している。上板で左右の足がつながっているので、一つの垂直がある意味全体のリード線の影響を受けていると言っても良い。
ただ、そういう、相互依存性が、これだけの体をか弱いサーボで動かすことができる理由でもある。一つのサーボに重さや動きが集中していると、支えきれなくなる。