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

2009年1月29日木曜日

Matz's talk! in "World of OSS" symposium



1月27日にせんだいメディアテークで催された「オープンソースソフトウェアの世界」というイベントに行ってきました。内容は、IPAの三浦広志氏とRubyの作者であるまつもとゆきひろ氏(Matz)の講演。
買ったばかりの、というか出版されたばかりのオライリーのRuby本にサインしていただきました。

軽く緊張してて、帽子被ったままサインを貰いに行ったのは良い(?)思い出。

2008年12月3日水曜日

スクリプト言語でちょっと短いコードを試してみる時のTips

RubyとかPerlでちょっとした短いコードを書いて(あるいはコピペして)試す場合、いちいちファイルに書き出すのは面倒です。
で、今まで知らなかったのが恥ずかしいくらいなのだけれど、簡単にちょちょっと試す方法があったのでTipsとして覚書。

  $ ruby
hoge = 12
puts hoge #ここまで入力してCtrl + D
12 #実行結果の表示が出てくれる
$

Perlでも同様にイケる。

この動画見て気づいたってのが、まぁ何だかなぁ、って感じ。

2008年8月5日火曜日

Rubyについて

最近Rubyをごにょごにょやっているのだけど、はてなのRubyに関する記述がかなり充実していて驚いた。
http://d.hatena.ne.jp/keyword/Ruby

こまった時は取り合えずここ見りゃいいな。うん。

2008年8月3日日曜日

端末でネギを振らせる


ニコ動でこんな動画を見つけて、簡単過ぎるだろ。。。と思い、なんとなくRubyで書き直してみた。


#/usr/bin/env ruby
loop do
print "\r・.・ y"
$stdout.flush
sleep 0.25
print "\r・.・_"
$stdout.flush
sleep 0.25
end


だが、sleepを使おうとすると何故かprintで何も表示されないままになってしまう。Google先生に聞いてみると、同様の症状があるらしく、標準出力の内容がバッファに溜まりつづけてるらしい。というわけで、$stdout.flushで強制的に出力させている。
これって、Rubyの仕様なのかしら? "にわか"なのでよく分からない orz

2008年7月23日水曜日

Rubyをごにょごにょ その2

Rubyで文字コード指定を行う場合、rubyコマンドに-KCODEオプションを付けるか、スクリプト中でグローバル変数$KCODEに代入して指定する。
この$KCODEの扱いについてちょっとおもしろかったのでTipsというかColumn。

$KCODEに代入するのは、"EUC","SJIS","UTF8","NONE"という文字列。初期値は"NONE"
大文字小文字関係なく指定でき、さらにそれぞれ'e','s','u','n'と省略して書く事ができる。

なぜ省略できるかというと、実は$KCODEに文字コードを示す文字列を代入する時、実際には文字列の1バイト目だけを評価しているからである。
例えば、次の様に代入式を書いても$KCODEにはSJISを指定したことになる。
$KCODE = "SUGEEEEEEEEE"
要するに最初の1文字だけが'e','s','u','n'(及びそれぞれの大文字)なら、代入する文字列は何でも良いのだ。そして、これら以外のものを代入すると、$KCODEは"NONE"になる。

それと言わずもがな、$KCODEのKはKANJIのK。

2008年7月22日火曜日

Rubyをごにょごにょ

NXTのコントロールスクリプトをRubyで書いたので、なんとなくRubyを覚え始めるようなった。

というわけで、ちょっとしたRubyまとめ〜識別子編〜

ローカル変数  :小文字から始まるもの。:foo
インスタンス変数:@から始まるもの。   :@foo
クラス変数   :@@から始まるもの。  :@@foo
グローバル変数 :$から始まるもの。   :$foo
定数      :大文字で始まるもの。 :FOO
擬似変数    :真偽値などを定義する。代入は不可。
        :nil   …null、偽。NilClass
        :true   …真。TrueClass
        :false  …偽。FalseClass
        :__FILE__ …現在のソースファイル名
        :__LINE__ …現在のソースファイル中の行番号

 Tips
  グローバル変数でも定数のような使い方をする場合は、大文字で書いてやると分かり易い。
  例えば、$DEBUGはスクリプトの初めにデバッグするかどうか真偽値で決めた後は殆ど変更しない。
  例文) puts("This is debug message.") if $DEBUG # $DEBUGが真ならデバッグ用メッセージを表示
  インスタンス変数やクラス変数でも、同様だろう。

2008年7月18日金曜日

LinuxのコマンドラインスクリプトについてのTips

