ROS 详细讲解通过键盘控制小海龟运动来实现话题发布者Publisher与订阅者Sbuscriber

// linear线性的 angular角度的
//%0.2f打印geometry_msgs::Twist类型
// %s打印std_msgs::String类型

发布者Publisher与订阅者Sbuscriber

// linear线性的 angular角度的
%0.2f打印geometry_msgs::Twist类型

第一步启动小海龟及其键盘控制

启动小海龟及其键盘控制

$ roscore
$ rosrun turtlesim turtlesim_node 
$ rosrun turtlesim turtle_teleop_key 

第二步查看rosnode节点直接的关系

查看rosnode节点直接的关系

$ rqt_graph

rqt_graph
由于箭头是单向的,所以消息传播是单向的,由图像可知,/teleop_turtle为发布者Publisher,用于键盘发布指令,/turtlesim为订阅者Subscriber,用于定义指令,两节点的通信管道为/turtle/cmd_vel,只要实现一个发布者在通信管道/turtle/cmd_vel发送相应信息都会被订阅者订阅,下面将介绍如何查看发布消息的类型

第三步查看发布消息的列表

查看发布消息的列表

$ rosnode list 

查看发布消息的类型
我们可以看到发布者/teleop_turtle

然后输入下列指令

$ rosnode info /teleop_turtle 

然后输入下列指令我们可以看到

Publications: 
 * /rosout [rosgraph_msgs/Log]
 * /turtle1/cmd_vel [geometry_msgs/Twist]

其中 /turtle1/cmd_vel [geometry_msgs/Twist]是我们要的信息
以 /turtle1/cmd_vel消息管道,以geometry_msgs::Twist传递消息

Services: 
 * /teleop_turtle/get_loggers
 * /teleop_turtle/set_logger_level

这里面可以看到/teleop_turtle,该为发布者的节点名

第四步创建发布者Publishser

创建发布者Publishser

//以 /turtle1/cmd_vel消息管道,以geometry_msgs::Twist传递消息
// /teleop_turtle,该为发布者的节点名
// linear线性的  angular角度的
//%0.2f打印geometry_msgs::Twist类型
#include "ros/ros.h"
#include "geometry_msgs/Twist.h"

int main(int argc, char **argv){
    //初始化ros节点
    ros::init(argc, argv, "Publisher");//也可以将Publisher改为/teleop_turtle
    //创建节点句柄
    ros::NodeHandle node;

    //创建一个发布者Publisher,消息管道/turtle1/cmd_vel,消息类型geometry_msgs::Twist
    ros::Publisher pub = node.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1000);

    //设置一个循环频率每秒5次
    ros::Rate loop_rate(5);

    //计数发布次数
    int count = 0;
    while (ros::ok()){
        //初始化消息类型geometry_msgs::Twist
        geometry_msgs::Twist msg;
        msg.linear.x = 5;
        msg.angular.z = 1;

        //发布消息
        pub.publish(msg);

        //发布成功在该节点终端显示
        //已成功发布第%d条消息,发布的内容为%0.2f打印geometry_msgs::Twist类型
        ROS_INFO("Successfully published message %d with:[msg.linear.x = %0.2f m/s , msg.angular.z = %.2f rad/s]"
                ,count , msg.linear.x, msg.angular.z);

        loop_rate.sleep();
        ++count;
    }
    return 0;
}

发布者运行结果:

创建Publishser

第五步创建订阅者Sbuscriber

创建订阅者Sbuscriber
创建订阅者由图像可知,消息管道为/turtle1/cmd_vel
消息类型为geometry_msgs::Twist

 * /turtlesim/get_loggers
 * /turtlesim/set_logger_level

节点名为/turtlesim

/*
 * 消息管道为/turtle1/cmd_vel 消息类型为geometry_msgs::Twist
 * 节点名为  /turtlesim
 */

#include "ros/ros.h"
#include "geometry_msgs/Twist.h"

void cmdCallBack(const geometry_msgs::Twist& msg){
    //将收到的消息打印出来
    ROS_INFO("The message I received was:[x=%0.2f m/s, z=%0.2f rad/s]"
            , msg.linear.x, msg.angular.z);
}

int main(int argc, char **argv){
    //初始化ros节点
    ros::init(argc, argv, "Subscriber");//节点名也可以写成/turtlesim
    //创建节点句柄
    ros::NodeHandle node;

    //创建一个Subscriber,消息管道为/turtle1/cmd_vel,注册回调函数为cmdCallBack
    ros::Subscriber sub = node.subscribe("/turtle1/cmd_vel", 1000, cmdCallBack);
    ros::spin();

    return 0;
}

订阅者运行结果:

运行结果

扩展:发布hello_n_word并订阅

通过上面的内容实现,不通过小海龟信息管道,自己定义一个,来实现发布者发布hello_n_word ,n为数字并打印在自己终端,订阅者接收并打印出该消息。

第一步:模拟发布者

//以 /talker消息管道,以std_msgs::String传递消息
// /Publisher,该为发布者的节点名
// %s打印std_msgs::String类型

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

int main(int argc, char **argv){
    //初始化ros节点
    ros::init(argc, argv, "Publisher");
    //创建节点句柄
    ros::NodeHandle node;

    //创建一个发布者Publisher,消息管道/turtle1/cmd_vel,消息类型std_msgs::String
    ros::Publisher pub = node.advertise<std_msgs::String>("/talker",1000);

    //设置一个循环频率每秒5次
    ros::Rate loop_rate(5);

    //计数发布次数
    int count = 0;
    while (ros::ok()){
        ++count;
        //初始化消息类型std_msgs::String
        std_msgs::String msg;
        std::stringstream ss;
        ss<< "hello_"<< ++count<<"_world";
        msg.data = ss.str();
        //发布消息
        pub.publish(msg);

        //发布成功在该节点终端显示
        //已成功发布第%d条消息,发布的内容为%s打印std_msgs::String类型
        ROS_INFO("Successfully published message with:[%s]",msg.data.c_str());

        loop_rate.sleep();

    }
    return 0;
}

第二步:模拟订阅者

/*
 * 消息管道为/talker 消息类型为std_msgs::String
 * 节点名为  /Subscriber
 */

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

void cmdCallBack(const std_msgs::String::ConstPtr& msg){
    //将收到的消息打印出来
    ROS_INFO("The message I received was:[%s]",msg->data.c_str());
}

int main(int argc, char **argv){
    //初始化ros节点
    ros::init(argc, argv, "Subscriber");
    //创建节点句柄
    ros::NodeHandle node;

    //创建一个Subscriber,消息管道为/turtle1/cmd_vel,注册回调函数为cmdCallBack
    ros::Subscriber sub = node.subscribe("/talker", 1000, cmdCallBack);
    ros::spin();

    return 0;
}

运行结果:

运行结果
运行结果

原创文章 44 获赞 8 访问量 3874

猜你喜欢

转载自blog.csdn.net/weixin_44692299/article/details/104352997
今日推荐