Guide du développeur ROS 2
Table des matières
Cette page définit les pratiques et politiques que nous employons lors du développement de ROS 2.
Principes généraux
Certains principes sont communs à tous les développements ROS 2 :
Propriété partagée : toute personne travaillant sur ROS 2 doit se sentir propriétaire de toutes les parties du système. L’auteur original d’un morceau de code n’a aucune permission ou obligation spéciale de contrôler ou de maintenir ce morceau de code. Chacun est libre de proposer des modifications n’importe où, de gérer n’importe quel type de ticket et d’examiner n’importe quelle pull request.
Être prêt à travailler sur n’importe quoi : en corollaire de la propriété partagée, tout le monde doit être prêt à assumer n’importe quelle tâche disponible et à contribuer à n’importe quel aspect du système.
Demandez de l’aide : si vous rencontrez des problèmes avec quelque chose, demandez de l’aide à vos collègues développeurs, via des tickets, des commentaires ou des e-mails, selon le cas.
Pratiques de qualité
Les packages peuvent être attribués à différents niveaux de qualité en fonction des pratiques de développement auxquelles ils adhèrent, conformément aux directives de REP 2004 : Package Quality Categories . Les catégories se différencient par leurs politiques en matière de gestion des versions, de test, de documentation, etc.
Les sections suivantes sont les règles de développement spécifiques que nous suivons pour garantir que les packages de base sont de la plus haute qualité (« Niveau 1 »). Nous recommandons à tous les développeurs ROS de s’efforcer de respecter les politiques suivantes pour garantir la qualité dans l’ensemble de l’écosystème ROS.
Gestion des versions
Nous utiliserons les Semantic Versioning guidelines (semver
) pour la gestion des versions.
Nous respecterons également certaines règles spécifiques à ROS construites au-dessus de la signification complète de semver
:
Les incréments de version majeurs (c’est-à-dire les changements de rupture) ne doivent pas être effectués dans une distribution ROS publiée.
Les correctifs (préservant l’interface) et les incréments de version mineurs (sans rupture) ne rompent pas la compatibilité, donc ces types de modifications sont autorisées dans une version.
Les versions majeures de ROS sont le meilleur moment pour publier des changements de rupture. Si un package de base nécessite plusieurs changements avec rupture, ils doivent être fusionnés dans leur branche d’intégration (par exemple, roulement) pour permettre de détecter rapidement les problèmes dans CI, mais publiés ensemble pour réduire le nombre de versions majeures pour les utilisateurs de ROS.
Bien que les incréments majeurs nécessitent une nouvelle distribution, une nouvelle distribution ne nécessite pas nécessairement une bosse majeure (si le développement et la publication peuvent se produire sans casser l’API).
Pour le code compilé, l’ABI est considérée comme faisant partie de l’interface publique. Toute modification nécessitant la recompilation du code dépendant est considérée comme majeure (rupture).
Les changements de rupture d’ABI * peuvent * être apportés dans une version mineure * avant * une version de distribution (ajoutée à la version continue).
Nous appliquons la stabilité de l’API pour les packages de base dans Dashing et Eloquent même si leurs principaux composants de version sont
0
, malgré la spécification de SemVer concernant le développement initial.Par la suite, les paquets doivent s’efforcer d’atteindre un état mature et passer à la version
1.0.0
afin de correspondre aux spécifications desemver
.
Mises en garde
Ces règles sont * au mieux *. Dans des cas extrêmes peu probables, il peut être nécessaire de casser l’API dans une version/distribution majeure. Le fait qu’une pause imprévue incrémente la version majeure ou mineure sera évalué au cas par cas.
Par exemple, considérons une situation impliquant une tortue X publiée, correspondant à la version majeure 1.0.0
, et une tortue Y publiée, correspondant à la version majeure 2.0.0
.
Si un correctif de rupture d’API est identifié comme étant absolument nécessaire dans X-turtle, le passage à 2.0.0
n’est évidemment pas une option car 2.0.0
existe déjà.
Les solutions pour gérer la version de X-turtle dans un tel cas, toutes deux non idéales, sont :
Version mineure de Bumping X-turtle : non idéale car elle viole le principe de SemVer selon lequel les changements de rupture doivent remplacer la version majeure.
Faire passer la version majeure de X-turtle au-delà de Y-turtle (à `` 3.0.0``): non idéal car la version de l’ancienne distribution deviendrait supérieure à la version déjà disponible d’une distribution plus récente, ce qui invaliderait / casserait la version- code conditionnel spécifique.
Le développeur devra décider quelle solution utiliser ou, plus important encore, quel principe il est prêt à enfreindre. Nous ne pouvons pas suggérer l’un ou l’autre, mais dans les deux cas, nous exigeons que des mesures explicites soient prises pour communiquer manuellement la perturbation et son explication aux utilisateurs (au-delà de l’incrément de version).
S’il n’y avait pas de Y-turtle, même si le correctif ne serait techniquement qu’un patch, X-turtle devrait passer à 2.0.0
. Ce cas adhère à SemVer, mais enfreint notre propre règle selon laquelle les incréments majeurs ne doivent pas être introduits dans une distribution publiée.
C’est pourquoi nous considérons les règles de versioning best-effort. Aussi improbables que soient les exemples ci-dessus, il est important de définir avec précision notre système de gestion des versions.
Déclaration d’API publique
Selon semver
, chaque paquet doit clairement déclarer une API publique. Nous utiliserons la section « Public API Declaration » de la déclaration de qualité d’un package pour déclarer quels symboles font partie de l’API publique.
Pour la plupart des packages C et C++, la déclaration est n’importe quel en-tête qu’il installe. Cependant, il est acceptable de définir un ensemble de symboles considérés comme privés. Éviter les symboles privés dans les en-têtes peut aider à la stabilité de l’ABI, mais n’est pas obligatoire.
Pour d’autres langages comme Python, une API publique doit être explicitement définie, de sorte qu’il soit clair sur quels symboles on peut s’appuyer en ce qui concerne les directives de version. L’API publique peut également être étendue pour créer des artefacts tels que des variables de configuration, des fichiers de configuration CMake, etc., ainsi que des exécutables, des options et des sorties de ligne de commande. Tous les éléments de l’API publique doivent être clairement indiqués dans la documentation du package. Si quelque chose que vous utilisez n’est pas explicitement répertorié dans le cadre de l’API publique dans la documentation du package, vous ne pouvez pas vous attendre à ce qu’il ne change pas entre les versions mineures ou correctives.
Stratégie d’abandon
Dans la mesure du possible, nous utiliserons également la stratégie de dépréciation et de migration tic-tac pour les incréments de version majeurs. De nouvelles dépréciations viendront dans une nouvelle version de distribution, accompagnées d’avertissements du compilateur indiquant que la fonctionnalité est obsolète. Dans la prochaine version, la fonctionnalité sera complètement supprimée (pas d’avertissement).
Exemple de fonction foo
obsolète et remplacée par la fonction bar
:
Version |
API |
---|---|
X-tortue |
void foo(); |
Y-tortue |
[[deprecated(« use bar() »)]] void foo(); <br> void bar(); |
Z-tortue |
barre vide(); |
Nous ne devons pas ajouter de dépréciations après la sortie d’une distribution. Cependant, les dépréciations ne nécessitent pas nécessairement un changement de version majeur. Une dépréciation peut être introduite dans un bump de version mineure si le bump se produit avant la sortie de la distribution (similaire aux changements de rupture d’ABI).
Par exemple, si X-turtle commence son développement en tant que 2.0.0
, une dépréciation peut être ajoutée dans 2.1.0
avant la sortie de X-turtle.
Nous essaierons de maintenir autant que possible la compatibilité entre les distributions. Cependant, comme les mises en garde associées à SemVer, le tic-tac ou même la dépréciation en général peuvent être impossibles à respecter complètement dans certains cas.
Changer le processus de contrôle
Toutes les modifications doivent passer par une pull request.
Nous appliquerons le Certificat d’origine du développeur (DCO) sur les demandes d’extraction dans les référentiels ROSSore.
Il exige que tous les messages de commit contiennent la ligne
Signed-off-by
avec une adresse e-mail qui correspond à l’auteur du commit.Vous pouvez passer
-s
/--signoff
à l’invocationgit commit
ou écrire le message attendu manuellement (par exempleSigned-off-by: Your Name Developer <your.name@ exemple.com>
).DCO n’est pas requis pour les demandes d’extraction qui traitent uniquement de la suppression des espaces blancs, de la correction des fautes de frappe et d’autres modifications triviales.
Exécutez toujours les travaux CI pour toutes les plates-formes de niveau 1 pour chaque demande d’extraction et incluez des liens vers les travaux dans la demande d’extraction. (Si vous n’avez pas accès aux travaux Jenkins, quelqu’un les déclenchera pour vous.)
Un minimum d’une approbation d’un autre développeur qui n’est pas l’auteur de la demande d’extraction est nécessaire pour la considérer comme approuvée. L’approbation est requise avant la fusion.
Les forfaits peuvent choisir d’augmenter ce nombre.
Toute modification requise de la documentation (documentation de l’API, documentation des fonctionnalités, notes de version, etc.) doit être proposée avant de fusionner les modifications associées.
Lignes directrices pour le rétroportage des PR
Lors de la modification d’une ancienne version de ROS :
Assurez-vous que les fonctionnalités ou les correctifs sont acceptés et fusionnés dans la branche roulante avant d’ouvrir un PR pour rétroporter les modifications vers les anciennes versions.
Lors de la rétroportation vers des versions plus anciennes, envisagez également de rétroporter vers toute autre versions encore prises en charge, même les versions non-LTS.
Si vous rétroportez un seul PR dans son intégralité, intitulez le PR rétroporté « [Distro] <nom du PR d’origine> ». Si vous rétroportez un sous-ensemble de modifications d’un ou de plusieurs PR, le titre doit être « [Distro] <description des modifications> ».
Lien vers tous les PR dont vous rétroportez les modifications à partir de la description de votre PR de rétroportage. Dans un rétroportage Dashing d’un changement Foxy, vous n’avez pas besoin de créer un lien vers le rétroportage Eloquent du même changement.
Documentation
Tous les packages doivent avoir ces éléments de documentation présents dans leur README ou liés à partir de leur README :
Description et objectif
Définition et description de l’API publique
Exemples
Comment créer et installer (doit faire référence à des outils/flux de travail externes)
Comment créer et exécuter des tests
Comment construire une documentation
Comment développer (utile pour décrire des choses comme
python setup.py develop
)Déclarations de licence et de copyright
Chaque fichier source doit avoir une licence et une déclaration de copyright, vérifiée avec un linter automatisé.
Chaque paquet doit avoir un fichier LICENSE, généralement la licence Apache 2.0, à moins que le paquet n’ait une licence permissive existante (par exemple, rviz utilise un BSD à trois clauses).
Chaque package doit se décrire lui-même et son objectif en supposant, autant que possible, que le lecteur est tombé dessus sans connaissance préalable de ROS ou d’autres projets connexes.
Chaque package doit définir et décrire son API publique afin que les utilisateurs s’attendent raisonnablement à ce qui est couvert par la politique de version sémantique. Même en C et C++, où l’API publique peut être appliquée par la vérification de l’API et de l’ABI, c’est une bonne occasion de décrire la disposition du code et la fonction de chaque partie du code.
Il devrait être facile de prendre n’importe quel package et à partir de la documentation de ce package, comprendre comment construire, exécuter, construire et exécuter des tests, et construire la documentation. Évidemment, nous devons éviter de nous répéter pour les flux de travail courants, comme la création d’un package dans un espace de travail, mais les flux de travail de base doivent être décrits ou référencés.
Enfin, il devrait inclure toute documentation destinée aux développeurs. Cela peut inclure des flux de travail pour tester le code en utilisant quelque chose comme python setup.py develop
, ou cela peut signifier décrire comment utiliser les points d’extension fournis par votre package.
Exemples:
capacités : https://docs.ros.org/hydro/api/capabilities/html/
Celui-ci donne un exemple de docs décrivant l’API publique
catkin_tools : https://catkin-tools.readthedocs.org/en/latest/development/extending_the_catkin_command.html
Ceci est un exemple de description d’un point d’extension pour un package
(Les documents API ne sont pas encore générés automatiquement)
Essai
Tous les packages doivent avoir un certain niveau de tests système, d’intégration et/ou unitaires.
Les tests unitaires doivent toujours se trouver dans le package en cours de test et doivent utiliser des outils tels que Mock
pour essayer de tester des parties étroites de la base de code dans des scénarios construits. Les tests unitaires ne doivent pas introduire de dépendances de test qui ne sont pas des outils de test, par ex. gtest, nosetest, pytest, mock, etc…
Les tests d’intégration peuvent tester les interactions entre des parties du code ou entre des parties du code et le système. Ils testent souvent les interfaces logicielles de manière à ce que nous attendions de l’utilisateur qu’il les utilise. Comme les tests unitaires, les tests d’intégration doivent être dans le package qui est testé et ne doivent pas introduire de dépendances de test non liées à l’outil, sauf en cas d’absolue nécessité, c’est-à-dire que toutes les dépendances non liées à l’outil ne doivent être autorisées que sous un examen minutieux, elles doivent donc être évitées si possible.
Les tests système sont conçus pour tester des situations de bout en bout entre les packages et doivent être dans leurs propres packages pour éviter les packages gonflés ou couplés et pour éviter les dépendances circulaires.
En général, il convient d’éviter de minimiser les dépendances de test externes ou entre packages pour éviter les dépendances circulaires et les packages de test étroitement couplés.
Tous les packages doivent avoir des tests unitaires et éventuellement des tests d’intégration, mais le degré auquel ils doivent les avoir est basé sur la catégorie de qualité du package. Les sous-sections suivantes s’appliquent aux forfaits de « niveau 1 » :
Couverture de code
Nous fournirons une couverture de ligne et atteindrons une couverture de ligne supérieure à 95 %. Si un objectif de pourcentage inférieur est justifiable, il doit être clairement documenté. Nous pouvons fournir une couverture de branche ou exclure du code de la couverture (code de test, code de débogage, etc.). Nous exigeons que la couverture augmente ou reste la même avant de fusionner une modification, mais il peut être acceptable d’apporter une modification qui diminue la couverture du code avec une justification appropriée (par exemple, la suppression du code qui était précédemment couvert peut entraîner une baisse du pourcentage).
Performance
Nous recommandons fortement les tests de performances, mais reconnaissons qu’ils n’ont pas de sens pour certains packages. S’il y a des tests de performance, nous choisirons de vérifier chaque changement ou avant chaque version ou les deux. Nous aurons également besoin d’une justification pour fusionner un changement ou faire une version qui réduit les performances.
Linters et analyse statique
Nous allons utiliser style de code ROS et l’appliquer avec les linters de ament_lint_common. Tous les linters/analyses statiques qui font partie de ament_lint_common
doivent être utilisés.
La documentation ament_lint_auto fournit des informations sur l’exécution de ament_lint_common
.
Pratiques générales
Certaines pratiques sont communes à tous les développements ROS 2.
Ces pratiques n’affectent pas le niveau de qualité du package tel que décrit dans REP 2004, mais sont toujours fortement recommandées pour le processus de développement.
Questions
Lorsque vous signalez un problème, assurez-vous de :
Incluez suffisamment d’informations pour qu’une autre personne comprenne le problème. Dans ROS 2, les points suivants sont nécessaires pour déterminer la cause d’un problème. Tester avec autant d’alternatives dans chaque catégorie que possible sera particulièrement utile.
Le système d’exploitation et la version. Raisonnement : ROS 2 prend en charge plusieurs plates-formes, et certains bogues sont spécifiques à des versions particulières de systèmes d’exploitation/compilateurs.
La méthode d’installation. Raisonnement : Certains problèmes ne se manifestent que si ROS 2 a été installé à partir de « fat archives » ou de Debians. Cela peut nous aider à déterminer si le problème vient du processus d’emballage.
La version spécifique de ROS 2. Raisonnement : Certains bogues peuvent être présents dans une version particulière de ROS 2 et corrigés ultérieurement. Il est important de savoir si votre installation inclut ces correctifs.
L’implémentation DDS/RMW utilisée (voir cette page pour savoir comment déterminer lequel). Raisonnement : les problèmes de communication peuvent être spécifiques au middleware ROS sous-jacent utilisé.
La bibliothèque cliente ROS 2 utilisée. Raisonnement : Cela nous aide à réduire la couche de la pile à laquelle le problème pourrait survenir.
Incluez une liste d’étapes pour reproduire le problème.
En cas de bogue, envisagez de fournir un exemple court, autonome et correct (compilable) <http://sscce.org/>`__. Les problèmes sont beaucoup plus susceptibles d’être résolus si d’autres peuvent les reproduire facilement.
Mentionnez les étapes de dépannage qui ont déjà été essayées, notamment :
Mise à niveau vers la dernière version du code, qui peut inclure des correctifs de bogues qui n’ont pas encore été publiés. Voir cette section et suivez les instructions pour obtenir les branches « rolling ».
Essayer avec une autre implémentation RMW. Voir cette page pour savoir comment procéder.
Branches
Note
Ce ne sont que des lignes directrices. Il appartient au responsable du paquet de choisir des noms de branche qui correspondent à son propre flux de travail.
Il est recommandé d’avoir des branches séparées dans le référentiel source d’un package pour chaque distribution ROS qu’il cible. Ces branches portent généralement le nom de la distribution qu’elles ciblent. Par exemple, une branche humble
pour le développement ciblant spécifiquement la distribution Humble.
Des sorties sont également faites à partir de ces branches, en ciblant la distribution appropriée. Le développement ciblé sur une distribution ROS spécifique peut se produire sur la branche appropriée. Par exemple : les commits de développement ciblant foxy
sont créés dans la branche foxy
, et les versions de package pour foxy
sont créées à partir de cette même branche.
Note
Cela nécessite que les responsables du paquet effectuent des backports ou des forwardports selon les besoins pour maintenir toutes les branches à jour avec les fonctionnalités. Les mainteneurs doivent également effectuer une maintenance générale (corrections de bogues, etc.) sur toutes les branches à partir desquelles des versions de paquets sont encore créées.
Par exemple, si une fonctionnalité est fusionnée dans la branche spécifique à Rolling (par exemple, rolling
ou main
), et que cette fonctionnalité est également appropriée à la distribution Humble (ne casse pas l’API, etc.), alors il est recommandé de rétroporter la fonctionnalité sur la branche spécifique à Humble.
Les responsables peuvent créer des versions pour ces distributions plus anciennes si de nouvelles fonctionnalités ou des corrections de bogues sont disponibles.
Qu’en est-il de main
et rolling
** ?**
main
cible généralement Rolling (et donc, la prochaine distribution ROS inédite), bien que les mainteneurs puissent décider de développer et de publier à partir d’un branche rolling
à la place.
Demandes d’extraction
Une demande d’extraction ne doit se concentrer que sur un seul changement. Les modifications distinctes doivent être placées dans des demandes d’extraction distinctes. Voir GitHub’s guide to writing the perfect pull request.
Un patch doit être de taille minimale et éviter tout type de modifications inutiles.
Une demande d’extraction doit contenir un nombre minimum de commits significatifs.
Vous pouvez créer de nouveaux commits pendant que la demande d’extraction est en cours d’examen.
Avant de fusionner une demande d’extraction, toutes les modifications doivent être écrasées dans un petit nombre de commits sémantiques pour garder l’historique clair.
Mais évitez d’écraser les commits pendant qu’une pull request est en cours d’examen. Vos examinateurs pourraient ne pas remarquer que vous avez apporté la modification, introduisant ainsi un risque de confusion. De plus, vous allez écraser avant de fusionner de toute façon ; il n’y a aucun avantage à le faire tôt.
Tout développeur est invité à examiner et à approuver une demande d’extraction (voir Principes généraux).
Lorsque vous commencez à examiner une demande d’extraction, commentez la demande d’extraction afin que les autres développeurs sachent que vous l’examinez.
La révision de la demande d’extraction n’est pas en lecture seule, le réviseur faisant des commentaires et attendant ensuite que l’auteur y réponde. En tant que réviseur, n’hésitez pas à apporter des améliorations mineures (fautes de frappe, problèmes de style, etc.) sur place. En tant qu’ouvreur d’une pull-request, si vous travaillez dans un fork, cochez la case pour autoriser les modifications des contributeurs en amont aidera avec ce qui précède. En tant que réviseur, n’hésitez pas non plus à apporter des améliorations plus substantielles, mais envisagez de les mettre dans une branche distincte (soit mentionner la nouvelle branche dans un commentaire, soit ouvrir une autre pull request de la nouvelle branche vers la branche d’origine).
N’importe quel développeur (l’auteur, le réviseur ou quelqu’un d’autre) peut fusionner n’importe quelle demande d’extraction approuvée.
Gestion des versions de la bibliothèque
Nous versionnerons toutes les bibliothèques d’un package ensemble. Cela signifie que les bibliothèques héritent de leur version du package. Cela empêche les versions de bibliothèque et de package de diverger et partage le raisonnement avec la politique de publication de packages qui partagent un référentiel ensemble. Si vous avez besoin de bibliothèques pour différentes versions, envisagez de les diviser en différents packages.
Processus de développement
La branche par défaut (dans la plupart des cas la branche roulante) doit toujours se construire, réussir tous les tests et compiler sans avertissement. Si à tout moment il y a une régression, la priorité absolue est de restaurer au moins l’état précédent.
Compilez toujours avec les tests activés.
Exécutez toujours les tests localement après les modifications et avant de les proposer dans une demande d’extraction. En plus d’utiliser des tests automatisés, exécutez également le chemin de code modifié manuellement pour vous assurer que le correctif fonctionne comme prévu.
Exécutez toujours les travaux CI pour toutes les plates-formes pour chaque demande d’extraction et incluez des liens vers les travaux dans la demande d’extraction.
Pour plus de détails sur le workflow de développement logiciel recommandé, consultez la section Cycle de vie du développement logiciel.
Modifications de l’API RMW
Lors de la mise à jour de RMW API, il est nécessaire que les implémentations RMW pour les bibliothèques middleware de niveau 1 soient également mises à jour. Par exemple, une nouvelle fonction rmw_foo()
introduite dans l’API RMW doit être implémentée dans les packages suivants (à partir de ROS Galactic) :
Les mises à jour pour les bibliothèques middleware non de niveau 1 doivent également être envisagées si possible (par exemple, en fonction de la taille du changement). Voir REP-2000 pour la liste des bibliothèques middleware et leurs niveaux.
Suivi des tâches
Pour aider à organiser le travail sur ROS 2, l’équipe de développement principale de ROS 2 utilise des tableaux de projet GitHub de style kanban <https://github.com/orgs/ros2/projects>`_.
Cependant, tous les problèmes et demandes d’extraction ne sont pas suivis sur les tableaux de projet. Un tableau représente généralement une version à venir ou un projet spécifique. Les tickets peuvent être consultés sur une base par dépôt en parcourant les référentiels ROS 2” pages de problèmes individuels.
Les noms et les objectifs des colonnes dans un tableau de projet ROS 2 donné varient, mais suivent généralement la même structure générale :
À faire : problèmes pertinents pour le projet, prêts à être attribués
En cours : demandes d’extraction actives sur lesquelles des travaux sont actuellement en cours
En cours d’examen : demandes d’extraction pour lesquelles le travail est terminé et prêt à être examiné, et pour celles qui sont actuellement en cours d’examen
Terminé : les demandes d’extraction et les problèmes associés sont fusionnés/fermés (à titre informatif)
Pour demander l’autorisation d’apporter des modifications, il vous suffit de commenter les tickets qui vous intéressent. En fonction de la complexité, il peut être utile de décrire comment vous envisagez de le résoudre. Nous mettrons à jour le statut (si vous n’en avez pas l’autorisation) et vous pourrez commencer à travailler sur une pull request. Si vous contribuez régulièrement, nous vous accorderons probablement simplement la permission de gérer vous-même les étiquettes, etc.
Conventions de programmation
Programmation défensive : assurez-vous que les hypothèses sont maintenues le plus tôt possible. Par exemple. vérifiez chaque code de retour et assurez-vous de lever au moins une exception jusqu’à ce que le cas soit traité avec plus de grâce.
Tous les messages d’erreur doivent être dirigés vers
stderr
.Déclarez les variables dans la portée la plus étroite possible.
Gardez le groupe d’éléments (dépendances, importations, inclusions, etc.) classés par ordre alphabétique.
Spécifique C++
Évitez d’utiliser le streaming direct (
<<
) versstdout
/stderr
pour empêcher l’entrelacement entre plusieurs threads.Évitez d’utiliser des références pour
std::shared_ptr
car cela perturbe le comptage des références. Si l’instance d’origine sort de la portée et que la référence est utilisée, elle accède à la mémoire libérée.
Disposition du système de fichiers
La disposition du système de fichiers des packages et des référentiels doit suivre les mêmes conventions afin de fournir une expérience cohérente aux utilisateurs parcourant notre code source.
Disposition de l’emballage
src
: contient tout le code C et C++Contient également des en-têtes C/C++ qui ne sont pas installés
include
: contient tous les en-têtes C et C++ qui sont installés<nom du package>
: pour tous les en-têtes installés en C et C++, ils doivent être placés dans un espace de nom de dossier par le nom du package
<package_name>
: contient tout le code Pythontest
: contient tous les tests automatisés et les données de testconfig
: contient les fichiers de configuration, par ex. Fichiers de paramètres YAML et fichiers de configuration RVizdoc
: contient toute la documentationlaunch
: contient tous les fichiers de lancementpackage.xml
: tel que défini par REP-0140 (peut être mis à jour pour le prototypage)CMakeLists.txt
: seuls les packages ROS qui utilisent CMakesetup.py
: uniquement les packages ROS qui utilisent uniquement du code PythonREADME
: peut être rendu sur GitHub en tant que page de destination pour le projetCela peut être aussi court ou détaillé que possible, mais il doit au moins être lié à la documentation du projet
Envisagez de mettre un CI ou une balise de couverture de code dans ce README
Il peut également s’agir de
.rst
ou de tout autre élément pris en charge par GitHub
CONTRIBUTING
: décrit les directives de contributionCela peut inclure l’implication de la licence, par ex. lors de l’utilisation de la licence Apache 2.
LICENSE
: une copie de la licence ou des licences pour ce packageCHANGELOG.rst
: REP-0132 journal des modifications conforme
Disposition du référentiel
Chaque package doit se trouver dans un sous-dossier portant le même nom que le package. Si un référentiel ne contient qu’un seul package, il peut éventuellement se trouver à la racine du référentiel.
Flux de travail du développeur
Nous suivons les tickets ouverts et les relations publiques actives liées aux versions à venir et aux projets plus importants à l’aide de tableaux de projets GitHub.
Le flux de travail habituel est :
Discutez de la conception (ticket GitHub sur le référentiel approprié et un PR de conception à https://github.com/ros2/design si nécessaire)
Écrire l’implémentation sur une branche de fonctionnalité sur un fork
Veuillez consulter le guide du développeur pour les directives et les meilleures pratiques
Rédiger des tests
Activer et exécuter les linters
Exécutez les tests localement en utilisant
colcon test
(voir le colcon tutorial)Une fois que tout se construit localement sans avertissement et que tous les tests réussissent, exécutez CI sur votre branche de fonctionnalité :
Allez sur ci.ros2.org
Connectez-vous (coin supérieur droit)
Cliquez sur la tâche
ci_launcher
Cliquez sur « Construire avec des paramètres » (colonne de gauche)
Dans la première case « CI_BRANCH_TO_TEST » entrez le nom de votre branche de fonctionnalité
Appuyez sur le bouton
construire
(si vous n’êtes pas un committer ROS 2, vous n’avez pas accès à la ferme CI. Dans ce cas, envoyez un ping au réviseur de votre PR pour qu’il exécute CI pour vous)
Si votre cas d’utilisation nécessite une couverture de code en cours d’exécution :
Allez sur ci.ros2.org
Connectez-vous (coin supérieur droit)
Cliquez sur le travail
ci_linux_coverage
Cliquez sur « Construire avec des paramètres » (colonne de gauche)
Assurez-vous de laisser « CI_BUILD_ARGS » et « CI_TEST_ARGS » avec les valeurs par défaut
Appuyez sur le bouton
construire
À la fin du document, il y a des instructions sur la façon de interpréter le résultat du rapport et calculer le taux de couverture
Si le travail CI construit sans avertissements, erreurs et échecs de test, postez les liens de vos travaux sur votre PR ou ticket de haut niveau regroupant tous vos PRs (voir exemple ici)
Notez que la démarque de ces badges se trouve dans la sortie console du travail
ci_launcher
Lorsque le PR a été approuvé :
la personne qui a soumis le PR le fusionne en utilisant l’option « Squash and Merge » afin que nous gardions un historique propre
Si les commits méritent d’être séparés : écrasez tous les nitpick/linters/typo ensemble et fusionnez l’ensemble restant
Remarque : chaque PR doit cibler une fonctionnalité spécifique afin que Squash et Merge aient du sens 99 % du temps
Supprimer la branche une fois fusionnée
Pratiques de développement architectural
Cette section décrit le cycle de vie idéal qui doit être utilisé lors de modifications architecturales importantes de ROS 2.
Cycle de vie du développement logiciel
Cette section décrit étape par étape comment planifier, concevoir et implémenter une nouvelle fonctionnalité :
Création de tâche
Création du document de conception
Examen de la conception
Mise en œuvre
Révision des codes
Création de tâche
Les tâches nécessitant des modifications des parties critiques de ROS 2 doivent faire l’objet de revues de conception au cours des premières étapes du cycle de publication. Si une révision de la conception a lieu dans les étapes ultérieures, les modifications feront partie d’une future version.
Un problème doit être créé dans le dépôt ros2 approprié, décrivant clairement la tâche en cours.
Il doit avoir des critères de réussite clairs et mettre en évidence les améliorations concrètes attendues de celui-ci.
Si la fonctionnalité cible une version ROS, assurez-vous que cela est suivi dans le ticket de version ROS (exemple).
Rédaction du document de conception
Les documents de conception ne doivent jamais inclure d’informations confidentielles. La nécessité ou non d’un document de conception pour votre modification dépend de l’ampleur de la tâche.
Vous apportez une petite modification ou corrigez un bogue :
Un document de conception n’est pas requis, mais un problème doit être ouvert dans le référentiel approprié pour suivre le travail et éviter la duplication des efforts.
Vous implémentez une nouvelle fonctionnalité ou souhaitez contribuer à l’infrastructure appartenant à OSRF (comme Jenkins CI):
La documentation de conception est requise et doit être ajoutée à ros2/design pour être rendue accessible sur https://design.ros2.org/.
Vous devez bifurquer le référentiel et soumettre une demande d’extraction détaillant la conception.
Mentionnez le problème ros2 associé (par exemple,
Design doc for task ros2/ros2#<issue id>
) dans la demande d’extraction ou le message de validation. Des instructions détaillées se trouvent sur la page ROS 2 Contribute. Les commentaires de conception seront faits directement sur la demande d’extraction.
S’il est prévu que la tâche soit publiée avec une version spécifique de ROS, ces informations doivent être incluses dans la demande d’extraction.
Examen des documents de conception
Une fois que la conception est prête à être examinée, une demande d’extraction doit être ouverte et des examinateurs appropriés doivent être affectés. Il est recommandé d’inclure le(s) propriétaire(s) du projet - responsables de tous les packages impactés (tel que défini par le champ responsable package.xml
, voir REP-140) - en tant que réviseurs.
Si le document de conception est complexe ou si les réviseurs ont des horaires contradictoires, une réunion facultative de révision de la conception peut être organisée. Dans ce cas,
Avant la réunion
Envoyer une invitation à une réunion au moins une semaine à l’avance
Une durée de réunion d’une heure est recommandée
L’invitation à la réunion doit répertorier toutes les décisions à prendre lors de l’examen (décisions nécessitant l’approbation du responsable du paquet)
- Réunion des participants requis : réviseurs de demandes d’extraction de conception
Réunion des participants facultatifs : tous les ingénieurs OSRF, le cas échéant
Pendant la réunion
Le propriétaire de la tâche dirige la réunion, présente ses idées et gère les discussions pour s’assurer qu’un accord est atteint à temps
Après la réunion
Le propriétaire de la tâche doit renvoyer les notes de réunion à tous les participants
Si des problèmes mineurs ont été soulevés concernant la conception :
Le propriétaire de la tâche doit mettre à jour la demande d’extraction de document de conception en fonction des commentaires
Un examen supplémentaire n’est pas nécessaire
Si des problèmes majeurs ont été soulevés concernant la conception :
Il est acceptable de supprimer les sections pour lesquelles il n’y a pas d’accord clair
Les parties discutables de la conception peuvent être soumises à nouveau en tant que tâche distincte à l’avenir
Si la suppression des parties discutables n’est pas une option, travaillez directement avec les propriétaires de packages pour parvenir à un accord
Une fois le consensus atteint :
Assurez-vous que la demande d’extraction ros2/design a été fusionnée, le cas échéant
Mettre à jour et fermer le problème GitHub associé à cette tâche de conception
Mise en œuvre
Avant de commencer, consultez la section « Demandes d’extraction »_ pour connaître les meilleures pratiques.
Pour chaque dépôt à modifier :
Modifiez le code, passez à l’étape suivante si vous avez terminé ou à intervalles réguliers pour sauvegarder votre travail.
Auto-examen vos modifications en utilisant
git add -i
.Créez un nouveau commit signé en utilisant
git commit -s
.Une demande d’extraction doit contenir un minimum de commits sémantiquement significatifs (par exemple, un grand nombre de commits d’une ligne n’est pas acceptable). Créez de nouveaux commits de correction tout en itérant sur les commentaires, ou éventuellement, modifiez les commits existants en utilisant
git commit --amend
si vous ne voulez pas créer un nouveau commit à chaque fois.Chaque commit doit avoir un message de commit correctement écrit et significatif. Plus d’instructions ici.
Le déplacement des fichiers doit être effectué dans un commit séparé, sinon git risque de ne pas suivre avec précision l’historique des fichiers.
Soit la description de la demande d’extraction, soit le message de validation doit contenir une référence au problème ros2 associé, de sorte qu’il est automatiquement fermé lorsque la demande d’extraction est fusionnée. Voir ce doc pour plus de détails.
Poussez les nouveaux commits.
Revue de code
Une fois que le changement est prêt pour la révision du code :
Ouvrez une demande d’extraction pour chaque référentiel modifié.
N’oubliez pas de suivre les meilleures pratiques relatives aux « demandes d’extraction ».
GitHub peut être utilisé pour créer des demandes d’extraction à partir de la ligne de commande.
S’il est prévu que la tâche soit publiée avec une version spécifique de ROS, ces informations doivent être incluses dans chaque demande d’extraction.
Les propriétaires de packages qui ont examiné le document de conception doivent être mentionnés dans la demande d’extraction.
SLO de révision du code : bien que la révision des demandes d’extraction soit un effort optimal, il est utile que les réviseurs commentent les demandes d’extraction dans un délai d’une semaine et que les auteurs de code répondent aux commentaires dans un délai d’une semaine, afin qu’il n’y ait pas de perte de contexte.
Itérer sur les commentaires comme d’habitude, modifier et mettre à jour la branche de développement si nécessaire.
Une fois le PR approuvé, les mainteneurs de paquets fusionneront les changements dans.
Construire une introduction à la ferme
La ferme de construction est située sur ci.ros2.org.
Chaque nuit, nous exécutons des tâches nocturnes qui construisent et exécutent tous les tests dans différents scénarios sur différentes plates-formes. De plus, nous testons toutes les demandes d’extraction sur ces plates-formes avant de les fusionner.
Il s’agit de l’ensemble actuel de plates-formes et d’architectures cibles, bien qu’il évolue au fil du temps :
Ubuntu 22.04 Jammy
amdshch
aarch64
Windows 10
amdshch
Il existe plusieurs catégories d’emplois sur le buildfarm :
tâches manuelles (déclenchées manuellement par les développeurs) :
ci_linux : compiler + tester le code sur Ubuntu Xenial
ci_linux-aarch64 : compilez + testez le code sur Ubuntu Xenial sur une machine ARM 64 bits (aarch64) ;
ci_linux_coverage : build + test + génération de couverture de test
ci_windows : compiler + tester le code sur Windows 10
ci_launcher : déclenche toutes les tâches répertoriées ci-dessus
nightly (courir tous les soirs):
Debug : compilez + testez le code avec CMAKE_BUILD_TYPE=Debug
nightly_linux_debug
nightly_linux-aarch64_debug
nightly_win_deb
Release : compiler + tester le code avec CMAKE_BUILD_TYPE=Release
nightly_linux_release
nightly_linux-aarch64_release
nightly_win_rel
Répété : construisez puis exécutez chaque test jusqu’à 20 fois ou jusqu’à l’échec (aka flakiness hunter)
nightly_linux_repeated
nightly_linux-aarch64_repeated
nightly_win_rep
Couverture:
nightly_linux_coverage : construit + teste le code + analyse la couverture pour c/c++ et python
les résultats sont exportés sous forme de rapport cobertura
packaging (exécuté toutes les nuits ; le résultat est regroupé dans une archive) :
packaging_linux
packaging_windows
Deux fermes de construction supplémentaires prennent en charge l’écosystème ROS / ROS 2 en fournissant la construction de packages source et binaires, l’intégration continue, les tests et l’analyse.
Pour plus de détails, les questions fréquemment posées et le dépannage, consultez build farms.
Remarque sur les courses de couverture
Les packages ROS 2 sont organisés de manière à ce que le code de test d’un package donné soit non seulement contenu dans le package, mais puisse également être présent dans un package différent. En d’autres termes : les packages peuvent exercer du code appartenant à d’autres packages pendant la phase de test.
Pour atteindre le taux de couverture atteint par tout le code disponible dans les packages de base ROS 2, il est recommandé d’exécuter les builds à l’aide d’un ensemble fixe de référentiels proposés. Cet ensemble est défini dans les paramètres par défaut des tâches de couverture dans Jenkins.
Comment lire le taux de couverture à partir du rapport buildfarm
Pour voir le rapport de couverture pour un package donné :
Lorsque la construction de
ci_linux_coverage
se termine, cliquez surRapport de couverture
Faites défiler jusqu’au tableau
Répartition de la couverture par forfait
Dans le tableau, regardez la première colonne intitulée « Nom »
Les rapports de couverture dans la buildfarm incluent tous les packages qui ont été utilisés dans l’espace de travail ROS. Le rapport de couverture comprend différents chemins correspondant à un même forfait :
Nommez les entrées sous la forme :
src.*.<repository_name>.<package_name>.*
Celles-ci correspondent aux exécutions de tests unitaires disponibles dans un package par rapport à son propre code sourceNommez les entrées sous la forme :
build.<repository_name>.<package_name>.*
Celles-ci correspondent aux exécutions de tests unitaires disponibles dans un package par rapport à ses fichiers générés au moment de la construction ou de la configurationNommer les entrées sous la forme :
install.<package_name>.*
Elles correspondent aux tests système/d’intégration provenant des séries de tests d’autres packages
Comment calculer le taux de couverture à partir du rapport buildfarm
Obtenez le taux de couverture unitaire combiné à l’aide du script automatique :
Depuis le build ci_linux_coverage Jenkins, copiez l’URL du build
Téléchargez le script get_coverage_ros2_pkg
Exécutez le script :
./get_coverage_ros2_pkg.py <jenkins_build_url> <ros2_package_name>
(README)Récupérez les résultats de la dernière ligne « Combined unit testing » dans la sortie du script
Alternative : obtenir le taux de couverture unitaire combiné à partir du rapport de couverture (nécessite un calcul manuel) :
Lorsque la construction de ci_linux_coverage est terminée, cliquez sur
Cobertura Coverage Report
Faites défiler jusqu’au tableau
Répartition de la couverture par forfait
Dans le tableau, sous la première colonne « Name », recherchez (où <package_name> est votre package en cours de test) :
tous les répertoires sous le modèle
src.*.<repository_name>.<package_name>.*
saisissez les deux valeurs absolues dans la colonne « Lines ».tous les répertoires sous le modèle
build/.<repository_name>.*
récupèrent les deux valeurs absolues dans la colonne « Lines ».
Avec la sélection précédente : pour chaque cellule, la première valeur correspond aux lignes testées et la seconde au total des lignes de code. Agrégez toutes les lignes pour obtenir le total des lignes testées et le total des lignes de code testées. Diviser pour obtenir le taux de couverture.
Comment mesurer la couverture localement à l’aide de lcov (Ubuntu)
Pour mesurer la couverture sur votre propre machine, installez lcov
.
sudo apt install -y lcov
Le reste de cette section suppose que vous travaillez depuis votre espace de travail colcon. Compiler en débogage avec des drapeaux de couverture. N’hésitez pas à utiliser les drapeaux colcon pour cibler des packages spécifiques.
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} --coverage" -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} --coverage"
lcov
nécessite une ligne de base initiale, que vous pouvez produire avec la commande suivante. Mettez à jour l’emplacement du fichier de sortie selon vos besoins.
lcov --no-external --capture --initial --directory . --output-file ~/ros2_base.info
Exécutez des tests pour les packages qui comptent pour vos mesures de couverture. Par exemple, si vous mesurez rclcpp
également avec test_rclcpp
colcon test --packages-select rclcpp test_rclcpp
Capturez les résultats lcov avec une commande similaire, cette fois en supprimant le drapeau --initial
.
lcov --no-external --capture --directory . --output-file ~/ros2.info
Combinez les fichiers de trace .info :
lcov --add-tracefile ~/ros2_base.info --add-tracefile ~/ros2.info --output-file ~/ros2_coverage.info
Générez du HTML pour une visualisation et une annotation faciles des lignes couvertes.
mkdir -p coverage
genhtml ~/ros2_coverage.info --output-directory coverage