関心分野 >> Ros4Winのインストール >> シンプルなPublisherとSubscriber
シンプルなPublisherとSubscriber
このページでは、ROSノードのトッピク通信を行うシンプルなノード(PublisherとSubscriber)を実装していきます。
ここで作成するROSノードは、ROS初心者向けチュートリアルのものと同じです。中身の詳細は、こちらのサイトを参照していただくと良いと思います。
TalkerとListener
では、シンプルなPublisher(talker)とSubscriber(listener)を作成していきます。TalkerとListenerは下記のような機能を実装していきます。
- ''Talker'': "chatter"という名前のトピック(String型)に ”Hello World!"という文字列を 10Hzの周期で配信し続けるROSノード。
- ''Listener'': "chatter"という名前のトピック(String型)のを購読し、データを受信すると ”I hard:[<受信文字列>]” を標準出力に出力するROSノード。
ここでは、上記の機能をもつ2つのROSノードをC++とPythonで実装していきます。
C++による実装
では、C++言語で実装していきます。下のように src というディレクトリを作成して移動してください。
> roscd mytut
> mkdir src
> cd src
Talker
では、Talkerノードの実装を行います。
典型的なC++版のPublusher ROSノードのmain関数は、
典型的なC++版のPublusher ROSノードのmain関数は、
- rosの初期化
- トピック通信ポート(Publisher)の生成
- 実行周期の定義
- 実行ループ
- 配信データの生成
- 配信(publish)
- 周期実行の残り時間のsleep
となります。
talker.cppというフィル名で下のコードを作成しましょう。
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
/* initilize ROS Node */
ros::init(argc, argv, "talker");
ros::NodeHandle n;
/* create Publisher interface */
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
/* define the rate of execution loop */
ros::Rate loop_rate(10);
int count = 0;
/* execution loop */
while (ros::ok())
{
/* create a message for publisher */
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
/* Publish the message */
chatter_pub.publish(msg);
/* wate for exection loop */
loop_rate.sleep();
++count;
}
return 0;
}
Listener
次に、Listenerを実装します。
典型的なC++版のSubscriber ROSノードのmain関数は、
典型的なC++版のSubscriber ROSノードのmain関数は、
- コールバック関数の定義
- rosの初期化
- トピック通信(Subscriber)のインターフェースを作成
- コールバック関数待ち(実行ループ)
となります。
listener.cppというファイル名で下のコードを作成しましょう。
#include "ros/ros.h"
#include "std_msgs/String.h"
/* define a callback function */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
/* initilize ROS Node */
ros::init(argc, argv, "listener");
ros::NodeHandle n;
/* create a interface for the subscriber */
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
/* run execute loop */
ros::spin();
return 0;
}
このコードでは、whereのように明示的な無限ループの記述はありません。''ros::spin()''関数では、内部で無限ループが回っています。
TalkerとListenerのビルド
takler.cppとlistener.cppの実装が終わったらプログラムをビルドします。
ROSでは、C++のプログラムのビルドにも catkin_makeを使います。
ROSでは、C++のプログラムのビルドにも catkin_makeを使います。
catkin_makeでC++のソースコードをビルドするには、適切にCMakeLists.txtを修正する必要があります。C++のプログラムをビルドするには、
- include_directories (includeファイルのあるPath設定)
- add_executabe (ビルドするファイルを設定)
- target_link_libraries (リンクするライブラリの設定)
を追記します。
以下のコードを追加して下さい。
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
CMakeLists.txtの修正が終わったら、最後にワークスペースのトップに移動し、ビルドを行います。
> roscd
> catkin_make --use-vc15
以上で、C++版のROSノードの生成は終了です。
Pythonによる実装
次に、PythonでTalkerとListenerの実装を行います。Pythonのコードは、scriptsというディレクトリの下に実装していきます。
> roscd mytut
> mkdir scripts
> cd scripts
Ros4Winでは、Pythonの実行フラグの設定は必要ありません。rosunスクリプトでは、拡張子が''.py''であるファイルは、pythonスクリプトとして実行します。
Talker
では、Talkerノードの実装を行います。
典型的なPython版のPublusher ROSノードの実装コードでは、C++言語のmain関数と同様の関数(ここではtalkerとします)を下のように定義します。
典型的なPython版のPublusher ROSノードの実装コードでは、C++言語のmain関数と同様の関数(ここではtalkerとします)を下のように定義します。
- トピック通信ポート(Publisher)の生成
- rosの初期化
- 実行周期の定義
- 実行ループ
- 配信データの生成
- 配信(publish)
- 周期実行の残り時間のsleep
この関数は、C++の時のmain関数とほぼ同じです。少し変更しているのは、1と2が逆転していますが、本来この順番は変更可能です。本来は、初期化 ->インターフェースの生成の順の方がよいかと思います。
talker.pyを下のように実装してください。
#
# license removed for brevity
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
r = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
str = "hello world %s"%rospy.get_time()
rospy.loginfo(str)
pub.publish(str)
r.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException: pass
Listener
次に、Listenerを実装していきます。
ここでは、C++版のSubscriber ROSノードのときと同じように、下のように実装します。
ここでは、C++版のSubscriber ROSノードのときと同じように、下のように実装します。
- コールバック関数の定義
- rosの初期化
- トピック通信(Subscriber)のインターフェースを作成
- コールバック関数待ち(実行ループ)
listener.pyを下のように実装してください。
#
import rospy
from std_msgs.msg import String
def callback(data):
rospy.loginfo(rospy.get_caller_id()+"I heard %s",data.data)
def listener():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
rospy.spin()
if __name__ == '__main__':
listener()
以上で、典型的なPubliserノードとSubscriberノードの実装は終了です。
次は、これらのコードを実際に動かしてみましょう。