Bases de ROS 1 Noetic
Ce chapitre présente le flux de travail de développement ROS 1 Noetic sur reComputer Jetson, y compris les espaces de travail, les packages, les outils courants, la communication par topic/service, les messages personnalisés et TF.
Les longs exemples exécutables sont enregistrés sous
./code/, et les figures associées sont enregistrées sous./images/.
Table des matières
7.2.1.1 Introduction à ROS 1
ROS 1 (Robot Operation System 1) est un framework logiciel robotique open source, maintenu par Open Robotics. Il ne s'agit pas d'un système d'exploitation au sens traditionnel, mais il fournit aux applications robotiques des mécanismes de communication, des chaînes d'outils et une bibliothèque de fonctionnalités communes, réduisant considérablement la difficulté du développement de logiciels robotiques. Il fournit les services requis par le système d'exploitation, y compris l'abstraction matérielle, le contrôle des équipements de bas niveau, la réalisation de fonctions couramment utilisées, la messagerie inter-processus et la gestion des packages. Il fournit également les outils et les fonctions de bibliothèque nécessaires pour acquérir, compiler, préparer et exécuter du code sur plusieurs ordinateurs.
Versions de ROS 1
Les éditions courantes de ROS 1 sont les suivantes :
| Nom de la version | Ubuntu | Statut de maintenance |
|---|---|---|
| Kinetic | 16.04 | Arrêtée |
| Melodic | 18.04 | Arrêtée |
| Noetic | 20.04 | Dernière version ROS 1 (LTS) |
Les exemples suivants de ce chapitre seront basés sur la version noetic de ROS 1.
L'objectif principal de ROS est de fournir un support de réutilisation de code pour la recherche et le développement en robotique. ROS est un framework distribué de processus (c'est-à-dire des « nœuds ») qui sont encapsulés dans des packages et ces packages sont facilement partagés et publiés. ROS prend également en charge un système conjoint similaire au dépôt de code, qui peut également permettre la collaboration et la diffusion en ingénierie. Cette conception permet le développement d'un projet d'ingénierie et la réalisation d'une prise de décision indépendante complète (sans restrictions ROS) du système de fichiers à l'interface utilisateur. En même temps, tous les travaux peuvent être intégrés dans les outils ROS de base.
Principales caractéristiques de ROS 1
(1) Une structure distribuée (chaque processus de travail est considéré comme un nœud, géré à l'aide d'un gestionnaire de nœuds),
(2) Support multilingue (par ex. C++, Python, etc.),
(3) Bonne élasticité (qui peut soit écrire un nœud, soit organiser de nombreux nœuds dans un projet plus vaste via roselaunch),
(4) Code open source (ROS suit l'accord BSD et est totalement gratuit pour les applications et modifications individuelles et commerciales).
Architecture globale de ROS 1
Niveau communauté open source : Cela inclut, entre autres, le partage de connaissances entre développeurs, les codes, les algorithmes.
Niveau système de fichiers : Une description du code et de l'exécutable qui peut être trouvé sur le disque dur.
Échelle de calcul : Reflète la communication entre processus et processus, processus et système.
Démarrer l'environnement de développement ROS 1
SeeedStudio Jetson Orin Nano Super DevKit, une version système locale d'ubuntu22.04, n'est pas prise en charge pour l'utilisation de ROS 1, mais pré-évaluée dans le solide, mais si vous utilisez les solides BSP que nous avons fournis, vous pouvez utiliser la commande suivante pour démarrer le conteneur Docker contenant ROS 1 dans la fenêtre du terminal du dispositif Jetson, en utilisant ubuntu22.04 :
xhost +
sudo docker run -it \
--net=host \
--privileged \
-v /dev:/dev \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e DISPLAY=$DISPLAY \
-e QT_X11_NO_MITSHM=1 \
ros:noeticSi vous achetez un dispositif Jetson sans environnement de développement ROS 1 pré-évalué, référez-vous ici pour l'installation.
Profil du graphe de calcul
Nœuds
Le nœud est le module d'implémentation de calcul le plus basique dans ROS 1 et correspond généralement à un processus exécuté indépendamment. Un système ROS n'est pas un programme unique mais un système distribué de plusieurs nœuds travaillant ensemble.
Dans ROS 1, chaque nœud a généralement une fonction relativement unique et distincte, telle que :
Acquisition de données de capteur (caméra, radar, IMU)
Traitement algorithmique (positionnement, construction, planification de route)
Sortie de contrôle (contrôle de vitesse, contrôle électrique)
Transfert de données et débogage (logs, visualisation)
Caractéristiques des nœuds ROS 1
Processus indépendant Chaque nœud est généralement un processus Linux indépendant, avec interaction entre les nœuds via les mécanismes de communication ROS.
Conception découplée La fonction n'est pas directement appelée entre les nœuds, mais communique plutôt via Topic, Service, Action, Parameter, etc., pour faciliter l'extension et la maintenance du système.
Nom unique Chaque nœud doit avoir un nom unique dans le calculateur ROS, par ex. /turtle_velocity_publisher
Exécution distribuable Le nœud peut s'exécuter sur différents hôtes tant qu'ils sont connectés au même ROS Master.
Cycle de vie géré par ROS Master Le nœud enregistre ses propres informations (nom, publication/abonnement, etc.) auprès de ROS Master au démarrage, et s'exécute par chaque nœud.
Moyens de communication courants pour le point médian ROS 1
Topic. Le nœud est utilisé pour la communication prête à l'emploi via le modèle de publication/abonnement pour les flux de données à haute fréquence.
Service Communication synchronisée basée sur requête-réponse.
Action Applicable aux tâches chronophages, prenant en charge le feedback et l'annulation.
Parameter Server (serveur de paramètres) Pour stocker les paramètres d'exécution du système.
Le nœud est le processus principal d'implémentation de calcul. ROS est composé de nombreux nœuds.
Il suffit de remplir avec [Tab] lorsque vous entrez une partie.
Voici un exemple de diagramme de nœuds :
Lorsque nous entrons [rosnode] dans la ligne de commande, et double-cliquons sur Tab, nous trouvons ces mots-clés sous la ligne de commande.
Outil en ligne de commande ROS rosnode :
Le nœud actuel et les informations de nœud sont souvent nécessaires pour développer le débogage, alors souvenez-vous de ces commandes couramment utilisées. Si cela n'est pas possible, l'utilisation de la commande rosnode peut également être consultée via l'aide de rosnode.
Message
Les liens logiques et les échanges de données entre les nœuds sont réalisés via des messages.
Lorsque nous entrons [rosmsg] dans la ligne de commande et double-cliquons sur la touche Tab, nous trouvons ces mots-clés sous la ligne de commande.
Outil en ligne de commande ROS rosmsg :
Topic
Le topic est un moyen de délivrer des informations (publication/abonnement). Chaque message est publié sur le thème correspondant, et chaque topic est d'un type fort.
Le message de topic de ROS peut être transmis en utilisant TCP/IP ou UDP, et ROS utilise par défaut TCP/IP. Basé sur la transmission TCP comme TCPROS, c'est une connexion à long terme ; basé sur UDP comme UDPROS est un mode de transmission à faible délai et efficace, mais facile à perdre des données et adapté au fonctionnement à distance.
Lorsque nous entrons [rostopic] dans la ligne de commande, puis double-cliquons sur la touche Tab, nous trouvons ces mots-clés sous la ligne de commande.
Outil en ligne de commande ROS rostopic :
Services
Le service doit également avoir un nom unique pour le modèle de requête-réponse. Lorsqu'un service est fourni par un nœud, tous les nœuds peuvent communiquer avec lui en utilisant des codes développés par le client ROS.
Lorsque nous entrons [rosservice] dans la ligne de commande, puis double-cliquons sur la touche Tab, nous trouvons ces mots-clés sous la ligne de commande.
Outil en ligne de commande ROS rosservice :
Package d'enregistrement de messages
Le package d'enregistrement de messages est un format de fichier pour sauvegarder et rejouer les données de messages ROS et est stocké dans le fichier .bag. C'est un mécanisme important pour stocker des données.
Lorsque nous entrons [rosbag] dans la ligne de commande et double-cliquons sur Tab, nous trouvons ces mots-clés sous la ligne de commande.
Outil en ligne de commande ROS rosbag :
Serveur de paramètres
Le serveur de paramètres est un dictionnaire multivarié partagé accessible en ligne et stocké sur le gestionnaire de nœuds par mot-clé.
Lorsque nous entrons [rosparam] dans la ligne de commande et double-cliquons sur la touche Tab, nous trouvons ces mots-clés sous la ligne de commande.
Outil en ligne de commande ROS rosparam :
Gestionnaire de nœuds (Master)
Le gestionnaire de nœuds est utilisé pour les thèmes, l'enregistrement des noms de service et la recherche, etc. Il n'y aura pas de communication entre les nœuds sans gestionnaire de nœuds dans tout le système ROS.
Niveau système de fichiers
Les dépendances entre les packages peuvent être configurées. Si le package A dépend du package B, B doit être plus ancien que A dans le système de construction ROS et A peut utiliser les fichiers d'en-tête et de bibliothèque dans B.
Le concept du niveau système de documentation est le suivant :
Liste de packages fonctionnels :
Cette liste indique la dépendance du package, la documentation du document source, etc. Le fichier package.xml du package est une liste de packages.
Package fonctionnel :
Le package est la forme de base de l'organisation logicielle dans le système ROS et contient des nœuds en cours d'exécution et des fichiers de configuration, etc.
Commande associée au package ROS
Kit fonctionnel intégré
Une combinaison de plusieurs packages peut être formée.
Type de message
Une note d'information préalable est requise pour envoyer le message entre les nœuds de ROS. Des messages de type standard sont fournis dans ROS et peuvent également être définis. La description du type de message est stockée dans le fichier msg sous le package.
Type de service
La structure de données sur les requêtes et réponses de service fournies par chaque processus dans ROS est définie.
Niveau communauté open source
Distribution : La version ROS est une série de packages intégrés qui peuvent être installés indépendamment avec un numéro de version. La version ROS joue un rôle similaire à celui de la distribution Linux. Cela facilite l'installation du logiciel ROS et permet de maintenir des versions cohérentes via un pool logiciel.
Dépôt : ROS s'appuie sur des sites web ou des services d'hébergement de dépôts open source et logiciels partagés où différentes agences peuvent publier et partager leurs propres logiciels et programmes robotiques.
ROSWiki : ROSWiki est le forum principal pour enregistrer des informations sur les systèmes ROS. Toute personne peut enregistrer des comptes, contribuer ses propres documents, fournir des corrections ou des mises à jour, préparer des programmes d'études et d'autres actes.
Système de tickets de bugs : Si vous trouvez un problème ou souhaitez proposer une nouvelle fonctionnalité, ROS fournit les ressources pour le faire.
Liste de diffusion (Mailing list) : La liste de diffusion des utilisateurs ROS est le principal canal de communication pour ROS, permettant l'échange de questions ou d'informations allant des mises à jour logicielles ROS à l'utilisation du logiciel ROS, comme c'est le cas pour le forum.
ROS Answer : Les utilisateurs peuvent utiliser cette ressource pour poser des questions.
Aperçu des mécanismes de communication
Topic
Le mode de communication publication-abonnement est largement utilisé dans ROS. Topic est généralement utilisé pour les communications unidirectionnelles et en continu. Topic a généralement une définition de type fort : un type de topic ne peut accepter/envoyer des messages que pour un type de données spécifique. Il n'est pas demandé au Publisher de vérifier la cohérence de type, mais le subscriber vérifie le type de md5 au moment de l'acceptation, puis signale une erreur.
Service
Service est utilisé pour traiter les communications synchrones dans les communications ROS, en utilisant la sémantique serveur/client. Chaque type de service a deux parties : requête et réponse. Pour le serveur de service, ROS ne vérifie pas les alias, seul le dernier serveur enregistré sera valide et connecté au client.
Action
Action utilise plusieurs topics pour définir des tâches, qui incluent l'objectif (Goal), le feedback (feedback) et les résultats (result). La compilation d'action produira automatiquement sept structures : Action, ActionGoal, ActionFeedback, ActionResult, Goal, Feedback et Result.
Caractéristiques d'Action :
Un mécanisme de communication de type question-réponse
Avec feedback continu
Peut être terminé pendant la mission.
Mécanisme d'information basé sur ROS réalisé
Interface pour Action :
Goal : publication des objectifs de mission
Cancel : Demande d'annulation
Status : notifier le client de l'état actuel
Feedback : Données de contrôle pour le feedback périodique sur l'exécution des tâches
Result : Envoyer les résultats de la mission au client, une seule fois.
Comparaison des modèles de communication
Composants communs
Le document de lancement launch ; conversion de coordonnées TF ; Rviz ; Gazebo ; boîte à outils QT ; (a) Navigation ; Movelt!
Launch : Le fichier Launch est un moyen d'activer simultanément plusieurs nœuds dans ROS. Il active également automatiquement le gestionnaire de nœuds ROS Master, et permet la configuration de chaque nœud, ce qui facilite grandement le fonctionnement de plusieurs nœuds.
Conversion de coordonnées TF : la robotique a souvent un grand nombre de composants dans son environnement de travail, et la position et l'attitude de différents composants sont impliquées dans la conception et les applications robotiques. TF est un package qui permet aux utilisateurs de suivre plusieurs coordonnées au fil du temps, en utilisant des structures de données arborescentes, en mettant en mémoire tampon le temps et en maintenant des relations de coordonnées entre plusieurs coordonnées, ce qui peut aider les développeurs à changer les coordonnées à tout moment, aux points d'achèvement entre les coordonnées, les vecteurs, etc.
Boîte à outils QT : Pour faciliter le débogage visuel et l'affichage, ROS fournit un package d'outils graphiques backend pour l'architecture Qt - rqt common plugins, qui contient un certain nombre d'outils pratiques : Outil de sortie de log (rqt console), Outil de visualisation de calcul (rqt graph), Outil de mappage de données (rqt plot), Outil de configuration dynamique des paramètres (rqt reconfigure)
Rviz : rviz est un outil de visualisation tridimensionnelle qui est bien compatible avec diverses plates-formes robotiques basées sur le framework logiciel ROS. Dans rviz, XML peut être utilisé pour décrire les dimensions, la masse, la position, le matériau, les articulations, etc. des robots, des objets environnants, etc., et les présenter dans les interfaces. En même temps, rviz peut afficher graphiquement en temps réel des informations sur les capteurs du robot, l'état de mouvement du robot, les changements dans l'environnement environnant, etc.
Gazebo : Gazebo est une puissante plate-forme de simulation physique tridimensionnelle avec des moteurs physiques puissants, un rendu graphique de haute qualité, des interfaces de programmation et graphiques pratiques et, surtout, open source et gratuit. Bien que les modèles robotiques dans Gazebo soient les mêmes que ceux utilisés dans rviz, les propriétés physiques des robots et de l'environnement environnant, telles que la masse, les facteurs de friction, les facteurs d'élasticité, etc., doivent être ajoutées aux modèles. Les informations des capteurs du robot peuvent également être présentées sous forme visuelle en ajoutant des environnements analogiques via des plugins.
Navigation : navigation est le kit de navigation 2D de ROS, qui, en termes simples, calcule une commande de contrôle de vitesse robotique sûre et fiable basée sur le flux d'informations et la position globale de la robotique, comme le compteur kilométrique d'entrée.
Moviet : Moviet! Le kit fonctionnel est le kit d'outils le plus couramment utilisé et est principalement utilisé pour la planification de trajectoire. Moveit! Il est essentiel que les assistants soient configurés pour certains documents qui doivent être utilisés dans la planification.
Toutes les versions de ROS 1
Lien de référence : http://wiki.ros.org/Distributions
La version ROS (publication ROS) fait référence au package logiciel ROS, similaire à la version Linux (par ex. Ubuntu). Le déploiement de la version ROS vise à permettre aux développeurs d'utiliser un dépôt de code relativement stable jusqu'à ce qu'ils soient prêts à mettre à niveau tout le contenu. En conséquence, les développeurs ROS réparent généralement ce bug de version uniquement après le déploiement de chaque version, tout en fournissant une petite quantité d'améliorations du package de base. En octobre 2019, le nom de la version de distribution principale de ROS, la date de publication et son cycle de vie sont indiqués dans le tableau ci-dessous :
Connexion de référence
Wiki officiel ROS :
Guide officiel ROS : http://wiki.ros.org/ROS/Tutorials
Installation ROS : https://wiki.ros.org/noetic/Installation/Ubuntu (ignorez ceci si ROS est déjà préinstallé)
Figures












7.2.1.2 Préparation de l'espace de travail
Répertoire de l'espace de travail
La structure de document de ROS, tous les dossiers ne sont pas obligatoires et sont conçus selon les besoins métier.
Concernant l'espace de travail
L'espace de travail est l'endroit où les documents du projet ROS sont gérés et organisés. La description visuelle est un entrepôt contenant divers travaux de projet pour ROS, ce qui facilite la gestion du système. C'est un dossier dans une interface graphique visuelle. Nos propres codes ROS sont généralement dans l'espace de travail. Il y a quatre principaux répertoires de niveau I ci-dessous :
src : espace source ; package ROS Catkin (package source)
build : Espace compilé ; informations de cache Catkin (CMake) et fichiers intermédiaires
devel : Espace de développement ; Sortie des fichiers cibles (y compris les en-têtes, la bibliothèque de liens dynamiques, la bibliothèque de liens statiques, les documents implémentables, etc.), variables d'environnement
install : espace d'installation
Le dossier d'espace de travail de niveau supérieur (qui peut être nommé aléatoirement) et src (doit être src) doivent être créés par vous-même ;
Les dossiers build et devel sont créés automatiquement par la commande catkin make ;
Les dossiers Install sont créés automatiquement par une commande Catkin make install, qui n'est presque jamais utilisée, et n'est généralement pas créée.
Remarque : L'espace de travail doit être ramené au niveau supérieur avant d'utiliser catkin make. (a) L'existence de packages sous le même espace de travail n'est pas autorisée ; Le package du même nom est autorisé dans différents espaces de travail.
mkdir -p ~/catkin_ws/src # create
cd catkin_ws/ # enter the workspace
catkin_make # build
source devel/setup.bash # source the workspace environmentPackages
Le package est une structure de fichier et une combinaison de dossiers spécifiques. Le code de programme qui réalise la même fonction est généralement placé dans un package. Seuls CMakeLists.txt et package.xml sont [obligatoires], et le reste du chemin dépend si le package est nécessaire.
Créer un package de fonctionnalité
cd ~/catkin_ws/src
catkin_create_pkg my_pkg rospy rosmsg roscpp[Rospy], [rosmsg], [roscpp] est une bibliothèque de dépendance qui peut être ajoutée selon les besoins métier, ou en ajouter d'autres, sans reconfigurer lors de la création, en oubliant que les ajouts doivent être configurés.
Structure de fichiers
|-- CMakeLists.txt # (required) build rules for the current package.
|—— package.xml # (required) package metadata and ROS dependencies.
|—— include directory # stores C++ header files
|—— config directory # stores parameter files
|—— launch directory # stores launch files (.launch or .xml)
|—— meshes directory # stores robot or simulation 3D models (.sda, .stl, .dae, etc.)
|—— urdf directory # stores robot model descriptions (.urdf or .xacro)
|—— rviz directory # rviz files
|—— src directory # C++ source code
|—— scripts directory # executable scripts, such as shell scripts (.sh) and Python scripts (.py)
|—— srv directory # custom services
|—— msg directory # custom topics
|—— action directory # custom actionsIntroduction à CMakeLists.txt
Généralités
Le CMakeLists.txt était à l'origine un document basé sur des règles pour le système de construction CMake, tandis que Catkin Builds suivait largement le style CMake de Builds, mais ajoutait quelques définitions de macro au projet ROS. Donc, en écriture, le CMakeLists.txt de Catkin est fondamentalement le même que CMake.
Ce document définit directement le processus par lequel le package dépend, quels objectifs il compile, comment il compile, etc. Donc CMakeLists.txt est très important car il spécifie les règles du code source au fichier cible, et les constructions catkin trouvent d'abord le CMakeLists.txt sous chaque package, puis compilent et construisent selon les règles.
Format
La syntaxe de base de CMakeLists.txt est la même que celle de CMake, dans laquelle Catkin a ajouté un petit nombre de macros, la structure globale étant la suivante :
Un CMakeLists.txt catkin typique inclut ces parties :
cmake_minimum_required(VERSION 3.0.2)
project(package_name)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
catkin_package()
include_directories(${catkin_INCLUDE_DIRS})
add_executable(node_name src/node_name.cpp)
target_link_libraries(node_name ${catkin_LIBRARIES})Les packages qui définissent des messages, services ou actions personnalisés utilisent également add_message_files(), add_service_files(), add_action_files() et generate_messages().
Boost activé
Si vous utilisez C++ et Boost, vous devez appeler Find package() sur Boost et spécifier quels aspects de Boost sont utilisés comme composants. Par exemple, si vous vouliez utiliser le thread Boost, vous diriez :
Find package
catkin package()
Catkin package() est une macro CMake fournie par catkin. Cela est nécessaire pour attribuer des informations spécifiques à catkin pour la construction du système, qui est utilisé pour générer des fichiers pkg-config et CMake.
Cette fonction doit être appelée avant que tout objet ne soit déclaré en utilisant add library() ou add executable(). Cette fonction a cinq paramètres optionnels :
INCLUDE DIRS - Chemins d'include d'exportation
LIBRARIES - Bibliothèque exportée du projet
CATKIN DEPENDS - Autres projets catkin sur lesquels le projet est basé
DEPENDS - Projet CMake non-catkin sur lequel le projet s'appuie. Pour une meilleure compréhension, regardez cette explication.
CFG EXTRAS - Autres options de configuration
Le document complet de la macro peut être trouvé ici.
Par exemple :
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp nodelet
DEPENDS eigen opencv)Cela indique que le dossier "include" dans le dossier du package est le point où le fichier d'en-tête est exporté. La variable d'environnement CMake ${PROJECT NAME} évalue tout ce qui a été précédemment passé à la fonction project(), dans ce cas ce sera "robot brain". "roscpp" + "nodelet" est un package logiciel qui doit exister pour construire/exécuter ce package, et "eigen" + "opencv" est une entrée dépendante du système qui doit exister pour construire/exécuter ce package.
Inclusion des chemins et bibliothèques
Avant de spécifier une cible, vous devez spécifier l'emplacement où les ressources peuvent être trouvées pour l'objectif déclaré, en particulier les fichiers d'en-tête et la bibliothèque :
Inclut le chemin - où le fichier d'en-tête (le plus souvent C/C++) peut être trouvé
Chemin de bibliothèque - Quelles bibliothèques sont situées avec la cible active ?
Include directors
link directors
Include directors()
Les paramètres pour include directories devraient être l'appel figure package et tout autre répertoire qui doit être inclus. Si vous utilisez catkin et Boost, votre include directors() devrait être comme suit :
Include directors
Le premier paramètre "include" signifie que le répertoire include/ dans le package fait également partie du chemin.
link directors()
Exemple :
link directors (~)
La fonction CMake link directors() peut être utilisée pour ajouter des chemins de bibliothèque supplémentaires, mais cela n'est pas recommandé. Tous les packages catkin et CMake ajoutent automatiquement des informations de lien à la bibliothèque dans taget target_link_libraries() lorsque vous trouvez packaged.
Voir la programmation sur cmake pour un exemple détaillé de l'utilisation de target target_link_libraries() dans Link directories().
Objectifs exécutables
Pour spécifier l'exécutable qui doit être construit, nous devons utiliser la fonction CMake add executable().
edd executeableCela construira un exécutable cible appelé MyProgram, qui est construit à partir de trois fichiers source : src/main.cpp, src/some file.cpp et src/other file.cpp.
Cibles de bibliothèque
Utilisez add_library() lorsque le package doit construire une cible de bibliothèque réutilisable. De nombreux packages de tutoriel simples n'ont besoin que d'exécutables.
add_library(${PROJECT_NAME} src/library_file.cpp)target_link_libraries
Utilisez target_link_libraries() après add_executable() ou add_library() pour lier la cible avec catkin et d'autres bibliothèques requises.
target_link_libraries(node_name ${catkin_LIBRARIES})Exemple :
(foo src/foo.cpp)
Add library (moo src/moo.cpp)
This links fly against libmoo.soVeuillez noter que dans la plupart des cas, l'utilisation de link directories() n'est pas requise, car les informations sont automatiquement introduites via find package().
Messages, services et actions
Les fichiers Message (.msg), service (.srv) et action (.action) nécessitent un constructeur de préprocesseur spécial avant que les packages ROS ne soient construits et utilisés. Les éléments clés de ces macros sont la génération de documents spécifiques au langage de programmation, afin qu'ils puissent utiliser des messages, services et actions dans le langage de programmation de leur choix. Le système de construction sera lié en utilisant tous les générateurs disponibles (par ex. gencpp, genpy, genlisp, etc.).
Trois macros ont été fournies pour traiter les messages, services et actions séparément :
add_message_files()
add_service_files()
add_action_files()
Ces macros doivent être suivies de la macro résultante :
generate_messages()
Lisez CMake Practice : https://github.com/Akagi201/learning-cmake/blob/master/docs/cmake-practice.pdf si vous n'avez jamais eu de contact avec la syntaxe de CMake. La maîtrise de CMake est très utile pour comprendre le projet ROS.
Introduction à Package.xml
Aperçu
La liste de packages est un dossier racine dans un fichier XML nommé Package.xml qui doit inclure tout package de compatibilité. Package.xml est également un package requis pour le package de catkin, une description du package, qui dans une version antérieure de ROS (système de construction Rosbuild) est appelé "manfect.xml" pour décrire les informations de base sur le package. Si vous voyez des projets ROS sur Internet qui contiennent le best.xml, c'est probablement avant la version hydro. Le package.xml contient des informations sur le nom, le numéro de version, la description du contenu, le personnel de maintenance, les licences logicielles, les outils de construction de compilation, la dépendance de construction et la dépendance de fonctionnement du package.
Les fichiers Package.xml doivent contenir la génération de messages, run depend doit contenir l'exécution des messages.
Format
Un package.xml typique contient les métadonnées du package et les déclarations de dépendance :
<package format="2">
<name>package_name</name>
<version>0.0.0</version>
<description>Package description</description>
<maintainer email="user@example.com">Maintainer Name</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>rospy</depend>
<depend>std_msgs</depend>
</package>Relations de dépendance
La liste de packages avec des étiquettes minimales ne spécifie aucune dépendance sur d'autres packages. Le package a six dépendances :
Construit une dépendance
Construit une dépendance
Exécution de la dépendance
Dépendance de test
Les dépendances d'outil de construction
L'outil de document dépend de
Onglets joints
- Auteur du package
Par exemple :
"Site Web"
Seed.
Espace de travail pour préparer des exemples officiels
Notez que les opérations ROS 1 doivent être effectuées dans des conteneurs Docker existants.
Après être entré dans le conteneur Docker, téléchargez l'exemple ROS officiel (si disponible) :
git clone https://github.com/ros/ros_tutorials.git -b noetic-develCeci est un cas de ROS 1 basé sur C++ :
cd ros_tutorials/
mkdir src
cp roscpp_tutorials/ src/ -r
catkin_make # start buildingLa compilation a été terminée comme suit :
Une fois la compilation terminée, l'initialisation est requise avant que l'espace de travail puisse être suivi :
source devel/setup.bashFigures


