2011年4月30日土曜日

Ubuntu 11.04 natty narwhal

Ubuntu定期リリースの2011年4月バージョン11.04 natty narwhal (粋なイッカク)がでました。

さっそくインストールしてみました。

Google日本語入力がおかしくなった以外はちゃんとうごいていますね。
(とりあえずanthyにしています)

rosはaptでいれていたので当然動かなくなりました。

なのでソースからいれ直してみました。
↓を参照するとできると思います。
http://www.ros.org/wiki/diamondback/Installation/Ubuntu/Source

非力なマシンなのでめっちゃ時間かかりましたが、いちおうrvizまで動くようになりました。
左のツールバーが特徴ですね。
そのうちROSもサポートするとは思いますが、LTSじゃないので、アップグレードは慎重に。。。

2011年4月27日水曜日

雑談:人間のステレオ視について

今日は雑談です。

Kinectのおかげで最近は手軽に物体の3次元位置を取得できるようになりつつありますが、
ロボット界では2つのカメラを使ったスレテオ視というのがむか〜しから研究されています。

これは人間の両眼を模擬したシステムですよね。

でも私は常日頃、片目でも物の奥行きとか分かるわけで、人間はそんなにスレテオ視を利用していないんじゃないかなぁ。記憶とか、常識とか、そういうもので奥行きを判断しているんじゃないかなぁ、と思っていました。


で、先日、私事ですが、右目の角膜が一部剥がれてしまい、右目の視力が0.01くらいまで低下し、1週間ほど眼帯をしていました。
今はほとんど治りましたのでご心配なく。

で、片目で生活していたのですが、結構不自由する場面があったのです。
それは手に持った何かと何かの位置合わせをする時です。

手と手、手と体とかなら問題ないのですが、
手に持った何かと、何か、の位置合わせが片目だと全くできませんでした。
手と物体、でもなんとかなります。タイピングも問題ない。

でも手にもった何かをどこかに作用させる(包丁で何かを切る、目薬の蓋をもどす)動作になると極端に精度が落ちるのです。

一方で遠距離のものに関してはほとんど支障がありませんでした。
っていうか、手が届かないからあたりまえか。

でもなんか自分的にはこれは大発見でした。

人間は近距離のみステレオ視をしている!
考えてみれば遠いところは視差がでにくいので当たり前ですが。

だから、ロボットに必要なステレオ視は近距離だな〜ってなんか思いました。
いや、実感したというべきか。。。

2011年4月26日火曜日

roscppのPublisherの挙動を調べる

一度だけメッセージをPublishしたい、というとき以下のようなコードを書くと思います。
これが下のコメントアウトしてあるsleep部分がないとうまくpublishされません。



#include <ros/ros.h>
#include <std_msgs/Int32.h>

int main(int argc, char* argv[]) {
  ros::init(argc, argv, "pubtest");
  ros::NodeHandle node;
  ros::Publisher pub = node.advertise<std_msgs::Int32>("hoge", 1);
  // sleep(1);
  std_msgs::Int32 msg;
  msg.data = 1;
  pub.publish(msg);
  // sleep(1);
  return 0;
}


何が起きているのか調べてみます。
advertiseした時点でmasterとのコネクションが確立され、publishが終わった時点でmasterとの通信が終わっているつもりになっていましたが、違うようです。

ということは実際にデータを送信するスレッドがいる、ということになりますね。

どの時点でそのスレッドは作られているんでしょうか?
たしかrospyはそんな仕様だったきがしますが、roscppもそうだったんですね。


後のsleepがないと動かないのは、そのスレッドが動く前にプログラムが終わってしまうからでしょう。
最初のsleepがないと動かない、ということはやはりPublisherが作られたときにスレッドが作られているんでしょう。Publisherごとにスレッドが作られているんでしょうか?

ソースを追いかけてみるとpoll_managerというのがinit時に作られていて、そいつがスレッドを持っているので、

そこにpublishキューを処理するコールバックを登録するみたいですね。
このスレッドはros::init時に作られているもよう。


じゃあ、なぜ最初のsleepが必要なんでしょうか?


以下のように getNumSubscribers()してみると少しわかります。
rostopic echo /hoge
している状態で、


sleepすると1で、sleepしないと0。



#include <ros/ros.h>
#include <std_msgs/Int32.h>

int main(int argc, char* argv[]) {
  ros::init(argc, argv, "pubtest");
  ros::NodeHandle node;
  ros::Publisher pub = node.advertise<std_msgs::Int32>("hoge", 0);
  sleep(1);
  if (pub) {
    ROS_INFO("num:%d", pub.getNumSubscribers());
  }
  std_msgs::Int32 msg;
  msg.data = 1;
  pub.publish(msg);
  sleep(1);
  return 0;
}

