Road To Robots – 0

Voici le premier article d’une série, qui je l’espère sera longue et enrichissante. Le titre n’est pas définitif, je cherche encore.

Comme son nom l’indique, cette série aura pour but de faire de la robotique. C’est un domaine que je connais assez peu et que j’ai envie d’explorer depuis pas mal d’années. Il est temps de s’y mettre, et pour rendre cela plus intéressant, j’ai envie de me rajouter une contrainte : coder les Robot uniquement en Rust.

Dans le cadre de cet article, on va commencer par se configurer un environnement de développement permettant de faire du Rust sur Raspberry Pi. Ce qui implique pour l’instant qu’il n’y aura pas de robots à proprement parler dans cet article.

Je comprends, la déception est immense, mais ne vous inquiétez pas, cela viendra.

Pourquoi en Rust?

C’est une question pertinente. Pour y répondre, commençons par présenter Rust.

Rust est un langage de programmation compilé multi-paradigme conçu et développé par Mozilla Research depuis 2010. Il a été conçu pour être « un langage fiable, concurrent, pratique », supportant les styles de programmation purement fonctionnel, modèle d’acteur, procédural, ainsi qu’orienté objet sous certains aspects.

Wikipedia – Rust

La définition Wikipedia, au-delà des aspects classiques d’un langage de programmation tel que « compilé », « multi-paradigme » ou encore « orienté objet », nous apprend trois choses importantes. Le Rust est conçu pour être fiable, concurrent et pratique, j’ajouterai à cela qu’il est aussi performant.

  • Performant : Rust est rapide, presque autant que le C ou le C++. En effet, il s’agit d’un langage compilé, par conséquent, contrairement au Python qui est interprété, ou le C# ou le Java qui se situent entre les deux, le langage machine résultant de la compilation est directement exécuté par le processeur.
  • Fiable : Par défaut Rust est sûr. Plusieurs mécanismes et concepts s’en assurent : typage fort, ownership, validation mémoire à la compilation, variables immutable par défaut, absence de nullité, etc.
  • Concurrent : Rust permet de faire de la programmation concurrente facilement via des threads et permet surtout d’éviter les problèmes d’accès concurrent via un mécanisme de messaging entre les threads.
  • Pratique : L’installation est rapide, multi-plateforme. Rust dispose d’un gestionnaire de paquet intégré, Cargo. Le langage est bien documenté.

Rust est utilisé dans différents domaines, en voici un échantillon non exhaustif :

  • Application CLI : Applications en ligne de commande, comme par exemple des scripts de compilation ou de déploiement.
  • WebAssembly : Applications web téléchargées directement par le client web, permet de faire des traitements lourds sur des clients légers avec de bonnes performances.
  • Réseau / Serveur : Applications déployées directement sur un serveur tel qu’une API REST.
  • Embarqué : C’est ce qui va nous intéresser ici, faire une application sur des environnements aux capacités limités comme les microcontrôleurs (ex: Arduino, ESP, …) ou les nano ordinateurs (ex: Raspberry Pi).

Il est également possible de faire des applications graphiques pour faire des IHM, mais pour l’instant il n’y a aucun consensus quant à la techno ou le framework à utiliser et la plupart des solutions ne sont pas encore matures.

Pour plus d’informations sur Rust, le site officiel est un bon point de départ.

Je pense que maintenant vous avez une petite idée de pourquoi j’ai choisi d’utiliser Rust dans le cadre de cette série, non ?

Je récapitule avec les points qui m’intéressent :

  • Le langage est adapté pour l’utilisation que l’on veut en faire, à savoir de l’embarqué.
  • Le langage est sûr, il n’y a donc pas de gros risque de fuite mémoire ou de crash.
  • Rust est performant, du même ordre que le C ou le C++, habituellement utilisé en robotique.
  • Rust est moderne et plus pratique que le C ou le C++, notamment avec Cargo qui permet de gérer les dépendances.
  • Rust est de plus en plus populaire, il est le langage le plus aimé sur Stack Overflow depuis plusieurs années, il y a donc une probabilité non négligeable qu’il s’agisse d’un langage incontournable d’ici quelques années.

