« RodenburgThomas » : différence entre les versions
Ligne 148 : | Ligne 148 : | ||
On peut lui passer un fichier CSV contenant les données brutes du capteur et grâce au fichier knowledge.dat, l'émulateur est capable de faire la différence entre les situations<syntaxhighlight lang="bat"> | On peut lui passer un fichier CSV contenant les données brutes du capteur et grâce au fichier knowledge.dat, l'émulateur est capable de faire la différence entre les situations<syntaxhighlight lang="bat"> | ||
PS C:\Users\gabyt\Documents\Gaby\emulators> .\NanoEdgeAI_Class_Emulator.exe neai_classification --knowledge_path .\knowledge.dat --file | PS C:\Users\gabyt\Documents\Gaby\emulators> .\NanoEdgeAI_Class_Emulator.exe neai_classification --knowledge_path .\knowledge.dat --file .\data.csv | ||
{ | { | ||
"status": "classification", | "status": "classification", | ||
"lib_id": " | "lib_id": "6582b12625c3e0368b2c2a09", | ||
"input": " | "input": ".\data.csv", | ||
"results": [ | "results": [ | ||
{"signal": 1, "line": 1, "class_status": 1, "class_name": " | {"signal": 1, "line": 1, "class_status": 2, "class_name": "dann", "class_proba": [0.01, 0.99]}, | ||
{"signal": 2, "line": 2, "class_status": 1, "class_name": " | {"signal": 2, "line": 2, "class_status": 2, "class_name": "dann", "class_proba": [0.01, 0.99]}, | ||
{"signal": 3, "line": 3, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]}, | |||
{"signal": 4, "line": 4, "class_status": 1, "class_name": "gaby", "class_proba": [0.83, 0.17]}, | |||
{"signal": 5, "line": 5, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 6, "line": 6, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 7, "line": 7, "class_status": 1, "class_name": "gaby", "class_proba": [0.50, 0.50]}, | |||
{"signal": 8, "line": 8, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 9, "line": 9, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]}, | |||
{"signal": 10, "line": 10, "class_status": 2, "class_name": "dann", "class_proba": [0.17, 0.83]}, | |||
{"signal": 11, "line": 11, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 12, "line": 12, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 13, "line": 13, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]}, | |||
{"signal": 14, "line": 14, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]}, | |||
{"signal": 15, "line": 15, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 16, "line": 16, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]}, | |||
{"signal": 17, "line": 17, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 18, "line": 18, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 19, "line": 19, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]}, | |||
{"signal": 20, "line": 20, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 21, "line": 21, "class_status": 2, "class_name": "dann", "class_proba": [0.11, 0.89]}, | |||
{"signal": 22, "line": 22, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]}, | |||
{"signal": 23, "line": 23, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 24, "line": 24, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]}, | |||
{"signal": 25, "line": 25, "class_status": 1, "class_name": "gaby", "class_proba": [0.50, 0.50]}, | |||
{"signal": 26, "line": 26, "class_status": 2, "class_name": "dann", "class_proba": [0.06, 0.94]}, | |||
{"signal": 27, "line": 27, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]}, | |||
{"signal": 28, "line": 28, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}, | |||
{"signal": 29, "line": 29, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]} | |||
], | |||
"classification_summary": {"signals": 29, "classified": [19, 10], "unclassified": 0} | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Version du 20 décembre 2023 à 11:06
Le binôme
Le binôme est constitué de 2 élèves de SE5-SC :
- Dann RODENBURG
- Gabriel THOMAS
Objectifs
Le but de ce TP est de créer un réseau de systèmes communicants en partant d'un capteur XNucléo 53L5A1 pour finir sur une machine virtuelle Xen. La particularité est d'intégrer une composante de Machine Learning
Compte rendu des séances
Séance du 04/12/2023
Création de la machine virtuelle
Création d'une machine virtuelle gabidann sur le serveur chassiron :
xen-create-image --hostname=gabidann --force --dist=bookworm --size=10G --memory=10G --dir=/usr/local/xen --password=glopglop --dhcp --bridge=bridgeStudents
La machine virtuelle est à présent connectée au WiFi.
Après cela, nous avons configuré la machine virtuelle selon l'énoncé du TP en faisant un xen console gabidann. Nous avons ensuite participé à la mise en place du point d'accès WiFi.
Premières observations du capteur
De plus nous avons observé le retour du capteur de distance Nucleo-53L5A1 avec l'outil minicom. Le contenu envoyé par le capteur était compréhensible avec une fréquence de 460 800 bauds ; sur minicom, on a pu constater que le capteur nous envoie des valeurs qui dépendent de la distance entre celui-ci et un obstacle.
Raspberry
D'un autre côté, nous avons branché la Raspberry Pi à l'ordinateur selon le pinout fourni dans la documentation.
Enfin, nous avons activé la communication UART de la Raspberry Pi afin de pouvoir communiquer avec. En fin de séance, nous étions en train de vérifier que la Raspberry Pi répondait bien, même en ayant ajouté la ligne enable_uart=1 dans le fichier config.txt de la Raspberry.
Séance du 18/12/2023
Configuration de la Raspberry
Nous avons résolu le problème de la Raspberry qui ne répondait pas. Cela était dû à l'alimentation : brancher la carte en USBC résoud le problème. Cependant, nous recevons une erreur l'erreur EXT4-fs error (device mmcblk0p2).
Le problème venait des arguments saisis lors du lancement de Minicom. Avec la commande suivante, il est à présent possible de se connecter sur la Raspberry : minicom -D /dev/ttyUSB0 -b 115200
Dans la Raspberry, nous avons configuré une interface réseau wlan0 pour se connecter à WiFi_IE_1 :
auto wlan0 iface wlan0 inet dhcp wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
A présent à partir de la Raspberry, on peut ping la machine virtuelle sur chassiron avec son IPv6.
Configuration du capteur de distance
Un programme était déjà présent sur le capteur. On a téléchargé le logiciel STM32CubeIDE pour pouvoir éditer du code et le téléverser sur le capteur. Nous avons testé de téléverser un programme d'exemple dont voici le résultat :
Nous avons modifié ce programme afin d'effectuer un formatage des données transmises par le capteur sous le format <distance>, pour chaque valeur. Grâce à ce formatage, il est à présent possible d'utiliser les données reçues par le logiciel NanoEdgeStudio AI pour la partie Machine Learning.
Pour recevoir les valeurs de manière exploitable, il faut modifier le code Exemple dans le logiciel STM Cube IDE
L'objectif est d'obtenir une liste séparée par des virgules, il a donc fallu supprimer les espaces et les barres verticales de la fonction d'affichage ainsi que les statuts de chacun des capteurs :
static void print_result(RANGING_SENSOR_Result_t *Result)
{
int8_t j;
int8_t k;
int8_t l;
uint8_t zones_per_line;
zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||
(Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;
for (j = 0; j < Result->NumberOfZones; j += zones_per_line)
{
for (l = 0; l < RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)
{
/* Print distance and status */
for (k = (zones_per_line - 1); k >= 0; k--)
{
if (Result->ZoneResult[j+k].NumberOfTargets > 0)
printf("%ld,",(long)Result->ZoneResult[j+k].Distance[l]);
}
}
}
printf("\n");
}
On passe ensuite sur Nano Edge Studio pour définir les signaux dans l'onglet "Signals" et entraîner le modèle dans l'onglet "Benchmark".
Une fois le modèle entraîné, on peut le tester avec l'onglet "Emulator"
Emulation avec NanoEdgeStudio AI
Dans un premier temps, nous avons essayé d'entraîner le programme à reconnaître les chiffres 1, 2, 3, 4 et 5 sur les doigts d'une main. Les résultats n'étaient pas concluant, il semblerait que le capteur détecte avant tout le volume de la main à la place de détecter le nombre de doigts.
Nous avons ensuite choisi de faire un détecteur de visages capable de faire la différence entre Gabriel et Dann. L'émulation donne des résultats très satisfaisant proche de 100% de réussite
Configuration du serveur
Configuration d'un serveur HTTP sur la machine virtuelle gabidann :
import socket
from http.server import HTTPServer, SimpleHTTPRequestHandler
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/ip':
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(f'Your IP address is {self.client_address[0]}'.encode())
return
else:
return SimpleHTTPRequestHandler.do_GET(self)
class HTTPServerV6(HTTPServer):
address_family = socket.AF_INET6
def main():
server = HTTPServerV6(('::', 8080), MyHandler)
server.serve_forever()
if __name__ == '__main__':
main()
Pour se connecter au serveur depuis un navigateur, on peut ouvrir un navigateur depuis la zabeth et y accéder avec l'adresse : [<ipv6_VM>]:<port>. Dans notre cas, le serveur écoute le port 8080.
La page index.html s'affiche par défaut lorsque l'on se connecte au serveur HTTP :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Gabidann</title>
</head>
<body>
<h1>Bienvenue sur Gabidann !<h1>
<div id="data"></div>
</body>
</html>
Nous avons également testé la communication en TCP avec l'utilitaire socat
Nous avons créé un serveur python en TCP. Nous pouvons maintenant envoyer des messages du client ( raspberry ) au serveur (VM Xen). Nous nous servirons de cette architecture pour envoyer les données du Nucleo à la Vm Xen
Une fois le modèle entrainé et les tests concluants, on peut déployer notre modèle sur n'importe quel appareils linux ou windows. Pour cela, on va dans l'onglet deployment et on télécharge notre librairie personnalisée.
Déploiement du modèle
On peut lui passer un fichier CSV contenant les données brutes du capteur et grâce au fichier knowledge.dat, l'émulateur est capable de faire la différence entre les situations
PS C:\Users\gabyt\Documents\Gaby\emulators> .\NanoEdgeAI_Class_Emulator.exe neai_classification --knowledge_path .\knowledge.dat --file .\data.csv
{
"status": "classification",
"lib_id": "6582b12625c3e0368b2c2a09",
"input": ".\data.csv",
"results": [
{"signal": 1, "line": 1, "class_status": 2, "class_name": "dann", "class_proba": [0.01, 0.99]},
{"signal": 2, "line": 2, "class_status": 2, "class_name": "dann", "class_proba": [0.01, 0.99]},
{"signal": 3, "line": 3, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]},
{"signal": 4, "line": 4, "class_status": 1, "class_name": "gaby", "class_proba": [0.83, 0.17]},
{"signal": 5, "line": 5, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 6, "line": 6, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 7, "line": 7, "class_status": 1, "class_name": "gaby", "class_proba": [0.50, 0.50]},
{"signal": 8, "line": 8, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 9, "line": 9, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]},
{"signal": 10, "line": 10, "class_status": 2, "class_name": "dann", "class_proba": [0.17, 0.83]},
{"signal": 11, "line": 11, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 12, "line": 12, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 13, "line": 13, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]},
{"signal": 14, "line": 14, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]},
{"signal": 15, "line": 15, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 16, "line": 16, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]},
{"signal": 17, "line": 17, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 18, "line": 18, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 19, "line": 19, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]},
{"signal": 20, "line": 20, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 21, "line": 21, "class_status": 2, "class_name": "dann", "class_proba": [0.11, 0.89]},
{"signal": 22, "line": 22, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]},
{"signal": 23, "line": 23, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 24, "line": 24, "class_status": 1, "class_name": "gaby", "class_proba": [0.74, 0.26]},
{"signal": 25, "line": 25, "class_status": 1, "class_name": "gaby", "class_proba": [0.50, 0.50]},
{"signal": 26, "line": 26, "class_status": 2, "class_name": "dann", "class_proba": [0.06, 0.94]},
{"signal": 27, "line": 27, "class_status": 2, "class_name": "dann", "class_proba": [0.37, 0.63]},
{"signal": 28, "line": 28, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]},
{"signal": 29, "line": 29, "class_status": 1, "class_name": "gaby", "class_proba": [0.63, 0.37]}
],
"classification_summary": {"signals": 29, "classified": [19, 10], "unclassified": 0}
}