Bricoleur du dimanche avec un scanner 3D

Le problème

Je redonne un coup de jeune à ma salle de bain et je dois tailler un plan de travail pour y poser un lavabo. Comment donc reporter le profil du mur sur une planche à couper ?

Côté bricolage classique, pas de soucis. Je remplace la toilette suspendue par une autre et je la déplace. Un peu de plomberie, un peu de Gyproc (BA-13) et de carrelage, tout va bien. Mais, vient le moment de poser le lavabo sur un réceptacle idoine. Selon les plans initiaux, tout est très simple. Il suffit de poser un plan de travail judicieusement coupé à l’endroit prévu à cet effet par des montants vissés dans les murs.

Or, il s’avère que ledit endroit en composé de plusieurs murs se jouxtant à angles tout sauf droits et que l’arête principale du plan de travail ne peut pas être matérialisée facilement : c’est une arête imaginaire entre le bord d’un mur et le bord de la toilette. D’où la difficulté à prendre des cotes fiables.

Les lieux

On peut voir le contexte du projet sur les photos ci-dessous. Un bâti en bois recouvert de BA13 et de carrelage. Et surtout, des murs (à droite sur les images) devant accueillir un plateau judicieusement coupé.

La solution

En bon bricoleur du dimanche, j’ai choisi d’utiliser un scanner 3D pour résoudre mon problème de report du profil de murs sur la planche à découper. J’ai jeté mon dévolu sur un TX8 de chez Trimble. En toute transparence, je dois mentionner le fait que ce soit mon employeur et que l’accès à la fois au matériel et aux logiciels (Trimble RealWorks et Trimble SketchUp) nécessaires à l’opération ont complètement motivé ce choix. Néanmoins, dans le principe, tout un chacun devrait sans doute pouvoir réaliser une opération similaire avec une Kinect et un logiciel libre comme CloudCompare (ou pas, je serais curieux de savoir).

La technologie

Le scanner 3D va permettre de mesurer précisément l’espace dans ma salle de bain. Le principe est de lancer des impulsions laser et de mesurer le temps qu’elles mettent à revenir jusqu’au télémètre embarqué dans le scanner. La vitesse de la lumière étant connue, il est ainsi possible de mesurer la distance parcourue. On convertit ainsi des secondes en mètres (ou en l’occurrence ici, des nanosecondes en millimètres).

Comme le scanner scanne (c’est à dire qu’il effectue un balayage), les impulsions vont ainsi échantillonner des points tout autour de l’instrument, permettant d’obtenir un nuage de points. À tire indicatif, le scanner Trimble TX8 échantillonne ainsi un million de points par seconde.

Le site de Potree offre des exemples de nuages de points visibles et manipulables directement sur le ouèbe.

Les données

Les captures d’écran ci-dessous montrent le nuage de points obtenu après la numérisation de ma salle de bain. On est sur un petit nuage de points de quelques dizaines de millions de points.

Le logiciel Trimble RealWorks permet d’effectuer des segmentations et donc de ne retenir que les points utiles à notre sujet, soit les murs et les montants en bois sur lesquels le plan de travail doit s’appuyer.

Les images suivantes en montre l’exemple : seuls ne sont visibles que quelques bouts de murs avec les montants de support.

La modélisation

Une fois la zone d’intérêt isolée, d’autres outils permettent de tracer un plan 3D tangent à 3 points répartis sur les montants en bois.

Pick 3 points-Trimble RealWorks
Plan 3D définit par trois points répartis sur les montants de support

Et une fois ce plan défini, on peut l’utiliser pour dessiner le contour des murs en s’aidant du nuage de points.

Create polyline-Trimble RealWorks
Contours du plateau dessinés à l’aide du nuage de points

Le polygone en vert représente maintenant la forme exacte souhaitée pour mon plateau à lavabo. Les images suivantes le montre dans l’espace en 3D. D’abord sous forme de contours sur le plan puis de polygone plein.

Les cotes et les coupes

Une fois cette géométrie obtenue, c’est un jeu d’enfant de l’exporter vers SketchUp et d’en sortir toutes les cotes et mesures qui peuvent être utiles.

Puis de reporter ces mesures sur la planche à débiter.

Vue de dessus du plateau une fois coupé
Vue de dessus du plateau une fois coupé

Au final, il ne reste plus qu’à couper et à poser.

Plan de travail
Plan de travail taillé et déposé sur les supports

La suite est aussi passionnante mais c’est du bricolage classique comme on en trouvera sur tout bon blog de rénovation de salle de bain. Je laisse donc aux experts carreleurs-blogueurs le soin de détailler le sujet.

Résultat

Installation finale
Installation finale

En conclusion

Pour reporter un profil mural sur une planche à couper, on peut soit écumer les solutions telle celle du carton et de l’X-ACTO, soit s’aider d’un scanner 3D et de la suite logicielle appropriée.

Note:

Bien sûr, le prix du scanner + suite logicielle dépasse largement l’investissement fait dans ma salle de bain (au moins par un facteur 50). Aussi, je ne conseille à personne d’acheter ce type de matériel uniquement dans le but de couper un bout de bois. Néanmoins, la capture de données 3D peut se faire par des moyens moins onéreux. En fouillant un peu et en bricolant, les principes énoncés doivent sans doute pouvoir être mis en œuvre avec du matériel un peu plus DIY.

Site de domotique

Rencontrés aujourd’hui, au Maker Faire de Paris: des bloggueurs inspirés par la domotique qui ont développé le « Smart Board Sensors » : une interface à base de Arduino permettant d’interfacer facilement une foultitude de capteurs et d’y accéder via HTTP et JSON.

Sur le stand, il y avait notamment une démo avec des électrovannes et des hygromètres. ça m’a rappelé quelque chose…  http://www.domotique-info.fr/

Un drapeau français en ligne de commande

Suites aux événement du vendredi 13 novembre 2015 à Paris (où j’habite), j’ai envie de partager cette petite ligne de code à lancer dans un shell (en tout cas ça fonctionne en bash).

 t=$(($(tput cols)/3));for FR in $(seq $(tput lines));do printf "e[44m%${t}se[47m%${t}se[41m%${t}se[0mn";done # French Flag

Le résultat devrait être quelque chose qui ressemble à l’image suivante:

CLI French flag

