示例#1
0
        public void PtsToMm_Coordinates_Null()
        {
            BallCoordinates expected = null;
            BallCoordinates actual   = _testAsset.PtsToMm(expected);

            Assert.AreEqual(actual, expected);
        }
示例#2
0
        /// <summary>
        /// Stabilization method used to remove shaking
        /// </summary>
        /// <param name="newCoordinates">New coordinates</param>
        /// <param name="storedCoordinates">Last known stored coordinates</param>
        /// <returns>Approximate Coordinates without shaking</returns>
        public BallCoordinates Stabilize(BallCoordinates newCoordinates, BallCoordinates storedCoordinates)
        {
            if (newCoordinates.IsDefined)
            {
                _undefinedCoordinatesCounter = 0;
                _lastGoodCoordinates         = newCoordinates;

                BallCoordinates coordinates = RemoveShaking(newCoordinates, storedCoordinates);
                return(coordinates);
            }
            else //new coordinates are undefined
            {
                if (_undefinedCoordinatesCounter < MAX_UNDEFINED_THRESHOLD)
                {
                    _undefinedCoordinatesCounter++;
                    if (storedCoordinates.IsDefined)
                    {
                        _lastGoodCoordinates = storedCoordinates;
                    }
                }
                else
                {
                    _lastGoodCoordinates = newCoordinates;
                }
                return(_lastGoodCoordinates);
            }
        }
示例#3
0
        /// <summary>
        /// Calculate actual linear movement (Y Axe) for current rod to perform
        /// Is based on desired linear move type
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="respondingPlayer">Responding player in current rod (1 based index)</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <param name="desiredLinearMove">Desired Linear Move Type</param>
        /// <returns>New rod coordinate to move to (Axe Y)</returns>
        protected int CalculateNewRodCoordinate(IRod rod, int respondingPlayer, BallCoordinates bfc, eLinearMove desiredLinearMove)
        {
            //Define actual desired rod coordinate to move to
            //NOTE: responding player might be undefined will be -1
            switch (desiredLinearMove)
            {
            case eLinearMove.BALL_Y:
                return(_helper.LocateRespondingPlayer(rod, bfc.Y, respondingPlayer));

            //    return bfc.Y - _helper.CalculateCurrentPlayerYCoordinate(rod, _currentRodYCoordinate[rod.RodType], respondingPlayer);

            //case eLinearMove.LEFT_BALL_DIAMETER:
            //    return (-1) * 2 * BALL_RADIUS;
            //case eLinearMove.RIGHT_BALL_DIAMETER:
            //    return 2 * BALL_RADIUS;
            case eLinearMove.VECTOR_BASED:
                if (rod.Intersection.IsDefined)
                {
                    int stopperPosition = _helper.LocateRespondingPlayer(rod, rod.Intersection.Y, respondingPlayer);
                    return((IsBallNearTheRod(bfc, rod, stopperPosition)) ? stopperPosition : rod.State.DcPosition);
                }
                //return rod.IntersectionY - _helper.CalculateCurrentPlayerYCoordinate(rod, _currentRodYCoordinate[rod.RodType], respondingPlayer);
                return(rod.State.DcPosition);

            //case eLinearMove.BEST_EFFORT:
            //    return rod.BestEffort;
            default:
                return(rod.State.DcPosition);
            }
        }
示例#4
0
        /// <summary>
        /// Only if ball is near the rod new location will be sent to communication layer.
        /// Method is based on distance, ball speed and BALL_DISTANCE_FACTOR, BALL_MAX_SPEED
        /// This method added to support Amit's requirement, to be able to set new position of rod based on distance to it.
        /// </summary>
        /// <param name="ballCoords">Ball Future Coordinates to respond to</param>
        /// <param name="currentRod">Current responding rod</param>
        /// <returns>[True] if we are near the rod or high speed, [False] otherwise</returns>
        protected bool IsBallNearTheRod(BallCoordinates ballCoords, IRod currentRod, int stopperPosition)
        {
            //By changing this parameter we set system sensitivity
            const double BALL_DISTANCE_FACTOR = 3000;
            const double BALL_MAX_SPEED       = 100;

            if (!ballCoords.IsDefined)
            {
                return(false);
            }

            double distanceFactor = Convert.ToDouble(TABLE_WIDTH) / Math.Abs(ballCoords.X - currentRod.RodXCoordinate);

            double speedFactor = 1;

            if (ballCoords.Vector != null && ballCoords.Vector.IsDefined)
            {
                speedFactor += Math.Abs(ballCoords.Vector.X / BALL_MAX_SPEED);
            }

            double diff = (double)Math.Abs(currentRod.State.DcPosition - stopperPosition) / (double)(currentRod.PlayerCount);

            bool result = (distanceFactor * diff * speedFactor > BALL_DISTANCE_FACTOR);

            return(result);
        }
示例#5
0
        public void MmToPts_Coordinates_Not_Defined()
        {
            BallCoordinates expected = new BallCoordinates(DateTime.Now);
            BallCoordinates actual   = _testAsset.MmToPts(expected);

            Assert.AreEqual(actual, expected);
        }
示例#6
0
        /// <summary>
        /// Ricochet coordinate calculation
        /// </summary>
        /// <param name="ballCoordinates">Ball Coordinates</param>
        /// <returns>Ricochet Ball Coordinates</returns>
        public BallCoordinates Ricochet(BallCoordinates ballCoordinates)
        {
            try
            {
                Coordinates2D intersectionPoint = FindNearestIntersectionPoint(ballCoordinates);

                //Marks.DrawRicochetMark(Convert.ToInt32(intersectionPoint.X), Convert.ToInt32(intersectionPoint.Y), true);

                DateTime ricocheTime = FindRicochetTime(ballCoordinates, intersectionPoint);

                Vector2D vector = FindIntersectionVector(ballCoordinates.Vector, intersectionPoint);

                BallCoordinates coordinates = new BallCoordinates(
                    Convert.ToInt32(intersectionPoint.X),
                    Convert.ToInt32(intersectionPoint.Y), ricocheTime);
                coordinates.Vector = vector;

                return(coordinates);
            }
            catch (Exception e)
            {
                throw new NotSupportedException(String.Format(
                                                    "[{0}] Failed to find ricochet coordinates. Reason: {1}",
                                                    MethodBase.GetCurrentMethod().Name, e.Message));
            }
        }
示例#7
0
        /// <summary>
        /// Main working method - runs in loop on Start
        /// </summary>
        public override void Job()
        {
            Initialize();

            //Detach from streamer
            _publisher.Detach(this);

            //get current ball coordinates
            BallCoordinates coordinates = SampleCoordinates();

            //show current ball coordinates on screen and GUI
            System.Drawing.PointF p = TransformAgent.Data.InvertTransform(new System.Drawing.PointF(_x, _y));
            Marks.DrawBall(new Point(p.X, p.Y), _ballRadius);

            Statistics.TryUpdateBasicImageProcessingInfo(String.Format("Generated coordinates: {0}x{1}", _x, _y));

            //set current coordinates to update
            ImagingData.BallCoords = coordinates;

            //set current coordinates and publish new ball coordinates
            BallLocationUpdater.UpdateAndNotify();

            //attach back to streamer
            _publisher.Attach(this);
        }
