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查看节点关系:

 

 

 

 话题列表如图所示:

 

 

 

posted @ 2020-03-27 19:29  静精进境  阅读(1497)  评论(0编辑  收藏  举报