经过一段时间ROS的学习,对ROS有了一些了解。
ROS的核心是节点(node)间的通信,节点是一种使用ROS的中间件进行通信的ROS程序,一个节点可以独立于其他节点启动,
多个节点也可以任何顺序启动,多个节点可以运行在同一台计算机中,或者分布于一个计算机网络中,但一个节点只有当与其他
节点通信并最终与传感器和执行器连接时,它才是有用的。
节点之间的通信涉及了message、topic、roscore、publisher和subscriber(service同样有用,而且这些与发布器和订阅器紧密相关),
节点间所有通信都是系列化的网络通信。
一个节点既可以是订阅器,也可以是发布器。例如,一个控制节点既是一个需要接收传感器信号的订阅器,同样也是一个发布控制指令的发布器,
这只需要在同一个节点内同时实例化订阅器对象和发布器对象即可,将消息管道化有利于进行顺序处理。例如,底层图像处理程序(比如边缘检测)
会订阅原始相机数据并发布底层的处理后的图像,更高层的一个节点会订阅这些处理后的边缘图像,寻找这个图像中的特定形状,并发布它的结果
(比如识别出来的形状)以便给更高层的处理程序做进一步的处理,执行连续层级处理的一组节点序列可以一次更换一个节点进行增量式修改,新节点
只需继续使用同样的输入和输出话题名和消息类型,就可以替换点整个链条中的一个环节,尽管在修改过的节点中的算法会有显著不同,但链条中的其他节点不会受影响。
下面我将详细介绍最小发布器和最小订阅器的设计,以及如何通过关联文件package.xml和CMakeLists.txt中的指令进行编译和代码链接。
最小发布器文件名为:minimal_publisher.cpp 代码如下:
1 #include <ros/ros.h>
2 #include <std_msgs/Float64.h>
3
4 int main(int argc, char **argv) {
5 ros::init(argc, argv, "minimal_publisher"); // name of this node will be "minimal_publisher"
6 ros::NodeHandle n; // two lines to create a publisher object that can talk to ROS
7 ros::Publisher my_publisher_object = n.advertise<std_msgs::Float64>("topic1", 1);
8 //"topic1" is the name of the topic to which we will publish
9 // the "1" argument says to use a buffer size of 1; could make larger, if expect network backups
10
11 std_msgs::Float64 input_float; //create a variable of type "Float64",
12 // as defined in: /opt/ros/indigo/share/std_msgs
13 // any message published on a ROS topic must have a pre-defined format,
14 // so subscribers know how to interpret the serialized data transmission
15
16 input_float.data = 0.0;
17
18
19 // do work here in infinite loop (desired for this example), but terminate if detect ROS has faulted
20 while (ros::ok())
21 {
22 // this loop has no sleep timer, and thus it will consume excessive CPU time
23 // expect one core to be 100% dedicated (waste fully) to this small task
24 input_float.data = input_float.data + 0.001; //increment by 0.001 each iteration
25 my_publisher_object.publish(input_float); // publish the value--of type Float64--
26 //to the topic "topic1"
27 }
28 }
29
分析一下代码:
#include<ros/ros.h>
引入核心ROS库的头文件。
#include<std_msgs/Float64.h>
引入描述对象类型std_msgs::Float64的头文件,它是我们在这个示例代码中会用到的消息类型,
随着加入使用更多的ROS消息类型或ROS库,你需要将他们相关的头文件包含代码中。
int main(int argc, char **argv)
声明了一个main函数,对于所有C++编写的ROS节点,每个节点必须且只能有一个main()函数
ros::init(argc, argv, "minimal_publisher")
引用了在ROS库中定义的函数和对象,在ROS系统中,新节点会被使用参数minimal_publisher作为自己的新名字在启动中被注册,
节点必须要有名字,系统中的每个节点的名字也必须不一样。
ros::NodeHandle n;
声明实例化了一个ROS NodeHandle对象 ,需要NodeHandle建立节点间的网络通信,NodeHandle的名字n可以随意命名。
ros::Publisher my_publisher_object = n.advertise<std_msgs::Float64>("topic1", 1);
实例化名为my_publisher_objest的对象,在实例化对象中,ROS系统收到通知,当前节点(这里称之为minimal_publisher)打算在名为topic1的话题上发布
std_msgs::Float64类型的消息。
std_msgs::Float64 input_float;
创建了一个std_msgs::Float64类型对象,并命名为input_float,需要在std_msgs中查阅消息定义才能了解如何使用这个对象。
input_float.data = 0.0;
程序将input_float的data成员初始化为0.0值。
my_publisher_object.publish(input_float);
它在之前已经建立(来自类ros::Pulisher的对象my_publisher_objest的实例化),my_publisher_object会把std_msgs::Float64
类型的消息发布到名为topic1的话题上,发布器对象my_publisher_objest有成员函数publish来调用发布,发布器期望一个兼容类型
的参数,因为对象input_float属于类型std_msgs::Float64,而且由于发布器对象实例化成该类型的参数,所以publish函数调用是一致的。
原文:https://www.cnblogs.com/tanshengjiang/p/12347906.html