示例#8
0
        public void FindNearestIntersectionPoint_NoMove_from_50_50()
        {
            _initialCoordinates        = new BallCoordinates(50, 50, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(0, 0);

            Coordinates2D actualResult = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
        }
示例#9
0
        /// <summary>
        /// Convert BallCoordinates in points to BallCoordinates in mm
        /// </summary>
        /// <param name="pts">BallCoordinates in Points</param>
        /// <returns>BallCoordinates in Milimeters</returns>
        public BallCoordinates PtsToMm(BallCoordinates pts)
        {
            BallCoordinates mmCoords = null;

            if (pts != null && pts.IsDefined)
            {
                int xMm = pts.X * XMaxMm / XMaxPts;
                int yMm = pts.Y * YMaxMm / YMaxPts;
                mmCoords = new BallCoordinates(xMm, yMm, pts.Timestamp);
            }
            else
            {
                return(pts);
            }

            if (pts.Vector != null && pts.Vector.IsDefined)
            {
                double xMm = pts.Vector.X * (double)XMaxMm / (double)XMaxPts;
                double yMm = pts.Vector.Y * (double)YMaxMm / (double)YMaxPts;
                mmCoords.Vector = new Vector2D(xMm, yMm);
            }
            else
            {
                mmCoords.Vector = pts.Vector;
            }
            return(mmCoords);
        }
示例#10
0
        /// <summary>
        /// Convert BallCoordinates in mm to BallCoordinates in points
        /// </summary>
        /// <param name="mm">BallCoordinates in Milimeters</param>
        /// <returns>BallCoordinates in Points</returns>
        public BallCoordinates MmToPts(BallCoordinates mm)
        {
            BallCoordinates pointsCoords = null;

            if (mm != null && mm.IsDefined)
            {
                int xMm = mm.X * XMaxPts / XMaxMm;
                int yMm = mm.Y * YMaxPts / YMaxMm;
                pointsCoords = new BallCoordinates(xMm, yMm, mm.Timestamp);
            }
            else
            {
                return(mm);
            }

            if (mm.Vector != null && mm.Vector.IsDefined)
            {
                double xMm = mm.Vector.X * (double)XMaxPts / (double)XMaxMm;
                double yMm = mm.Vector.Y * (double)YMaxPts / (double)YMaxMm;
                pointsCoords.Vector = new Vector2D(xMm, yMm);
            }
            else
            {
                pointsCoords.Vector = mm.Vector;
            }
            return(pointsCoords);
        }
示例#11
0
        /// <summary>
        /// Main Decision Flow
        /// </summary>
        /// <param name="currentCoordinates"></param>
        public void Flow(BallCoordinates currentCoordinates)
        {
            //Calculate Actual Possible Action Time
            DateTime timeOfAction = DateTime.Now + DELAYS;

            //Calculate ball future coordinates
            FindBallFutureCoordinates(currentCoordinates, timeOfAction);

            //Calculate dynamic sectors
            if (currentCoordinates.IsDefined && currentCoordinates.Vector.IsDefined)
            {
                CalculateDynamicSectors(currentCoordinates.X, currentCoordinates.Vector.X);
            }
            else
            {
                throw new NotSupportedException("Currently not defined coordinates are not supported by Pre-Decision Flow");
            }

            //Calculate Rod Intersection with a ball for all rods
            CalculateSectorIntersection(currentCoordinates);

            //Take decision for each rod
            foreach (Rod rod in _rods.Values)
            {
                _decisionTree.Decide(rod, _bfc);
            }
        }
示例#12
0
        /// <summary>
        /// Callculate Rod Intersection with current rod
        /// </summary>
        /// <param name="rod">Current rod to calculate intersection with</param>
        /// <param name="currentCoordinates">Current ball coordinates to calculate intersection</param>
        private void CalculateSectorIntersection(Rod rod, BallCoordinates currentCoordinates)
        {
            int xintersection = (rod.RodXCoordinate > currentCoordinates.X) ?
                                Convert.ToInt32(rod.RodXCoordinate - rod.DynamicSector / 2.0) :
                                Convert.ToInt32(rod.RodXCoordinate + rod.DynamicSector / 2.0);

            double inms = (xintersection - currentCoordinates.X) / currentCoordinates.Vector.X;

            if (inms >= 0)
            {
                TimeSpan intersectionTime = TimeSpan.FromMilliseconds(inms);

                int yintersection = Convert.ToInt32(currentCoordinates.Vector.Y * intersectionTime.TotalMilliseconds + currentCoordinates.Y);

                if (IsCoordinatesYInRange(yintersection))
                {
                    rod.SetBallIntersection(xintersection, yintersection, currentCoordinates.Timestamp + intersectionTime);
                }
                else
                {
                    //ToDo: Call ricoshet algorithm with:
                    BallCoordinates ricoshetCoordiantes = null;
                    //ricoshetCoordiantes = RicoshetAlgorithm(currentCoordinates);
                    CalculateSectorIntersection(rod, ricoshetCoordiantes);
                }
            }
            else
            {
                rod.SetBallIntersection();
            }
        }
示例#13
0
 /// <summary>
 /// Callculate Rod Intersection for all rods
 /// </summary>
 /// <param name="currentCoordinates">Current ball coordinates to calculate intersection</param>
 private void CalculateSectorIntersection(BallCoordinates currentCoordinates)
 {
     foreach (Rod rod in _rods.Values)
     {
         CalculateSectorIntersection(rod, currentCoordinates);
     }
 }
示例#14
0
        /// <summary>
        /// Calculate Ball Future Coordinates in actual time system can responce
        /// </summary>
        /// <param name="currentCoordinates"><Current ball coordinates/param>
        /// <param name="actionTime">Actual system responce time</param>
        private void FindBallFutureCoordinates(BallCoordinates currentCoordinates, DateTime actionTime)
        {
            TimeSpan deltaT = actionTime - currentCoordinates.Timestamp;

            if (currentCoordinates.IsDefined && currentCoordinates.Vector.IsDefined)
            {
                int xfc = Convert.ToInt32(currentCoordinates.Vector.X * deltaT.TotalMilliseconds + currentCoordinates.X);
                int yfc = Convert.ToInt32(currentCoordinates.Vector.Y * deltaT.TotalMilliseconds + currentCoordinates.Y);

                if (IsCoordinatesInRange(xfc, yfc))
                {
                    _bfc = new BallCoordinates(xfc, yfc, actionTime);
                }
                else
                {
                    //ToDo: Call ricoshet algorithm with:
                    BallCoordinates ricoshetCoordiantes = null;
                    //ricoshetCoordiantes = RicoshetAlgorithm(currentCoordinates);
                    FindBallFutureCoordinates(ricoshetCoordiantes, actionTime);
                }
            }
            else
            {
                throw new NotSupportedException("Currently not defined coordinates are not supported by Pre-Decision Flow");
            }
        }
示例#15
0
        public void MmToPts_Coordinates_Null()
        {
            BallCoordinates expected = null;
            BallCoordinates actual   = _testAsset.MmToPts(expected);

            Assert.AreEqual(actual, expected);
        }
示例#16
0
        /// <summary>
        /// Verify coordinates and vector are defined, not null and not both vector x and y are 0
        /// </summary>
        /// <param name="ballCoordinates">Ball Coordianates with vector</param>
        /// <exception cref="NotSupportedException">Thrown in case vector or coordinates are not defined or are NULL, or both vector x and y are 0</exception>
        private void VerifyBallCoordinatesAndVectorInput(BallCoordinates ballCoordinates)
        {
            if (ballCoordinates == null)
            {
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because ball coordinates are NULL", MethodBase.GetCurrentMethod().Name));
            }

            if (!ballCoordinates.IsDefined)
            {
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because ball coordinates are not defined", MethodBase.GetCurrentMethod().Name));
            }

            if (ballCoordinates.Vector == null)
            {
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because vector is NULL", MethodBase.GetCurrentMethod().Name));
            }

            if (!ballCoordinates.Vector.IsDefined)
            {
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because vector is undefined", MethodBase.GetCurrentMethod().Name));
            }

            if (ballCoordinates.Vector.X == 0 && ballCoordinates.Vector.Y == 0)
            {
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because vector is 0x0", MethodBase.GetCurrentMethod().Name));
            }
        }
示例#17
0
        /// <summary>
        /// Convert BallCoordinates in points to BallCoordinates in mm
        /// </summary>
        /// <param name="pts">BallCoordinates in Points</param>
        /// <returns>BallCoordinates in Millimeters</returns>
        public BallCoordinates PtsToMm(BallCoordinates pts)
        {
            BallCoordinates mmCoords = null;
            if (pts != null && pts.IsDefined)
            {
                int xMm = pts.X * XMaxMm / XMaxPts;
                int yMm = pts.Y * YMaxMm / YMaxPts;
                mmCoords = new BallCoordinates(xMm, yMm, pts.Timestamp);
            }
            else
            {
                return pts;
            }

            if (Vector2D.NotNullAndDefined(pts.Vector))
            {
                double xMm = pts.Vector.X * (double)XMaxMm / (double)XMaxPts;
                double yMm = pts.Vector.Y * (double)YMaxMm / (double)YMaxPts;
                mmCoords.Vector = new Vector2D(xMm, yMm);
            }
            else
            {
                mmCoords.Vector = pts.Vector;
            }
            return mmCoords;
        }
示例#18
0
        public void FindBallFutureCoordinates_RicochetTestThree()
        {
            //arrange
            DateTime        timeStamp          = DateTime.Now;
            BallCoordinates currentCoordinates = new BallCoordinates(300, 200, timeStamp);

            currentCoordinates.Vector = new Vector2D(100, -100);
            DateTime        actionTime           = timeStamp + TimeSpan.FromSeconds(10);
            BallCoordinates ricocheteCoordinates = new BallCoordinates(500, 0, timeStamp + TimeSpan.FromSeconds(2));

            ricocheteCoordinates.Vector = new Vector2D(100, -100);
            _surveyorMock.IsCoordinatesInRange(Arg.Any <int>(), Arg.Any <int>()).Returns(false, true);
            _ricochetMock.Ricochet(Arg.Any <BallCoordinates>()).Returns(ricocheteCoordinates);

            double deltaT          = (actionTime - ricocheteCoordinates.Timestamp).TotalSeconds;
            int    expectedX       = Convert.ToInt32(ricocheteCoordinates.X + ricocheteCoordinates.Vector.X * deltaT);
            int    expectedY       = Convert.ToInt32(ricocheteCoordinates.Y + ricocheteCoordinates.Vector.Y * deltaT);
            double expectedVectorX = ricocheteCoordinates.Vector.X;
            double expectedVectorY = ricocheteCoordinates.Vector.Y;

            //act
            BallCoordinates actualResult = _testAsset.FindBallFutureCoordinates(currentCoordinates, actionTime);

            //assert
            Assert.AreEqual(actualResult.X, expectedX);
            Assert.AreEqual(actualResult.Y, expectedY);
            Assert.AreEqual(actualResult.Vector.X, expectedVectorX);
            Assert.AreEqual(actualResult.Vector.Y, expectedVectorY);
            Assert.AreEqual(actualResult.Timestamp, actionTime);
        }
示例#19
0
        /// <summary>
        /// Stabilization method used to remove shaking
        /// </summary>
        /// <param name="newCoordinates">New coordinates</param>
        /// <param name="storedCoordinates">Last known stored coordinates</param>
        /// <returns>Approximate Coordinates without shaking</returns>
        public BallCoordinates Stabilize(BallCoordinates newCoordinates, BallCoordinates storedCoordinates)
        {
            if (newCoordinates.IsDefined)
            {
                _undefinedCoordinatesCounter = 0;
                _lastGoodCoordinates = newCoordinates;

                BallCoordinates coordinates = RemoveShaking(newCoordinates, storedCoordinates);
                return coordinates;
            }
            else //new coordinates are undefined
            {
                if (_undefinedCoordinatesCounter < MAX_UNDEFINED_THRESHOLD)
                {
                    _undefinedCoordinatesCounter++;
                    if (storedCoordinates.IsDefined)
                        _lastGoodCoordinates = storedCoordinates;
                }
                else
                {
                    _lastGoodCoordinates = newCoordinates;
                }
                return _lastGoodCoordinates;
            }
        }
示例#20
0
        /// <summary>
        /// Calculate Rod Intersection with current rod.
        ///
        /// The Main Idea of this method is to set Intersection Property of
        /// ControlRod Class as Intersection Coordinate with Timestamp.
        /// In current case both time and coordinates should be defined
        /// if intersection exists or both undefined because if there is no
        /// intersection found the timestamp is also not relevant.
        /// </summary>
        /// <param name="currentCoordinates">Current ball coordinates to calculate intersection</param>
        public void CalculateSectorIntersection(BallCoordinates currentCoordinates)
        {
            try
            {
                //If unable to calculate OR no intersection - set Intersection as undefined and exit
                if (currentCoordinates == null || !currentCoordinates.IsDefined ||
                    currentCoordinates.Vector == null || !currentCoordinates.Vector.IsDefined ||
                    currentCoordinates.Vector.X == 0)
                {
                    Intersection = new TimedPoint();
                    return;
                }

                /*
                 * After practical simulations it seems we don't want to define
                 * intersection with X using sector definition. Anyway if this need
                 * to be changed, following code can be used:
                 *
                 *  int xintersection = (RodXCoordinate > currentCoordinates.X) ?
                 *      Convert.ToInt32(RodXCoordinate - DynamicSector / 2.0) :
                 *      Convert.ToInt32(RodXCoordinate + DynamicSector / 2.0);
                 *
                 */
                int xintersection = RodXCoordinate;

                //find intersection time using: T = dX/V in seconds
                double intersectionTimestamp = (xintersection - currentCoordinates.X) / currentCoordinates.Vector.X;

                //If intersecion will happen in the future but before maximum future time limit
                if (intersectionTimestamp >= 0 && intersectionTimestamp < PredictIntersectionMaxTimespan)
                {
                    TimeSpan intersectionTime = TimeSpan.FromSeconds(intersectionTimestamp);

                    int yintersection = Convert.ToInt32(currentCoordinates.Vector.Y * intersectionTime.TotalSeconds + currentCoordinates.Y);
                    if (_surveyor.IsCoordinatesYInRange(yintersection))
                    {
                        Intersection = new TimedPoint(xintersection, yintersection, currentCoordinates.Timestamp + intersectionTime);
                        // Log.Common.Debug(String.Format("[{0}] Found intersection point with rod [{1}]: [{2}x{3}]",
                        //     MethodBase.GetCurrentMethod().Name, _rodType, xintersection, yintersection));
                    }
                    else
                    {
                        BallCoordinates ricoshetCoordiantes = _vectorUtils.Ricochet(currentCoordinates);
                        CalculateSectorIntersection(ricoshetCoordiantes);
                    }
                }
                else
                {
                    //Intersection found is from the past or not in the near future and is irrelevant
                    Intersection = new TimedPoint();
                }
            }
            catch (Exception e)
            {
                Intersection = new TimedPoint();
                Log.Print(String.Format("Unable to calculate rod intersection. Reason: {0}",
                                        e.Message), eCategory.Error, LogTag.DECISION);
            }
        }
示例#21
0
        /// <summary>
        /// Choose player to respond on current rod and action to perform
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="bfc">Ball Future Coordinates</param>
        /// <param name="respondingPlayer">Responding Player index (1 based) on current rod [out]</param>
        /// <returns>Rod Action to be performed</returns>
        protected RodAction DefineActionAndRespondingPlayer(IRod rod, BallCoordinates bfc, out int respondingPlayer)
        {
            if (rod == null)
            {
                throw new ArgumentException(String.Format(
                                                "[{0}] Unable to define action and responding player while rod argument is NULL!",
                                                MethodBase.GetCurrentMethod().Name));
            }

            if (bfc == null || !bfc.IsDefined)
            {
                throw new ArgumentException(String.Format(
                                                "[{0}] Unable to define action and responding player while ball coordinates are NULL or UNDEFINED!",
                                                MethodBase.GetCurrentMethod().Name));
            }

            RodAction action = null;

            respondingPlayer = -1;
            switch (_helper.IsBallInSector(bfc.X, rod.RodXCoordinate, rod.DynamicSector))
            {
            //Ball is in Current Rod Sector
            case eXPositionSectorRelative.IN_SECTOR:
                action           = SubTree.Decide(rod, bfc);
                respondingPlayer = SubTree.RespondingPlayer;
                break;

            /* OLD :
             *  //The Big Sub Tree
             *  action = EnterDecisionTreeBallInSector(rod, bfc, out respondingPlayer);
             */

            //Ball is ahead of Current Rod Sector
            case eXPositionSectorRelative.AHEAD_SECTOR:
                //Ball Vector Direction is TO Current Rod and we have intersection point
                if (_helper.IsBallVectorToRod(bfc.Vector) &&
                    rod.Intersection.IsDefined)
                {
                    action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.VECTOR_BASED);

                    //Define responding player index
                    BallYPositionToPlayerYCoordinate(bfc.Y, rod);
                    respondingPlayer = this.RespondingPlayer;
                }
                else
                {
                    //Ball Vector Direction is FROM Current Rod
                    action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.BEST_EFFORT);
                }
                break;

            //Ball is behind Current Rod Sector
            case eXPositionSectorRelative.BEHIND_SECTOR:
                action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.BEST_EFFORT);
                break;
            }
            return(action);
        }
