1、创建流程文字描述:
发布者:
初始化ROS节点 -->向ROS Master注册节点信息(发布的话题名、话题中的消息类型) --> 按照一定频率循环发布信息。
订阅者:
初始化ROS节点 -->订阅需要订阅的话题--> 循环等待话题消息、接收到消息之后进入回调函数--> 在回调函数中完成消息处理
2、创建流程具体代码分析:
发布者:
主函数中初始化ROS节点:
ros::init(argc,argv,”发布者节点名”)
向ROS Master注册节点,其中分为两步骤:句柄的创建 + 句柄的实例化
ros::NodeHandle n;
ros::Publisher chatter_pub=n.advertise<std_msgs::String>(“话题名”,发布者队列长度) :句柄用于接受相关的资源,发布者被句柄初始化;句柄初始化的消息类型是std_msgs::String的一个消息接口,传的参数是“话题名”+“队列长度”;此处设置的队列长度的目的是缓存来不及发送或接收的数据。
按照一定的频率循环地发布消息,分为两步:设置循环频率 + 编写发布的具体内容
ros::Rate loop_rate(10); 设置循环频率为10Hz
while(ros::ok())
{
std_mags::String msg; //初始化之前定义的消息
std::stringstream ss;
ss<<”hello woorld!”<<count
msg.data=ss.str();
ROS_INFO(“%s”,msg.data.c_strr());
chatter_pub.publish(msg);
//循环等待回调函数 ,在发布者中可要可不要这个函数
ros::spinOnce()
//按照循环频率延时
loop_rate.sleep();
++count;
}
备注:ros::spinOnce() 与ros::spin()的用法及区别:
https://www.cnblogs.com/liu-fa/p/5925381.html
订阅者:
初始化ros节点:
ros::init(argc,argv,”订阅者节点名”)
订阅话题名:分为两步:初始化句柄 + 订阅实例化
ros:NodeHandle n;
ros::Subscriber sub=n.subscribe(“订阅话题名”,消息缓冲池大小,回调函数名)
循环等待话题消息,有消息则进入消息回调函数,并在回调函数中对消息进行处理。
ros::spin(); //该函数一旦进入,将不会返回,会一直循环等待回调函数
void 回调函数名(const std_msgs::String::ConstPtr& msg)
{
//对消息进行处理;比如打印消息
ROS_INFO(“I heard:[%s]”,msg->data.c_str());
}
备注:ros:spin() 和 回调函数的关系:
https://blog.youkuaiyun.com/liweibin1994/article/details/53084306
当订阅者知道布者发布消息之后,其将发布的消息data作为参数传给回调函数中,并将回调函数放入一个回调函数队列中,并非马上执行。想要执行回调函数,必须通过ros::spin()或者是ros::spinOnce()。两者的共同点是:执行一次,那么就会选择处于回调函数队列中最前面的回调函数。通常回调函数队列的长度是有限的,所以需要考虑处理的频率。
3、编译代码:
设置要编译的代码和生成的可执行文件、设置链接库、设置依赖
add_executable(可执行文件名src/源文件名.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_message_cpp)