BeagleBone Blackへのubuntu 14.04インストール

ずっと以前に購入したBeagleBone Black(Rev A5B)にubuntu 14.04をインストールした。
手順はここを参考にした。
「Get prebuilt image:」の下に書かれた
wget https://rcn-ee.net/rootfs/2015-02-19/microsd/bone-ubuntu-14.04.2-console-armhf-2015-02-19-2gb.img.xz
を参考に、bone-ubuntu…img.xzというファイル(ファイル名は変わる可能性あり)をMac(Mavericks)にダウンロードし、Terminalで
unxz bone-ubuntu-14.04.2-console-armhf-2015-02-19-2gb.img.xz
を実行した後で、適当なMicroSDカードに書き込んだ。
BeagleBone BlackにMicroSDカードを挿入して起動したらubuntu 14.04が起動した。(ユーザー名はubuntu、パスワードはtemppwdでログイン)
ログインしたら、パーティションを拡張するスクリプトを実行するのだが、なぜかネームサーバーの設定がうまくない。
/etc/resolvconf/resolv.conf.d/original ファイルの中身を修正し、一番最後の行を以下のようにして再起動した。
nameserver 8.8.8.8
再起動後、以下を実行する。
cd /opt/scripts/tools
git pull
sudo ./grow_partition.sh
sudo reboot

更なる再起動の後でパーティションが拡張された。

第71回Smalltalk勉強会でのLT内容(後編)

12/25に年末恒例のSmalltalk勉強会があり今年も参加してきた。昨年はビデオ参加で他の方の発表がちゃんと聞けなかったのだけど、今年はいろんな方の発表が聞けて多いに楽しんだ。
せっかくのチャンスなので自分も発表をしたけど、他の方の真面目な取り組みに対してかなり緊張感のない内容で申し訳なかった。
パワポなども一切持って行かずにその場でのぶっつけデモだったので、せめて発表内容についての簡単な説明をしてお詫びしたいと思う。
なお、記事が長くなりすぎたので、前編・後編に分けて公開する。
LTでは前半にRoassal3dのデモを行い、後半はLeapMotionと接続するデモを行った。
別にLeapMotionでなくとも良かったのだが、他にネタが思いつかなかったのとデバイスが小さく持ち運びやすかったから選んだに過ぎない。
https://www.leapmotion.com/?lang=jpはKinectのように人体の位置を測定する入力デバイスであるが、Kinectと異なる点は身体全体ではなく、肘から指までの測定に特化していることである。
LeapMotionはhttps://developer.leapmotion.com/されており、自分のアプリケーションと連携させることができる。

Roassal3dの準備とFluoのインストール

今回の内容を再現するには、第71回Smalltalk勉強会でのLT内容(前編)に従って必要なパッケージをインストールする必要がある。

LeapMotionとの接続

Pharoとの接続については、前回の記事でインストールしたFluo DevicesにNativeBoost経由でデータを得るパッケージを組み込んであるが、NariveBoost用の共有ライブラリは別途インストールする必要がある。
まだ開発途中でMac OS X版しか作成していないため、https://oohito.com/downloads/NBLeapMotion.dylibから直接共有ライブラリ(NBLeapMotion.dylib)をダウンロードする。
ダウンロードしたらMac版のPharo VMのフォルダを開き、Contents/MacOS/Pluginsフォルダの中にダウンロードしたNBLeapMotion.dylibと、LeapMotion SDKに含まれているlibLeap.dylibをコピーしておく。

動作確認

LeapMotionをPCに接続し、メニューバー上のインジケータが緑色に変わったことを確認したら、Fluo上での動作確認を行う。
左側のメニューからloadをクリックしてNBLeapMotionTest1を選ぶ。

NBLeapMotionTest1
NBLeapMotionTest1

左側のメニューからopen allをクリックしてノードをスタートさせてLeapMotionの上に手をかざすと、LeapMotionFingerBehaviorのプロパティボックスに読み取った指や掌の位置が表示される。
LeapMotionFingerBehavior
LeapMotionFingerBehavior

手の動きにあわせて立方体を動かす

