• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

ROS中编写服务器和客户端的方法(C++版)

人工智能 宗孝鹏 1713次浏览 0个评论

参考:http://wiki.ros.org/cn/ROS/Tutorials/CreatingMsgAndSrv 参考:http://wiki.ros.org/cn/ROS/Tutorials/WritingServiceClient%28c%2B%2B%29   要注意在ROS中有catkin和rosbuild两种创建程序包的方法,关于catkin与rosbuild的区别,可参考博客http://blog.csdn.net/chishuideyu/article/details/53581013 个人感觉意思就是说catkin比rosbuild的方法要更鲁棒一些,因此选择catkin的方法创建包,在编译的时候不要把这两种给混淆  

一、创建catkin工作空间

 

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make

  创建好后,将会在src路径下生成CMakeLists.txt,并且在src的上一级文件夹中生成build和devel的文件夹,在devel文件夹中会看到几个setup.*sh文件,然后将这些文件的路径添加到环境变量中,为了避免每次都添加,直接在~/.bashrc文件的末尾添加以下语句即可  

source ~/catkin_ws/devel/setup.bash

  为了确保工作空间正确的添加,可以输出环境变量查看,是否有新建的工作空间catkin_ws  

echo $ROS_PACKAGE_PATH

 

二、创建catkin程序包

  在新建的工作空间中的src目录下,创建一个新的程序包,这个程序包依赖于std_msgs、roscpp和rospy  

cd src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

  这将会创建一个名为beginner_tutorials的文件夹,这个文件夹里面包含一个package.xml文件和一个CMakeLists.txt文件,这两个文件都已经自动包含了部分你在执行catkin_create_pkg命令时提供的信息   新打开一个终端,运行命令,查看功能包是否创建  

rospack find beginner_tutorials

 

三、在包中创建一个服务:

 

roscd beginner_tutorials
mkdir srv

  在srv文件下创建AddTwoInts.srv的文件,内容如下:  

int64 a
int64 b
---
int64 sum

  还有很关键的一步:我们要确保srv文件被转换成C++,Python和其他语言的源代码。 查看package.xml, 确保它包含以下两条语句  

  <build_depend>message_generation</build_depend>
  <run_depend>message_runtime</run_depend>

  如果没有,添加进去。 注意,在构建的时候,我们只需要”message_generation”。然而,在运行的时候,我们只需要”message_runtime”。 现在认为,你已经如前边所介绍的,在CMakeLists.txt文件中增加对message_generation的依赖:  

# Do not just add this line to your CMakeLists.txt, modify the existing line
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation)

  (对的, message_generation 对msg和srv都起作用) 然后删掉#,去除对下边语句的注释(没有的话在文件末尾添加):  

# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

  用你自己的srv文件名替换掉那些Service*.srv文件:  

add_service_files(
  FILES
  AddTwoInts.srv
)

 

现在,你可以生成自己的服务源代码了。  

四、使用服务

 

以上就是创建一个服务所需的所有步骤。下面通过rosmsg show命令,检查ROS是否能够识该服务。   使用方法:  

rossrv show <service type>

  例子:  

rossrv show beginner_tutorials/AddTwoInts

  你将会看到:

int64 a
int64 b
---
int64 sum

  你也可以不指定具体的package名来查找服务文件:  

$ rossrv show AddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum
 
[rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum

  接下来,在CMakeLists.txt中找到如下部分:  

# generate_messages(
#   DEPENDENCIES
# #  std_msgs  # Or other packages containing msgs
# )

  去掉注释并附加上所有你消息文件所依赖的那些含有.msg文件的package(这个例子是依赖std_msgs,不要添加roscpp,rospy),结果如下  

generate_messages(
  DEPENDENCIES
  std_msgs
)

  由于增加了新的消息,所以我们需要重新编译我们的package:  

# In your catkin workspace
cd ~/catkin_ws/
catkin_make
cd -

  所有在msg路径下的.msg文件都将转换为ROS所支持语言的源代码。生成的C++头文件将会放置在~/catkin_ws/devel/include/beginner_tutorials/。 Python脚本语言会在 ~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg 目录下创建。 lisp文件会出现在 ~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/ 路径下.  

五、编写Service节点

  这里,我们将创建一个简单的service节点(“add_two_ints_server”),该节点将接收到两个整形数字,并返回它们的和。   首先进入所创建的beginner_tutorials包所在的目录:  

roscd beginner_tutorials

  在beginner_tutorials包中创建src/add_two_ints_server.cpp文件,并复制粘贴下面的代码:  

#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
 
bool add(beginner_tutorials::AddTwoInts::Request  &req,
         beginner_tutorials::AddTwoInts::Response &res)
{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}
 
int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_server");
  ros::NodeHandle n;
 
  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  ROS_INFO("Ready to add two ints.");
  ros::spin();
 
  return 0;
}

  现在,让我们来逐步分析代码。  

#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"

  beginner_tutorials/AddTwoInts.h是由编译系统自动根据我们先前创建的srv文件生成的对应该srv文件的头文件。  

bool add(beginner_tutorials::AddTwoInts::Request  &req,
         beginner_tutorials::AddTwoInts::Response &res)

  这个函数提供两个int值求和的服务,int值从request里面获取,而返回数据装入response内,这些数据类型都定义在srv文件内部,函数返回一个boolean值。  

{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}

  现在,两个int值已经相加,并存入了response。然后一些关于request和response的信息被记录下来。最后,service完成计算后返回true值。  

  ros::ServiceServer service = n.advertiseService("add_two_ints", add);

  这里,service已经建立起来,并在ROS内发布出来。  

六、编写Client节点

  在beginner_tutorials包中创建src/add_two_ints_client.cpp文件,并复制粘贴下面的代码:  

#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
#include <cstdlib>
 
int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_client");
  if (argc != 3)
  {
    ROS_INFO("usage: add_two_ints_client X Y");
    return 1;
  }
 
  ros::NodeHandle n;
  ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
  beginner_tutorials::AddTwoInts srv;
  srv.request.a = atoll(argv[1]);
  srv.request.b = atoll(argv[2]);
  if (client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
 
  return 0;
}

  现在,让我们来逐步分析代码。  

  ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");

  这段代码为add_two_ints service创建一个client。ros::ServiceClient 对象待会用来调用service。  

  beginner_tutorials::AddTwoInts srv;
  srv.request.a = atoll(argv[1]);
  srv.request.b = atoll(argv[2]);

  这里,我们实例化一个由ROS编译系统自动生成的service类,并给其request成员赋值。一个service类包含两个成员request和response。同时也包括两个类定义Request和Response。

  if (client.call(srv))

  这段代码是在调用service。由于service的调用是模态过程(调用的时候占用进程阻止其他代码的执行),一旦调用完成,将返回调用结果。如果service调用成功,call()函数将返回true,srv.response里面的值将是合法的值。如果调用失败,call()函数将返回false,srv.response里面的值将是非法的。  

七、编译节点

  再来编辑一下beginner_tutorials里面的CMakeLists.txt,文件位于~/catkin_ws/src/beginner_tutorials/CMakeLists.txt,并将下面的代码添加在文件末尾:  

add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp)
 
add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)

  这段代码将生成两个可执行程序”add_two_ints_server”和”add_two_ints_client”,你可以直接调用可执行程序,或者使用rosrun命令去调用它们。它们不会被装在<prefix>/bin目录下,因为当你在你的系统里安装这个包的时候,这样做会污染PATH变量。如果你希望在安装的时候你的可执行程序在PATH变量里面,你需要设置一下install target 现在运行catkin_make命令:  

# In your catkin workspace
cd ~/catkin_ws
catkin_make

 

八、测试节点

首先运行Service:  

rosrun beginner_tutorials add_two_ints_server

  然后运行Client并附带一些参数:  

rosrun beginner_tutorials add_two_ints_client 1 3

  你将会看到如下类似的信息:  

request: x=1, y=3
sending back response: [4]


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明ROS中编写服务器和客户端的方法(C++版)
喜欢 (0)

您必须 登录 才能发表评论!

加载中……