IMA5 2019/2020 P18
Sommaire
Présentation générale
Sujet : Virtual Reality Old Gaming
Etudiant : Ibrahim Ben Dhiab et Fabien Di Natale
Encadrant : Laurent Grisoni
Description
L'équipe de recherche MINT, dans le cadre d'un projet européen, travaille sur un système permettant de jouer, via un système de réalité virtuelle, à de vieux jeux, utilisés sous la forme d'émulateurs logiciels. Ce dispositif est développé par l'équipe dans le cadre d'un projet européen portant sur l'utilisation de la RV pour la rééducation. Le dispositif existant utilise un PC portable combiné à un casque de RV (Oculus Quest).
Nous souhaitons:
- faire l'adaptation nécessaire à l'allègement de la forme physique du dispositif, ou nous souhaitons passer à une version n'utilisant plus le portable, mais une émulation sur carte Rapsberry. Le travail de proposition d'architecture a déjà été fait pour ce point.
- faire en sorte d'étendre le système pour avoir une appli de configuration permettant de choisir la console et le jeu. Une partie de ces éléments de configuration pourront être utilisables dans le casque de RV par le malade, l'autre partie par le médecin, via une application tierce.
- éventuellement et en fonction de l'avancement du projet, mettre en place quelques scénarios d'interaction spécifiques, déjà déterminés, dans le dispositif interactif utile à l'avancée du projet européen.
Objectifs
Mettre en place quelques fonctionnalités dans un émulateur RV d'ancienne console
Préparation du projet
Cahier des charges
Le projet est fait suite à un besoin des hôpitaux et cliniques de rendre la rééducation moins compliquée et plus attrayante. Nous utilisons donc de vieux jeux vidéo en réalité virtuel afin d'amener les personnes à bouger comme si elle faisait des exercices tout en s'amusant rendant ainsi le processus de rééducation moins pénible et plus facile à suivre. De plus, toutes les personnes ayant besoin de rééducation ou ayant besoin de faire de l'exercice dans les hôpitaux ont des maladies ou ont eu des accidents très variés. Notre dispositif doit alors être polyvalent et facilement configurable par les médecins ou les infirmières qui serait amené à faire les rééducations.
Ainsi, nous allons nous concentrer sur la partie polyvalence et configuration du système. Nous avons pour objectif de rendre le système le plus polyvalent afin qu'il puisse convenir au plus de personnes possible. Le plus facilement et le plus rapidement utilisable par l'équipe médical.
Choix techniques : matériel et logiciel
Ce projet est fait à l'aide de unity avec les scripts en C# couplé à un serveur node.js sur une Raspberry pi donnant l'accès à une page web pour le personnel médical permettant la configuration et renvoyant la configuration à l'oculus. Nous utilisons un Oculus car c'est un casque de réalité virtuel de bonne qualité, dans des prix raisonnables mais surtout ne nécessitant pas d'ordinateur derrière pour faire tourner les jeux.
Liste des tâches à effectuer
Nous devons :
- Améliorer la page web afin de proposer les personnalisations de paramètre suivant:
- Choisir le nombre de manettes (type NES) utilisables par le patient
- Possibilité d'avoir juste les boutons que le personnel soignant pourra déplacer
- Ajout de script C# en concordance avec le serveur web
- Décoder correctement les configurations envoyant par la page web (la raspberry pi)
- Créer un groupe d'objet que de boutons sans la manette
- Créer une fonction pour déplacer tous les boutons séparément de la manette de base
- Vérifier si un scénario ayant pour objectif faire marcher le patient en déplaçant l'affichage du jeu et en fixant la manette NES sur les déplacements du casque est possible
Calendrier prévisionnel
Réalisation du Projet
Semaine 1
Pour ce projet, nous sommes intégrés à l'équipe mint s'occupant du contrat complet. Dans ce cadre nous pouvons alors découvrir complètement le sujet et voir les différentes personnes qui sont affectés à ce contrat.
Nous avons ensuite installé tous les logiciels nécessaires au lancement du projet sur l'Oculus:
- Télécharger le projet à partir du git
- Suivre les instructions des read.me (téléchargement de Unity, de certain assets et paramétrage d'Unity; téléchargement de node.js et paramétrage de la raspberry pi)
Ce sujet et divisé en deux parties:
- Une première partie web
- Une seconde partie Unity
Pour cette fin de première semaine nous avons pu découvrir la partie web qui est un serveur web écrit en node js. Le serveur web tourne sur la raspberry et a pour but de faire la liaison entre le praticien et le patient. Pour cela la raspberry héberge un serveur web sur lequel nous pouvons choisir la configuration du casque. Pour l'instant nous pouvons choisir entre:
- Contrôler le jeu à l'aide de la manette directement sur le serveur web
- Contrôler le jeu avec les pads matérialisé devant le joueur. Le nombre de pad peut varier de 1 à 3.
Semaine 2
Prise en main du projet avec un apprentissage des langages javascript, node.js et C# que nous avons peu utiliser pour le javascript et jamais utiliser pour les deux autres. Pour cette deuxième semaine dans l'équipe mint nous avons pu découvrir la seconde partie du projet sous unity. Celle-ci se compose principalement de deux chose, les scènes et les scripts permettant aux scènes d'évoluer.
La scène Unity
Pour les scènes nous en avons une seule composée des objets suivants :
- L'objet statique créant la pièce de jeu, c'est l'environnement que nous pouvons retrouver autour de nous lorsque nous avons le casque de réalité virtuelle devant les yeux. Cet objet est statique et n'est pas relié à des scripts ou autre d'où son nom.
- L'objet quad qui est un affichage reliè à 4 scripts, cet objet est l'endroit où l'image que la raspberry produit va apparaître, en d'autre mot, ça sera là où l'on peut voir le jeu comme une télévision. Les 4 scripts permettent la connexion et les échanges avec la raspberry, nous avons les scripts TCP config, TCP Commande, TCP screen et Vibration manager. TCP config permet de récupérer la configuration envoyée par la raspberry et lancer toutes les fonctions nécessaires afin de reconfigurer l'oculus selon la configuration reçue.
- L'objet Event System permet la liaisons entre la scène et les interactions extérieurs comme des entrées clavier, souris ou des entrées spéciales. Cet objet est fait pour faciliter la gestion des différents objets de la scènes et la communication entre ces objets. L'Event System gère quel objet est sélectionné, quel gamme d'entrées sont considéré et les différentes mise à jour de la scène.
- L'objet Canvas permet l'affichage des erreurs, cet objet a était ajouté afin de pouvoir afficher du texte en jeu. Il est positionné devant le joueur mais ne peut être activé seulement à partir de Unity, quand cet objet est activé cela signifie que l'on est en DEBUG mode. Nous pouvons ainsi voir tous les messages que le programme essaye de nous envoyer et ainsi détecter les erreurs plus facilement.
- L'objet OVRPlayerControler est l'objet le plus complexe, nous ne rentrerons pas dans les détails mais cet objet va gérer toute la partie casque, manette lié au casque Oculus et suivi des mains du joueur. Il possède une partie de suivi de position du casque permettant de positionner le joueur dans l'espace de la scène, pour cela il a des sous objets fixe qui lui servent de repère dans l'espace. Il possède ensuite d'autres sous objets fixe afin de pouvoir suivre le mouvement des manettes ou des mains à l'aide des caméras qu'il possède.
- L'objet GameControl regroupe les manettes NES de base que l'on utilise dans la configuration par défaut. Il y a trois sous objets, soit trois manettes. Ces trois manettes on une seule différence leur positionnement, elles sont positionné de tel sorte que lorsque les trois manettes sont activés on puisse avoir accès à tous les boutons sans conflit entre eux. L'objet utilise un script Game Controle Button permettant la modification du nombre de manette affiché et donnant la possibilité de changer les boutons actif à intervalle de temps régulié.
- L'objet PadLibre est l'objet créé pour notre scénario, c'est une manette NES comme les sous objets du GameControl mais sans le design autour donnant une impression de bouton volant et nous permettant donc de déplacer n'importe où les boutons dans l'espace.
Les scripts utilisé
- ActiveControllerCollider permet l'activation des collisions des mains avec les autres objets de la scène ayant leur collision activé (Partie du projet où l'on ne veux plus utiliser les manette de l'Oculus mais plus que les mains)
- ChangeScale permet d'agrandir ou réduire l'objet sur un input particulier
- ClickOnButtonMenu est un script pas utilisé mais fait dans le but de pouvoir viser avec la manette de l'Oculus et sélectionner certain boutons, ici les boutons du menu
- CollisionScript fait toute les commandes nécessaire lors de la rencontres entre la manette et les boutons, ce script rend le bouton un petit peu plus foncé et fait vibrer la manette lors de la collisions afin de pouvoir voir que l'on touche le bouton. De plus il change des variables afin que le programme sache quel boutons est appuyé et puisse l'envoyer à la raspberry.
- ControllerXbox permet de détecter les entrées du contrôleur xbox afficher sur le site web, les transformes en commande et les envoie à la raspberry.
- Cube est un script s'occupant de la partie du projet sans les manettes, il permet de créer la représentation des mains du joueur
- GameControleButton a pour but de gérer l'objet GameControl et les trois manettes qui vont avec, il permet d'activer de zéro à trois manettes tout en les positionnant du mieux possible afin qu'elles soit le plus centré possible. De plus lorsque plusieurs manettes sont activé le script possède un système de changement de bouton actif afin que les boutons actif change en permanence, par défaut c'est toute les 30 secondes.
- Handcollider est un script s'occupant de la partie du projet sans les manettes, il permet de créer les collisions entre les mains du joueur et les différents objets de la scènes.
- HandInteraction est un script s'occupant de la partie du projet sans les manettes, il permet de transformer certain mouvement de doigt ou position de main en commande comme ouvrir le menu ou autre
- Lz4DecoderStream permet de coder et décoder les messages que nous envoyons et recevons de la raspberry.
- OculusController permet de détecter les entrées du contrôleur de l'Oculus, les transformes en commande et les envoie à la raspberry.
- QuitGame permet de fermer l'application proprement.
- rotationScreen est un script créé dans le but de faire tourner l'écran par la suite mais pas utilisé pour le moment.
- TCPClient est un script fonctionnant en collaboration avec le script TCPScreen afin de mettre à jour l'affichage du jeu produit par la raspberry.
- TCPCommande permettant de faire la liaisons entre les collisions entre les manettes et les boutons et les commandes envoyé à la raspberry pour manipuler le jeu.
- TCPConfig permet la configuration de notre scènes (de l'environnement de jeu), celui ci lit les messages en attendant une configuration dans un thread, une fois que cette configuration est arrivé il décortique l'information et lance les fonctions nécessaire et change les variables nécessaires afin d'appliquer la nouvelle configuration reçu.
- TCPScreen permet de recevoir les messages en provenance de la rapsberry, les décode à l'aide du script Lz4DecoderStream et les affiches ensuite. La réception des messages est fait dans un thread comme toute les réceptions de message.
- VibrationManager permet de faire vibrer les manettes lorsque la fonction est appelé.
Brainstorming
Première réunion avec tous les membres du projet afin de trouver les meilleurs scénarios et les meilleurs paramètre à mettre en place pendant notre PFE.
Au cours de cette réunion nous avons pu récolter des idées de scénario de toute l'équipe pouvant convenir à notre projet. Nous avons pu en ressortir deux idées de scénario qui apporterait un plus à notre scénario. La première est un scénario dans lequel nous pouvons déplacer à souhait les différents boutons que compose la manette NES afin de pouvoir changer la difficulté de l'exercice pendant celui ci et pouvoir adapter l'exercice aux plus de patients possible. La seconde idée a pour but de faire marcher le patient, pour ceci nous avons penser à faire bouger l'écran afin que le patient soit obligé de se déplacer pour pouvoir continuer à voir l'écran correctement et donc jouer. Ce scénario pose plusieurs problème, si nous faisons bouger l'écran et que le patient bouge, nous devons faire bouger la manette NES matérialisé dans le casque. Cependant, faire bouger la manette NES sans aucune concordance avec les déplacements du patient rendrait l'utilisation de la manette très difficile. Nous avons donc décidé d'accrocher la manette NES à la caméra et ainsi toujours l'avoir devant les yeux. Le second problèmes viens du déplacement, si le patient se déplace avec le casque sur les yeux il ne pourra pas voir les obstacles qui l'entoure. Pour cela la seul solution est un bon paramétrage du guardian (zone de jeu, en dehors de cette zone de jeu l'image s'arrête et le casque arrête d'afficher le jeu pour afficher ce qui entoure le patient grâce au caméra de l'Oculus) ou une surveillance des médecins. Pour ce second problème nous pouvons limiter les risques d'accident en définissant les déplacements de l'écran et toujours le faire revenir à sa position initial et donc faire des aller-retour. A la fin de cette réunion nous avons pu parler de ce qui était faisable dans notre temps impartie et avec l'équipe nous en avons déduit que le second scénario était trop dur et trop long à réaliser en intégralité avec le peu de temps que nous disposons au vu de notre moindre connaissance des différents langage de programmation de Unity et du projet en général. Cependant il serait bien que l'on en étudie la faisabilité pour les personnes qui continuerons de travailler sur le projet. Nous avons ainsi était assigner au premier scénario qui est le plus intéressant en terme de résultat et apparemment le moins difficile à faire.
Le premier scénario
Suite au brainstorming, notre tuteur nous a lancé sur notre premier scénario qui a pour avantage de pouvoir convenir au plus de patient possible et surtout à la majorité des pathologie nécessitant une rééducation du haut du corp. Ce scénario est en réalité une configuration particulière et très polyvalente, le but est de délier les boutons de la manette NES de leur support afin de pouvoir les placer tout autour du joueur. Ainsi le but est de pouvoir changer le placement de tous les boutons quand on le souhaite et pouvoir les placer la où on le souhaite à l'aide de la page web.
La partie web
Du côté du serveur web nous devons créer deux affichages gérant les boutons afin que l'utilisateur puisse bouger les boutons en 3D et ainsi augmenter ou diminuer la dificulté de l'exercice en temps réel. Ceci pose plusieurs problèmes :
Partie Unity
Du côté du casque de réalité virtuel nous devons créer un nouvel objet manette NES couplé à un nouveau script afin de placer les boutons en fonction de la configuration que nous recevons. Pour commencer nous avons du nous entendre sur la formation du message json permettant de transférer la configuration entre la raspberry et le casque. Nous avons choisi de créer un sous fichier json pour chaque bouton composé de ses trois coordonnées. Notre choix de créer un nouvel objet indépendant de tous les autres objets de la scène à pour but de garder le projet le plus propre possible. Comme nous sommes en coopération avec l'équipe mint nous avons préféré modifier le moins possible les fichiers de base afin de pouvoir mieux identifier ce que l'on a fait et permettre à l'équipe de pouvoir utiliser les fonctionnalité que nous allons rajouté le plus pertinemment possible. Dans ce projet nous sommes nouveau et ne connaissons pas toute les subtilités de celui ci, il est donc plus prudent de faire tout à part et ajouter notre travail au projet une fois que tout fonctionne et aura était validé par notre tuteur.
Une fois cela définit nous avons du apprendre comment manipuler un fichier json en C#, récupérer les informations que l'on souhaitez. Cela nous a pris quelque temps car avec le programme déjà en place nous avons pu voir comment récupérer les éléments basique d'un fichier json et les traiter. Cependant le fait que nous aillons choisi d'avoir mis des objets json pour chaque boutons cela impliqué une nouvelle méthode de lecture car celle utilisé dans ce projet ne fonctionné pas. Nous avons remarqué que lors de l'appel à la fonction affichage, l'affichage se fait correctement mais lorsque nous essayons de manipuler les objets le compilateur nous produit des erreurs. Nous avons donc choisi de reproduire une parti de la fonction d'affichage, la parti cast nous permettant alors de manipuler les sous objets comme des strings pour pouvoir enfin récupérer les données qui nous on était envoyé. Nous envoyons ensuite la configuration des boutons dans le casque.
Afin que tous cela fonctionne nous avons du modifier le fichier de configuration qui est l'une des pièces maîtresse du projet. Nous avons fait en sorte que cette fonction ne soit pas la prioritaire et que la fonction prioritaire soit la manette NES totalement prédéfinie.
La modification du fichier de configuration n'as était faite qu'une fois le test fini c'est à dire que pour tester notre script nous l'avons rendu complétement indépendant avec une mise à jour lors d'une entré clavier sur un fichier qui était directement stocké sur l'ordinateur. Le fait de travailler sous Unity avec un matériel de ce type et une dépendance à la raspberry nous a obligé à nous adapter et découvrir de nouvelle fonctionnalité du logiciel Unity. Ainsi après avoir tester tout cela au fur et à mesure grâce à Unity nous avons pu testé cela avec la configuration venant directement de la raspberry. (Ne pas oublié d'enlevé tous ce qui a permis de faire les test sur le simulateur de Unity et ajouter les liaisons avec le fichier de configuration.)
semaine 3
Le premier scénario (suite)
La phase de test et debug
Pour cette troisième semaine, nous reprenons notre travaille en cours, maintenant que les partie programmation web et programmation Unity pour les boutons sont fini nous pouvons tester le tout. Lors de ce test nous avons découvert un nouveau type de bug qui entraînait la fin de l'update du côté de l'oculus. Dans un projet Unity tous les scripts qui sont lié à un objet Unity possède une fonction Start qui se lance lors du lancement du projet et une fonction Update permettant la mise à jour des images, elle est donc appelé à chaque images formé par l'Oculus. Nous faisons tourner l'Oculus sur une base de 60 images par seconde se qui produit un appelle de la fonction Update 120 fois par seconde car l'oculus fonctionne avec deux écrans, un par oeil.
Ainsi lorsque le programme s'arrête pendant l'update, le jeu continuera de fonctionner et ignoreras seulement la fin de la fonction Update et la rappellera au prochain rafraîchissement. De plus lorsque nous transférons le projet Unity sur le casque de réalité virtuel celui ci devient indépendant donc nous n'avons aucune façon conventionnelle de trouver les erreurs. Nous avons alors du créer un objet dans la scène unity affichant des messages, pour aller avec cela nous avons du créer des logs afin de trouver pourquoi l'Update ne se faisait pas.
Nous avons enfin découvert notre problème, notre lecture de message et donc de fichier json était fait sans aucune protection. C'est à dire qu'au moindre problème de lecture de message, de formation de message ou de formation du fichier de configuration json. Pour que notre fonction Update fonctionne ce message devait être parfait et toute les options devait être renseigné sinon la lecture du json formé à partir du message provoqué une exception. Nous avons ainsi ajouté des protections pour toute les lectures d'options implémenté et utilisé. Pour cela nous avons du choisir une configuration par défaut, la configuration choisi est la configuration simple d'une manette formé sans aucune modification. Pour cela nous avons tout d'abord initialiser toute les options afin de répondre à la configuration par défaut. Ensuite pour chaque option nous vérifions que l'option est présente dans le json avant d'essayer de la lire. Une fois lu nous mettons la priorité sur la configuration par défaut en cas de conflit entre les différentes options. Nous faisons la même chose pour la lecture des boutons si l'option padLibre est activé, tous les boutons on une place prédéfinie qu'ils prennent en cas de manque d'information ou de problème de lecture.
Structure finale des scripts
Le second scénario
Ce second scénario comme on a pu le voir précédemment consiste à faire bouger l'écran (l'éloigner et le rapprocher) afin de faire marcher le patient tout en gardant la manette NES matérialisé juste devant le joueur. Dans un premier temps nous devons en étudier la faisabilité et le coder si le temps nous le permet.