後半のデモのハイライトは、LeapMotionで読み取った手の動きに従って、Roassal3dの3Dビュー上の立方体を動かすというものであった。
このデモはRoassal3dのサンプルを改造しながら行っていった。
まず、Roassal3dDemo1をloadしておく。次に、LeapMotionに関係するプロキシであるNBLeapMotionProxyを追加し、さらに階層的なデータを取得するトピックであるNBLeapMotionTopicを追加する。トピックからどんなデータが得られるかを調べるためにInspectBehaviorも追加して下図のように接続しておく。

LeapMotionFingerBehavior
LeapMotionFingerBehavior

NBLeapMotionProxyのチェックボックスをオンにするとデータの取り込みが始まる。InspectBehaviorのInspectボタンを押すと最初に到着したデータをInspectorウィンドウで調べることができる。dataをダブルクリックすると上図のようにDictionary形式のデータがあり、#id, #left, #rightの3つのキーがあることがわかる。
このトピックはLeapMotionから得られたデータを階層的なDictionaryデータとして送信する機能を持つ。
デモでは右手の掌の座標を用いたので、#right から #palm へとデータを掘り下げる必要がある。
これをFluoのノードで実現するには、DataUnpackBehaviorを用いる。このビヘイビアはDictionaryを分解して、キーの名前のついたアークにデータを送信するというものである。
なお、アークに名前を付けるにはアーク上で右クリックしてadd labelを選べば良い。
DataUnpackBehaviorを用いてグラフを下図のように変更する。
DataUnpackBehavior
DataUnpackBehavior

InspectBehaviorでClearを押して再度データを取り込み直すと、x,y,zをキーとするDictionaryデータが得られることがわかる。
後はこの3次元座標をRoassalに送れば良いのだが、LeapMotionから得られたデータはcm単位で大きいためデータを小さくする。この役割はScaleBehaviroが担う。これは得られた数値データに一定の倍率を掛けて送信するという単純なものである。
不要となったTimerBehaviorやJoystickBehaviorを取り除き、ScaleBehaviorを通してFluoR3AbsolutePositionに接続したグラフは以下のようになる。
LeapMotion to Roassal3d
LeapMotion to Roassal3d

以上のデモが動いたところで発表を終えた。ということで、この記事もおしまい。
(Smalltalk勉強会ではご清聴ありがとうございました)

第71回Smalltalk勉強会でのLT内容(前編)

12/25に年末恒例のSmalltalk勉強会があり今年も参加してきた。昨年はビデオ参加で他の方の発表がちゃんと聞けなかったのだけど、今年はいろんな方の発表が聞けて多いに楽しんだ。
せっかくのチャンスなので自分も発表をしたけど、他の方の真面目な取り組みに対してかなり緊張感のない内容で申し訳なかった。
パワポなども一切持って行かずにその場でのぶっつけデモだったので、せめて発表内容についての簡単な説明をしてお詫びしたいと思う。

「オトナのためのVPL」

こんなタイトルの発表だったのだが、開始から2時間後の発表で、ビールですっかり酔っぱらってしまい1割も言えていなかったが趣旨としてはこんな感じだった。

Scratchびすけっとを始めとしてさまざまなビジュアルプログラミング言語(VPL)が流行している。テキスト系の言語に対してVPLを卑下する見方もあるけど、プロトタイピングなど使う場面によっては生産性を高める場合もあるだろう。
過去10年くらいグラフベースのVPLに取り組んできたが、2年前のSmalltalk勉強会の帰宅途中の会話にヒントを得て、Pharo Smalltalkの素晴らしい開発環境にシームレスにつながるVPLが作れないか試行錯誤した。
実用的な段階にはまだまだ遠いが、現状でどのような感じなのかを見てもらいたい。

Roassal3dの準備とFluoのインストール

デモではインストールから始めて格好よく見せようと思ったのだが、実は事前にRoassal3dのインストールを行っていた。

MetacelloConfigurationBrowser open.

でRoassal3dを選んでInstall Stable Versionを押し、インストールを済ませておく。
次に公開されているFluoの最新バージョンをインストールする。今回はデモでRoassalとLeapMotionを使ったのでそのパッケージを追加する。