Pour finir sur les raisons du choix, il me faut également être honnête. Le fait que je souhaite apprendre ce langage depuis beaucoup de temps, mais que je n’ai pas trouvé de projet pour me forger une expérience y joue pour beaucoup.

Cela étant dit, je précise que je débute en Rust, il y aura donc certainement des approximations, des facilités, des incompréhensions et des erreurs. Venant plutôt du C#, je risque aussi de ne pas forcément adopter la philosophie Rust dès le départ. Fin du disclaimer.

Premier projet Rust

On va commencer, simplement, par le classique des projets débutant : Hello World!

C’est pas très fun, je vous l’accorde, mais il faut bien configurer et vérifier le bon fonctionnement de son environnement.

Ce premier projet sera fait directement sur le RPI, je ne traiterai pas l’installation de Raspberry OS et sa configuration, la seule chose à prendre en compte est qu’il faut activer le SSH pour plus tard dans l’article. Comme je vais utiliser Visual Studio Code, il est préférable, dans un premier temps de prendre la version avec IHM.

Installation de Rust

Cette étape est plutôt simple, il faut ouvrir une console sur le raspberry et saisir la commande suivante :

curl https://sh.rustup.rs -sSf | sh

Une fois l’installation terminée, pour vérifier que tout est bien en place, il y a deux commandes à faire :

rustc --version
cargo --version

La première donne la version du compilateur Rust, la seconde la version de Cargo.

Création du Hello World

La création d’un projet rust est très simple avec cargo :

cargo new first_rust_project

Pour lancer ce premier projet, c’est tout aussi simple :

cd first_rust_project
cargo run

Si vous voyez dans la console le texte « Hello, world! », c’est que votre installation Rust sur Raspberry fonctionne. Cool !

Par contre, ce n’est pas super fun et on est encore loin de faire des robots…

Pour rendre cela plus intéressant on va faire l’équivalent du Hello World pour électronique programmable : faire clignoter une LED.

Il va falloir modifier le code du projet pour ajouter la gestion des GPIO. Une multitude de choix s’offrent à vous pour cela, personnellement j’utilise Visual Studio Code pour coder en Rust. Son installation sur Raspberry se fait de la façon suivante :

sudo apt update
sudo apt install code

J’ouvre le projet dans VSCode :

# Depuis le dossier du projet
code .

Ajout de la dépendance pour accéder aux GPIO

Afin de faire clignoter la LED, il est nécessaire de contrôler les GPIO du Raspberry. Pour y arriver il existe différentes librairies, celle qui revient régulièrement dans mes recherches est rust_gpiozero, un portage de la librairie python gpiozero. Essayons donc celle-là pour commencer.

Dans le fichier Cargo.toml du projet il faut ajouter la dépendance vers rust_gpiozero :

[dependencies]
rust_gpiozero = "0.2.1"

On fait un petit cargo check après pour télécharger les dépendances.

Code blink

Modifions maintenant le fichier main.rs pour y importer gpiozero et modifier la fonction main pour instancier une LED et la faire clignoter :

use rust_gpiozero::*; // Import all from rust_gpiozero.

fn main() {
    // Create a new led on Pin 17. Should be mutable for blinking.
    let mut led = LED::new(17);

    // Blink the LED, on for 1s, off for 1s;
    led.blink(1.0, 1.0);

    // Infinite loop.
    led.wait();
}

Au niveau électronique il suffit de brancher la borne positive de la LED sur le pin 17, et la borne négative sur le pin 9.

RTR_0_Schema_1

Alors, non, je n’ai pas mis de résistance, c’est un montage rapide de test et en 3,3V je ne risque pas de cramer la LED sur la durée du test. Mais pour un vrai montage il faut mettre une résistance !

Une fois la LED branchée on lance le programme avec un petit cargo run et on obtient le résultat suivant :

Ça fonctionne !

Bon, encore une fois, rien d’exceptionnel, mais on avance.

Il y a cependant un souci avec la librairie rust_gpiozero : il n’y a pas eu de mise à jour depuis quelques mois, et la dernière release a plus d’un an. Espérons que le projet ne soit pas abandonné, sinon il nous faudra trouver une alternative.

