zoukankan      html  css  js  c++  java
  • actionlib学习

    ROS中的服务service是一问一答的形式,你来查询了,我就返给你要的信息。
    action也有服务的概念,但是它不一样的地方是:不是一问一答,而多了一个反馈,它会不断反馈项目进度。

    如navigation下的move_base package,你设定了目标点,反馈信息可能是机器人在规划路径上的即时位姿,

    直到机器人到达目标点,返回SUCCEEDED消息。

    上面所述的 ActionClient 和 ActionServer 通过 ROS Action Protocol (ROS Action 协议,建立在ROS messages的基础上)来通信。

    Client&Server 为用户提供了简单的API,通过函数的调用和回调,用来在client端request一个目标,或者,在server端来执行达成一个目标。

    下图说明这个机制如何运行:

    Action Specification: Goal, Feedback, & Result

    Goal

    为了用actions机制完成一个任务,我们引入了the notion of a goal, 这个goal可以被ActionClient发送到ActionServer. 比如在move base

    这个案例中,它的类型是PoseStamped,包含了机器人应该到达的哪里的信息。在激光扫描云台控制案例中,the goal会包含扫描的参数

    (min angle, max angle, speed 等)

    Feedback

    Feedback是server用来告诉ActionClient goal执行过程中的各种情况。在moving_base案例中,它是机器人现在的位姿;

    在controlling the tilting laser scanner案例中, this might be the time left until the scan completes(扫描剩余时间).

    Result

    执行结果,比如在move_base中的结果和机器人pose;在云台激光扫描中的一个请求的点云数据。等

    下面写一个actionlib的c++例程

    catkin_create_pkg actionlib_tutorials roscpp rospy actionlib actionlib_msgs message_generation
    

    在包中添加action文件夹在里面新建一个 Fibonacci.action文件

    #goal definition
    int32 order
    ---
    #result definition
    int32[] sequence
    ---
    #feedback definition
    int32[] sequence
    

     修改package.xml添加

      <run_depend>message_generation</run_depend>
    

     修改 CMakeLists.txt删除添加;编译cpp文件根据自己的添加

    add_action_files(
    DIRECTORY action
    FILES Fibonacci.action
    ) generate_messages(DEPENDENCIES actionlib_msgs ) CATKIN_DEPENDS actionlib actionlib_msgs message_generation roscpp rospy

    简单的client.cpp

    #include <ros/ros.h>
    #include <actionlib/client/simple_action_client.h>
    #include <actionlib_tutorials/FibonacciAction.h>
    
    using namespace actionlib_tutorials;
    typedef actionlib::SimpleActionClient<FibonacciAction> Client;
    
    int main (int argc, char **argv)
    {
      ros::init(argc, argv, "test_fibonacci_callback");
    
      // Create the action client
      Client ac("fibonacci", true);
    
      ROS_INFO("Waiting for action server to start.");
      ac.waitForServer();
      ROS_INFO("Action server started, sending goal.");
    
      // Send Goal
      FibonacciGoal goal;
      goal.order = 10;
      ac.sendGoal(goal);
      bool finish_before_timeout=ac.waitForResult(ros::Duration(15));
      
      if(finish_before_timeout)
      {
          actionlib::SimpleClientGoalState state = ac.getState();
          ROS_INFO("action finish : %s",state.getState().toString().c_str());
      }else
      {
          ROS_INFO("TIMEOUT");
      }
    
      ros::spin();
      return 0;
    }
    

     带回调显示的clientprocess.cpp

    #include <ros/ros.h>
    #include <actionlib/client/simple_action_client.h>
    #include <actionlib_tutorials/FibonacciAction.h>
    
    using namespace actionlib_tutorials;
    typedef actionlib::SimpleActionClient<FibonacciAction> Client;
    
    // Called once when the goal completes
    void doneCb(const actionlib::SimpleClientGoalState& state,
                const FibonacciResultConstPtr& result)
    {
      ROS_INFO("Finished in state [%s]", state.toString().c_str());
      ROS_INFO("Answer: %i", result->sequence.back());
      ros::shutdown();
    }
    
    // Called once when the goal becomes active
    void activeCb()
    {
      ROS_INFO("Goal just went active");
    }
    
    // Called every time feedback is received for the goal
    void feedbackCb(const FibonacciFeedbackConstPtr& feedback)
    {
      ROS_INFO("Got Feedback of length %lu", feedback->sequence.size());
    }
    
    int main (int argc, char **argv)
    {
      ros::init(argc, argv, "test_fibonacci_callback");
    
      // Create the action client
      Client ac("fibonacci", true);
    
      ROS_INFO("Waiting for action server to start.");
      ac.waitForServer();
      ROS_INFO("Action server started, sending goal.");
    
      // Send Goal
      FibonacciGoal goal;
      goal.order = 20;
      ac.sendGoal(goal, &doneCb, &activeCb, &feedbackCb);
    
      ros::spin();
      return 0;
    }
    

     server.cpp

    #include <ros/ros.h>
    #include <actionlib/server/simple_action_server.h>
    #include <actionlib_tutorials/FibonacciAction.h>
    
    typedef actionlib::SimpleActionServer<actionlib_tutorials::FibonacciAction> Server;
    
    class FibonacciAction
    {
    protected:
    
      ros::NodeHandle nh_;
      Server as_; // NodeHandle instance must be created before this line. Otherwise strange error occurs.
      std::string action_name_;
      // create messages that are used to published feedback/result
      actionlib_tutorials::FibonacciFeedback feedback_;
      actionlib_tutorials::FibonacciResult result_;
    
    public:
    
      FibonacciAction(std::string name) :
        as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1), false),
        action_name_(name)
      {
        as_.start();
      }
    
      ~FibonacciAction(void)
      {
      }
    
      void executeCB(const actionlib_tutorials::FibonacciGoalConstPtr &goal)
      {
        // helper variables
        ros::Rate r(1);
        bool success = true;
    
        // push_back the seeds for the fibonacci sequence
        feedback_.sequence.clear();
        feedback_.sequence.push_back(0);
        feedback_.sequence.push_back(1);
    
        // publish info to the console for the user
        ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i", action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]);
    
        // start executing the action
        for(int i=1; i<=goal->order; i++)
        {
          // check that preempt has not been requested by the client
          if (as_.isPreemptRequested() || !ros::ok())
          {
            ROS_INFO("%s: Preempted", action_name_.c_str());
            // set the action state to preempted
            as_.setPreempted();
            success = false;
            break;
          }
          feedback_.sequence.push_back(feedback_.sequence[i] + feedback_.sequence[i-1]);
          // publish the feedback
          as_.publishFeedback(feedback_);
          // this sleep is not necessary, the sequence is computed at 1 Hz for demonstration purposes
          r.sleep();
        }
    
        if(success)
        {
          result_.sequence = feedback_.sequence;
          ROS_INFO("%s: Succeeded", action_name_.c_str());
          // set the action state to succeeded
          as_.setSucceeded(result_);
        }
      }
    
    
    };
    
    
    int main(int argc, char** argv)
    {
      ros::init(argc, argv, "fibonacci");
    
      FibonacciAction fibonacci("fibonacci");
      ros::spin();
    
      return 0;
    }
    

     编译后运行

    rosrun actionlib_tutorials client
    rosrun actionlib_tutorials sever

     

    在设置时间内服务完成则状态输出完成,否则反馈失败,这种等待模式效率太低

    rosrun actionlib_tutorials clientprocess
    
    rosrun actionlib_tutorials sever
    

     

    将动作完成过程实时的将状态反馈回来,直到动作完成或失败

  • 相关阅读:
    JavaScript中弧度和角度的转换
    HTML <meta> Attribute
    rel 属性<small>H5保留属性</small>
    React学习笔记
    React学习笔记
    jQuery插件制作
    jQuery ajax
    js数据存贮之数组与json
    列表与表格的一些学习
    18-10-16学习内容总结
  • 原文地址:https://www.cnblogs.com/CZM-/p/6279755.html
Copyright © 2011-2022 走看看