7.2.1.3 Commandes et outils courants
Méthode de nœud de commencement
documents launch
Il y a au moins deux façons de démarrer un fichier launch avec une commande roslanch :
- Démarrer avec le chemin du package ROS
Le format est le suivant :
roslaunch package_name launch_file_name
roslaunch pkg_name launchfile_name.launch- Chemin absolu vers le fichier launch
Le format est le suivant :
roslaunch path_to_launchfileQuelle que soit la façon dont vous démarrez le fichier launch, vous pouvez ajouter des paramètres à l'arrière, qui sont plus courants.
--screen : facilite le débogage des informations du nœud ROS (le cas échéant) à afficher à l'écran au lieu de les sauvegarder dans un fichier journal
arg: =value : si la variable à donner dans le fichier launch est donnée, la valeur peut être donnée de cette façon, par ex. :
roslaunch pkg_name launchfile_name model:=urdf/myfile.urdf # the launch file has a `model` argument that must be setou
roslaunch pkg_name launchfile_name model:='$(find urdf_pkg)/urdf/myfile.urdf' # use `find` to provide the pathLa commande roslaunch est exécutée pour d'abord détecter si le rosmaster du système est en cours d'exécution ou, s'il est démarré, pour utiliser le rosmaster existant ; si vous ne démarrez pas, vous pouvez d'abord démarrer le rosmaster, puis exécuter les paramètres dans le fichier launch, et vous pouvez démarrer plusieurs nœuds à notre pré-configuration.
Il convient de noter que le fichier launch n'a pas besoin d'être compilé et peut être exécuté directement comme décrit ci-dessus.
rosrun
Le gestionnaire de nœuds (master) doit être activé, et master est utilisé pour de nombreux processus dans le système de gestion, et chaque nœud démarre en enregistrant et en gérant la communication entre nœud et nœud. Après le démarrage du master, il passe par le master pour enregistrer chaque nœud. Entrez la commande dans le terminal Ubuntu :
roscoreDémarrage du nœud, rosrun+nom du package+ nom du nœud ; La méthode rosrun n'exécute qu'un seul nœud à la fois.
rosrun [--prefix cmd] [--debug] pkg_name node_name [ARGS]Rosrun recherchera un programme exécutable appelé Package, qui apportera des ARGS optionnels.
Python
Si Python est le code, vous pouvez démarrer directement dans le répertoire où se trouve le fichier py, en faisant attention à la différence entre Python2 et python3.
Démarrer une petite tortue
roscore # start roscore in the first terminal
rosrun turtlesim turtlesim_node # start the turtlesim node in the second terminal
rosrun turtlesim turtle_teleop_key # start keyboard teleoperation in the third terminalUne fois le démarrage terminé, vous pouvez manipuler le mouvement des petites tortues via l'entrée clavier, et le curseur doit contrôler le mouvement des petites tortues en cliquant sur le clavier [haut], [bas], [gauche], [droite] sous la commande de [rosrun turtlesim turtle teleop key].
Et le terminal rosrun turtlesim turtlesim node imprimera quelques logs de petite tortue.
[ INFO] [1607648666.226328691]: Starting turtlesim with node name /turtlesim
[ INFO] [1607648666.229275030]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]Lancement de la deuxième tortue
Dans le premier terminal, démarrez le nœud via le fichier launch :
roslaunch turtle_tf turtle_tf_demo.launchGardez le nœud de contrôle clavier précédent comme actif
À ce stade, appuyez sur le clavier [haut], [bas], [gauche], [droite] pour conduire le mouvement de la petite tortue ; Une petite tortue peut être observée en suivant un autre mouvement.
documents launch
Généralités
Un programme de nœud dans ROS n'exécute généralement qu'une seule fonction, mais un robot ROS complet fonctionne généralement simultanément avec de nombreux programmes de nœuds et collabore les uns avec les autres pour effectuer des tâches complexes, et cela nécessite que de nombreux programmes de nœuds soient initiés lorsqu'un robot est activé, ce qui est plus gênant si un nœud démarre un nœud. Le fichier launch et la commande roslaunch permettent d'activer plusieurs nœuds une fois, facilitent le "one-key" et définissent des paramètres riches.
Format de documentation
Le fichier launch est essentiellement un fichier xml, qui peut être mis en évidence dans certains éditeurs, lisible, ajouté à l'en-tête ou non ajouté
Quoi ? "0" ? >
Similaire à d'autres fichiers au format xml, les fichiers launch sont écrits par balises (tag), les balises principales sont les suivantes :
Fichier de code : 7-2-1-3-common-commands-and-tools-example-01.xml
<launch> <!-- root tag -->
<node> <!-- node and parameters to start -->
<include> <!-- include another launch file -->
<machine> <!-- target machine -->
<env-loader> <!-- set environment variables -->
<param> <!-- define a parameter on the parameter server -->
<rosparam> <!-- load YAML parameters into the parameter server -->
<arg> <!-- define an argument -->
<remap> <!-- set topic remapping -->
<group> <!-- set a group -->
</launch> <!-- root tag -->- Balise [node]
La balise [node] est la partie centrale du fichier launch.
Fichier de code : 7-2-1-3-common-commands-and-tools-example-02.xml
<launch>
<node pkg="package_name" type="executable_file" name="node_name"/>
<node pkg="another_package" type="another_executable" name="another_node"></node>...
</launch>dont
pkg est le nom du package du nœud
type est le document actionnable dans le package, qui, s'il est préparé par Python, peut être .py ou, s'il est préparé par C++, le nom du document exécutable après que le fichier source a été compilé.
Le nom est le nom après le démarrage du nœud, et chaque nœud a son propre nom unique.
Remarque : roslaunch ne peut pas garantir l'ordre de démarrage du nœud, donc tous les nœuds dans le fichier launch devraient être aussi bons que l'ordre de démarrage.
Plus de paramètres peuvent être définis, comme suit :
Fichier de code : 7-2-1-3-common-commands-and-tools-example-03.xml
<launch>
<node
pkg=""
type=""
name=""
respawn="true"
required="true"
launch-prefix="xterm -e"
output="screen"
ns="namespace"
/>
</launch>Dans l'ordre ci-dessus,
respawn : Si ce nœud est fermé, est-il automatiquement redémarré ?
required : si ce nœud est fermé, si tous les autres nœuds sont fermés
launch-prefix : S'il faut ouvrir une nouvelle fenêtre pour l'exécution. Par exemple, une nouvelle fenêtre devrait être ouverte pour le contrôle du nœud lorsque les contrôles de mouvement robotique sont requis via des fenêtres ; Ou lorsque le nœud a une sortie d'informations qui ne veut pas se mélanger avec d'autres informations de nœud.
output : par défaut, launch démarre les informations de nœud dans le fichier journal suivant, qui peut être affiché à l'écran en définissant les paramètres ici
ns : Intégrer le nœud dans un espace de noms différent, c'est-à-dire ajouter un préfixe ns avant le nom du nœud. Pour réaliser ce type d'opération, le nom du nœud et le nom du topic sont définis dans le fichier source du nœud en utilisant un nom relatif, c'est-à-dire sans symbole /.
Le nom de la source de calcul est divisé en :
-
Nom de base, par ex. topic
-
Nom global, par ex. : /A/topic
-
Nom relatif, par ex. A/topic
-
Noms privés, par ex. ~topic
Il y a cette ligne de code au moment de la publication ou de la réservation.
ros::init(argc, argv, "publish_node");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::string>("topic",1000);- Balise [remap]
Apparaît souvent comme une sous-balise pour une balise de nœud pour modifier le topic. Dans de nombreux fichiers rosnode, le topic de réception ou d'envoi peut ne pas avoir été spécifié, mais seulement remplacé par input topic et output topic, de sorte que les noms de topic abstraits sont utilisés au lieu des noms de topic dans des scènes spécifiques.
En bref, la fonction de remap est de faciliter l'application du même fichier de nœud à un environnement différent, en utilisant remap topic de l'extérieur sans changer le fichier source.
Les formats d'utilisation courants pour remap sont les suivants :
Fichier de code : 7-2-1-3-common-commands-and-tools-example-04.xml
<node pkg="some" type="some" name="some">
<remap from="origin" to="new" />
</node>- Include
Cette balise est utilisée pour ajouter un autre fichier launch à ce fichier launch, similaire à l'imbrication de fichiers launch. Format de base :
"Path-to-launch-file"
Le chemin du fichier supérieur peut être donné à un chemin spécifique, mais généralement pour la portabilité du programme, il est préférable de donner le chemin du fichier avec une commande find :
<include file=$(find package-name)"/>
Pour la commande ci-dessus, la valeur de $(find package-name) est égale au chemin du package correspondant dans cette machine. Cela permet de trouver le chemin correspondant même si l'autre master est remplacé par le même package.
Parfois, un autre nœud introduit par launch peut avoir besoin d'un nom uniforme ou d'un nom de nœud avec des caractéristiques similaires, telles que /my/gps, /my/lidar, /my/imu, ou le nœud a un préfixe uniforme qui est facile à rechercher. Cela peut être réalisé en définissant les propriétés ns (namespace), avec les commandes suivantes :
<include file=$(find package-name) "ns= "my"/>
- Balise
La répétition des paramètres par [arg] est possible et peut être facilement modifiée à plusieurs endroits. Trois méthodes courantes :
<arg name= "foo" : une déclaration [arg] mais pas une valeur. À un stade ultérieur, vous pouvez attribuer une valeur par ligne de commande ou par la balise [include].
<arg name= "foo" default= "1" : valeur par défaut.: Une valeur fixe.
Attribuer une valeur par ligne de commande
Roslaunch pack name file name.launch arg1:=value1 arg2:=value2
- Remplacement de variables
Il y a deux remplacements de variantes couramment utilisés dans les fichiers launch
$(find pkg) : par exemple, $(find rospy)/manifest.xml. Les chemins basés sur le package sont fortement recommandés lorsque c'est possible.
$(arg arg_name) : définit une valeur par défaut ; l'utiliser lorsqu'aucune substitution n'est fournie
Par exemple :
Fichier de code : 7-2-1-3-common-commands-and-tools-manifest.xml
<arg name="gui" default="true" />
<!-- set a default value; use it when no override is provided -->
<param name="use_gui" value="$(arg gui)"/>Un autre exemple :
<node pkg="package_name" type="executable_file" name="node_name" args="$(arg a) $(arg b)" />Après avoir défini cette valeur peut être donnée aux paramètres args lorsque le roslaunch est démarré
roslaunch package_name file_name.launch a:=1 b:=5- Balise
Contrairement à [arg], [param] est partagé, et sa valeur n'est pas limitée à value, elle peut être un fichier, même une ligne de commande.
Format
Fichier de code : 7-2-1-3-common-commands-and-tools-example-06.xml
<param name="param_name" type="type1" value="val"/> # type can be omitted; ROS infers it
<param name="param_name" textfile="$(find pkg)/path/file"/> # read file content as a string
<param name="param_name" command="$(find pkg)/exe '$(find pkg)/arg.txt'"/>
Example:
<param name="param" type="yaml" command="cat '$(find pkg)/*.yaml'"/> # store command output in the parameter[Param] peut être dans le contexte global, son nom est le nom d'origine, ou dans une plage plus petite, comme Node, et son nom global est node/param.
Par exemple, dans le contexte global, définissez comme suit :
<param name="publish_frequency" type="double" value="10.0" />Définissez ce qui suit dans la plage de nœuds
Fichier de code : 7-2-1-3-common-commands-and-tools-example-07.xml
<node name="node1" pkg="pkg1" type="exe1">
<param name="param1" value="False"/>
</node>Si la liste [param] des serveurs avec rosparam list, oui
/publish_frequency
/node1/param1 # namespace prefix is added automaticallyRemarque : Bien que l'espace de noms ait été ajouté au nom [param], il est toujours global.
[Rosparam]
[Param] ne peut opérer que sur un seul [Param] et seulement sous trois formes : value, textfile, common, renvoie le contenu individuel de [Param]. [Rosparam] permet des opérations par lots et inclut des commandes pour le réglage des paramètres, par ex. dump, delete, etc.
load : Charger un lot de params à partir du fichier Yaml dans le format suivant :
<rosparam command="load" file="$(find rosparam)/example.yaml" />Delete : Supprimer certains param
<rosparam command="delete" param="my_param" />Opération d'attribution similaire à [param]
<rosparam param="my_param">[1,2,3,4]</rosparam>Ou...
Fichier de code : 7-2-1-3-common-commands-and-tools-example-08.xml
<rosparam>
a: 1
b: 2
</rosparam>[Rosparam] peut également être placé dans [node], à ce moment-là l'espace de noms du nœud.
- Group
Si vous voulez la même configuration pour plusieurs nœuds, par exemple, dans le même espace de noms, remapper le même topic, vous pouvez utiliser [group]. Toutes les balises communes peuvent être utilisées dans [group], par exemple
Fichier de code : 7-2-1-3-common-commands-and-tools-example-09.xml
<group ns="rosbot">
<remap from="chatter" to="talker"/> # applies to following nodes in this group
<node... />
<node... >
<remap from="chatter" to="talker1"/> # each node can override the remap
</node>
</group>Conversion de coordonnées TF
tf est un package qui permet aux utilisateurs de suivre plusieurs coordonnées à tout moment. tf maintient la relation entre les coordonnées dans la structure d'un tampon en temps réel et permet aux utilisateurs de convertir des points, des vecteurs, etc. à tout moment entre deux trames quelconques.
Le package Tf est celui qui convertit les coordonnées d'un point dans un système de coordonnées en coordonnées d'un autre. Le capteur peut voir un système de coordonnées, la machine peut voir un système de coordonnées et la barrière peut voir un point.
Après l'activation de deux petites tortues, effectuez les opérations suivantes.
Outils courants tf
- Outil view frames
Il est capable d'écouter toutes les coordonnées tf diffusées via ROS à l'heure actuelle et de dessiner des arbres pour indiquer la connexion entre les coordonnées, générant un fichier appelé frame.pdf et le sauvegardant à sa position locale actuelle.
rosrun tf view_frames- Outil rqt tf tree
Bien que view frames puisse sauvegarder la relation de coordonnées actuelle dans un fichier hors ligne, il ne peut pas refléter la relation de coordonnées en temps réel, il est donc possible de mettre à jour la relation de coordonnées en temps réel avec rqt tf tree
rosrun rqt_tf_tree rqt_tf_tree- Outil tf echo
En utilisant l'outil tf echo, vous pouvez voir la relation entre les deux systèmes de référence radio.
rosrun tf tf_echo <source_frame> <target_frame>Imprime la transformation rotationnelle du cadre source au cadre cible ; Par exemple :
rosrun tf tf_echo turtle1 turtle2- Static transform publisher
Publie des coordonnées statiques entre les deux coordonnées, qui ne changent pas de positions relatives. Format de commande :
static_transform_publisher x y z yaw pitch roll frame_id child_frame_id period_in_ms
static_transform_publisher x y z qx qy qz qw frame_id child_frame_id period_in_msUtilisation dans launch :
Fichier de code : 7-2-1-3-common-commands-and-tools-example-10.xml
<launch>
<node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 1 link1_parent link1 100" />
</launch>- Plugin Roswtf
Un plugin pour analyser votre configuration tf actuelle et essayer d'identifier les problèmes courants.
roswtfSystème commun de coordonnées
Les coordonnées habituelles sont le frame id, avec map, odom, base link, base footprint, base laser, etc.
Coordonnée mondiale (map)
Les coordonnées Map sont un système de coordonnées fixe du monde avec un axe Z pointant vers le haut. La posture de la plate-forme mobile vis-à-vis du système Map ne devrait pas bouger de manière significative au fil du temps. Les coordonnées Map ne sont pas continues, ce qui signifie que l'attitude de la plate-forme mobile dans le système Map peut être séparée à tout moment. Paramètres typiques, les modules de positionnement sont basés sur la surveillance des capteurs, recalculant constamment la position des robots dans les coordonnées mondiales, éliminant ainsi les déviations, mais peuvent sauter lorsque de nouvelles informations de capteur arrivent. Les coordonnées Map sont utiles comme référence globale à long terme, mais les sauts en font une mauvaise référence pour les capteurs locaux et les capteurs.
odom
Odom est un système de coordonnées global qui enregistre la posture de mouvement actuelle du robot via un compteur kilométrique. La position de la plate-forme mobile dans les coordonnées odom est libre de se déplacer sans aucune limite, ce qui empêche les coordonnées odom de servir de référence globale à long terme. C'est pour distinguer entre les concepts de coordonnées et de kilométrage calculés sur la base de l'encodeur (ou visuel, etc.). Mais il y a aussi une relation, et la matrice de transformation du topic odom est la relation tf de odom->base link. Les coordonnées odom et map coïncident au début du mouvement robotique. Cependant, avec le temps, il n'y a pas de chevauchement, et la déviation est l'erreur cumulative du compteur kilométrique. Une estimation de position (localisation) est donnée dans certains packages de co-correction tels que amcl, qui peut être obtenue par le tf de Map->base link, donc la différence entre la position et la position kilométrique est la différence entre les coordonnées de l'odom et de la Map. Si votre calcul odom n'est pas erroné, le tf map-odom est nul. Le système de coordonnées odom est utile comme référence locale à court terme, mais la déviation l'empêche d'être une référence à long terme.
Coordonnées de base (base link)
Le système de coordonnées du robot (matrice) chevauche le centre robotique, qui est généralement le centre de rotation robotique.
Base footprint : L'origine est la projection de l'origine de base link sur le sol, avec une certaine différence (valeurs z).
Relation entre les coordonnées
Dans les systèmes robotiques, nous utilisons un arbre pour connecter toutes les coordonnées, donc chacune a une coordonnée patrilinéaire et aléatoire, comme suit : Map-> odom-> base link - la coordonnée mondiale est le père de la coordonnée odom et la coordonnée odom est le père de base link. Bien que, intuitivement, Map et odom devraient être connectés à base link, cela n'est pas autorisé, car un seul parent peut être trouvé dans chaque système.
Autorisations du système de coordonnées
La conversion de odom à base link est calculée et publiée par la source du compteur kilométrique. Cependant, le module localisateur ne publie pas le transfert (transform) de Map à base link. Au lieu de cela, le module localisateur reçoit la transform de odom à base link, et utilise ces informations pour publier la transform de map à odom.
rqt (outil QT)
Ouvre la fenêtre de ligne de commande et entre rosrun rqt et double-clique sur la touche Tab pour voir ce qui est contenu dans l'outil QT dans ROS, comme indiqué dans la figure ci-dessous :
Alors prenons l'exemple des petites tortues et donnons une brève introduction à certains des outils QT utilisés :
- Visualisation du graphe de calcul rqt graph
Ouvre la fenêtre de ligne de commande et entre la commande suivante et une fenêtre de dialogue apparaît.
Rosrun rqt gram rqt gram
Il ressort clairement des images que le nœud /teleop_turtle est transmis via le topic /turtle1/cmd_vel au nœud /turtlesim.
/teleop_turtle est le nœud avec la fonction Publisher.
/turtlesim est le nœud avec la fonction subscriber.
Cet article fait partie de notre couverture spéciale Zambie.
- rqt topic Voir les topics
rosrun rqt topic rqt topic
Grâce à cet outil, nous pouvons clairement voir des informations en temps réel sur les changements des petites tortues.
- rqt publisher
rqt publisher a fourni un plugin GUI pour publier n'importe quel message avec des valeurs de champ fixes ou calculées. Ouvre la fenêtre de ligne de commande et entre la commande suivante et une fenêtre de dialogue apparaît.
rosrun rqt_publisher rqt_publisherCliquez sur la boîte de sélection à droite de Topic pour trouver le topic /turtle1/cmd_vel dont nous avons besoin et cliquez à droite pour ajouter le numéro comme suit :
- rqt plot mappage de données
Les instructions de référence sont les suivantes :
rosrun rqt_plot rqt_plot- rqt console sortie de log
Le système de log RS (log) fonctionne pour générer des messages de log qui sont affichés à l'écran, envoyés à un topic spécifique ou stockés dans un fichier log spécifique pour faciliter le débogage, l'enregistrement, l'alarme, etc.
Le message de log dans ROS peut être divisé en 5 niveaux selon la gravité : DEBUG, INFO, WARN, ERROR, FATAL. Tant que le programme peut s'exécuter, aucune attention ne doit être portée, mais la présence de ERROR et FATAL indique qu'il y a de graves problèmes avec le programme qui le rendent impossible à exécuter.
rosrun rqt_console rqt_consoleL'outil de sortie de log fait partie du cadre ROS Logging, qui montre les informations de sortie pour les nœuds, et nous pouvons voir sur la carte que la tortue a heurté le mur.
API courante
- rqt reconfigure configuration dynamique des paramètres
Les instructions de référence sont les suivantes :
rosrun rqt_reconfigure rqt_reconfigureSource de l'image ROS wiki :
Rviz
rviz est un outil graphique qui peut facilement exécuter graphiquement le programme ROS. Il est également plus simple à utiliser.
[Set initial pose], [Set target pose]
L'interface rviz se compose principalement de :
1 : Zone de vue 3D pour l'affichage visuel des données, qui n'est actuellement pas disponible et donc noire.
2 : Barre d'outils, qui fournit des outils tels que le contrôle de perspective, la définition de cible, l'emplacement de distribution, etc.
3 : Affiche une liste d'éléments pour montrer le plugin d'affichage actuellement sélectionné, qui peut configurer les propriétés de chaque plugin.
4 : Réglage de perspective, avec plusieurs observations disponibles.
5 : Zone d'affichage du temps montrant l'heure actuelle du système et l'heure ROS.
Ajouter un affichage
Étape 1 : Cliquez sur le bouton [Add]. Une boîte apparaîtra.
Étape 2 : Ajoutez par type d'affichage [By display type], bien que les coordonnées puissent être affichées seulement si elles modifient le topic correspondant ; Vous pouvez également ajouter directement en sélectionnant le topic [by topic] afin de l'afficher correctement.
Étape 3 : Cliquez sur [OK].
Commandes ROS courantes
Figures













