上一节讲了ros机制中的话题机制,今天教程讲剩余的两种机制,动作和服务.
服务适用于只需要偶尔去做并且会在有限的时间内完成的事情.
举个例子,我们使用手机的时候想查询自己的手机话费余额,那我们可以使用10086的短信服务,只需要编辑短信发送给10086请求查询余额的服务我们就能收到查询结果.
这里使用ros入门例子测试服务机制.
首先启动ros:
roscore
打开小乌龟:
rosrun turtlesim turtlesim_node
启动键盘控制:
rosrun turtlesim turtle_teleop_key
查看服务列表:
rosservice list
调用清除轨迹的服务:
rosservice call clear
计算字符串中单词数目,例如输入:“one two three”,输出3
1.1、进入basic包:
cd ~/catkin_ws/src/basic/
1.2、创建srv目录
mkdir srv
1.3、在srv目录下创建WordCount.srv文件
cd srv
vi WordCount.srv
cd ..
vi CMakeLists.txt
2.1、修改CMakeLists.txt的find_package()如下:
2.2、修改add_service_files()去掉注释加入WordCount.srv
如下图:
2.3、修改generate_messages()如下图:
vi package.xml
cd ~/catkin_ws
catkin_make
rossrv show WordCount
6.1、在basic包的src文件夹下创建service_server.py文件,设置权限:
cd ~/catkin_ws/src/basic/src
vi service_server.py
chmod 777 service_server.py
service_server.py
#!/usr/bin/env python
import rospy
from basic.srv import WordCount,WordCountResponse
def count_words(request):
return WordCountResponse(len(request.words.split()))
rospy.init_node('service_server')
service = rospy.Service('word_count',WordCount,count_words)
rospy.spin()
roscore
cd ~/catkin_ws
catkin_make
source devel/setup.bash
rosrun basic service_server.py
这是已经在运行了不过没写现象。
rosservice list
rosservice info word_count
rosservice call word_count 'one two three'
12.1、在basic的src内创建service_client.py文件:
cd ~/catkin_ws/src/basic/src
vi service_client.py
chmod 777 service_client.py
service_client.py:
#!/usr/bin/env python
import rospy
from basic.srv import WordCount
import sys
rospy.init_node('service_client')
rospy.wait_for_service('word_count')
word_counter=rospy.ServiceProxy('word_count',WordCount)
words=' '.join(sys.argv[1:])
word_count=word_counter(words)
print words,'->',word_count.count
12.2、返回catkin根目录编译运行
cd ~/catkin_ws
catkin_make
source devel/setup.bash
rosrun basic service_client.py one two three
前面尝试了定义自己的消息类型和服务,接下来是定义动作。服务只适用于及时响应的消息类型,和编程的函数基本类似,有自己的输入输出。但是在解决机器人运作问题上服务显然就不够用了,就好比投篮,我们用服务来写只能做到写好一个服务将球投出去,至于球在空中的轨迹,是否进球框就不得而知了。而动作的话可以做到将球投出去,等待球进框或者没进框又做下一步的决策。
这里我们将创建一个计时的动作
前面的步骤默认已经创建好了ros的工作区和创建好了包basic,在这基础上继续完成动作的创建。
1、ctrl+alt+t呼出终端,在basic目录下创建action目录,并在action目录下创建Timer.action文件:
cd ~/catkin_ws/src/basic/
mkdir action
cd action
vi Timer.action
输入如下文本在Timer.action中:
#这坑爹的书把变量全写在注释里了,还好我眼睛比较尖锐。。。坑死我了
#就像这样duration time_to_wait
#你如果中英文隔开我还挺好看出来的,妈妈的全是英文的谁会注意看哦
duration time_to_wait
---
duration time_elapsed
uint32 updates_sent
---
duration time_elapsed
duration time_remaining
cd ~/catkin_ws
catkin_make
3、修改CMakeLists.txt
cd ~/catkin_ws/src/basic
vi CMakeLists.txt
3.1、修改find_package()添加action_msgs:
3.2、修改add_action_files()中添加FILES Timer.action:
3.3、修改generate_message()添加actionlib_msgs:
3.4、修改catkin_package()添加actionlib_msgs:
4、在package.xml中加上构建依赖项和运行依赖项:
vi package.xml
粘贴下面两行进去。
5、返回catkin的根目录编译:
cd ~/catkin_ws/
catkin_make
6、编写基本动作服务器:
6.1、在basic包的src下创建simple_action_serve.py文件:
cd ~/catkin_ws/src/basic/src
vi simple_action_serve.py
chmod 777 simple_action_serve.py
输入以下;
simple_action_serve.py
#!/usr/bin/env python
import rospy
import time
import actionlib
from basic.msg import TimerAction,TimerGoal,TimerResult
def do_timer(goal):
start_time=time.time()
time.sleep(goal.time_to_wait.to_sec())
result=TimerResult()
result.time_elapsed=rospy.Duration.from_sec(time.time()-start_time)
result.updates_sent=0
server.set_succeeded(result)
rospy.init_node('timer_action_server')
server=actionlib.SimpleActionServer('timer',TimerAction,do_timer,False)
server.start()
rospy.spin()
6.2、ctrl+alt+t打开新终端运行roscore:
roscore
6.3、返回根目录编译运行脚本:
cd ~/catkin_ws
catkin_make
source devel/setup.bash
rosrun basic simple_action_serve.py
7、list看是否有相应的服务运行
8、动作的使用:
8.1、创建动作使用脚本:
cd ~/catkin_ws/src/basic/src
vi simple_action_client.py
chmod 777 simple_action_client.py
输入以下:
simple_action_client.py
#!/usr/bin/env python
import rospy
import actionlib
from basic.msg import TimerAction,TimerGoal,TimerResult
rospy.init_node('timer_action_client')
client=actionlib.SimpleActionClient('timer',TimerAction)
client.wait_for_server()
goal=TimerGoal()
goal.time_to_wait=rospy.Duration.from_sec(5.0)
client.send_goal(goal)
client.wait_for_result()
print('Time elapsed:%f'%(client.get_result().time_elapsed.to_sec()))
8.2、返回根目录编译运行脚本:
cd ~/catkin_ws
catkin_make
source devel/setup.bash
rosrun basic simple_action_client.py
1.使用Python或者c语言实现有限状态机,可以通过终端输入来作为状态切换的标志.
2.完成本节实验,定义自己的服务和动作,随意发挥,但不要和本文例子相同.
程序作业提交截至日期为2020年08月03日23时59分,上传到群文件夹7.31程序作业中,程序作业需要提交源代码,截图运行结果,写上必要的文字说明。