机器人操作系统ROS(08):msg of publisher和subscriber

publisher和subscriber的C++和Python实现。

  • 11、Publisher和Subscriber(C++语言)

节点node通常就是指连接到ROS网络的一些可执行节点,常见的例如发布者publisher和订阅者subscruber。
1、建一个不停广播消息的发布者(讲者)node。在src下编辑talker.cpp:
$ cd ~/catkin_ws/src/beginner_tutorials
$ mkdir -p ~/catkin_ws/src/beginner_tutorials/src
$ vi talker.cpp
#include “ros/ros.h”
#include “std_msgs/String.h”
#include
int main(int argc, char **argv) {
ros::init(argc, argv, “talker”);//第三个参数是node名称
ros::NodeHandle n;//这是与ROS系统通讯的句柄,注意构造和析构
ros::Publisher chatter_pub = n.advertise<std_msgs::String>(“chatter”, 1000);//消息类型是std_msgs/String ,第二个参数是最大缓存消息数目,该函数生成一个publisher对象,该对象有一个比较重要的方法是publish()
ros::Rate loop_rate(10);//循环周期是10Hz
int count = 0;
while (ros::ok()) {
std_msgs::String msg;//消息对象
std::stringstream ss;
ss << “hello world ” << count;
msg.data = ss.str();
ROS_INFO(“%s”, msg.data.c_str());
chatter_pub.publish(msg);//消息类型要符合advertise<>()
ros::spinOnce();//这个主要用于回调
loop_rate.sleep();//休眠,直到满足10Hz
++count;
}
return 0;
}
2、建一个订阅者(讲者)node。在src下编辑listener.cpp:
#include “ros/ros.h”
#include “std_msgs/String.h”
void chatterCallback(const std_msgs::String::ConstPtr& msg) {//消息到达之后的回调函数
ROS_INFO(“I heard: [%s]”, msg->data.c_str());
}
int main(int argc, char **argv) {
ros::init(argc, argv, “listener”);
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe(“chatter”, 1000, chatterCallback);//返回一个ros::Subscriber对象,第二个参数是缓存消息最大数目
ros::spin();//进入循环
return 0;
}
3、编辑CMakeLists.txt,添加:
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)
这样就建立了两个可执行的talker和listener,然后可以make:
$ catkin_make
4、可以测试:
$ cd ~/catkin_ws
$ source ./devel/setup.bash
$ roscore
运行publisher:
$ rosrun beginner_tutorials talker
[INFO] [WallTime: 1314931831.774057] hello world 1314931831.77
[INFO] [WallTime: 1314931832.775497] hello world 1314931832.77

运行subscriber:
$ rosrun beginner_tutorials listener
[INFO] [WallTime: 1314931969.258941] /listener_17657_1314931968795I heard hello world 1314931969.26
[INFO] [WallTime: 1314931970.262246] /listener_17657_1314931968795I heard hello world 1314931970.26

13、Publisher和Subscriber(Python语言)
1、如果需要,建立工作区:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
cd ..
catkin_make
2、如果需要,建立类似hello_word这样一个package:
cd ~/catkin_ws/src
catkin_create_pkg hello_world std_msgs rospy
cd ..
catkin_make
source ~/catkin_ws/devel/setup.bash 或者
echo “source ~/catkin_ws/devel/setup.bash” >> ~/.bashrc
3、建立保存脚本的文件夹:
mkdir scripts
4、发布节点hello_world_publisher.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher(‘hello_pub’, String, queue_size = 10) #give topic name and define msg type
rospy.init_node(‘hello_world_publisher’, anonymous = True) #give node name
r = rospy.Rate(10) #10hz, create a Rate object rate.
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
Python脚本对缩进敏感,如图:

def定义了一个函数。if __name__==’__main__’说明仅在直接在CML下面才运行,try-except-pass掉来自ros的exception。
5、订阅者节点hello_world_subscriber.py
#!/usr/bin/env python
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(‘hello_world_subscriber’, anonymous=True)
rospy.Subscriber(“hello_pub”, String, callback)
rospy.spin()
if __name__ == ‘__main__’:
listener()
6、可以测试
运行发布者node:
rosrun hello_world hello_world_publisher.py

运行订阅者node:
rosrun hello_world hello_world_subscriber.py

0 回复

发表评论

Want to join the discussion?
Feel free to contribute!

发表评论