7.2.1.4 Publisher
Publisher
Le publisher, par définition, agit comme un éditeur. Ce message, qui pourrait être envoyé par la machine inférieure aux informations du capteur sur la machine, a ensuite été empaqueté et envoyé au subscriber du topic ; Il peut également être possible de calculer les données sur l'appareil et de les empaqueter et de les envoyer au subscriber qui s'abonne au topic.
Création de l'espace de travail et du kit de topic
Création d'espaces de travail
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspaceCompilation de l'espace de travail
cd ~/catkin_ws/
catkin_makeMise à jour des variables d'environnement
source devel/setup.bashExamen des variables d'environnement
echo $ROS_PACKAGE_PATHCréer des packages
cd ~/catkin_ws/src
catkin_create_pkg learning_topic std_msgs rospy roscpp geometry_msgs turtlesimNote explicative : learning topic est le nom du kit fonctionnel
Construire des packages
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bashCréer un publisher
Étapes de création
Initialisation des nœuds ROS
- Créer des handles
- enregistrer les informations du nœud auprès de ROS Master, y compris le nom et le type d'informations publiées et la longueur de la file d'attente
- Créer et initialiser les données de message
Cinq, recycler le message à une certaine fréquence
Implémentation C++
- Créer un fichier C++ (fichier suffixé .cpp) dans le dossier src du package nommé turtle development publisher.cpp (rappels d'utilisation de base de vim : 14 avec l'éditeur Vim)
touch turtle_velocity_publisher.cpp # create the file
vim turtle_velocity_publisher.cpp # edit the file- Copier le code du programme ci-dessous dans le fichier turtle development publisher.cpp
Fichier de code : 7-2-1-4-publisher-turtle_velocity_publisher.cpp
/*Create a turtlesim velocity publisher.*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv){
ros::init(argc, argv, "turtle_velocity_publisher");//Initialize the ROS node.
ros::NodeHandle n;//Create a node handle.
//Create a publisher for /turtle1/cmd_vel with geometry_msgs::Twist messages and queue size 10.
ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
ros::Rate loop_rate(10);//Set the loop rate.
while (ros::ok()){
//Initialize a message with the same type as the publisher.
geometry_msgs::Twist turtle_vel_msg;
turtle_vel_msg.linear.x = 0.8;
turtle_vel_msg.angular.z = 0.6;
turtle_vel_pub.publish(turtle_vel_msg);// Publish the velocity message.
//Print the published velocity.
ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", turtle_vel_msg.linear.x, turtle_vel_msg.angular.z);
loop_rate.sleep();//Sleep according to the loop rate.
}
return 0;
}La structure du répertoire du projet édité est la suivante :
catkin_ws/
├── CMakeLists.txt
└── src/
├── CMakeLists.txt
└── learning_topic/
├── CMakeLists.txt
├── package.xml
└── src/
└── turtle_velocity_publisher.cpp-
Organigramme du programme, qui correspond au contenu 1.3.1
-
Dans catkin ws/src/learning_topic/CMakeLists.txt, sous la zone construite, ajoutez ce qui suit :
(rappels d'utilisation de base de vim : 14 avec l'éditeur Vim)
Fichier de code : 7-2-1-4-publisher-example-02.cmake
add_executable(turtle_velocity_publisher src/turtle_velocity_publisher.cpp)
target_link_libraries(turtle_velocity_publisher ${catkin_LIBRARIES})Notez de changer le CMakeLists.txt au bon chemin
- Recompilation des codes sous le répertoire de l'espace de travail
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the programProcédures opérationnelles
Ouvrir le premier terminal exécutant roscore :
roscoreExécuter le nœud Little Turtle
rosrun turtlesim turtlesim_nodeExécuter le lanceur, continuer à envoyer de la vitesse à la tortue.
rosrun learning_topic turtle_velocity_publisher-
Résultat attendu
-
Description du fonctionnement de la procédure
Lorsque vous entrez la liste des topics au terminal, vous trouverez le topic de /turtle1/cmd_vel.
Nous le découvrirons avec Rostopicinfo /turtle1/cmd_vel
Cela signifie que la tortue est un subscriber du topic de vitesse de /turtle1/cmd_vel, donc le publisher continue d'envoyer des données de vitesse et lorsque les tortues sont reçues, elles commencent à se déplacer à la vitesse.
Implémentation Python
-
Sous le répertoire du package, créez un nouveau dossier scripts, puis un nouveau fichier Python (suffixe de fichier .py) sous le dossier scripts nommé turtle development publisher.py
-
Copier le code du programme suivant dans le fichier turtle development publisher.py
Fichier de code : 7-2-1-4-publisher-suffix.py
#!/usr/bin/env python3
import rospy
from geometry_msgs.msg import Twist
def turtle_velocity_publisher():
rospy.init_node('turtle_velocity_publisher', anonymous=True) # Initialize the ROS node.
# Create a turtlesim velocity publisher on /turtle1/cmd_vel. The message type is geometry_msgs/Twist and the queue size is 8.
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=8)
rate = rospy.Rate(10) # Set the loop rate.
while not rospy.is_shutdown():
# Initialize a geometry_msgs::Twist message.
turtle_vel_msg = Twist()
turtle_vel_msg.linear.x = 0.8
turtle_vel_msg.angular.z = 0.6
# Publish the message.
turtle_vel_pub.publish(turtle_vel_msg)
rospy.loginfo("linear is:%0.2f m/s, angular is:%0.2f rad/s",
turtle_vel_msg.linear.x, turtle_vel_msg.angular.z)
rate.sleep()# Sleep according to the loop rate.
if __name__ == '__main__':
try:
turtle_velocity_publisher()
except rospy.ROSInterruptException:
pass-
Organigramme du projet
-
Procédures opérationnelles
Ouvrir le premier terminal exécutant roscore
roscoreExécuter le nœud Little Turtle
rosrun turtlesim turtlesim_nodeExécuter le lanceur, continuer à envoyer de la vitesse à la tortue.
rosrun learning_topic turtle_velocity_publisher.pyRemarque : Avant l'exécution, une autorisation exécutable doit être ajoutée au turtle development publisher.py pour ouvrir le terminal dans le dossier turtle development publisher.py.
sudo chmod a+x turtle_velocity_publisher.pyTous les Pythons doivent ajouter des autorisations d'exécution, sinon ils auront tort !
Figures






7.2.1.5 Subscriber
Subscribers
s'abonne, reçoit les données publiées par le publisher, puis entre dans sa fonction de callback, où les données reçues sont traitées. Le contenu principal est une fonction de callback, et chaque subscriber s'abonne au topic.
Créer un subscriber
Étapes de création
Initialisation des nœuds ROS
-
Créer des handles
-
Topics pour l'abonnement
-
Boucler le message du topic et le récupérer dans la fonction de callback
5 ), terminer le traitement du message dans une fonction de callback.
L'espace de travail de ce chapitre suit l'espace de travail créé dans la section IV.
Implémentation C++
-
Créer un nouveau fichier C++ dans le répertoire du tutoriel
publishingsous le dossier src du package créé nommé turtle pose subscriber.cpp -
Copier le code du programme inférieur dans le fichier turtle pose subscriber.cpp
Fichier de code : 7-2-1-5-subscriber-subscriber.cpp
/*Create a subscriber for the current turtlesim pose.*/
#include <ros/ros.h>
#include "turtlesim/Pose.h"
// The callback runs when a subscribed message is received.
void turtle_poseCallback(const turtlesim::Pose::ConstPtr& msg){
// Print the received message.
ROS_INFO("Turtle pose: x:%0.3f, y:%0.3f", msg->x, msg->y);
}
int main(int argc, char **argv){
ros::init(argc, argv, "turtle_pose_subscriber");// Initialize the ROS node.
ros::NodeHandle n;//Create a node handle.
// Create a subscriber for /turtle1/pose and register poseCallback.
ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, turtle_poseCallback);
ros::spin(); // Wait for callbacks.
return 0;
}catkin_ws/
├── CMakeLists.txt
└── src/
├── CMakeLists.txt
└── learning_topic/
├── CMakeLists.txt
├── package.xml
└── src/
└── turtle_velocity_publisher.cpp
└── turtle_pose_subscriber.cpp-
Organigramme du programme, correspondant au contenu 5.2.1
-
Dans catkin ws/src/learning_topic/CMakeLists.txt, sous la zone construite, ajoutez ce qui suit :
(rappels d'utilisation de base de vim : 14 avec l'éditeur Vim)
Add executeable (turtle pose subscriber src/turtle_pose_subscriber.cpp)
{\cHFFFFFF}{\cH00FFFF}- Codes compilés sous le répertoire de l'espace de travail
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the programProcédures opérationnelles
Ouvrir le premier terminal exécutant roscore
roscoreLe deuxième terminal exécute le nœud tortue.
rosrun turtlesim turtlesim_nodeLe troisième terminal exécute le nœud d'abonnement et continue de recevoir des données sur la position de livraison des tortues
rosrun learning_topic turtle_pose_subscriber- Description du fonctionnement de la procédure
Après avoir exécuté le nœud de la petite tortue, les tortues continuent d'envoyer leurs messages de position, et le topic est,
/turtle1/pose
Et quand il s'exécute, il reçoit des messages de données envoyés par les tortues, puis les imprime dans la fonction echo.
Implémentation Python
-
Sous le répertoire du package, créez un nouveau dossier scripts puis un nouveau fichier Python (suffixe de fichier .py) dans le dossier scripts, nommé turtle pose subscriber.py
-
Copier le code du programme suivant dans le turtle pose subscriber.py
Fichier de code : 7-2-1-5-subscriber-suffix.py
#!/usr/bin/env python3
import rospy
from turtlesim.msg import Pose
def poseCallback(msg):
rospy.loginfo("Turtle pose: x:%0.3f, y:%0.3f", msg.x, msg.y)
def turtle_pose_subscriber():
rospy.init_node('turtle_pose_subscriber', anonymous=True)# Initialize the ROS node.
# Create a subscriber for /turtle1/pose and register poseCallback.
rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
rospy.spin()# Wait for callbacks.
if __name__ == '__main__':
turtle_pose_subscriber()-
Organigramme du projet
-
Procédures opérationnelles
Exécuter roscore
roscoreExécuter le nœud Little Turtle
rosrun turtlesim turtlesim_nodeExécuter le subscriber et continuer à recevoir des données sur la position de livraison de la tortue
rosrun learning_topic turtle_pose_subscriber.pyFigures





