コード例 #1
0
        // Could go off angle, but left as X coordinate for now
        private DriveCommand DriveTowardBall(TennisBall ball)
        {
            // Not within required distance
            float ballX = ball.CenterPoint.X;

            if (ballX < leftThreshold)  // TODO look into this for dynamic video sizes. ie. be able to account for 1080, 720, etc.
            {
                // Ball to left
                return(DriveCommand.LeftTurn(Speed.VISION));
            }
            else if (ballX > rightThreshold)
            {
                // Ball to right
                return(DriveCommand.RightTurn(Speed.VISION));
            }
            else
            {
                // Ball straight ahead
                return(DriveCommand.Straight(Speed.VISION));
            }
        }
コード例 #2
0
        public DriveCommand FindNextDriveCommand()
        {
            short ascentHeading = AscentPacketHandler.Compass;

            if (this.isAligningToHeading)
            {
                // Turn toward heading
                // Scan, use heading as reference

                GPS    ascent        = AscentPacketHandler.GPSData;
                double headingToGate = ascent.GetHeadingTo(this.gate);

                Console.Write("Scan aligning toward heading | compass: "******" | Heading to gate: " + headingToGate + " | ");



                // Have reached heading. Start turning right
                if (IMU.IsHeadingWithinThreshold(ascentHeading, headingToGate, HEADING_THRESHOLD))
                {
                    this.isAligningToHeading = false;

                    // If driving for a certain duration
                    if (driveTowardHeadingForMillis > 0)
                    {
                        // Drive straight for a duration
                        this.isDrivingStraightForDuration = true;
                        this.driveStraightUntilMillis     = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + this.driveTowardHeadingForMillis;

                        return(DriveCommand.Straight(Speed.VISION_SCAN));
                    }
                    else
                    {
                        // Start scan
                        this.isScanning          = true;
                        scanStartHeading         = ascentHeading;
                        scanStartTimestampMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

                        return(DriveCommand.RightTurn(Speed.VISION_SCAN));
                    }
                }

                // Turn toward heading angle
                if (ascentHeading < ((headingToGate + 180) % 360) && ascentHeading > headingToGate)
                {
                    return(DriveCommand.LeftTurn(Speed.VISION_SCAN));
                }
                else
                {
                    return(DriveCommand.RightTurn(Speed.VISION_SCAN));
                }
            }
            else if (this.isDrivingStraightForDuration)
            {
                if (this.driveStraightUntilMillis > DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
                {
                    // Drive straight for duration
                    return(DriveCommand.Straight(Speed.VISION_SCAN));
                }
                else
                {
                    // Start scan
                    this.isDrivingStraightForDuration = false;

                    this.isScanning          = true;
                    scanStartHeading         = ascentHeading;
                    scanStartTimestampMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

                    return(DriveCommand.RightTurn(Speed.VISION_SCAN));
                }
            }
            else
            {
                // Scan
                // ... more to do for this case
                Console.Write("Scan scanning | ");

                // Increment deltaTheta accordingly
                deltaTheta = (ascentHeading - scanStartHeading + 360) % 360;

                Console.Write("Scan scanning | compass: "******" | deltaTheta: " + deltaTheta + " | ");

                if (deltaTheta > 330 && (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() > scanStartTimestampMillis + 2000))
                {
                    // Use boolean incase of wrap around to 0 due to mod
                    isScanNearlyComplete = true;
                }

                return(DriveCommand.RightTurn(Speed.VISION_SCAN));
            }
        }
コード例 #3
0
        private DriveCommand DriveNoBallDetected(TennisBall ball)
        {
            // Sanity check
            if (ball != null)
            {
                return(null);
            }


            Console.Write("Ball not detected | ");

            // Clear verification queue if it has values
            this.verificationQueue.Clear();

            GPS    ascent         = AscentPacketHandler.GPSData;
            double distanceToGate = ascent.GetDistanceTo(this.gate);

            // Kick back to GPS
            if (distanceToGate > DISTANCE_SWITCH_TO_GPS)    // 6 meters
            {
                Console.WriteLine("Distance: " + distanceToGate + ". Switch to GPS");

                switchToGPS = true;
                return(DriveCommand.Straight(Speed.HALT));
            }

            // Turn to face heading, drive toward it
            if (distanceToGate > DISTANCE_USE_HEADING)      // 3 meters
            {
                Console.WriteLine("Distance: " + distanceToGate + ". Turning toward heading to drive towrad it");

                short  ascentHeading = AscentPacketHandler.Compass;
                double headingToGate = ascent.GetHeadingTo(this.gate);

                Console.Write("currCompass: "******" | headingToGoal: " + headingToGate + " | distance: " + distanceToGate + " | ");

                // Aligned with heading. Start going straight
                if (IMU.IsHeadingWithinThreshold(ascentHeading, headingToGate, Scan.HEADING_THRESHOLD))
                {
                    return(DriveCommand.Straight(Speed.VISION));
                }

                // Turn toward gate heading angle
                if (IMU.IsHeadingWithinThreshold(ascentHeading, (headingToGate + 90) % 360, 90))
                {
                    return(DriveCommand.LeftTurn(Speed.VISION_SCAN));
                }
                else
                {
                    return(DriveCommand.RightTurn(Speed.VISION_SCAN));
                }

                // Probably would work, kept as reference

                /*
                 * double lowBound = headingToGate;
                 * double highBound = (headingToGate + 180) % 360;
                 *
                 * if (lowBound < highBound)
                 * {
                 *  if (lowBound < ascentHeading && ascentHeading < highBound)
                 *  {
                 *      return DriveCommand.LeftTurn(DriveCommand.SPEED_VISION_SCAN);
                 *  }
                 *  else
                 *  {
                 *      return DriveCommand.RightTurn(DriveCommand.SPEED_VISION_SCAN);
                 *  }
                 * }
                 * else
                 * {
                 *  if (!(highBound < ascentHeading && ascentHeading < lowBound))
                 *  {
                 *      return DriveCommand.LeftTurn(DriveCommand.SPEED_VISION_SCAN);
                 *  }
                 *  else
                 *  {
                 *      return DriveCommand.RightTurn(DriveCommand.SPEED_VISION_SCAN);
                 *  }
                 * }
                 */
            }

            // If scanning, complete scan
            if (this.scan != null)
            {
                Console.WriteLine("Scanning... Distance: " + distanceToGate);

                if (!this.scan.IsComplete())
                {
                    return(scan.FindNextDriveCommand());
                }
                else
                {
                    this.completedScans++;

                    // Clear scan, will rescan below
                    this.scan = null;
                }
            }

            switch (this.completedScans)
            {
            case 0:
            {
                // Initialize the first scan
                if (distanceToGate > DISTANCE_CLOSE_RANGE)          // 2 meters
                {
                    // Turn toward heading. Scan, use heading as reference
                    StatusHandler.SendDebugAIPacket(Status.AIS_BEGIN_SCAN, "Scan: Using heading as reference. Distance: " + Math.Round(distanceToGate, 2));
                    Console.WriteLine("Scan: Using heading as reference. Distance: " + Math.Round(distanceToGate, 2));

                    this.scan = new Scan(this.gate, true);
                }
                else
                {
                    // Scan
                    StatusHandler.SendDebugAIPacket(Status.AIS_BEGIN_SCAN, "Scan: Not using heading as reference. Distance: " + Math.Round(distanceToGate, 2));
                    Console.WriteLine("Scan: Not using heading as reference. Distance: " + Math.Round(distanceToGate, 2));

                    this.scan = new Scan(this.gate, false);
                }

                break;
            }

            case 1:
            {
                // Align toward heading, drive for 10ish seconds,
                StatusHandler.SendDebugAIPacket(Status.AIS_BEGIN_SCAN, "Scan: 1st 10s scan toward heading. Distance: " + Math.Round(distanceToGate, 2));
                Console.WriteLine("Scan: Distance: " + Math.Round(distanceToGate, 2) + ". Scanning (using heading). Driving 5m away...");

                this.scan = new Scan(this.gate, SCAN_DRIVE_STRAIGHT_DURATION_MILLIS);

                break;
            }

            /*
             * case 2:
             * {
             *  // Broaden HSV values, scan
             *  StatusHandler.SendDebugAIPacket(Status.AIS_BEGIN_SCAN, "Scan: Broadening HSV values. Distance: " + Math.Round(distanceToGate, 2));
             *  Console.WriteLine("Scan: Broadening HSV values. Distance: " + Math.Round(distanceToGate, 2));
             *
             *  this.camera.BroadenHsvValues();
             *
             *  this.scan = new Scan(this.gate, false);
             *
             *  break;
             * }
             */
            case 2:
            {
                // Align toward heading (again), drive for 5ish seconds,
                StatusHandler.SendDebugAIPacket(Status.AIS_BEGIN_SCAN, "Scan: 2nd 5m scan toward heading. Distance: " + Math.Round(distanceToGate, 2));
                Console.WriteLine("Scan: 2nd 5m scan toward heading. Distance: " + Math.Round(distanceToGate, 2));

                this.scan = new Scan(this.gate, SCAN_DRIVE_STRAIGHT_DURATION_MILLIS);

                break;
            }

            case 3:
            {
                // We've already run 1 scan, 1 5m scan, 1 broaden HSV, 1 more 5m scan, so drive straight to kick back to GPS and do it over again
                return(DriveCommand.Straight(Speed.VISION));
            }

            default:
            {
                break;
            }
            }

            return(scan.FindNextDriveCommand());
        }
コード例 #4
0
        /// <summary>
        /// Find the next DriveCommand to be issued to ROCKS.
        /// </summary>
        /// <returns>DriveCommand - the next drive command for ROCKS to execute.</returns>
        public DriveCommand FindNextDriveCommand()
        {
            GPS    currGPS        = AscentPacketHandler.GPSData;
            short  currCompass    = AscentPacketHandler.Compass;
            double idealDirection = currGPS.GetHeadingTo(gate);
            double distance       = AscentPacketHandler.GPSData.GetDistanceTo(gate);

            // Add distance to averaging queue
            while (this.averagingQueue.Count >= AVERAGING_QUEUE_CAPACITY)
            {
                double value;
                this.averagingQueue.TryDequeue(out value);
            }
            this.averagingQueue.Enqueue(distance);

            // Debugging - delete
            Console.Write("currCompass: "******" | headingToGoal: " + idealDirection + " | distance: " + distance + " | ");

            // Stop when within proximity to see if average distance of last 5 distances is within proximity.
            // If so, wait to switch to Vision, otherwise this acts as a buffer.
            if (distance <= GATE_PROXIMITY)
            {
                return(DriveCommand.Straight(Speed.HALT));
            }

            // If current heading within threshold, go straight
            if (IMU.IsHeadingWithinThreshold(currCompass, idealDirection, THRESHOLD_HEADING_ANGLE))
            {
                return(DriveCommand.Straight(Speed.SLOW_OPERATION));
            }

            // not aligned with endGPS point, need to turn
            // the math here is strange due to compass vs unit circle stuff
            // the first case takes care of all time when the ideal direction is in some way east of us,
            // and the second case takes care of all time when the ideal direction is in some way west of us
            double opposite = (idealDirection + 180) % 360;

            if (idealDirection < opposite)
            {
                // Modulo not necessary - ideal direction < 180
                if (currCompass > idealDirection && currCompass < opposite)
                {
                    // Turn left
                    return(DriveCommand.LeftTurn(Speed.SLOW_TURN));
                }
                else
                {
                    // Turn right
                    return(DriveCommand.RightTurn(Speed.SLOW_TURN));
                }
            }
            else
            {
                // Modulo necessary
                if ((currCompass > idealDirection && currCompass < 360) || (currCompass >= 0 && currCompass < opposite))
                {
                    // Turn left
                    return(DriveCommand.LeftTurn(Speed.SLOW_TURN));
                }
                else
                {
                    // Turn right
                    return(DriveCommand.RightTurn(Speed.SLOW_TURN));
                }
            }
        }