示例#22
0
        /// <summary>
        /// Find ball location in image in defined area
        /// </summary>
        /// <param name="image">Image to detect ball on</param>
        /// <param name="imageTimestamp">Image timestamp</param>
        /// <param name="isFullAreaSearch">[True] search will be performed in all image = default,
        /// otherwise area will be defined based on last stored location adn maximum possible speed
        /// </param>
        /// <returns>[True] if ball location found, [False] otherwise</returns>
        private bool FindBallLocation(Image <Gray, byte> image, DateTime imageTimestamp, bool isFullAreaSearch = true)
        {
            image = image.Clone();

            int    additionalOffsetX = 0;
            int    additionalOffsetY = 0;
            string area = (isFullAreaSearch) ? "FULL" : "SELECTED";

            if (!isFullAreaSearch)
            {
                TimeSpan deltaT       = imageTimestamp - _storedLocation.Timestamp;
                double   searchRadius = MAX_BALL_SPEED * deltaT.TotalSeconds;

                int maxX = (Convert.ToInt32(_storedLocation.X + searchRadius) > image.Width) ? image.Width : Convert.ToInt32(_storedLocation.X + searchRadius);
                int maxY = (Convert.ToInt32(_storedLocation.Y + searchRadius) > image.Height) ? image.Height : Convert.ToInt32(_storedLocation.Y + searchRadius);
                additionalOffsetX = (Convert.ToInt32(_storedLocation.X - searchRadius) < 0) ? 0 : Convert.ToInt32(_storedLocation.X - searchRadius);
                additionalOffsetY = (Convert.ToInt32(_storedLocation.Y - searchRadius) < 0) ? 0 : Convert.ToInt32(_storedLocation.Y - searchRadius);

                List <System.Drawing.PointF> croppingPoints = new List <System.Drawing.PointF>()
                {
                    new System.Drawing.PointF(maxX, maxY),
                    new System.Drawing.PointF(maxX, additionalOffsetY),
                    new System.Drawing.PointF(additionalOffsetX, maxY),
                    new System.Drawing.PointF(additionalOffsetX, additionalOffsetY)
                };

                image = base.Crop(image, croppingPoints);
                //croppedImage.Save("test\\" + imageTimestamp.ToString("mm_ss_fff") + ".png");
            }

            CircleF[] pos = base.DetectCircles(image, _calibrator.Radius, _calibrator.ErrorRate * 2, _calibrator.Radius * 5, 250, 37, 1.5);//300, 40, 1.3);
            if (pos.Length > 0)
            {
                _storedLocation = new Location(pos[0].Center.X + additionalOffsetX, pos[0].Center.Y + additionalOffsetY, imageTimestamp);

                int x = _storedLocation.X + OffsetX;
                int y = _storedLocation.Y + OffsetY;

                Log.Image.Info(String.Format("[{0}] Possible ball location in {1} area: {2}x{3}",
                                             MethodBase.GetCurrentMethod().Name, area, x, y));
                UpdateMarkup(Helpers.eMarkupKey.BALL_CIRCLE_MARK, new System.Windows.Point(x, y), Convert.ToInt32(pos[0].Radius));

                System.Drawing.PointF coordinates = Transformation.Transform(new System.Drawing.PointF(x, y));

                this.LastBallCoordinates = new BallCoordinates(Convert.ToInt32(coordinates.X), Convert.ToInt32(coordinates.Y), imageTimestamp);
                IsBallLocationFound      = true;
                UpdateStatistics(Helpers.eStatisticsKey.BallCoordinates,
                                 String.Format("Ball coordinates: {0}x{1}", LastBallCoordinates.X, LastBallCoordinates.Y));

                return(true);
            }
            Log.Image.Debug(String.Format("[{0}] Ball not found in {1} area", MethodBase.GetCurrentMethod().Name, area));
            IsBallLocationFound = false;
            return(false);
        }
