Tous les articles par Jonathan Munn

Code : stratégies de débogguage

Parfois, lorsqu’un sketch tourne, c’est utile d’afficher des informations complémentaires afin de montrer si des parties de notre code tourne comme prévu. Le cas c’est produit récemment avec un étudiant de 4e année qui faisait du tracking avec un Kinect, la visualisation de son sketch ne donnait pas le résultat escompté lors des interactions. Mais où se trouvait le problème ?

Pour les besoins de ce code, on va supposer que kinet.getHand() invoque une librairie externe qui récupère les informations formattées venant du Kinect 60 fois par seconde. Que la classe kinect peut détecter une main et retourner la forme détecter, ainsi que le rectangle qui enferme cette forme de main. Et que la fonction rectInRect() retourne true s’il y a recouvrement entre les deux rectangles, et false sinon. Mais en fin de compte, ces details ne sont pas importantes.

Si les collisions ne semblent pas fonctionner, nous avons besoin, tout d’abord de vérifier que les informations arrivent de la part du Kinect.

Dans ce cas, on devrait voir un restangle rouge translucide à l’écran et qui devrait suivre la position de notre main. Si nous ne voyons pas ceci, soit le Kinect, soit la librairie ne fonctionne pas prévu, et nous rechercher ailleurs.

Pendant que nous travaillons sur notre sketch, nous allons rajouter et enlever ce bout de code à plusieurs reprises, probablement en utilisant des commentaires pour le rendre inactif.

Or, il existe une manière plus simple.

Il y a plusieurs choses à voir dans ce code. Le premier est l’emploi d’un constant debug. Différents langages de programmation gèrent les constants de la même manière, mais le principe reste pareil — une fois que ce genre particulier de variable a été défini, il ne peut plus être changé par la suite, le variable reste constant… Ceci possède au moins deux avantages. Primo, on ne peut changer sa valeur par accident ailleurs dans notre code, ce qui peut se produre quand le code devient plus complexe. Deuxio, il y a généralement un petit avantage de vitesse, car lors de l’exécution du programme [ou sketch] l’environnement n’a pas besoin de vérifier si le variable a changé de valeur.

Dans Processing, le mot clé final permet d’indiquer que ceci est la valeur finale, et donc ne peut pas changer. Tout ce qu’on peut demander d’un constant.

Lors de l’exécution de notre code, on utilise une condition — si debug est vrai, alors exécute le code suivant, sinon on le saute. Ceci permet de garder des bouts de code de débogguage en place dans notre code, puis de les activer/désactiver en changeant la valeur de notre constant — soit true, soit false.

À noter aussi, comme ceci est du code temporaire, je n’applique pas l’indentation habituelle du code, je reviens sur la marge gauche. Ceci me permet, quand je regarde le code dans sa version finale, de savoir ce qui relève du code fonctionnel — ça suit l’indentation habituelle — ou du code temporaire, typiquement du débogguage — l’indentation revient sur la marge gauche. Et je peux l’éliminer sans souci du code final.

Allant plus loin avec des drapeaux…

J’ai commencé la programmation il y a très longtemps, où les ordinateurs avaient beaucoup moins de mémoire — mon premier avait 1K — 1024 octets! Mon préféré, un Apple //c, avait 128K soit 128 x 1024 octets. Autant dire rien. Non seulement je codais en Assembleur — une réprésentation symbolique des instructions du microprocesseur — mais je devais apprendre des astuces pour gagner de la place en mémoire. En, comme en C, nous devons gérer et, plus important, libérer l’espace mémoire manuellement.

Une des techniques est d’utiliser des drapeaux — aujourd’hui on dirait un boolean — un simple variable qui peut avoir deux états, et dans le fil du programme, comme pour la gestion du debug ci-haut, on sélectionne tel ou tel chemin dans le code. Mais chaque drapeau devait normalement prendre un octet en mémoire. Ce qui est très gaspilleur quand on pense qu’un octet peut encoder 8 bits, et que, fondamentalement, un boolean n’est qu’un bit. Ainsi, la logique nous disait que sur un octet on pouvait encoder 8 bits, donc 8 drapeaux.

Si on regarde un octet en mémoire, on peut le répresenter comme un tiroir à 8 cases. Chaque case peut contenir soit zéro, soit un. SI c’est un, le drapeau est mis.

Mais comment les mettre en place, et comment les lire par la suite ?

La réponse se passe par ce qu’on appèle des opérateurs bitwise, c’est-à-dire qu’au lieu de regarder la logique boolean [vrai ou faux], ces opérateurs regardent l’état des bits…

Exemple :

Résultat : "pas de correspondance"

Mais si nous changeons la comparaison…

Résultat : "correspondance"

La valeur 1 se lit en bits comme 00000001

La valeur 2 se lit en bits comme 00000010

La valeur 3 se lit en bits comme 00000011

Ainsi on peut voir que dans la réprésentation binaire de 1 et 2 il n’y a pas de bit à ’1’ qui soit placé en même endroit. D’où le résultat « pas de corresdonce ». Mais pour la réprésentation binaire de 1 et de 3 l’emplacement le plus à droite est égale à 1 pour les deux. On peut donc affirmer que
un & trois égale un
dans la logique des bits.

