素材巴巴 > 程序开发 >

ROS机器人操作系统中关于消息、主题、节点、服务、启动文件的详细叙述

程序开发 2023-09-11 16:02:39

概述

首先我们先来具体认识一下这几种不同的名字代表的都是什么内容,话不多说,先roscore,然后rosrun turtlesim turtlesim_node调出小乌龟,之后在开启新终端输入rosnode info turtlesim就会出现下方图片所示内容。
调出小乌龟这其中可以看到列出的几项内容,其中
Node后边列出的是节点名称,可以看出其名字就是我们查阅的turtlesim节点。
Publications后边列出的是当前节点发布的消息。其中比较重要的是/turtle1/pose这个消息。其中turtle1可以看做当前节点中这一只小乌龟的名字(后边我们会涉及spawn服务,会出现一个窗口中不止一只乌龟的情况,那时便可理解这个名字和节点名的区别)。pose是指当前坐标。这个消息的类型是[turtlesim/Pose]。
Subscriptions是节点订阅的消息。和上述发布消息类似,消息类型是[geometry_msgs/cmd_vel]。
Services是当前节点可以接受的服务。

消息、主题、节点之间的相互关系

消息和主题是相互依赖的关系,节点把消息发布到主题,其他节点再从主题订阅相应的消息类型。

发布消息到一个主题

//我们重新创建了一个节点
 //pubvel.cpp
 #include 
 #include 
 #include int main(int argc,char **argv)
 {ros::init(argc,argv,"publish_velocity");//这个节点的名称是publish_velocityros::NodeHandle nh;//定义一个消息发布的句柄,消息类型为geometry_msgs::Twist![在这里插入图片描述](https://img-blog.csdnimg.cn/20191116122257221.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3h1ZnVxaWFuZzIwMTc=,size_16,color_FFFFFF,t_70)//并把这个消息发布到turtle1/cmd_vel这个主题中ros::Publisher pub=nh.advertise("turtle1/cmd_vel",1000);srand(time(0));ros::Rate rate(2);while(ros::ok()){geometry_msgs::Twist msg;msg.linear.x=double(rand())/double(RAND_MAX);msg.angular.z=2*double(rand())/double(RAND_MAX)-1;pub.publish(msg);rate.sleep();}
 }
 

运行这个节点,在终端输入rosnode list查看
在这里插入图片描述能够查看到以下信息,与我们在文件中设置的一样,其中geometry_msgs/Twist这个消息类型的具体内容在其中也列了出来。

从主题中接受一条信息