示例#23
0
        public void FindNearestIntersectionPoint_MoveLeftUp_LeftFirst_from_50_50()
        {
            _initialCoordinates        = new BallCoordinates(50, 50, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(-50, 100);

            Coordinates2D actualResult   = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
            Coordinates2D expectedResult = new Coordinates2D(XMIN, 150);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
        }
示例#24
0
 /// <summary>
 /// Remove Shaking method
 /// </summary>
 /// <param name="newCoordinates">New coordinates</param>
 /// <param name="lastKnownCoordinates">Last known coordinates</param>
 /// <returns>Approximate Coordinates without shaking</returns>
 private BallCoordinates RemoveShaking(BallCoordinates newCoordinates, BallCoordinates lastKnownCoordinates)
 {
     if (lastKnownCoordinates.IsDefined)
     {
         if (IsInRadiusRange(newCoordinates, lastKnownCoordinates))
         {
             return(new BallCoordinates(lastKnownCoordinates.X, lastKnownCoordinates.Y, newCoordinates.Timestamp));
         }
     }
     return(newCoordinates);
 }
示例#25
0
        public void FindNearestIntersectionPoint_MoveDown_from_100_50()
        {
            _initialCoordinates        = new BallCoordinates(100, 50, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(0, -100);

            Coordinates2D actualResult   = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
            Coordinates2D expectedResult = new Coordinates2D(100, YMIN);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
        }
示例#26
0
        public void FindNearestIntersectionPoint_MoveRightDown_RightFirst_from_700_100()
        {
            _initialCoordinates        = new BallCoordinates(700, 100, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(100, -50);

            Coordinates2D actualResult   = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
            Coordinates2D expectedResult = new Coordinates2D(XMAX, 50);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
        }
示例#27
0
        public void FindRicochetTime_Vector_100_50()
        {
            DateTime        now             = DateTime.Now;
            Coordinates2D   intersection    = new Coordinates2D(XMAX, 350);
            BallCoordinates ballCoordinates = new BallCoordinates(700, 300, now);

            ballCoordinates.Vector = new Vector2D(100, 50);
            DateTime actualTime = _testAsset.FindRicochetTime(ballCoordinates, intersection);
            DateTime expected   = now + TimeSpan.FromSeconds(1.0);

            Assert.AreEqual(expected, actualTime);
        }
示例#28
0
        public void FindRicochetTime_Vector_minus140_minus20()
        {
            DateTime        now             = DateTime.Now;
            Coordinates2D   intersection    = new Coordinates2D(XMIN, 200);
            BallCoordinates ballCoordinates = new BallCoordinates(700, 300, now);

            ballCoordinates.Vector = new Vector2D(-140, -20);
            DateTime actualTime = _testAsset.FindRicochetTime(ballCoordinates, intersection);
            DateTime expected   = now + TimeSpan.FromSeconds(5.0);

            Assert.AreEqual(expected, actualTime);
        }
示例#29
0
        public void FindBallFutureCoordinates_ActionTimeIsEarlierThanTimeStamp()
        {
            //arrange
            DateTime        timeStamp          = DateTime.Now;
            BallCoordinates currentCoordinates = new BallCoordinates(100, 100, timeStamp);

            //act
            DateTime actionTime = timeStamp - TimeSpan.FromSeconds(5);

            //assert
            _testAsset.FindBallFutureCoordinates(currentCoordinates, actionTime);
        }
示例#30
0
        public void VectorCalculationAlgorithm_Stored_BallCoordinates_Not_Defined_Test()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(DateTime.Now);
            PrivateObject po = new PrivateObject(typeof(VectorCalculationUnit), _mockPublisher,null);

            Vector2D expected = new Vector2D();
            Vector2D actual = (Vector2D)po.Invoke("VectorCalculationAlgorithm",
                                                new Type[] { typeof(BallCoordinates) },
                                                new Object[] { ballCoordinates },
                                                new Type[] { typeof(BallCoordinates) });
            Assert.AreEqual(actual, actual);
        }
示例#31
0
        /// <summary>
        /// Choose player to respond on current rod and action to perform
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="bfc">Ball Future Coordinates</param>
        /// <param name="respondingPlayer">Responding Player index (1 based) on current rod [out]</param>
        /// <returns>Rod Action to be performed</returns>
        protected RodAction DefineActionAndRespondingPlayer(IRod rod, BallCoordinates bfc, out int respondingPlayer)
        {
            if (rod == null)
                throw new ArgumentException(String.Format(
                     "[{0}] Unable to define action and responding player while rod argument is NULL!",
                        MethodBase.GetCurrentMethod().Name));

            if (bfc == null || !bfc.IsDefined)
                throw new ArgumentException(String.Format(
                    "[{0}] Unable to define action and responding player while ball coordinates are NULL or UNDEFINED!",
                        MethodBase.GetCurrentMethod().Name));

            RodAction action = null;
            respondingPlayer = -1;
            switch (_helper.IsBallInSector(bfc.X, rod.RodXCoordinate, rod.DynamicSector))
            {
                //Ball is in Current Rod Sector
                case eXPositionSectorRelative.IN_SECTOR:
                    action = SubTree.Decide(rod, bfc);
                    respondingPlayer = SubTree.RespondingPlayer;
                    break;

                    /* OLD :
                     *  //The Big Sub Tree
                     *  action = EnterDecisionTreeBallInSector(rod, bfc, out respondingPlayer);
                     */

                //Ball is ahead of Current Rod Sector
                case eXPositionSectorRelative.AHEAD_SECTOR:
                    //Ball Vector Direction is TO Current Rod and we have intersection point
                    if (_helper.IsBallVectorToRod(bfc.Vector) &&
                            rod.Intersection.IsDefined)
                    {
                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.VECTOR_BASED);
                        
                        //Define responding player index
                        BallYPositionToPlayerYCoordinate(bfc.Y, rod);
                        respondingPlayer = this.RespondingPlayer;
                    }
                    else
                    {
                        //Ball Vector Direction is FROM Current Rod
                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.BEST_EFFORT);
                    }
                    break;
                //Ball is behind Current Rod Sector
                case eXPositionSectorRelative.BEHIND_SECTOR:
                    action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.BEST_EFFORT);
                    break;
            }
            return action;
        }
