ROSのPointCloud2で独自のフィールドを定義
ROSのpclパッケージで独自のフィールドを定義したPointCloud2
のトピックをpublish, subscribeする方法です。
環境
- Ubuntu 14.04
- ROS Indigo
スクリプト例(Publisher)
rvizで確認
上記のスクリプトを動かし、rvizでPointCloud2
型の/custom_point_cloud
トピックを表示すると、下図のように生成した3つの点が色付きで表示されることが確認できます。
$ rosrun some_package publish_custom_point_cloud.py
フィールドの定義
上記スクリプトではFIELDS
の部分で独自のフィールドを定義しています。
FIELDS = [ # x, y, zやrgbなどはよく使われるフィールド名 PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1), PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1), ... # 以下が独自のフィールド PointField(name='my_field1', offset=16, datatype=PointField.FLOAT32, count=1), ]
よく使われるフィールドについては pcl/Overview - ROS Wiki の 1.3 Common PointCloud2 field names の項目で列挙されています。
PointFieldの各引数は以下のように定義されています。
string name # Name of field
uint32 offset # Offset from start of point struct
uint8 datatype # Datatype enumeration, see above
uint32 count # How many elements in the field
name
とdatatype
は見ての通り、フィールド名とデータ型です。
offset
はPointCloud2の各点を表す構造体の中で、何バイトのところからがそのフィールドを表しているかを定義するようです。
例えばx
座標のフィールドのFloat32
は4バイトなので、後続するy
座標のフィールドはoffset=4
となっています。
また、count
は当該フィールドのデータ数を表しています。通常は1で良いと思います。
ポイントの生成
POINTS = [ # FIELDSで定義したフィールドを列挙 # [x, y, z, rgb, my_field1, my_field2] [0.3, 0.0, 0.0, 0xff0000, 0.5, 1.2], [0.0, 0.3, 0.0, 0x00ff00, 1.8, 0.0], [0.0, 0.0, 0.3, 0x0000ff, 0.9, 0.4], ]
create_cloud
の3番目の引数には点のリストであるPOINTS
を渡しています。
POINTS
の各要素はそれぞれがポイントに対応しており、各ポイントもリスト型になっていて、FIELDS
で定義したフィールドの順に値が並んでいます。
例えば、count=1
のフィールドが3個の場合は長さ3のリストに、count=1
のフィールドが3個とcount=3
のフィールドが1個の場合は長さ6にリストになります。
スクリプト例(Subscriber)
このスクリプトを動かすと以下のような出力が表示されます。
$ rosrun some_package subscribe_custom_point_cloud.py [WARN] [WallTime: 1456466400.492649] x, y, z: 0.3, 0.0, 0.0 [WARN] [WallTime: 1456466400.492909] my field 1: 0.500000 [WARN] [WallTime: 1456466400.493283] my field 2: 1.200000 [WARN] [WallTime: 1456466400.493446] x, y, z: 0.0, 0.3, 0.0 [WARN] [WallTime: 1456466400.493641] my field 1: 1.800000 [WARN] [WallTime: 1456466400.493788] my field 2: 0.000000 [WARN] [WallTime: 1456466400.493930] x, y, z: 0.0, 0.0, 0.3 [WARN] [WallTime: 1456466400.494073] my field 1: 0.900000 [WARN] [WallTime: 1456466400.494212] my field 2: 0.400000
各ポイントを使うときはread_points
関数を利用すると、publisherのPOINTS
と同じ形式で点群を取得できます。
参考URL
Python, OpenCVでRGBとHSVを相互変換
動作環境
- OpenCV 2.4.8
OpenCVでRGBとHSVを相互変換
画像のRGBとHSVをまるごと変換するにはcv2.cvtColor
をそのまま使えばよいのですが、こちらはRGBとHSVの値を1ピクセルだけ変換するためのラッパー関数です。
import numpy as np import cv2 def hsv_to_rgb(h, s, v): bgr = cv2.cvtColor(np.array([[[h, s, v]]], dtype=np.uint8), cv2.COLOR_HSV2BGR)[0][0] return (bgr[2], bgr[1], bgr[0]) def rgb_to_hsv(r, g, b): hsv = cv2.cvtColor(np.array([[[b, g, r]]], dtype=np.uint8), cv2.COLOR_BGR2HSV)[0][0] return (hsv[0], hsv[1], hsv[2])
>>> hsv_to_rgb(0, 255, 255) (255, 0, 0) >>> hsv_to_rgb(60, 255, 255) (0, 255, 0) >>> hsv_to_rgb(120, 255, 255) (0, 0, 255) >>> rgb_to_hsv(255, 0, 0) (0, 255, 255) >>> rgb_to_hsv(0, 255, 0) (60, 255, 255) >>> rgb_to_hsv(0, 0, 255) (120, 255, 255)
人感センサ(SB00412A-1)検知時にLEDを光らせる
aitendoで人感センサ(SB00412A-1)を購入したので、センサが人を検知した時にLEDを光らせてみました。
追記(2016/02/28)
SB00412A-1を3.3Vで接続すると動作が不安定になるため、5Vでの接続を推奨します!
接続方法は、Raspberry Piで人感センサ(SB00412A-1)を5Vで利用する方法 - Yura YuLifeの記事を参照してください。
ちなみに人感センサことPIRセンサは赤外線の変化を捉えるセンサで、人間が発する赤外線によって人が近づいたのを検知できます。
性能
一回点灯すると人がいなくなっても7〜8秒は点灯し続けています。
スペックによると感知距離は3〜5mとのこと。机の上に上向きにセンサを設置した部屋に入ると、LEDがピカッと光りました。机とドアの距離は大体1.5mくらいです。
必要なもの
- Raspberry Pi2 Model B (Raspberry Pi A/B+も可)
- 低電圧極小PIRセンサー SB00412A-1
- LED
- 1kオームの抵抗
- ブレッドボード
- ジャンパーワイヤ 7本くらい
配線
SB00412A-1
基板に+と-が書いてあるので、それぞれ3.3VとGNDへ。GPIOはどこでも大丈夫です。
LEDと抵抗
LEDの足の長い方をGPIOに、短い方を抵抗を介してGNDに接続します。
スクリプト
プログラム中のSENSOR_PIN
とLED_PIN
を、それぞれSB00412A-1とLEDが接続されたGPIOのピン番号に変更します。
$ python sync_sensor_led.py
を実行するとセンサーが人を検知した時にLEDが光ります。
参考URL
Raspberry Piでスイッチを押すと音楽を再生する
Raspberry Piに接続したタクトスイッチを押すと、音楽を再生するPythonのスクリプトです。
ちなみに、上の動画で流れているのは僕のバンドCosmic Time Scaleの曲です。
必要なもの
- Raspberry Pi2 Model B (Raspberry Pi A/B+も可)
- タクトスイッチ
- 10kΩの抵抗
- ジャンパーワイヤ 5本くらい
Raspberry Piとタクトスイッチを接続
こんな感じで配線します。
GPIOピンは今回は19番を使っていますが、空いていればどのピンでも大丈夫。
スイッチの動作をテスト
以下のスクリプトをraspi_gpio_pin.py
として保存します。
$ python raspi_gpio_pin.py
を実行し、スイッチを押していない時は0
、スイッチを押している時は1
がコンソールに出力されれば、問題なく配線されています。
スイッチ押下で音楽を再生
以下のスクリプトをraspi_play_music.py
として保存します。
$ python raspi_play_music.py
を実行し、スイッチを押すとSONG_LIST
の中からランダムに曲が再生されます。
これを応用すればRaspberry Piで音響さんやDJができますね。
参考URL
Raspberry Piに接続したLCD(ACM1602NI)をPythonで動かす
Raspberry PiにI2Cで接続したLCD(ACM1602NI-FLW-FBW-M01)を、Pythonから動かします。
ソースコード、セットアップ手順はGitHubにて公開しています。
必要なもの
- Raspberry Pi2 Model B (Raspberry Pi A/B+も可)
- LCDモジュール(ACM1602NI-FLW-FBW-M01)
- 10kΩの半固定抵抗
- ハンダゴテ、ハンダ、吸い取り線(必要に応じて)
- ブレッドボード
- ジャンパーワイヤ(長いオス-メス: 4本、短いオス-オス:10本くらい)
Raspberry PiとLCDを接続
LCDにハンダ付け
LCDの基板に7ピンのピンフレームをハンダ付けします。
ブレッドボードにピンを刺した状態でハンダ付けすると、ピンを垂直に固定するのが容易になるのでオススメです。
LCDとRaspberry Piを接続
ブレッドボード上はこんな感じで接続します。
ちなみに本体側のピンはこちら。
ここまでできたらRaspberry Piを起動します。
Raspbianの設定
I2Cを有効にする
$ sudo raspi-config
9 Advanced Options
から A7 I2C
を選択し、 Yes
を2回選択します。raspi-config
を抜けたらRaspberry Piを再起動します。
必要なライブラリのインストール
$ sudo apt-get install i2c-tools python-smbus
ドライバーのロード
$ sudo modprobe i2c-bcm2708 $ sudo modprobe i2c-dev
I2C Configの編集
/boot/config.txt
を開いて以下の行を追記します。
dtparam=i2c_baudrate=50000
ここで再度Raspberry Piを再起動します。
設定の確認
以下のコマンドを実行し、bcm2708
がロードされていること、baudrate
が50000
に変更されていることを確認します。
$ dmesg | grep i2c
[ 3.787020] bcm2708_i2c 3f804000.i2c: BSC1 Controller at 0x3f804000 (irq 79) (baudrate 50000) [ 3.820524] i2c /dev entries driver
LCDの動作テスト
以下のコマンドを実行し、LCDにA
と表示されることを確認します。
$ sudo i2cset -y 1 0x50 0x00 0x01 $ sudo i2cset -y 1 0x50 0x00 0x38 $ sudo i2cset -y 1 0x50 0x00 0x0c $ sudo i2cset -y 1 0x50 0x00 0x06 $ sudo i2cset -y 1 0x50 0x80 0x41
なお、i2cset
コマンドの引数の1
はI2Cバスの番号、0x50
はLCDのアドレスです。
通常これらはi2cdetect
コマンドで調べられるのですが、このコマンドを実行するとLCDがハングするため絶対に行ってはいけません。
PythonからLCDを操作
$ git clone https://github.com/yuma-m/raspi_lcd_acm1602ni.git $ cd raspi_lcd_acm1602ni $ sudo python raspi_lcd.py "Hello world!" $ sudo python raspi_lcd.py "ラズベリーパイデ、" "ニホンゴヲLCDヒョウジ!"
raspi_lcd.py
は引数を1つ、もしくは2つ取ることができ、それぞれが1行目、2行目の表示内容に対応しています。
入力可能な文字は、半角英数記号、半角・全角のカタカナ、一部の特殊文字(千、万、円、Σ、α、βなど)です。