This tutorial is created by Rosbotics Ambassador 012 Alessandro
Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)
Contenuto del tutorial
- Come creare Service personalizzati
- Cosa definisce la struttura di un Service
- Quali cambiamenti apportare al package per compilare il nuovo Service
- Come importare i messaggi relativi al Service all’interno del nostro package
In questo video imparerai come definire e utilizzare i servizi personalizzati.
Risorse
- Rosject utilizzato per questo tutorial
- Piattaforma: The Construct
- Corso: ROS Basics in 5 days
Come utilizzare i Rosject
Nel caso non si volesse installare ROS Noetic sul proprio sistema e fare il set up dell’ambiente di sviluppo, è possibile utilizzare i Rosject offerti da The Construct per poter testare i contenuti del tutorial o per seguirlo passo passo.
Per fare ciò sarà sufficiente seguire il link indicato nelle risorse e cliccare su “Run”. In questo modo si avrà accesso a una copia del Rosject utilizzato all’interno del tutorial.
Aprire terminal e IDE
Per aprire un nuovo terminale e avere accesso all’IDE forniti dal Rosject, sarà possibile utilizzare la console in basso a destra
Creare un nuovo package
Per poter creare un nuovo package sarà sufficiente spostarsi all’interno del workspace di catkin, e creare il package con l’aiuto di catkin_create_pkg. In questo caso aggiungendo come dependencies rospy (poiché scriveremo in Python) e std_msgs.
cd ~/catkin_ws
catkin_create_pkg custom_srv_pkg rospy std_msgs
Creare un nuovo file per la definizione del Service
Quello che bisogna fare ora è creare una cartella che possa contenere i file di definizione dei Service e il file per il nostro Service personalizzato.
mkdir custom_srv_pkg/srv
touch custom_srv_pkg/srv/CustomSrvMsg.srv
Definizione della struttura del Service personalizzato
I servizi sono identificati da due sezioni, divise da un triplo dash (- – -):
Request: inviata da un client a un server, con i parametri necessari all’esecuzione del servizio
Response: ritornata dal server al client, con eventuali risultati dell’esecuzione del servizio
⚠ Request e response possono essere anche vuoti
All’interno delle due sezioni possiamo usare per esempio std_msgs, ma anche altri tipi di messaggio come geometry_msgs.
Andiamo quindi a definire il nostro servizio con i seguenti parametri:
# Request
string da_stampare
geometry_msgs/Point punto
---
# Response
float64 somma
bool successo
In questo caso abbiamo una stringa da stampare, un punto tridimensionale, una variabile somma rappresentante la somma delle coordinate del punto e un booleano che indica il successo dell’esecuzione del servizio.
CMakeLists e package.xml
Per permettere la compilazione del servizio e la generazione dei relativi messaggi, bisogna apportare qualche modifica al file CMakeLists e al package.xml.
CMakeLists
Qui sarà necessario includere le seguenti linee:
cmake_minimum_required(VERSION 3.0.2)
project(custom_srv_pkg)
find_package(catkin REQUIRED COMPONENT
rospy
std_msgs
message_generation # per la generazione dei messaggi relativi al servizio
geometry_msgs # poiché abbiamo utilizzato un messaggio di questo tipo
)
add_service_files(
FILES
CustomSrvMsg.srv # il nostro file dove abbiamo definito il servizio
)
generate_messages(
DEPENDENCIES
std_msgs
geometry_msgs # per generare messaggi contenenti geometry_msgs
)
catkin_package(
CATKIN_DEPENDS rospy std_msgs
)
package.xml
All’interno del package.xml dovremo aggiungere le dependencies per la generazione e l’utlizzo dei messaggi relativi al servizio
<build_depend>message_generation</build_depend>
<build_export_depend>message_runtime</build_export_depend>
<exec_depend>message_runtime</exec_depend>
Compilazione
cd ~/catkin_ws
catkin_make –only-pkg-with-deps custom_srv_pkg
source devel/setup.bash # poiché sono stati generati nuovi messaggi e servizi
Verificare la generazione dei messaggi del Service personalizzato
Per poter verificare la presenza dei messaggi relativi al nostro nuovo messaggio e il loro contenuto possiamo utilizzare i seguenti comandi:
rossrv list | grep custom # grep custom è usato per filtrare l’output
# l’output sarà del tipo:
# custom_srv_pkg/CustomSrvMsg
rossrv show custom_srv_pkg/CustomSrvMsg
# l’output sarà del tipo:
# string da_stampare
# geometry_msgs/Point punto
# float64 x
# float64 y
# float64 z
# ---
# float64 somma
# bool successo
Importare i messaggi generati per il servizio
All’interno dello script server.py possiamo importare:
- Nel caso di un server:
- [NomeDelMessaggioDelServizio]
- [NomeDelMessaggioDelServizio]Response
- Nel caso di un client:
- [NomeDelMessaggioDelServizio]
- [NomeDelMessaggioDelServizio]Request
Nel tutorial scriveremo un esempio di un server di Servizi, quindi importeremo i messaggi in questo modo:
from custom_srv_pkg.srv import CustomSrvMsg,CustomSrvMsgResponse
# from custom_srv_pkg.srv import CustomSrvMsg,CustomSrvMsgRequest # nel caso client
Accesso ai parametri di request e response
In una possibile implementazione del nostro server accediamo a request, ricevuto dal client tramite una callback invocata ogni volta che viene richiesto il servizio, e ai relativi parametri.
Possiamo poi istanziare una response (di tipo CustomSrvMsgResponse) e riempirne i campi con le informazioni che ci interessa ritornare al client.
#! /usr/bin/env python
import rospy
from custom_srv_pkg.srv import CustomSrvMsg, CustomSrvMsgResponse
# CustomServiceRequest in caso di un client
def callback(request):
response = CustomSrvMsgResponse()
print(request.da_stampare)
response.somma = request.punto.x + request.punto.y + request.punto.z
response.successo = True
return response
rospy.init_node("service_server")
service = rospy.Service("my_service", CustomSrvMsg, callback)
rospy.spin()
Conclusione
Se siete riusciti a seguire fino a qui sarà possibile compilare il package e eseguire il nodo relativo al Service server. In questo modo sarà reso disponibile il servizio che potrà essere chiamato da linea di comando o da un client.
# terminale 1
roscore
# terminale 2
rosrun custom_srv_pkg server.py # esecuzione del nodo server.py
# terminale 3
rosservice list | grep my # mostra tutti i servizi disponibili contenenti "my"
rosservice call /my_service [TAB] [TAB] # chiama il servizio e precompone la request
0 Comments