「Raspberry Piで学ぶ ROSロボット入門」を安価に楽しむ方法

Pocket
LINEで送る

先月30日に発売された「Raspberry Piで学ぶ ROSロボット入門」ですが、やっぱりロボットが高くて手が出しにくいという反応をいただいておりますので、なくても楽しめるように、いくつかロボットなしのプランを提示します。ついでに本書の内容もどんなものか匂わせます。

もちろん、実機があるのがベストです。

Travis CIとの格闘を楽しむ

本書はロボットを動かすための本ですが、テストがたくさん盛り込んであり、Travis CIも裏の操作対象のような位置付けになっています。また、ロボットがなくても、テストが通るかどうかで、コードが正しいかどうかは、完全ではありませんがだいたい分かります。ということで、勉強だけならTravis CIでテストを通すことを目標にしてコードを書くことができます。

また、講義では、ロボットを1人1台ではなく、教室に数台だけにしておき、テストを通した人から実機を試すという運用も考えられます。これはテストを扱っているからこそ可能になることです。また、私も職業柄、当然講義を持っておりますので、ちゃんと講義や実習が成立するように考えて書いておりますです。

実機を作る

これはかえってコストがかかるかもしれませんが、少しずつ部品を揃えて試していくこともできます。ハードウェアの使用はこちらに公開されていますので、挑戦してみるのも良いかもしれません。

シミュレータと接続

最後、ラズパイマウスのシミュレータで試すという方法もあります。ただ、本書のコードとシミュレータのつなぎこみには少し手間がかかります。少しだけ付録で説明しましたが、ちょっと本書を読み進めないと難しいかと。

ということで、シミュレータの作者にどんどんissueを投げていけば、そのうち答えが出てくるものと予想されます(ひどい)。

また、シミュレータは、入出力口を全てROSのインタフェースで持っています。が、実機はデバイスファイルがインタフェースなので、そういう点ではシミュレータは不完全です。ここをデバイスファイル(もちろん普通のファイルでも可)でブリッジできればシミュレータとして完全なのですが・・・。この点は気になっているところなので、こちらでも働きかけを続けます。

おわりに

3つ挙げたうちの後ろの2つは大変ですが、最初の項目のように、本書は一つのロボットを多人数でシェアしても大丈夫な構成になっています。また、ロボットは持っている人のところで動かして、あとはテスト環境でソフトウェアを書くということもできるようになっています。

ということで、ぜひ一読いただければと。

Pocket
LINEで送る

「Raspberry Piで学ぶ ROSロボット入門」という本を書きました

Pocket
LINEで送る

ロボットにラズパイを載っけてROSで動かすという流行りもの全部乗せの節操のない本を書きました。3月30日に出ます。以前の日経Linuxの連載をまとめて、原型を留めないほどROS化したものです。本日校了ということで、9月から12月までは執筆、1月からは書き直しや校正と、充実した地獄が終わりました。

 

 

まさか自分がROSの本を書くとは思っていませんでした。私のROSに関するコントリビューションは、たまにROS Wikiを翻訳するくらいです。あんまりROSのコミュニティーに仁義が切れてないのは、別のコミュニティーをやってる身としては褒められたものではないという認識なのですが、日経Linuxの内容を強化する上でROSが避けられず、自分も真正面から扱うことにした次第です。

本の中ではこんなことをしています。

内容は大学の講義や実習を想定しています。4月からの講義にはギリギリですが、ぜひ本を手にとっていただければと。

Pocket
LINEで送る

日記 —自己位置推定の実機実装

Pocket
LINEで送る

必要に迫られ、およそ10年数ぶりに実機用のパーティクルフィルタのコードを書いています。売るものではないので公開してますが、ロボットの場合、ハードウェアが違うとコードがそのまま使えないのであまり反響はありません・・・が、ロボットは日経Linuxの連載で使っているRaspberry Pi Mouseで市販品なので、ちゃんとお化粧して教科書書いて小銭を稼ぐ使ってもらうのが目標です。

リポジトリを見ても、「ああC++だなあ(逃げよう)」ということくらいしか分からんのでここに何やってるか書いておくと、次の写真のような環境で、ロボットに地図をもたせて、地図のどこにロボットがいるのか自分で把握させるコードを書いています。センサ情報はロボット前面の四つの赤外線センサから得られます。また、ロボットがどれだけ動いたかはモータへの指令から求めることができますが、壁に接触しながら動くと訳の分からん挙動を示すので大変です。

スクリーンショット 2015-08-09 20.14.35

ロボットは次のような地図を持っています。ロードした地図をテキストで描画する確認用プログラムの出力を示します。シェル芸でしょうか。いいえ、C++です。

uedambp:map ueda$ ./main ./map | head -n 15
+---+---+---+---+
|       |       |   
+   +   +   +   +
|       |       |   
+   +   +   +   +
|       |       |   
+---+   +---+---+
|   |           |   
+---+---+---+---+

この出力をFacebookに貼りつけたら「Rogueみたい」というコメントを書き込むおじさまがたがたくさん釣れたんですが、さあなんのことやら。