//subpose.cpp
 #include 
 #include 
 #include 
 //要接收的消息类型为turtleism::Pose
 void poseMessageReceived(const turtlesim::Pose& msg)
 {ROS_INFO_STREAM("the info is "<

在上一个程序运行的基础上,在运行这个程序,得到结果
在这里插入图片描述得到的结果与程序种设置的一样。接下来要进行一个对比。创建一个launch启动文件,内容设置如下:


 
 
 

其中pkg为功能包名称,type为调用的可执行文件名称,name为节点名称,这个名称将覆盖我们在cpp文件中设置的节点名称。运行结果如下
在这里插入图片描述首先是new_turtle这个节点名称覆盖了乌龟的默认节点名turtlesim,但是它订阅和发布的消息和主题名称并未改变。因为我们是改变了运行乌龟的这个节点的名称,并未改变这个节点中小乌龟自己的名字。所以当有其他节点发布同类型的消息到这个节点的时候,他还是可以接受并且做出相应动作的。
同样可以查看其他节点的详细信息,可以发现都只是改变了节点的名称,而其他均为改变。

改变接受的消息的主题

接下来尝试改变乌龟接收的消息的主题,但是消息的类型并未改变,依旧是geometry_msgs::Twist。

//reverse_cmd_vel.cpp
 #include 
 #include 
 ros::Publisher *pubPtr;
 void commandVelocityReceived(const geometry_msgs::Twist &msgin)
 {geometry_msgs::Twist msgout;msgout.linear.x=-msgin.linear.x;msgout.angular.z=-msgin.angular.z;pubPtr->publish(msgout);
 }
 int main(int argc,char **argv)
 {ros::init(argc,argv,"reverse_velocity");ros::NodeHandle nh;//从默认的turtle1/cmd_vel主题中接受消息,再以turtle1/cmd_vel_reversed为主题发送出去,利用回调函数pubPtr=new ros::Publisher(nh.advertise("turtle1/cmd_vel_reversed",1000));ros::Subscriber sub=nh.subscribe("turtle1/cmd_vel",1000,&commandVelocityReceived);ros::spin();delete pubPtr;
 }
 

接下来配置一下启动launch文件


 
 
 
 
 
 

在这其中启动了两个小乌龟节点,都对节点名进行重新设置,分别为reversed_turtle和normal_turtle。其中对reversed_turtle节点的接受消息的主题进行重新设置为turtle1/cmd_vel_reversed。之后运行启动文件。
在这里插入图片描述可以看到,turtlesim的节点名字改为了reversed_turtle,同时订阅的主题也变了和我们设置的一样。
其实到这里对于节点、消息、主题的理解应该已经深入了许多,但是我们虽然改变了节点名称,主题名称,但是关于turtle1这个参数却从未改变过,消息的类型也没有改变过。接下来我们在详细讨论。(会在最后讨论如何新建一个消息类型)

服务的加入

首先需要做到就是把之前的终端窗口全部停止关闭。重新运行一个小乌龟,再次查看rosnode info turtlesim。(或者从上面图片查看),如图:
在这里插入图片描述在services列表下边有许多属于这个节点的服务,其中有/spawn,是在不增加终端窗口的情况下,在当前窗口新增一个小乌龟。在终端输入
rosservice call /spawn 3 3 0 turtle_2
再次在终端输入查询信息:在这里插入图片描述如图产生了与turtle1地位并列的turtle_2,这是这个乌龟的订阅的主题名称也相应的改变了。这是之后我们会继续讨论的。
除了在终端直接调用服务外,我们还可以在客户端程序种调用。

spawn_turtle.cpp
 #include 
 #include 
 int main(int argc,char **argv)
 {ros::init(argc,argv,"spawn_turtle");ros::NodeHandle nh;ros::ServiceClient spawnClient=nh.serviceClient("spawn");turtlesim::Spawn::Request  req;turtlesim::Spawn::Response resp; //在命令行需要输入的是三个参数:位置,角度,名字req.x=2;req.y=3;req.theta=M_PI/2;req.name="wang";bool success=spawnClient.call(req,resp);if(success){ROS_INFO_STREAM("Spawned a turtle named "<

运行此节点,同时保持刚才的节点开启,查询:在这里插入图片描述可以看到,又增加了一个乌龟的名字“wang”。那该如何向这些处于同一个终端的龟龟发送消息呢?我们结合着待会的服务器程序一块看。

pubvel_toggle.cpp
 #include 
 #include 
 #include 
 bool forward =true;
 bool toggleForward(std_srvs::Empty::Request &req,std_srvs::Empty::Response &resp)
 {forward=!forward;ROS_INFO_STREAM("Now sending "<<(forward?"forward":"rotate")<<" commands");return true;
 }
 int main(int argc,char **argv)
 {ros::init(argc,argv,"pubvel_toggle");ros::NodeHandle nh;//定义了一个叫toggle_forward的服务。,其接受的数据为空ros::ServiceServer server=nh.advertiseService("toggle_forward",&toggleForward);//向wang/cmd_vel这个节点发送消息ros::Publisher pub =nh.advertise("wang/cmd_vel",1000);ros::Rate rate(2);while(ros::ok()){geometry_msgs::Twist msg;msg.linear.x=forward?1.0:0.0;msg.angular.z=forward?0.0:1.0;pub.publish(msg);ros::spinOnce();rate.sleep();}
 }
 

编译之后调用toggle_forward服务,先运行这个节点在调用服务。
rosservice call /toggle_forward.
你会发现其中一个开始运动了,多次调用,你会明白的。

下节看点

下节将继续ros之路,讲述如何创建新的属于自己的消息类型和服务类型,以及ros中常用的指令。


标签:

上一篇: WebStorm常用功能的使用技巧分享 下一篇:
素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。