Merci à Command Line Magic (@climagic) pour cette belle trouvaille.

Gamme pythagoricienne

Lors des derniers posts, on s’est quitté sur des considérations d’encodage de caractère, de détection de langue et d’API REST. Comme on dit en Papouasie-Nouvelle-Guinée: « Time flies » !

Pendant cet épisode silencieux, une événement s’est produit: j’ai découvert la guitare (un instrument de musique généralement à six cordes). Le silence était donc tout à fait relatif, le reste de la maison peut en témoigner… Bon, bref, l’objectif ici n’est pas de m’épancher sur ma nouvelle vie de rock star (auprès des mes chats, ça fonctionne bien) mais de partager ce que j’ai découvert en essayant de comprendre tout ce qui m’apparaissait arbitraire derrière les concepts de gamme, de ton, de demi-ton. Et pourquoi 12 demis tons (pourquoi pas 10 ou 16). Et puis, entre mi et fa, pourquoi ce hiatus impromptu? Comme on dit aux Malouines: « First things first« , alors commençons par le commencement.

Pour tout individu ayant été un tant soit peu en contact avec la musique occidentale, il y a 7 notes, soit Do, , Mi, Fa, Sol, La et Si en suivant la nomination de Guido , ou C, D, E, F, G, A et B selon la notation anglo-saxonne.  Après on recommence. Mais en plus aiguë. On repart de Do mais une octave au-dessus. D’autres systèmes existent mais ce n’est pas l’objet de cet article.

Tout de suite, on se dit hé, ben ouais, 7 notes, comme les 7 jours de la semaine, les 7 péchés capitaux, les 7 plaies d’Égypte, les 7 nains de Blanche-Neige, les 7 doigts de la mains, les 7 commandements, les 77 dalmatiens, etc. Je m’emporte. C’est un peu vrai. N’empêche que les trucs un peu cool et mystérieux viennent souvent en bande de 7 (comme les Tortues Ninja, les mousquetaires, les saisons , les 7 tomes d’Harry Potter, le 7e ciel, les atomes de carbone dans l’heptane et le Supplique pour être enterré à la plage de Sète).

Donc, on se dit « héhé, 7 c’est cool, c’est un nombre premier sûr, c’est un peu mystiquifianisant, etc. c’est pour ça qu’il y a sept notes dans notre gamme ». Comme aurait dit Ovide: « Que nenni! » En fait l’explication est ailleurs.

Bien qu’il y ait plusieurs sortes de gammes, il y a un principe généralement admis: quand on double la fréquence d’une note, on retombe sur la même note en plus aiguë (augmentée d’une octave). Corollaire: en divisant par deux la fréquence d’une note, on reste sur la même note mais une octave plus basse.

Par exemple, si on part du La à 440 Hertz on trouve:

\(440 Hz \times 2 = 880 Hz\) fréquence du La suivant. Aussi \(\frac{440 Hz}{2} = 220 Hz\): fréquence du La plus grave.

Description
Illustration de la plage de fréquence d’une octave

Donc, entre deux notes identiques séparées d’une octave on a un intervalle de fréquence. Intervalle à diviser (couper en rondelles) pour obtenir des notes intermédiaire. On pourrait tous diviser cet intervalle en \(2, 3, 7, 12, 17, 32\) ou n’importe quel nombre et inventer son système musical personnel. C’est un peu ce qu’a fait notre ami Pythagore.

Après avoir savamment observé son monocorde favori, il s’aperçut que les notes étaient rarement pures. Une note pure est produite par une onde sinusoïdale  unique, qui oscille à une fréquence audible, ce qui pour l’humain correspond grosso modo à la plage \(20 Hz-20 kHz\). En fait, de façon naturelle, un corps vibrant génère des harmoniques, c’est à dire des notes secondaires particulières. Sans doute parce qu’elles sont naturelles et qu’on les retrouve un peu partout un peu tout le temps, l’oreille humaine y trouve un certain réconfort. Une certaine harmonie.

Harmoniques

Les harmoniques sont des multiples entier d’une fréquence de base. Si notre fréquence de base est <e\(f\), les harmoniques seront \(0 f, 1f, 2f, 3f, 4f, 5f\), etc. Chacun des harmoniques (si si, harmonique est masculin). Par exemple, un son à \(0 Hertz\) produira respectivement les harmoniques de fréquences suivantes: \(0 Hz, 0 Hz, 0 Hz, 0 Hz\), etc. En d’autre mots: s’il n’y a pas de source sonore ,il n’y a pas d’harmoniques. C’est plutôt rassurant et corrobore plusieurs lois physiques, notamment en rapport avec la conservation de l’énergie.

Comme les premiers harmoniques ont tendances à être de plus forte amplitude que ceux plus loin dans le spectre, on se concentre généralement sur ces derniers.

Si on se concentre sur les premiers entiers naturels, on a 0, 1, 2, 3, 4, 5.

  • \(0 f\), c’est un peu intérêt et on ne peut pas en faire grand chose.
  • \(1 f\) s’appelle fondamentale puisque c’est la fréquence de base. Le fondement. On se rappelle que 1 est l’élément neutre de la multiplication, ce qui veut dire que \(1 \times f = f\). C’est d’ailleurs aussi vrai pour quelques autres valeurs tel que le rappelle le tableau ci-dessous.
Tableau de la multiplication par 1 de nombres célèbres
Une fois Nombre Résultat
1 X 0 0
1 X +∞ +∞
1 X -∞ -∞
1 X NaN NaN
  • \(2 f\), on l’a déjà rencontré, c’est la même note mais à l’octave. Comme c’est la même note, ce n’est d’aucune utilité pour construire une gamme.
  • \(3 f\) est le premier harmonique intéressant. Comme c’est le 3e, on l’appelle quinte. (En fait, il y a une autre raison qu’on verra plus loin). C’est le premier et le plus simple. C’est avec lui qu’on va construire notre gamme.
  • \(4 f\) est le double de 2f, donc l’octave de l’octave. Si on était parti du La à \(440 Hz\), on serait maintenant sur le La \( \left(2 \times 440 Hz \right) \times 2\), soit un La de \(1760 Hz\). Comme on reste encore sur la même note, ce n’est toujours pas utile pour notre gamme.
  • \(5 f\) est le second harmonique à produire une nouvelle note. Comme c’est le 5e harmonique, on l’a naturellement nommé tierce. D’ailleurs, en plus de faire des gammes, Pythagore faisait des accords (avec des orchestres de monocordes?) et ce qu’on appelle accord parfait est justement composé de la fondamentale, de la tierce et de la quinte.
