はじめに
ハードウェアのことは何も知らないところからロボットの制御を始めます。
- OSXからシリアルUSBアダプタを使えるようにする
- Rubyからシリアルポートを叩けるようにする
- RCB-3と通信する
- RCB-3のバージョン情報を取得する
- 2HV011_お辞儀.RCB
OSXとRubyを使ってKHR-2HVを(というかRCB-3を)操作します。 シリアルUSBアダプタのドライバはLinux版も公開されてるから、 多分Linuxでも同じ事ができるんだと思う。
OSXからシリアルUSBアダプタを使えるようにする
まず付属のSerial USB AdapterをOSXから使えるようにする。
Serial USB Adapterのページによると、中のチップはFTDIのFT232BMというものであるらしい。 またMacにシリアル(RS-232C)ポートのページによると、FTDI社からFT232BM用ドライバをダウンロードしてくれば使えるようになるかも、とのこと。ということで、FTDI社のページからMac OSX (Intel)用ドライバ(FTDIUSBSerialDriver_v2_2_10.dmg)を ダウンロードし(6th August 2008版)、パッケージを展開してドライバをインストールした。 インストールガイドによると、再起動後は
/dev/cu.usbserial-xxxxxxxx
/dev/tty.usbserial-xxxxxxxx
というデバイスができているはずだが、できていなかった。
さらに調べて、Intel Macでパソコン用学習リモコンPC-OP-RS1を使う方法というページを発見。/System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist
にSerial USB Adapter用の項目を追加すればよくて、
他デバイスの項目をコピペしてProduct IDとVendor IDだけ修正すればいいみたい。
sudo emacs /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist
して、製品リストの最後に以下を追加した。
<key>Kondo Serial USB Adapter</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.FTDI.driver.FTDIUSBSerialDriver</string>
<key>IOClass</key>
<string>FTDIUSBSerialDriver</string>
<key>IOProviderClass</key>
<string>IOUSBInterface</string>
<key>bConfigurationValue</key>
<integer>1</integer>
<key>bInterfaceNumber</key>
<integer>0</integer>
<key>idProduct</key>
<integer>2</integer>
<key>idVendor</key>
<integer>5724</integer>
</dict>
Product IDとVendor IDはSerial USB Adapterを挿した状態でアプリケーション→システムプロファイラ→USB→SERIAL USB ADAPTERで、それぞれ0x0002と0x165cだとわかるので、10進数に変換して2と5724になった。最後にsudo touch /System/Library/Extensionsして再起動。
再起動後、
% ls -l /dev/*.usbserial*
crw-rw-rw- 1 root wheel 9, 7 12 29 13:37 /dev/cu.usbserial-KORB79DX
crw-rw-rw- 1 root wheel 9, 6 12 29 13:37 /dev/tty.usbserial-KORB79DX
デバイスができた!
Rubyからシリアルポートを叩けるようにする
- ruby-serialport-0.6.tar.gz
- README
- ruby extconf.rb; make; sudo make install
RCB-3と通信する
RCB-3コマンドリファレンス(p.7)を見て、 まず0Dを送って0Dが返ってくることを確認する。 KHR-2HVの電源を入れるのを忘れずに。
#!/usr/bin/ruby
require 'serialport'
port = "/dev/cu.usbserial-KORB79DX" # ポート名
# ポートのオープン
# 通信速度115200bps、データビット=8bit、ストップビット=1bit、パリティ無し
sp = SerialPort.new(port, 115200, 8, 1, SerialPort::NONE)
# 0Dを送る
command = ["0D"] # Array::pack を使うので文字列をarrayに
sp.write(command.pack("H*")) # 16進数としてpackして送信
# 1バイト受け取って16進数で表示
result = sp.getc
printf("recv = %02x\n", result)
sp.close # ポートのクローズ
試してみる。↓
% ./sync.rb
recv = 0d
おけ。
RCB-3のバージョン情報を取得する
手順としては、
- 0Dを送る
- 1 byte (0D)受け取る
- FFFFを送る
- 65 bytes 受け取る
- 表示
となる。命令が1 byte (FF)なので、チェックサムも自動的にFFとなる。
#!/usr/bin/ruby
require 'serialport'
port = "/dev/cu.usbserial-KORB79DX"
sp = SerialPort.new(port, 115200, 8, 1, SerialPort::NONE)
# 0Dを送る
command = ["0D"]
sp.write(command.pack("H*"))
# 1バイト受け取る
result = sp.getc
# FFFFを送る
command = ["FFFF"]
sp.write(command.pack("H*"))
# 65バイト受け取る
result = "" # 空文字列を用意して
65.times {
result << sp.getc #1バイトを65回受け取り文字列に追加していく
}
printf("%s\n", result.unpack("A*")) # unpackした後文字列として表示
sp.close # ポートのクローズ
試してみる。↓
% ./version.rb
RCB-3 V1.10A 2007/09/19 ###% 3
いやっほう。
2HV011_お辞儀.RCB
の動作を模倣してみる
一番簡単そうなお辞儀の動作を模倣してみた。2HV011_お辞儀.RCB
の中を見ると7つポーズがあって、それぞれパラメータ(Prm)が割り当てられている。
最初の数字がスピード、残りの24個の数字が各モータの相対舵角(コマンドリファレンスp10参照)らしい。これを順番に再生していけば良いのだと思う。
「動作パラメータと動作速度を設定する」(p.20)の通りにコマンドを送ると (モーション番号とポジション番号は適当に)、書き込みしなくて も動くことがわかった。というか書き込み方がわからないんだが…。
で、チェックサムの計算やらなんやらで長くなったプログラム。書き込んだモーションと比較して、同じようにお辞儀をしてると思う。
動くには動いたけど、実はよくわかってない。 「動作パラメータと動作速度を設定する」(p.20)を見て、 モーション番号は3、ポジション番号は0に設定してるけど、 これでいいのか?とか、複数のポジションはどうやって設定するのか?とか、 ポジション間をどうやって繋ぐのか?とか、条件分岐はどうするのか?とか、 全然わかってない。
ACKは各モーションの終わりに返ってくると思ってたけど、 どうやらコマンドを受理した瞬間に返ってくるらしいので (オプションの下位1bitを立てても変わらなかった)、 モーションの終わりが判定できない。なので、0.015*スピード秒sleepを 入れてる。モーションの終わりを判定する方法は無いのかな。
この文書について
- Author
- 山崎 匡 <tyam@brain.riken.jp>
- Date
- 20081230
- LastModified
- 20081230
- Changelog
- 20081230: Initial version