Gofer new
  url: 'http://smalltalkhub.com/mc/oohito/Fluo/main';
  package: 'Grafeo';
  package: 'Fluo Core';
  package: 'Fluo Devices';
  package: 'Fluo UI';
  package: 'Fluo LeapMotion';
  package: 'Fluo Roassal3d';
  load.

上記をWorkspaceにコピペしてDo itすればよい。
なお、利用しているPharoのバージョンは3.0である。環境に合わせてダウンロードしておく。
小田さんの発表で「Jun」のPharo移植が述べられていたので、将来的には3D表示系としてそちらを採用する可能性が高いと思う。

Roassal3dのデモ

Fluo new openInWorld.

Workspaceで上記をDo itすると、以下のような画面が現れる。

Fluo起動画面
Fluo起動画面

左側のボタンでLoadを選んでRoassal3dDemo1を選ぶと以下のような画面になる。
Roassal3dDemo1
Roassal3dDemo1

これはRoassal3dの3Dビューに立方体を表示させ、それを黄色に赤のジョイスティックを模したMorphで上下左右に動かすデモである。ジョイスティックは赤いノブをマウスでドラッグすることで、上下左右に動かすことができるので試してみる。

ノードの説明

このデモには5つのノードがある。ノードの右下のプロパティボックスに小さな文字で書かれているのがノードの名前である。列挙すると以下の通り。

  • Roassal3dProxy
  • FluoR3AbsolutePosition
  • MonitorBehavior
  • JoystickBehavior
  • TimerBehavior

ノードは3種類あり、円の中央の図形で区別する。中央の図形が正方形のものはプロキシといってFluoの外の世界をつなぐノードである(このデモだとRoassal3dProxy)。円のものはビヘイビアと言ってFluo内でさまざまなデータ処理を行うノードである。三角形のものはトピックといってプロキシとビヘイビアをつなぐノードである(このデモだとFluo3dAbsolutePosition)。ノード間は一方向のアークで結ばれ、その向きでデータが流れる。
Roassal3dProxyはその名の通り、Roassal3dを用いるためのノードである。このノードは接続されたトピックに従ってRoassal3dのエレメントを生成して表示する。
FluoR3AbsolutePositionは、プロパティで指定した形状のRoassal3dエレメントを操作するトピックである。入力として3次元座標を受け取ると、その位置にエレメントを配置する。
MonitorBehaviorは受け取ったデータをプロパティボックスに表示するだけのデバッグ用ノードである。他には何もしない。
JoystickBehaviorは、プロパティボックスに表示したジョイスティックの位置の2次元座標(-1から+1の範囲)を送信するノードである。ただし、tickメッセージが来た時だけデータを送信する。
TimerBehaviorは、指定した間隔でtickメッセージを送信するノードである。
これらのノード間でデータは、(デバッグ用ノードであるMonitorBehaviorを除くと)TimerBehavior -> JoystickBehavior -> FluoR3AbsolutePosition -> Roassal3dProxyのように流れる。つまり、TimerBehaviorで生成されたtickメッセージがJoystickBehaviorに送られると、ジョイスティックの位置データがFluoR3AbsolutePositionに送られ、それが形状データとともにRoassal3dProxyに送られて3Dビューが更新される。

動かしてみる

TimerBehaviorのプロパティボックスにあるチェックボックスをクリックすると、tickメッセージの送信が100ms間隔で始まる。データを受け取ったノードは中央が白くなるのがわかる。ジョイスティックを動かすと座標がMonitorBehaviorに表示されることがわかる。
Roassal3dProxyのプロパティボックスにあるチェックボックスをクリックすると、下図のようにRoassal3dの3Dビューが現れ、立方体が中央に表示される。

Roassal3dの3Dビュー
Roassal3dの3Dビュー

ウィンドウをずらしてジョイスティックを操作すると、操作に応じて立方体が上下左右に動くのがわかる。

修正

