middleware/src/MainModule/KinectMain.cs
author bastiena
Wed, 30 May 2012 10:21:36 +0200
changeset 35 4267d6d27a7d
parent 28 9ccef81f02ab
child 37 37ebedd84755
permissions -rw-r--r--
Front IDILL : Config file added dor the Front Random play at the beginning (when no user is detected) Pointers added Curves added (search and filter modes) Mosaic completion added (depletion to come later) State of the Front : just before the communication module creation

/*
* This file is part of the TraKERS\Middleware package.
*
* (c) IRI <http://www.iri.centrepompidou.fr/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/*
 * 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.
 * Découpe l'interaction avec le middleware en différents modes.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Documents;
using Microsoft.Kinect;
using Trakers.Communication;
using Trakers.MainModule.Events;
using Trakers.Tracking.Search;
using Trakers.Debug;
using System.Windows;
using Trakers.Tracking.Gestures;
using Trakers.Tracking.Postures;

namespace Trakers.MainModule
{
    //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 Bend.
    public delegate void BendHandler(object o, BendEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements Cross.
    public delegate void CrossHandler(object o, CrossEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements KneeUp.
    public delegate void KneeUpHandler(object o, KneeUpEventArgs 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 Wave.
    public delegate void WaveHandler(object o, WaveEventArgs e);
    //Il s'agit de la fonction permettant d'appeler les fonctions des événements Circle.
    public delegate void CircleHandler(object o, CircleEventArgs 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
    {
        //Fenêtre de debug.
        private 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 penchés.
        private BendDetector bendDetector;
        //Détecteur de croisement de bras en X.
        private CrossDetector crossDetector;
        //Détecteur de levé de genou.
        private KneeUpDetector kneeUpDetector;

        //Détecteur de swipes.
        private SwipeDetector swipeDetector;
        //Détecteur de pushes.
        private PushDetector pushDetector;
        //Détecteur de jumps.
        private JumpDetector jumpDetector;
        //Détecteur de waves.
        private WaveDetector waveDetector;
        //Détecteur de cercles.
        private CircleDetector circleDetector;
        //Détecteur de proximité.
        private UserPositionDetector userPositionDetector;

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

        //Gestionnaire de modes.
        private ModeManagement modeManagement;

        //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 bend.
        public static event BendHandler BendEvent;
        //L'événement cross.
        public static event CrossHandler CrossEvent;
        //L'événement kneeUp.
        public static event KneeUpHandler KneeUpEvent;

        //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 wave.
        public static event WaveHandler WaveEvent;
        //L'événement circle.
        public static event CircleHandler CircleEvent;
        //L'événement l'utilisateur se déplace dans la zone de détection.
        public static event UserPositionHandler UserPositionEvent;

        /*
        *  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 crée la fenêtre de debug.
            debug = new DebugWindow();

            //On crée les détecteurs de postures.
            bendDetector = new BendDetector(debug);
            crossDetector = new CrossDetector(debug);
            kneeUpDetector = new KneeUpDetector(debug);

            //On crée les détecteurs de gestes.
            swipeDetector = new SwipeDetector(debug);
            pushDetector = new PushDetector(debug);
            jumpDetector = new JumpDetector(debug);
            waveDetector = new WaveDetector(debug);
            circleDetector = new CircleDetector(debug);
            //On crée le détecteur de proximité.
            userPositionDetector = new UserPositionDetector(debug.getMinDist(), debug.getMaxDist(), debug.getZeroPoint(), debug.getMinDistHands(), debug.getMaxDistHands());

            //On connecte le serveur à l'adresse locale sur le port 80.
            try
            {
                server = new Server(debug.getConnexionHost(), debug.getConnexionPort(), debug.getTimerElapsing());
                //On crée le gestionnaire de modes.
                modeManagement = new ModeManagement(server, debug, this);
            }
            catch (Exception)
            {
                debug.ShowException("serverCantStart");
            }

            //On écoute l'événement de clic sur le bouton on/off du debug.
            //Car on lancera l'intitialisation/fermeture de la kinect.
            debug.getSwitch().Click += new RoutedEventHandler(Switch_ClickInKinectMain);
            debug.Loaded += new RoutedEventHandler(Window_LoadedInKinectMain);
            debug.Closed += new EventHandler(Window_CloseInKinectMain);
            debug.getQuitMenu().Click += new RoutedEventHandler(Quit_ClickInKinectMain);
            debug.getParametersWindow().getModButton().Click += new RoutedEventHandler(updateParameters);

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

        /*
         * Envoi les paramètres mis à jour dans les différents modules.
         */
        public void updateParameters(object sender, RoutedEventArgs e)
        {
            userPositionDetector.setParams(debug.getMinDist(), debug.getMaxDist(), debug.getMinDistHands(), debug.getMaxDistHands(), debug.getZeroPoint());
            server = new Server(debug.getConnexionHost(), debug.getConnexionPort(), debug.getTimerElapsing());
        }

        /*
        *  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();

            }
            catch (System.Exception)
            {
                debug.ShowException("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.showAndSend);

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

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

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

            //Fonction appelée lorsque l'utilisateur se penche.
            BendListener bendListener = new BendListener();
            BendEvent += new BendHandler(bendListener.showAndSend);

            //Fonction appelée lorsque l'utilisateur croise les bras en X.
            CrossListener crossListener = new CrossListener();
            CrossEvent += new CrossHandler(crossListener.showAndSend);

            //Fonction appelée lorsque l'utilisateur lève le genou.
            KneeUpListener kneeUpListener = new KneeUpListener();
            KneeUpEvent += new KneeUpHandler(kneeUpListener.showAndSend);

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

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

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

            //Fonction appelée lorsque l'utilisateur effectue un Wave.
            WaveListener waveListener = new WaveListener();
            WaveEvent += new WaveHandler(waveListener.showAndSend);

            //Fonction appelée lorsque l'utilisateur effectue un Circle.
            CircleListener circleListener = new CircleListener();
            CircleEvent += new CircleHandler(circleListener.showAndSend);

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

            modeManagement.DetectProximityBasedModes(0);
        }

        /*
        * Bouton ON/OFF du debug écouté dans KinectMain.
        */
        public void Switch_ClickInKinectMain(object sender, RoutedEventArgs e)
        {
            Console.Out.WriteLine(debug.getOn());
            //Si la kinect est allumée.
            if (debug.getOn())
            {
                //On initialise la Kinect.
                KinectInitialization();
            }
            else
            {
                //On éteint la Kinect.
                KinectClose();
            }
        }

        /*
         * Méthode associée à l'événement : Quitter via le menu écoutée dans KinectMain.
         */
        private void Quit_ClickInKinectMain(object sender, RoutedEventArgs e)
        {
            KinectClose();
            debug.Quit_Click(sender, e);
        }

        /*
         * Permet d'initialiser la Kinect dès que la fenêtre est lancée écoutée dans KinectMain.
         */
        private void Window_LoadedInKinectMain(object sender, RoutedEventArgs e)
        {
            KinectInitialization();
        }

        /*
        * Fermeture du debug écouté dans KinectMain.
        */
        private void Window_CloseInKinectMain(object sender, EventArgs e)
        {
            //On éteint la Kinect.
            KinectClose();
            debug.Window_Closed(sender, e);
        }

        /*
        *  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.ShutDownInterface();
            }
            catch (System.Exception)
            {
                debug.ShowException("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 écoute le debug pour savoir si les paramètres ont été modifiés.
            

            //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);
                PostureDetector.UpdateSkeletonState(joints);

                //Si la main gauche est dans le champ, on lance l'événement approprié.
                if (handLeft.Position.Z < debug.getMaxDistHands() && handLeft.Position.Z > debug.getMinDistHands())
                {
                    LeftHandTrackedEventArgs leftHandTrackedEvent = new LeftHandTrackedEventArgs(server, debug, handLeft, handLeft.Position.Z);
                    OnLeftHandTrackedEvent(leftHandTrackedEvent);
                    /*if (circleDetector.CheckForLeftCircle())
                    {
                        CircleEventArgs circleEvent = new CircleEventArgs(server, debug);
                        OnCircleEvent(circleEvent);
                    }*/
                }
                //Si la main gauche quitte le champ, on lance l'événement approprié.
                else
                {
                    LeftHandQuitEventArgs leftHandQuitEvent = new LeftHandQuitEventArgs(server, debug);
                    OnLeftHandQuitEvent(leftHandQuitEvent);
                }
                //Si la main droite est dans le champ, on lance l'événement approprié.
                if (handRight.Position.Z < debug.getMaxDistHands() && handRight.Position.Z > debug.getMinDistHands())
                {
                    RightHandTrackedEventArgs rightHandTrackedEvent = new RightHandTrackedEventArgs(server, debug, handRight, handRight.Position.Z);
                    OnRightHandTrackedEvent(rightHandTrackedEvent);
                    /*if (circleDetector.CheckForRightCircle())
                    {
                        CircleEventArgs circleEvent = new CircleEventArgs(server, debug);
                        OnCircleEvent(circleEvent);
                        //Console.Out.WriteLine("CIRCLE");
                    }*/
                }
                //Si la main droite quitte le champ, on lance l'événement approprié.
                else
                {
                    RightHandQuitEventArgs rightHandQuitEvent = new RightHandQuitEventArgs(server, debug);
                    OnRightHandQuitEvent(rightHandQuitEvent);
                }

                //Si l'utilisateur s'est penché.
                if (bendDetector.CheckForBend())
                {
                    BendEventArgs bendEvent = new BendEventArgs(server, debug);
                    OnBendEvent(bendEvent);
                }

                //Si l'utilisateur a croisé les bras en X.
                if (crossDetector.CheckForCross())
                {
                    CrossEventArgs crossEvent = new CrossEventArgs(server, debug);
                    OnCrossEvent(crossEvent);
                }

                //Si l'utilisateur a levé le genou.
                if (kneeUpDetector.CheckForKneeUp())
                {
                    KneeUpEventArgs kneeUpEvent = new KneeUpEventArgs(server, debug);
                    OnKneeUpEvent(kneeUpEvent);
                }

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

                //Si l'utilisateur effectue un swipe right.
                if (swipeDetector.CheckForSwipeRight())
                {
                    SwipeEventArgs swipeEvent = new SwipeEventArgs(server, debug, 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(server, debug, PushDetector.Direction.PUSH, handPush);
                    OnPushEvent(pushEvent);
                }
                //Si l'utilisateur effectue un pull.
                if ((handPush = pushDetector.CheckForPull()) != PushDetector.Hand.NONE)
                {
                    PushEventArgs pushEvent = new PushEventArgs(server, debug, PushDetector.Direction.PULL, handPush);
                    OnPushEvent(pushEvent);
                }

                //Si l'utilisateur effectue un wave.
                if (waveDetector.CheckForWave())
                {
                    WaveEventArgs waveEvent = new WaveEventArgs(server, debug);
                    OnWaveEvent(waveEvent);
                    Console.Out.WriteLine("WAVE");
                }

                //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);
                    int numberOfImages = userPositionDetector.ImagesToShow(proximity, debug.getImagesToShow());

                    modeManagement.DetectProximityBasedModes(proximity);

                    if (proximity > 0f)
                    {
                        UserPositionEventArgs userPositionEvent = new UserPositionEventArgs(server, debug, proximity, numberOfImages);
                        OnUserPositionEvent(userPositionEvent);
                    }
                    else if(proximity < 10f)
                    {
                        debug.hideSkeleton();
                        modeManagement.DetectProximityBasedModes(0);
                        LeftHandQuitEventArgs leftHandQuitEvent = new LeftHandQuitEventArgs(server, debug);
                        OnLeftHandQuitEvent(leftHandQuitEvent);
                        RightHandQuitEventArgs rightHandQuitEvent = new RightHandQuitEventArgs(server, debug);
                        OnRightHandQuitEvent(rightHandQuitEvent);
                    }
                }

                //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();
                modeManagement.DetectProximityBasedModes(0);
                LeftHandQuitEventArgs leftHandQuitEvent = new LeftHandQuitEventArgs(server, debug);
                OnLeftHandQuitEvent(leftHandQuitEvent);
                RightHandQuitEventArgs rightHandQuitEvent = new RightHandQuitEventArgs(server, debug);
                OnRightHandQuitEvent(rightHandQuitEvent);
            }
        }

        /*
        *  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 se penche.
        */
        public static void OnBendEvent(BendEventArgs e)
        {
            if (BendEvent != null)
                BendEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur croise les bras en X.
        */
        public static void OnCrossEvent(CrossEventArgs e)
        {
            if (CrossEvent != null)
                CrossEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur lève le genou.
        */
        public static void OnKneeUpEvent(KneeUpEventArgs e)
        {
            if (KneeUpEvent != null)
                KneeUpEvent(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 effectue un cercle.
        */
        public static void OnCircleEvent(CircleEventArgs e)
        {
            if (CircleEvent != null)
                CircleEvent(new object(), e);
        }

        /*
        *  Initialise l'événement et fait appel aux fonctions du listener quand l'utilisateur effectue un wave.
        */
        public static void OnWaveEvent(WaveEventArgs e)
        {
            if (WaveEvent != null)
                WaveEvent(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);
        }
    }
}