2、话题编程:
在/home/catkin_ws/src/learning_comnunication/src 编写源码文件;
其中talker.cpp 与 listener.cpp 是发布者与订阅者实现,源代码分别如下:
1 /** 2 * 该例程将发布chatter话题,消息类型String 3 */ 4 5 #include <sstream> 6 #include "ros/ros.h" 7 #include "std_msgs/String.h" 8 9 int main(int argc, char **argv) 10 { 11 // ROS节点初始化 12 ros::init(argc, argv, "talker"); 13 14 // 创建节点句柄 15 ros::NodeHandle n; 16 17 // 创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String 18 ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); 19 20 // 设置循环的频率 21 ros::Rate loop_rate(10); 22 23 int count = 0; 24 while (ros::ok()) 25 { 26 // 初始化std_msgs::String类型的消息 27 std_msgs::String msg; 28 std::stringstream ss; 29 ss << "hello world " << count; 30 msg.data = ss.str(); 31 32 // 发布消息 33 ROS_INFO("%s", msg.data.c_str()); 34 chatter_pub.publish(msg); 35 36 // 循环等待回调函数 37 ros::spinOnce(); 38 39 // 按照循环频率延时 40 loop_rate.sleep(); 41 ++count; 42 } 43 44 return 0; 45 }
/** * 该例程将订阅chatter话题,消息类型String */ #include "ros/ros.h" #include "std_msgs/String.h" // 接收到订阅的消息后,会进入消息回调函数 void chatterCallback(const std_msgs::String::ConstPtr& msg) { // 将接收到的消息打印出来 ROS_INFO("I heard: [%s]", msg->data.c_str()); } int main(int argc, char **argv) { // 初始化ROS节点 ros::init(argc, argv, "listener"); // 创建节点句柄 ros::NodeHandle n; // 创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback); // 循环等待回调函数 ros::spin(); return 0; }
在/home/catkin_ws/src/learning_comnunication 中的CMakeLists.txt 中添加如下:
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
在/home/catkin_ws下编译、运行
catkin_make
在新终端执行
root@sry:~# rosrun learning_communication talker
报错:
[rosrun] Couldn't find executable named talker below /root/catkin_ws/src/learning_communication
经过痛苦查找,发现我的功能包名字叫: learning_comnunication
上述的rosrun learning_communication talker 会查找根目录下那个相关文件夹;所以控制台报错
说在XXXXX路径下找不到可执行文件 talker
【将错就错】
rosrun learning_comnunication talker
rosrun learning_comnunication listener
我们在三个终端中分别执行以下三条指令
roscore
rosrun learning_communication talker
rosrun learning_communication listener
消息定义如下:
##########3话题消息定义#############
在 /home/catkin_ws/src/learning_communication
mkdir msg
##创建消息文件Person.msg
文件中添加以下内容:
1 string name 2 uint8 sex 3 uint8 age 4 5 uint8 unknown = 0 6 uint8 male = 1 7 uint8 female = 2
#在 /home/catkin_ws/src/learning_communication/package.xml添加依赖【注意添加位置,否则无效】
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
#在 /home/catkin_ws/src/learning_communication/CMakeLists.txt 中添加编译选项
find_package( …… message_generation)
catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
## 查看消息是否定义成功
rosmsg show Person
类似创建msg文件,
mkdir srv
gedit AddTwoInts.srv 文件中内容
1 ## 请求数据 ,发送给服务端 2 int64 a 3 int64 b 4 --- 5 ## 应答数据,发送求和结果给客户端 6 int64 sum
#在 /home/catkin_ws/src/learning_communication/CMakeLists.txt 中添加编译选项
find_package( …… message_generation)
catkin_package(CATKIN_DEPENDS roscpp rospy std_msgs message_runtime)
## 请你务必实现阅读package.xml文件的架构
add_service_files(FILES AddTwoInts.srv)
generate_messages(DEPENDENCIES std_msgs)
然后编写client文件和service文件,修改CMakeList.txt
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)
add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)
package.xml修改后文件如下:
1 <?xml version="1.0"?> 2 <package format="2"> 3 <name>learning_communication</name> 4 <version>0.0.0</version> 5 <description>The learning_communication package</description> 6 7 <!-- One maintainer tag required, multiple allowed, one person per tag --> 8 <!-- Example: --> 9 <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> 10 <maintainer email="root@todo.todo">root</maintainer> 11 12 13 <!-- One license tag required, multiple allowed, one license per tag --> 14 <!-- Commonly used license strings: --> 15 <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> 16 <license>TODO</license> 17 18 19 <!-- Url tags are optional, but multiple are allowed, one per tag --> 20 <!-- Optional attribute type can be: website, bugtracker, or repository --> 21 <!-- Example: --> 22 <!-- <url type="website">http://wiki.ros.org/learning_communication</url> --> 23 24 25 <!-- Author tags are optional, multiple are allowed, one per tag --> 26 <!-- Authors do not have to be maintainers, but could be --> 27 <!-- Example: --> 28 <!-- <author email="jane.doe@example.com">Jane Doe</author> --> 29 30 31 <!-- The *depend tags are used to specify dependencies --> 32 <!-- Dependencies can be catkin packages or system dependencies --> 33 <!-- Examples: --> 34 <!-- Use depend as a shortcut for packages that are both build and exec dependencies --> 35 <!-- <depend>roscpp</depend> --> 36 <!-- Note that this is equivalent to the following: --> 37 <!-- <build_depend>roscpp</build_depend> --> 38 <!-- <exec_depend>roscpp</exec_depend> --> 39 <!-- Use build_depend for packages you need at compile time: --> 40 <!-- <build_depend>message_generation</build_depend> --> 41 <!-- Use build_export_depend for packages you need in order to build against this package: --> 42 <!-- <build_export_depend>message_generation</build_export_depend> --> 43 <!-- Use buildtool_depend for build tool packages: --> 44 <!-- <buildtool_depend>catkin</buildtool_depend> --> 45 <!-- Use exec_depend for packages you need at runtime: --> 46 <!-- <exec_depend>message_runtime</exec_depend> --> 47 <!-- Use test_depend for packages you need only for testing: --> 48 <!-- <test_depend>gtest</test_depend> --> 49 <!-- Use doc_depend for packages you need only for building documentation: --> 50 <!-- <doc_depend>doxygen</doc_depend> --> 51 <buildtool_depend>catkin</buildtool_depend> 52 <build_depend>roscpp</build_depend> 53 <build_depend>rospy</build_depend> 54 <build_depend>std_msgs</build_depend> 55 <build_export_depend>roscpp</build_export_depend> 56 <build_export_depend>rospy</build_export_depend> 57 <build_export_depend>std_msgs</build_export_depend> 58 <exec_depend>roscpp</exec_depend> 59 <exec_depend>rospy</exec_depend> 60 <exec_depend>std_msgs</exec_depend> 61 62 <build_depend>message_generation</build_depend> 63 <exec_depend>message_runtime</exec_depend> 64 65 <!-- The export tag contains other, unspecified, tags --> 66 <export> 67 <!-- Other tools can request additional information be placed here --> 68 69 70 </export> 71 </package>
CMakeList.txt
1 cmake_minimum_required(VERSION 2.8.3) 2 project(learning_communication) 3 4 ## Compile as C++11, supported in ROS Kinetic and newer 5 # add_compile_options(-std=c++11) 6 7 ## Find catkin macros and libraries 8 ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) 9 ## is used, also find other catkin packages 10 find_package(catkin REQUIRED COMPONENTS 11 roscpp 12 rospy 13 std_msgs 14 message_generation 15 ) 16 17 ## System dependencies are found with CMake's conventions 18 # find_package(Boost REQUIRED COMPONENTS system) 19 20 21 ## Uncomment this if the package has a setup.py. This macro ensures 22 ## modules and global scripts declared therein get installed 23 ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html 24 # catkin_python_setup() 25 26 ################################################ 27 ## Declare ROS messages, services and actions ## 28 ################################################ 29 30 ## To declare and build messages, services or actions from within this 31 ## package, follow these steps: 32 ## * Let MSG_DEP_SET be the set of packages whose message types you use in 33 ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). 34 ## * In the file package.xml: 35 ## * add a build_depend tag for "message_generation" 36 ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET 37 ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in 38 ## but can be declared for certainty nonetheless: 39 ## * add a exec_depend tag for "message_runtime" 40 ## * In this file (CMakeLists.txt): 41 ## * add "message_generation" and every package in MSG_DEP_SET to 42 ## find_package(catkin REQUIRED COMPONENTS ...) 43 ## * add "message_runtime" and every package in MSG_DEP_SET to 44 ## catkin_package(CATKIN_DEPENDS ...) 45 ## * uncomment the add_*_files sections below as needed 46 ## and list every .msg/.srv/.action file to be processed 47 ## * uncomment the generate_messages entry below 48 ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) 49 50 ## Generate messages in the 'msg' folder 51 # add_message_files( 52 # FILES 53 # Message1.msg 54 # Message2.msg 55 # ) 56 57 ## Generate services in the 'srv' folder 58 # add_service_files( 59 # FILES 60 # Service1.srv 61 # Service2.srv 62 # ) 63 64 ## Generate actions in the 'action' folder 65 # add_action_files( 66 # FILES 67 # Action1.action 68 # Action2.action 69 # ) 70 71 ## Generate added messages and services with any dependencies listed here 72 # generate_messages( 73 # DEPENDENCIES 74 # std_msgs 75 # ) 76 add_message_files(FILES Person.msg) 77 78 add_service_files(FILES AddTwoInts.srv) 79 80 generate_messages(DEPENDENCIES std_msgs) 81 82 #generate_messages(DEPENDENCIES std_msgs) 83 84 ################################################ 85 ## Declare ROS dynamic reconfigure parameters ## 86 ################################################ 87 88 ## To declare and build dynamic reconfigure parameters within this 89 ## package, follow these steps: 90 ## * In the file package.xml: 91 ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" 92 ## * In this file (CMakeLists.txt): 93 ## * add "dynamic_reconfigure" to 94 ## find_package(catkin REQUIRED COMPONENTS ...) 95 ## * uncomment the "generate_dynamic_reconfigure_options" section below 96 ## and list every .cfg file to be processed 97 98 ## Generate dynamic reconfigure parameters in the 'cfg' folder 99 # generate_dynamic_reconfigure_options( 100 # cfg/DynReconf1.cfg 101 # cfg/DynReconf2.cfg 102 # ) 103 104 ################################### 105 ## catkin specific configuration ## 106 ################################### 107 ## The catkin_package macro generates cmake config files for your package 108 ## Declare things to be passed to dependent projects 109 ## INCLUDE_DIRS: uncomment this if your package contains header files 110 ## LIBRARIES: libraries you create in this project that dependent projects also need 111 ## CATKIN_DEPENDS: catkin_packages dependent projects also need 112 ## DEPENDS: system dependencies of this project that dependent projects also need 113 catkin_package( 114 # INCLUDE_DIRS include 115 # LIBRARIES learning_communication 116 CATKIN_DEPENDS roscpp rospy std_msgs message_runtime 117 # DEPENDS system_lib 118 ) 119 120 ########### 121 ## Build ## 122 ########### 123 124 ## Specify additional locations of header files 125 ## Your package locations should be listed before other locations 126 include_directories( 127 # include 128 ${catkin_INCLUDE_DIRS} 129 ) 130 131 ## Declare a C++ library 132 # add_library(${PROJECT_NAME} 133 # src/${PROJECT_NAME}/learning_communication.cpp 134 # ) 135 136 ## Add cmake target dependencies of the library 137 ## as an example, code may need to be generated before libraries 138 ## either from message generation or dynamic reconfigure 139 # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 140 141 ## Declare a C++ executable 142 ## With catkin_make all packages are built within a single CMake context 143 ## The recommended prefix ensures that target names across packages don't collide 144 # add_executable(${PROJECT_NAME}_node src/learning_communication_node.cpp) 145 146 ## Rename C++ executable without prefix 147 ## The above recommended prefix causes long target names, the following renames the 148 ## target back to the shorter version for ease of user use 149 ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" 150 # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") 151 152 ## Add cmake target dependencies of the executable 153 ## same as for the library above 154 # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 155 156 ## Specify libraries to link a library or executable target against 157 # target_link_libraries(${PROJECT_NAME}_node 158 # ${catkin_LIBRARIES} 159 # ) 160 add_executable(talker src/talker.cpp) 161 target_link_libraries(talker ${catkin_LIBRARIES}) 162 163 add_executable(listener src/listener.cpp) 164 target_link_libraries(listener ${catkin_LIBRARIES}) 165 166 add_executable(server src/server.cpp) 167 target_link_libraries(server ${catkin_LIBRARIES}) 168 add_dependencies(server ${PROJECT_NAME}_gencpp) 169 170 add_executable(client src/client.cpp) 171 target_link_libraries(client ${catkin_LIBRARIES}) 172 add_dependencies(client ${PROJECT_NAME}_gencpp) 173 174 175 176 ############# 177 ## Install ## 178 ############# 179 180 # all install targets should use catkin DESTINATION variables 181 # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html 182 183 ## Mark executable scripts (Python etc.) for installation 184 ## in contrast to setup.py, you can choose the destination 185 # install(PROGRAMS 186 # scripts/my_python_script 187 # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 188 # ) 189 190 ## Mark executables and/or libraries for installation 191 # install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node 192 # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 193 # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 194 # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 195 # ) 196 197 ## Mark cpp header files for installation 198 # install(DIRECTORY include/${PROJECT_NAME}/ 199 # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 200 # FILES_MATCHING PATTERN "*.h" 201 # PATTERN ".svn" EXCLUDE 202 # ) 203 204 ## Mark other files for installation (e.g. launch and bag files, etc.) 205 # install(FILES 206 # # myfile1 207 # # myfile2 208 # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 209 # ) 210 211 ############# 212 ## Testing ## 213 ############# 214 215 ## Add gtest based cpp test target and link libraries 216 # catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_communication.cpp) 217 # if(TARGET ${PROJECT_NAME}-test) 218 # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) 219 # endif() 220 221 ## Add folders to be run by python nosetests 222 # catkin_add_nosetests(test)
其中service的源代码如下:
1 /** 2 * AddTwoInts Server 3 */ 4 5 #include "ros/ros.h" 6 #include "learning_communication/AddTwoInts.h" 7 8 // service回调函数,输入参数req,输出参数res 9 bool add(learning_communication::AddTwoInts::Request &req, 10 learning_communication::AddTwoInts::Response &res) 11 { 12 // 将输入参数中的请求数据相加,结果放到应答变量中 13 res.sum = req.a + req.b; 14 ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b); 15 ROS_INFO("sending back response: [%ld]", (long int)res.sum); 16 17 return true; 18 } 19 20 int main(int argc, char **argv) 21 { 22 // ROS节点初始化 23 ros::init(argc, argv, "add_two_ints_server"); 24 25 // 创建节点句柄 26 ros::NodeHandle n; 27 28 // 创建一个名为add_two_ints的server,注册回调函数add() 29 ros::ServiceServer service = n.advertiseService("add_two_ints", add); 30 31 // 循环等待回调函数 32 ROS_INFO("Ready to add two ints."); 33 ros::spin(); 34 35 return 0; 36 }
client代码:
1 /** 2 * AddTwoInts Client 3 */ 4 5 #include <cstdlib> 6 #include "ros/ros.h" 7 #include "learning_communication/AddTwoInts.h" 8 9 int main(int argc, char **argv) 10 { 11 // ROS节点初始化 12 ros::init(argc, argv, "add_two_ints_client"); 13 14 // 从终端命令行获取两个加数 15 if (argc != 3) 16 { 17 ROS_INFO("usage: add_two_ints_client X Y"); 18 return 1; 19 } 20 21 // 创建节点句柄 22 ros::NodeHandle n; 23 24 // 创建一个client,请求add_two_int service,service消息类型是learning_communication::AddTwoInts 25 ros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts>("add_two_ints"); 26 27 // 创建learning_communication::AddTwoInts类型的service消息 28 learning_communication::AddTwoInts srv; 29 srv.request.a = atoll(argv[1]); 30 srv.request.b = atoll(argv[2]); 31 32 // 发布service请求,等待加法运算的应答结果 33 if (client.call(srv)) 34 { 35 ROS_INFO("Sum: %ld", (long int)srv.response.sum); 36 } 37 else 38 { 39 ROS_ERROR("Failed to call service add_two_ints"); 40 return 1; 41 } 42 43 return 0; 44 }
功能简述:客户端向服务器发送请求,服务器完成请求并响应反馈给客户端。
在三个终端分别执行以下命令:
roscore rosrun learning_communication client 3 4 rosrun learning_communication server