7.2.1.6 Messages de topic personnalisés et utilisation
Exécutez les commandes dans le conteneur Docker ROS 1 Noetic décrit dans 7.2.1.1 Introduction à ROS 1.
Cette section crée et utilise un message de topic personnalisé nommé Information.msg. L'exemple continue avec le package learning_topic créé précédemment.
Créer le fichier de message
Créez le répertoire msg et définissez le message personnalisé :
cd ~/catkin_ws/src/learning_topic
mkdir -p msg
vim msg/Information.msgFichier de code : 7-2-1-6-custom-topic-messages-and-usage-Information.msg
string company
string cityMettre à jour package.xml
Ajoutez les dépendances de génération/exécution de message à package.xml :
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>Mettre à jour CMakeLists.txt
Ajoutez la génération de message à CMakeLists.txt :
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
add_message_files(
FILES
Information.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS message_runtime
)Construisez l'espace de travail :
cd ~/catkin_ws
catkin_make
source devel/setup.bashPublisher et Subscriber C++
Créez les fichiers suivants sous ~/catkin_ws/src/learning_topic/src.
Fichier de code : 7-2-1-6-custom-topic-messages-and-usage-Information_publisher.cpp
/**
* Publish /company_info with the custom learning_topic::Information message type.
*/
#include <ros/ros.h>
#include "learning_topic/Information.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "company_information_publisher");
ros::NodeHandle nh;
ros::Publisher info_pub = nh.advertise<learning_topic::Information>("/company_info", 10);
ros::Rate loop_rate(1);
while (ros::ok())
{
learning_topic::Information info_msg;
info_msg.company = "Seeed";
info_msg.city = "Shenzhen";
info_pub.publish(info_msg);
ROS_INFO("Information: company:%s city:%s", info_msg.company.c_str(), info_msg.city.c_str());
loop_rate.sleep();
}
return 0;
}Fichier de code : 7-2-1-6-custom-topic-messages-and-usage-Information_subscriber.cpp
/**
* Subscribe to /company_info with the custom learning_topic::Information message type.
*/
#include <ros/ros.h>
#include "learning_topic/Information.h"
void companyInfoCallback(const learning_topic::Information::ConstPtr& msg)
{
ROS_INFO("Company: %s, city: %s", msg->company.c_str(), msg->city.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "company_information_subscriber");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("/company_info", 10, companyInfoCallback);
ros::spin();
return 0;
}Ajoutez les exécutables à CMakeLists.txt :
add_executable(Information_publisher src/Information_publisher.cpp)
target_link_libraries(Information_publisher ${catkin_LIBRARIES})
add_dependencies(Information_publisher ${PROJECT_NAME}_generate_messages_cpp)
add_executable(Information_subscriber src/Information_subscriber.cpp)
target_link_libraries(Information_subscriber ${catkin_LIBRARIES})
add_dependencies(Information_subscriber ${PROJECT_NAME}_generate_messages_cpp)Construisez et exécutez :
cd ~/catkin_ws
catkin_make
source devel/setup.bash
roscore
rosrun learning_topic Information_publisher
rosrun learning_topic Information_subscriberPublisher et Subscriber Python
Créez les fichiers suivants sous ~/catkin_ws/src/learning_topic/scripts, puis rendez-les exécutables.
Fichier de code : 7-2-1-6-custom-topic-messages-and-usage-Information_publisher.py
#!/usr/bin/env python3
import rospy
from learning_topic.msg import Information
def information_publisher():
rospy.init_node('information_publisher', anonymous=True)
info_pub = rospy.Publisher('/company_info', Information, queue_size=10)
rate = rospy.Rate(1)
while not rospy.is_shutdown():
info_msg = Information()
info_msg.company = 'Seeed'
info_msg.city = 'Shenzhen'
info_pub.publish(info_msg)
rospy.loginfo('Information: company:%s city:%s', info_msg.company, info_msg.city)
rate.sleep()
if __name__ == '__main__':
information_publisher()Fichier de code : 7-2-1-6-custom-topic-messages-and-usage-Information_subscriber.py
#!/usr/bin/env python3
import rospy
from learning_topic.msg import Information
def company_info_callback(msg):
rospy.loginfo('Company: %s, city: %s', msg.company, msg.city)
def information_subscriber():
rospy.init_node('information_subscriber', anonymous=True)
rospy.Subscriber('/company_info', Information, company_info_callback)
rospy.spin()
if __name__ == '__main__':
information_subscriber()chmod +x scripts/Information_publisher.py scripts/Information_subscriber.py
roscore
rosrun learning_topic Information_publisher.py
rosrun learning_topic Information_subscriber.pyFigures








