ラベル Original の投稿を表示しています。 すべての投稿を表示
ラベル Original の投稿を表示しています。 すべての投稿を表示

2017年11月6日月曜日

urdf-vizのバイナリリリースの自動化

URDFのビューワーの urdf-viz のバイナリリリースをはじめました。

Linux(たぶんなんでも動く)/MacOS/Windows用の3つがあります。さすがに64bit版だけです。

↓からダウンロード出来ます。

https://github.com/OTL/urdf-viz/releases

Windowsだとurdfファイルをurdf-viz.exeのアイコンにドラッグ・アンド・ドロップでURDF可視化できちゃう(rospackとかPATH通っていれば。もしくはmeshファイルのPathがurdfからの相対で書かれている場合は)ので本当に楽でいいです。(っていうかwindowsでrospack動くのか?)

前回は手動でリリースしたんですが、いい加減めんどくさいので自動化しました。

↓を参考に、というかこれを利用して環境を作りました。

https://github.com/japaric/trust

Linux/MacOS用にはおなじみのtravis-ciを使って、Windows用のCIには Appveryor を使いました。

タグをpushするとgithubのreleaseを自動で作ってくれて、そこにバイナリを配置してくれるようになっています。
githubのdeploy用のキーをさらに暗号化して 設定することでこういうことが出来るようです。

2017年8月21日月曜日

Rustで書かれたURDF Viewer: urdf-viz

今やロボットに最も適した言語として有名になりつつあるRustでURDFを可視化するツールを作りました。

http://github.com/OTL/urdf-viz

ぶっちゃけRustを勉強するために作り始めたのですが、やっと実用的な状態になったのでアナウンスしました。


Rustにはすでに

あたりを自分で作りました。


特徴的な機能として以下があります。
  • Rustなのでシングルバイナリで動く
  • 関節角度Limitを考慮して関節を動かせる
  • 逆運動学(ヤコビアン)で手先を動かせる
Ubuntu16.04 64bitを使っている人は↓からダウンロードできます。

Rust使っている人は

$ cargo install urdf-viz

でインストールできます。

使い勝手は正直かなり悪いですが、やりたいことはなんとかできるのではないでしょうか?
フィードバックお待ちしております。

今回これを作ってみて、URDFフォーマットに少し詳しくなりました。

2017年1月7日土曜日

Anki cozmoをROSで動かす

前回CozmoSDKのインストールをしました。
SDKが出たら当然ROS化したくなるのが心情です。

なので作ってみました。以下です。

https://github.com/OTL/cozmo_driver

マニアックな動画も用意しました。rqt_ez_publisherで動かして、rvizで表示しています。
https://www.youtube.com/watch?v=1RK-Mo6DGEw



出来たもの

いまのところ以下のようなことが出来てます。
  • カメラ画像のPublish (sensor_msgs/Image)
  • 台車の操作 (geometry_msgs/Twist)
  • 首とリフトの操作(面倒だったのでstd_msgs/Float64でやっちゃってます)
  • 発話 (std_msgs/String)
  • 背中のLED操作 (std_msgs/ColorRGBA)
  • 首とリフトの角度をPublish(sensor_msgs/JointState)
  • 見えたCubeの位置姿勢をPublish, /tf
  • バッテリ残量 (sensor_msgs/BatteryState)
  • IMU (sensor_msgs/Imu)
今後できそうなこととしては
  • trajectory_msgs/JointTrajectoryのサポート
  • キューブ関係
があります。Cozmo SDKは機能が豊富なのですべてをカバーするのは結構大変です。公式からなかなか出ないのも納得。機能的にSDK自体が豊富でよく出来ているのでROSでラップするありがたみもあまり感じないかもです。SDK自体がそもそもAndroidとの単なるブリッジだし、それをさらにラップするのもなぁ、って感じ。

Cozmoは発売してかなり経つのですが、いままでROS対応した人が(おそらく)いなかったのには理由があります。
Cozmo SDKがpython3.5必須なので、python2.7が必要なrospyとは同居出来ないのです。
私はその事実を知って驚愕しましたが、(危険な?)ハックでなんとか動かしました。なのでしばらくは日の目をみなそう(公式にReleaseできなかったり、動かしたくないと思う人もいるかも。)

Python3でrospy?

