ROS is the abbreviation of Robot Operating System. This article introduces the introduction of ROS application development, the definition and use of service data. The communication between the client and the server uses service data. This article first defines a service data. After the compilation is successful, use a server and a client to verify. The client can also use the rosservice call directly, so that the client does not need a program. The test verification is the C++ code first, and then the python code. You can also choose to only look at the one you are familiar with.
Function package creation
This article is a continuation of the programming of the Client Client in the introduction to ROS application development . If you have created a function package in that article, you don't need it here, just skip this section.
The ROS workspace is established in the article ROS Development and Application Preparation: Create a Workspace . Now, create a functional package:
cd ~/catkin_ws/src
catkin_create_pkg learning_service std_msgs roscpp rospy geometry_msgs turtlesim
Custom service data
Create a new directory srv under the project package directory
cd ~/catkin_ws/src/learning_service
mkdir srv
cd srv
Then create a new Person.srv file
nano Person.srv
The content of the file is:
string name
uint8 age
uint8 sex
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
---
string result
Let's take a look at the characteristics of this file:
The request data and the response data are separated by --- 3 horizontal lines-, the upper part is the request data, and the lower part is the response data.
The above is to send data, the data type that is not assigned is the data type, and the assigned value may be an enumeration class, so you need to enter 3 variables string name, uint8 age, uint8 sex
Below is the response data, here is just a string
Go back to the project package directory, open and edit package.xml:
cd ~/catkin_ws/src/learning_service
nano package.xml
Add the following 2 lines:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
The added position refers to the following position, which is above the comment in front of <export>:
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>turtlesim</exec_depend>
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
Then open and edit CMakeLists.txt, a total of 3
nano CMakeLists.txt
First add message_generation in find_package and
add it as follows:
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
rospy
std_msgs
turtlesim
message_generation
)
Add the following code, which can also be used as 2 lines,
add_service_files(
FILES
Person.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
The adding location is as follows:
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# geometry_msgs# std_msgs
# )
add_service_files(
FILES
Person.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
################################################
## Declare ROS dynamic reconfigure parameters ##
################################################
In catkin_package, uncomment the CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim line, and add message_runtime to
have the following effect:
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES learning_topic
CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime
# DEPENDS system_lib
)
After modifying these two files, compile in the workspace.
Compilation must go back to the ~/catkin_ws directory
cd ~/catkin_ws
catkin_make
If the compilation is successful, the service data is defined and ready.
Look at the final stage of compilation information
Scanning dependencies of target learning_service_generate_messages_py
[ 40%] Generating Python code from SRV learning_service/Person
[ 45%] Generating Python srv __init__.py for learning_service
[ 45%] Built target turtle_command_server
Scanning dependencies of target learning_service_generate_messages_eus
[ 50%] Generating EusLisp code from learning_service/Person.srv
[ 54%] Generating EusLisp manifest code for learning_service
[ 54%] Built target learning_service_generate_messages_py
Scanning dependencies of target learning_service_generate_messages_nodejs
[ 59%] Generating Javascript code from learning_service/Person.srv
[ 59%] Built target learning_service_generate_messages_nodejs
Scanning dependencies of target learning_service_generate_messages_cpp
[ 63%] Generating C++ code from learning_service/Person.srv
[ 63%] Built target learning_service_generate_messages_cpp
Scanning dependencies of target learning_service_generate_messages_lisp
[ 68%] Generating Lisp code from learning_service/Person.srv
[ 68%] Built target learning_service_generate_messages_lisp
[ 72%] Built target learning_topic_generate_messages_nodejs
[ 77%] Built target learning_topic_generate_messages_cpp
[ 86%] Built target learning_topic_generate_messages_eus
[ 95%] Built target learning_topic_generate_messages_py
[100%] Built target learning_topic_generate_messages_lisp
[100%] Built target learning_topic_generate_messages
[100%] Built target learning_service_generate_messages_eus
Scanning dependencies of target learning_service_generate_messages
[100%] Built target learning_service_generate_messages
It seems to be ready for multiple languages.
c++ verify source code
To use the service data to verify, you need two programs for the server and the client, and we put them in the src directory of the project directory
Go to the src directory and create the files person_client.cpp and person_server.cpp.cpp respectively
cd ~/catkin_ws/src/learning_service/src
nano person_client.cpp
The content of the file is:
/**
* 该例程将请求/show_person服务,服务数据类型learning_service::Person
*/
#include <ros/ros.h>
#include "learning_service/Person.h"
int main(int argc, char** argv)
{
// 初始化ROS节点
ros::init(argc, argv, "person_client");
// 创建节点句柄
ros::NodeHandle node;
// 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
ros::service::waitForService("/show_person");
ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");
// 初始化learning_service::Person的请求数据
learning_service::Person srv;
srv.request.name = "Tom";
srv.request.age = 20;
srv.request.sex = learning_service::Person::Request::male;
// 请求服务调用
ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]",
srv.request.name.c_str(), srv.request.age, srv.request.sex);
person_client.call(srv);
// 显示服务调用结果
ROS_INFO("Show person result : %s", srv.response.result.c_str());
return 0;
};
nano person_server.cpp
The content of the file is:
/**
* 该例程将执行/show_person服务,服务数据类型learning_service::Person
*/
#include <ros/ros.h>
#include "learning_service/Person.h"
// service回调函数,输入参数req,输出参数res
bool personCallback(learning_service::Person::Request &req,
learning_service::Person::Response &res)
{
// 显示请求数据
ROS_INFO("Person: name:%s age:%d sex:%d", req.name.c_str(), req.age, req.sex);
// 设置反馈数据
res.result = "OK";
return true;
}
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "person_server");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个名为/show_person的server,注册回调函数personCallback
ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
// 循环等待回调函数
ROS_INFO("Ready to show person informtion.");
ros::spin();
return 0;
}
2 files are ready.
Configure cmake file
In the ~/catkin_ws/src/learning_service/ directory, there is a CMakeLists.txt file, we need to modify this file
cd ~/catkin_ws/src/learning_service/
nano CMakeLists.txt
Add the following lines to this file,
add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)
add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)
The added position is the end of the Build section. Refer to the following position, which is in front of ## install ##, and then the previous client and the server add 2 lines after each:
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
add_executable(turtle_spawn src/turtle_spawn.cpp)
target_link_libraries(turtle_spawn ${catkin_LIBRARIES})
add_executable(turtle_command_server src/turtle_command_server.cpp)
target_link_libraries(turtle_command_server ${catkin_LIBRARIES})
add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)
add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)
#############
## Install ##
#############
Save, exit
This completes the compilation and configuration.
Compile and run the test
Compilation must go back to the ~/catkin_ws directory
cd ~/catkin_ws
catkin_make
It should be sourced once after compilation:
source devel/setup.bash
If there is an error in the compilation, the error must be eliminated and the test will be run after the compilation is complete.
Open a terminal, start ros, execute
roscore
Open another terminal, start the server, and execute
rosrun learning_service person_server
Open another terminal and start the client:
rosrun learning_service person_client
In fact, you can also use rosservice directly as a client for testing
rosservice call /show_person leon 12 2
or
leon@ubuntu:~$ rosservice call /show_person "name:'Leon'
age: 50
sex: 20" The
program running results are as follows: the client first executes the client twice, then the rosservice call twice, and then the client again
c++ verification is successful.
python verify source code
To verify the service data, two programs, the server side and the client side, are required. We put them in the scripts directory of the project directory.
Go to the scripts directory and create the files person_client.py and person_server.py respectively, if not, create one (mkdir scripts).
~/catkin_ws/src/learning_service/scripts
nano person_server.py
The content of the file is:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将执行/show_person服务,服务数据类型learning_service::Person
import rospy
from learning_service.srv import Person, PersonResponse
def personCallback(req):
# 显示请求数据
rospy.loginfo("Person: name:%s age:%d sex:%d", req.name, req.age, req.sex)
# 反馈数据
return PersonResponse("OK")
def person_server():
# ROS节点初始化
rospy.init_node('person_server')
# 创建一个名为/show_person的server,注册回调函数personCallback
s = rospy.Service('/show_person', Person, personCallback)
# 循环等待回调函数
print "Ready to show person informtion."
rospy.spin()
if __name__ == "__main__":
person_server()
nano person_client.py
The content of the file is:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Person
import sys
import rospy
from learning_service.srv import Person, PersonRequest
def person_client():
# ROS节点初始化
rospy.init_node('person_client')
# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
rospy.wait_for_service('/show_person')
try:
person_client = rospy.ServiceProxy('/show_person', Person)
# 请求服务调用,输入请求数据
response = person_client("Tom", 20, PersonRequest.male)
return response.result
except rospy.ServiceException, e:
print "Service call failed: %s"%e
if __name__ == "__main__":
#服务调用并显示调用结果
print "Show person result : %s" %(person_client())
Run test
Because python does not need to be compiled, but needs to be set as an executable file
chmod +x *.py
Open a terminal, start ros, execute
roscore
First source:
source ~/catkin_ws/devel/setup.bash
Open another terminal, start the server, and execute
rosrun learning_service person_server.py
Open another terminal and start the client:
rosrun learning_service person_client.py
Client authentication can also directly use rosservice call
rosservice call /show_person leon 12 2
or
leon@ubuntu:~$ rosservice call /show_person "name: 'Leon'
age: 50
sex: 20"
rosservice list can list all service names.
The results of the program are as follows:
Python verification is successful.
The source code can also be downloaded at https://github.com/huchunxu/ros_21_tutorials
The full text is introduced here.