目录
一、准备工作——vscode配置
二、服务端实现
1.创建demo01_server_p.py
2.添加可执行权限
3.配置CMakeList.txt(melodic不用配置也行,noetic需要配置)
4.测试服务端
三、客户端实现
1.创建demo01_client_p.py
2.添加可执行权限+CMakeList.txt配置
3.测试客户端
4.客户端优化
参考:赵虚左课程+古月的ROS机器人开发实践
一、准备工作——vscode配置
![](https://img-blog.csdnimg.cn/a922034caeb64cdba090289dac52d704.png)
选择在集成终端中打开,输入:
pwd
输出一个路径。
rosmelodic@rosmelodic-virtual-machine:~/catkin_ws/devel/lib/python2.7/dist-packages$ pwd
/home/rosmelodic/catkin_ws/devel/lib/python2.7/dist-packages
将输出的路径加入.vscode文件夹中的setting.json文件
{
"python.autoComplete.extraPaths": [
"/opt/ros/melodic/lib/python2.7/dist-packages",
"/home/rosmelodic/catkin_ws/devel/lib/python2.7/dist-packages"
],
"python.analysis.extraPaths": [
"/opt/ros/melodic/lib/python2.7/dist-packages"
]
}
这是为了vscode开发时能够找到自定义服务数据类型的库。
二、服务端实现
1.创建demo01_server_p.py
![](https://img-blog.csdnimg.cn/014cfff9e20742c39b5ac500d63cc08d.png)
demo01_server_p.py
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
import rospy
from server_client.srv import AddInts,AddIntsRequest,AddIntsResponse
def huidiao(request):
# request = AddIntsRequest()
num11 = request.num1
num22 = request.num2
sum12 = num11 + num22
response = AddIntsResponse()
response.sum = sum12
rospy.loginfo("服务器解析数据:num11 = %d, num22 = %d, 响应结果为:sun12 = %d", num11, num22, sum12)
return response
if __name__ == "__main__":
rospy.init_node("jiafa_server_p")
server = rospy.Service(name="add_ints", service_class=AddInts, handler=huidiao)
rospy.loginfo("服务器已经启动了")
rospy.spin()
相较于c++实现精简了很多。
python版本声明,和utf-8编码,不声明编码格式默认ascii码,防止程序中有中文出现报错。
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
调用rospy库,和之前自定义的服务数据类型库,自定义的服务数据类型库中包含了这三个类。
import rospy
from server_client.srv import AddInts,AddIntsRequest,AddIntsResponse
/home/rosmelodic/catkin_ws/devel/lib/python2.7/dist-packages/server_client/srv
![](https://img-blog.csdnimg.cn/0d0d5892e8c646c894c57690378df8bb.png)
![](https://img-blog.csdnimg.cn/ee6cb44db94043b89a8f3eecf552dd0b.png)
回调函数部分
def huidiao(request):
# request = AddIntsRequest()
num11 = request.num1
num22 = request.num2
sum12 = num11 + num22
response = AddIntsResponse()
response.sum = sum12
rospy.loginfo("服务器解析数据:num11 = %d, num22 = %d, 响应结果为:sun12 = %d", num11, num22, sum12)
return response
def huidiao(request):
回调函数部分,由于request只是个形参,而且没有声明request的数据类型,导致num1没有代码的自动补齐。尝试了加上request = AddIntsRequest(),但是会导致回调函数接受不到请求request的数值,这个方法失败了,只能在没有代码补齐的情况下硬着去编写。而在c++代码中,转入的形参通过指针的方式给了数据类型,自然有了代码补齐,但是python没有指针功能。
num11 = request.num1
num22 = request.num2
sum12 = num11 + num22
response = AddIntsResponse()
response.sum = sum12
rospy.loginfo("服务器解析数据:num11 = %d, num22 = %d, 响应结果为:sun12 = %d", num11, num22, sum12)
return response
首先解析请求的两个参数,再将两个参数相加,再将得到的结果赋值给应答,此时的request的num1和num2和response的sum实现着存放请求和应答数据的功能,这些数据是可以通过ROS服务通信去操作的,而num11、num22、sum12只是个符合自定义服务数据类型的数。
if __name__ == "__main__":
rospy.init_node("jiafa_server_p")
server = rospy.Service(name="add_ints", service_class=AddInts, handler=huidiao)
rospy.loginfo("服务器已经启动了")
rospy.spin()
初始化节点,相较于c++不用再初始化句柄操作。
创建服务端,name为服务名,service_class服务参数的数据类型,handler回调函数。
设置回头函数,不断循环。
2.添加可执行权限
![](https://img-blog.csdnimg.cn/639c42ee49df4c47b7b20b9e743a7e5f.png)
3.配置CMakeList.txt(melodic不用配置也行,noetic需要配置)
catkin_install_python(PROGRAMS
scripts/demo01_server_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
melodic不用配置也行,noetic需要配置,在melodic中这个配置也是生效的,如果打错了路径会出现找不到文件。
4.测试服务端
roscore
rosrun server_client demo01_server_p.py
rosservice call add_ints "num1: 0
num2: 0"
通过调整num1和num2数值,观察结果:
![](https://img-blog.csdnimg.cn/cbba6525d7b24020ac6303435fd60e36.png)
三、客户端实现
1.创建demo01_client_p.py
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
import rospy
from server_client.srv import AddInts,AddIntsRequest,AddIntsResponse
if __name__ == "__main__":
rospy.init_node("jiafa_client_p")
client = rospy.ServiceProxy(name="add_ints", service_class=AddInts)
response = client.call(AddIntsRequest(10, 30))
# response = client.call(10, 30)
rospy.loginfo("响应的数据为:%d",response.sum)
初始化ROS节点→创建客户端(不用回调函数,同时注意服务名称必须相同)→组织请求数据,并发布请求→控制台输出
2.添加可执行权限+CMakeList.txt配置
与之前方法相同
chmod +x *.py
catkin_install_python(PROGRAMS
scripts/demo01_client_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
3.测试客户端
rosrun server_client demo01_server_p.py
rosrun server_client demo01_client_p.py
![](https://img-blog.csdnimg.cn/46255a16e8a54e3f9e9ff844d3227c27.png)
![](https://img-blog.csdnimg.cn/df05d5897aa943e498441d02bea28016.png)
4.客户端优化
修改的部分:
import sys
import logging
logging.basicConfig()
sys为system的库,通过这个能导入argv,与c++不同,此处没有argc,其中argc就为argv数组的长度,用过len(sys.argv)来使用。
import logging
logging.basicConfig()此处是一个为了rospy.logerr("提交参数个数有误")能正常输出,如果不加上这个库会报错:
No handlers could be found for logger "rosout"
这部分是判断输入参数的长度,其中第一个参数为文件名,第二个和第三个为请求的数值 ,当长度不等于3,返回警告。
if len(sys.argv) != 3:
rospy.logerr("提交参数个数有误")
sys.exit(1)
这部分注意system返回的输入值为字符串类型,需要强制转换为int类型,才能参与计算。
req = AddIntsRequest()
req.num1 = int(sys.argv[1])
req.num2 = int(sys.argv[2])
response = client.call(req.num1, req.num2)
# response = client.call(AddIntsRequest(10, 30))
修改后:
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
import rospy
from server_client.srv import AddInts,AddIntsRequest,AddIntsResponse
import sys
import logging
logging.basicConfig()
if __name__ == "__main__":
if len(sys.argv) != 3:
rospy.logerr("提交参数个数有误")
sys.exit(1)
rospy.init_node("jiafa_client_p")
client = rospy.ServiceProxy(name="add_ints", service_class=AddInts)
req = AddIntsRequest()
req.num1 = int(sys.argv[1])
req.num2 = int(sys.argv[2])
response = client.call(req.num1, req.num2)
# response = client.call(AddIntsRequest(10, 30))
rospy.loginfo("响应的数据为:%d",response.sum)
测试:
rosrun server_client demo01_server_p.py
rosrun server_client demo01_client_p.py 10 20
![](https://img-blog.csdnimg.cn/5167623d515c4803b27c25a637013428.png)
![](https://img-blog.csdnimg.cn/3000dae6aa5d46faaaae0f09c822f198.png)
rosrun server_client demo01_client_p.py 10 20 30
![](https://img-blog.csdnimg.cn/54aced67ea51434ab05e453234d95005.png)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)