private void drawMallet(Point offset)
 {
     Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
     {
         // Draw mallet location
         var malletLoc = MotorHelper.GetCoordinatesFromOffset(offset);
         malletLocationTextBlock.Text = "Mallet (X,Y): (" + malletLoc.X + ", " + malletLoc.Y + ")";
         Canvas.SetLeft(mallet, malletLoc.X - mallet.Width / 2);
         Canvas.SetTop(mallet, malletLoc.Y - mallet.Height / 2);
         mallet.Visibility = Visibility.Visible;
     });
 }
        private void runDecisionThread(Point puckPosition)
        {
            ThreadPool.RunAsync((s) =>
            {
                Point malletOffset;

                if (gameMode == GameMode.Mirror || mirrorMode)
                {
                    // Mirror the puck
                    double yOffset = MotorHelper.GetOffsetYFromCoordinateX(virtualWidth - puckPosition.X);
                    double xOffset = MotorHelper.GetOffsetXFromCoordinateY(puckPosition.Y);

                    if (Math.Abs(xOffset - robot.StepperX.CurrentPosition) < 50)
                    {
                        xOffset = robot.StepperX.CurrentPosition;
                    }

                    if (Math.Abs(yOffset - robot.StepperY.CurrentPosition) < 50)
                    {
                        yOffset = robot.StepperY.CurrentPosition;
                    }

                    malletOffset = new Point(xOffset, yOffset); //MotorHelper.GetOffsetFromCoordinates(puckPosition);
                }
                else
                {
                    // Figure out where the mallet should move
                    malletOffset = robot.AI.calculateMalletTarget(puckPosition, Global.Stopwatch.ElapsedMilliseconds);
                }

                if (malletOffset != CoordinateHelper.INVALID_POINT)
                {
                    // Set the destination for stepper motors

                    if (!robot.AI.DoNotInterrupt)
                    {
                        switch (robot.AI.Move)
                        {
                        case MoveType.Fast:
                            robot.MoveFastToOffset(malletOffset);
                            break;

                        case MoveType.Straight:
                            robot.MoveStraightToOffset(malletOffset);
                            break;
                        }
                    }
                }
            });
        }
        // Draw the UI
        private void runUIThread()
        {
            ThreadPool.RunAsync(async(s) =>
            {
                while (!stopThread)
                {
                    var puckPosition = robot.AI.GetPuckPosition();

                    clearLines();
                    //drawDot(puckPosition);
                    if (puckPosition != CoordinateHelper.INVALID_POINT)
                    {
                        drawPuck(puckPosition);
                    }

                    drawMallet(robot.GetOffsets());
                    drawCenterOfMass(robot.AI.GetPuckCenterOfMass());

                    // Draw line from mallet to destination
                    drawLine(MotorHelper.GetCoordinatesFromOffset(robot.GetOffsets()),
                             MotorHelper.GetCoordinatesFromOffset(new Point(robot.StepperX.TargetPosition, robot.StepperY.TargetPosition)));

                    var bouncePts = robot.AI.GetPreviousBouncePoints();

                    if (bouncePts != null && bouncePts.Count > 0)
                    {
                        // Draw lines for bounces
                        drawBounces(puckPosition, bouncePts);
                    }
                    else if (robot.AI.GetPreviousTrajectory() != CoordinateHelper.INVALID_POINT)
                    {
                        // Draw line for trajectory
                        drawTrajectory(puckPosition, robot.AI.GetPreviousTrajectory());
                    }

                    setOutputText("Speed: " + robot.AI.GetPuckSpeed());

                    await Task.Delay(1);
                }
            });
        }