一応Python3でROS(のごく一部)を動かす方法を下に書いておきますが、真似しないようにしましょう。
やっても動くものは限られるので今回のようなシチュエーションじゃないと意味ないです。今回作ったcozmo_driverが使うのはrospyとメッセージ定義くらいだったのでなんとか動きました。(最近のROSはpython3でも動くように推奨されているので公式に近いコードは本質的には動くが、バイナリインストールとの兼ね合いで問題が発生している。)

sudo apt-get install python3-yaml
sudo pip3 install rospkg catkin_pkg

ハードウェア構成

Cozmo SDKを使ってないとわかりにくいのですが、ハードウェア的には結構ややこしいことになっています。

Cozmo(WiFi Station) <---WiFi---> Android Phone() <--- USB cable ---> PC (SDK and ROS)

となっています。なのでROSは完全に手元のPCで動いていて、それが携帯に送られ、Cozmoが動きます。ちょっと微妙ですが、Cozmo SDKとはそういうものなのです。

2015年2月16日月曜日

MYOでPepperを動かしてみる

MYOがやっと届きました。注文したのが1年くらい前だったので、すっかり忘れていました。
MYOを知らない人は↓の動画を見てください。



ところが、このMYO、このビデオのようにいろんなジェスチャが認識できるわけじゃないです。
APIでサポートしてくれるのは

  • 手を開く
  • 手を閉じる
  • 手首右
  • 手首左
  • 指をダブルタップ
の5つだけです。IMU(姿勢角センサ)の性能もそこまで良くなく、ちょっと残念。
といえど、せっかく買ったので、同時期に届いたPepperと組み合わせてみました。

↓です。そのうち、顔出ししないでPepperだけで済むようにしたいですが、
今回のように筋電を取るようなデバイスだと人が出演せざるを得ないですね。


使ったのはMYOのジェスチャのうち、

  • 手を開く
  • 手を閉じる
  • 手首右(なんでやねん)
でした。あとはIMUの角度を使って、Pepperの右腕の肩2軸を制御しています。

ソースコードは↓においてあります。あまり整備されていないので参考程度に。

メインプログラムは60行くらいです。

MYOのROSノードはclearpathのものがapt-getで入りますが、Windowsが別途必要なようだったでやめました。
↓のものはLinux単体で使えるのでそっちにしました。

ジェスチャーやIMUのデータがPublishされます。
ROSを使えばビデオでちょっと出したように、可視化も簡単にできます。
(rqt_plot, rviz)
MYOをお持ちの方は試してみては。

2014年7月13日日曜日

何でもPublishできるGUI:rqt_ez_publisher

ROSの基本はTopicのPub/Subにあると思います。
(rostopicがもっとも使うコマンドではないでしょうか?)

私は何かをpublishするときに、
すぐスライダで値を変えられるGUIを作りたくなるのですが、
メッセージ型に合わせていちいち作るのがあほらしいといつも思っていました。

ROS標準にはrqt_publisherというのがあるのですが、いかんせんテキスト形式で値をセットするだけで、私の要求には答えません。

そこで自分で作ってみました。


indigoとhydroにリリースしたので、

$ sudo apt-get install ros-indigo-rqt-ez-publisher

もしくは

$ sudo apt-get install ros-hydro-rqt-ez-publisher

でインストール出来ます。

実行は以下のようにするか

$ rosrun rqt_ez_publisher rqt_ez_publisher

$ rqt
として、Plugins -> Topics -> Easy Message Publisherとして作ってください。
(rqt_publisherと同じように、rqtのプラグインになっています)

使い方は基本的にはすでにSubscribeされているトピックを選択すると、GUIができます。
あとはスライダを動かせばPublishされます。

イメージビデオを作りました。(全画面での視聴推奨)


まだまだバグがあるとおもいますが、何かフィードバックいただけるとありがたいです。

wiki: http://wiki.ros.org/rqt_ez_publisher
ソースコード: https://github.com/OTL/rqt_ez_publisher

2013年12月1日日曜日

もう一つのUSBカメラROSドライバ cv_camera

ROS hydroにcv_cameraをリリースしました。

https://github.com/OTL/cv_camera

hydro使っている人ならば、

$ sudo apt-get install ros-hydro-cv-camera

で入ります。


USBカメラのドライバは、一番メジャーなのが、Bosch作成のusb_cam

http://wiki.ros.org/usb_cam

だと思うのですが、他にも

