private void Vertical(NormalizedHands hands, MoveCommand moveCommand)
        {
            double deltaY   = this.neutralHands.Center.Y - hands.Left.Y;
            double deltaX   = this.neutralHands.Center.X - hands.Left.X;
            double gradient = deltaY / deltaX;
            double alpha    = this.ConvertRadiansToDegrees(Math.Atan(gradient));

            deltaY   = hands.Right.Y - this.neutralHands.Center.Y;
            deltaX   = hands.Right.X - this.neutralHands.Center.X;
            gradient = deltaY / deltaX;
            double beta       = this.ConvertRadiansToDegrees(Math.Atan(gradient));
            double deltaAngle = alpha - beta;

            bool areBothHandsUp   = this.neutralHands.Left.Y > hands.Left.Y && this.neutralHands.Right.Y > hands.Right.Y;
            bool areBothHandsDown = this.neutralHands.Left.Y < hands.Left.Y && this.neutralHands.Right.Y < hands.Right.Y;

            double angle = 180 - Math.Abs(deltaAngle);

            if (angle < VERTICAL_ANGLE_THRESHOLD)
            {
                if (deltaAngle < 0 && areBothHandsDown)
                {
                    moveCommand.Vertical = MOVE_DOWN;
                }
                else if (deltaAngle > 0 && areBothHandsUp)
                {
                    moveCommand.Vertical = MOVE_UP;
                }
            }
        }
        private void Lateral(NormalizedHands hands, MoveCommand moveCommand)
        {
            double deltaY          = this.neutralHands.Right.Y - this.neutralHands.Left.Y;
            double deltaX          = this.neutralHands.Right.X - this.neutralHands.Left.X;
            double neutralGradient = deltaY / deltaX;
            double neutralAngle    = this.ConvertRadiansToDegrees(Math.Atan(neutralGradient));

            deltaY = hands.Right.Y - hands.Left.Y;
            deltaX = hands.Right.X - hands.Left.X;
            double actualGradient = deltaY / deltaX;
            double actualAngle    = this.ConvertRadiansToDegrees(Math.Atan(actualGradient));

            double deltaAngle         = neutralAngle - actualAngle;
            double absoluteDeltaAngle = Math.Abs(deltaAngle);

            if (LATERAL_ANGLE_THRESHOLD < absoluteDeltaAngle)
            {
                if (deltaAngle < 0)
                {
                    moveCommand.Lateral = MOVE_RIGHT;
                }
                else if (0 < deltaAngle)
                {
                    moveCommand.Lateral = MOVE_LEFT;
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Processes a hands input.
        /// </summary>
        /// <param name="hands">The key input to evaluate.</param>
        /// <returns>The evaluation result of the <paramref name="hands"/>.</returns>
        public InputProcessResult ProcessHandsInput(NormalizedHands hands)
        {
            this.LatestHandsInputEvaluated = this.handsInputEvaluator.EvaluateHands(hands);
            DroneControllerHandsInputProcessResult result =
                new DroneControllerHandsInputProcessResult(this.LatestHandsInputEvaluated.Copy() as MoveCommand);

            this.Control();
            return(result);
        }
Esempio n. 4
0
        public void KeyInputIsSentAfterHandsInput_KeyInputIsNotIgnored()
        {
            var skinColorHandsDetectorMock = new Mock <ISkinColorHandsDetector>();

            skinColorHandsDetectorMock.Setup(schd => schd.Tuned).Returns(true);

            var left  = new NormalizedHand(0.15, 0.2, 0.18);
            var right = new NormalizedHand(0.85, 0.2, 0.18);
            var hands = new NormalizedHands(left, right);
            var handsDetectorResult = new HandsDetectorResult(hands, null);

            skinColorHandsDetectorMock.Setup(schd => schd.DetectHands(It.IsAny <BgrImage>()))
            .Returns(handsDetectorResult);

            var keyInputEvaluator   = new GeneralDroneKeyInputEvaluator();
            var handsInputEvaluator = new DroneControllerHandsInputEvaluator();
            var neutralLeft         = new NormalizedHand(0.15, 0.5, 0.18);
            var neutralRight        = new NormalizedHand(0.85, 0.5, 0.18);
            var neutralHands        = new NormalizedHands(neutralLeft, neutralRight);

            handsInputEvaluator.Tune(neutralHands);

            this.caduhdApp = new CaduhdApp(null, skinColorHandsDetectorMock.Object, this.tello, keyInputEvaluator, handsInputEvaluator);

            this.caduhdApp.Input(BgrImage.GetBlank(1, 1, Color.Black));
            this.udpClient.Client.ReceiveTimeout = 1000;

            string response          = string.Empty;
            bool   handsInputIgnored = false;

            try
            {
                response = this.udpClient.Receive(ref this.anyEndPoint).AsString();
                Assert.Equal($"rc 0 0 {this.tello.Speed} 0", response);
            }
            catch (SocketException)
            {
            }

            this.caduhdApp.Input(new KeyInfo(Key.D, KeyState.Down));

            try
            {
                response = this.udpClient.Receive(ref this.anyEndPoint).AsString();
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode == SocketError.TimedOut)
                {
                    handsInputIgnored = true;
                }
            }

            this.tello.Dispose();
            Assert.False(handsInputIgnored);
            Assert.Equal($"rc 0 0 0 {this.tello.Speed}", response);
        }
Esempio n. 5
0
        /// <summary>
        /// This is the entry point of the hands into the Caduhd App.
        /// </summary>
        /// <param name="image">The image, possibly containing hands.</param>
        public void Input(BgrImage image)
        {
            if (Interlocked.CompareExchange(ref this.isWebCameraFrameProcessorBusy, YES, NO) == NO)
            {
                if (this.handsAnalyzer != null)
                {
                    this.uiConnector.SetHandsAnalyzerState(this.handsAnalyzer.State);
                }

                BgrImage    frame       = image;
                MoveCommand moveCommand = null;

                if (this.skinColorHandsDetector.Tuned)
                {
                    HandsDetectorResult result = this.skinColorHandsDetector.DetectHands(frame);
                    frame = result.Image;
                    var hands = result.Hands;
                    moveCommand =
                        (this.handsDroneController.ProcessHandsInput(hands) as DroneControllerHandsInputProcessResult)?.Result;
                }
                else
                {
                    if (this.handsAnalyzer.State == HandsAnalyzerState.ReadyToAnalyzeLeft || this.handsAnalyzer.State == HandsAnalyzerState.AnalyzingLeft)
                    {
                        if (this.handsAnalyzer.State == HandsAnalyzerState.AnalyzingLeft)
                        {
                            this.handsAnalyzer.AnalyzeLeft(frame, this.handsDroneController.HandsInputEvaluator.TunerHands["left"]["poi"]);
                            this.handsAnalyzer.AdvanceState();
                        }

                        frame.MarkPoints(this.handsDroneController.HandsInputEvaluator.TunerHands["left"]["outline"], Color.Yellow);
                    }
                    else if (this.handsAnalyzer.State == HandsAnalyzerState.ReadyToAnalyzeRight || this.handsAnalyzer.State == HandsAnalyzerState.AnalyzingRight)
                    {
                        if (this.handsAnalyzer.State == HandsAnalyzerState.AnalyzingRight)
                        {
                            this.handsAnalyzer.AnalyzeRight(frame, this.handsDroneController.HandsInputEvaluator.TunerHands["right"]["poi"]);
                            this.handsAnalyzer.AdvanceState();
                        }

                        frame.MarkPoints(this.handsDroneController.HandsInputEvaluator.TunerHands["right"]["outline"], Color.Yellow);
                    }
                    else if (this.handsAnalyzer.State == HandsAnalyzerState.Tuning)
                    {
                        HandsAnalyzerResult result       = this.handsAnalyzer.Result;
                        NormalizedHands     neutralHands = this.skinColorHandsDetector.Tune(result);
                        this.handsDroneController.HandsInputEvaluator.Tune(neutralHands);
                    }
                }

                this.uiConnector?.SetComputerCameraImage(frame);
                this.uiConnector?.SetEvaluatedHandsInput(moveCommand);

                Interlocked.Exchange(ref this.isWebCameraFrameProcessorBusy, NO);
            }
        }
        /// <summary>
        /// Evaluates hands to <see cref="MoveCommand"/>.
        /// </summary>
        /// <param name="hands">Hands to evaluate.</param>
        /// <returns>The evaluated hands as a <see cref="MoveCommand"/>.</returns>
        public MoveCommand EvaluateHands(NormalizedHands hands)
        {
            MoveCommand moveCommand = new MoveCommand();

            this.Lateral(hands, moveCommand);
            this.Longitudinal(hands, moveCommand);
            this.Vertical(hands, moveCommand);
            this.Yaw(hands, moveCommand);

            return(moveCommand);
        }
        public HandsDroneControllerTests()
        {
            this.controllableDroneMock   = new Mock <AbstractDrone>();
            this.keyInputEvaluatorMock   = new Mock <IDroneControllerKeyInputEvaluator>();
            this.handsInputEvaluatorMock = new Mock <IDroneControllerHandsInputEvaluator>();
            this.droneController         = new HandsDroneController(this.controllableDroneMock.Object,
                                                                    this.handsInputEvaluatorMock.Object,
                                                                    this.keyInputEvaluatorMock.Object);

            this.hands = new NormalizedHands(new NormalizedHand(), new NormalizedHand());
        }
Esempio n. 8
0
        public void DifferentHandsInputsAfterEachOther_BothSent()
        {
            var skinColorHandsDetectorMock = new Mock <ISkinColorHandsDetector>();

            skinColorHandsDetectorMock.Setup(schd => schd.Tuned).Returns(true);

            var firstLeft  = new NormalizedHand(0.15, 0.2, 0.18);
            var firstRight = new NormalizedHand(0.85, 0.2, 0.18);
            var firstHands = new NormalizedHands(firstLeft, firstRight);
            var firstHandsDetectorResult = new HandsDetectorResult(firstHands, null);

            var secondLeft  = new NormalizedHand(0.15, 0.8, 0.18);
            var secondRight = new NormalizedHand(0.85, 0.7, 0.18);
            var secondHands = new NormalizedHands(secondLeft, secondRight);
            var secondandsDetectorResult = new HandsDetectorResult(secondHands, null);

            skinColorHandsDetectorMock.SetupSequence(schd => schd.DetectHands(It.IsAny <BgrImage>()))
            .Returns(firstHandsDetectorResult)
            .Returns(secondandsDetectorResult);

            var keyInputEvaluator   = new GeneralDroneKeyInputEvaluator();
            var handsInputEvaluator = new DroneControllerHandsInputEvaluator();
            var neutralLeft         = new NormalizedHand(0.15, 0.5, 0.18);
            var neutralRight        = new NormalizedHand(0.85, 0.5, 0.18);
            var neutralHands        = new NormalizedHands(neutralLeft, neutralRight);

            handsInputEvaluator.Tune(neutralHands);

            this.caduhdApp = new CaduhdApp(null, skinColorHandsDetectorMock.Object, this.tello, keyInputEvaluator, handsInputEvaluator);

            this.caduhdApp.Input(BgrImage.GetBlank(1, 1, Color.Black));
            this.caduhdApp.Input(BgrImage.GetBlank(1, 1, Color.Black));

            this.udpClient.Client.ReceiveTimeout = 1000;
            int counter = 0;

            try
            {
                string response = this.udpClient.Receive(ref this.anyEndPoint).AsString();
                Assert.Equal($"rc 0 0 {this.tello.Speed} 0", response);
                counter++;
                response = this.udpClient.Receive(ref this.anyEndPoint).AsString();
                Assert.Equal($"rc 0 0 -{this.tello.Speed} 0", response);
                counter++;
            }
            catch (SocketException)
            {
            }

            this.tello.Dispose();
            Assert.Equal(2, counter);
        }
        private void Yaw(NormalizedHands hands, MoveCommand moveCommand)
        {
            double handsWeightRatio = hands.Left.Weight / (this.neutralHands.RatioOfLeftWeightToRightWeight * hands.Right.Weight);

            if (handsWeightRatio < YAW_LOWER_THRESHOLD)
            {
                moveCommand.Yaw = YAW_LEFT;
            }
            else if (handsWeightRatio > YAW_UPPDER_THRESHOLD)
            {
                moveCommand.Yaw = YAW_RIGHT;
            }
        }
        private void Longitudinal(NormalizedHands hands, MoveCommand moveCommand)
        {
            double leftRatio  = hands.Left.Weight / this.neutralHands.Left.Weight;
            double rightRatio = hands.Right.Weight / this.neutralHands.Right.Weight;

            if (LONGITUDINAL_UPPER_THRESHOLD < leftRatio && LONGITUDINAL_UPPER_THRESHOLD < rightRatio)
            {
                moveCommand.Longitudinal = MOVE_FORWARD;
            }
            else if (leftRatio < LONGITUDINAL_LOWER_THRESHOLD && rightRatio < LONGITUDINAL_LOWER_THRESHOLD)
            {
                moveCommand.Longitudinal = MOVE_BACKWARD;
            }
        }
Esempio n. 11
0
        public void HandsInputAnalyzerTuned_HandsInput_MoveDownwards_HandsInputEvaluated_CorrectMoveCommandSent()
        {
            var skinColorHandsDetectorMock = new Mock <ISkinColorHandsDetector>();

            skinColorHandsDetectorMock.Setup(schd => schd.Tuned).Returns(true);

            var neutralLeft  = new NormalizedHand(0.15, 0.5, 0.18);
            var neutralRight = new NormalizedHand(0.85, 0.5, 0.18);
            var neutralHands = new NormalizedHands(neutralLeft, neutralRight);

            var left  = new NormalizedHand(0.15, 0.8, 0.18);
            var right = new NormalizedHand(0.85, 0.8, 0.18);
            var hands = new NormalizedHands(left, right);
            var handsDetectorResult = new HandsDetectorResult(hands, null);

            skinColorHandsDetectorMock.Setup(schd => schd.DetectHands(It.IsAny <BgrImage>()))
            .Returns(handsDetectorResult);

            var keyInputEvaluator   = new GeneralDroneKeyInputEvaluator();
            var handsInputEvaluator = new DroneControllerHandsInputEvaluator();

            handsInputEvaluator.Tune(neutralHands);

            this.caduhdApp = new CaduhdApp(null, skinColorHandsDetectorMock.Object, this.tello, keyInputEvaluator, handsInputEvaluator);

            string response = string.Empty;

            this.caduhdApp.Input(BgrImage.GetBlank(1, 1, Color.Black));

            try
            {
                response = this.udpClient.Receive(ref this.anyEndPoint).AsString();
            }
            catch (SocketException)
            {
            }

            // it needs to be disposed of here
            this.tello.Dispose();

            Assert.Equal($"rc 0 0 -{this.tello.Speed} 0", response);
        }
Esempio n. 12
0
 public HandsDetectorResultTests()
 {
     this.hands = new NormalizedHands(new NormalizedHand(), new NormalizedHand());
     this.image = BgrImage.GetBlank(100, 100, Color.White);
     this.handsDetectorResult = new HandsDetectorResult(this.hands, this.image);
 }
Esempio n. 13
0
 public NormalizedHandsTests()
 {
     this.left  = new NormalizedHand(LEFT_X, LEFT_Y, LEFT_WEIGHT);
     this.right = new NormalizedHand(RIGHT_X, RIGHT_Y, RIGHT_WEIGHT);
     this.hands = new NormalizedHands(this.left, this.right);
 }
 /// <summary>
 /// Tuner method to set the neutral hands as a reference for future hands input evaluation.
 /// </summary>
 /// <param name="neutralHands">Hands detected in their neutral position.</param>
 public void Tune(NormalizedHands neutralHands) => this.neutralHands = neutralHands;