今度は以下のようにすると2になります。
同一プロセス内だとadvertiseした瞬間につながるみたいです。



int main(int argc, char* argv[]) {
  ros::init(argc, argv, "pubtest");
  ros::NodeHandle node;
  ros::Subscriber sub = node.subscribe<std_msgs::Int32>("hoge", 1, hoge);
  ros::Publisher pub = node.advertise<std_msgs::Int32>("hoge", 1);
  sleep(1);
  if (pub) {
    ROS_INFO("num:%d", pub.getNumSubscribers());
  }
  std_msgs::Int32 msg;
  msg.data = 1;
  pub.publish(msg);
  sleep(1);
  return 0;
}

ということで、(プロセス外の)subscriberとのリンクも別スレッドで行われているから、でした。

つまり、最初のsleepはsubscriberとのリンク待ち、2つ目はpublish待ちのsleepということでした。

ちなみに今回の場合は以下のようにlatchedにするとsleepは1回で済みますね。

int main(int argc, char* argv[]) {
  ros::init(argc, argv, "pubtest");
  ros::NodeHandle node;
  ros::Publisher pub = node.advertise<std_msgs::Int32>("hoge", 1, true);
  std_msgs::Int32 msg;
  msg.data = 1;
  pub.publish(msg);

  sleep(1); 
  if (pub) {
    ROS_INFO("hoge:%d", pub.getNumSubscribers());
  }

  return 0;
}

以上すごい適当に調べた結果メモでした〜。間違っていたら教えてください。

2011年4月20日水曜日

RGBDSlamを試す

KinectでSLAM(地図作成)を行うRGBSlamを試してみます。
作ったのはgmappingなどで有名なフライブルグ大学です。
色付きの3次元マップができるはずです。

まずはROSはdiamondbackのバージョンを利用していることを確かめましょう。
$ echo $ROS_ROOT
/opt/ros/diamondback/ros
になっているでしょうか?

なっていなければdiamondbackをインストールしましょう。
http://www.ros.org/wiki/diamondback/Installation/Ubuntu


↓などを参考にしてもよいです。

http://ros-robot.blogspot.com/2011/03/diamondback.html

で、次に必要なパッケージをaptでインストールします。
$ sudo apt-get update
$ sudo apt-get install ros-diamondback-desktop-full ros-diamondback-perception-pcl-addons ros-diamondback-openni-kinect meshlab
~/rosにROS_PACKAGE_PATHが通っているなら、以下のようにします。
$ cd ros
$ svn co http://alufr-ros-pkg.googlecode.com/svn/trunk/freiburg_tools/hogman_minimal
$ svn co https://svn.openslam.org/data/svn/rgbdslam/trunk rgbdslam
$ roscd rgbdslam && rosmake --rosdep-install rgbdslamam
途中httpsの証明書の警告がでますが、気にせずpでインストールしました。
perception_pclとかを個別にインストールしていた人は削除してdiamondbackのものを使いましょう。

ちなみに以下も必要ですね。
$ sudo apt-get install libgsl0-dev


ところで最初にインストールしたmeshlabってよさそうですね。ライセンスはGPL。
http://meshlab.sourceforge.net
ポイントクラウドからメッシュ作ったりできるみたいです。
ポリゴンリダクションはできないのかな。

では実行しましょう。Kinectを差して、
$ roslaunch openni_camera openni_node.launch
$ roslaunch rgbdslam rgbdslam.launch
すると以下のような画面がでますので、スペースでスタートです。
ゆっくりkinectを動かしていくと・・・
じょじょにマップが構成されていきます。
熊ちゃんがちょっとダブっちゃってます。

またスペースを押すと終了です。
Graph->Send Modelするとrvizにできたモデルが表示されます。
私の環境(MacbookPro Core2Duo 2.8GHz)ではちょっと動作が遅すぎたためか、
机の足などがダブってしまいました。
もっとゆっくりKinectを動かせばちゃんとできるのかもしれません。

もしくは、もっと早いPC環境ではもっとちゃんとできるかな。

2011年4月15日金曜日

bashの補完機能を試す(rosbashの中身を見てみる)

roscdやrostopicを初めて使ったとき、その補完機能にびっくりした人は私だけじゃないはず。
今回はこの補完機能に迫ります。

$ roscd rosbash
して、そのなかのrosbashというファイルを見てみます。

ここにはいろいろ書いてありますが以下に注目しました。

function _roscomplete {
local arg opts
COMPREPLY=()
arg="${COMP_WORDS[COMP_CWORD]}"
opts="`_ros_list_packages` `_ros_list_stacks`"
IFS=$'\n'
COMPREPLY=($(compgen -W "${opts}" -- ${arg}))
unset IFS
}
complete -F "_roscomplete" "rosmake"
$ man bash
として、compgenを検索するとこの使い方が書いてありました。
上記の例ではrosmakeというコマンドの引数の補完として、_roscomplete関数を用いる。
そして、${opts}変数に入っている文字列をIFS変数を区切り文字として使って、
現在入力中の${arg}を補完する。という意味になるみたいです。-Wはwordの意味。
-Wを-Gにすると正規表現も使えるみたいです。

