ROS Pythonにおけるuint8[]の扱い方
ROSでuint8[]
型を利用しているトピックをPythonで使う場合にハマった点です。
環境
- Ubuntu 14.04
- ROS Indigo
rospyにおけるuint8[]
型の扱い
ROSのメッセージ型に関するリファレンスを参照すると、uint8[]
型について以下のような記述があります。
uint8 has special meaning in Python. uint8[] is treated as a Python bytes so that it is compatible with other byte-oriented APIs in Python.
rospy treats
uint8[]
data as a bytes, which is the Python representation for byte data. In Python 2, this is the same as str.
Pythonでは、ROSのuint8[]
型がbytes型(Python 2系ではstr型)として扱われるらしく、これは時に厄介な問題を引き起こします。
発生した問題
とあるセンサー群の測定値を測定するメッセージ型を以下のように定義しました。
foo_package/msg/FooSensor.msg
uint8[] value
そして、以下のようなシンプルなPublisherとSubscriberを作成しました。
publisher.py
import rospy from foo_package.msg import FooSensor def publish(): publisher = rospy.Publisher('/foo', FooSensor, queue_size=1) value = FooSensor(value=[100, 110, 120]) r = rospy.Rate(1.0) while not rospy.is_shutdown(): publisher.publish(value) r.sleep() publish()
subscriber.py
import rospy from foo_package.msg import FooSensor def callback(data): rospy.loginfo(data) rospy.loginfo(data.value) def subscribe(): rospy.Subscribe('/foo', FooSensor, callback) rospy.spin() subscribe()
publisher.py
, subscriber.py
を実行すると、以下のような2つのINFOレベルのログが出力されます。
- [INFO] [WallTime: 1461145922.975544] value: [100, 110, 120]
- [INFO] [WallTime: 1461145941.678116] dnx
data
自体を出力すると、valueにint型の数値が入っているのが確認できるのですが、data.value
を出力するとdnx
という文字列が出力されてしまい、配列の要素をint型として利用することが出来ません。
対処方法
対処方法はあまり根本的なものではないのですが、valueの各要素のASCIIコードが本来のintの値なので、ord
関数で変換してあげることでint型の配列を得ることが出来ます。
def callback(data): int_array = [ord(n) for n in data.value] rospy.logwarn(int_array)
再度実行すると[100, 110, 120]
という配列が出力されます。
ただし、この処理は直感的でなく、uint8[]
型以外に対してはエラーを返すため、あまりオススメできません。出来れば、メッセージ型の定義部分でuint16[]
等を利用することで回避するのが好ましいと思われます。