示例#32
0
        public void MmToPts_Coordinates_Only()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(50, 50, DateTime.Now);

            int xMm = ballCoordinates.X * X_MAX_PTS / X_MAX_MM;
            int yMm = ballCoordinates.Y * Y_MAX_PTS / Y_MAX_MM;

            BallCoordinates expected = new BallCoordinates(xMm, yMm, ballCoordinates.Timestamp);
            BallCoordinates actual   = _testAsset.MmToPts(ballCoordinates);

            Assert.AreEqual(actual.X, expected.X);
            Assert.AreEqual(actual.Y, expected.Y);
        }
示例#33
0
    public static byte[] SerializeBallCoordinates(Vector3 position, Vector3 direction, float speed)
    {
        var builder = new FlatBufferBuilder(1);

        BallCoordinates.StartBallCoordinates(builder);
        BallCoordinates.AddPosition(builder, Vec3.CreateVec3(builder, position.x, position.y, position.z));
        BallCoordinates.AddDirection(builder, Vec3.CreateVec3(builder, direction.x, direction.y, direction.z));
        BallCoordinates.AddSpeed(builder, speed);
        var ball = BallCoordinates.EndBallCoordinates(builder);

        BallCoordinates.FinishBallCoordinatesBuffer(builder, ball);
        return(builder.SizedByteArray());
    }
        public void VectorCalculationAlgorithm_BallCoordinates_Not_Defined_Test()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(DateTime.Now);
            PrivateObject   po = new PrivateObject(typeof(VectorCalculationUnit), _mockPublisher, null);

            Vector2D expected = new Vector2D();
            Vector2D actual   = (Vector2D)po.Invoke("VectorCalculationAlgorithm",
                                                    new Type[] { typeof(BallCoordinates) },
                                                    new Object[] { ballCoordinates },
                                                    new Type[] { typeof(BallCoordinates) });

            Assert.AreEqual(actual, actual);
        }
示例#35
0
        public void FindBallFutureCoordinates_BallCoordinatesVectorNull()
        {
            //arrange
            BallCoordinates currentCoordinates = new BallCoordinates(100, 100, DateTime.Now);
            DateTime actionTime = DateTime.Now + TimeSpan.FromSeconds(5);

            //act
            BallCoordinates actualCoordinates = _testAsset.FindBallFutureCoordinates(currentCoordinates, actionTime);


            //assert
            Assert.AreEqual(currentCoordinates.X, actualCoordinates.X);
            Assert.AreEqual(currentCoordinates.Y, actualCoordinates.Y);
            Assert.AreEqual(actionTime, actualCoordinates.Timestamp);
            Assert.IsNull(actualCoordinates.Vector);

        }