http://wiki.ros.org/gencam_cu
https://github.com/ericperko/uvc_cam

とか色々あります。

でも、camera_infoをサポートしていなかったり、
Nodeletとして使えなかったり、キャプチャ周期を指定できなかったり、
不満がありました。

そこで以上の不満を解決するものをゼロから作ることにしました。

と、ここまで書いて、それらを満たすものを発見してしまいました。

http://wiki.ros.org/uvc_camera

あるある。。。。

cv_cameraは、OpenCVのcv::VideoCaptureを使うことで、
OSに依存しません。(OpenCVに丸投げ)

なので、OSXでも普通に動くのも特徴ですから。むしろそここそが特徴ですから!

と、思ったらuvc_cameraもOSXで動くみたい!オワタ。。。

2013年8月23日金曜日

Oculus Riftで動かすロボット作ってみた

OculusRiftのROSドライバを作りました。

https://github.com/OTL/oculus

OculusRiftは3Dのヘッドマウントディスプレイです。
http://www.oculusvr.com/
基本ゲーム向けなんですが、ロボットのインタフェースとしても非常に面白そうですよね。

2つのカメラ画像をROSメッセージとしてPublishすれば、
それを使ってOculus用の画像を作ります。

また、頭の傾きをtfとして発行します。

また、これを使ったテレプレゼンスロボットを作ってみました。
Oculusはオキュラスと読むようですね。。。



rvizでの仮想世界をOculusで眺めることができるプラグインがすでにあります。
http://ros.org/wiki/oculus_rviz_plugins

こっちも楽しそう。まだ試してないけど。

2012年8月31日金曜日

wxconsole (Web rxconsole)作ってみた

前回Android版rxconsoleを作りましたが、今回はWeb版を作ってみました。

見た目は↓な感じです。
Webということは当然rosbridgeを必要としますが、
多分、AndroidでもiOSでも動くと思います。


メッセージ詳細の表示。

設定。rosbridgeのバージョンを選択できます。
デフォルトはversion2.0にしちゃいました。



左上のテキストボックスにrosbridgeのホスト名を入れてEnter押すとつながります。
設定はすべてcookieに保存されるので次回アクセスからホスト名を含めた設定は不要です。
今回はAndroid版で付けなかったフィルタ機能もいれたのでかなり実用的だと思います。

ここにアクセスすればすぐ使えます。

ソースは
です。

rosbridgeはこちらを参照してください。

2012年5月27日日曜日

ROS Unity Indicator

Ubuntu Unityユーザのみなさんこんにちは。

最初にUnityを触った時はありえない!
と思いましたが、今や慣れました。みなさんはどうですか?

前回ちらっと紹介しましたが、ROSの状態を示すアイコンをバーに追加してみました。

インストールは前回記事を参照してください。
roswsを使っている人は以下で入れられます。


$ rosws merge 'https://raw.github.com/OTL/orz-ros-pkg/master/orz-ros-pkg.rosinstall'

$ rosws update

実行は以下です。

$ rosrun unity_indicator ros_indicator


おなじみROSのアイコンがでます。
で、ノードやトピック、サービス、パラメータの参照ができます。


エラーが発生(Logにエラーレベルを出力)するとアイコンが赤くなります。


また、トピック詳細を参照すると、ぼやっと現れます。
ノードをKillしたりもできます。


ROSは基本的にコマンドラインが重視されますが、これくらいのちょい機能+オシャレならいいんじゃないかなー。
本当はrosrubyでつくろうとしたけど、Pythonでプロトタイプしてたらめんどくさくなって、そのままPythonです。

動画はこちら。
大画面推奨ですが全画面だとおかしくなるかも。


追記:
すでにほぼ同じものがありました。
さすがiHeartRoboticsやるなぁ。

http://www.ros.org/news/2010/08/rind-ros-status-indicator.html
http://ros.org/wiki/rind

2012年4月27日金曜日

ニコニコ超会議出ます!

野生の研究者としてニコニコ超学会にでます。
タイトルは「3分間ルンバハッキング」です。

持ち時間は5分なのに、このタイトル、というあからさまに狙った感じです。

ニコニコ超学会というは、
ニコニコ学会βとは、簡単に言うと「ユーザー参加型の研究の場」です。
従来プロの研究者だけがするものだった研究を、「野生の研究者がやってもいんじゃね?」的な
発想で考え出された研究団体・シンポジウムだとのこと。堅苦しくない感じで、みんなで楽しく
研究をして発表し合おうということですね。