Et ce que nous venons de voir ici l’emploi d’un drapeau…

Et comment ça nous aide ?

Supposons que nous travaillons sur un sketch avec trois composants principaux — audio, une librairie externe et le rendu du kinect sur l’écran — et que, par moments, nous devons activer ou désactiver le code de débogguage correspondant à chaque.

ensuite, il suffit de décider à chaque fois ce que avons besoin de débogguer

ou

ou

et, si on veut afficher le code de débogguage de plus d’une partie à la fois, on peut cumuler les drapeau au moment de l’initialisation de notre constant en utilisant l’opérateur OR.

dans ce cas, les codes de débogguage pour debug_ecran et debug_son seront activés.

Et ensuite ?

Ce qui pourrait être intéressant serait de lire le clavier pendant le déroulement d’un sketch, et selon la touche enfoncée — S pour son, K pour Kinect, et E pour écran — d’activer ou désactiver les parties correspondants du code.

Allez-y, proposer du code pour le faire et poster-le ici..

Code : l’itération des ensembles d’envergure

C’est un problème qu’on rencontre régulièrement — nous avons un grand nombre d’éléments [particules, points, traits…] qui doivent être traités dans une boucle, par exemple, dans la fonction draw() de Processing. Je vais utiliser Processing comme exemple, mais les mêmes principes s’appliquent à PHP, C, JavaScript, ActionScript…

Par défaut, Processing cherche à rafraîchir l’écran de votre ordinateur 60 fois par seconde. S’il y a trop de traitements à effectuer dans votre boucle principale vous allez faire face à soit des ralentissements, soit, carrément, à un plantage de votre sketch.

Explorons des stratégies pour fluidifier le traitement.

Dans Processing notre boucle de traitement ressemblerait à ceci. [MyObjects est simplement un élément d’exemple — tableau, objet… – qui contient les éléments à itérer.]

Tandis que Processing peut facilement itérer à travers un tableau de 10000 éléments, les problèmes commencent quand, par exemple, vous voulez traiter des collisions avec un autre tableau [array] important.

Supposons un vol de 8000 oiseaux et un essaim de 8000 mouches. Les oiseaux devant attraper et manger les mouches. Dans ce cas, la boucle doit traiter 64 millions de collisions possibles (8000 × 8000) à chaque fois. Cette simple multiplication arithmétique est pourquoi, dans ce cas, votre sketch aura des problèmes.

Vient donc l’idée de ne pas traiter chaque cas lors de chaque itération, de procéder par lots. Dans la meilleure des cas, les humains réagissent en environ 1/30e de seconde à ce qui se produit autour d’eux. En traitant nos éléments par lot, et en rafraichissant l’écran 60 fois par seconde, mais, par exemple, ne traitant que 10  % de notre ensemble lors de chaque boucle, nous pouvons continuer de donner l’illusion d’un mouvement continu. Bien sûr, la taille des lots et le temps de traitement sera dépendant de chaque cas spécifique, mais les exemples ici sont destinés à vous mettre sur des pistes de travail intéressantes.

Alors, comment créer des lots ?

La première stratégie consiste à traiter les éléments aléatoirement.

Dans ce cas, nous ne traitons que la moitié des possibilités pour chaque itération. D’autres valeurs peuvent changer la taille du lot…

La loi des grands nombres impliquent que, considéré sur une période longue, chaque élément sera tout de même traité de manière égale. Toutefois, sur des périodes plus courtes, les éléments de notre tableau seront traités selon une courbe en cloche, qui se lissera plus le temps passe. Ceci implique, pendant les périodes courtes, qu’environ 10 % des éléments sera moins traités que les autres. Toutefois ceci peut être un effet intéressant, par exemple, si vous cherchez à simuler les effets d’essaimage ou de murmuration — oiseaux, insectes, poissons… — où des ‘retards’ au sein du groupe, des retardataires qui suivent le groupe de manière plus paresseusement, peut de fait augmenter la vraisemblance de la simulation.

Une manière plus traditionnelle sera de construire des lots, puis de les traiter en séquence.
Isolons, un échantillon d’un huitième de l’ensemble…

Mais dans ce cas, les sept autres lots sont ignorés. Comment les traiter en séquence ?

Et voilà. Il y a d’autres techniques que nous allons explorer dans l’avenir. Mais ces informations devraient vous aider à démarrer.

Encore plus de possibilités dans le browser

Les développements récents de HTML5 rend le browser de plus en plus puissant comme outil de prototypage [voir de développement] de réalisations qui auparavent devaient se faire en Flash ou par le biais d’un sketch Prototype.

Voici donc un lien vers une expérimentation Move a Cube With Your Head or Head-Tracking With WebGL — Bouger un cube avec votre tête, ou le suivi de visage avec WebGL — qui fait une démonstration, à la fois des librairies récentes de JS [ici, three.js] et les ouvertures du browser vers les dispositifs d’entrée de son ordinateur.