Linux環境なんかで、PerlやらRubyやらPythonやらのスクリプトについてのTips

スクリプトの1行めに、
#!/usr/bin/ruby
と、書くとRubyのスクリプトとして実行してくれるわけだけど。(rubyコマンドの引数にスクリプトを突っ込まず、直接スクリプトファイルから動作させる場合)
これでは、rubyコマンドが/usr/bin/ディレクトリに存在しない場合は動作しない。

そこで、
#!/usr/bin/env ruby
と書くと、環境変数PATHを見て回ってrubyコマンドを探してくれるので、可搬性がある。

今日は何も出来なかったので、これでお茶を濁す。

2008年7月15日火曜日

Bluetooth接続でLEGO MINDSTORM NXTを動かした

昨日のエントリからの続き。


機体を改造して最終的に出来たのが写真のもの。(奥にあるのは先生が作った見本機。俺は男のロマンを追求してキャタピラにしたが)

元々、授業中の「ライントレースを行う」という課題のために作ったので、前に光センサx2とか付けていたりする。ただし、昨日のエントリで書いたスクリプトは単純に走行用のモータを制御するだけだ。

写真だと分かりづらいが、機体上部にロケットパンチ(?)みたいなのを付けてみた。3つ目のモータが回転するとクランクで力を伝えてスイッチを押し、ロケットパンチを発射する。(ちなみにロケットパンチはNXTの拡張キットにしか入ってないらしい)
ロケットパンチを発射するためのスクリプトも書いてみた。次のコードを昨日のエントリのコードに追記して、ENTERキーが押されたときにcanon_fireメソッドを呼び出すようにメインループにもコードを書き加えた。
@motor_canon = NXTComm::MOTOR_C

def canon_fire
@nxt.set_output_state(
@motor_canon,
100,
NXTComm::MOTORON,
NXTComm::REGULATION_MODE_IDLE,
0,
NXTComm::MOTOR_RUN_STATE_RUNNING,
360
)
end

@nxt.set_output_stateメソッドで、@motor_canon(ポートCのモータとして初期化)を360回転させるようにしている。
クランク部分や、実際の動作時の映像とかを撮っておけばよかったなぁ orz

普通に付属のソフトウェアで、動作ルーチンのプログラムも勿論組んだ。というか、授業ではそちらがメイン。俺だけだ、リモートコントロールなんてしてるのは。
そのプログラムでは、機体上部にモータと共に設置した超音波センサによって、前方に障害物があるとロケットパンチを発射する様にしたりしたw


さて、次はiアプリでコントロール出来るようにするか。

2008年7月14日月曜日

Bluetooth接続でLEGO MINDSTORM NXTを動かすRubyスクリプト

ヨドバシでBluetoothドングルを購入し、そのまま大学へ。
買ったのはPCIのBT-MicroEDR2
買った後に、先生から「MINDSTORMのBluetoothは相性キツいよ」と言われたが、問題なく繋がった。

んで、色々参考にしながら書いたのが下のRubyスクリプト。実行環境はUbuntu 8.04。
require 'sdl'
require 'rubygems'
require 'nxt_comm'

# control motors methods
# com is boolean. true/false = go/stop
def motor_right(com, pow)
if com
@nxt.set_output_state(
@motor_right,
pow,
NXTComm::MOTORON,
NXTComm::REGULATION_MODE_IDLE,
0,
NXTComm::MOTOR_RUN_STATE_RUNNING,
0
)
else
@nxt.set_output_state(@motor_right, 0, 0, 0, 0, 0, 0)
end
end

def motor_left(com, pow)
if com
@nxt.set_output_state(
@motor_left,
pow,
NXTComm::MOTORON,
NXTComm::REGULATION_MODE_IDLE,
0,
NXTComm::MOTOR_RUN_STATE_RUNNING,
0
)
else
@nxt.set_output_state(@motor_left, 0, 0, 0, 0, 0, 0)
end
end

#MoveMethods
def goAhead(com)
if com
puts "goAhead"
motor_right(true, -100)
motor_left(true, -100)
else
puts "goAhead stop"
motor_right(false, 0)
motor_left(false, 0)
end
end
def goBack(com)
if com
puts "goBack"
motor_right(true, 100)
motor_left(true, 100)
else
puts "goBack stop"
motor_right(false, 0)
motor_left(false, 0)
end
end
def rotateRight(com)
if com
puts "rotateRight"
motor_right(true, 85)
motor_left(true, -85)
else
puts "rotateRight stop"
motor_right(false, 0)
motor_left(false, 0)
end
end
def rotateLeft(com)
if com
puts "rotateLeft"
motor_right(true, -85)
motor_left(true, 85)
else
puts "rotateLeft stop"
motor_right(false, 0)
motor_left(false, 0)
end
end