ということらしいです。
まあ全然研究じゃないんですけどね。


29日の14:00 「研究してみたマッドネス ネットの部」
のトリででます。登場は14:50くらいかな?


放送はこちらで見れるようです。
http://live.nicovideo.jp/watch/lv89959587

時間はたったの5分。
概論に近いので私のBlogの熱心な読者には面白くないかもしれません。

僕の個人的な知り合いは楽しいでしょうけど。
なんか投票とかもあるっぽい?のでもしあったら投票してくださいね。

実物持っていけばいいとこまで行けると思うんですが、
そこまではできないかなー。

2012年4月15日日曜日

rosruby作ってみた

rubyによるROSのクライアント rosrubyを試しに作ってみました。

https://github.com/OTL/rosruby

簡単なドキュメントはこっちを参照ください。
基本的に書いてある通りにやれば動くと思います。
https://github.com/OTL/rosruby/wiki/rosruby

まだ完全な動作を保証するレベルではないのですが、
デザインも含めてフィードバックいただきたく公開することにしました。
本当にプロトタイプそのままです。

ちょっとrubyっぽいのはSubscriberのcallbackをsubscribeの後にブロックで書けるところですかね。
Callbackの型が決まっているとノードクラスにCallback専用関数を用意しなくちゃいけなくなりますが、この形式だと本来のデザイン通りのクラス設計ができるかと思います。

また、roscpp, rospyは1ノード1プロセスですが、rosrubyは複数のノードを1プロセスで使えるようにしてみました。rosjavaもそうなっているし、できるならできたほうがいいかと。

中身の設計は前述のようにプロトタイプそのまんまなんで、ユーザが使う各クラスが結構実装丸出しなので、インタフェース用のクラスと実装を分けたいと思っています。

また、中身でrospackを使っていたりとまだまだやりたいことがいっぱいです。
ですが、とりあえずこれでロボットを動かそうかと思っています。
(まだ自分でもサンプルとテストしか使っていないので。やっぱロボット動かしてなんぼですよね。)

#!/usr/bin/env ruby

require 'ros'
require 'std_msgs/String'

node = ROS::Node.new('/rosruby/sample_subscriber')
node.subscribe('/chatter', Std_msgs::String) do |msg|
  puts "message come! = \'#{msg.data}\'"
end

while node.ok?
  node.spin_once
  sleep(1)
end

2012年2月4日土曜日

Android + rosjava でRoombaを操作

当初の目標だったAndroidでのルンバ操作アプリが一応できました。

Androidで端末の傾きセンサの値を取得し、それを速度に変換し、rosjavaを使ってtopicとして出力します。



おまけで掃除機能のOn/Off、ドックへの合体指示も出せるようにボタンをつけました。
ただし、この機能はotl_roombaパッケージのroomba_twist_node.pyを想定しています。
システム図は↓のような感じです。
Roomba制御のためにPCを経由しています。本当はAndroidからBluetoothで直接Roombaを操作可能なので、実はこのアプリはかなり冗長です。

でもこのノードは/cmd_vel (geometry_msgs/Twist)を出力するので、制御対象がルンバだろうが、PR2だろうが、動かすことができるというメリットもあります。


シミュレータでの動作画面は↓のようになっています。
スライダで最大動作速度を変えたり、ボタンでクリーナーのOn/Off等ができます。
一番上のでかいロゴに意味はありません。


リポジトリに上げましたが、
ソースもさらしておきます。まずはルンバ操作用クラス


/**
 * @license New BSD License
 * 
 */
package com.ogutti.ros.android.roomba;

import org.ros.message.geometry_msgs.Twist;
import org.ros.message.std_msgs.Bool;

import org.ros.namespace.GraphName;
import org.ros.node.NodeMain;
import org.ros.node.topic.Publisher;
import org.ros.node.Node;

/**
 * class for Controlling a roomba by Twist msg
 * 
 */
public class RoombaControllerNode implements NodeMain {
 private Publisher<Twist> velPublisher;
 private Publisher<Bool> cleanPublisher;
 private Publisher<Bool> dockPublisher;

 @Override
 public void onShutdown(Node arg0) {
 }

 @Override
 public void onShutdownComplete(Node arg0) {
 }

