middleware/src/Tracking/KinectMain.cs
author bastiena
Tue, 20 Mar 2012 18:00:55 +0100
changeset 7 8a21bec5d45f
parent 6 93dfb08dcc97
child 8 e4e7db2435f8
permissions -rw-r--r--
Middleware : No proximity bugs anymore. The skeleton disappear if a tracked person is too close or not tracked anymore. Processing : There are no laggs anymore when an user stay too long moving his hands and drawing tons of ellipses. (TUIO Cursors are not taken by their vectors, only the last position of the cursors are caught to be drawn).

/*
 * Projet : TraKERS
 * Module : MIDDLEWARE
 * Sous-Module : Tracking
 * Classe : KinectMain
 * 
 * Auteur : alexandre.bastien@iri.centrepompidou.fr
 * 
 * Fonctionnalités : Récupère les trames de données de la Kinect, les squelettes détectés via le SDK 1.0 de Microsoft.
 * Interprète ces trames de façon à afficher le flux vidéo couleurs, et récupérer la distance de l'utilisateur et les
 * noeuds de son squelette. Lance des événements lorsque la main gauche/droite entre dans/quitte le champ.
 * Envoie des données au sous-module de debug de manière a afficher un retour visuel sur la position de l'utilisateur,
 * son squelette, la détection de ses mains.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Drawing;
using System.Windows.Media.Media3D;
using Microsoft.Kinect;

using Coding4Fun.Kinect.Wpf;
using System.ComponentModel;

using Trakers.Debug;
using Tuio;
using Trakers.Communication;
using System.IO;
using Trakers.Tracking.Gestures;
using Trakers.Tracking.Events;
using System.Configuration;
using System.Resources;
using System.Reflection;

namespace Trakers.Tracking
{
    //Il s'agit des fonctions permettant d'appeler les fonctions des événements Main droite/gauche entre/quitte le champ.
    public delegate void LeftHandTrackedHandler(object o, LeftHandTrackedEventArgs e);
    public delegate void RightHandTrackedHandler(object o, RightHandTrackedEventArgs e);
    public delegate void LeftHandQuitHandler(object o, LeftHandQuitEventArgs e);
    public delegate void RightHandQuitHandler(object o, RightHandQuitEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements Swipe left/right/up/down.
    public delegate void SwipeHandler(object o, SwipeEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements Push/Pull.
    public delegate void PushHandler(object o, PushEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements Jump.
    public delegate void JumpHandler(object o, JumpEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements de proximité.
    public delegate void UserPositionHandler(object o, UserPositionEventArgs e);

    public class KinectMain
    {
        //Gestionnaire de ressources.
        private ResourceManager rm;
        //Fenêtre de debug.
        private Debug.DebugWindow debug;
        //Squelettes (Il y en a 6 par défaut).
        private Skeleton[] skeletons;
        //Caméra infrarouge (sensor) de la Kinect.
        private KinectSensor kinectSensor;

        //Détecteur de swipes.
        private SwipeDetector swipeDetector;
        //Détecteur de pushes.
        private PushDetector pushDetector;
        //Détecteur de jumps.
        private JumpDetector jumpDetector;
        //Détecteur de proximité.
        private UserPositionDetector userPositionDetector;

        //Distances min/max délimitant le champ de recherche.
        private float minDistHands;
        private float maxDistHands;
        private float minDist;
        private float maxDist;
        private float zeroPoint;

        //Temps de rafraichissement pour le timer (Détection de gesture dans le serveur TUIO).
        private int timerElapsing;

        //Serveur TUIO pour la connexion du Middleware vers le Front Atelier.
        private Server server;

        //Les événements des mains pour la recherche.
        public static event LeftHandTrackedHandler LeftHandTrackedEvent;
        public static event RightHandTrackedHandler RightHandTrackedEvent;
        public static event LeftHandQuitHandler LeftHandQuitEvent;
        public static event RightHandQuitHandler RightHandQuitEvent;
        //L'événement swipe.
        public static event SwipeHandler SwipeEvent;
        //L'événement push.
        public static event PushHandler PushEvent;
        //L'événement jump.
        public static event JumpHandler JumpEvent;
        //L'événement l'utilisateur se déplace dans la zone de détection.
        public static event UserPositionHandler UserPositionEvent;

        private string connexionHost;
        private int connexionPort;

        /*
        *  Initialisation de la classe principale.
        *  Affiche l'écran de debug dans lequel on voit la distance à la Kinect,
        *  les mains détectées et le squelette de l'utilisateur.
        */
        public KinectMain()
        {
            //On fait appel au gestionnaire de ressources.
            rm = new ResourceManager("Trakers.Properties.resources", Assembly.GetExecutingAssembly());
            
            //On tente de charger les paramètres du fichier params.ini.
            //Si on n'y arrive pas, on affiche une erreur et on charge les paramètres par défaut.
            if (!loadParameters())
            {
                debug.ExceptionLbl.Content = rm.GetString("loadParametersFail");
                //Distances de détection des mains par défaut pour la recherche (ici de 1m à 2m de la Kinect).
                minDistHands = 1.0f;
                maxDistHands = 1.5f;
                minDist = 1.0f;
                maxDist = 4.0f;
                zeroPoint = 1.7f;
                connexionHost = "127.0.0.1";
                connexionPort = 80;
                timerElapsing = 1000;
            }

            //On crée la fenêtre de debug.
            debug = new Debug.DebugWindow(this);

            //On crée les détecteurs de gestes.
            swipeDetector = new SwipeDetector(debug);
            pushDetector = new PushDetector(debug);
            jumpDetector = new JumpDetector(debug);
            //On crée le détecteur de proximité.
            userPositionDetector = new UserPositionDetector(debug, minDist, maxDist, zeroPoint, minDistHands, maxDistHands);

            //On affiche la fenêtre de debug.
            try
            {
                debug.ShowDialog();
            }
            catch(Exception){}
        }

        /*
        *  Initialisation de la classe principale avec comme argument le gestionnaire de ressources.
        */
        public KinectMain(ResourceManager _rm) : this()
        {
            rm = _rm;
        }

        /*
        *  Initialisation du sensor de la Kinect.
        */
        public void KinectInitialization()
        {
            try
            {
                //On sélectionne la première kinect détectée.
                kinectSensor = KinectSensor.KinectSensors.FirstOrDefault(s => s.Status == KinectStatus.Connected);
                //La caméra couleur est activée avec une résolution 640x480 et un framerate de 30 FPS.
                kinectSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
                //La caméra de profondeur est activée.
                kinectSensor.DepthStream.Enable();
                //Le squelette est activé.
                kinectSensor.SkeletonStream.Enable();

                //Quand le Middleware reçoit des trames de la Kinect, on va dans cette fonction.
                kinectSensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(AllFramesReady);

                //On applique des paramètres d'ajustement pour le squelette.
                TransformSmoothParameters parameters = new TransformSmoothParameters();
                parameters.Smoothing = 0.2f;
                parameters.Correction = 0.8f;
                parameters.Prediction = 0.0f;
                parameters.JitterRadius = 0.5f;
                parameters.MaxDeviationRadius = 0.5f;
                kinectSensor.SkeletonStream.Enable(parameters);
                //On démarre la Kinect.
                kinectSensor.Start();
                debug.ExceptionLbl.Content = "";
            }
            catch (System.Exception)
            {
                debug.ExceptionLbl.Content = rm.GetString("KinectNotConnected");
            }

            //Pour les événements main gauche/droite entre dans/quitte le champ, on a 4 listeners.
            //Fonction appelée lorsque la main gauche entre dans le champ de recherche.
            LeftHandTrackedListener leftHandTrackedListener = new LeftHandTrackedListener();
            LeftHandTrackedEvent += new LeftHandTrackedHandler(leftHandTrackedListener.ShowOnScreen);

            //Fonction appelée lorsque la main droite entre dans le champ de recherche.
            RightHandTrackedListener rightHandTrackedListener = new RightHandTrackedListener();
            RightHandTrackedEvent += new RightHandTrackedHandler(rightHandTrackedListener.ShowOnScreen);

            //Fonction appelée lorsque la main gauche quitte le champ de recherche.
            LeftHandQuitListener leftHandQuitListener = new LeftHandQuitListener();
            LeftHandQuitEvent += new LeftHandQuitHandler(leftHandQuitListener.ShowOnScreen);

            //Fonction appelée lorsque la main droite quitte le champ de recherche.
            RightHandQuitListener rightHandQuitListener = new RightHandQuitListener();
            RightHandQuitEvent += new RightHandQuitHandler(rightHandQuitListener.ShowOnScreen);

            //Fonction appelée lorsque l'utilisateur effectue un Swipe right/left/up/down.
            SwipeListener swipeListener = new SwipeListener();
            SwipeEvent += new SwipeHandler(swipeListener.ShowOnScreen);

            //Fonction appelée lorsque l'utilisateur effectue un Push/Pull.
            PushListener pushListener = new PushListener();
            PushEvent += new PushHandler(pushListener.ShowOnScreen);

            //Fonction appelée lorsque l'utilisateur effectue un Jump.
            JumpListener jumpListener = new JumpListener();
            JumpEvent += new JumpHandler(jumpListener.ShowOnScreen);

            //Fonction appelée lorsque l'utilisateur se déplace dans la zone de détection.
            UserPositionListener userPositionListener = new UserPositionListener();
            UserPositionEvent += new UserPositionHandler(userPositionListener.ShowOnScreen);

            //On connecte le serveur à l'adresse locale sur le port 80.
            server = new Server(connexionHost, connexionPort, timerElapsing, debug);
        }

        /*
        *  Fermeture du sensor de la Kinect.
        */
        public void KinectClose()
        {
            try
            {
                //On stoppe la Kinect.
                kinectSensor.Stop();
                //On met a zero l'image d'affichage et le serveur.
                debug.DebugImage.Source = null;
                //server = null;
                debug.ExceptionLbl.Content = "";
            }
            catch (System.Exception)
            {
                debug.ExceptionLbl.Content = rm.GetString("KinectNotConnected");
            }
        }

        /*
        *  Récupère le premier squelette.
        */
        Skeleton GetFirstSkeleton(object sender, AllFramesReadyEventArgs e)
        {
            using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
            {
                if (skeletonFrameData == null)
                    return null;
                if ((skeletons == null) || (skeletons.Length != skeletonFrameData.SkeletonArrayLength))
                    skeletons = new Skeleton[skeletonFrameData.SkeletonArrayLength];
                skeletonFrameData.CopySkeletonDataTo(skeletons);

                //On obtient le premier skelette.
                Skeleton first = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();

                return first;
            }
        }

        /*
        *  Récupère le squelette le plus proche.
        */
        Skeleton GetNearestSkeleton(object sender, AllFramesReadyEventArgs e)
        {
            using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
            {
                if (skeletonFrameData == null)
                    return null;
                if ((skeletons == null) || (skeletons.Length != skeletonFrameData.SkeletonArrayLength))
                    skeletons = new Skeleton[skeletonFrameData.SkeletonArrayLength];
                skeletonFrameData.CopySkeletonDataTo(skeletons);

                Skeleton s;
                float minDist = (float)-1.0;
                int minID = 0;
                    
                //Pour tous les squelettes.
                for(int i = 0 ; i < skeletons.Count() ; i++)
                {
                    s = skeletons.ElementAt(i);
                    //S'il est tracké.
                    if(s.TrackingState == SkeletonTrackingState.Tracked)
                    {
                        //On récupère sa position et on obtient la distance min et l'ID du squelette qui est à la distance min.
                        float dist = skeletons.ElementAt(i).Position.Z;
                        if (minDist == -1)
                        {
                            minDist = dist;
                            minID = i;
                        }
                        else if(minDist > dist)
                        {
                            minDist = dist;
                            minID = i;
                        }
                    }
                }

                //On renvoie le skelette le plus proche.
                return skeletons.ElementAt(minID);
            }
        }

        /*
        *  Récupère le squelette le plus proche.
        */
        private void AllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            //On ne calcule rien si la fenêtre de debug se ferme.
            if (debug.isClosing())
                return;

            //On met à jour la vidéo de debug.
            debug.RefreshVideo(e);
            //On récupère le premier squelette tracké.
            //Skeleton first = GetFirstSkeleton(e);
            //On récupère le plus proche squelette tracké.
            Skeleton first = GetNearestSkeleton(sender, e);
            //Si celui-ci n’est pas nul
            if (first == null)
                return;
            
            //Si ce squelette est tracké (donc suivi et reconnu par la camera)
            if (first.TrackingState == SkeletonTrackingState.Tracked)
            {
                //Ensemble des noeuds du squelette.
                Joint hipCenter = getJoint(first, JointType.HipCenter), spine = getJoint(first, JointType.Spine), shoulderCenter = getJoint(first, JointType.ShoulderCenter), head = getJoint(first, JointType.Head);
                Joint shoulderLeft = getJoint(first, JointType.ShoulderLeft), elbowLeft = getJoint(first, JointType.ElbowLeft), wristLeft = getJoint(first, JointType.WristLeft), handLeft = getJoint(first, JointType.HandLeft);
                Joint shoulderRight = getJoint(first, JointType.ShoulderRight), elbowRight = getJoint(first, JointType.ElbowRight), wristRight = getJoint(first, JointType.WristRight), handRight = getJoint(first, JointType.HandRight);
                Joint hipLeft = getJoint(first, JointType.HipLeft), kneeLeft = getJoint(first, JointType.KneeLeft), ankleLeft = getJoint(first, JointType.AnkleLeft), footLeft = getJoint(first, JointType.FootLeft);
                Joint hipRight = getJoint(first, JointType.HipRight), kneeRight = getJoint(first, JointType.KneeRight), ankleRight = getJoint(first, JointType.AnkleRight), footRight = getJoint(first, JointType.FootRight);

                //On construit l'historique des postures.
                List<Joint> joints = new List<Joint>();
                joints.Clear();
                joints.Insert((int)JointType.HipCenter, hipCenter);
                joints.Insert((int)JointType.Spine, spine);
                joints.Insert((int)JointType.ShoulderCenter, shoulderCenter);
                joints.Insert((int)JointType.Head, head);
                joints.Insert((int)JointType.ShoulderLeft, shoulderLeft);
                joints.Insert((int)JointType.ElbowLeft, elbowLeft);
                joints.Insert((int)JointType.WristLeft, wristLeft);
                joints.Insert((int)JointType.HandLeft, handLeft);
                joints.Insert((int)JointType.ShoulderRight, shoulderRight);
                joints.Insert((int)JointType.ElbowRight, elbowRight);
                joints.Insert((int)JointType.WristRight, wristRight);
                joints.Insert((int)JointType.HandRight, handRight);
                joints.Insert((int)JointType.HipLeft, hipLeft);
                joints.Insert((int)JointType.KneeLeft, kneeLeft);
                joints.Insert((int)JointType.AnkleLeft, ankleLeft);
                joints.Insert((int)JointType.FootLeft, footLeft);
                joints.Insert((int)JointType.HipRight, hipRight);
                joints.Insert((int)JointType.KneeRight, kneeRight);
                joints.Insert((int)JointType.AnkleRight, ankleRight);
                joints.Insert((int)JointType.FootRight, footRight);
                GestureDetector.UpdateSkeletonHistory(joints);

                //Si la main gauche est dans le champ, on lance l'événement approprié.
                if (handLeft.Position.Z < maxDistHands && handLeft.Position.Z > minDistHands)
                {
                    LeftHandTrackedEventArgs leftHandTrackedEvent = new LeftHandTrackedEventArgs(handLeft, handLeft.Position.Z, debug, server);
                    OnLeftHandTrackedEvent(leftHandTrackedEvent);
                }
                //Si la main gauche quitte le champ, on lance l'événement approprié.
                else
                {
                    LeftHandQuitEventArgs leftHandQuitEvent = new LeftHandQuitEventArgs(handLeft, handLeft.Position.Z, debug, server);
                    OnLeftHandQuitEvent(leftHandQuitEvent);
                }
                //Si la main droite est dans le champ, on lance l'événement approprié.
                if (handRight.Position.Z < maxDistHands && handRight.Position.Z > minDistHands)
                {
                    RightHandTrackedEventArgs rightHandTrackedEvent = new RightHandTrackedEventArgs(handRight, handRight.Position.Z, debug, server);
                    OnRightHandTrackedEvent(rightHandTrackedEvent);
                }
                //Si la main droite quitte le champ, on lance l'événement approprié.
                else
                {
                    RightHandQuitEventArgs rightHandQuitEvent = new RightHandQuitEventArgs(handRight, handRight.Position.Z, debug, server);
                    OnRightHandQuitEvent(rightHandQuitEvent);
                }

                //Si l'utilisateur effectue un swipe left.
                if (swipeDetector.CheckForSwipeLeft())
                {
                    SwipeEventArgs swipeEvent = new SwipeEventArgs(debug, server, SwipeDetector.Direction.LEFT);
                    OnSwipeEvent(swipeEvent);
                }

                //Si l'utilisateur effectue un swipe right.
                if (swipeDetector.CheckForSwipeRight())
                {
                    SwipeEventArgs swipeEvent = new SwipeEventArgs(debug, server, SwipeDetector.Direction.RIGHT);
                    OnSwipeEvent(swipeEvent);
                }

                //Enum sur la main qui effectue le geste.
                PushDetector.Hand handPush;
                //Si l'utilisateur effectue un push.
                if ((handPush = pushDetector.CheckForPush()) != PushDetector.Hand.NONE)
                {
                    PushEventArgs pushEvent = new PushEventArgs(debug, server, PushDetector.Direction.PUSH, handPush);
                    OnPushEvent(pushEvent);
                }
                //Si l'utilisateur effectue un pull.
                if ((handPush = pushDetector.CheckForPull()) != PushDetector.Hand.NONE)
                {
                    PushEventArgs pushEvent = new PushEventArgs(debug, server, PushDetector.Direction.PULL, handPush);
                    OnPushEvent(pushEvent);
                }

                //Si l'utilisateur effectue un saut.
                /*if (jumpDetector.CheckForJump())
                {
                    JumpEventArgs jumpEvent = new JumpEventArgs(debug, server);
                    OnJumpEvent(jumpEvent);
                }*/

                //Si l'utilisateur se déplace dans la zone de détection.
                //On traite le problème en plusieurs limites, on discrétise la zone.
                if (first.TrackingState == SkeletonTrackingState.Tracked)
                {
                    float proximity = userPositionDetector.CalcProximity(first.Position.Z);

                    if (proximity > 0f)
                    {
                        UserPositionEventArgs userPositionEvent = new UserPositionEventArgs(debug, server, proximity);
                        OnUserPositionEvent(userPositionEvent);
                    }
                    else
                    {
                        Console.Out.WriteLine("FAIL");
                        debug.hideSkeleton();
                    }
                }

                //Dessine le squelette dans le debug.
                debug.drawJoints(first.Joints, first);
                debug.showSkeleton(hipCenter, spine, shoulderCenter, head, shoulderLeft, elbowLeft, wristLeft, handLeft, shoulderRight, elbowRight, wristRight, handRight, hipLeft, kneeLeft, ankleLeft, footLeft, hipRight, kneeRight, ankleRight, footRight);
            }
            else
                debug.hideSkeleton();
        }

        /*
        *  Change l'échelle des coordonnées d'un noeud pour qu'en X et Y il corresponde à la résolution et en Z à la distance à la Kinect.
        */
        public Joint getJoint(Skeleton ske, JointType jointID)
        {
            return Coding4Fun.Kinect.Wpf.SkeletalExtensions.ScaleTo(ske.Joints[jointID], 600, 400, 0.75f, 0.75f);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand la main gauche entre dans le champ.
        */
        public static void OnLeftHandTrackedEvent(LeftHandTrackedEventArgs e)
        {
            if (LeftHandTrackedEvent != null)
                LeftHandTrackedEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand la main droite entre dans le champ.
        */
        public static void OnRightHandTrackedEvent(RightHandTrackedEventArgs e)
        {
            if (RightHandTrackedEvent != null)
                RightHandTrackedEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand la main gauche quitte le champ.
        */
        public static void OnLeftHandQuitEvent(LeftHandQuitEventArgs e)
        {
            if (LeftHandQuitEvent != null)
                LeftHandQuitEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand la main droite quitte le champ.
        */
        public static void OnRightHandQuitEvent(RightHandQuitEventArgs e)
        {
            if (RightHandQuitEvent != null)
                RightHandQuitEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur effectue un swipe right.
        */
        public static void OnSwipeEvent(SwipeEventArgs e)
        {
            if (SwipeEvent != null)
                SwipeEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur effectue un push.
        */
        public static void OnPushEvent(PushEventArgs e)
        {
            if (PushEvent != null)
                PushEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur effectue un saut.
        */
        public static void OnJumpEvent(JumpEventArgs e)
        {
            if (JumpEvent != null)
                JumpEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur se déplace
         *  dans la zone de détection.
        */
        public static void OnUserPositionEvent(UserPositionEventArgs e)
        {
            if (UserPositionEvent != null)
                UserPositionEvent(new object(), e);
        }

        /*
        *  Méthode de chargement des paramètres (position du champ de recherche...).
        */
        public bool loadParameters()
        {
            try
            {
                minDistHands = (float)double.Parse(ConfigurationManager.AppSettings["searchMinDistance"]);
                maxDistHands = (float)double.Parse(ConfigurationManager.AppSettings["searchMaxDistance"]);
                minDist = (float)double.Parse(ConfigurationManager.AppSettings["minDistance"]);
                maxDist = (float)double.Parse(ConfigurationManager.AppSettings["maxDistance"]);
                zeroPoint = (float)double.Parse(ConfigurationManager.AppSettings["zeroPoint"]);
                connexionHost = ConfigurationManager.AppSettings["connexionHost"];
                connexionPort = int.Parse(ConfigurationManager.AppSettings["connexionPort"]);
                timerElapsing = int.Parse(ConfigurationManager.AppSettings["timerElapsing"]);
            }
            catch (Exception)
            {
                return false;
            }

            if (maxDistHands <= 0f || minDistHands <= 0f || maxDistHands > maxDist || minDistHands > maxDist ||
                minDistHands >= maxDistHands || zeroPoint < maxDistHands || minDistHands < minDist ||
                zeroPoint >= maxDist || connexionPort < 0 || timerElapsing < 0)
            {
                debug.ExceptionLbl.Content = rm.GetString("loadParametersIncorrect");
                return false;
            }
            return true;
        }

        /*
         * Met à jour les nouveaux paramètres dans la configuration.
         */
        public void updateParameters()
        {
            userPositionDetector.setParams(minDist, maxDist, minDistHands, maxDistHands, zeroPoint);

            //On récupère la config.
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            //On met à jour.
            config.AppSettings.Settings.Remove("searchMinDistance");
            config.AppSettings.Settings.Add("searchMinDistance", minDistHands.ToString());
            config.AppSettings.Settings.Remove("searchMaxDistance");
            config.AppSettings.Settings.Add("searchMaxDistance", maxDistHands.ToString());
            config.AppSettings.Settings.Remove("minDistance");
            config.AppSettings.Settings.Add("minDistance", minDist.ToString());
            config.AppSettings.Settings.Remove("maxDistance");
            config.AppSettings.Settings.Add("maxDistance", maxDist.ToString());
            config.AppSettings.Settings.Remove("zeroPoint");
            config.AppSettings.Settings.Add("zeroPoint", zeroPoint.ToString());
            config.AppSettings.Settings.Remove("connexionHost");
            config.AppSettings.Settings.Add("connexionHost", connexionHost);
            config.AppSettings.Settings.Remove("connexionPort");
            config.AppSettings.Settings.Add("connexionPort", connexionPort.ToString());
            config.AppSettings.Settings.Remove("timerElapsing");
            config.AppSettings.Settings.Add("timerElapsing", timerElapsing.ToString());

            //Sauvegarde la configuration.
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        /*
         * Getters et setters des paramètres du Middleware.
         */
        public void setMinDistHands(float min)
        {
            minDistHands = min;
        }
        public void setMaxDistHands(float max)
        {
            maxDistHands = max;
        }
        public void setConnexionHost(String host)
        {
            connexionHost = host;
        }
        public void setConnexionPort(int port)
        {
            connexionPort = port;
        }
        public void setTimerElapsing(int time)
        {
            timerElapsing = time;
        }

        public float getMinDistHands()
        {
            return minDistHands;
        }
        public float getMaxDistHands()
        {
            return maxDistHands;
        }
        public String getConnexionHost()
        {
            return connexionHost;
        }
        public int getConnexionPort()
        {
            return connexionPort;
        }
        public int getTimerElapsing()
        {
            return timerElapsing;
        }
    }
}