ROS 消息通讯——动作action的来龙去脉
创建功能包:
- 修改功能包说明文件package.xml
1 <?xml version="1.0"?> 2 <package> 3 <name>action_tutorials</name> 4 <version>0.0.0</version> 5 <description>The action_tutorials package</description> 6 <maintainer email="hcx@todo.todo">hcx</maintainer> 7 <license>TODO</license> 8 <buildtool_depend>catkin</buildtool_depend> 9 <build_depend>actionlib</build_depend> 10 <build_depend>actionlib_msgs</build_depend> 11 <build_depend>roscpp</build_depend> 12 <run_depend>actionlib</run_depend> 13 <run_depend>actionlib_msgs</run_depend> 14 <run_depend>roscpp</run_depend> 15 <export> </export> 16 </package>
- CMake编译配置文件CMakeLists.txt
1 cmake_minimum_required(VERSION 2.8.3) 2 project(action_tutorials) 3 4 5 find_package(catkin REQUIRED COMPONENTS 6 actionlib 7 actionlib_msgs 8 roscpp 9 ) 10 11 12 find_package(catkin REQUIRED genmsg actionlib_msgs actionlib) 13 add_action_files(DIRECTORY action FILES DoDishes.action) 14 generate_messages(DEPENDENCIES actionlib_msgs) 15 16 include_directories( 17 ${catkin_INCLUDE_DIRS} 18 ) 19 20 21 add_executable(DoDishes_client src/DoDishes_client.cpp) 22 target_link_libraries( DoDishes_client ${catkin_LIBRARIES}) 23 add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS}) 24 25 add_executable(DoDishes_server src/DoDishes_server.cpp) 26 target_link_libraries( DoDishes_server ${catkin_LIBRARIES}) 27 add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS})
- 添加动作文件:与CMakeLists.txt对应,add_action_files(DIRECTORY action FILES DoDishes.action)
内容如下:---用于分割目标、结果、反馈,顺序不能打乱
1 # Define the goal 2 uint32 dishwasher_id # Specify which dishwasher we want to use 3 --- 4 # Define the result 5 uint32 total_dishes_cleaned 6 --- 7 # Define a feedback message 8 float32 percent_complete
- 创建动作客户端节点:与CMakeLists.txt对应,add_executable(DoDishes_client src/DoDishes_client.cpp)
内容如下:
1 #include <actionlib/client/simple_action_client.h> 2 #include "action_tutorials/DoDishesAction.h" 3 4 typedef actionlib::SimpleActionClient<action_tutorials::DoDishesAction> Client; 5 6 // 当action完成后会调用该回调函数一次 7 void doneCb(const actionlib::SimpleClientGoalState& state, 8 const action_tutorials::DoDishesResultConstPtr& result) 9 { 10 ROS_INFO("Yay! The dishes are now clean"); 11 ros::shutdown(); 12 } 13 14 // 当action激活后会调用该回调函数一次 15 void activeCb() 16 { 17 ROS_INFO("Goal just went active"); 18 } 19 20 // 收到feedback后调用该回调函数 21 void feedbackCb(const action_tutorials::DoDishesFeedbackConstPtr& feedback) 22 { 23 ROS_INFO(" percent_complete : %f ", feedback->percent_complete); 24 } 25 26 int main(int argc, char** argv) 27 { 28 ros::init(argc, argv, "do_dishes_client"); 29 30 // 定义一个客户端 31 Client client("do_dishes", true); 32 33 // 等待服务器端 34 ROS_INFO("Waiting for action server to start."); 35 client.waitForServer(); 36 ROS_INFO("Action server started, sending goal."); 37 38 // 创建一个action的goal 39 action_tutorials::DoDishesGoal goal; 40 goal.dishwasher_id = 1; 41 42 // 发送action的goal给服务器端,并且设置回调函数 43 client.sendGoal(goal, &doneCb, &activeCb, &feedbackCb); 44 45 ros::spin(); 46 47 return 0; 48 }
- 创建动作服务器节点:与CMakeLists.txt对应,add_executable(DoDishes_server src/DoDishes_server.cpp)
内容如下:
1 #include <ros/ros.h> 2 #include <actionlib/server/simple_action_server.h> 3 #include "action_tutorials/DoDishesAction.h" 4 5 typedef actionlib::SimpleActionServer<action_tutorials::DoDishesAction> Server; 6 7 // 收到action的goal后调用该回调函数 8 void execute(const action_tutorials::DoDishesGoalConstPtr& goal, Server* as) 9 { 10 ros::Rate r(1); 11 action_tutorials::DoDishesFeedback feedback; 12 13 ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id); 14 15 // 假设洗盘子的进度,并且按照1hz的频率发布进度feedback 16 for(int i=1; i<=10; i++) 17 { 18 feedback.percent_complete = i * 10; 19 as->publishFeedback(feedback); 20 r.sleep(); 21 } 22 23 // 当action完成后,向客户端返回结果 24 ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id); 25 as->setSucceeded(); 26 } 27 28 int main(int argc, char** argv) 29 { 30 ros::init(argc, argv, "do_dishes_server"); 31 ros::NodeHandle n; 32 33 // 定义一个服务器 34 Server server(n, "do_dishes", boost::bind(&execute, _1, &server), false); 35 36 // 服务器开始运行 37 server.start(); 38 39 ros::spin(); 40 41 return 0; 42 }
- 运行效果:
- 运行rqt_graph查看节点关系:
话题列表如图所示: