ScratchからBezelieを動かしちゃう
このエントリーは、QiitaのRobot/ロボット Advent Calendar 2016の12月20日分のエントリーです。
さて、一昨日の豊田さんのエントリー、昨日の高橋くんのエントリーを受けて、何を書こうか非常に迷ったのだけど、今年はやはりこのネタで締めくくるべきだろうと思い、「Scratchからロボットを動かす」ことにしました。
今年のアクティビティだけでも見ても、西田さんと太田さんの作った同人誌でもScratchでロボットを動かすことについて書き、月刊I/OのV-Sidoの連載でもScratchからくまちゃんのロボットを操り、様々なイベントにScratchとロボットで遊びに行きました。今年の締めくくりはやっぱり「Scratchとロボット」であり、せっかくのバトンだし、豊田さんのエントリーを引き継いで、ScratchからBezelieを動かすことにします。
Scratchと通信する
Scratch(1.4)には、遠隔センサー接続(Remote Sensor Connection)という仕組みがあります。これは、ソケット通信でセンサー情報などをやる取りする仕組みで、(隠されてはいる機能ですが)Scratchのメッシュという通信の基礎ともなっているものです。
Scratchの遠隔センサー接続のプロトコルはRemote Sensor Protocolというそのままの名前なのですが、仕様を見ると非常にシンプルでわかりやすい仕組みとなっています。
Remote Sensors Protocol - Scratch Wiki
ただ、以前僕が探したときは、Python向けの気に入った実装がなかったため、とりあえず僕が個人でPython向けのライブラリを実装してしまいました。
Python3.x向け実装
github.com
Python2.7向け実装(上記の別ブランチ)
github.com
今回もこちらを使います。先日の豊田さんのエントリーがPython2.7向けて書かれていたようなので、2.7版を利用します。
今回は、このブランチから必要なファイルをコピーして持って来てしまいましたが、正しくは、上記の2.7向けブランチを
$ git clone -b 2.7 https://github.com/hine/pyscratch.git
して、その上でそのディレクトリで、
pip install ./
すれば、pyscratchライブラリはインストールされます。使い方はREADME.mdを御覧ください。
Bezelieを動かす
今回のコード一式はこちらです。
github.com
今回Bezelieは、一昨日の豊田さんのエントリーをそのまま利用できるよう、RaspberryPiとPCA9685を利用して接続します。ちょうど手元に、RaspberryPi3と中国製の基板があったので、そのまま利用しました。
Bezelieを動かすコードはbezelie.pyとファイル名は豊田さんのエントリーそのままですが、今回Classにさせていただきました。コードはほとんどそのままコピペです。
import bezelie bez = bezelie.Control() bez.setTrim(head=0, back=0, stage=0) bez.moveCenter()
などとして動かすことができます。
Scratchとつなぐ
今回は、レポジトリの中に、pyscratchレポジトリからscratch.pyをコピーして持ってきてしまいました。
こちらの使い方は若干クセが有り、
import scratch def broadcast_handler(message): pass def sensor_update_handler(**sensor_data): pass rsc = RemoteSensorConnection(broadcast_handler, sensor_update_handler) rsc.connect()
のように、メッセージなどを受け取った時のハンドラなどを用意して、それを引数として渡してあげます。
実際にこちらのプログラムを動かす前に、接続されるScratch側で作業が必要となります。
Scratchを立ち上げ、左上のブロック種類から「調べる」を選択し、下のブロック一覧の一番下の「○○センサーの値」のブロックを右クリック、「遠隔センサー接続を有効にする」を選びます。
こうすることで、Scratchの遠隔センサー接続が利用できるようになります。
今回、プログラムを動かすのはRaspberryPi上です。RaspberryPiにもScratchが搭載されていますので、HDMIのモニタなどにつなぎ、デスクトップでScratchを起動させて、上記の作業を行ってください。
一方で、僕のようにRaspberryPiをディスプレイに繋がずに利用している人も多いかと思います。その場合は、同一ネットワーク内の他のマシンで動かしている(例えば手元のMacやWindowsで動かしている)Scratchに接続させることもできます。その場合は、接続したい先のIPアドレスを調べて、
rsc.connect(host='192.168.11.1')
などと、IPアドレスを指定してください。
いよいよScratchからBezelieを動かす
上記の2つのライブラリを用いて今回作ったのがscratch2bezelie.pyです。
実行は
python scratch2bezelie.py
もしくは
python scratch2bezelie.py '192.168.11.1'
などと、接続先のIPアドレスを指定してください。
問題がなければ
Connected to Scratch on 192.168.11.1
などのように表示されますので、その後は、Scratch側の作業となります。
今回は2つの方法でBezelieを動かせるようにしました。
一つは、「broadcast」を用いた方法です。制御ブロックの「○○を送る」ブロックを用いてメッセージを送る方法です。ここで、メッセージに「bezelie:move:head:10」を指定すると、頭の角度位置10の位置に頭が移動します。同様に「bezelie:move:back:10」で身体が、「bezelie:move:stage:10」でステージが動きます。
この方法は、数値が値になるとは限らないもの、例えば「何かを話せ」みたいなコマンドを用意したい場合には「bezelie:talk:何か」などというコマンドを作ることなどに応用できます。
もう一つの方法は、グローバル変数の変更イベント「sensor_update」を受け取る方法です。この方法は、変数ブロックで新し変数としてすべてのスプライト用(グローバル変数)で「bezelie:head」「bezelie:back」「bezelie:stage」を作成し、変数変更ブロックなどで値を変化させる方法です。
こちらは、数値の変化しかない情報の受け渡しに便利な方法です。例えば、LEDの光の強弱、音声のボリュームなどにも応用できそうです。
ここまでくれば、あとはScratchで遊ぶだけです。