Nomenclature des premiers harmoniques
0f 1f 2f 3f 4f 5f
rien  la fondamentale l’octave la quinte l’octave de l’octave (2X2f) la tierce

 

Une fois tout ça en place, on va se concentrer sur la quinte: le troisième harmonique, soit le premier harmonique à produire une nouvelle note.

Cette note de fréquence \(3 f\) est supérieure à \(2 f\). (on se souviendra que \(3 \gt 2\) et que \( f\) est strictement positif). Elle est donc en dehors de l’intervalle \(\left[f, 2f \right]\) sur lequel on veut construire une gamme. Heureusement, grâce à une propriété énoncée plus haut, on sait que cette note existe aussi sur une octave plus basse (plus grave). Pour descendre d’une octave on divise par 2 la fréquence, par conséquent \(3 f\) et \(\frac{3}{2}f\) sont une seule et même note (à l’octave près). Bien sûr, \(\frac{3}{2}f\) = \(1.5 f\); ce qui tombe bien sur une fréquence comprise entre \(f\)et \(2 f\). On a enfin généré une première nouvelle note pour notre gamme. Si la note de départ était un Do, 3/2f tombera sur le Sol. Do, , Mi, Fa, Sol: Il y a 5 notes entre Do et Sol, on appelle donc ça une pinte quinte. En fait, il n’y a que trois notes entre Do et Sol. Mais bon, pour aller de Do à Sol, il faut bien dire Do, , Mi, Fa, Sol, ce qui nécessite 5 notes. C’est comme ça qu’on en arrive à nommer le produit du 3e harmonique «quinte».

Grayé de cet algorithme, on peut réitérer de façon récursive le processus. On prend la quinte de notre quinte. Partant de Sol = \( \frac{3}{2}f \), on trouve \( 3\times \left( \frac32 \right) f = \frac92 f \). Pour revenir dans l’intervalle \(\left[f, 2f \right]\) on peut diviser par deux autant de fois que l’on veut, en l’occurrence ici on le fera deux fois pour s’arrêter à  \(\frac98f = 1,125f\). On a donc une série de multiplications par 3 des fréquences et de divisions par 2 pour ramener la note dans l’intervalle de l’octave. Dit autrement, la fréquence de chaque note dans notre gamme basées sur les quintes successives a la forme
$$\left(\frac{3^n}{2^m}\right)f$$

Illustration de la position des notes en fonction de leur fréquence
Répartition des notes sur une octave

 

p.s.: cet article est resté à l’état de brouillon depuis longtemps,  trop longtemps. Le choix éditorial du jour est donc de le publier en l’état. Sans toutes le conclusions sur les gammes tempérées ou non, sur la quinte du loup et sans les tables où l’on peut voir la correspondance entre Hertz et note. Ces dernières tergiversations pourront toujours venir en complément.

 

Retour sur le dongle WI-FI Edimax nano

L’adaptateur Wi-Fi Edimax EW-7811Un n’aime pas le chaud.

On se souviendra que dans les articles précédent, j’ai présenté le dongle Wi-Fi Edimax EW-7811Un. Il est tout beau. Il est tout petit. Il est reconnu par la Raspbian et sur Lego Mindstorm. En plus il coûte moins de 10€. Bref, il a tout ce qu’il faut.

Enfin presque. Dès qu’il a chaud il boude. Le dongle est donc très bien pour une utilisation occasionnelle dans une maison par exemple. Dans mon cas, il doit assurer la liaison 24/24 depuis le cabanon du jardin (là où il y la le contrôle des électrovannes et tout et tout). Ledit cabanon étant ce qu’il est, c’est à dire ni plus ni mois que bonne vieille shed des familles, sans isolation aucune, la température monte l’été largement au-dessus des specs présumées. Enfin, c’est la conclusion à laquelle je suis parvenu. Ayant passé une gros câble RJ-45 de la maison au jardin pour fin d’investigation, j’ai pu m’assurer que le Raspberry Pi était toujours alerte même lorsque le dongle tait mort. En ces occasions, seul un reboot physique permettant de récupérer le dongle. Il faut couper l’alimentation du système. Un soft reboot n’arrive pas à relancer le Edimax EW-7811Un.

J’avais commandé deux dongle identiques et j’ai eu le même comportement avec les deux dongles. Ma conclusion est non scientifique mais relativement étayée par les faits sur un échantillon de 2 observations. J’ai d’autres aspirations que de valider ma théorie par des tests de Student ce qui me demanderaient d’agrandir mon échantillon au-delà de ce que je suis prêt à pourvoir en ressources pour ce problème. D’un point vue plus pratique, j’ai acheté deux autres dongles Ouiphi. Je les ai testés. J’en ai gardé un pour sa facilité de configuration. Le premier (j’ai perdu la référence mais je pourrais la retrouver en fouillant dans mon historique de commandes auprès d’un plus grand fournisseur de tout et n’importe quoi en-ligne) ne voulait pas se configurer facilement sur ma Raspbian. Le second, dont la référence m’échappe au moment d’écrire ces lignes (mais qui pourrait être retrouvée si telle était ma volonté) s’est installé comme un charme, et n’a plus jamais décroché.

Conclusion:
Le dongle WI-FI Edimax EW-7811Un est mignon, il est tout petit, mais il craint la chaleur. Ou du moins, il craint d’être online trop longtemps (la chaleur comme source du problème étant une hypothèse probable mais pas entièrement démontrée). Je le conseille donc plutôt pour une utilisation occasionnelle. Si l’objectif est d’avoir du 24/7 (ce qui approche la valeur de 3,428571428571429 mais vous aviez compris que je ne parlais pas de ça), alors mieux vaut chercher un dongle un peu plus gros, mais un peu plus robuste.

Unicode, UTF-8 et autres considérations

Unicode, UTF-8 et autres considérations

