public override void trainValues(double start, double duration, CancellationToken ct)
        {
            waitForStart(start, ct);

            var userId        = getTargetID();
            var fifthDuration = duration / 5;

            var stopwatch = Stopwatch.StartNew();

            // Record avg pos for first fifth duration
            var startPos = recordAvgValue(stopwatch, fifthDuration, duration, userId, ct);

            while (stopwatch.Elapsed < TimeSpan.FromSeconds(duration - fifthDuration))
            {
                if (ct.IsCancellationRequested)
                {
                    setDescription("Cancelled!");
                    return;
                }
                decrementDuration(duration, stopwatch);
            }

            // Record avg pos for last fifth duration
            var endPos = recordAvgValue(stopwatch, duration, duration, userId, ct);

            // Record measurement distance
            if (Options.MeasuringUnit != FubiUtils.BodyMeasurement.NUM_MEASUREMENTS)
            {
                float measureConfidence;
                Fubi.getBodyMeasurementDistance(userId, Options.MeasuringUnit, out m_measureDist, out measureConfidence);
            }

            // Calc change between first and last fifth avg position
            AvgValue = endPos - startPos;

            // Apply active axes
            if ((Options.IgnoreAxes & (uint)FubiUtils.CoordinateAxis.X) != 0)
            {
                AvgValue.X = 0;
            }
            if ((Options.IgnoreAxes & (uint)FubiUtils.CoordinateAxis.Y) != 0)
            {
                AvgValue.Y = 0;
            }
            if ((Options.IgnoreAxes & (uint)FubiUtils.CoordinateAxis.Z) != 0)
            {
                AvgValue.Z = 0;
            }

            // Calculate speed
            m_speed = (endPos - startPos).Length / (duration - fifthDuration);
        }
        protected Vector3D getCurrentJointValue(uint targetID, FubiUtils.SkeletonJoint jointID, FubiUtils.BodyMeasurement measureID = FubiUtils.BodyMeasurement.NUM_MEASUREMENTS)
        {
            float  x, y, z, confidence;
            double timeStamp;

            if (Type == XMLGenerator.RecognizerType.JointRelation || Type == XMLGenerator.RecognizerType.LinearMovement)
            {
                if (UseHand)
                {
                    Fubi.getCurrentHandJointPosition(targetID, (FubiUtils.SkeletonHandJoint)jointID, out x, out y, out z, out confidence, out timeStamp, Options.Local, Options.Filtered);
                }
                else
                {
                    Fubi.getCurrentSkeletonJointPosition(targetID, jointID, out x, out y, out z, out confidence, out timeStamp, Options.Local, Options.Filtered);
                    if (measureID != FubiUtils.BodyMeasurement.NUM_MEASUREMENTS && Type == XMLGenerator.RecognizerType.JointRelation)
                    {
                        float measureDist, measureConfidence;
                        Fubi.getBodyMeasurementDistance(targetID, measureID, out measureDist, out measureConfidence);
                        if (measureDist > 0)
                        {
                            x /= measureDist;
                            y /= measureDist;
                            z /= measureDist;
                        }
                    }
                }
            }
            else
            {
                var mat = new float[9];
                if (UseHand)
                {
                    Fubi.getCurrentHandJointOrientation(targetID, (FubiUtils.SkeletonHandJoint)jointID, mat, out confidence, out timeStamp, Options.Local, Options.Filtered);
                }
                else
                {
                    Fubi.getCurrentSkeletonJointOrientation(targetID, jointID, mat, out confidence, out timeStamp, Options.Local, Options.Filtered);
                }
                FubiUtils.Math.rotMatToRotation(mat, out x, out y, out z);
            }
            return(new Vector3D(x, y, z));
        }