 @Override
 public void onStart(Node node) {
  velPublisher = node.newPublisher("/cmd_vel", "geometry_msgs/Twist");
  cleanPublisher = node.newPublisher("/roomba/clean", "std_msgs/Bool");
  dockPublisher = node.newPublisher("/roomba/dock", "std_msgs/Bool");

 }

 @Override
 public GraphName getDefaultNodeName() {
  return new GraphName("roomba_controller");
 }

 /**
  * start/stop cleaning motor
  * @param isOn if true start cleaning, false stop.
  */
 public void publishClean(boolean isOn) {
  if (cleanPublisher != null) {
   Bool msg = new Bool();
   msg.data = isOn;
   cleanPublisher.publish(msg);
  }
 }

 /**
  * Publish roomba's velocity (Vx, Vtheta)
  * @param linearX twist.linear.x forward speed [m/s]
  * @param angularZ twist.angular.z rotational speed [rad/s]
  */
 public void publishVelocity(double linearX, double angularZ) {
  if (velPublisher != null) {
   Twist vel = new Twist();
   vel.linear.x = linearX;
   vel.angular.z = angularZ;
   velPublisher.publish(vel);
  }
 }

 /**
  * start docking
  */
 public void publishDock() {
  if (dockPublisher != null) {
   Bool msg = new Bool();
   msg.data = true;
   dockPublisher.publish(msg);
  }
 }
}
つぎはメインのActivityのクラス
/**
 * @license New BSD License
 */

package com.ogutti.ros.android.roomba;

import java.text.DecimalFormat;
import java.util.List;
import android.os.Bundle;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.ToggleButton;

import org.ros.address.InetAddressFactory;
import org.ros.android.MessageCallable;
import org.ros.android.RosActivity;
import org.ros.android.views.RosTextView;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeMainExecutor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import com.ogutti.ros.android.roomba.R;
import org.ros.message.geometry_msgs.Twist;

/**
 * MainActivity of this App (roomba controller)
 * 
 */
public class MainActivity extends RosActivity implements SensorEventListener {

 private RosTextView<Twist> rosTextView;
 private SensorManager sensorManager;
 private RoombaControllerNode controllerNode;
 
 private static final double LINEAR_VELOCITY_RATE  = 0.05;
 private static final double ANGULAR_VELOCITY_RATE = 0.1;

 /**
  * 1.0 means max speed, 0.0 means stop always.
  */
 private double speedRate;

 public MainActivity() {
  super("Roomba Controller", "Roomba Controller");
  speedRate = 0.5;
 }

 @SuppressWarnings("unchecked")
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  rosTextView = (RosTextView<Twist>) findViewById(R.id.text);
  rosTextView.setTopicName("/cmd_vel");
  rosTextView.setMessageType("geometry_msgs/Twist");
  rosTextView
    .setMessageToStringCallable(new MessageCallable<String, Twist>() {
     @Override
     public String call(Twist message) {
      DecimalFormat df = new DecimalFormat();
      df.setMaximumFractionDigits(2);

      return "vel_x:\n" + df.format(message.linear.x) + "\n"
        + "vel_theta:\n" + df.format(message.angular.z);
     }
    });
 }

 @Override
 protected void init(NodeMainExecutor nodeMainExecutor) {
  // create ROS nodes
  controllerNode = new RoombaControllerNode();
  NodeConfiguration nodeConfiguration = NodeConfiguration
    .newPublic(InetAddressFactory.newNonLoopback().getHostName());
  nodeConfiguration.setMasterUri(this.getMasterUri());
  nodeMainExecutor.execute(controllerNode, nodeConfiguration);
  nodeMainExecutor.execute(rosTextView, nodeConfiguration);

  // set callback for accelerometer
  List<Sensor> sensors = sensorManager
    .getSensorList(Sensor.TYPE_ACCELEROMETER);
  if (sensors.size() > 0) {
   Sensor accelerometer = sensors.get(0);
   sensorManager.registerListener(this, accelerometer,
     SensorManager.SENSOR_DELAY_FASTEST);
  } else {
   android.util.Log.v("MainActivity", "NOT found sensor!");
  }
  
  // set toggle button's callback
  ToggleButton tb = (ToggleButton) findViewById(R.id.toggleButton1);
  tb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {
    controllerNode.publishClean(isChecked);
   }
  });

  // set seekbar callback. 
  SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar1);
  final TextView tv1 = (TextView) findViewById(R.id.textView1);
  seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    tv1.setText("Speed:" + progress + "%");
    speedRate = progress * 0.01f;
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
   }

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {
   }
  });
  Button dockButton = (Button) findViewById(R.id.button1);
  dockButton.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(android.view.View v) {
    controllerNode.publishDock();
   }
  });

 }

 @Override
 protected void onResume() {
  super.onResume();

 }

 @Override
 protected void onStop() {
  super.onStop();
  sensorManager.unregisterListener(this);
 }

 @Override
 public void onAccuracyChanged(Sensor sensor, int accuracy) {
 }

 /**
  * callback of sensor change(accelerometer)
  */
 @Override
 public void onSensorChanged(SensorEvent event) {
  if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
   double linearX = event.values[1] * -LINEAR_VELOCITY_RATE * speedRate;
   double angularZ = event.values[0] * ANGULAR_VELOCITY_RATE * speedRate;
   if (Math.abs(linearX) < LINEAR_VELOCITY_RATE) {
    linearX = 0.0d;
   }
   if (Math.abs(angularZ) < ANGULAR_VELOCITY_RATE) {
    angularZ = 0.0d;
   }
   controllerNode.publishVelocity(linearX, angularZ);
  }
 }
}
ちょっと長いですが以上になります。
Androidアプリは作るのが結構簡単なのでチャレンジしてみてはどうでしょうか。