今日と明日はロボットのいる大学に行けないのでロボットへの行動指令とセンサの値のログを採取して開発中ですが、とりあえずそれっぽいものができましのでgifアニメをはりつけます。

animation

作っているコードはパーティクルフィルタというものです。地図の上にロボットの分身(ブツブツ)をばら撒いて、行動とセンサの履歴が説明できない分身を殺しまくって、説明できるやつを増やしてロボットの実際の位置に分身の位置を寄せていきます。

上の実行例は実際のロボットの位置を書き込んでないのですが、最終的にはロボットの最後の位置近くにブツブツが固まりました。

まだなんのことかサッパリ分からんと思いますが、続きは某所での講義で。分かってる人には「壁にぶつかったあとのパーティクルの挙動のモデル化が難しかったけど適当な方法でもうまくいった」とお伝えします。

寝る。

Pocket
LINEで送る

例のロボットを今度はHaskellで動かした

Pocket
LINEで送る

今日は某氏が取り仕切るMaker Faire Tokyo 2015に遊びに行きました。大いに啓蒙されたので、帰宅後、俺も何かやろうということで、「Raspberry Pi Mouseはどの言語でも動かせるアピール」の一環としてHaskellでRaspberry Pi Mouseを動かしてみました。

Raspberry Pi Mouseというのは日経Linuxの連載「Raspberry Piで始めるかんたんロボット製作」で作っているロボットです。よく「パソコンのカーソル動かす方のマウス」と間違われるのですが、ここで言っている「マウス」というのはロボット競技のマイクロマウスの「マウス」です。

このロボットをHaskellで動かすわけですが、そのためにはセンサの読み込みとモータの動作を非同期で行う必要があります。私みたいな阿呆でも分かる解説を探していたところ、

Haskellでマルチスレッド処理 – Qiita

が大変分かりやすかったので参考にさせていただきました。

ちゃんとやるにはこの本↓も参考になるかもしれません。(amazonに飛びます。)

コードの前に動いたロボットの様子をお見せすると、

というように、前進して壁を検知したら止まるという動作ができました。たいしたことはやってませんが、滑らかに動きつつセンサの値を読んでいるのがミソです。

このムービーで使ったコードはミニマムなサンプルにして、GitHubにアップしてあります。これで

  • シェルスクリプト(bash)
  • C/C++
  • Python
  • Haskell

と、自分がよく使う4大言語で動きました。デバイスファイルに字を出し入れするだけで動くので当たり前ですが・・・。たぶん、もうやらなくても十分アピールになるかなあ・・・。

Raspberry PiでHaskellを使うときはsudo apt-get install ghcします。

コード

コードは以下のような感じです。もう一度書いておくと、Haskellでマルチスレッド処理 – Qiita のコード(サンプルコードその2)の影響を色濃く受けています。

大雑把な説明ですが、モータを動かすforward関数と、センサ値を読み出すreadSensorという関数がロボットに直接関与しています(デバイスファイルを読み書きしている)。こいつらは両方最後に自分を呼び出していて、readSensorだけ、センサ値が閾値を超えると、その旨をputMVarという関数でrefに反映して処理を終わっています。

forwardとreadSensorを動かしているのはmain関数のにあるforkIOで、これが非同期に上記2つの関数を実行します。watchSensor関数はmainで呼ばれ、refの値を監視してTrueだったらforwardの処理を止め、そうでなかったら再度自分自身を呼び出しています。refの型はMVar Boolで、これは非同期で動くスレッド間で安全に読み書きできるそうです。間違ってたらアレなので、その筋の方のブログや書籍を参考にどうぞ。

import Control.Concurrent
import Control.Monad
import System.Posix.Unistd

-- 単純に前進する関数
forward :: IO ()
forward = do
  -- 車輪を400Hzで0.1秒回す
  writeFile "/dev/rtmotor0" "400 400 100"
  -- 無限ループ(・・・という言い方は不適切か?)
  forward

-- 距離センサを読み出す
readSensor :: MVar Bool -> IO ()
readSensor ref = do
  -- センサを休める
  threadDelay 200000
  cs <- readFile "/dev/rtlightsensor0"
  -- 4つのセンサの値を合計
  let v = sum [ read w :: Int | w <- words cs ]
  -- センサが反応していなかったら再度計測
  if v > 1000 then putMVar ref True else readSensor ref

-- センサに何か反応したらモータのスレッドを止める
watchSensor :: MVar Bool -> ThreadId -> IO ()
watchSensor ref w = do
  tf <- takeMVar ref
  if tf then killThread w else watchSensor ref w

main = do
  ref <- newMVar False
  w <- forkIO $ forward
  _ <- forkIO $ readSensor ref

  watchSensor ref w

この部分だけ見ると、Haskellなのに手続き的なのですが、ここにもっと高度な処理を関数で書いていけるのならば、Haskellで書くメリットも出てくるかもしれません。個人的にはシミュレーションで書いたHaskellの関数が使るという確実なメリットが。

ということでHaskellでロボットが動いたので、後はどなたか関数型言語でロボットを動かす講義をやって欲しい・・・。私はやりません。

参考: Raspberry Pi Mouseって何?

こちらのページで。

Pocket
LINEで送る