7.2.1.7 Client
Exécutez les commandes dans le conteneur Docker ROS 1 Noetic décrit dans 7.2.1.1 Introduction à ROS 1.
En plus de la communication par topic, il existe une communication par service. Un client envoie une requête, et un serveur renvoie une réponse. Cette section se concentre sur le client, montrant comment implémenter un client en C++ et Python.
Travail préparatoire
Continuez à utiliser le package
learning_servercréé dans cette section.
Établissement des packages
- Basculez vers ~/catkin_ws/src, exécution du terminal :
catkin_create_pkg learning_server std_msgs rospy roscpp geometry_msgs turtlesimBasculez vers le répertoire ~ pour exécuter la compilation :
catkin_makeImplémentation C++
Étapes vers la réalisation
Initialisation des nœuds ROS
- Créer des handles
3 ), créer un exemple de client
-
Initialisation et publication des données de requête de service
-
RÉPONSE REÇUE PAR le serveur
Créez a_new_turtle.cpp sous ~/catkin_ws/src/learning_server/src et collez le code suivant.
a new turtle.cpp
Fichier de code : 7-2-1-7-client-new.cpp
/**
This example calls the turtlesim /spawn service to create a new turtle at the specified position.
*/
#include <ros/ros.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "a_new_turtle");// Initialize the ROS node.
ros::NodeHandle node;
ros::service::waitForService("/spawn"); // Wait for the /spawn service.
ros::ServiceClient new_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");//Create a service client for /spawn.
// Initialize the turtlesim::Spawn request.
turtlesim::Spawn new_turtle_srv;
new_turtle_srv.request.x = 6.0;
new_turtle_srv.request.y = 8.0;
new_turtle_srv.request.name = "turtle2";
// Call the service with x/y position and name parameters.
ROS_INFO("Call service to create a new turtle name is %s,at the x:%.1f,y:%.1f", new_turtle_srv.request.name.c_str(),
new_turtle_srv.request.x,
new_turtle_srv.request.y);
new_turtle.call(new_turtle_srv);
ROS_INFO("Spawn turtle successfully [name:%s]", new_turtle_srv.response.name.c_str());// Display the service call result.
return 0;
};- Organigramme des procédures
- Dans la configuration CMakeLists.txt, sous la zone construite, ajoutez ce qui suit :
(rappels d'utilisation de base de vim : 14 avec l'éditeur Vim)
Fichier de code : 7-2-1-7-client-example-02.cmake
add_executable(a_new_turtle src/a_new_turtle.cpp)
target_link_libraries(a_new_turtle ${catkin_LIBRARIES})- Recompiler le code sous le répertoire de l'espace de travail
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the program- Ouvrir trois terminaux exécutant des programmes
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server a_new_turtle-
Résultat attendu
-
Processus
Une fois le nœud de petite tortue activé, la ré-exécution de a new turtle montre une autre tortue dans l'image, car le nœud de petite tortue fournit le service de /spawn, qui produit une autre tortue turtle 2, qui peut être visualisée via la commande rosservice list, comme indiqué ci-dessous.
Les paramètres requis pour ce service peuvent être visualisés via rosserviceinfo /spawn, comme indiqué dans la figure ci-dessous.
On peut voir que quatre paramètres sont nécessaires : x, y, theta, name, qui sont initialisés dans a new turtle.cpp
Fichier de code : 7-2-1-7-client-turtle.cpp
srv.request.x = 6.0;
srv.request.y = 8.0;
srv.request.name = "turtle2";Remarque : Theta n'est pas attribué, la valeur par défaut est 0
Implémentation Python
Créez scripts/a_new_turtle.py sous ~/catkin_ws/src/learning_server et collez le code suivant.
a_new_turtle.py
Fichier de code : 7-2-1-7-client-a_new_turtle.py
#!/usr/bin/env python3
import rospy
from turtlesim.srv import Spawn
def turtle_spawn():
rospy.init_node('new_turtle')
rospy.wait_for_service('/spawn')
try:
spawn_client = rospy.ServiceProxy('/spawn', Spawn)
response = spawn_client(2.0, 2.0, 0.0, 'turtle2')
return response.name
except rospy.ServiceException as exc:
rospy.logerr('Failed to call /spawn: %s', exc)
return None
if __name__ == '__main__':
name = turtle_spawn()
if name:
rospy.loginfo('Created a new turtle named %s.', name)-
Organigramme des procédures
-
Ouverture de trois terminaux exécutant des programmes
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server a_new_turtle.py- Les effets de l'opération et la description de la procédure sont cohérents avec les résultats obtenus par C++, et voici les paramètres de la façon dont Python fournit le service,
response = spawn_client(2.0, 2.0, 0.0, "turtle2")
Les paramètres correspondants sont x, y, theta, name.
Figures







