发布者与订阅者

发布者节点是可以不断的广播消息的可执行文件,订阅者接收这些消息。

C++ 实例

src/publisher.cc

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

int main(int argc, char* argv[]) {
    // ROS 操作的开端
    ros::init(argc, argv, "publisher");

    // ROS 系统的通讯接口,节点跟随句柄生命周期
    ros::NodeHandle handle;

    // 以 neo 为主题名,1000 个大小的消息队列对象,主题跟随对象生命周期;
    // 主节点会通知所有订阅 neo 的节点,由他们自己协商产生点对点链路。
    ros::Publisher publisher = handle.advertise<std_msgs::String>("neo", 1000);
    // 频率 10Hz
    ros::Rate rate(10);

    int count = 0;

    std_msgs::String msg;
    std::stringstream ss;

    // SIGINT (Ctrl+C)
    // 网络同名冲突
    // 调用 `ros::shutdown()`
    // 所有节点句柄都被销毁
    while(ros::ok()) {
        ss << "Hello " << count;
        msg.data = ss.str();

        ss.clear();
        ss.str("");

        // 通知级别的日志输出
        ROS_INFO("%s", msg.data.c_str());
        // 广播输出
        publisher.publish(msg);

        // 接收订阅者回调用
        ros::spinOnce();
        // 阻塞一段时间已达指定频率
        rate.sleep();

        ++count;
    }

    return 0;
}

src/subscriber.cc

#include "ros/ros.h"
#include "std_msgs/String.h"

void neo_callback(const std_msgs::String::ConstPtr& msg) {
    ROS_INFO("echo: [%s]", msg->data.c_str());
}

int main(int argc, char* argv[]) {
    ros::init(argc, argv, "subscriber");
    ros::NodeHandle handle;

    // 取消订阅操作跟随对象生命周期
    ros::Subscriber subscriber = handle.subscribe("neo", 1000, neo_callback);

    // 进入循环抽取模式,所有回调被主线程直接调用,直到中断或被主关闭
    ros::spin();

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(echo_hello)

find_package(catkin REQUIRED COMPONENTS
    rospy
    roscpp
    std_msgs
)

catkin_package(
)

include_directories(
    ${catkin_INCLUDE_DIRS}
)

add_executable(publisher src/publisher.cc)
add_dependencies(publisher
    ${${PROJECT_NAME}_EXPORTED_TARGETS}
    ${catkin_EXPORTED_TARGETS}
)
target_link_libraries(publisher
    ${catkin_LIBRARIES}
)

add_executable(subscriber src/subscriber.cc)
add_dependencies(subscriber
    ${${PROJECT_NAME}_EXPORTED_TARGETS}
    ${catkin_EXPORTED_TARGETS}
)
target_link_libraries(subscriber
    ${catkin_LIBRARIES}
)

Python 实例

scripts/publisher.py

#!/usr/bin/env python2

import rospy
from std_msgs.msg import String

def publisher():
    publisher = rospy.Publisher('neo', String, queue_size=10)
    rospy.init_node('publisher', anonymous=True)
    rate = rospy.Rate(10)

    count = 1
    while not rospy.is_shutdown():
        # rospy.get_time()
        hello_str = "Hello %d" % (count)
        rospy.loginfo(hello_str)
        publisher.publish(hello_str)
        rate.sleep()

        count = count + 1

if __name__ == '__main__':
    try:
        publisher()
    except rospy.ROSInterruptException:
        pass

scripts/subscriber.py

#!/usr/bin/env python2

import rospy
from std_msgs.msg import String

def callback(data):
    # rospy.get_caller_id() 
    rospy.loginfo("echo [%s]", data.data)

def subscriber():
    rospy.init_node("subscriber", anonymous=True)
    rospy.Subscriber("neo", String, callback)

    rospy.spin()

if __name__ == '__main__':
    subscriber()
测试

准备

cd ~/ROS
source devel/setup.*sh
roscore &

运行发布者

# C++
rosrun echo_hello publisher

# Python
rosrun echo_hello publisher.py

运行订阅者

# C++
rosrun echo_hello subscriber

# Python
rosrun echo_hello subscriber.py