2011年12月9日金曜日

テレプレゼンスロボットの作り方

Makeに持っていったロボットの中身を軽く紹介しようと思います。

まず全体構成は↓のようになっています。
基本的にいままでつくってきたノードをrosbridgeでブラウザから動かしています。

roombaは前に自作したotl_roombaパッケージのもの、lv2_armはアーム用に作ったノード、usb_camはboshのもの、battery_checkerはこの前紹介したノードでPCのバッテリーチェックをします。jtalk_nodeは日本語をしゃべるノードです。
いずれも公開済みです。

ブラウザでアクセスすると以下のように表示されます。
ぐるぐるのところでルンバの速度を出力、スライダやボタンでロボットのカメラ操作、
バッテリ残量を右上のアイコンで表示(@tera_kojiさんに作ってもらいました)、
テキストボックスに文字を書くとロボットがしゃべってくれます。
画面の上には大きくカメラ動画が流れます。
javascript/HTML5で動的なページにしています。
HTMLやjavascriptにはまったく詳しくないので苦労しました。


rosbridgeはsocketやwebsocketでROSプロトコルをしゃべってくれるサーバーで、javascriptからROSを簡単に使えます。
rosbridgeはsubversionの最新版がおすすめです。安定版だとfirefoxだとうまく動きません。

画像を動画で表示する方法は、

HTMLに以下のように書いて、


  <img src="img/camera_dummy.jpg" name="camera" width="320" height="240"/>


javascriptに以下のような感じで書きます。


    connection.addHandler('/usb_cam/image_raw',
                          function(msg) {
                            document.camera.src=msg.uri;
                          });

これだけで/usb_cam/image_rawがガンガン送られてくれば動画になります。

まあ、そんな感じです。


例によって以下のリポジトリにおいておきました。整理もしていないので見せられる状態にないですが、ジョイスティックの部分とか、出せるように整理したいです。

2011年11月20日日曜日

PC (Linux)のバッテリ残量を調べる

PC(Linux)のバッテリ容量をプログラムから知りたいことがあったのでPythonで作ってみました。
例によって参考程度になればと貼っておきます。
他にもっといい方法あれば教えてください。

一応ノードも作りました。

#! /usr/bin/env python

import re

class AcpiChecker():
    """read /proc/acpi/battery/*** files for check the PC's battery"""
    def __init__(self, battery_name):
        self._info_path = "/proc/acpi/battery/" + battery_name + "/info"
        self._state_path = "/proc/acpi/battery/" + battery_name + "/state"
    def get_capacity(self):
        f = open(self._info_path)
        for line in f:
            match = re.search(r'^last full capacity:\s*(\d+)', line)
            if match:
                capacity = match.groups()[0]
        f.close()
        return capacity

    def get_state(self):
        f = open(self._state_path)
        for line in f:
            match = re.search(r'^remaining capacity:\s*(\d+)', line)
            if match:
                state = match.groups()[0]
        f.close()
        return state

    def get_rate(self):
        return float(self.get_state()) / float(self.get_capacity())