示例#36
0
        /// <summary>
        /// Calculate Ball Future Coordinates in actual time system can response
        /// </summary>
        /// <param name="currentCoordinates"><Current ball coordinates/param>
        /// <param name="actionTime">Actual system response time</param>
        /// <returns>Ball Future coordinates</returns>
        public BallCoordinates FindBallFutureCoordinates(BallCoordinates currentCoordinates, DateTime actionTime)
        {
            if (currentCoordinates == null || !currentCoordinates.IsDefined)
                throw new ArgumentException(String.Format(
                    "[{0}] Unable to calculate ball future coordinates while current coordinates are null or undefined",
                        MethodBase.GetCurrentMethod().Name));

            if (actionTime < currentCoordinates.Timestamp)
                throw new ArgumentException(String.Format(
                    "[{0}] Unable to calculate ball future coordinates while action time is earlier than time stamp",
                        MethodBase.GetCurrentMethod().Name));

            BallCoordinates bfc;

            if (!Vector2D.NotNullAndDefined(currentCoordinates.Vector))
            {
                bfc = new BallCoordinates(currentCoordinates.X, currentCoordinates.Y, actionTime);
                bfc.Vector = currentCoordinates.Vector;
                return bfc;
            }

            bfc = currentCoordinates;
            try
            {
                TimeSpan deltaT = actionTime - currentCoordinates.Timestamp;

                int xfc = Convert.ToInt32(currentCoordinates.Vector.X * deltaT.TotalSeconds + currentCoordinates.X);
                int yfc = Convert.ToInt32(currentCoordinates.Vector.Y * deltaT.TotalSeconds + currentCoordinates.Y);

                if (_surveyor.IsCoordinatesInRange(xfc, yfc))
                {
                    bfc = new BallCoordinates(xfc, yfc, actionTime);
                    bfc.Vector = currentCoordinates.Vector;
                }
                else
                {
                    BallCoordinates ricoshetCoordiantes = _ricochetCalc.Ricochet(currentCoordinates);
                    return FindBallFutureCoordinates(ricoshetCoordiantes, actionTime);
                }
            }
            catch (Exception e)
            {
                Log.Print("Error: " + e.Message, eCategory.Error, LogTag.DECISION);
            }
            return bfc;
        }
示例#37
0
        /// <summary>
        /// Main Decision Flow Method
        /// </summary>
        /// <param name="rod">Rod to use for decision</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <returns>Rod Action to perform</returns>
        public override RodAction Decide(IRod rod, BallCoordinates bfc)
        {
            //Player to respond  (index base is 0)
            int respondingPlayer = -1;

            //Chose responding player on rod and define action to perform
            RodAction action = DefineActionAndRespondingPlayer(rod, bfc, out respondingPlayer);

            //Define actual desired rod coordinate to move to
            int startStopperDesiredY = CalculateNewRodCoordinate(rod, respondingPlayer, bfc, action.Linear);
            action.DcCoordinate = rod.NearestPossibleDcPosition(startStopperDesiredY);

            //Set last decided rod and player coordinates 
            rod.State.DcPosition = action.DcCoordinate;
            if (_helper.ShouldSetServoStateFromTree(rod.RodType))
                rod.State.ServoPosition = action.Rotation;
            return action;
        }
示例#38
0
 public void Ricochet_UndefinedVector()
 {
     _initialCoordinates = new BallCoordinates(10, 10, DateTime.Now);
     _initialCoordinates.Vector = new Vector2D();
     _testAsset.Ricochet(_initialCoordinates);
 }
示例#39
0
 public void Ricochet_UndefinedCoordinates()
 {
     _initialCoordinates = new BallCoordinates(DateTime.Now);
     _testAsset.Ricochet(_initialCoordinates);
 }
示例#40
0
 public void Ricochet_NullVector()
 {
     _initialCoordinates = new BallCoordinates(10, 10, DateTime.Now);
     _testAsset.Ricochet(_initialCoordinates);
 }
示例#41
0
 public void Ricochet_NullCoordinates()
 {
     _initialCoordinates = null;
     _testAsset.Ricochet(_initialCoordinates);
 }
示例#42
0
        public void MmToPts_Vector_Not_Defined()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(50, 50, DateTime.Now);
            ballCoordinates.Vector = new Vector2D();

            int xMm = ballCoordinates.X * X_MAX_PTS / X_MAX_MM;
            int yMm = ballCoordinates.Y * Y_MAX_PTS / Y_MAX_MM;

            BallCoordinates expected = new BallCoordinates(xMm, yMm, ballCoordinates.Timestamp);
            expected.Vector = new Vector2D();

            BallCoordinates actual = _testAsset.MmToPts(ballCoordinates);

            Assert.AreEqual(actual.X, expected.X);
            Assert.AreEqual(actual.Y, expected.Y);
            Assert.AreEqual(actual.Vector.IsDefined, expected.Vector.IsDefined);
        }
示例#43
0
        /// <summary>
        /// Ricochet coordinate calculation
        /// </summary>
        /// <param name="ballCoordinates">Ball Coordinates</param>
        /// <returns>Ricochet Ball Coordinates</returns>
        public BallCoordinates Ricochet(BallCoordinates ballCoordinates)
        {
            try
            {
                Coordinates2D intersectionPoint = FindNearestIntersectionPoint(ballCoordinates);

                DateTime ricocheTime = FindRicochetTime(ballCoordinates, intersectionPoint);

                Vector2D vector = FindIntersectionVector(ballCoordinates.Vector, intersectionPoint);

                BallCoordinates coordinates = new BallCoordinates(
                        Convert.ToInt32(intersectionPoint.X),
                        Convert.ToInt32(intersectionPoint.Y), ricocheTime);
                coordinates.Vector = vector;

                return coordinates;
            }
            catch (Exception e)
            {
                throw new NotSupportedException(String.Format(
                    "[{0}] Failed to find ricochet coordinates. Reason: {1}",
                        MethodBase.GetCurrentMethod().Name, e.Message));
            }
        }
示例#44
0
        /// <summary>
        /// Find nearest intersection point with table borders based on
        /// - given ball coordinates and vector
        /// </summary>
        /// <param name="ballCoordinates">Defined coordinates with defined vector</param>
        /// <returns>Coordinates of intersection with border</returns>
        public Coordinates2D FindNearestIntersectionPoint(BallCoordinates ballCoordinates)
        {
            //verify we can proceed to calculate intersection
            VerifyBallCoordinatesAndVectorInput(ballCoordinates);

            Dictionary<Vector2D, Coordinates2D> borderIntersection = new Dictionary<Vector2D, Coordinates2D>();
            List<Vector2D> vectors = new List<Vector2D>();

            //get line slope
            double m = CalculateLineSlope(ballCoordinates.Vector);

            if (ballCoordinates.Vector.X != 0)
            {
                double yb = CalculateY2OnLine(m, ballCoordinates.X, ballCoordinates.Y, MinBorderX);
                double yc = CalculateY2OnLine(m, ballCoordinates.X, ballCoordinates.Y, MaxBorderX);

                Coordinates2D B = new Coordinates2D(MinBorderX, yb);
                Vector2D vB = new Vector2D(B.X - ballCoordinates.X, B.Y - ballCoordinates.Y);
                vectors.Add(vB);
                borderIntersection.Add(vB, B); //B

                Coordinates2D C = new Coordinates2D(MaxBorderX, yc);
                Vector2D vC = new Vector2D(C.X - ballCoordinates.X, C.Y - ballCoordinates.Y);
                vectors.Add(vC);
                borderIntersection.Add(vC, C); //C
            }

            if (ballCoordinates.Vector.Y != 0)
            {
                double xa = CalculateX2OnLine(m, ballCoordinates.X, ballCoordinates.Y, MinBorderY);
                double xd = CalculateX2OnLine(m, ballCoordinates.X, ballCoordinates.Y, MaxBorderY);

                Coordinates2D A = new Coordinates2D(xa, MinBorderY);
                Vector2D vA = new Vector2D(A.X - ballCoordinates.X, A.Y - ballCoordinates.Y);
                vectors.Add(vA);
                borderIntersection.Add(vA, A); //A

                Coordinates2D D = new Coordinates2D(xd, MaxBorderY);
                Vector2D vD = new Vector2D(D.X - ballCoordinates.X, D.Y - ballCoordinates.Y);
                vectors.Add(vD);
                borderIntersection.Add(vD, D); //D
            }

            //remove points from wrong direction
            foreach (Vector2D vector in vectors)
            {
                double direction = vector.ScalarProduct(ballCoordinates.Vector)
                    / (vector.Velocity() * ballCoordinates.Vector.Velocity());
                if (Math.Round(direction, 0) != 1)
                    borderIntersection.Remove(vector);
            }

            //if no points found => Error, consider adding error rate threshold
            if (borderIntersection.Count < 1)
                Log.Print("No vectors found!", eCategory.Error, LogTag.VECTOR);

            //get nearest point
            Coordinates2D intersectionPoint = null;
            double minDistance = MaxBorderX * MaxBorderY;
            foreach (Coordinates2D intersection in borderIntersection.Values)
            {
                double dist = intersection.Distance(ballCoordinates);
                if (dist < minDistance)
                {
                    minDistance = dist;
                    intersectionPoint = intersection;
                }
            }

            return intersectionPoint;
        }