#main

begin
@nxt = NXTComm.new("/dev/rfcomm0")
@motor_right = NXTComm::MOTOR_A
@motor_left = NXTComm::MOTOR_B
rescue
puts "Bluetooth Connection failed"
exit
end

puts "Connected to NXT"

SDL.init(SDL::INIT_VIDEO)
screen = SDL.setVideoMode(320, 240, 16, SDL::SWSURFACE)

puts "press ESC to exit"

while true
begin
case event = SDL::Event2.poll
when SDL::Event2::Quit
exit
when SDL::Event2::KeyDown
if event.sym == SDL::Key::UP
goAhead(true)
end
if event.sym == SDL::Key::DOWN
goBack(true)
end
if event.sym == SDL::Key::RIGHT
rotateRight(true)
end
if event.sym == SDL::Key::LEFT
rotateLeft(true)
end
when SDL::Event2::KeyUp
if event.sym == SDL::Key::UP
goAhead(false)
end
if event.sym == SDL::Key::DOWN
goBack(false)
end
if event.sym == SDL::Key::RIGHT
rotateRight(false)
end
if event.sym == SDL::Key::LEFT
rotateLeft(false)
end
if event.sym == SDL::Key::ESCAPE
puts "bye"
exit
end
end
rescue
puts "Error"
exit
end
end

exit
余計な部分もあるが、まだ少し弄くろうと思ってるので分かり易さ重視。

作ったのは戦車のような機体。
モータの回転力を与える部分で、前進させるのに-100と指定しているのは、機体のモータの向きを逆に付けてしまっているため。
超信地旋回では、少し回転力を弱くして(85)回りすぎないようにしている。初め、50に設定してみたが、弱すぎて動かず、ビープ音が(汗


事前にインストールしておくもの
  • libserialport-ruby
    Rubyで使うシリアルポートライブラリ。
  • rubygems
    ruby-nxt-0.8.1.gemをインストールするのに必要。gemはRubyでパッケージ/ライブラリを管理するコマンド。
  • ruby-nxt-0.8.1.gem
    RubyからNXTを使うためのライブラリ。aptではなく、直接DLしてきてgemでインストールする。sudo gem install ruby-nxt-0.8.1.gem。http://rubyforge.org/projects/ruby-nxt/
  • libsdl-ruby
    RubyからSDLを使うためのライブラリ。キー入力を取得するのに使った。
また、実行前にNXTとPCをBluetooth接続して、デバイスファイルを作っておく必要がある。そして、デバイスファイルのパスを、スクリプト中のNXTComm.newの引数として渡してやらなければならない。


デバイスファイルの作成方法は次の手順。

NXTのBluetoothをONにして、PCにBluetoothドングルを差した状態で
$ hcitool scan
を実行してNXTのMACアドレスを表示させる。
/etc/bluetooth/rfcomm.confを編集し、次の様にする。
rfcomm0 {
bind yes;
device MACアドレス;
channel 1;
comment "NXT";
}
Bluetoothデーモンを再起動。
/etc/init.d/bluetooth restart
PC側から、もしくはNXT側からBluetooth接続要求を出して接続をペアリングする。ペアリングは上のサ行の前にやっても良かったかもしれない。
これで、Bluetooth接続したNXTへのデバイスファイルが/dev/rfcomm0というパスで出来ている筈。


設定ファイルをいじらずにデバイスファイルを作成する方法が合ったので追記。
$ hcitool scan
で機器を検索し、MACアドレスを表示させる。

$ sudo rfcomm bind 1 MACアドレス チャンネル番号
で、MACアドレスで指定した機器への/dev/rfcomm1というデバイスファイルが出来る。チャンネル番号は省略して良い。省略すると自動で1が割り当てられる。

$ rfcomm
何もオプションを指定せずにrfcommコマンドを叩くと、現在登録している機器の情報が表示される。
rfcomm1: 01:23:45:67:89:10 channel 1 clean
という感じ。

登録機器を開放する場合は、
$ sudo rfcomm releace rfcomm1



これで、取り合えずは動いたのだが、キーを連打すると実際の動作が追いつかなかったり、左右のモータを同時に動かそうとしても少し時間差が出てしまったり、、、

<追記>
ってか、Rubyの標準ライブラリにCursesあるんじゃん。SDLいらんかった orz