if __name__=='__main__':
    checker = AcpiChecker('BAT0')
    print checker.get_rate()

ノードはこんな感じでてきとーに作ってみました。


#! /usr/bin/env python

import roslib
roslib.load_manifest('otl_battery_checker')

import rospy
from std_msgs.msg import Float64
from battery_check import AcpiChecker

class BatteryCheckerNode():
    """check battery and publish the charge rate"""
    def __init__(self, battery_name='BAT0'):
        self._checker = AcpiChecker(battery_name)
        self._pub = rospy.Publisher('/pc/battery_rate', Float64)
    def proc(self):
        msg = Float64()
        msg.data = self._checker.get_rate()
        self._pub.publish(msg)

if __name__=='__main__':
    rospy.init_node('pc_battery_checker')
    battery_name = 'BAT0'
    if rospy.has_param('~device'):
        battery_name = rospy.get_param('~device')
    check = BatteryCheckerNode(battery_name)
    rate = rospy.Rate(1)
    while not rospy.is_shutdown():
        check.proc()
        rate.sleep()


参考にしたサイト

2011年10月12日水曜日

トランスフォーマー作ってみた

今日はROSでも僕の作品でもないものの紹介です。
会社のイベントにアイデアコンテストというものがありまして、
今年のテーマが「未来の車」でした。

私たちのチームでいろいろ考えた結果できた車がこれです。

  1. ロボットアームを収納し変身
  2. ヘリを収納し発射
  3. アームでヘリをキャッチしてドッキング!
というオモシロロボットカーです。

アームでは、車から降りないで駐車券を取ったり、ドライブスルーを受け取ったりできます。
ヘリでは渋滞のときに先を見に行ったり、ヘリのカメラで本当のアラウンドビューができます。

ドッキングは男の夢です。
社内コンテストは優勝はできませんでしたが、結構満足行くものが出来ました。
自慢です。

2011年6月14日火曜日

プライベートなパッケージだけにroscdするotlcdを作ったよ

Minecraftがこのブログのトップにあると色々不安なので更新します。

私は一応趣味でrosのパッケージを作ってみています。
大体パッケージ名はotl_hogehogeという名前になっています。
rosはwikiのドキュメントとかがいきなりパッケージ名なので、これが他の人とかぶると困るからです。

普段、自分が作ったパッケージに移動(cd)するには

$ roscd otl_
と入力して、Tabを押してそこから目的のパッケージを探しています。

これをもっと簡単にするotlcdを作ります。

$ otlcd
と入力して、Tabを押すと
$ otlcd otl_
と展開されて、もう一度Tabを押すと候補("otl_"で始まるパッケージ)一覧が表示される、という状態にしたいです。


というわけでroscdを参考に、というか、ちょっとだけいじって作ってみました。
ソースは以下のような感じ。

function _otlcomplete_sub_dir {
    local arg opts rosvals
    COMPREPLY=()
    arg="${COMP_WORDS[COMP_CWORD]}"
    _ros_decode_path ${arg}
    if [[ -z ${rosvals[2]} ]]; then
        opts=`_ros_list_locations | grep ^${OTLCD_PREFIX}`        IFS=$'\n'
        COMPREPLY=($(compgen -W "${opts}" -S / -- ${rosvals[0]}))
        unset IFS
    else
        if [ -e ${rosvals[1]}${rosvals[2]} ]; then
          opts=`find -H ${rosvals[1]}${rosvals[2]} -maxdepth 1 -mindepth 1 -type d
 ! -regex ".*/[.].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1\//g"`
        else
          opts=''
        fi
        IFS=$'\n'
        COMPREPLY=($(compgen -P ${rosvals[0]}${rosvals[2]} -W "${opts}" -- ${rosvals[3]}))
        unset IFS
    fi
}
alias otlcd=roscd
complete -F "_otlcomplete_sub_dir" -o "nospace" "otlcd"
これをotl_bashパッケージにotlbashというファイル名で作りました。
赤いところをいじってあとはrosbashのコピペです。
(やっつけ感がすごくてすみませんがsubversionにいれておきました)


.bashrcでsetup.bashを読み込んだあとで以下の記述を追加すると使えます。

