Note: This tutorial assumes that you have completed the previous tutorials: examining the simple publisher and subscriber. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Escrevendo um Serviço-Cliente simples (Python)
Description: Esse tutorial cobre como escrever um nó serviço-cliente simples em python.Tutorial Level: BEGINNER
Next Tutorial: Examinando um Serviço-Cliente Simples
Contents
Escrevendo um Nó Serviço
Aqui nós vamos criar o nó contendo o serviço ("add_two_ints_server"), o qual recebe dois inteiros e retorna a soma deles.
Mude para o diretório do pacote beginner_tutorials que você criou anteriormente, creating a package:
Mude para o diretório do pacote beginner_tutorials que você criou anteriormente, creating a package:
$ roscd beginner_tutorials
Certifique-se de que você seguiu as instruções do tutorial anterior para criar o serviço necessário nesse tutorial, creating the AddTwoInts.srv (certifique-se de escolher a build tool correta no topo da página de acordo com o que estiver utilizando).
O Código
Crie o arquivo scripts/add_two_ints_server.py dentro do pacote beginner_tutorials e cole o seguinte trecho:
1 #!/usr/bin/env python
2 import roslib; roslib.load_manifest('beginner_tutorials')
3 from beginner_tutorials.srv import *
4 import rospy
5
6 def handle_add_two_ints(req):
7 print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))
8 return AddTwoIntsResponse(req.a + req.b)
9
10 def add_two_ints_server():
11 rospy.init_node('add_two_ints_server')
12 s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
13 print "Ready to add two ints."
14 rospy.spin()
15
16 if __name__ == "__main__":
17 add_two_ints_server()
1 #!/usr/bin/env python
2
3 from beginner_tutorials.srv import AddTwoInts,AddTwoIntsResponse
4 import rospy
5
6 def handle_add_two_ints(req):
7 print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))
8 return AddTwoIntsResponse(req.a + req.b)
9
10 def add_two_ints_server():
11 rospy.init_node('add_two_ints_server')
12 s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
13 print "Ready to add two ints."
14 rospy.spin()
15
16 if __name__ == "__main__":
17 add_two_ints_server()
Não se esqueça de dar permissão de execução ao nó:
chmod +x scripts/add_two_ints_server.py
O Código Explicado
Agora, vamos dar uma olhada com mais atenção em cada parte.
É preciso muito pouco para escrever um serviço usando rospy. Nós declaramos o nó utilizando init_node() e então declaramos o serviço:
12 s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
Isso declara um novo serviço do tipo AddTwoInts chamado add_two_ints. Todas as requisições são passadas para a função handle_add_two_ints. handle_add_two_ints é chamada com instâncias de AddTwoIntsRequest e retorna instâncias de AddTwoIntsResponse.
Assim como no exemplo do subscriber, rospy.spin() evita que seu código termine de executar até que o serviço seja finalizado.
Escrevendo o Nó Cliente
O Código
Crie o arquivo scripts/add_two_ints_client.py dentro do pacote beginner_tutorials package e cole o seguinte trecho:
1 #!/usr/bin/env python
2
3 import sys
4 import rospy
5 from beginner_tutorials.srv import *
6
7 def add_two_ints_client(x, y):
8 rospy.wait_for_service('add_two_ints')
9 try:
10 add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
11 resp1 = add_two_ints(x, y)
12 return resp1.sum
13 except rospy.ServiceException, e:
14 print "Service call failed: %s"%e
15
16 def usage():
17 return "%s [x y]"%sys.argv[0]
18
19 if __name__ == "__main__":
20 if len(sys.argv) == 3:
21 x = int(sys.argv[1])
22 y = int(sys.argv[2])
23 else:
24 print usage()
25 sys.exit(1)
26 print "Requesting %s+%s"%(x, y)
27 print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))
Não se esqueça de torná-lo executável:
$ chmod +x scripts/add_two_ints_client.py
O Código Explicado
Agora, vamos examinar o código com mais atenção.
O código do cliente para chamar serviços também é simples. Nos clientes, não é preciso chamar init_node(). Chamamos primeiramente:
8 rospy.wait_for_service('add_two_ints')
Esse é um método conveniente que bloqueia até que o serviço chamado add_two_ints esteja disponível. Em seguida, criamos um handle para chamar o serviço:
10 add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
Nós podemos utilizar esse handle assim como qualquer outra função e chamamos ele:
Como nós declaramos o tipo do serviço como sendo AddTwoInts, ele faz o trabalho de gerar o objeto AddTwoIntsRequest para você. O valor de retorno é um objeto AddTwoIntsResponse. Se a chamada falhar, uma exceção rospy.ServiceException será lançada, assim você pode escrever um bloco try/except para tratar a exceção.
Construindo seus nós
Nós utilizamos CMake como o nosso build system e, sim, você deve utilizá-lo mesmo em nós em Python. Isso é para garantir que as mensagens autogenerated Python code for messages and services sejam criadas.
We also use a Makefile for a bit of convenience. roscreate-pkg automatically created a Makefile, so you don't have to edit it.
Now run make:
$ make
Go to your catkin workspace and run catkin_make.
# In your catkin workspace $ cd ~/catkin_ws $ catkin_make
Experimente!
Em um novo terminal, rode
$ cd ~/catkin_ws $ . devel/setup.bash $ rosrun beginner_tutorials add_two_ints_server.py
Em um novo terminal, rode
$ cd ~/catkin_ws $ . devel/setup.bash $ rosrun beginner_tutorials add_two_ints_client.py
- E você verá a informação de uso, similar a
/home/user/catkin_ws/src/beginner_tutorials/scripts/add_two_ints_client.py [x y]
Então rode
$ rosrun beginner_tutorials add_two_ints_client.py 4 5
- E você terá
Requesting 4+5 4 + 5 = 9
- E o servidor vai printar
Returning [4 + 5 = 9]
Agora que você escreveu um Serviço-Cliente simples, vamos examinar um serviço-cliente simples.