7.learningAction(行为库)2
来源:互联网 发布:sql注入防范 编辑:程序博客网 时间:2024/06/05 05:59
1.使用目标回调方法(Goal Callback Method)编写一个简单的行为服务器
开始编写行为前,先创建行为消息文件Averaging.action
#goal definitionint32 samples---#result definitionfloat32 meanfloat32 std_dev---#feedbackint32 samplefloat32 datafloat32 meanfloat32 std_dev
手动生成消息
rosrun actionlib_msgs genaction.py -o msg/ action/Averaging.action
在编译过程中自动生成消息文件,在CMakeList.txt中添加
find_package(catkin REQUIRED COMPONENTS actionlib std_msgs message_generation) add_action_files(DIRECTORY action FILES Averaging.action)generate_messages(DEPENDENCIES std_msgs actionlib_msgs)
2.编写简单的行为服务器
#include <ros/ros.h>#include <std_msgs/Float32.h>#include <actionlib/server/simple_action_server.h>#include <actionlib_tutorials/AveragingAction.h>class AveragingAction{public://在行为构造函数中,创建一个行为服务器//行为服务器加载一个节点句柄(node handle)、行为名称和可选的回调(executeCB)。//在本示例中创建的行为服务器不需要回调(executeCB)参数。//在行为服务器构造之后,等价替换成注册的目标(goal)和抢占(preempt)回调用于行为的构造函数。 AveragingAction(std::string name) : as_(nh_, name, false), action_name_(name) {//注册目标和反馈回调函数as_.registerGoalCallback(boost::bind(&AveragingAction::goalCB, this)); as_.registerPreemptCallback(boost::bind(&AveragingAction::preemptCB, this));//订阅感兴趣的话题数据,建立一个数据回调,该回调会处理行为并且行为服务器开启 sub_ = nh_.subscribe("/random_number", 1, &AveragingAction::analysisCB, this); as_.start(); } ~AveragingAction(void) { }//这里是一个目标(goalCB)回调函数,参考构造函数。这个回调函数不返回任何东西也不需要任何参数。当目标回调(goalCB)调用行为时,需要接收目标并且存储任何重要的信息。 void goalCB() { // 重置帮助变量 data_count_ = 0; sum_ = 0; sum_sq_ = 0; // 接收新目标 goal_ = as_.acceptNewGoal()->samples; }//行为事件声明,当回调发生,行为代码会运行,否则一个会创建一个抢占回调来保证行为响应及时来取消请求。回调函数不需要参数,并且会设置抢占(preempted)到行为服务器。 void preemptCB() { ROS_INFO("%s: Preempted", action_name_.c_str()); // 设置行为状态为抢占(preempted) as_.setPreempted(); }//这里模拟回调得到订阅数据通道的消息格式,并且在继续处理数据之前检查行为是否处于活跃状态。 void analysisCB(const std_msgs::Float32::ConstPtr& msg) { // 确保行为还没有被取消 if (!as_.isActive()) return; data_count_++; feedback_.sample = data_count_; feedback_.data = msg->data; //处理std_dev和数据含义 sum_ += msg->data;//把相关数据放到反馈变量中,然后在行为服务器提供的反馈通道发布出去。 feedback_.mean = sum_ / data_count_; sum_sq_ += pow(msg->data, 2); feedback_.std_dev = sqrt(fabs((sum_sq_/data_count_) - pow(feedback_.mean, 2))); as_.publishFeedback(feedback_);//一旦收集到足够的数据,行为服务器会设置成功或失败。这将禁用行为服务器并且analysisCB函数会向之前描述的那样立即返回。 if(data_count_ > goal_) { result_.mean = feedback_.mean; result_.std_dev = feedback_.std_dev; if(result_.mean < 5.0) { ROS_INFO("%s: Aborted", action_name_.c_str()); //设置行为状态为崩溃(aborted) as_.setAborted(result_); } else { ROS_INFO("%s: Succeeded", action_name_.c_str()); // 设置行为状态为成功(succeeded) as_.setSucceeded(result_); } } }//这些是行为类的受保护的变量。在构造行为的过程中,构造节点句柄然后传递到行为服务器。构造的行为服务器正如以上描述那样。创建的反馈和结果消息用于在行为中发布。创建的订阅也会保存节点句柄。protected: ros::NodeHandle nh_; actionlib::SimpleActionServer<actionlib_tutorials::AveragingAction> as_; std::string action_name_; int data_count_, goal_; float sum_, sum_sq_; actionlib_tutorials::AveragingFeedback feedback_; actionlib_tutorials::AveragingResult result_; ros::Subscriber sub_;};int main(int argc, char** argv){ ros::init(argc, argv, "averaging"); AveragingAction averaging(ros::this_node::getName()); ros::spin(); return 0;}
CMakelist.txt
add_executable(averaging_server src/averaging_server.cpp)target_link_libraries(averaging_server ${catkin_LIBRARIES})
3.编写简单的客户端线程
#include <ros/ros.h>#include <actionlib/client/simple_action_client.h>#include <actionlib/client/terminal_state.h>#include <actionlib_tutorials/AveragingAction.h>#include <boost/thread.hpp>/*actionlib/server/simple_action_client.h是行为库,实现简单行为客户端。actionlib/client/terminal_state.h 定义目标可能的状态。boost线程库用于循环示例中的线程*///一个简单的函数用于循环线程,该函数会在代码之后用到。这个线程会在后台循环ros节点void spinThread(){ ros::spin();}int main (int argc, char **argv){ ros::init(argc, argv, "test_averaging");// 创建一个行为客户端//在行为定义中的行为客户端模板,制定和行为服务器通信的消息类型。//行为客户端构造函数会加载两个参数,包括需要连接的服务名和一个可选的布尔类型用于循环一个线程。//这里创建的行为客户端使用服务名和自动循环选项为false作为参数,这意味着一个必须创建一个线程。 actionlib::SimpleActionClient<actionlib_tutorials::AveragingAction> ac("averaging");//创建一个线程,然后在后台开启一个ros节点。通过使用这个方法你可以创建多个线程用于你的行为客户端,如果有必要的话。 boost::thread spin_thread(&spinThread); ROS_INFO("Waiting for action server to start.");//由于行为服务器又可以没有挂起或运行,行为客户端将在继续之前等待行为服务器开启 ac.waitForServer();//这里创建一个目标消息,设置目标值并且发送到行为服务器 ROS_INFO("Action server started, sending goal."); actionlib_tutorials::AveragingGoal goal; goal.samples = 100; ac.sendGoal(goal);//行为客户端在继续之前,等待目标结束。超时时间设置为30秒,这意味着函数会在30秒后如果目标没有完成,将会返回false。 bool finished_before_timeout = ac.waitForResult(ros::Duration(30.0));//超时之前目标完成,将会报告目标状态,否则通知用户目标没有在限定时间内完成 if (finished_before_timeout) { actionlib::SimpleClientGoalState state = ac.getState(); ROS_INFO("Action finished: %s",state.toString().c_str()); } else ROS_INFO("Action did not finish before the time out."); // 关闭节点,在退出前加入线程 ros::shutdown(); spin_thread.join(); //exit return 0;}
CMakeList.txt
add_executable(averaging_client src/averaging_client.cpp)target_link_libraries(averaging_client ${catkin_LIBRARIES})
在开始运行服务器和客户端之前,需要创建一个数据节点
#!/usr/bin/env pythonimport rospyfrom std_msgs.msg import Float32import randomdef gen_number(): pub = rospy.Publisher('random_number', Float32) rospy.init_node('random_number_generator', log_level=rospy.INFO) rospy.loginfo("Generating random numbers") while not rospy.is_shutdown(): pub.publish(Float32(random.normalvariate(5, 1))) rospy.sleep(0.05)if __name__ == '__main__': try: gen_number() except Exception, e: print "done"
不要忘记编译节点可运行:
chmod +x gen_numbers.py
0 0
- 7.learningAction(行为库)2
- 6.learningAction(行为库)
- 8.learningAction(行为库)3
- 行为型模式(2)
- 行为2
- C++研究笔记(2)程序行为
- 设计模式:行为型(2)
- unity3d AI 学习--个体行为操控(1)--具体行为类(2)
- 15.2.2 介绍行为
- Thinkphp3.2行为扩展
- 行为模式 (3)
- 行为模式(二)
- 行为模式(一)
- 行为模式(二)
- 行为模式 (三)
- UE4AI(行为树)
- 行为
- 行为
- android实现多图片放大缩小的切换
- bwlabel函数
- DWR实例浅析
- Animation
- java获取不同时间的工具类
- 7.learningAction(行为库)2
- 网络编程-实验1-C与S通信
- Spring 学习2--Spring特殊语义注释类定义bean
- 测试博客
- Java异常
- 基于Primeton ESB的高可用MQ集群配置
- C# Keycode对照表
- 鼠标滚轮兼容火狐,
- Android5.0 开机设置静态IP地址