示例#45
0
        /// <summary>
        /// Main Decision Flow Method decides on action and sets property of responding player
        /// </summary>
        /// <param name="rod">Rod to use for decision</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <returns>Rod Action to perform</returns>
        public override RodAction Decide(IRod rod, BallCoordinates bfc)
        {
            RodAction action = new RodAction(rod.RodType);

            //Action will be ignored if not enough time passed since last request was made inside sector
            if (!IgnoreDecision(rod.RodType))
            {
                //Get relative Y position and set Responding Player
                eYPositionPlayerRelative relativeY = BallYPositionToPlayerYCoordinate(bfc.Y, rod);

                //Get relative X position
                eXPositionRodRelative relativeX = BallXPositionToRodXPosition(bfc.X, rod);

                /*
                 * Beta Version of inner DECISION TREE
                 */
                switch (relativeX)
                {
                    case eXPositionRodRelative.FRONT:
                        switch (relativeY)
                        {
                            case eYPositionPlayerRelative.RIGHT:
                            case eYPositionPlayerRelative.LEFT:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                    case eRotationalMove.DEFENCE:
                                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.BALL_Y);
                                        break;
                                    case eRotationalMove.KICK:
                                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.NA);
                                        break;
                                }
                                break;
                            case eYPositionPlayerRelative.CENTER:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                    case eRotationalMove.DEFENCE:
                                        action = new RodAction(rod.RodType, eRotationalMove.KICK, eLinearMove.NA);
                                        break;
                                    case eRotationalMove.KICK:
                                        if (_helper.IsEnoughSpaceToMove(rod, rod.State.DcPosition, BALL_RADIUS))
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.RIGHT_BALL_DIAMETER);
                                        }
                                        else
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.LEFT_BALL_DIAMETER);
                                        }
                                        break;
                                }
                                break;
                        }
                        break;
                    case eXPositionRodRelative.CENTER:
                    case eXPositionRodRelative.BACK:
                        switch (relativeY)
                        {
                            case eYPositionPlayerRelative.RIGHT:
                            case eYPositionPlayerRelative.LEFT:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                        action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.BALL_Y);
                                        break;
                                    case eRotationalMove.DEFENCE:
                                        action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.NA);
                                        break;
                                    case eRotationalMove.KICK:
                                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.NA);
                                        break;
                                }
                                break;
                            case eYPositionPlayerRelative.CENTER:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                        action = new RodAction(rod.RodType, eRotationalMove.KICK, eLinearMove.NA);
                                        break;
                                    case eRotationalMove.DEFENCE:
                                    case eRotationalMove.KICK:
                                        if (_helper.IsEnoughSpaceToMove(rod, rod.State.DcPosition, BALL_RADIUS))
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.RIGHT_BALL_DIAMETER);
                                        }
                                        else
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.LEFT_BALL_DIAMETER);
                                        }
                                        break;
                                }
                                break;
                        }
                        break;
                }
                Log.Print(String.Format("Defined action for {0}: [{1}] [{2}]", rod.RodType, action.Rotation, action.Linear),
                    eCategory.Info, LogTag.DECISION);
                ActivateDelay(action);

                //Define actual desired rod coordinate to move to
                int startStopperDesiredY = CalculateNewRodCoordinate(rod, RespondingPlayer, bfc, action.Linear);
                action.DcCoordinate = rod.NearestPossibleDcPosition(startStopperDesiredY);
            }
            else
            {
                Log.Print(String.Format("Ignoring inner tree of {0} for {1} milliseconds", rod.RodType,
                    (ACTION_DELAY - _sectorWatch[rod.RodType].Elapsed).TotalMilliseconds), eCategory.Debug, LogTag.DECISION);
            }

            //Set last decided rod and player coordinates if it was defined
            if (action.Linear!=eLinearMove.NA) rod.State.DcPosition = action.DcCoordinate;
            if (_helper.ShouldSetServoStateFromTree(rod.RodType))
                if (action.Rotation != eRotationalMove.NA) rod.State.ServoPosition = action.Rotation;

            return action;
        }
示例#46
0
 public void MmToPts_Coordinates_Not_Defined()
 {
     BallCoordinates expected = new BallCoordinates(DateTime.Now);
     BallCoordinates actual = _testAsset.MmToPts(expected);
     Assert.AreEqual(actual, expected);
 }
示例#47
0
        public void MmToPts__Vector_And_Coordinates()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(50, 50, DateTime.Now);
            ballCoordinates.Vector = new Vector2D(100, 100);

            int xMm = ballCoordinates.X * X_MAX_PTS / X_MAX_MM;
            int yMm = ballCoordinates.Y * Y_MAX_PTS / Y_MAX_MM;

            double xMmVector = ballCoordinates.Vector.X * (double)X_MAX_PTS / (double)X_MAX_MM;
            double yMmVector = ballCoordinates.Vector.Y * (double)Y_MAX_PTS / (double)Y_MAX_MM;

            BallCoordinates expected = new BallCoordinates(xMm, yMm, ballCoordinates.Timestamp);
            expected.Vector = new Vector2D(xMmVector, yMmVector);

            BallCoordinates actual = _testAsset.MmToPts(ballCoordinates);

            Assert.AreEqual(actual.X, expected.X);
            Assert.AreEqual(actual.Y, expected.Y);
            Assert.AreEqual(actual.Vector.X, expected.Vector.X);
            Assert.AreEqual(actual.Vector.Y, expected.Vector.Y);
        }
示例#48
0
 public void Ricochet_ZeroVelocity()
 {
     _initialCoordinates = new BallCoordinates(10, 10, DateTime.Now);
     _initialCoordinates.Vector = new Vector2D(0, 0);
     _testAsset.Ricochet(_initialCoordinates);
 }