7.2.1.8 Serveur
Exécutez les commandes dans le conteneur Docker ROS 1 Noetic décrit dans 7.2.1.1 Introduction à ROS 1.
Quand nous parlons de requêtes client puis de service, nous parlons de livraison de service.
Continuez à utiliser le package
learning_servercréé dans cette section.
Implémentation C++
Étapes vers la réalisation
Initialisation des nœuds ROS
- Exemples de création de Server
-
Boucle d'attente des requêtes de service, entrée dans une fonction de callback
-
terminer le traitement fonctionnel du service dans la fonction de callback et fournir un feedback sur les données de réponse
Créez turtle_vel_command_server.cpp sous ~/catkin_ws/src/learning_server/src et collez le code suivant.
Fichier de code : 7-2-1-8-server-new.cpp
/**
This example provides /turtle_vel_command with the std_srvs/Trigger service type.
*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_srvs/Trigger.h>
ros::Publisher turtle_vel_pub;
bool pubvel = false;
// Service callback: req is the request and res is the response.
bool pubvelCallback(std_srvs::Trigger::Request &req,
std_srvs::Trigger::Response &res)
{
pubvel = !pubvel;
ROS_INFO("Do you want to publish the vel?: [%s]", pubvel==true?"Yes":"No");// Print the client request.
// Set response data.
res.success = true;
res.message = "The status is changed!";
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "turtle_vel_command_server");
ros::NodeHandle n;
// Create the /turtle_vel_command server and register pubvelCallback.
ros::ServiceServer command_service = n.advertiseService("/turtle_vel_command", pubvelCallback);
// Create a publisher for /turtle1/cmd_vel. The message type is geometry_msgs::Twist and the queue size is 8.
turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 8);
ros::Rate loop_rate(10);// Set the loop rate.
while(ros::ok())
{
ros::spinOnce();// Process callbacks once.
// Publish turtle velocity commands when pubvel is true.
if(pubvel)
{
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.6;
vel_msg.angular.z = 0.8;
turtle_vel_pub.publish(vel_msg);
}
loop_rate.sleep();//Sleep according to the loop rate.
}
return 0;
}- Organigramme des procédures
- Configurer dans CMakeLists.txt, sous la zone construite, ajoutez ce qui suit :
Fichier de code : 7-2-1-8-server-example-02.cmake
add_executable(turtle_vel_command_server src/turtle_vel_command_server.cpp)
target_link_libraries(turtle_vel_command_server ${catkin_LIBRARIES})- Codes compilés sous le répertoire de l'espace de travail
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the program- Lancement de quatre terminaux exécutant des programmes
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server
rosservice call /turtle_vel_command-
Résultat attendu
-
Processus
D'abord, lors de l'exécution du nœud de petite tortue, vous pouvez entrer rosservice list au terminal pour voir quel est le service actuel, comme suit :
Et puis nous exécutons le programme turtle vel command server, et entrons rosservice list, et nous trouvons un turtle vel command server supplémentaire, comme indiqué dans la figure ci-dessous.
Et puis nous appelons ce service en l'entrant au terminal, et nous trouvons de petites tortues faisant un mouvement circulaire, et si elles appellent à nouveau, elles s'arrêtent. C'est parce que, dans le service de va-et-vient, nous inversons la valeur de pubvel, puis renvoyons le feedback, la fonction principale jugera la valeur de pubvel, et si c'est True, donne des instructions de vitesse, et pas pour False.
Implémentation Python
Créez scripts/turtle_vel_command_server.py sous ~/catkin_ws/src/learning_server et collez le code suivant.
turtle_vel_command_server.py
Fichier de code : 7-2-1-8-server-turtle_vel_command_server.py
#!/usr/bin/env python3
import threading
import rospy
from geometry_msgs.msg import Twist
from std_srvs.srv import Trigger, TriggerResponse
pubvel = False
turtle_vel_pub = None
def publish_velocity_loop():
rate = rospy.Rate(10)
while not rospy.is_shutdown():
if pubvel:
vel_msg = Twist()
vel_msg.linear.x = 0.6
vel_msg.angular.z = 0.8
turtle_vel_pub.publish(vel_msg)
rate.sleep()
def pubvel_callback(req):
global pubvel
pubvel = not pubvel
rospy.loginfo('Publish turtle velocity: %s', pubvel)
return TriggerResponse(success=True, message='Velocity publishing toggled.')
def turtle_pubvel_command_server():
global turtle_vel_pub
rospy.init_node('turtle_vel_command_server')
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=8)
rospy.Service('/turtle_vel_command', Trigger, pubvel_callback)
threading.Thread(target=publish_velocity_loop, daemon=True).start()
rospy.loginfo('Ready to receive /turtle_vel_command requests.')
rospy.spin()
if __name__ == '__main__':
turtle_pubvel_command_server()- Organigramme des procédures
- Ouvrir trois terminaux exécutant des programmes :
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server.py- Les effets de l'opération de la procédure et la description de la procédure sont cohérents avec ceux obtenus par C++.
Figures







7.2.1.9 Messages de service personnalisés et utilisation
Exécutez les commandes dans le conteneur Docker ROS 1 Noetic décrit dans 7.2.1.1 Introduction à ROS 1.
Cette section définit un service personnalisé nommé IntPlus.srv et implémente une paire serveur/client en C++ et Python.
Créer le fichier de service
cd ~/catkin_ws/src/learning_server
mkdir -p srv
vim srv/IntPlus.srvFichier de code : 7-2-1-9-custom-service-messages-and-usage-IntPlus.srv
int64 a
int64 b
---
int64 resultMettre à jour package.xml et CMakeLists.txt
Ajoutez ces dépendances à package.xml :
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>Ajoutez la génération de service à CMakeLists.txt :
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
add_service_files(
FILES
IntPlus.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS message_runtime
)Construisez l'espace de travail :
cd ~/catkin_ws
catkin_make
source devel/setup.bashServeur et Client C++
Fichier de code : 7-2-1-9-custom-service-messages-and-usage-IntPlus_server.cpp
#include <ros/ros.h>
#include "learning_server/IntPlus.h"
bool intPlusCallback(learning_server::IntPlus::Request &req,
learning_server::IntPlus::Response &res)
{
ROS_INFO("number 1 is:%ld, number 2 is:%ld", req.a, req.b);
res.result = req.a + req.b;
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "IntPlus_server");
ros::NodeHandle nh;
ros::ServiceServer service = nh.advertiseService("/Two_Int_Plus", intPlusCallback);
ROS_INFO("Ready to calculate two integers.");
ros::spin();
return 0;
}Fichier de code : 7-2-1-9-custom-service-messages-and-usage-IntPlus_client.cpp
#include <ros/ros.h>
#include "learning_server/IntPlus.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "IntPlus_client");
ros::NodeHandle nh;
ros::service::waitForService("/Two_Int_Plus");
ros::ServiceClient client = nh.serviceClient<learning_server::IntPlus>("/Two_Int_Plus");
learning_server::IntPlus srv;
srv.request.a = 8;
srv.request.b = 6;
if (client.call(srv)) {
ROS_INFO("Result: %ld", srv.response.result);
} else {
ROS_ERROR("Failed to call /Two_Int_Plus");
}
return 0;
}Ajoutez les exécutables à CMakeLists.txt :
add_executable(IntPlus_server src/IntPlus_server.cpp)
target_link_libraries(IntPlus_server ${catkin_LIBRARIES})
add_dependencies(IntPlus_server ${PROJECT_NAME}_generate_messages_cpp)
add_executable(IntPlus_client src/IntPlus_client.cpp)
target_link_libraries(IntPlus_client ${catkin_LIBRARIES})
add_dependencies(IntPlus_client ${PROJECT_NAME}_generate_messages_cpp)Exécutez l'exemple :
roscore
rosrun learning_server IntPlus_server
rosrun learning_server IntPlus_clientVous pouvez également appeler le service directement :
rosservice call /Two_Int_Plus 5 6Serveur et Client Python
Fichier de code : 7-2-1-9-custom-service-messages-and-usage-IntPlus_server.py
#!/usr/bin/env python3
import rospy
from learning_server.srv import IntPlus, IntPlusResponse
def int_plus_callback(req):
rospy.loginfo('Ints: a:%d b:%d', req.a, req.b)
return IntPlusResponse(req.a + req.b)
if __name__ == '__main__':
rospy.init_node('IntPlus_server')
rospy.Service('/Two_Int_Plus', IntPlus, int_plus_callback)
rospy.loginfo('Ready to calculate two integers.')
rospy.spin()Fichier de code : 7-2-1-9-custom-service-messages-and-usage-IntPlus_client.py
#!/usr/bin/env python3
import rospy
from learning_server.srv import IntPlus
if __name__ == '__main__':
rospy.init_node('IntPlus_client')
rospy.wait_for_service('/Two_Int_Plus')
plus_client = rospy.ServiceProxy('/Two_Int_Plus', IntPlus)
response = plus_client(22, 20)
rospy.loginfo('Result: %d', response.result)chmod +x scripts/IntPlus_server.py scripts/IntPlus_client.py
roscore
rosrun learning_server IntPlus_server.py
rosrun learning_server IntPlus_client.pyFigures







7.2.1.10 Publication et écoute avec TF
Exécutez les commandes dans le conteneur Docker ROS 1 Noetic décrit dans 7.2.1.1 Introduction à ROS 1.
packages tf
tf est un package qui permet aux utilisateurs de suivre plusieurs systèmes de coordonnées au fil du temps, en utilisant des structures de données arborescentes qui aident les développeurs à changer les coordonnées à tout moment, le point d'achèvement entre les coordonnées, les vecteurs, etc., en utilisant des tampons temporels et en maintenant les alternances de coordination entre plusieurs coordonnées.
Étapes d'utilisation
- Interception de la transformation tf
Reçoit toutes les coordonnées publiées dans le système de cache, transforme les données, et à partir desquelles vous recherchez les coordonnées requises.
- Diffusion de la transformation tf
(b) Diffuse l'alternance de coordonnées entre les coordonnées dans le système. Il peut y avoir des diffusions modifiées par tf dans plusieurs parties du système. Chaque diffusion peut être insérée directement dans l'arbre tf sans aucune synchronisation supplémentaire.
Programmation de la diffusion et de l'écoute des coordonnées tf réalisée
Créer et compiler des packages
cd ~/catkin_ws/src
catkin_create_pkg learning_tf rospy roscpp turtlesim tf
cd..
catkin_makeComment réaliser un diffuseur tf
-
Définition du diffuseur TF (Transform Broadcaster) ;
-
Initialisation des données tf et création des coordonnées ;
3), publication de la conversion des coordonnées (sendTransform) ;
Comment réaliser un dispositif d'écoute tf
- Définition des dispositifs d'écoute TF (TransformListener) ;
- Recherche des coordonnées (waitForTransform, lookupTransform)
Réalisation en langage C++ du diffuseur tf
-
Créer un fichier C++ (fichier suffixé par .cpp) dans le dossier src du package
-
Copier le code du programme ci-dessous dans le fichier turtle tf broadcaster.cpp
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-with.cpp
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>
std::string turtle_name;
void poseCallback(const turtlesim::PoseConstPtr& msg)
{
static tf::TransformBroadcaster br;// Create a TF broadcaster.
// Initialize TF data.
tf::Transform transform;
transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );//Set xyz coordinates.
tf::Quaternion q;
q.setRPY(0, 0, msg->theta);//Set Euler angles for x, y, and z rotation.
transform.setRotation(q);
br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));// Broadcast TF data between world and the turtle frame.
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "turtle_world_tf_broadcaster");// Initialize the ROS node.
if (argc != 2)
{
ROS_ERROR("Missing a parameter as the name of the turtle!");
return -1;
}
turtle_name = argv[1];// Use the input argument as the turtle name.
// Subscribe to the turtle pose topic.
ros::NodeHandle node;
ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
// Wait for callbacks.
ros::spin();
return 0;
};-
Organigramme du projet
-
Résolution de code
Tout d'abord, abonnez-vous à la position /pose de la tortue, et si le topic est publié, entrez alors dans la fonction de va-et-vient. Et puis revenez au diffuseur de tf, puis initialisez les données tf, dont la valeur est l'abonnement au topic /pose. Enfin, la transformation des coordonnées du monde par les petites tortues est publiée via br.sendTransform, une fonction de sendTransform. Il y a quatre paramètres, le premier représentant tf : (c'est-à-dire les données tf précédemment initialisées) les coordonnées du type Transform, le deuxième paramètre est un horodatage, et les troisième et quatrième sont une source variable et des coordonnées cibles.
Réalisation en langage C++ des dispositifs d'écoute tf
-
Créer un fichier C++ (fichier suffixé par .cpp) dans le dossier src du package
-
Copier le code du programme ci-dessous dans le fichier turtle tf lister.cpp
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-with.cpp
/**
This example listens to TF data, computes velocity commands, and publishes them to turtle2.
turtle2->turtle1 = world->turtle*world->turtle2
*/
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "turtle1_turtle2_listener");// Initialize the ROS node.
ros::NodeHandle node; // Create a node handle.
// Call the service to spawn turtle2.
ros::service::waitForService("/spawn");
ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
turtlesim::Spawn srv;
add_turtle.call(srv);
// Create a publisher for turtle2 velocity commands.
ros::Publisher vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);
tf::TransformListener listener;// Create a TF listener.
ros::Rate rate(10.0);
while (node.ok())
{
// Get TF data between turtle1 and turtle2.
tf::StampedTransform transform;
try
{
listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
}
catch (tf::TransformException &ex)
{
ROS_ERROR("%s",ex.what());
ros::Duration(1.0).sleep();
continue;
}
// Compute angular and linear velocity from the relative pose between turtle1 and turtle2, then publish commands for turtle2.
geometry_msgs::Twist turtle2_vel_msg;
turtle2_vel_msg.angular.z = 6.0 * atan2(transform.getOrigin().y(),
transform.getOrigin().x());
turtle2_vel_msg.linear.x = 0.8 * sqrt(pow(transform.getOrigin().x(), 2) +
pow(transform.getOrigin().y(), 2));
vel.publish(turtle2_vel_msg);
rate.sleep();
}
return 0;
};-
Organigramme du projet
-
Résolution de code
D'abord, le service appelle la création d'une autre petite tortue turtle2, puis crée un contrôleur de vitesse turtle2 ; Ensuite crée un dispositif d'écoute, écoutant et recherchant la gauche de turtle1 et turtle2, ce qui implique deux fonctions :
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-example-03.cpp
waitForTransform and lookupTransform
waitForTransform(target_frame,source_frame,time,timeout)Les deux frames représentent respectivement les coordonnées cibles et les coordonnées source, et les temps indiquent le temps d'attente d'un changement entre les deux coordonnées, puisque le changement de coordonnées est une procédure bloquante et doit donc être configuré pour indiquer la limite de temps.
LookupTransform (target frame, source frame, transferform) : étant donné la frame source et les coordonnées cibles (target frame), étant donné le temps entre les deux coordonnées (transform).
Nous avons obtenu le résultat de la transformation des coordonnées via le LoopupTransform puis x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
Modifications de CMakeLists.txt et compilations
- Modification de CMakeLists.txt
Modifiez le src/learning_tf/CMakeLists.txt sous le package en ajoutant ce qui suit :
(rappels d'utilisation de base de vim : 14 avec l'éditeur Vim)
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-example-04.cpp
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})- Compiler les documents d'implémentation
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the programDémonstration du démarrage et des effets opérationnels
- Ouvrez six terminaux et exécutez les commandes suivantes :
roscore
rosrun turtlesim turtlesim_node
rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1
rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
rosrun learning_tf turtle_tf_listener
rosrun turtlesim turtle_teleop_key # start keyboard teleoperation for the turtle- Impact démontré
III. DÉCLARATIONS PROCÉDURALES
Lorsque roscore est activé, le nœud de petite tortue est activé, et une petite tortue apparaîtra à la fin ; Ensuite, nous publions deux transformations tf, turtle1->world, turtle2->world, parce que si nous voulons connaître le changement entre turtle2 et turtle1, nous devons connaître le changement entre elles et world ; Le programme d'écoute tf est ensuite ouvert, à ce moment le terminal trouve qu'une autre tortue est produite, et la turtle2 se déplacera vers turtle1 ; Ensuite, nous activons le contrôle du clavier, puis cliquez sur la flèche pour contrôler le mouvement de turtle1, et la turtle2 suivra le mouvement de turtle1.
Diffuseur tf en langage Python
-
Créer un dossier script dans le package tf, basculer vers ce répertoire, créer un nouveau fichier .py nommé turtle tf broadcaster.py
-
Copier le code du programme ci-dessous dans le fichier turtle tf broadcaster.py
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-new.py
#!/usr/bin/env python3
import roslib
roslib.load_manifest('learning_tf')
import rospy
import tf
import turtlesim.msg
def handle_turtle_pose(msg, turtlename):
br = tf.TransformBroadcaster()# Create a TF broadcaster.
# Broadcast the TF transform between world and the named turtle.
br.sendTransform((msg.x, msg.y, 0),
tf.transformations.quaternion_from_euler(0, 0, msg.theta),
rospy.Time.now(),
turtlename,
"world")
if __name__ == '__main__':
rospy.init_node('turtle1_turtle2_tf_broadcaster')# Initialize the ROS node.
turtlename = rospy.get_param('~turtle') # Get the turtle name from the parameter server.
# Subscribe to the turtle pose topic.
rospy.Subscriber('/%s/pose' % turtlename,
turtlesim.msg.Pose,
handle_turtle_pose,
turtlename)
rospy.spin()- Organigramme du projet
Le langage Python réalise les dispositifs d'écoute tf
-
Créer un fichier Python (fichier suffixé par .py) dans le dossier script du package learning_tf nommé turtle tf lister.py
-
Copier le code du programme ci-dessous dans le fichier turtle tf lister.py
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-with.py
#!/usr/bin/env python3
import rospy
import math
import tf
import geometry_msgs.msg
import turtlesim.srv
if __name__ == '__main__':
rospy.init_node('turtle_tf_listener')# Initialize the ROS node.
listener = tf.TransformListener()# Initialize a TF listener.
rospy.wait_for_service('spawn')
# Call the service to create another turtle named turtle2.
spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
spawner(8, 6, 0, 'turtle2')
# Declare a publisher for turtle2 velocity.
turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)
rate = rospy.Rate(10.0)
while not rospy.is_shutdown():
try:
# Look up the TF transform between turtle2 and turtle1.
(trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
continue
# Compute linear and angular velocity, then publish them.
angular = 6.0 * math.atan2(trans[1], trans[0])
linear = 0.8 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)
cmd = geometry_msgs.msg.Twist()
cmd.linear.x = linear
cmd.angular.z = angular
turtle_vel.publish(cmd)
rate.sleep()- Organigramme du projet
Démonstration du démarrage et de l'efficacité opérationnelle
- Préparation d'un document launch
Dans le répertoire du package, créez un nouveau dossier launch, basculez vers launch, créez un nouveau fichier launch nommé Start tf demo py.launch, et copiez ce qui suit dedans :
Fichier de code : 7-2-1-10-publishing-and-listening-with-tf-py.xml
<launch>
<!-- turtlesim node-->
<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
<!-- broadcast turtle1 -> world -->
<node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
<param name="turtle" type="string" value="turtle1" />
</node>
<!-- broadcast turtle2 -> world -->
<node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
<param name="turtle" type="string" value="turtle2" />
</node>
<!--listener-->
<node pkg="learning_tf" type="turtle_tf_listener.py" name="listener" />
<!--turtle keyboard control node-->
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
</launch>- Lancement
roslaunch learning_tf start_tf_demo_py.launchLorsque l'application est en cours d'exécution, la souris clique sur la fenêtre qui exécute launch, appuyez sur la touche fléchée, et la turtle2 se déplace avec la turtle1.
- Les effets opérationnels sont largement cohérents avec C++
Figures






