• ROS node调用service: ros::service::call/client.call()


    简介:介绍如何在一个node里调用现有的rosservice list查询到的service。

    效果:通过talker publish需要调用服务的数据,listener接收到数据后调用服务进行三个整形数据相加,并返回相加和。

    环境:ubuntu 14.04 +indigo.

    备注:文中未详细介绍的api或ros的基本函数请参看之前博文。

    [正文]

    创建过程类似wiki教程中msg和srv的测试过程。在beginner_turtorials包下面创建。

    1,创建msg文件夹,srv文件夹。

    msg 文件夹下创建Num.msg,内容是

    int32 A

    int32 B

    int32 C

    srv文件夹下AddTwoInts.srv,内容是

    int32 A

    int32 B

    int32 C

    ---

    int32 sum

    该文件表面输入是ABC,返回是 sum,两者通过“---”分割。

    2,然后更改CMakeList.txt文件,修改为如下内容,主要设计msg,srv的其他依赖关系及编译运行的相关关系。

    ## Find catkin macros and libraries
    ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
    ## is used, also find other catkin packages
    find_package(catkin REQUIRED COMPONENTS
      roscpp
      rospy
      std_msgs
      message_generation
    )
    
    ## Generate messages in the 'msg' folder
     add_message_files(
       FILES
       Num.msg
     )
    
    
    ## Generate services in the 'srv' folder
     add_service_files(
       FILES
       AddTwoInts.srv
     )
    
    ## Generate added messages and services with any dependencies listed here
     generate_messages(
       DEPENDENCIES
       std_msgs
     )
    
    # include_directories(include)
    include_directories(
      ${catkin_INCLUDE_DIRS}
    )
    
    catkin_package(
    #  INCLUDE_DIRS include
    #  LIBRARIES beginner_tutorials
    #  CATKIN_DEPENDS roscpp rospy std_msgs
    #  DEPENDS system_lib
      CATKIN_DEPENDS message_runtime
    )
    

    也可参考,wiki中CreatingMsgAndSrv中过程,名称都没有改变,只是改变了文件中内容,改写完成后可以在catkin_ws目录下catkin_make一次,并source devel/setup.bash下。

    3,建立几个cpp的源文件,位于src目录下。

    3.1 src/example_srv_request.cpp

    作用:主要实现服务的定义,初始化,注释由于ubuntu没装汉语输入,因此注释为英文...聊胜于无。

    #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+req.C;
        ROS_INFO("request: A=%ld,B=%ld,C=%ld",(int)req.A,(int)req.B,(int)req.C);
        ROS_INFO("sending back response:[%ld]",(int)res.sum);
    
        return true;
    }
    
    
    int main(int argc,char **argv)
    {
       ros::init(argc,argv,"add_3_ints_server");
       ros::NodeHandle n;
       //init service:
       //Name: add_3_ints,advertise the service. add: call back function
       ros::ServiceServer service=n.advertiseService("add_3_ints",add);
       ROS_INFO("Ready to add 3 ints.");
       ros::spin();// start to deal with the call back event
    
       return 0;
    }
    3.2 src/example_srv_response.cpp,该文件并非必要,是典型的client调用服务的形式,并非此文目的,不添加最终目的也可实现,调用示例是(现在还不能调用):

    rosrun beginner_tutorials example_srv_response 1 2 3

    #include "ros/ros.h"
    #include "beginner_tutorials/AddTwoInts.h"
    #include <cstdlib>
    
    
    int main(int argc,char **argv)
    {
        ros::init(argc,argv,"add_3_ints_client");
        if(argc != 4)
        {
            ROS_INFO("usage: add_3_ints_client A B C");
            return 1;
        }
        ros::NodeHandle n;
        ros::ServiceClient client=n.serviceClient<beginner_tutorials::AddTwoInts>("add_3_ints");
    
        beginner_tutorials::AddTwoInts srv;
    
        //atoll:convert a string to long long int variable
        srv.request.A=atoll(argv[1]);
        srv.request.B=atoll(argv[2]);
        srv.request.C=atoll(argv[3]);
    
    
        if(client.call(srv))
        {
            ROS_INFO("Sum:%ld",(long int)srv.response.sum);
        }
        else
        {
            ROS_ERROR("Failed to call service add_three_ints");
            return 1;
    
        }
        return 0;
    }
    
    3.3 src/example_talker_msg.cpp

    该文件主要实现3个参数的发布,此处发布了A=1,B=2,C=3;

    #include "ros/ros.h"
    #include "beginner_tutorials/Num.h"
    #include <sstream>
    //Usage:publish a msg with topic named message
    
    
    int main(int argc, char **argv)
    {
      ros::init(argc, argv, "example_talker_msg");
      ros::NodeHandle n;
      //advertise a topic named "message"
      ros::Publisher pub=n.advertise<beginner_tutorials::Num>("message",1000);
      ros::Rate loop_rate(10);
      while (ros::ok())
      {
        beginner_tutorials::Num msg;
        msg.A=1;
        msg.B=2;
        msg.C=3;
        pub.publish(msg);
    
        ros::spinOnce();
        loop_rate.sleep();
      }
      return 0;
    }
    
    3.4 src/example_listener_msg.cpp

    该文件主要实现对前文talker发布的数据的监听,监听到Num类型定义数据后,通过service: ros::service::call / client.call()两种方式进行add_3_ints服务的调用。

    #include "ros/ros.h"
    #include "beginner_tutorials/Num.h"
    #include "beginner_tutorials/AddTwoInts.h"
    
    //declaration of the Example class:construct function, member and so on.
    class Example{
    public:
        Example();
    private:
        ros::NodeHandle nh;
        ros::ServiceClient client;
        ros::Subscriber listener;
        void messageCallback(const beginner_tutorials::Num::ConstPtr& msg);
    
    };
    
    //implementation of construct function.
    Example::Example()
    {
        client=nh.serviceClient<beginner_tutorials::AddTwoInts>("add_3_ints");
        //monitor a topic named "message",this -> current object,pointer
        listener=nh.subscribe("message",1000,&Example::messageCallback,this);
    
    }
    
    //implementation of one of the Example class memeber.
    void Example::messageCallback( const beginner_tutorials::Num::ConstPtr& msg)
    {
    //    ROS_INFO("I heard:[%d] [%d] [%d]",msg->A,msg->B,msg->C);
        beginner_tutorials::AddTwoInts srv;
        srv.request.A=msg->A;
        srv.request.B=msg->B;
        srv.request.C=msg->C;
        if(ros::service::call("add_3_ints",srv))
            ROS_INFO("SUM: %ld",(long int)srv.response.sum);
        else
            ROS_ERROR("Failed to call service add_three_ints");
        /*
        if(client.call(srv))
        {
            ROS_INFO("SUM: %ld",(long int)srv.response.sum);
        }
        else
        {
            ROS_ERROR("Failed to call service add_three_ints");
    
        }
        */
    }
    
    
    
    int main(int argc, char **argv)
    {
      ros::init(argc, argv, "example_listener_msg");
      Example exp;
      ros::spin();
      return 0;
    }
    
    4 再次修改CMakeList.txt文件
    添加编译链接的相关控制语句。

    add_executable(example_srv_request src/example_srv_request.cpp)
    target_link_libraries(example_srv_request ${catkin_LIBRARIES})
    
    add_executable(example_srv_response src/example_srv_response.cpp)
    target_link_libraries(example_srv_response ${catkin_LIBRARIES})
    
    add_executable(example_talker_msg src/example_talker_msg.cpp)
    target_link_libraries(example_talker_msg ${catkin_LIBRARIES})
    
    add_executable(example_listener_msg src/example_listener_msg.cpp)
    target_link_libraries(example_listener_msg ${catkin_LIBRARIES})
    添加后在工作空间主目录cd ~/catkin_ws下进行catkin_make编译,理论上不会出现问题,若有问题检查自己包和msg,srv的生成及cmakelist文件。
    5 测试

    一个终端运行命令:roscore,

    一个终端运行命令(注意此时近乎所有命令和包的名称及可执行文件名称都可以<table>自动补全):rosrun beginner_tutorials example_srv_request;会返回:  [INFO][时间戳]:Ready to add 3 ints.  此时若通过roservice list查询ros提供的服务则会返回add_3_ints等几个服务。

    一个终端运行命令:rosrun beginner_tutorials example_talker_msg

    一个终端运行命令:rosrun beginner_tutorials example_listener_msg;此时会返回: [INFO][时间戳]:SUM: 6

    在此文件中,我们实现了在一个node中以下面两种方式对add_3_ints的服务调用,而不是在命令行中通过rosrun beginner_tutorials example_srv_response 1 2 3调用。

     if(ros::service::call("add_3_ints",srv))
            ROS_INFO("SUM: %ld",(long int)srv.response.sum);
        else
            ROS_ERROR("Failed to call service add_three_ints");
        /*
        if(client.call(srv))
        {
            ROS_INFO("SUM: %ld",(long int)srv.response.sum);
        }
        else
        {
            ROS_ERROR("Failed to call service add_three_ints");
    
        }
        */






  • 相关阅读:
    C#多线程操作界面控件的解决方案
    InvokeHelper,让跨线程访问/修改主界面控件不再麻烦
    .netCF中后台多线程与UI界面交互的冻结问题
    c#设计模式第一天
    C#代理
    界面
    第一章面向对象涉及原则
    C# 为webBrowser设置代理
    设计模式等
    下载: Intel® 64 and IA32 Architectures Software Developer Manuals
  • 原文地址:https://www.cnblogs.com/siahekai/p/5840316.html
Copyright © 2020-2023  润新知