試しに以下のようなファイルを作ってみました。

_hoge()
{
local arg
COMPREPLY=()
arg=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -W 'hokan1 hokan2 kouho1 kouho2' -- $arg))
}
complete -F _hoge hoge

_hoga()
{
local arg
COMPREPLY=()
arg=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -o dirnames -- $arg))
}
complete -F _hoga hoga

_hogi()
{
local arg
COMPREPLY=()
arg=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -G "${arg}*.txt" -- $arg))
}
complete -F _hogi hogi
これをhoge.sh
として保存して、
$ source hoge.sh
すると
hogeに対してhokan1 hokan2 kouho1 kouho2が、
hogaに対してはディレクトリが、
hogiに対しては*.txtファイルが、
それぞれ出てきます。

これでプログラムの補完ができたら、ちょっとおしゃれですね。

2011年4月14日木曜日

rospython

rospythonというコマンドをご存知でしょうか?

rospyを使うためには
import roslib
roslib.load_manifest('hogehoge')
とするのがお決まりです。
こうするとmanifest.xmlに書いてあるdependパッケージにPYTHONPATHが通るようになり、
依存パッケージを呼び出すことができる。

例えばmanifest.xmlに
<depend package="joy"/>
と書いてあるパッケージhogehogeがあったとして、

通常Pythonから使うには
$ python
>>> import roslib
>>> roslib.load_manifest('hogehoge')
>>> import joy
としないといけない。

rospythonはこれを簡単に使うためのもので、
$ rospython hogehoge
>>> import joy
と、いきなりdependパッケージを使うことができる。
ちょっと便利?

今のところroshにはこの機能はないみたいです。

2011年4月10日日曜日

TurtleBotの持つ意味

Willow GarageからTurtleBotという新しいロボットが発表されました。

http://www.willowgarage.com/turtlebot

紹介動画はこちら


PR2と比べちゃうとちょっと、、、、
という感じがしますね。

しかしWillowのrobot紹介ページでは、テレプレゼンスロボットのTexaiより上にあります。
PR2, TurtleBot, Texaiの順。
ここからもWillowのやる気をちょっと感じます。
http://www.willowgarage.com/robots

TurtleBotはiRobotのCreateというルンバの掃除機抜きバージョン(日本では未発売)+Kinect+Netbookという構成で、自律移動ができます。
僕の以前作ったロボットにちょっと似てませんかね。




この亀ロボットが持つ意味は実は大きいと思います。
Createは確か2万円くらい、Kinectは1.5万くらい、Netbookは数万、これに特注フレームを合わせても10万くらいでしょうか。
ということは普通のPCと同じかそれより安いくらいです。

WillowがやりたいのはROSにより誰でもロボットのプログラムが簡単に作れる世界の実現だと思います。今のPCのように。
しかしそれには誰でもロボットを持っていないといけない。でもロボットは誰でも持てるわけじゃない。高いし、作るにはある程度のメカ、電気の技術が必要。
そこでまず彼らがやったのはPR2を配ること。でもPR2は高すぎて(4000万円!)一般人には手がでない。
ROSとそのコミュニティのおかげでソフトはかなり揃ってきたけど、開発者の裾野はそこまで広がりきってはいない。
ハードウェアの壁は大きい。

シミュレータ上でPR2のプログラムも作れるけど、結局シミュレータでしか動かないならゲームのエージェントでも作ったほうが楽しい。やっぱりロボットの面白さは目の前で物理エージェントが動くことじゃないでしょうか。

そこでこのTurtleBotです。
このロボットなら誰でも、PCより安い値段で手に入れることができる。
しかも3Dセンサと、自律移動のソフトも付いている。
ロボットの知識がなくても誰でもロボットプログラミングができる時代がついに来たのです。
なのでTurtleBotは今までのWillowのロボットの中でもかなり革命的だと思います。
ロボットとしては普通だけど、そのもたらす意味は革命だと思うわけです。

ROSは自律移動、画像処理系のソフトが充実しているというイメージを僕は持っています。
なのでTurtleBotはROSとの相性もいいんじゃないでしょうか?

あとはマニピュレーション系をどうするかです。
6軸以上はないと満足なマニピュレーションはできないと思います。
つまりモータが6個以上ということで、ルンバよりさらに高価になります。
このマニピュレーションが可能なロボットが安価に手に入るようになったとき、
ロボット界には真の革命が起きるでしょう。
そこを狙っている人たちもきっといるでしょう。

なんて勝手な想像をしてみました。