rosserial通信での配列のやりとりについて

1,285 views
Skip to first unread message

b130...@planet.kanazawa-it.ac.jp

unread,
Feb 2, 2017, 10:16:56 PM2/2/17
to ROS JAPAN Users Group
こんにちは、ROS1年生の学生です。

本日は、arduino_MegaとPC(python)での通信部分でどうしても解決できない問題が発生してしまったため、この場をお借りして質問させていただきます。

arduinoのスケッチの例にあるarray_testを試している時に発生した問題です。
結論としては、arduino側のコールバックがうまくかかりません

スケッチ例のarray_testは、PoseArray型をsubし、その要素のpositionを合計したものをPose型としてパブリッシュする、と言うものです。
これを試してみるため、pythonでPoseArray型をパブリッシュする簡単なプログラムを組み、実行して見たところ、
PC側でパブリッシュするPoseArrayの配列数が1の時は、arduino側のコールバックはほとんどうまく実行されます。(20回に一回程度反応しない)
PC側でパブリッシュするPoseArrayの配列数が2の時は、arduino側のコールバックはほとんど実行されません(50回に一回程度反応する)
と言う問題が発生しました。配列数1の時はいいとしても、配列数2のほとんどコールバックがかからないのはとても困ります。
配列数3以上も2の場合と同様でした。

この問題にあたって、バッファの溢れを疑ったのですが、ターミナルにはバッファ溢れのエラーは表示されませんでした。
また、ヘッダーを除いたバイト数は、配列数2の場合、112byte程度なので、arduino側が512byteのバッファ空間を所有していることを考えると溢れではないと思います。

JointState型やFloatMultiArray型といった配列を有した型でも、まったくの同じ条件ではありませんが、コールバックがかからないという似た問題が発生しました。
String型やint8型等の場合は、問題なく動作しました。

特殊なことをしていないため、私が基本的なことを怠っている可能性が高いのですが、解決することができません。お力をお貸しください。
ardino_IDEのバージョン: 1.6.12
使用arduino     : arduino_Mega2560
rosのバージョン    : indigo
Ubuntuのバージョン  : Ubuntu 14.04.5 LTS

arduino側のプログラム
arduino_IDEにros_libを追加したときに、サンプルとして初期に追加されるものです。


PC(python)のパブリッシュ側のプログラム
#!/usr/bin/env python
#coding: utf-8
import rospy
from geometry_msgs.msg import PoseArray, Pose

if __name__ == '__main__':
rospy.init_node('test_pub')
pub_pa = rospy.Publisher("poses", PoseArray , queue_size=10)

aaa = PoseArray()
aaa.header.seq = 0 
aaa.header.stamp =  rospy.Time.now()
aaa.header.frame_id = "umaku_ike"
aaa.poses.append( Pose() )
aaa.poses[0].position.x=1.1
aaa.poses[0].position.y=1.2
aaa.poses[0].position.z=1.3
aaa.poses[0].orientation.x=1.4
aaa.poses[0].orientation.y=1.5
aaa.poses[0].orientation.z=1.6
aaa.poses[0].orientation.w=1.7

aaa.poses.append( Pose() )
aaa.poses[1].position.x=2.1
aaa.poses[1].position.y=2.2
aaa.poses[1].position.z=2.3
aaa.poses[1].orientation.x=2.4
aaa.poses[1].orientation.y=2.5
aaa.poses[1].orientation.z=2.6
aaa.poses[1].orientation.w=2.7

rate = rospy.Rate(1)
while not rospy.is_shutdown():
aaa.header.seq += 1 
aaa.header.stamp =  rospy.Time.now()
pub_pa.publish(aaa)
rate.sleep()

Ryosuke Tajima

unread,
Feb 3, 2017, 10:11:13 PM2/3/17
to ROS JAPAN Users Group
こんにちは、

ハードウェアが絡むと、それを持ってない人は答えにくいのでなかなか返事が来ないかと思いますが、
投稿された情報からは以下の2点が気になったところです。