このデモでは、上下の向きがジョイスティックと立方体の動きとで逆になってしまう。
発表時に南谷さんからその修正ができないかと問われたのだが、酔っぱらっていたためにその場で対応できなかった。
これに対応するにはデータを修正するノードを追加すれば良い。新しいノードを作るのは手間がかかるので、Smalltalk式を設定できるExpressionBehaviorを追加する。
Fluo画面の上部にあるnew behaviorというノードのプレースホルダをドラッグして、適当な場所でドロップすると、ポップアップメニューが現れる。
その中のdata convertサブメニューからExpressionBehaviorを選ぶとそのノードが追加される。

ExpressionBehaviorの追加
ExpressionBehaviorの追加

expression=の右の空欄をクリックすると入力欄が現れるので以下をコピペする。

data at: #y put: (data at: #y) negated. data

受け取ったDicionaryデータ(data)のyキーの数値の正負を反転させるというものである。ExpressionBehaviorはこのようにインスタントにSmalltalk式を埋め込むことができる。
後は下図のようにアークを繋いでデータの流れを変える。

流れを変える
流れを変える

アークを繋ぎ変えるには、アークをクリックして丸いハンドルを出し、それをドラッグ&ドロップすることで行う。
以上でジョイスティックの上下の向きが立方体の動きと合うようになった。
記事が長くなったので、いったん打ち切ってLeapMotion関係は別記事にまとまる。

クリスマスのコード

クリスマスの夜はコーディングに限りますね。
ちょっと思いついたプログラムを公開しました。
ネタはちょっと古くなった感の強いhttp://bijint.com/です。
参考にさせて頂いたのはhttps://d.hatena.ne.jp/Yamashiro0217/20090930/1254305886。
現在時刻から画像を入手して背景画像に設定します。コードはこんな感じ。