export OTLCD_PREFIX="otl_"
source `rospack find otl_bash`/otlbash
OTLCD_PREFIXに好きな文字列を入れられるので、もし私と同じようなprefixをパッケージ名に付けている人はいかがでしょうか?

2011年5月15日日曜日

テレプレゼンスロボット作ってみた

前から興味があったので作ってみました。
rosjsとかはこのために勉強しました。

ハード、ソフト的にもほとんど揃っていたので制作費0円、製作時間1日、っていう感じです。
出先からiPhoneさえあれば使えるので、これから実際にいろいろと利用してみたいと思います。



ハードウェア構成:
ルンバ <- bluetoothアダプタFriskRoomba(by longjie) -> Thinkpad X61 tablet
サーボモータ <- Arduino -> Thinkpad
USB Camera <-> Thinkpad
Thinkpad <- rosbridge + rosjs -> iPhone/Macのブラウザ
+ Skype
という感じです。

ビデオを撮ってみて思ったのは、全然面白みがないですね。
なんていうか、普通というか。。。
まあ、もうあるロボットコンセプトなんでこんなもんですね。

2010年9月19日日曜日

お茶注ぎロボット完成〜。

前回紹介したお茶注ぎロボットが(一応)完成したのでとりあえず動画だけ
紹介しておきます。

本当はもっといろいろやりたかったですが、もう時間がないのでここまでです。

次回以降中身を少し紹介します。



2010年9月16日木曜日

作成中のお茶くみロボットのソフト構成

現在製作中のお茶くみロボットのノード構成の設計を以下に示します。
やっつけなので、メッセージはstd_msgsを連発してしまいます。
まあ、こまられなければそれがいいんでしょうけどちょっと寂しいですね。
これまでにやってきた既存資産とオープンソースの力をいかしまくって、ROSの多対多の通信を活用して、
さらっと結合できる。
予定です。

多分世界一高機能なお茶くみロボットになるでしょう。


作ったロボットはMOM01で展示するので、万一興味をもたれた方は見にきてくださいね〜。

2010年8月31日火曜日

日本語をしゃべるROSノード

ロボットに日本語をしゃべらせたかったので、
日本語をしゃべるROSノードを作りました。Ubuntuでのみ動作します。




jtalk_nodeです。
ソースは最後に張っておきます。

(もし使いたい人がいれば、
http://code.google.com/p/otl-ros-pkg/source/checkout
の指示にしたがいsubversionからcheckoutしてください。)

/talkトピックをSubscribeして、もらった文字列(ローマ字)を発音します。
~talk_speedをパラメータに取ってしゃべる速度を変えることができます。

インストールには、

$ rosdep install jtalk_node
$ rosmake jtalk_node
としてください。

主にライブラリAquesTalk2のインストールの自動化ところに苦労しました。
jtalk_nodeはNew BSDライセンスですが、

AquesTalk2のライセンス
「本ソフトは、非営利の個人利用に限り無償で使用できます。それ以外のご利用の場合はライセンスの購入が必要です。 法人での使用は、使用が個人であってもライセンスの購入が必要です。 」
となっているので注意してください。

以下ソース



/// talk japanese node

#include <stdio.h>
#include "AquesTalk2.h"
#include <ros/ros.h>
#include <std_msgs/String.h>

// talk speed
static int s_talk_speed = 100;

/// call back for /talk
void CommandCB(const std_msgs::String::ConstPtr& talk)
{
  int   data_size;
  FILE *play_fd;

  // make wav data usign AquesTalk2
  unsigned char *wav_buff = AquesTalk2_Synthe_Roman(talk->data.c_str(), s_talk_speed, &data_size, NULL);

  if(wav_buff==0){
    ROS_ERROR("AquesTalk2_Synthe_Roman failed");
  }
  else
  {
    play_fd = popen("play -t wav -", "w");
  
    if (play_fd < 0)
    {
        ROS_ERROR("popen fail");
    }
    else
    {
      // write to play command stdin
      fwrite(wav_buff, 1, data_size, play_fd);
      // free the data buff
      AquesTalk2_FreeWave(wav_buff);
      pclose(play_fd);
    }
  }
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "talk_node");
  ros::NodeHandle local_node("~");
  local_node.param<int>("talk_speed", s_talk_speed, 100);

  ros::NodeHandle node;
  ros::Subscriber sub = node.subscribe("talk", 10, &CommandCB);
  ros::spin();
  return 0;
}