示例#49
0
        public void FindNearestIntersectionPoint_MoveDown_from_100_50()
        {
            _initialCoordinates = new BallCoordinates(100, 50, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(0, -100);

            Coordinates2D actualResult = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
            Coordinates2D expectedResult = new Coordinates2D(100, YMIN);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
        }
示例#50
0
 public void FindRicochetTime_Vector_minus140_minus20()
 {
     DateTime now = DateTime.Now;
     Coordinates2D intersection = new Coordinates2D(XMIN, 200);
     BallCoordinates ballCoordinates = new BallCoordinates(700, 300, now);
     ballCoordinates.Vector = new Vector2D(-140, -20);
     DateTime actualTime = _testAsset.FindRicochetTime(ballCoordinates, intersection);
     DateTime expected = now + TimeSpan.FromSeconds(5.0);
     Assert.AreEqual(expected, actualTime);
 }
示例#51
0
        /// <summary>
        /// Find intersection time based on ball coordinates, timestamp, vector and intersection point.
        /// </summary>
        /// <param name="ballCoordinates">Ball coordinates before intersection with border</param>
        /// <param name="intersection">Intersection with border point</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown in case calculated intersection time is too big</exception>
        /// <exception cref="NotSupportedException">Thrown in case intersection coordinates undefined.</exception>
        /// <returns>Intersection timestamp</returns>
        public DateTime FindRicochetTime(BallCoordinates ballCoordinates, Coordinates2D intersection)
        {
            VerifyBallCoordinatesAndVectorInput(ballCoordinates);

            if (intersection == null || !intersection.IsDefined)
                throw new NotSupportedException(String.Format("[{0}] Intersection coordinates undefined!", MethodBase.GetCurrentMethod().Name));

            double distance = ballCoordinates.Distance(intersection);
            double velocity = ballCoordinates.Vector.Velocity();
            double deltaT = distance / velocity;
            return ballCoordinates.Timestamp + TimeSpan.FromSeconds(deltaT);
        }
示例#52
0
        public void Ricochet_FromCoord100_50_SpeedMinus100_0()
        {
            DateTime initTime = DateTime.Now;
            _initialCoordinates = new BallCoordinates(100, 50, initTime);
            _initialCoordinates.Vector = new Vector2D(-100, 0);

            DateTime expectedTime = initTime + TimeSpan.FromSeconds(1);
            BallCoordinates expectedResult = new BallCoordinates(XMIN, 50, expectedTime);
            expectedResult.Vector = new Vector2D(100 * RICOCHE, 0);

            BallCoordinates actualResult = _testAsset.Ricochet(_initialCoordinates);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
            Assert.AreEqual(expectedResult.Timestamp, actualResult.Timestamp);
            Assert.AreEqual(expectedResult.Vector.X, actualResult.Vector.X);
            Assert.AreEqual(expectedResult.Vector.Y, actualResult.Vector.Y);
        }
示例#53
0
        public void FindNearestIntersectionPoint_MoveLeftUp_UpFirst_from_700_100()
        {
            _initialCoordinates = new BallCoordinates(700, 100, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(-100, 50);

            Coordinates2D actualResult = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
            Coordinates2D expectedResult = new Coordinates2D(100, YMAX);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
        }
示例#54
0
        public void MmToPts_Coordinates_Only()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(50, 50, DateTime.Now);

            int xMm = ballCoordinates.X * X_MAX_PTS / X_MAX_MM;
            int yMm = ballCoordinates.Y * Y_MAX_PTS / Y_MAX_MM;

            BallCoordinates expected = new BallCoordinates(xMm, yMm, ballCoordinates.Timestamp);
            BallCoordinates actual = _testAsset.MmToPts(ballCoordinates);

            Assert.AreEqual(actual.X, expected.X);
            Assert.AreEqual(actual.Y, expected.Y);
        }
示例#55
0
        /// <summary>
        /// Decide on action to be taken for each rod
        /// </summary>
        /// <param name="currentCoordinates">Current ball coordinates and vector</param>
        /// <returns>List of actions per each rod</returns>
        public List<RodAction> Decide(BallCoordinates currentCoordinates)
        {
            if (!IsInitialized) Initialize();

            if (currentCoordinates == null)
                throw new ArgumentException(String.Format("[{0}] Coordinates received from vector calculation unit are null",
                    MethodBase.GetCurrentMethod().Name));

            //Convert pts and pts/sec to mm and mm/sec
            currentCoordinates = _surveyor.PtsToMm(currentCoordinates);

            //Calculate Actual Possible Action Time
            DateTime timeOfAction = DateTime.Now + SystemDelays;

            //Calculate ball future coordinates
            BallCoordinates bfc = _predictor.FindBallFutureCoordinates(currentCoordinates, timeOfAction);

            List<RodAction> actions = new List<RodAction>();

            foreach(IRod rod in _controlledRods)
            {
                //Calculate dynamic sectors
                rod.CalculateDynamicSector(currentCoordinates);

                //Draw dynamic sector, better to use on one rod at a time because together is chaos on the screen
                Marks.DrawSector(rod.RodType, rod.DynamicSector);
                
                //Calculate intersection point 
                rod.CalculateSectorIntersection(bfc);
                //Decide on action
                RodAction action = _decisionTree.Decide(rod, bfc);
                actions.Add(action);
                
                Marks.DrawRodPlayers(rod.RodType, rod.State.DcPosition,
                    rod.State.ServoPosition);
            }
            return actions;
        }
示例#56
0
        public void FindNearestIntersectionPoint_MoveRight_from_50_100()
        {
            _initialCoordinates = new BallCoordinates(50, 100, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(100, 0);

            Coordinates2D actualResult = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
            Coordinates2D expectedResult = new Coordinates2D(XMAX, 100);

            Assert.AreEqual(expectedResult.X, actualResult.X);
            Assert.AreEqual(expectedResult.Y, actualResult.Y);
        }
示例#57
0
        public void FindNearestIntersectionPoint_NoMove_from_50_50()
        {
            _initialCoordinates = new BallCoordinates(50, 50, DateTime.Now);
            _initialCoordinates.Vector = new Vector2D(0, 0);

            Coordinates2D actualResult = _testAsset.FindNearestIntersectionPoint(_initialCoordinates);
        }
示例#58
0
 public void FindRicochetTime_Vector_100_50()
 {
     DateTime now = DateTime.Now;
     Coordinates2D intersection = new Coordinates2D(XMAX, 350);
     BallCoordinates ballCoordinates = new BallCoordinates(700, 300, now);
     ballCoordinates.Vector = new Vector2D(100, 50);
     DateTime actualTime = _testAsset.FindRicochetTime(ballCoordinates, intersection);
     DateTime expected = now + TimeSpan.FromSeconds(1.0);
     Assert.AreEqual(expected, actualTime);
 }
示例#59
0
        public void PtsToMm_Vector_Null()
        {
            BallCoordinates ballCoordinates = new BallCoordinates(50, 50, DateTime.Now);

            int xMm = ballCoordinates.X * X_MAX_MM / X_MAX_PTS;
            int yMm = ballCoordinates.Y * Y_MAX_MM / Y_MAX_PTS;

            BallCoordinates expected = new BallCoordinates(xMm, yMm, ballCoordinates.Timestamp);
            expected.Vector = null;

            BallCoordinates actual = _testAsset.PtsToMm(ballCoordinates);

            Assert.AreEqual(actual.X, expected.X);
            Assert.AreEqual(actual.Y, expected.Y);
            Assert.AreEqual(actual.Vector, expected.Vector);
        }
示例#60
0
        /// <summary>
        /// Verify coordinates and vector are defined, not null and not both vector x and y are 0
        /// </summary>
        /// <param name="ballCoordinates">Ball Coordianates with vector</param>
        /// <exception cref="NotSupportedException">Thrown in case vector or coordinates are not defined or are NULL, or both vector x and y are 0</exception>
        private void VerifyBallCoordinatesAndVectorInput(BallCoordinates ballCoordinates)
        {
            if (ballCoordinates == null)
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because ball coordinates are NULL", MethodBase.GetCurrentMethod().Name));

            if (!ballCoordinates.IsDefined)
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because ball coordinates are not defined", MethodBase.GetCurrentMethod().Name));

            if (ballCoordinates.Vector == null)
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because vector is NULL", MethodBase.GetCurrentMethod().Name));

            if (!ballCoordinates.Vector.IsDefined)
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because vector is undefined", MethodBase.GetCurrentMethod().Name));

            if (ballCoordinates.Vector.X == 0 && ballCoordinates.Vector.Y == 0)
                throw new NotSupportedException(String.Format("[{0}] Intersection point can not be found because vector is 0x0", MethodBase.GetCurrentMethod().Name));
        }