updateBackground
    | url |
    DateAndTime now
        in: [ :now |
            url := 'http://bijint.com/jp/img/clk/{h}{m}.jpg'
                format:
                    {(#h -> (now hour printPaddedWith: $0 to: 2)).
                    (#m -> (now minutes printPaddedWith: $0 to: 2))} asDictionary ].
    (PluginBasedJPEGReadWriter on: url asUrl retrieveContents readStream) nextImage setAsBackground.
    self currentWorld backgroundMorph layout: #scaledAspect

これを30秒おきに呼び出しています。もっと効率の良いコードはかけますが、どうせ使い捨てなのでこの程度で。
以下をWorkspaceでDo itすればインストールできます。

Gofer new
  url: 'http://smalltalkhub.com/mc/oohito/Fluo/main';
  package: 'BijinTokei';
  load.

起動は以下で。

BijinTokei start.

終了は以下で。

BijinTokei stop.

表示された方が美人かどうかはさておき、お楽しみください。
メリークリスマス!

Pharoで3D表示

これはSmalltalk Advent Calendar 2014の12/23の記事です。
以前からPharoで3D表示させたいと考えていた。NativeBoost経由でOpenGLを使うNBOpenGLを試してみたのだが、どうやらメンテされていないらしくうまく動作しない。
そんなところ、第67回Smalltalk勉強会でRoassalが取り上げられた。あいにく仕事で参加できなかったのだが、プレゼン資料でRoassal3dについても紹介されていたので、遊んでみることにした。

Roassal3dの導入

MetacelloConfigurationBrowser open.

上記をWorkspaceでDo itしてConfiguration Browserを起動する。一覧からRoassal3dを選んでInstall stable versionをクリックすると自動的にRoassal3dがインストールされる。

サンプルの実行

Roassal3dの機能をひととおり試してみるには以下をWorkspaceでDo itする。

R3RoassalExample new open.

いろんなアイコンが並んでいるのでマウスで左クリックするとそれぞれのデモウィンドウが現れる。右クリックをするとBrowserが現れ、対応するメソッドが表示される。
デモウィンドウの操作はキーおよびマウスで行う。キー操作では、Wは前進、Sは後退、Aは左移動、Dは右移動、Cが下移動、スペースが上移動できる。マウスではドラッグにより向きを変えることができる。
デモの中にはアニメーションを表示したり、マウスの動きに反応するものがある。

3Dビューの作成

R3Viewのインスタンスに対して、R3Elementのインスタンスを追加することで3Dビューを作成する。
R3Elementには形や位置、向きなどの様々な属性がある。立方体や球体など一般的な物体は、R3Elementを直接生成せず、R3Shapeの該当するサブクラスを経由して生成する。
以下は最も簡単なサンプルで3Dビューの中心に立方体を置くものである。

| view |
view := R3View new.
view add: R3CubeShape new element.
view open.

上記で生成した3Dビューをinspectしてelementsを調べると2個の要素がある一方は生成した立方体で、もう一方は照明である。
立方体の位置を変えるには、R3Vectorオブジェクトを引数としてposition:メッセージを送れば良い。

view elements last position: (R3Vector x: -1 y: -1 z: 0); signalUpdate

先ほどのコードに続けて上記をDo itすれば、立方体は中央から左下に移動する。
position:を送っただけでは3Dビューに変化は現れないので、signalUpdateを送って3Dビューを更新する。

アニメーション

3Dビュー上の物体を動かす手段としてアニメーションがある。R3ViewのインスタンスにR3Animationのインスタンスをアニメーションとして登録すると、3Dビューの更新にあわせてアニメーションが動作する。R3AnimationはR3Elementに作用して位置や向きを変えることができる。
以下のコードをDo itすると、立方体が中央から左下に移動する。

| view element animation |
view := R3View new.
element := R3CubeShape new.
view add: element element.
animation := R3LinearMove new on: element by: (R3Vector3 x: -1 y: -1 z: 0).
view addAnimation: animation.
view open.

複数のアニメーションを連結させて、連続したアニメーションを作ることもできる。
以下のコードでは、立方体が4隅を連続して移動する。

| view element a1 a2 a3 a4 |
view := R3View new.
element := R3CubeShape new element.
view add: element.
a1 := R3LinearMove new on: element by: (R3Vector3 x: -1 y: -1 z: 0).
a2 := R3LinearMove new on: element by: (R3Vector3 x: 1 y: -1 z: 0).
a3 := R3LinearMove new on: element by: (R3Vector3 x: 1 y: 1 z: 0).
a4 := R3LinearMove new on: element by: (R3Vector3 x: -1 y: 1 z: 0).
a1 followedBy: a2.
a2 followedBy: a3.
a3 followedBy: a4.
a4 followedBy: a1.
view addAnimation: a1.
view open.

インタラクション

今までの例では3Dビューは固定されたカメラからの画像しか得ることができなかったが、冒頭のサンプルのようにキーボードやマウスを用いてカメラの位置を変えることができる。
そのためには以下のコードを追加すればよい。

view addInteraction: R3MKControl.

以上概観したように、Roassal3dはPharo上で簡単に3D表示することのできる優れたパッケージである。
この記事では一つの物体のみ操作したが、少ない労力で多数の物体の操作を行うこともできる。
Roassal3dに関する情報はhttp://objectprofile.com/Roassal.htmlから得ることができる。

Pharoでフィジカルコンピューティング(2)

これはSmalltalk Advent Calendar 2014の12/12の記事です。
前回の記事では、拙作のパッケージを用いてPharoでScratch Sensor BoardとGainerを扱う方法について述べましたが、今回はArduinoを扱う方法について紹介します。

Physical Etoys

Smalltalkでさまざまなデバイスを動かすことについては、既に先行しているプロジェクトがあります。
Physical Etoysは、(Pharoのベースとなった)Squeakのビジュアルプログラミング環境であるeToys上で、Arduinoを始めとする多様なデバイスを扱うことができるようにするプロジェクトです。
ウェブサイトでも紹介されているように、Physical Etoysでは、以下のようなデバイスをサポートしています。聞いたことのないデバイスもありますが、SpheroやKinect、LeapMotionなど比較的新しいハードウェアも扱えることがわかります。

  • Femisapien
  • Isobot
  • Kinect
  • Lego Dacta Control Lab
  • Puerto paralelo
  • Roboquad
  • Robosapien
  • Sphero
  • Wiimote
  • Leap Motion

SqueakとPharoは親戚同士で、eToys関連のクラス以外ならかなり利用することができます。そこで、今回はPhysical Etoysを使ってArduinoを扱う方法について解説します。

Arduino

Arduinoの準備

ArduinoとはFirmataプロトコルで通信するため、Arduino IDEでArduinoにFirmataのスケッチをUploadしておく。とりあえずAllInputsFirmataで良い。

Arduinoパッケージの導入

Arduinoのパッケージはhttp://ss3.gemstone.com/ss/Arduino.htmlから入手できるが、ここにあるのは古いものなのでうまく動かない。
面倒だが以下のようにする必要がある。
まずTerminalなどでgithubのリポジトリをcloneする。

git clone https://github.com/GIRA/PE

Pharoを起動後、Monticelloを開いて+Repositoryボタンを押し、filetree://を選んでcloneしたフォルダ内のPE/stを選ぶ。
リポジトリが開いたら、左側のペインでArduino-Coreを選び、右側のペインでArduino-Core.packageを選んでLoadボタンを押す。
次にBrowserでArduinoクラスを開き、initializeメソッドの中身をコメントアウトする。
また、ArduinoTypeクラスを開き、以下の内容のinitializeメソッドを登録する。

initialize
    digitalPins := 2 to: 13.
    analogPins := 0 to: 5

最後にWorkspaceで以下をDo itする。

ArduinoType initialize.

これで準備は完了。

Arduinoオブジェクトの生成

Arduinoオブジェクトを生成するには以下のようにする。

arduino := Arduino on: Firmata new.

接続と解除

#connectOnPort:と#disconnectを用いる。具体例は以下の通り。ポート部分はOS等にあわせて適切なものを指定する。

arduino connectOnPort: '/dev/cu.usbmodem1421'.
arduino disconnect.

ディジタル・アナログピンの制御

Arduinoのディジタル・アナログピンを操作するには、AttachableDeviceのサブクラスのオブジェクトに対してArduino上のピンをattachする。
例えば、pin13に接続されたLEDを扱うには、LightEmittingDiodeクラスのオブジェクトを生成してArduinoにattachする。

led := LightEmittingDiode new.
led attach: (arduino digitalPin: 13).

接続されたLEDをオン・オフするには以下のようにする。

led value: 1. "オン"
led value: 0. "オフ"

アナログピンの状態を調べるのは以下のようにする。

analog := Potentiometer new.
analog attach: (arduino analogPin: 1).
analog value. "値を読み取る"

なお、我が家の環境ではStuduinoはうまく使えなかった。

Pharoでフィジカルコンピューティング(1)

これはSmalltalk Advent Calendar 2014の12/9の記事です。
教科書的なイメージだとSmalltalkでフィジカルコンピューティングするとは思えないけど、それっぽいことをする人向けの情報になればと思います。
ScratchのSensor Board(https://wiki.scratch.mit.edu/wiki/PicoBoardやなのぼーど)、Gainer、ArduinoなどをPharoで制御するパッケージがあるので、その辺の情報をまとめておきます。
Sensor BoardとGainerについては拙作のパッケージを、Arduino(Firmata)については他の方のパッケージを(別の記事で)紹介します。
なお、デバイスをPC等に接続するために必要なドライバやインストール方法などの情報は、適宜参照して適切なものを導入しておいてください。おそらく他のツール(なのぼーどならScratch、Gainer miniならProcessing等)で使えることを確認した後で以下を試された方が良いでしょう。

Sensor BoardとGainerのためのパッケージ導入

Sensor Boardは「http://tiisai.dip.jp/?page_id=935」、Gainerは「Gainer mini」しか実績はありませんが、拙作のパッケージで扱うことができます。
Pharo 3.0でWorkspaceを開き、以下を選択してDo itします。

Gofer new
  url: 'http://smalltalkhub.com/mc/oohito/Fluo/main';
  package: 'Fluo Devices';
  load.

Fluo Devicesのパッケージには他のデバイス用のクラスも入っていますが、それらについて後日紹介する予定です。

Sensor Boardの使い方

インスタンス生成

ScratchSensorBoard new

インスタンス生成するにはScratchSensorBoardクラスにnewメッセージを送る。

SensorBoardへの接続(connect)と解除(disconnect)

ScratchSensorBoardオブジェクトに対し、ポート名を引数として#connectOnPort:メッセージを送ると接続できる。また、#disconnectメッセージを送ると解除できる。

| sensor |
sensor := ScratchSensorBoard new.
sensor connectOnPort: '/dev/cu.usbmodem'.
sensor disconnect.

上記のポート名はサンプルです。実際のポート名はOSにより異なります。

SensorBoardデータの取得(1)

以下のメッセージを送ることで、ScratchSensorBoardのデータを取得する。

  • #button — ボタンが押されればTrue、離されていればFalseを返す
  • #slider — スライダーセンサの値を0から100の範囲で返す
  • #sound — サウンドセンサの値を0から100の範囲で返す
  • #light — ライトセンサの値を0から100の範囲で返す
  • #registanceA,#registanceB,#registanceC,#registanceD — A,B,C,Dの抵抗値を0から100の範囲で返す

SensorBoardではセンサー入力の取得のみ対応しています。なのぼーどで拡張されたサーボの制御や超音波センサには対応していません。

SensorBoardデータの取得(2)

ブロックを設定することでScratchSensorBoardの情報を取得する。
1つのパラメータを持つブロックを引数として#receiveBlock:メッセージを送ると、SensorBoardからデータを受信する度に受信データを引数としてブロックが評価される。

| sensor |
sensor := ScratchSensorBoard new
sensor connectOnPort: '/dev/cu.usbmodem'.
sensor reeiveBlock: [:data| Transcript show: data; cr].

Sensor Boardの互換デバイスについて

阿部さんが日本で買えるScratchセンサーボードというページで互換デバイスを紹介しています。
なのぼーど以外のデバイスでも標準的な機能は使えると思います。

Gainerの使い方

インスタンス生成

Gainer new

インスタンス生成するにはGainerクラスにnewメッセージを送る。

Gainerへの接続(connect)と解除(disconnect)

Gainerオブジェクトに対し、ポート名を引数として#connectOnPort:メッセージを送ると接続できる。また、#disconnectメッセージを送ると解除できる。

| gainer |
gainer := Gainer new.
gainer connectOnPort: '/dev/cu.usbmodem1411'.
gainer disconnect.

上記のポート名はサンプルです。実際のポート名はOSにより異なります。

Gainerからのデータの取得(1)

以下のメッセージを送ることで、Gainerの入力ポートのデータを取得できる。

  • #button — ボタンが押されればTrue、離されていればFalseを返す
  • #digitalAt: — 指定したディジタルピンの値をTrue/Falseで返す
  • #analogAt: — 指定したアナログピンの値を0から255の範囲で返す

ディジタルピン、アナログピンの番号は0から3までの範囲で指定します。

Gainerからのデータの取得(2)

ブロックを設定することでGainerの情報を取得することもできる。
1つのパラメータを持つブロックを引数として#receiveBlock:メッセージを送ると、Gainerからデータを受信する度に受信データを引数としてブロックが評価される。

| gainer |
gainer := Gainer new
gainer connectOnPort: '/dev/cu.usbmodem1411'.
gainer reeiveBlock: [:data| Transcript show: data; cr].

Gainerへのデータの設定

以下のメッセージを送ることで、Gainerの出力ポートへデータを設定できる。

  • #led: — 引数に指定した真理値によってLEDを点灯(True)・消灯(False)する
  • #digitalAt:put: — 指定したディジタルピンを真理値で指定した状態にする
  • #analogAt:put: — 指定したアナログピンを0から255の値に設定する

ディジタルピン、アナログピンの番号は0から3までの範囲で指定します。

以上です。
Arduino(Firmata)については後日紹介します。

学園祭で用いたFluoグラフ

今年の学園祭ではTurtleBot1をタブレットで操作するというデモを行った。
TurtleBot1に付けたシャフトの先端にWebカメラを載せて、リアルタイムでタブレットに画像を送りつつ、画面上のボタンからTurtleBot1を操作するというもの。
Pythonとかで作れば何の変哲もないプログラムだけど、今回はFluoを用いて制御してみた。
(ちなみに画像はMJPG-Streamerを使った)
作成したグラフはこんな感じ。

TurtleBot1WebControl
TurtleBot1WebControl

左上にあるWebServerProxyが、8081番にきたリクエストを受け取って/moveというURLであれば、その引数cmdに与えられたleft, right, forwardという値を検出する。その後、それぞれの値に応じて、linear, angularというデータをROSの/cmd_vel_mux/input/teleopトピックにPublishする。
Webからの入力とROSへの出力は思ったよりシンプルになった。
やはり実演を伴うと、いろいろ工夫した中で現実的な解を見つけやすい。

MJPG-streamerの導入

通常の場合

本家サイトに行けばわかる話ですが、いちおう備忘録のため。
SVNでソースを入手してからmakeでビルドする。SVNのリポジトリは変更になったようなので古い情報とは異なっている場合がある。
Raspberry-piなどでビルドする場合には、 subversion imagemagick libjpeg-dev のパッケージをインストールしておく。

svn checkout svn://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer-code
cd cd mjpg-streamer-code/mjpg-streamer
make

動作を確認するには以下のようにする。なお、/dev/video0 は適切なビデオのデバイスファイルにする。

sudo ./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -y" -o "./output_http.so -w ./www -p 8080"

Firewallの設定をしている場合はポート8080を許可するのを忘れずに。
http://localhost:8080 にアクセスすると、MJPG-streamerのページが表示され、カメラの画像が現れるはず。

Raspberry-piのカメラモジュールを使う場合

https://neuralassembly.blogspot.jp/2013/11/raspberry-pipi-noirandroid.htmlを参考にする。
ポイントは、

  1. raspi-configでカメラモジュールを有効にしておく。
  2. gitを使って別のリポジトリからソースを得る。

ことぐらい。

SerialPortの謎

「なのぼーど」をつなげたPC上で、Fluoのプログラミングを行っているのだが、例によってSerialPortで悩まされている。
ずっとMac OS X上で開発していて特にトラブルがなかったので見過ごしていたが、Windowsで利用すると問題が生じることに気づいた。
現象としては一度オープンしたポートをクローズすると再オープンできなくなるということ。
コードで示すと、2番目のopenPort:でエラーになる。

s := SerialPort new openPort: 'COM3'.
s close.
s openPort: 'COM3'.

これについては既に議論がなされていた。
http://forum.world.st/Package-for-manage-USB-RS232-td4744124.html
SerialPortのソースを眺めてみると、primitiveClosePortByName:に問題があるようだ。

primClosePortByName: portName
	
	^ nil"(DNS)"
	"self primitiveFailed."

わざわざself primitiveFailedがコメントアウトされているのは、コードを書いた人がこの問題を認識していて放置したってことか。
SerialPortではあたかもcloseが成功したかのように見せかけているのだが、実際にはこのプリミティブを呼んだ後、primOpenPortByName:を呼ぶと失敗し、SerialPort>>#openPort:の中でエラーと判定される。
先ほどのメーリングリストのやり取りではSerialPort>>#openPort:内のエラー判定部分を削除すれば動くとあり、試してみたらちゃんと2度目もオープンできた。該当箇所はここ。

	"result isNil ifTrue:[ self error:'Cannot open ', portId printString. ]."

このようにコメントアウトしておけば冒頭のトラブルは回避できる。
これでいいのか甚だ疑問であるが。
プラグインに問題ありそうだから暇を見つけて原因究明してみよう。
とかいってプラグイン関係はいつも挫折してるけど。
(ここから追記)
https://github.com/pharo-project/pharo-vm/blob/master/platforms/win32/plugins/SerialPlugin/sqWin32SerialPort.cを眺めて見ると、プラグインの方でハンドルの管理を行っていた。ポートを名前でなく番号でも呼べるようになっていたのはそのせいか。
WindowsではCOM3に対応する番号は3なので、以下のコードを試してみたらオープンもクローズも問題なく動くではないか。

s := SerialPort new.
s openPort: 3.
s primClosePort: 3.
s openPort: 3.
s primClosePort: 3.

ということでWindows上では番号でポートを指定すれば大丈夫なようだ。