Comme mentionné précédemment, manipuler du texte en différentes langues nécessite  de s’intéresser au codage des caractères. Il y a beaucoup de choses  à dire sur l’ASCII (version originale à 7 bits, puis étendue à 8 bits), sur l’Unicode et les différentes façon de représenter les caractères. Mais Internet est là pour ça et beaucoup l’ont expliqué mieux que je ne saurais le faire.

Concentrons nous donc sur le problème concret de la création d’histogramme de n-gram à partir de caractères UTF-8. Selon votre langage de programmation favori, un caractère peut avoir différentes significations.  En C et comme dans beaucoup de ses dérivés, un « char » est une suite de 8 bits. C’est donc simplement un nombre entier compris entre [-127, 128] ou [0, 255] selon qu’on le considère signé ou non-signé. C’est tout. Fin de l’histoire. Il n’y a aucune notion de représentation derrière, un caractère est un entier défini sur un domaine restreint de 256 valeurs.  Ça tombait plutôt pas mal, le standard ASCII, après une mise à jour, associait une lettre, un élément de ponctuation, un chiffre, un caractère à chacune de ces 256 valeurs possibles. La plupart des langues basées sur l’alphabet latin peuvent être couvertes avec 256 symboles (sachant qu’il faut aussi garder de la place pour le chiffres, la ponctuation, des signes essentiels comme $, £, &, @, % et autres #. En y ajoutant quelques symboles qu’on ne voit pas mais qui sont nécessaires (comme le changement de ligne (0x0D), le son de cloche (0x07) ou le 0x15  NAK « negative acknowledge », on remplit rapidement l’espace disponible. Notons que l’euro (€) n’existait pas à l’époque, donc le symbole n’est pas inclut dans l’ASCII. On le retrouve grâce à l’Unicode.

256, c’est joli mais c’est petit

En fait, toutes les langues utilisant un alphabet latin ne peuvent pas s’écrire avec 256 symboles (moins les trucs bizarres comme le NAK). Si on met les ğ et Ş turcs, il n’y a plus de place pour les Ð, Þ ou æ islandais par exemple. Et puis vous savez quoi ? Il y a une multitude de langues qui n’utilisent pas l’alphabet latin ! Déjà que l’ascii ne couvrait pas toutes les déclinaisons de cet alphabet, on peut imaginer le problème des alphabets inuitcyrillyquehindî, grec, arabe ou hébreux et plus encore des idéogrammes asiatiques tels les sinogrammes ou les hiraganas.

On veut des bits

Naturellement on se dit qu’il n’y a qu’à rajouter des bits. En effet, en passant à seize (16) bits par caractères, on atteint un potentiel de 65536 symboles différents. En passant à 32 bits, on ouvre les mode des possibles à plus de 4 milliards de lettres/symboles/idéogrammes/smileys.

Bref, tout ça pour dire que l’UTF-8 peut représenter l’ensemble des caractères des langues naturelles en utilisant un nombre variable d’octets. Pour les 128 symboles de l’ASCII de base (2 7 bits = 128 possibilités) tout se passe comme il faut, un seul octet est nécessaire. Ça couvre l’anglais, la ponctuation et quelques autres caractères fondamentaux comme l’inénarrable barre verticale « | » (0x7C).

Mais me direz-vous, octet, octant, octogone, octopode ça me rappelle vaguement le nombre huit. Et bien oui, le huitième bit de l’octet UTF-8 sert à signaler qu’on est dans un cas spécial et qu’il faut combiner les bits déjà lus avec ceux de l’octet suivant pour retrouver notre caractère qui est donc en dehors du domaine des 128 codes de base. Le second octet ayant évidemment lui-même un bit signalant la possibilité d’aller voir chez l’octet suivant et ainsi de suite jusqu’à… 4. Donc un caractère codé en UTF-8 est une suite de 1, 2, 3 ou 4 octets.

L’UTF-8 a beaucoup d’avantages et est largement répandu sur Internet. Je fais donc le Postulat numéro 1 (ou serait-ce un axiome?) que les données d’entrées seront codées de cette façon. Si ce n’est pas le cas, la pléthore d’outils permettant la conversion d’autres systèmes vers UTF-8 permettra, via un pré-traitement des données, de s’assurer de la validité dudit postulat.

Mais alors, c’est quoi un caractère ?

Ça peut être beaucoup de chose. Twitter s’est d’ailleurs posé la question puisque leur mission est de les compter jusqu’à hauteur de 140 (un nombre abondant). Leur définition semble satisfaisante pour les besoins de création de n-gram. Grosso-modo, un unigramme est un « code point« , c’est à dire un ensemble de 1, 2, 3 ou 4 octets représentant une lettre, un idéogramme, un symbole.

Ce n’est pas parfait parce que l’Unicode permet la composition. Par exemple, pour faire ê, il y a plusieurs chemins. La lettre e peut être accentuée, c’est dire qu’une séquence comprenant 2 code points peut être utilisée (un « e » suivi d’un « ^ » ou vice versa, j’en sais trop rien) ou bien on peut aussi coder directement le symbole ê. C’est un exemple de non-orthogonalité flagrante selon une de ses définitions en informatique (2 façons d’arriver au même résultat). L’autre définition portant sur les effets collatéraux d’un appel de fonction sur un appel précédent. C’est dans le même esprit mais je m’égare…

Idéalement, tous les diacritiques devraient être normalisés pour être codés sous la même forme. Mais le postulat numéro 2 dit que ce n’est pas nécessaire. D’ailleurs, l’intérêt est de voir si ça marche avec n’importe qu’elle entrée ayant été le moins pré-traitée possible. Si ça ne fonctionne pas, on remettra en cause le Postulat numéro 2. Pour l’instant, on considère que le système sera assez robuste pour être efficace malgré le biais induit par les différents codages d’un même glyphe. Si ça se passe mal, on rétrogradera le postulat en hypothèse qu’on infirmera. Pour l’instant allons de l’avant.

La ponctuation ?

Les points, point d’interrogation, virgules sont de bons indicateurs de fin ou de début de mot. Ils sont donc utiles puisque selon les différentes langues, les lettres n’ont pas la même fréquence en début ou en fin de mot. L’espace (un nom féminin dans ce contexte !) joue donc aussi un rôle important et doit être considéré comme un caractère à part entière. Cependant, selon l’origine du texte, on peut se retrouver avec des suites de 2, 3 voire 10 espaces consécutives. Le trigramme  »    » (3 espaces à la queue-leu-leu) est même le plus fréquent avec les données Wikipedia pour le français et l’anglais sur mes premiers tests. C’est un facteur qu’il faudra prendre en compte.

Et concrètement ?

Tout ça pour dire que j’ai trouvé une façon simple de regrouper des unigrammes, des bigrammes et des trigrammes malgré le fait que chacun des code point soit en fait une une chaîne  de caractères. Merci à cette librairie qui permet d’itérer sur les code points tout en gardant l’accès aux positions des octets sous-jacents.  De cette façon, on peut avancer de un, deux ou trois caractères pour former les n-grammes et construire une std::string à partir des positions des octets. L’histogramme se bâtit en incrémentant les valeurs d’une std::map où la clef est une std::string et la valeur un compteur (int, long long, etc.)


#include <fstream>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>

#include "utf8/utf8.h" //http://www.codeproject.com/Articles/38242/Reading-UTF-with-C-streams

typedef std::map<std::string, int> histotype;
typedef std::pair<std::string, int> histonodetype;

void PrintGrams(const histotype& gram)
{
    std::vector<histonodetype> vectgram;

    std::copy(gram.begin(), gram.end(), std::back_inserter(vectgram));
    std::sort(vectgram.begin(), vectgram.end(), [](const histonodetype& left, const histonodetype& right){return left.second < right.second;});

    for(auto elem : vectgram )
    {
        std::cout << elem.first << " " << elem.second << std::endl;
    }
}

int main(int argc, char** argv)
{
    std::ifstream in(argv[1]);
    std::string line;

    histotype unigram;
    histotype bigram;
    histotype trigram;
    while( std::getline(in, line))
    {
        typedef  decltype(line.begin()) ittype;
        utf8::iterator<ittype> it(line.begin(), line.begin(), line.end());
        utf8::iterator<ittype> endit (line.begin() + line.size(),
                line.begin(), line.begin() + line.size());

        if(it==endit) // check for end of line
            continue;

        auto unibeg = it;
        auto bibeg = it;
        auto tribeg = it;

        it++;

        unigram[std::string(unibeg.base(), it.base())]++;
        it++; unibeg++;
        if(it==endit) // check for end of line
            continue;

        unigram[std::string(unibeg.base(), it.base())]++;
        bigram[std::string(bibeg.base(), it.base())]++;
        it++; unibeg++; bibeg++;
        if(it==endit) // check for end of line
            continue;

        for(;it != endit; it++, unibeg++, bibeg++, tribeg++)
        {
            unigram [ std::string(unibeg.base(), it.base())]++;
            bigram  [ std::string(bibeg.base(), it.base())  ]++;
            trigram [ std::string(tribeg.base(), it.base()) ]++;
        }
    }

    PrintGrams(unigram);
    PrintGrams(bigram);
    PrintGrams(trigram);

    return 0;
}
Programme de création de n-grammes

Ce code compile avec une version récente de gcc (il y a quelques éléments de syntaxe du c++0x11). C’est une preuve de concept, pas du code de production, mais si vous voulez expérimenter la génération de n-grammes, c’est un bon point de départ.

Pour ma part j’ai testé quelques 100 000 lignes en français et en anglais venant de Wikipedia (avec et sans les tags XML) et malgré les biais induits par les nombreuses suites d’espaces et les séquences spéciales pour mettre en forme le texte sur Wikipedia (les [[[,  »’, et autre), on voit déjà poindre les « de  » et « ng  » en pôle position pour respectivement les trigrammes français et anglais.

Le choix et le pré-traitement des corpus d’apprentissage sera un dossier en soi, mais d’ici là, je compte travailler sur le stockage des résultats (peut-être avec SQLite) et leur mise à jour (peut-être via une API REST.

 

Identification de la langue d’un texte

 Identification de la langue d’un texte

Récemment, un article m’a rappelé qu’il était serait amusant de faire un système pour détecter de manière automatique la langue dans laquelle un texte est écrit. L’article en question parlait de complètement autre chose et ne faisait que reprendre les résultats d’un blog anglophone. Cependant, en présentant d’une certaine façon les distributions d’occurrence des lettres au sein de quelques langues européennes, je me suis souvenu que ces distributions donnaient une signature qu’on pouvait utiliser pour reconnaitre la langue d’un texte. Ce peut aussi d’ailleurs être utilisé pour briser les codes simples comme le chiffre de César tel que Simon Singh nous l’expliquait dans son excellent livre sur l’histoire des codes secrets.

Pour créer les signatures, on peut analyser la fréquence d’occurrence des lettres individuelles, mais aussi des séquences de deux lettres consécutives. Par exemple en français, la séquence « ch » est plus fréquente que « sh » ou « cz ». D’autres langues présenteront d’autres proportions pour ces même suites. Et pourquoi s’arrêter à deux ? On peut aussi répertorier les séquences de trois, quatre ou N lettres consécutives. C’est ce qui s’appelle des  n-grams. Ça ne se résume pas qu’aux lettres et ça ne sert pas qu’à détecter une langue, mais c’est le contexte dans lequel le présent projet va les utiliser.

Sommairement, il s’agit donc de :

  • Créer des signatures basées sur les n-grams pour différentes langues
  • Extraire la signature d’un texte inconnu dont on veut identifier la langue
  • Comparer sa signature avec celles des langues « apprises »
  • En déduire l’idiome du texte

La signature n’étant que l’histogramme des fréquences d’occurrence des différents n-grams.

Heu… mais pour quoi faire ?

Clarifions tout de suite un point : je n’en ai personnellement aucune utilité. Ce n’est ni lié à des sujets professionnels, ni à un quelconque outil qui pourrait me servir. La recherche sur le sujet est bien avancée et je ne cherche pas à l’approfondir. Tous les jours on peut d’ailleurs voir à l’œuvre des sites qui ont de très bons résultats dans le domaine. Cependant, la (relative) simplicité de mise en œuvre d’une solution à un problème qui peut sembler aussi complexe est fascinante.  C’est donc en pur dilettante que j’ai envie de jouer un peu avec ce problème.

D’un autre côté, bien que la solution soit conceptuellement simple, quelques détails pratiques font qu’il y a tout de même quelques petits défis à relever et questions à répondre. Comment trouver des données d’apprentissage ? Comment gérer les caractères internationaux, l’Unicode et les codages à nombre variable d’octets (par exemple l’UTF-8) ? Que faire de la ponctuation, des espaces, ou même des tags HTML dans le cas où les données viendraient de source web ? Quelle technique choisir pour mesurer la similarité des signatures (vecteurs de cardinalité et de dimensions différentes) ? Comment présenter les résultats ? Bref, suffisamment d’interrogations pour rendre le projet intéressant.

 Étapes du projet

Avant de me lancer, j’ai détaillé sommairement les grands blocs ou thèmes sur lesquels il faut travailler. Je les présente ci-dessous, sachant que cela n’a rien de formel. Ce découpage est relativement orthogonal, ce qui permet de travailler indépendamment sur un sujet ou un autre.

    • Création des bases de données
      1. Obtenir des sources de texte
      2. Analyse des langues
      3. Stockage des résultats
    • Reconnaissance de la langue
      1. Analyse et création des signatures
      2. Comparaison avec les signatures en base de données
      3. Calcul des estimations de probabilité pour chaque langue
    • Interface et interaction
      1. Soumission des données à analyser
      2. Mise à jour de la base de données
      3. Affichage des résultats

 État des lieux

Corpus d’apprentissage

J’ai quelques pistes pour les corpus d’apprentissage. J’ai expérimenté un peu avec Wikipedia qui permet de télécharger l’intégralité de son contenu à un instant t. C’est trié par langue et de nombreuses langues sont disponibles. Pour récupérer le contenu de Wikipedia, c’est mieux que :

quirysse@beluga:~$ wget --random-wait -r -p -e robots=off -U mozilla http://en.wikipedia.org/wiki/Main_Page

Le problème c’est que c’est gros. Très gros.

wilhelm@beluga:~/WikiCrawl$ ll -h *xml
-rw-r--r-- 1 wilhelm woodself 46G Jul  9 00:58 enwiki-latest-pages-articles.xml
-rw-r--r-- 1 wilhelm woodself 12G Jul 16 21:00 frwiki-latest-pages-articles.xml
wilhelm@beluga:~/WikiCrawl$
Espace occupé par deux langues sur Wikipedia

 

De plus, les fichiers sont codés en XML dans le langage de Wikipedia, ce qui après quelques tests, même après avoir enlevé les tags XML, on trouve beaucoup d’occurrences de  » [[ »  et autres balises du genre. Ça reste quand même une option mais un peu de préparation de la base de données s’avèrera nécessaire. Il y a une piste avec European Parliament Proceedings Parallel Corpus 1996-2011. C’est d’ailleurs ce qui a été utilisé dans l’article cité plus haut.

Analyse

La génération d’histogrammes d’unigrammes, de bigrammes et de trigrammes n’est pas un souci en soi. Cependant, il faut penser au codage Unicode et comme l’UTF-8 semble tout indiqué, il faut gérer le fait qu’un caractère puisse être composé d’un nombre variable d’octets. Un article complet sur le sujet est en préparation, puisque grâce à cette bibliothèque on peut arriver rapidement  à une solution.

Stockage

Les histogrammes, on en fait quoi ? Ils peuvent être longs à générer. On peut vouloir les mettre à jour en utilisant de nouveaux corpus et de nouvelles langues. Alors SQL, fichier maison ? A voir.

Détection de la langue

De façon naturelle on pense au cosinus, mais ça cause certaines difficultés. Je pense plutôt à une erreur RMS ou une distance euclidienne sur les dimensions présentes dans le vecteur d’entrée. Et puis qu’est-ce qu’on fait des hapax et des n-grams très rares. On les garde ou on nettoie le vecteur d’entrée ? Rien n’est fixé mais on en reparlera.

Interface

Évidemment, tout commence toujours pas une série de petits scripts bash et 2 ou 3 mini programmes en C++. Mais au final, une API REST pour obtenir les probabilités des différentes langues sachant une signature pour un texte en entrée, ça serait sympa, non ? Et une page web où l’on verrait les probabilité évoluer en même temps qu’on entre du texte dans un champ, ça serait encore mieux ! C’est un dossier qui est encore un peu loin, mais il y a du potentiel pour faire un système agréable. Pour l’instant, on va en rester au bash…

Conclusion

Donc, voilà où on en est. L’UTF-8 est à peu près réglé (article à suivre). Reste à faire le reste. C’est à dire, à peu près tout…

Framboise en boîte 5/N

Préambule

Bon, il fait beau, il fait chaud, on a tous le soleil dans les yeux et le sourire aux lèvres… Surtout, mes plants de tomates ont 5 pieds de haut, il est grand temps de terminer ce post préparé au mois de mai (déjà, mais qu’est-ce que le temps passe). Donc voilà, on conclut sur l’installation de l’arrosage et on passe à autre chose. En fait, il restera la partie où notre amie la Framboise Magique se connecte à Internet pour déterminer toute seule le moment idoine

C’est en creusant qu’on devient creuseron (du verbe creuserer)

Après avoir validé les différents sous-systèmes, il est temps de mettre en place l’arrosage proprement dit. C’est à dire qu’il y a un moment où le geek intérieur doit laisser la place aux pulsions du cerveau reptilien et que, tel le mammouth creusant son nid, le jardinier numérique doit prendre sa pelle et sa pioche afin de libérer l’espace nécessaire au creux de notre bonne vielle Terre afin d’y installer des vannes et des tuyaux.

 Galerie de quelques étapes creusatoires

J’y vais un peu dans le désordre. En gros, pour enterrer des tuyaux, il faut faire des trous. Je laisse le soin à chacun de trouver sa façon de faire. Tous les goûts étant dans la nature, ce n’est pas un terrain sur lequel j’ai envie de m’avancer. On déplace de la terre, on la remplace par des tuyaux et on rebouche, le tout avec le modus operandi choisi.

Et les électrovannes ?

Qu’est-ce qu’on fait avec les électrovannes ? On les enterre comme un vulgaire tuyau de polychlorure de vinyle ?   Que nenni ! On les protège, les chouchoute, on leur creuse un nid. Donc, on fait un gros trou, rond ou carré. Ça dépend du nid choisi. Le nid en question s’appelle un regard pour électrovanne. C’est un caisson fait pour accueillir des choses enterrées avec divers trous permettant le passage des tuyaux et des gaines électriques. L’astuce c’est qu’une fois ledit caisson mis en terre, on garde un accès à son précieux trésor via une trappe, un regard. Tout est dans tout. Le regard pour électrovanne accueille des fils électrique (électro), des tuyaux (vanne) tout en préservant un accès depuis le monde  des vivants (le regard).

Comme souvent quand on met les doigts dans la flotte, on pense au drainage. En l’occurrence, un grosse poche de gros cailloux à moins de 10€ pour 25 kg fera l’affaire (Les gens biens appellent ça gravillon, c’est joli et ça rime avec papillon. Ça n’en reste pas moins qu’un tas de cailloux).

Donc les cailloux vont au fond du trou. Ensuite on met les vannes, on passe les câbles électriques (contrôlés via les relais et le Raspberry Pi mais on l’a vu dans les chapitres précédents). Il y a même de l’information en-ligne sur la mise en place des ces fameux regards.

Les dangers du monoxyde de dihydrogène

C’est au moment de brancher les câbles électriques sur les électrovannes qu’on réalise que, malgré le drain caillouteux, la pérennité du système semble mitigée.  On pourrait se dire : il fait beau, mon trou est rempli d’air sec, un domino et puis basta. Mais que se passera-t-il lorsque la bise sera venue et amènera avec elle des litres d’eau à en saturer ma terre nourricière ? Eh ben c’est simple, le monoxyde de dihydrogène (rempli de sels ionisés et donc conducteur) fera en sorte que l’installation s’autodétruira, en créant au passage un tremblement de terre,  des famines, des électrocutions massives et toutes sortes d’autre horreurs dont l’honnête citoyen que j’essaie d’être ne peut porter la responsabilité sur ses frêles épaules. Il possible que ce soit moins dramatique mais ce n’est pas certain. Le principe de précaution m’a donc amené à trouver une solution simple: le connecteur étanche. Il s’agit d’une mini-éprouvette remplie de gras dans lequel on vient planter une marette. Le gras n’étant hydrosoluble (à moins que ce ne soit l’eau qui soit lipophobe), une fois les conducteurs engoncés dans le gras, ils sont à l’abri des assauts de l’eau.

Varia

Pour les tomates, j’ai installé un tuyau poreux enterré qui répand l’eau directement sous les racines des plants. Comme ça, on minimise l’évaporation et les risques de différents champignons qui peuvent se former sur le feuilles des tomates trop humides.

J’en ai profité pour installer sur le réseau hydraulique un peu de tuyau goutte-à-goutte. Tant qu’à faire, aussi bien rassasier les géraniums en même temps que le reste…

Le rythme de tomates  n’étant pas nécessairement celui de la pelouse, j’ai installé quelques tuyères sur un second circuit pour cette dernière. Donc 2 relais, 2 électrovannes et 2 programmes d’arrosage.

Et maintenant ?

Maintenant, les plants de tomate sont grands mais pas encore leurs fruits. La pelouse n’a jamais été aussi verte. Ça marche. Cependant, le contrôle se fait encore avec un bon vieux crontab des familles. Je suis donc arrivé au même point du point de vue fonctionnel que si j’avais acheté un programmateur d’arrosage sur le marché. C’est tout de même un peu différent puisque personne à part moi ne peut faire le ssh qui va bien via la tablette numérique et commander l’arrosage. C’est une lourde responsabilité. Par contre,  lors de nos barbecues mondains, l’effet est tout à fait réjouissant. En effet, faire jaillir l’eau sur la pelouse depuis sa tablette et lui commander de retourner d’où elle vient du bout des doigts permet d’avoir une petite minute de gloire entre deux merguez.

Donc la suite sera sans doute de faire une interface web pour contrôler plus facilement facilement l’installation. Mais surtout, de surveiller le web pour connaître la météo et de décider automatiquement s’il faut arroser ou non. Là, on aura un système vraiment intéressant.

Ce sera la prochaine étape du projet arrosage (pour ceux qui ont suivi, N sera donc supérieur ou égal à 6). Mais d’ici là, je pense que je vais commencer un autre truc qui me démange… Mais il est tard, on en parlera une autre fois.

 

<– Précédent –|

Un peu de selfies en 3D

Ça y est, Google IO est en route et les annonces sont faites. Permettez-moi donc de publier mon selfie fait avec le prototype de Google Tango. La couleur matérialisant ici la carte des profondeurs (des distances). En arrière plan, on voit l’image capturée par la caméra RGB.

Selfie avec un Google Tango
Selfie avec un Google Tango

Rien de grandiose d’un point de vue artistique (quoiqu’ une certaine inspiration Pop Art puisse en ressortir) mais l’effet est plaisant.

Puisqu’on est dans les selfies et que j’avais  un Trimble TX8 ce week-end à la maison, j’en ai profité pour réaliser cette petite photo de famille devant le parasol du jardin.

Selfie 3D dans le jardin avec un Trimble TX8

Pour terminer, comme il y a toujours un chat qui traîne dans le coin, j’ai aujourd’hui retrouvé Diderot dans mes données scannées…

Framboise en boîte 4/N

Le futur

Dans cet article, nous aborderons les technologies futuristiques (à ne pas confondre avec futuristes) des drivers FTDI qui permettent à notre sympathique framboise de communiquer avec ses relais (là, le s s’avère nécessaire réforme ou pas1 ).

Retour sur l’Arros-o-tron

La dernière fois, nous avons testé l’ensemble de contrôle des relais avec de la vraie eau, tout à fait vraiment vraie (et humide). Malencontreusement, quelques digressions annexes nous ont fait perdre le focus (qui a la fâcheuse propriété d’être évanescent) et la conclusion s’en est allée. Cette conclusion, je vous la donne donc directement en introduction du l’article N+1 (N est ici tout à fait déterminé, il s’agit du nombre 3.  À ne pas confondre avec N, le nombre total d’articles sur le sujet qui nous occupe, qui lui n’est pas encore déterminé. Ou peut-être que si, dans l’hypothèse où vous liriez cet article dans le futur par rapport à maintenant. Peut-être  n’avons-nous pas le même maintenant. Nous verrons d’ailleurs plus loin comment FTDI  a répondu à cet opaque problème. Mais enfin, je m’égare).

Donc oui, ça marche. On contrôle très bien l’électrovanne à partir de l’alimentation 12V et du relai. L’eau jaillit et se tarit à souhait à partir de simples commandes (connexion ssh sur le Rapsbperry Pi et quelques commandes UNIX).

Ce ne sera pas la configuration finale, mais pour ce premier test arrosatoire, j’ai utilisé une électrovanne 24 VAC. Je l’ai commandée à partir de mon alimentation 12 VDC (voir article premier). Pas très orthodoxe, mais je suis parti de l’hypothèse que les tensions nominales sur n’avait pas à être franchement respectées. Selon notre ami Maxwell (rien à voir avec le café), s’il y a du courant dans la bobine, on pourra faire bouger un truc en utilisant la force du champ magnétique induit par le passage des électrons enivrés par les enroulements de notre conducteur. Jamais dans ses équations est dit qu’on doive respecter les tensions nominales de notre fournisseur de solénoïdes. Je fais sans doute quelques raccourcis, mais toujours est-il que ça marche (d’ailleurs pour ce test, j’ai bien appliqué 12 volts en courant continu alors que nominalement on requérait du courant alternatif, na!)

Contrôleur du travail

Les électrovannes en tant que telles pourront d’ailleurs être l’objet d’un article ultérieur tant il y a à dire sur cet objet contrôlant le travail. En effet, en autorisant ou interdisant le déplacement de masses d’eau, la vanne contrôle le travail (on se souviendra qu’il y a vaguement un lien entre la force (qui peut elle-même être liée à la masse) et le déplacement). Les joyeux jaillissements de l’eau à travers mon tuyau sont donc du travail. Et comme toute peine mérite salaire, Veolia ne manque pas de se faire rétribuer à chacune de mes saillies.

 Le contrôle de la carte à relais

Nous avons déjà dit que la carte USB-X440 était munie d’un connecteur USB (et de cinq trous de quatre millimètres, mais ce dernier constat n’intervient que très peu, ou pas du tout, sur le sujet précis qui nous occupe dans cette section). En fait, la carte USB-X440 communique en série. Oui, oui, ce bon vieux port série, le RS-232, les stop bit et start bit, la parité, le baud, et tout et tout. A priori, rien de très sexy. C’est là que la technologie du future entre en jeu.

FTDI produit des chips qui permettent d’émuler une communication de type RS-232 à travers un support USB.

Petit mot sur le futur

On se souviendra que dans les années 1990, et même avant, plusieurs entreprises ajoutaient le suffixe 2000 à leur raison sociale ou à leurs produits. Du système d’exploitation au plombier du coin, tous étaient résolument tournés vers l’avenir et la modernité. Tout le monde voulait son 2000. C’était dans l’air du temps, et si l’on a moins de 20 ans, on ne s’en souvient guère. Cette bohème ne pouvait pas durer éternellement parce qu’elle avait un défaut intrinsèque: le temps passe, les années changent, et le futur d’hier devient le passé d’aujourd’hui. Si Windows 2000 n’est plus qu’un (plus ou moins bon) souvenir, tous les chauffagistes 2000, les menuisiers 2000 et autres assureurs 2000 qui ont survécus sont passés de visionnaires à passéistes, tournés à jamais vers une époque de plus en plus lointaine.

FTDI a trouvé la solution. Bien qu’issue des années 1990, cette entreprise est à jamais tournée vers l’avenir, puisque son point de fuite n’est pas une année déterminée, mais bien le futur en personne. Ce futur qui dès maintenant et pour toujours sera invariablement devant. FTDI est en effet l’acronyme de Future Technology Devices International ce qui se traduit (assez librement) par: « Bidules internationaux basés sur la technologie du futur ». Le problème de la relativité temporelle est donc résolu. Peu importe le point de vu, FTDI sera toujours devant.

Le port série automagique

Quoi qu’on en dise, les circuits FTDI on plusieurs atouts :

  1. Ils permettent une communication simple à travers une connectique standard (USB était encore répandu au moment d’écrire ces lignes, bien que cela paraisse incongru au lecteur d’un certain futur)
  2. Les spécifications sont ouvertes et il est donc aisé d’écrire les pilotes idoines
  3. Ils sont supportés nativement par tous les bons noyaux près de chez vous

Ce troisième point est particulièrement intéressant. C’est la pierre d’achoppement du l’automagicité. En effet, il suffit de relier la carte munie du chip FTDI  à son ordinateur (en l’occurrence, un Raspberry Pi faisant tourner une distribution Raspbian) pour n’avoir rien à faire… En fait le pilote papote avec le chip. Chacun fait sa tambouille de son côté. On finit par s’entendre sur un truc du genre 9600 8N1. Et hop, on se retrouve avec un device dans /dev/ttyUSB0

pi@nsa ~ $ ls /dev/ttyUSB0
/dev/ttyUSB0
pi@nsa ~ $

On a donc une émulation de port série, installée en quelques millisecondes, sans aucune configuration. C’est à ce demander à quoi sert de faire un blog pour en parler tellement l’opération est sans douleur.

Du coup, de façon tout à fait classique, pour envoyer une commande à la carte, on écrit dans /dev/ttyUSB0 et, symétriquement, on lit dans /dev/ttyUSB0 pour recevoir des messages (le zéro (0) pouvant bien entendu être incrémenté si plus d’un port USB émulé est présent).

D’après la documentation, la relais se commandent ainsi:

Sxb

S veut dire relai (switch?)

x, le numéro du relai

b, une valeur booléenne (0 ou 1) pour changer l’état du relai.

Il suffit donc d’écrire dans sa commande dans le tty pour pour commander une action, en utilisant echo par exemple.

Cela donne donc, comme on l’a vu précédemment:

Relai #1 au repos:

pi@nsa ~ $ echo S10 &gt; /dev/ttyUSB0

Relai #1 actif:

pi@nsa ~ $ echo S11 &gt; /dev/ttyUSB0

Pour écouter ce que nous dit la carte, on utilisera cat :

pi@nsa ~ $ cat /dev/ttyUSB0

La suite

On se rendra donc bien entendu à N 5 puisque nous n’avons pas encore abordé l’installation du circuit hydraulique, le creusage dans le jardin ni la plantation de tomates.

<– Précédent   Suivant –>