Rover Hardware Library Design - PolyOrbite-Rover/polyorbite_rover GitHub Wiki
Description brève et raison d'être
Bibliothèque de code C++ ou Python qui expose des abstractions des différentes composantes du rover qu'on peut contôler. Par exemple, cette bibliothèque peut offrir un objet "DriveTrain" composé d'objets "Motor", qui permettent de définir la vitesse et la direction de chaque roue sans toute fois exposer la façon concrète utilisée pour faire tourner les roues. Dans l'implémentation concrète du contrôle des moteurs, on change le voltage sur certaines pins des GPIO et on envoie des messages par I2C. On ne veut pas que l'utilisateur de la bibliothèque sache tout ça, parce que ça peut changer (si on utilise d'autres contrôleurs de moteurs, par exemple). L'utilisateur de la bibliothèque doit seulement savoir qu'il y a six roues et qu'on peut changer leur vitesse et leur direction. En outre, la vitesse que l'utilisateur donne et reçoit doit être en m/s ou autre unité interprétable.
Architecture en couches
Je vois la séparation de ce projet en couches d'abstraction, les voici de la plus abstraite à la plus concrète :
- Interfaces qui sont utilisées par l'utilisateur de la bibliothèque, ici on a des objets qui ont des méthodes faciles à comprendre ex. Motor::setVelocity(float32) ou Light::activate() ;
- Implémentation de ces interfaces, ici on implémente les méthodes des classes montrées ci-haut, ces implémentations ne font pas directement le travail bas-niveau (ex. Envoyer des messages par I2C), mais on sait ici que ce travail bas-niveau existe ;
- Outils génériques bas-niveau, ici on implémente un wrapper qui gère la communication I2C, un autre qui permet de changer le voltage des GPIO, etc. le code de l'étape 2. appelle ces outils.
À l'étape 1. on ne doit pas du tout connaître les détails d'interaction avec le hardware (I2C, GPIO, etc.). À l'étape 3. on ne doit pas du tout connaître la business logic (on ne doit pas savoir c'est quoi un moteur ni une lumière ni une caméra). À l'étape 2. on fait le lien entre les deux en implémentant les interfaces de l'étape 1. et en appellant le code de l'étape 3. dans ces implémentations. On peut faire plusieurs implémentations pour différents hardware concrets si besoin est.
Requis
REQ1 : des interfaces doivent être exposées à l'utilisateur pour chaque composante matérielle qu'on peut contrôler ou utiliser pour mesurer quelque chose sur le rover (c'est-à-dire les moteurs, les encodeurs des moteurs, les lumières, la killswitch software, les instruments de science, etc.).
REQ2 : ces interfaces ne doivent pas contenir d'information spécifique à la façon d'interfacer physiquement avec ces composantes (ex. I2C).
REQ3 : la configuration du rover doit être modifiable durant le runtime (on ne veut pas avoir à compiler plusieurs versions du logiciel pour les différentes itérations du rover).
REQ4 : pour les composantes qui mesurent quelque chose, on doit pouvoir exécuter du code seulement au moment où on reçoit une nouvelle donnée (ex. Observer pattern).
REQ5 : toutes les mesures (ex. Vélocités) doivent être représentées avec des unités interprétables (ex. m/s).
REQ6 : ça serait bien qu'on offre la possibilité de créer des plugins pour que l'équipe bras robotique puisse implémenterx ses propres composantes et les intégrer à notre système.
Liste de toutes les composantes qui doivent être incorporées dans la library
- In the library
○ Motors
§ Set velocity and direction
○ Motor encoders
§ Get the velocity and direction
○ Lights
§ Turn on and off
§ Set intensity or colour ?
○ Power monitoring
§ Get Power, Voltage and Amperage
○ Robotic arm
§ To be defined with the robotic arm team
- Outide the library
○ Cameras
○ Lidar
○ GPS
○ IMU
Représentation de l'architecture en trois couches d'abstraction
À droite vous avez des interfaces qui décrivent les actions que vous pouvez effectuer sur chaque composante (ex. setVelocity(float) pour un moteur, ou toggle() pour une lumière).
Au centre, vous avez des classes qui implémentent les interfaces de droite. Il peut y avoir plusieurs implémentations pour chaque composante (ex. si on a deux puces électroniques différentes pour le contrôle des moteurs, alors on peut implémenter deux fois l'interface de moteur). Ainsi, tout le code qui appelle les classes de la library le fait selon les méthodes des interfaces et donc tant que les interfaces ne changent pas, on peut substituer le comportement de chaque compostante en créant de nouvelles implémentations sans toute fois changer le code qui utilise la library.
Représentation de la configuration des programmes ROS pour les composantes
Pour chaque composante, une node ROS doit exister. C'est juste un programme tout simple qui inclue la library, qui instancie la classe de la composante en question et qui fait le pont entre ROS et la classe en exposant des topics ou services ROS. Ainsi, on peut interagir avec la classe de la library depuis ROS en envoyant des messages aux topics/services exposés.
Pour définir la configuration réelle du rover, il suffit de créer un launchfile ROS qui décrit toutes les nodes dont on a besoin, leur donne les bons paramètres nomme correctement leurs topics/services.
Ainsi, si nous avons plusieurs versions/configurations matérielles du rover en même temps, il nous suffit d'avoir plusieurs launchfiles.