节点是一个可执行程序,它连接到了ROS的网络系统中。我们将会创建一个发布者,也就是说话者节点,它将会持续的广播一个信息。
改变目录到之前所建立的那个包下:
cd ~/catkin_ws/src/beginner_tutorials
mkdir -p ~/catkin_ws/src/beginner_tutorials/src
vim src/talker.cpp
#include "ros/ros.h" #include "std_msgs/String.h" #include <sstream> /** * This tutorial demonstrates simple sending of messages over the ROS system. */ int main(int argc, char **argv) { /** * The ros::init() function needs to see argc and argv so that it can perform * any ROS arguments and name remapping that were provided at the command line. For programmatic * remappings you can use a different version of init() which takes remappings * directly, but for most command-line programs, passing argc and argv is the easiest * way to do it. The third argument to init() is the name of the node. * * You must call one of the versions of ros::init() before using any other * part of the ROS system. */ ros::init(argc, argv, "talker"); /** * NodeHandle is the main access point to communications with the ROS system. * The first NodeHandle constructed will fully initialize this node, and the last * NodeHandle destructed will close down the node. */ ros::NodeHandle n; /** * The advertise() function is how you tell ROS that you want to * publish on a given topic name. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. After this advertise() call is made, the master * node will notify anyone who is trying to subscribe to this topic name, * and they will in turn negotiate a peer-to-peer connection with this * node. advertise() returns a Publisher object which allows you to * publish messages on that topic through a call to publish(). Once * all copies of the returned Publisher object are destroyed, the topic * will be automatically unadvertised. * * The second parameter to advertise() is the size of the message queue * used for publishing messages. If messages are published more quickly * than we can send them, the number here specifies how many messages to * buffer up before throwing some away. */ ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); ros::Rate loop_rate(10); /** * A count of how many messages we have sent. This is used to create * a unique string for each message. */ int count = 0; while (ros::ok()) { /** * This is a message object. You stuff it with data, and then publish it. */ std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str(); ROS_INFO("%s", msg.data.c_str()); /** * The publish() function is how you send messages. The parameter * is the message object. The type of this object must agree with the type * given as a template parameter to the advertise<>() call, as was done * in the constructor above. */ chatter_pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); ++count; } return 0; }
解释一下代码:
#include "ros/ros.h"
#include "std_msgs/String.h"
这条代码包括了std_msgs/String消息,它存在于std_msgs包中。这是有std_msgs中的String.msg文件自动产生的。
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
NodeHandle::advertise()将会返回ros::Publisher对象,该对象有两个作用,首先是它包括一个publish()方法可以在制定的话题上发布消息,其次,当超出范围之外的时候就会自动的处理。
ros::Rate loop_rate(10);
int count = 0; while (ros::ok()) {
ros::ok()在以下几种情况下也会返回false:(1)按下Ctrl-C时(2)我们被一个同名同姓的节点从网络中踢出(3)ros::shutdown()被应用程序的另一部分调用(4)所有的ros::NodeHandles都被销毁了。一旦ros::ok()返回false,所有的ROS调用都会失败。
std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str();
chatter_pub.publish(msg);
ROS_INFO("%s", msg.data.c_str());
ros::spinOnce();
loop_rate.sleep();
下面总结一下创建一个发布者节点的步骤:(1)初始化ROS系统(2)告诉主机我们将要在chatter话题上发布std_msgs/String类型的消息(3)循环每秒发送10次消息。