1. シリアル通信の通信条件
ROSとArduinoの通信条件があっているかを確認してください。通信速度、ビット幅、パリティ、ストップビットが正しいかどうか。Arduinoコード内では設定していないので、たぶんArduino IDEの設定が引き継がれていると思います。rosserial_pythonの規定値は8N1 (8ビット、パリティ無し、ストップビット1)ですが、Arduinoがそうなっているかを確認した方がいいでしょう。このへんが間違っていても化けたデータが来て一見通信できてるように見えるときもあります。

2. header.seqは自分でいじってはいけない
これは今回の問題と関係ある可能性は低いですが、header.seqは自動で処理されるので、自分で+1とかする必要は無く、またいじっても思った通りの値にもならないです。
header.seqはROSではもう使われていないようなので(ROS2では無くなるようです)、関係ないとは思いますが、もしかしたらrosserialの中でなんか使っている、かもしれない、と思いました。


たじま


2017年2月3日(金) 12:16 <b130...@planet.kanazawa-it.ac.jp>:
--
このメールは Google グループのグループ「ROS JAPAN Users Group」に登録しているユーザーに送られています。
このグループから退会し、グループからのメールの配信を停止するには ros-japan-use...@googlegroups.com にメールを送信してください。
その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。

b130...@planet.kanazawa-it.ac.jp

unread,
Feb 4, 2017, 2:39:04 PM2/4/17
to ROS JAPAN Users Group
ご返信ありがとうございます。
ご指摘の点に関して試してみました。

1. シリアル通信の通信条件について、
Serial.begin(57600, SERIAL_8N1);
をnd.initNode();の前後等に書いてみて何通りか試して見ましたが、解決しませんでした。

nh.getHardware()->setBaud(57600);
で明示的にポーレートを設定してみましたが、変化はありませんでした。(ポーレート自体を変更できることはBool型で確認済)
rosrun rosserial_pyon serial_node.pyを実行した時に出るログにも、57600baudで通信できているとの表記されています。

[INFO] [WallTime: 1486236949.288067] Connecting to /dev/ttyACM0 at 57600 baud


2. header.seqは自分でいじってはいけない について、
これについては、私自身知りませんでした。ありがとうございます。
header.seqの部分を除いてみたのですが、変化ありませんでした。


ハードウェアの問題とは考えたことがなかったため、UNO等が手に入り次第試してみたいと思います。

もしよろしければ、このプログラムを使えば配列型でも確実に動くことを確認ができた、というpython、arduino双方のプログラムはありませんでしょうか

b130...@planet.kanazawa-it.ac.jp

unread,
Feb 15, 2017, 10:31:31 PM2/15/17
to ROS JAPAN Users Group
Arduino Unoを入手することができたので、一通り試しました。

結果としては、動作は変わらず、Megaのときと変わらずうまくいかないままでした。
これを見るに、ハードウェア固有の問題ではないように思えます。

Ryosuke Tajima

unread,
Mar 7, 2017, 9:56:28 PM3/7/17
to ROS JAPAN Users Group
こんにちは、

もう解決したかもしれませんが、こちらでも少し試してみました。手持ちのArduinoが Arduino pro miniしかなかったので、それで試しました。
たしかに、サンプルのスケッチで、メールにあったpythonコードだと、コールバックが呼ばれないですね。

バッファサイズが一番怪しいようです。rosserialのバッファサイズの既定値は送受信共に512byteですが、
実はArduino自体のシリアルのバッファサイズは別のところで指定されています。それらは、RAMが1k以下の機種だと16byte, それ以外の機種だと64byteです。


変更するには、HardwareSerial.hの該当部分を書き換える必要があります。

その他、arduino, serial, buffer sizeで検索

ただ、自分のArduino pro mini + arduino 1.8.1 + rosserial では、バッファサイズを増やすとRAMが足りない旨のワーニングが出て動作自体が不安定になり、うまく動作していないです。RAM 2kだとそもそもキツそうです。

なので、RAMの多いArduino Megaで、これらの値を512byteとかに増やして試してみるのはどうでしょうか。

但馬

2017年2月16日(木) 12:31 <b130...@planet.kanazawa-it.ac.jp>:
Reply all
Reply to author
Forward
0 new messages