Esempio n. 4
0
        // Decision-making function; given puck position, decide where we should net move the mallet
        public Point calculateMalletTarget(Point currentPuckPosition, long currentTime)
        {
            puckPosition = currentPuckPosition;

            Move = MoveType.Straight;

            addToHistory(currentPuckPosition, currentTime);
            if (positionHistory.Count < 2)
            {
                return(CoordinateHelper.INVALID_POINT);
            }

            // Set the default defense position
            defenseOffset = new Point(Config.MAX_MALLET_OFFSET_X / 2, 0);

            // Calculate center of mass for trajectory calculations
            // Get the previous center of mass position
            Point prevCenterOfMass = com.Position;

            // Add the new puck position to the queue for calculations
            com.SafeEnqueue(currentPuckPosition);
            // Calculate the new center of mass
            Point centerOfMass = com.Calculate();

            calculateLine(com.PointQueue.ToArray());

            // If we don't have the previous center of mass, we can't do trajectory calculations, so skip this
            if (prevCenterOfMass == CoordinateHelper.INVALID_POINT)
            {
                return(CoordinateHelper.INVALID_POINT);
            }

            // For speed calculations
            var prevPosition = positionHistory[positionHistory.Count - 2];
            var currPosition = positionHistory.Last();

            // Convert everything to positions (coordinates in the coordinate plane) or offsets (steps for motors)
            Point malletTargetOffset = CoordinateHelper.INVALID_POINT;
            // Mallet offset
            Point currentMalletOffset = new Point(robot.StepperX.CurrentPosition(), robot.StepperY.CurrentPosition());
            // Mallet target in steps
            Point currentMalletTargetOffset = new Point(robot.StepperX.TargetPosition(), robot.StepperY.TargetPosition());
            // Mallet position coordinates
            Point currentMalletPosition = MotorHelper.GetCoordinatesFromOffset(currentMalletOffset);
            // Mallet target coordinates
            Point currentMalletTargetPosition = MotorHelper.GetCoordinatesFromOffset(currentMalletTargetOffset);
            // Distance from previous point
            Vector distanceFromPrevious = Helper.GetDistance(prevCenterOfMass, centerOfMass);

            speed = distanceFromPrevious.H;
            // Puck distance from mallet (coordinates)
            Vector distanceFromMallet = Helper.GetDistance(currentPuckPosition, currentMalletPosition);

            Point trajectoryPoint = CoordinateHelper.INVALID_POINT, bouncePoint = CoordinateHelper.INVALID_POINT;
            // List of points where we think the puck will bounce
            List <Point> bouncePoints = new List <Point>();

            // If this flag has been set, it means we're in the middle of a non-interruptable move
            if (DoNotInterrupt)
            {
                return(CoordinateHelper.INVALID_POINT);
            }

            // The mallet and puck have probably collided, don't do anything yet
            if (Helper.GetDistance(currentMalletPosition, currentPuckPosition).H < 40)
            {
                return(CoordinateHelper.INVALID_POINT);
            }

            // Puck is behind the mallet
            if (distanceFromMallet.X < 0)
            {
                // Defensive position in front of goal
                malletTargetOffset = defenseOffset;

                // Don't interrupt this move until we get to the destination
                DoNotInterrupt = true;
            }
            // Puck is moving away
            else if (prevCenterOfMass.X > centerOfMass.X)
            {
                // Defensive position in front of goal
                malletTargetOffset = defenseOffset;
            }
            else if (distanceFromPrevious.H < 5 && currentPuckPosition.X > Config.TABLE_MID_X_COORDINATE && currentMalletOffset == defenseOffset)
            {
                if (distanceFromMallet.H < 400)
                {
                    // Get new mallet position
                    var targetPoint = CoordinateHelper.CalculateTrajectoryPoint(currentMalletPosition, currentPuckPosition, currentPuckPosition.X - 100);
                    malletTargetOffset = MotorHelper.GetOffsetFromCoordinates(targetPoint);

                    DoNotInterrupt = true;
                }
            }
            // Puck is moving towards mallet
            else if (prevCenterOfMass.X < centerOfMass.X)
            {
                trajectoryPoint = CoordinateHelper.CalculateTrajectoryPoint(prevCenterOfMass, centerOfMass, currentMalletPosition.X);

                if (trajectoryPoint == CoordinateHelper.INVALID_POINT)
                {
                    malletTargetOffset = CoordinateHelper.INVALID_POINT;
                }
                // We can block the puck from our current location (no Y movement)
                else if (trajectoryPoint.X == currentMalletPosition.X)
                {
                    // We're already at the point
                    if (Math.Abs(trajectoryPoint.Y - currentMalletPosition.Y) < 50)// && currentPuckPosition.X > Config.TABLE_MID_X_COORDINATE)//Helper.GetDistance(currentPuckPosition, currentMalletPosition).H < 400)
                    {
                        var targetPoint = CoordinateHelper.CalculateTrajectoryPoint(currentMalletPosition, currentPuckPosition, currentPuckPosition.X - 100);
                        malletTargetOffset = MotorHelper.GetOffsetFromCoordinates(targetPoint);

                        DoNotInterrupt = true;
                    }
                    else
                    {
                        malletTargetOffset = new Point(MotorHelper.GetOffsetXFromCoordinateY(trajectoryPoint.Y), currentMalletOffset.Y);
                    }
                }
                else if (trajectoryPoint.X != currentMalletPosition.X)
                {
                    if (speed > 15)
                    {
                        double angleAdjust = 1;
                        double adjustment  = .1;

                        if (trajectoryPoint.X != currentMalletPosition.X)
                        {
                            bouncePoints.Add(trajectoryPoint);
                            bouncePoint = CoordinateHelper.CalculateBouncePoint(centerOfMass, trajectoryPoint, currentMalletPosition.X, angleAdjust += adjustment);
                            Point prevBouncePoint = trajectoryPoint;
                            while (bouncePoint.X != currentMalletPosition.X && bouncePoints.Count < 1)
                            {
                                bouncePoints.Add(bouncePoint);
                                bouncePoint     = CoordinateHelper.CalculateBouncePoint(prevBouncePoint, bouncePoint, currentMalletPosition.X, angleAdjust += adjustment);
                                prevBouncePoint = bouncePoint;
                            }

                            bouncePoints.Add(bouncePoint);
                        }

                        if (bouncePoint.X == currentMalletPosition.X)
                        {
                            // Don't react to bounce unless we think it's going to be near the goal
                            if (bouncePoint.Y > Config.TABLE_GOAL_Y_TOP && bouncePoint.X < Config.TABLE_GOAL_Y_BOTTOM)
                            {
                                malletTargetOffset = MotorHelper.GetOffsetFromCoordinates(bouncePoint);
                            }
                        }
                    }
                }
                else
                {
                    // Defensive position in front of goal
                    malletTargetOffset = defenseOffset;
                }
            }

            // We have a valid target destination for the mallet
            if (malletTargetOffset != CoordinateHelper.INVALID_POINT)
            {
                // Constrain offset so that mallet doesn't move too far
                malletTargetOffset.X = Helper.Constrain(malletTargetOffset.X, 0, Config.MAX_MALLET_OFFSET_X);
                malletTargetOffset.Y = Helper.Constrain(malletTargetOffset.Y, 0, Config.MAX_MALLET_OFFSET_Y);
            }

            previousTrajectoryPoint = trajectoryPoint;
            previousBouncePoints    = bouncePoints;

            return(malletTargetOffset);
        }