个人觉得,和前面话题的发布和订阅没有很大的区别,所以这一节主要将内容集中在总结上。
一、实验任务通过C++代码创建一个客户端,该客户端通过向海龟可视化界面应用中的请求/spawn
服务,在指定位置产生一个新的海龟。 整个流程总结如下:
#mermaid-svg-XLHKdz9AtxR7k1Ic {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .error-icon{fill:#552222;}#mermaid-svg-XLHKdz9AtxR7k1Ic .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XLHKdz9AtxR7k1Ic .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .marker.cross{stroke:#333333;}#mermaid-svg-XLHKdz9AtxR7k1Ic svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XLHKdz9AtxR7k1Ic .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .cluster-label text{fill:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .cluster-label span{color:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .label text,#mermaid-svg-XLHKdz9AtxR7k1Ic span{fill:#333;color:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .node rect,#mermaid-svg-XLHKdz9AtxR7k1Ic .node circle,#mermaid-svg-XLHKdz9AtxR7k1Ic .node ellipse,#mermaid-svg-XLHKdz9AtxR7k1Ic .node polygon,#mermaid-svg-XLHKdz9AtxR7k1Ic .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XLHKdz9AtxR7k1Ic .node .label{text-align:center;}#mermaid-svg-XLHKdz9AtxR7k1Ic .node.clickable{cursor:pointer;}#mermaid-svg-XLHKdz9AtxR7k1Ic .arrowheadPath{fill:#333333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XLHKdz9AtxR7k1Ic .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XLHKdz9AtxR7k1Ic .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XLHKdz9AtxR7k1Ic .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XLHKdz9AtxR7k1Ic .cluster text{fill:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic .cluster span{color:#333;}#mermaid-svg-XLHKdz9AtxR7k1Ic div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XLHKdz9AtxR7k1Ic :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
二、实验过程
2.1 创建一个package
开始
创建package
编写服务端代码
修改CMakeLists.txt并编译
启动核心和应用
结束
到工作空间下的src中使用catkin_create_pkg
创建一个新的功能包:
catkin_create_pkg service_test roscpp std_msgs geometry_msgs turtlesim
注意添加上本次实验要用到的turtlesim功能包,roscpp、std_msgs 和geometry_msgs都是功能包。
2.2 编写服务端代码无论是话题还是服务,无论是发起端还是请求端,基本过程都类似,总结如下:
#mermaid-svg-AYRD57fRuHHvesdv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-AYRD57fRuHHvesdv .error-icon{fill:#552222;}#mermaid-svg-AYRD57fRuHHvesdv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AYRD57fRuHHvesdv .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-AYRD57fRuHHvesdv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AYRD57fRuHHvesdv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AYRD57fRuHHvesdv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AYRD57fRuHHvesdv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AYRD57fRuHHvesdv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AYRD57fRuHHvesdv .marker.cross{stroke:#333333;}#mermaid-svg-AYRD57fRuHHvesdv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AYRD57fRuHHvesdv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AYRD57fRuHHvesdv .cluster-label text{fill:#333;}#mermaid-svg-AYRD57fRuHHvesdv .cluster-label span{color:#333;}#mermaid-svg-AYRD57fRuHHvesdv .label text,#mermaid-svg-AYRD57fRuHHvesdv span{fill:#333;color:#333;}#mermaid-svg-AYRD57fRuHHvesdv .node rect,#mermaid-svg-AYRD57fRuHHvesdv .node circle,#mermaid-svg-AYRD57fRuHHvesdv .node ellipse,#mermaid-svg-AYRD57fRuHHvesdv .node polygon,#mermaid-svg-AYRD57fRuHHvesdv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AYRD57fRuHHvesdv .node .label{text-align:center;}#mermaid-svg-AYRD57fRuHHvesdv .node.clickable{cursor:pointer;}#mermaid-svg-AYRD57fRuHHvesdv .arrowheadPath{fill:#333333;}#mermaid-svg-AYRD57fRuHHvesdv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AYRD57fRuHHvesdv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AYRD57fRuHHvesdv .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-AYRD57fRuHHvesdv .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-AYRD57fRuHHvesdv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AYRD57fRuHHvesdv .cluster text{fill:#333;}#mermaid-svg-AYRD57fRuHHvesdv .cluster span{color:#333;}#mermaid-svg-AYRD57fRuHHvesdv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AYRD57fRuHHvesdv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
开始
初始化节点
创建节点句柄
输入输出数据准备
等待或者返回结果
结束
在对一个应用进行服务请求前,可以通过rosserive list
查看当前可以使用的服务(注意,应用需要启动才能看到): 因为请求服务必须得知道约定的数据格式是什么,所以我们可以通过
rosservice info + 服务名
查看服务约定的参数有哪些格式。这里我查看了/spawn
服务的信息: 为了进一步得到这个数据具体格式需要用到
rosservice type /spawn
+rossrv show
: 可以很清楚的看出各参数的类型,具体含义需要查看服务是如何定义的,这里:
x
y
theta
代表新海龟的位置和角度,name
表示海龟名字(可以让程序自动生成)。
#include
#include
int main(int argc,char ** argv)
{
//初始化节点
ros::init(argc,argv,"requestNewLife");
ros::NodeHandle node;
//利用节点管理器node创建一个客户端
ros::service::waitForService("/spawn");//话题阻塞至服务启动
ros::ServiceClient client=node.serviceClient("/spawn");//模板参数是在语言层面上的,参数是实际通信层面的
//准备数据
turtlesim::Spawn srv;
srv.request.x=2.0;
srv.request.y=2.0;
srv.request.name="NewTurtle";
ROS_INFO("Requesting new turtle name= %s, at [%f,%f,%f]",
srv.request.name.c_str(),srv.request.x,srv.request.y,srv.request.theta);
//客户端数据输出操作
client.call(srv);
ROS_INFO("A new turtle created!");
return 0;
}
2.3 修改CMakeLists.txt并编译
新增以下语句:
add_executable(callforNewlife src/requestNewTurtle.cpp)
target_link_libraries(callforNewlife ${catkin_LIBRARIES})
回到工作空间根目录,catkin_make
,如无意外,显示结果如下:
roscore
rosrun turtlesim turtlesim_node
rosrun service_test callforNewlife
果然产生了一个小乌龟:
[1] https://www.ncnynl.com/archives/201608/503.html