En l’état on dispose d’un environnement fonctionnel pour développer des robots en Rust sur Raspberry Pi, cependant j’aimerai pousser plus loin la configuration de l’environnement.

Si vous ne souhaitez pas en savoir plus sur le sujet, vous pouvez vous arrêter maintenant la suite est facultative et plus expérimentale qu’autre chose.

Développement en remote

Comme dit juste avant, notre environnement de développement est fonctionnel, mais il ne me plait pas totalement. En effet on doit directement développer sur le RPI.

En soit ce n’est pas un problème, les Raspberry sont prévu pour cela, mais dans le cas d’une application robotique ou embarqué on sera souvent amené à choisir une distribution Lite, sans IHM.

Et qui dit pas d’IHM, dit pas de VSCode, personnellement je ne me vois pas coder tout un robot dans nano ou vim.

Il est plus agréable de travailler depuis le PC sur lequel on a l’habitude de développer.

Visual Studio Code : extensions pour le développement en remote

La première piste que j’ai vue est d’utiliser les extensions de VSCode pour faire du dev en remote, que vous trouverez ici.

L’idée avec cette solution est, sur VSCode, d’ouvrir le dossier du projet Rust qui se trouve sur le Raspberry en se connectant en SSH.

Les différentes étapes rapidement :

  1. Cliquer sur le bouton remote en bas à droite de VSCode.
  2. Cliquer sur Se connecter à l'hôte...
  3. Cliquer sur + ajouter un nouvel hôte SSH...
  4. Saisir la commande de connexion SSH.
  5. Sélectionner le fichier de configuration SSH à mettre à jour, personnellement je choisis C:\Users\{user}\.ssh\config.
  6. Refaire les étapes 1 & 2.
  7. Cliquer sur l’IP de l’hôte ajouté précédemment.
  8. Un nouveau VSCode s’ouvre, une fenêtre demande de saisir le mot de passe pour se connecter au RPI.
  9. Sélectionner le dossier à ouvrir, choisir le dossier du projet Rust sur lequel on souhaite développer.
  10. Ouvrir un terminal dans VSCode (Ctrl+Maj+ù).
  11. Faire un cargo run.
  12. Voir la LED clignoter.

On a donc un moyen de modifier le code depuis un PC (W10 dans mon cas), de l’exécuter et de le débuguer dans VSCode. C’est plutôt pas mal.

Il y a même la possibilité de cloner un repo Git directement depuis VSCode sur le Raspberry PI distant, ce qui peut être intéressant pour des projets plus importants avec plusieurs contributeurs. Cependant, cela amène deux aspects qui sont à mon sens problématique. Le premier est que les sources sont directement sur le Raspberry. Le second en découle directement, le repo Git est également sur le Raspberry. Cela implique qu’il faut configurer git sur le RPI et qu’en cas de merge c’est géré sur celui-ci, même si VSCode nous aide, si on est habitué à des outils spécifiques c’est plus compliqué.

Un autre point négatif est que le build est fait directement sur le Raspberry, du coup on est dépendant des ressources de celui-ci. Si le projet est gros le build risque d’être long.

Pros

  • Utilisation de VSCode depuis le PC
  • Build en remote
  • Debug en remote

Cons

  • Build du projet sur le Raspberry
  • Source directement sur le Raspberry
  • Utilisation et configuration de Git sur le Raspberry

Cette solution est particulièrement intéressante et efficace malgré ses défauts. J’étudie une autre piste qui pourrait permettre de les corriger, mais pour l’instant elle n’est pas concluante. J’en parlerai sûrement dans un autre article, car au final ce n’est pas le sujet de cette série et la solution actuelle est amplement suffisante.

Conclusion

Un article plutôt long pour simplement faire clignoter une LED sur un Raspberry Pi via du Rust, mais il était nécessaire de poser les bases et de se configurer un environnement efficace.

La prochaine fois on attaquera les choses sérieuses : l’utilisation de capteurs pour permettre à notre Robot de « voir » son environnement. Ça promet d’être intéressant.

Sources

Laissez un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.