Ejemplo n.º 1
0
def selectKickInLeftEdge():
    selfH2BallH = hMath.normalizeAngle_0_360(selfH + ballH)
    ballH2TGoalH = hMath.getHeadingBetween(ballX,ballY,\
                                           Constant.TARGET_GOAL_X,Constant.TARGET_GOAL_Y)
    selfH2TGoalH = hMath.normalizeAngle_180(selfH2BallH - ballH2TGoalH)

    ballH2CenterH = hMath.getHeadingBetween(ballX,ballY,\
                                            Constant.FIELD_WIDTH/2.0,ballY+200)
    selfH2CenterH = hMath.normalizeAngle_180(selfH2BallH - ballH2CenterH)

    # We are safe to do something...
    if 0 <= selfH2BallH <= 135:
        #
        if 45 <= abs(selfH2TGoalH) <= 60:
            if selfH2TGoalH > 0:
                return (KT_UPENN_LEFT, ballH2TGoalH, Constant.dAUTO)
            else:
                return (KT_UPENN_RIGHT, ballH2TGoalH, Constant.dAUTO)
        #
        else:
            return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    # Otherwise, if we just approach, the ball might go out.
    # Hence, get-around-the-ball action.
    else:
        return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)
Ejemplo n.º 2
0
def shouldIWirelessBackOff():
    global gBackOffType

    BALL_DISTANCE = 50

    ## If you receive wireless information of mate being closer to the
    ## ball than you and you are behind him
    selfX, selfY = Global.selfLoc.getX(), Global.selfLoc.getY()
    for i in range(Constant.NUM_TEAM_MEMBER):
        mate = Global.teamPlayers[i]
        if i != Global.myPlayerNum - 1\
            and mate.isValid()\
            and not mate.isGoalie()\
            and mate.hasSeenBall()\
            and Global.ballD > mate.getBallDist()\
            and mate.getBallDist() < BALL_DISTANCE:
            #and Global.ballD < BALL_DISTANCE + 5

            mateX, mateY = Global.teammatesLoc[i].getX(
            ), Global.teammatesLoc[i].getY()

            ## Compare headings of yourself and your mate from the
            ## ball to tell whether you two are near by.
            selfH2ball = hMath.normalizeAngle_0_360(\
                            hMath.getHeadingBetween(Global.ballX,Global.ballY,selfX,selfY))
            mateH2ball = hMath.normalizeAngle_0_360(\
                            hMath.getHeadingBetween(Global.ballX,Global.ballY,mateX,mateY))

            selfD2mate = hMath.getDistanceBetween(selfX, selfY, mateX, mateY)

            if abs(selfH2ball - mateH2ball) < 50:

                if selfD2mate < 5\
                    and i > Global.myPlayerNum - 1:
                    return True

                elif selfD2mate < 20:
                    gBackOffType = SIDE_BACKOFF
                    if Debug.backOffTriggerDebug:
                        print "shouldIWirelessBackOff(): True, Side backoff"
                    return True

            if abs(selfH2ball - mateH2ball) < 70:

                if selfD2mate < 5\
                    and i > Global.myPlayerNum - 1:
                    return True

                elif selfD2mate < 30:
                    gBackOffType = FACE_BACKOFF
                    if Debug.backOffTriggerDebug:
                        print "shouldIWirelessBackOff(): True, Face backoff"
                    return True

    return False
Ejemplo n.º 3
0
def getOutOfTheCircle(centerX, centerY, targetH, doForce=False, radius=40):
    selfX, selfY = Global.selfLoc.getPos()
    dist = hMath.getDistanceBetween(centerX, centerY, selfX, selfY)
    heading = hMath.getHeadingBetween(centerX, centerY, selfX, selfY)

    if amIInTheCircle(centerX,centerY,radius)\
        or doForce:

        if dist > radius:
            relX = dist * 2 * math.cos(hMath.DEG2RAD(heading))
            relY = dist * 2 * math.sin(hMath.DEG2RAD(heading))

        else:
            relX = radius * 2 * math.cos(hMath.DEG2RAD(heading))
            relY = radius * 2 * math.sin(hMath.DEG2RAD(heading))

        destX = centerX + relX
        destY = centerY + relY

        hTrack.saGoToTargetFacingHeading(destX, destY, targetH)

        Indicator.showFacePattern([0, 2, 0, 2, 0])
        return Constant.STATE_EXECUTING

    return Constant.STATE_SUCCESS
Ejemplo n.º 4
0
def perform():
    global gLastFrameCalled
    global gDirection
    global gNoGetBehindCounter

    if gLastFrameCalled != Global.frame - 1:
        resetPerform()
    gLastFrameCalled = Global.frame

    gNoGetBehindCounter = max(gNoGetBehindCounter - 1, 0)

    selfLoc = Global.selfLoc
    selfX, selfY = selfLoc.getPos()
    selfH = selfLoc.getHeading()

    ballX, ballY = Global.ballX, Global.ballY
    ballD = Global.ballD
    ballH = Global.ballH

    selfH2BallH = selfH + ballH
    ballH2OGoalH = hMath.getHeadingBetween(ballX,ballY,\
                                           Constant.OWN_GOAL_X,Constant.OWN_GOAL_Y)
    selfH2OGoalH = hMath.normalizeAngle_180(selfH2BallH - ballH2OGoalH)

    selfH2SafeH = hMath.normalizeAngle_180(selfH2OGoalH + 180)

    if abs(selfH2OGoalH) > 110:
        resetPerform()
        return Constant.STATE_SUCCESS

    # If we are far away from the ball, then just use our implicit get behind.
    #if Global.ballD > 60:
    #    sFindBall.perform(doGetBehind = sFindBall.GET_BEHIND_LOTS)
    #    # Reset the direction.
    #    gDirection = None
    #    return Constant.STATE_EXECUTING

    # First time to enter the function, so choose the direction.
    if gDirection == None:
        # go left
        if selfH2OGoalH < 0:
            gDirection = Constant.dANTICLOCKWISE
        # go right
        else:
            gDirection = Constant.dCLOCKWISE

    if gNoGetBehindCounter > 0:
        sFindBall.perform(doGetBehind=sFindBall.GET_BEHIND_PRIORITY)

    else:
        sFindBall.perform(True)
        r = sGetBehindBall.performBall(dist=25,
                                       direction=gDirection,
                                       accuracy=10)
        if r == Constant.STATE_SUCCESS:
            sFindBall.perform(doGetBehind=sFindBall.GET_BEHIND_PRIORITY)
            gNoGetBehindCounter = NO_GET_BEHIND_DURATION

    return Constant.STATE_EXECUTING
Ejemplo n.º 5
0
def performToPosition(targetPos=(0, 0), minTimeToDribble=1500):
    global gForceToTargetGoal
    global gForceTimeElapse
    global targetPosition
    pos = Global.selfLoc.getPos()
    targetPosition = targetPos
    dkd = hMath.getHeadingBetween(pos[0], pos[1], targetPos[0], targetPos[1])
    performToDKD(dkd, minTimeToDribble)
Ejemplo n.º 6
0
def GetReadyGenerator():

    selfx = Global.selfLoc.getX() 
    selfy = Global.selfLoc.getY()
    selfh = hMath.normalizeAngle_180(Global.selfLoc.getHeading()) 
    centerx = Constant.FIELD_WIDTH / 2
    centery = Constant.FIELD_LENGTH / 2
    heading = hMath.getHeadingBetween(selfx,selfy,centerx,centery)
    
    # 1st quad
    if selfx <= centerx and selfy <= centery: 
        turn = heading - selfh                    
    # 2nd quad
    elif selfx <= centerx and selfy >= centery:  
        turn = heading + selfh 
    # 3rd quad
    elif selfx >= centerx and selfy <= centery: 
        turn = - heading + selfh 
    # 4th quad
    else: 
        turn = - heading - selfh
    
    print "Turn Angle is " + str(turn) + "   Heading is " + str(heading)
                                       
    period = turn / 30 * 8                                   
                                        
    for _ in range(period):
        sGrabWalk.Perform(0,0,30) 
        yield Constant.STATE_EXECUTING
        
    for _ in range(15):
        Action.kick(Action.DiveKickWT)
        yield Constant.STATE_EXECUTING 
    
    Action.forceStepComplete()
    
    i = 0     
    while 1:
        i += 1
        if Global.vBall.getConfidence() > 0:
            # Wait at least one second before checking this.. 
            # So that the ball goes somewhere far
            if i > 75\
               and Global.vBall.getDistance() < 60\
               and Global.haveBall > 5: 
                break    
            turn = hMath.CLIP(Global.vBall.getHeading(),20) 
            Action.walk(3,0,turn)
            hTrack.trackVisualBall()
        else: 
            Action.walk(3,0,5)
            hTrack.spinningLocalise()             
        yield Constant.STATE_EXECUTING
    
    while 1:
        yield Constant.STATE_SUCCESS    
Ejemplo n.º 7
0
def perform():
    global gObsToBall
    global selfX, selfY, selfH, ballX, ballY, ballD, ballH
    global gPerform, gPerformFrame

    if gPerformFrame == Global.frame:
        return gPerform

    selfX, selfY = Global.selfLoc.getPos()
    selfH = Global.selfLoc.getHeading()

    ballX = Global.ballX
    ballY = Global.ballY
    ballH = Global.ballH
    ballD = Global.ballD

    ballH2TGoalH = hMath.getHeadingBetween(ballX, ballY,\
                                           Constant.TARGET_GOAL_X,
                                           Constant.TARGET_GOAL_Y)

    # Special variable lighting challenge kick selection
    if Global.lightingChallenge:
        # In the rear of the field just kick the ball out - it will get replaced
        # at the centre circle
        if ballY < Constant.FIELD_LENGTH * 0.35:
            rtn = selectKickOut()
        elif ballY < Constant.FIELD_LENGTH * 0.55:
            rtn = (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)
        else:
            rtn = (KT_GRAB_DRIBBLE_GOAL, ballH2TGoalH, Constant.dAUTO)

    # Special penalty shooter kick selection
    elif Global.penaltyShot:
        if ballY < Constant.FIELD_LENGTH * 0.55:
            rtn = (KT_GRAB_DRIBBLE_STOP, ballH2TGoalH, Constant.dAUTO)
        else:
            return (KT_GRAB_DRIBBLE_GOAL, ballH2TGoalH, Constant.dAUTO)

    elif not sGrab.isGrabbed and Global.frame - gLastAvoidOwnGoalFrame < 5:
        rtn = (KT_AVOID_OWN_GOAL, ballH2TGoalH, Constant.dAUTO)

    # Usual attacker kick selection
    elif ballY < Constant.FIELD_LENGTH * 0.4:
        rtn = selectKickInDefensiveThird()

    elif ballY < Constant.FIELD_LENGTH * 0.6:
        rtn = selectKickInMiddleThird()

    else:
        rtn = selectKickInOffensiveThird()

    gPerform = rtn
    gPerformFrame = Global.frame
    return rtn
Ejemplo n.º 8
0
def timeToReachPoint(x, y, h, myX=None, myY=None, myH=None,\
                    doTurn=True, doDKD=True, doObs=True):
    if myX == None:
        myX = Global.selfLoc.getX()
        myY = Global.selfLoc.getY()
        myH = Global.selfLoc.getHeading()

    relH = hMath.getHeadingToMe(myX, myY, myH, x, y)
    absH = hMath.getHeadingBetween(myX, myY, x, y)
    (lX, lY) = hMath.getLocalCoordinate(myX, myY, myH, x, y)
    # 1. Estimate the straight line time to get there
    # 2. Add time to turn and face (or slow walk due to turning on the run)
    # 3. Add time to face desired heading when we arrive (or getBehind)
    # 4. Add time for obstacles if there are any in the way

    #    if (Global.frame % 10 == 0):
    #        print "dist:", hMath.getDistanceBetween(myX, myY, x, y) /EST_WALK_SPEED
    #        print "turn:", abs(relH) /EST_TURN_SPEED
    #        print "dkd:", abs(hMath.normalizeAngle_180(absH - h)) /EST_TURN_SPEED

    time = hMath.getDistanceBetween(myX, myY, x, y) / EST_WALK_SPEED
    if doTurn:
        time += abs(relH) / EST_TURN_SPEED
    if doDKD:
        # Time to turn to dkd when we get there is penalised more harshly
        time += (abs(hMath.normalizeAngle_180(absH - h)) /
                 EST_TURN_SPEED) * 1.3
    if doObs:
        nobs = VisionLink.getNoObstacleBetween(0, 0, int(lX), int(lY), 30, 30,
                                               0, Constant.OBS_USE_NONE)
        if nobs > 100:
            nobs = 50
        #if x == Global.ballX:
        #    print "Nobs=", nobs
        if nobs >= 5:
            # 10ms per obstacle point. A typical half-obstructed path might
            # count 60 obs -> 600ms. Max at nobs 100 -> 1 sec
            time += nobs * 10

    return int(time)
Ejemplo n.º 9
0
def selectKickInOffensiveThird():

    tGoalY = Constant.TARGET_GOAL_Y + 20

    # If the ball's y is somehow futher away than Constant.TARGET_GOAL_Y,
    # then hack the target goal y.
    if ballY > tGoalY:
        tGoalY = ballY + 50

    selfH2BallH = hMath.normalizeAngle_0_360(selfH + ballH)

    ballH2TGoalH = hMath.getHeadingBetween(ballX,ballY,\
                                           Constant.TARGET_GOAL_X,tGoalY)
    selfH2TGoalH = hMath.normalizeAngle_180(selfH2BallH - ballH2TGoalH)

    ballH2CrossingH = hMath.getHeadingBetween(ballX,ballY,\
                                              Constant.TARGET_GOAL_X,tGoalY-40)
    selfH2CrossingH = hMath.normalizeAngle_180(selfH2BallH - ballH2CrossingH)

    ballH2CenterH = hMath.getHeadingBetween(ballX,ballY,\
                                            Constant.FIELD_WIDTH/2.0,ballY+200)
    selfH2CenterH = hMath.normalizeAngle_180(selfH2BallH - ballH2CenterH)

    if sGrab.isGrabbed:
        if hWhere.ballInTriTLCorner()\
            or hWhere.ballInTriTRCorner():
            return (KT_GRAB_DRIBBLE, ballH2CrossingH, Constant.dAUTO)
        elif hWhere.ballOnLEdge(100)\
            or hWhere.ballOnREdge(100):
            return (KT_GRAB_DRIBBLE, ballH2CenterH, Constant.dAUTO)
        else:
            return (KT_GRAB_DRIBBLE_GOAL, ballH2TGoalH, Constant.dAUTO)

    # If we are stuck in offensive area, do something!!!
    # FIXME : smart strategy
    elif hStuck.gUseContestDetect and hStuck.isBallContested():
        dkd = ballH2TGoalH
        if hWhere.ballInTriTLCorner() or hWhere.ballInTriTRCorner():
            dkd = ballH2CrossingH
        selfH2dkd = hMath.normalizeAngle_180(selfH2BallH - dkd)

        if 40 <= abs(selfH2dkd) < 75:
            if selfH2dkd < 0:
                return (KT_UPENN_RIGHT, dkd, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, dkd, Constant.dAUTO)

        elif (ballD < sGrab.CLOSE_DIST or Global.frame - sGrab.gLastApproachFrame < 5)\
            and (hWhere.isOnLEdge(EDGE_DIST)
                or hWhere.isOnREdge(EDGE_DIST)
                or hWhere.ballInTriTLCorner()
                or hWhere.ballInTriTRCorner()
                or selfH >= 180):
            return (KT_GRAB_DRIBBLE, dkd, Constant.dAUTO)

        else:
            return (KT_DRIBBLE, dkd, Constant.dAUTO)

    # If the ball is in the corner, kick it across the field.
    elif hWhere.ballInTriTLCorner():
        if abs(selfH2CrossingH) < 10:
            return (KT_DRIBBLE, ballH2CrossingH, Constant.dAUTO)

        elif 45 <= abs(selfH2CrossingH) < 60:

            if selfH2CrossingH < 0:
                return (KT_UPENN_RIGHT, ballH2CrossingH, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, ballH2CrossingH, Constant.dAUTO)

        else:
            return (KT_GRAB_DRIBBLE, ballH2CrossingH, Constant.dAUTO)

        # If there's already a supporter waiting, then TURN KICK????

    # If the ball is in the left edge.
    elif hWhere.ballOnLEdge(100):
        if hStuck.isBallContested():
            return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)
        else:
            return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    # If the ball is in the corner, kick it across the field.
    elif hWhere.ballInTriTRCorner():
        if abs(selfH2CrossingH) < 10:
            return (KT_DRIBBLE, ballH2CrossingH, Constant.dAUTO)

        elif 45 <= abs(selfH2CrossingH) < 60:
            if selfH2CrossingH < 0:
                return (KT_UPENN_RIGHT, ballH2CrossingH, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, ballH2CrossingH, Constant.dAUTO)

        else:
            return (KT_GRAB_DRIBBLE, ballH2CrossingH, Constant.dAUTO)

            # If there's already a supporter waiting, then TURN KICK????

    # If the ball is in the right edge.
    elif hWhere.ballOnREdge(100):
        if hStuck.isBallContested():
            return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)
        else:
            return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    # If the ball is really close to the goal, dribble
    elif not sGrab.isGrabbed\
        and ballY > (Constant.FIELD_LENGTH - 30)\
        and ballX > (Constant.FIELD_WIDTH/2 - Constant.GOAL_WIDTH/2 + 15)\
        and ballX < (Constant.FIELD_WIDTH/2 + Constant.GOAL_WIDTH/2 - 15)\
        and abs(selfH2TGoalH) < 45:

        return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    # If the ball is really close to the goal, grab dribble into goal
    elif ballY > (Constant.FIELD_LENGTH - Constant.GOALBOX_DEPTH)\
        and ballX > (Constant.FIELD_WIDTH/2 - Constant.GOAL_WIDTH/2 - 50)\
        and ballX < (Constant.FIELD_WIDTH/2 + Constant.GOAL_WIDTH/2 + 50):

        return (KT_GRAB_DRIBBLE_GOAL, ballH2TGoalH, Constant.dAUTO)

    elif hStuck.isBallContested():
        if sGrab.isGrabbed:
            return (KT_GRAB_DRIBBLE_GOAL, ballH2TGoalH, Constant.dAUTO)
        elif abs(selfH2TGoalH) < 40:
            return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    # If the robot is a little far, then dribble
    elif ballY < Constant.FIELD_LENGTH * 0.65 and abs(selfH2TGoalH) < 15:
        return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    return (KT_GRAB_DRIBBLE_GOAL, ballH2TGoalH, Constant.dAUTO)
Ejemplo n.º 10
0
def perform(dkd = 90, side = None, bx = None, by = None):
    # This implementation is very similar to sGetBehindBall (based on 2003)
    # but the ball is on the bottom edge of the circle, not the centre.
    global onCircle

    if side != None:
        print "Warning: sGetBesideBall.perform: side is not yet implemented"

    if bx == None or by == None:
        (bx, by) = Global.gpsGlobalBall.getPos()
    (myx, myy) = Global.selfLoc.getPos()
    myh = Global.selfLoc.getHeading()

    # Determine the centre of the circle, which is CIRCLE_RADIUS towards
    # dkd from the ball. Global coords.
    cx = bx + math.cos(hMath.DEG2RAD(dkd)) * CIRCLE_RADIUS
    cy = by + math.sin(hMath.DEG2RAD(dkd)) * CIRCLE_RADIUS

    # If we are backward of the ball or really close just run at it
    ballRobotH = hMath.getHeadingToMe(bx, by, dkd, myx, myy)
    ballDSquared = hMath.getDistSquaredBetween(myx, myy, bx, by)
    if (abs(ballRobotH) > 90 or ballDSquared < hMath.SQUARE(20)):
        Indicator.showHeadColor(Indicator.RGB_PURPLE)
        ballH = hMath.getHeadingBetween(myx, myy, bx, by)
        hTrack.saGoToTargetFacingHeading(bx, by, ballH)
        return

    # Work out if we are left or right of the centre (relative to DKD as 0)
    robotH = hMath.getHeadingToMe(cx, cy, dkd, myx, myy)
    # FIXME: allow choice of direction
    if (robotH > 0):  # robot to the left
        #print "robot to left of ball",
        direction = Constant.dANTICLOCKWISE
    else:           # robot to the right
        #print "robot to right of ball",
        direction = Constant.dCLOCKWISE
    
    # The circling point can be calculated as looking from the centre
    # towards the robot at CIRCLE_DEGREES to the left/right, and distance
    # CIRCLE_RADIUS. CircleAng is from the centre facing the robot with
    # positive x at zero degrees.
    # There are two modes here. In the first we are well outside the and
    # running to make a tangent with the circle. In the second we are close
    # to or inside the circle and tracing the circumference
    centreDSquared = hMath.getDistSquaredBetween(myx, myy, cx, cy)
    if (centreDSquared > hMath.SQUARE(CIRCLE_RADIUS + 20)):
        #print "Outside circle, running to tangent"
        onCircle = False
        Indicator.showHeadColor(Indicator.RGB_GREEN)
        if direction == Constant.dANTICLOCKWISE:
            circleAng = 90 + CIRCLE_DEGREES
        else:
            circleAng = 90 - CIRCLE_DEGREES
        circleAng = hMath.normalizeAngle_180(circleAng)
    else:
        #print "On circle, tracing circumference"
        onCircle = True
        Indicator.showHeadColor(Indicator.RGB_YELLOW)
        if direction == Constant.dANTICLOCKWISE:
            circleAng = 110
        else:
            circleAng = 70
        
#    print "me", int(myx), int(myy), "ball", int(bx), int(by), \
#        "centre", int(cx), int(cy), "robotH", int(robotH),
    # relative to centre facing robot
    circleRelX = math.cos(hMath.DEG2RAD(circleAng)) * CIRCLE_RADIUS
    circleRelY = math.sin(hMath.DEG2RAD(circleAng)) * CIRCLE_RADIUS
    #print "circleAng", circleAng, "rel circle pos", circleRelX, circleRelY
    robotH = hMath.normalizeAngle_180(robotH + dkd) # now global
    (circleX, circleY) = hMath.getGlobalCoordinate(cx, cy, robotH, \
                                                    circleRelX, circleRelY)
#    print "gRobotH", robotH, "circle pos", int(circleX), int(circleY)
    # circleX/Y now is the global coords of the circle point, so walk there.

#    ballH = hMath.getHeadingBetween(myx, myy, bx, by)   # global
    
    if onCircle:
        # Calls the walk directly to ensure smoothness: no stopping to turn
        relX = circleX - myx
        relY = circleY - myy
        relD = hMath.getLength((relX, relY))
        relTheta = hMath.RAD2DEG(hMath.getHeadingToRelative(relX, relY))

        # Don't turn outwards much, even if we are inside the circle. Walking
        # forward will put us back on it. Nobu can you fix this?
#        print "relTheta", relTheta, "=>",
#        if direction == Constant.dANTICLOCKWISE and relTheta < 0:
#            #relTheta = hMath.CLIP(relTheta, 15)
#            relTheta = 0
#        elif direction == Constant.dCLOCKWISE and relTheta > 0:
#            #relTheta = hMath.CLIP(relTheta, 15)
#            relTheta = 0
#        print relTheta
        left = 0
        if abs(relTheta) < 30:
            Action.walk(Action.MAX_FORWARD, left, relTheta)
        else:
            Action.walk(Action.MAX_FORWARD, left, relTheta)
    else:
        hTrack.saGoToTarget(circleX, circleY)
Ejemplo n.º 11
0
def getDKDRange():

    nearEdgeDist = 40
    debugDKD = False
    length = Constant.FIELD_LENGTH
    width = Constant.FIELD_WIDTH

    # Make sure determine ballSource is called
    if Global.ballSource is None:
        print "Warning: in getDKDRange() havent determined the ball source before getDKD()"
        return None

    X_ = Global.ballX
    Y_ = Global.ballY
    if debugDKD:
        print "Ball Source: ", Global.ballSource, "   X_ ", X_, "  Y_ ", Y_

    # If you don't know where the ball is determine dkd based on where you are.
    if Global.ballSource == Constant.GPS_BALL\
        and VisionLink.getGPSBallMaxVar() >= hMath.get95var(35):

        X_, Y_ = Global.selfLoc.getPos()
        if debugDKD:
            print "Warning: in getDKDRange(): I dont trust GPS ball right now: use my own pos is X_ ", X_, "  Y_ ", Y_

    Y_ = hMath.CLIPTO(Y_, 0, length)
    X_ = hMath.CLIPTO(X_, 0, width)

    # If the ball is near one of the side edges and not in corners then the direction becomes up the field.
    if Y_ > nearEdgeDist:
        if X_ < nearEdgeDist:  # on the left edge
            if debugDKD:
                print "On the left edge"
            return (90, 70, 100, 10, 110)
        elif X_ > (width - nearEdgeDist):  #on the right edge
            if debugDKD:
                print "On the right edge"
            return (90, 80, 110, 70, 170)

    # upper 60%, can I use voak?

    if Y_ > 0.6 * length:

        # If target goal seen and is close and not many obstacles, it has a good heading, get the best heading like VOAK
        if (Global.vTGoal.getConfidence() > 3
                and Global.ballSource == Constant.VISION_BALL):
            toY = length - Y_
            toX = width / 2.0 - X_
            xRange = Constant.GOAL_WIDTH / 2.0 + (toY *
                                                  math.tan(hMath.DEG2RAD(30)))
            inVOAKcal = abs(toX) < xRange

            if inVOAKcal:

                (lmin, lmax, rmin, rmax) = VisionLink.getHeadingToBestGap()
                lmin = hMath.normalizeAngle_0_360(lmin +
                                                  Global.selfLoc.getHeading())
                lmax = hMath.normalizeAngle_0_360(lmax +
                                                  Global.selfLoc.getHeading())
                rmin = hMath.normalizeAngle_0_360(rmin +
                                                  Global.selfLoc.getHeading())
                rmax = hMath.normalizeAngle_0_360(rmax +
                                                  Global.selfLoc.getHeading())
                if abs(lmax - lmin) > abs(rmax - rmin):
                    tdkdmin, tdkdmax = lmin, lmax
                    dkd = (lmin + lmax) / 2.0
                else:
                    tdkdmin, tdkdmax = rmin, rmax
                    dkd = (rmin + rmax) / 2.0
                if (dkd < 150 and dkd > 30):
                    return (dkd, tdkdmin, tdkdmax, 10, 170)

    # Find the dkd fron the center of the target and own goals
    dkdup = hMath.getHeadingBetween(X_, Y_, (width / 2.0), length)
    dkdbottom = hMath.getHeadingBetween((width / 2.0), 0, X_, Y_)

    # if i cant use voak, then the heading to the center of target goal is used as dkd
    if Y_ > 0.6 * length:

        tdkdmin = hMath.getHeadingBetween(X_, Y_, Constant.RIGHT_GOAL_POST,
                                          length)
        tdkdmax = hMath.getHeadingBetween(X_, Y_, Constant.LEFT_GOAL_POST,
                                          length)
        if debugDKD:
            print "close to target goal, dkd directed to the target goal", Global.DKD[
                0]
        return (dkdup, tdkdmin, tdkdmax, 10, 170)

    # if close to own goal, direted out of own goal
    elif Y_ < 0.4 * length:

        if debugDKD:
            print "close to own goal, dkd directed out of the own goal"
        return (dkdbottom, 20, 160, 10, 170)

    # Now, the middle 20% of the field should have a continous change of direction.
    else:
        myy = Y_ - 0.4 * length
        ratio = myy / (0.2 * length)
        dkd = dkdup * ratio + dkdbottom * (1 - ratio)

        if debugDKD:
            print "middle 20%, linear interpolation"
        return (dkd, 40, 140, 20, 160)
Ejemplo n.º 12
0
def doAvoidGoalBox(ownGoalBox=True):
    headToBall = hMath.normalizeAngle_0_360(Global.ballH + \
                                            Global.selfLoc.getHeading())

    ballH2OGoalH = hMath.getHeadingBetween(Global.ballX,Global.ballY,\
                                           Constant.OWN_GOAL_X,Constant.OWN_GOAL_Y)

    selfH2OGoalH = hMath.normalizeAngle_180(headToBall - ballH2OGoalH)

    xOffset = 50
    if (Global.selfLoc.getX() > Constant.FIELD_WIDTH/2 \
            and Global.ballX < Constant.FIELD_WIDTH/2) \
            or (Global.selfLoc.getX() < Constant.FIELD_WIDTH/2 \
            and Global.ballX > Constant.FIELD_WIDTH/2):
        xOffset += abs(Global.ballX - Constant.FIELD_WIDTH / 2) / 2

    # Far away? Just go as normal
    if not hWhere.inGoalBox(Global.selfLoc.getX(), Global.selfLoc.getY(),
                            ownGoalBox, Constant.GOALBOX_WIDTH):
        doTrackBall()

    # If next to the goal box walk to the corner of it
    elif ownGoalBox and Global.selfLoc.getY() < Constant.GOALBOX_DEPTH - 10:
        if Global.selfLoc.getX() < Constant.FIELD_WIDTH / 2:
            hTrack.saGoToTargetFacingHeading(Constant.MIN_GOALBOX_EDGE_X,
                                             Constant.OWN_GOALBOX_EDGE_Y + 25,
                                             headToBall)
        else:
            hTrack.saGoToTargetFacingHeading(Constant.MAX_GOALBOX_EDGE_X,
                                             Constant.OWN_GOALBOX_EDGE_Y + 25,
                                             headToBall)

    elif (not ownGoalBox
          ) and Global.selfLoc.getY() > Constant.TOP_GOALBOX_EDGE_Y + 10:
        if Global.selfLoc.getX() < Constant.FIELD_WIDTH / 2:
            hTrack.saGoToTargetFacingHeading(Constant.MIN_GOALBOX_EDGE_X,
                                             Constant.TOP_GOALBOX_EDGE_Y - 25,
                                             headToBall)
        else:
            hTrack.saGoToTargetFacingHeading(Constant.MAX_GOALBOX_EDGE_X,
                                             Constant.TOP_GOALBOX_EDGE_Y - 25,
                                             headToBall)
    # Else if we are in front of goalbox walk to line up ouselves with
    # the ball and goal
    elif ownGoalBox:
        # Move to the side of the ball, so we can localise as well.
        # May need hysterisis here... not to switch sides frequently.
        if selfH2OGoalH < 0:
            adjX = xOffset
        else:
            adjX = -xOffset

        hTrack.saGoToTargetFacingHeading(Global.ballX + adjX,
                                         Constant.OWN_GOALBOX_EDGE_Y + 20,
                                         headToBall)
    elif not ownGoalBox:
        # Move to the side of the ball, so we can localise as well.
        # May need hysterisis here... not to switch sides frequently.
        if selfH2OGoalH < 0:
            adjX = xOffset
        else:
            adjX = -xOffset

        hTrack.saGoToTargetFacingHeading(Global.ballX + adjX,
                                         Constant.TOP_GOALBOX_EDGE_Y - 20,
                                         headToBall)
Ejemplo n.º 13
0
def perform(params=None):
    global gLastFrameCalled
    global gLastDecisionFunction
    global pos, friendPos, isPlayerSet, friend, friendloc, centerPos
    hTeam.sendWirelessInfo()

    id(params)  # ignore
    if not isPlayerSet:
        if Global.myPlayerNum == 3:
            friend = Global.teamPlayers[1]
            friendloc = Global.teammatesLoc[1]
            centerPos = (Constant.FIELD_WIDTH / 2, Constant.GOALBOX_DEPTH)
        else:
            friend = Global.teamPlayers[2]
            friendloc = Global.teammatesLoc[2]
            centerPos = (Constant.FIELD_WIDTH / 2,
                         Constant.FIELD_LENGTH - Constant.GOALBOX_DEPTH)
        isPlayerSet = True
        print "Player no:", Global.myPlayerNum

    friendPos = friendloc.getPos()
    pos = Global.selfLoc.getPos()
    #if friend grab, go to center position, while looking at obstacle, get facing ball.
    #if see ball far away, get behind ball (don't pass half the field) while scanning for ball and obstacle.
    #if see ball < 1/2 field, chase and grab, turn no obstacle, until facing friend or gap upfield. and kick if obstacle near, if not stop realease, and scan look for obstacle and ball.
    #if got wirelessball get behind wireless ball on keep a distance with obstacle, scan.
    #if doesn't see and doesn't have wireless ball, find ball and goto base spot to spin again.

    calculateObstacleBox()

    shouldIBeDodgy = gUseDodgyDog

    if gLastFrameCalled != Global.frame - 1:
        resetPerform()
    gLastFrameCalled = Global.frame

    #     elif shouldIKick():
    #         #shouldIBeDodgy = False  #Really?
    #         doKick()
    if (sGrab.isGrabbed):
        print "friend is in :", friendPos[0], " ", friendPos[1]
        r = scGrabDribble.performToPosition((friendPos[0], friendPos[1]))


#         if r == Constant.STATE_EXECUTING:
#             return
#         else:
#             scGrabDribble.resetPerform()
#align to friend gps, while avoiding the obstacle.
#and the pass to him.

    elif (sGrab.grabbingCount > 0):
        #print "grabbing"
        r = sGrab.perform(doGetBehindv=sFindBall.GET_BEHIND_NONE)
        if r == Constant.STATE_EXECUTING:
            return
        elif r == Constant.STATE_FAILED:
            sGrab.resetPerform()

    elif shouldIFindSpace():
        #print "Find space"
        doFindSpace()

    elif not shouldIEndActivelyLocalise()\
        or shouldIActivelyLocalise():
        #print "active loc"
        doActivelyLocalise()

    elif (Global.vBall.isVisible() or Global.lostBall < Constant.LOST_BALL_GPS
          or friend.hasSeenBall()):
        #print "see a ball"
        #if (friend.getTimeToReachBall() < selfobj.getTimeToReachBall() + 1000):
        if (centerPos[1] < Constant.FIELD_LENGTH / 2):
            isOtherHalf = Global.ballY > Constant.FIELD_LENGTH / 2
        else:
            isOtherHalf = Global.ballY < Constant.FIELD_LENGTH / 2

        if (isOtherHalf):  #And no near obstacle and Global.ballD > 30):
            #print "ball the other end"
            #if hMath.getDistSquaredBetween(pos[0],pos[1],Global.ballX,Global.ballY) > YDISTANCE_TO_BALL_SQR:
            if (abs(Global.ballX - pos[0]) > YDISTANCE_TO_BALL):
                sFindBall.perform(True)
                #time to ball ? to get the ball if the other one is slow
                if (centerPos[1] < Constant.FIELD_LENGTH / 2):
                    hTrack.saGoToTarget(
                        Global.ballX,
                        max(pos[1], Global.ballY - YDISTANCE_TO_BALL)
                    )  #and ywhere the same or more if y diff less than 2 meter)
                else:
                    hTrack.saGoToTarget(
                        Global.ballX,
                        max(pos[1], Global.ballY + YDISTANCE_TO_BALL)
                    )  #and ywhere the same or more if y diff less than 2 meter)
            else:
                sFindBall.perform(True)
                if (centerPos[1] < Constant.FIELD_LENGTH / 2):
                    movePoint = (max(
                        LOOK_OFFSETX,
                        min(Global.ballX,
                            Constant.FIELD_WIDTH - LOOK_OFFSETX)),
                                 Global.ballY - YDISTANCE_TO_BALL)
                else:
                    movePoint = (max(
                        LOOK_OFFSETX,
                        min(Global.ballX,
                            Constant.FIELD_WIDTH - LOOK_OFFSETX)),
                                 Global.ballY + YDISTANCE_TO_BALL)

                hTrack.saGoToTargetFacingHeading(
                    movePoint[0], movePoint[1],
                    hMath.getHeadingBetween(pos[0], pos[1], Global.ballX,
                                            Global.ballY))
        else:
            #print "Grab"
            r = sGrab.perform(doGetBehindv=sFindBall.GET_BEHIND_NONE)
            if r == Constant.STATE_EXECUTING:
                return
            elif r == Constant.STATE_FAILED:
                sGrab.resetPerform()
    else:  #if shouldIGoToCenter():
        #print "goto center"
        doGotoCenter()

    # Use dodgy dog if required
    fwdCmd = Action.finalValues[Action.Forward]
    shouldIBeDodgy = shouldIBeDodgy and (not sGrab.isGrabbed) \
                    and sGrab.grabbingCount == 0 \
                    and Global.ballD > sGrab.CLOSE_DIST \
                    and fwdCmd > Action.MAX_SKE_FWD_SPD/2 \
                    and fwdCmd > Action.finalValues[Action.Left] \
                    and sDodgyDog.shouldIBeDodgyToBall()

    if shouldIBeDodgy:
        sDodgyDog.dodgyDogToBall()
Ejemplo n.º 14
0
def doFindSpace():
    hTrack.saGoToTargetFacingHeading(
        centerPos[0], centerPos[1],
        hMath.getHeadingBetween(pos[0], pos[1], Global.ballX, Global.ballY))
Ejemplo n.º 15
0
def perform(dkd=90, dist=20, direction=None, bx=None, by=None, accuracy=20):
    global gDirection

    #if side != None:
    #    print "Warning: sGetBehindBall.perform: side is not yet implemented"

    if bx == None or by == None:
        (bx, by) = Global.gpsGlobalBall.getPos()
    (myx, myy) = Global.selfLoc.getPos()
    myh = Global.selfLoc.getHeading()

    # Work out if we are to the left or right of the ball (relative to DKD as 0)
    lRobotH = hMath.getHeadingToMe(bx, by, dkd, myx, myy)

    if direction == None and gDirection == None:
        if lRobotH < 0:  # robot to the left
            #print "robot to left of ball",
            gDirection = Constant.dANTICLOCKWISE
        else:  # robot to the right
            #print "robot to right of ball",
            gDirection = Constant.dCLOCKWISE

    elif direction != None:
        gDirection = direction

    # The circling point can be calculated as looking from the ball
    # towards the robot at CIRCLE_DEGREES to the left/right, and distance
    # dist. CircleAng is from the ball facing the robot with positive x
    # at zero degrees


#    if robotH > 180 - CIRCLE_DEGREES:
#        # If we are within CIRCLE_DEGREES of the target point don't overshoot
#        circleAng = 90 + (180 - robotH)
#    elif robotH < -180 + CIRCLE_DEGREES:
#        circleAng = 90 - (-180 + robotH)
#    else:
    if gDirection == Constant.dANTICLOCKWISE:
        circleAng = 90 + CIRCLE_DEGREES
    else:
        circleAng = 90 - CIRCLE_DEGREES
    circleAng = hMath.normalizeAngle_180(circleAng)

    #print ""
    #print "local robot H ", lRobotH
    # relative to target facing robot

    # This factor is used to adjust the dodgyness of the sidewards and
    # backwards ability of fast skelliptical walk.
    factor = 1  #max(min(abs(180-lRobotH)/60.0,2),1)
    lcx = math.cos(hMath.DEG2RAD(circleAng)) * dist * factor
    lcy = math.sin(hMath.DEG2RAD(circleAng)) * dist * factor

    #print "circleAng", circleAng, "rel circle pos", circleRelX, circleRelY

    robotH = hMath.normalizeAngle_0_360(lRobotH + dkd)  # now global
    cx, cy = hMath.getGlobalCoordinate(bx, by, robotH, lcx, lcy)

    #print " local circle pos : (", lcx ,",",lcy,")"
    #print "my pos : (", myx, ",", myy, ",",myh,")"
    #print "global robotH ", robotH
    #print "global ball :(", bx, ",", by, ") global circle pos : (", cx ,",",cy,")"
    # circleX/Y now is the global coords of the circle point, so walk there.

    bh = hMath.getHeadingBetween(myx, myy, bx, by)  # global
    lbh = hMath.normalizeAngle_180(bh - myh)

    lcx, lcy = hMath.getLocalCoordinate(myx, myy, myh, cx, cy)
    #lcdSquared = hMath.getDistSquaredBetween(0,0,lcx,lcy)
    Action.walk(lcy, lcx, lbh, "ddd", minorWalkType=Action.SkeFastForwardMWT)

    if abs(hMath.normalizeAngle_180(bh -
                                    dkd)) < accuracy and abs(lbh) < accuracy:
        resetPerform()
        return Constant.STATE_SUCCESS

    return Constant.STATE_EXECUTING
Ejemplo n.º 16
0
def selectKickInMiddleThird():
    global gLastAvoidOwnGoalFrame

    selfH2BallH = hMath.normalizeAngle_0_360(selfH + ballH)
    ballH2OGoalH = hMath.getHeadingBetween(ballX,ballY,\
                                           Constant.OWN_GOAL_X,Constant.OWN_GOAL_Y)
    selfH2OGoalH = hMath.normalizeAngle_180(selfH2BallH - ballH2OGoalH)

    ballH2TGoalH = hMath.getHeadingBetween(ballX,ballY,\
                                           Constant.TARGET_GOAL_X,Constant.TARGET_GOAL_Y-50)
    selfH2TGoalH = hMath.normalizeAngle_180(selfH2BallH - ballH2TGoalH)

    ballH2CenterH = hMath.getHeadingBetween(ballX,ballY,\
                                            Constant.FIELD_WIDTH/2.0,ballY+200)
    selfH2CenterH = hMath.normalizeAngle_180(selfH2BallH - ballH2CenterH)

    if sGrab.isGrabbed:
        if hWhere.ballOnLEdge() or hWhere.ballOnREdge():
            return (KT_GRAB_DRIBBLE, ballH2CenterH, Constant.dAUTO)
        else:
            return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    elif abs(selfH2OGoalH) < 40 or Global.vOGoal.isVisible():
        gLastAvoidOwnGoalFrame = Global.frame
        return (KT_AVOID_OWN_GOAL, ballH2TGoalH, Constant.dAUTO)

    # If we are stuck in midfield area, do something!!!
    # FIXME : smart strategy
    elif hStuck.gUseContestDetect and hStuck.isBallContested():
        if 45 <= abs(selfH2TGoalH) < 60:
            if selfH2TGoalH < 0:
                return (KT_UPENN_RIGHT, ballH2TGoalH, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, ballH2TGoalH, Constant.dAUTO)
        elif (ballD < sGrab.CLOSE_DIST or Global.frame - sGrab.gLastApproachFrame < 5)\
            and ((hWhere.isOnLEdge(EDGE_DIST) and abs(selfH2TGoalH) > 10)
                or (hWhere.isOnREdge(EDGE_DIST) and abs(selfH2TGoalH) > 10)
                or selfH >= 180):
            return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

        else:
            return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

    # If the ball is in the left edge.
    elif hWhere.ballOnLEdge():
        return selectKickInLeftEdge()

    # If the ball is in the right edge.
    elif hWhere.ballOnREdge():
        return selectKickInRightEdge()

    # If the ball is not in the edges of the field
    else:

        if 45 <= abs(selfH2TGoalH) < 60:
            if selfH2TGoalH < 0:
                return (KT_UPENN_RIGHT, ballH2TGoalH, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, ballH2TGoalH, Constant.dAUTO)

        elif abs(selfH2TGoalH) < 90:

            if abs(selfH2TGoalH) < 10:
                return (KT_DRIBBLE, ballH2TGoalH, Constant.dAUTO)
            else:
                return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)

        else:
            return (KT_GRAB_DRIBBLE, ballH2TGoalH, Constant.dAUTO)
Ejemplo n.º 17
0
def selectKickInDefensiveThird():
    global gLastAvoidOwnGoalFrame

    selfH2BallH = hMath.normalizeAngle_0_360(selfH + ballH)

    ballH2OGoalH = hMath.getHeadingBetween(ballX,ballY,\
                                           Constant.OWN_GOAL_X,Constant.OWN_GOAL_Y)
    ballH2MinOGoalBoxH = hMath.getHeadingBetween(ballX,ballY,\
                                                 Constant.MIN_GOALBOX_EDGE_X,Constant.OWN_GOAL_Y)
    ballH2MaxOGoalBoxH = hMath.getHeadingBetween(ballX,ballY,\
                                                 Constant.MAX_GOALBOX_EDGE_X,Constant.OWN_GOAL_Y)

    selfH2OGoalH = hMath.normalizeAngle_180(selfH2BallH - ballH2OGoalH)

    ballH2CenterH = hMath.getHeadingBetween(ballX,ballY,\
                                            Constant.FIELD_WIDTH/2.0,ballY+200)
    selfH2CenterH = hMath.normalizeAngle_180(selfH2BallH - ballH2CenterH)

    if sGrab.isGrabbed:
        return (KT_GRAB_DRIBBLE, ballH2CenterH, Constant.dAUTO)

    elif abs(selfH2OGoalH) < 60\
        or ballH2MinOGoalBoxH < selfH2BallH < ballH2MaxOGoalBoxH\
        or Global.vOGoal.isVisible():
        gLastAvoidOwnGoalFrame = Global.frame
        return (KT_AVOID_OWN_GOAL, ballH2CenterH, Constant.dAUTO)

    # If we are stuck in defensive area, do something!!!
    elif hStuck.gUseContestDetect and hStuck.isBallContested():
        if 45 <= abs(selfH2CenterH) < 60:
            if selfH2CenterH < 0:
                return (KT_UPENN_RIGHT, ballH2CenterH, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, ballH2CenterH, Constant.dAUTO)
        elif (ballD < sGrab.CLOSE_DIST or Global.frame - sGrab.gLastApproachFrame < 5)\
            and ((hWhere.isOnLEdge(EDGE_DIST) and abs(selfH2CenterH) > 10)
                or (hWhere.isOnREdge(EDGE_DIST) and abs(selfH2CenterH) > 10)
                or selfH >= 180):
            return (KT_GRAB_DRIBBLE, ballH2CenterH, Constant.dAUTO)
        else:
            return (KT_DRIBBLE, ballH2CenterH, Constant.dAUTO)

    # If the ball is in the left edge.
    elif hWhere.ballOnLEdge():
        return selectKickInLeftEdge()

    # If the ball is in the right edge.
    elif hWhere.ballOnREdge():
        return selectKickInRightEdge()

    # If the ball is not in the edge of the field
    else:
        if 45 <= abs(selfH2CenterH) < 60:
            if selfH2CenterH < 0:
                return (KT_UPENN_RIGHT, ballH2CenterH, Constant.dAUTO)
            else:
                return (KT_UPENN_LEFT, ballH2CenterH, Constant.dAUTO)

        elif abs(selfH2CenterH) < 90:

            if abs(selfH2CenterH) < 20:
                return (KT_DRIBBLE, ballH2CenterH, Constant.dAUTO)
            else:
                return (KT_GRAB_DRIBBLE, ballH2CenterH, Constant.dAUTO)

        # Otherwise we should do get behind??
        # turn kick
        else:
            return (KT_GRAB_DRIBBLE, ballH2CenterH, Constant.dAUTO)
Ejemplo n.º 18
0
def DecideNextAction(radius, aa, turndir, taOff, raOff, kp, ki, kd):

    global lastBx, lastBy, sum_reqTurn, last_reqTurn, lastFrame, lastDir

    skippedFrames = Global.frame - (lastFrame + 1)

    # Reset the running sum if the routine is not called.
    lastFrame = Global.frame  # record the last frame

    Indicator.showFacePattern(Constant.FP_DIR_KICK)

    # No need to showFacePattern, because rAttacker has called already before entering this.

    myx, myy = Global.selfLoc.getPos()  # My (the dog) position and its heading
    myh = Global.selfLoc.getHeading()

    if Global.vBall.getConfidence() > 2:
        bx, by = Global.vBall.getPos()  # ball position
        lastBx, lastBy = Global.vBall.getPos()
    else:
        bx = lastBx
        by = lastBy

    # Find the lp, given the ball position, taOff and the attack angle
    # aa+180 because u want the tagental offset extended to behind the ball
    # the point where the dog leaves the locus (leaving point)

    lpx, lpy = hMath.getPointRelative(bx, by, (aa + 180), taOff)

    # Find the center of the circle, given the lp, the radius and attack angle, and where u are.

    angleFromBall = hMath.getHeadingBetween(bx, by, myx, myy)
    angleRelativeToAA = hMath.normalizeAngle_180(angleFromBall - aa)

    if angleRelativeToAA >= 0 and angleRelativeToAA <= 180:
        turndir = Constant.dANTICLOCKWISE
    else:
        turndir = Constant.dCLOCKWISE

    if turndir == Constant.dCLOCKWISE:
        cx, cy = hMath.getPointRelative(lpx, lpy, (aa - 90), (radius + raOff))
    else:
        cx, cy = hMath.getPointRelative(lpx, lpy, (aa + 90), (radius + raOff))

    c2my = hMath.getDistanceBetween(cx, cy, myx,
                                    myy)  # distance btw me and center
    errL = radius - c2my  # Indicates inside or outside of the circle. Used as adjustment in vector field.

    # If not outside of the circle, no point to use alpha(Angle between center and cloest tangent point)
    if c2my <= radius:
        alpha = 0
    else:
        alpha = hMath.RAD2DEG(math.asin(radius / c2my))  # 0 <= alpha <= 90

    beta = hMath.getHeadingBetween(
        myx, myy, cx, cy)  # Angle between global x-axis and center

    # Fing the current vector
    if turndir == Constant.dANTICLOCKWISE:
        vectorArr = beta - 90  # Find the tangent vector perp to the c2my line first
        if errL > 0:
            vectorArr = vectorArr - (errL / radius * 45.0
                                     )  # linear discrepency
        elif errL < 0:  # When outside of the circle, the vector is
            vectorArr = beta - alpha  # the tangent closest to the circle.
    else:
        vectorArr = beta + 90
        if errL > 0:
            vectorArr = vectorArr + (errL / radius * 45.0)
        elif errL < 0:
            vectorArr = beta + alpha

    b2my = hMath.getDistanceBetween(bx, by, myx, myy)
    angleFromCenToMe = hMath.normalizeAngle_180(
        hMath.getHeadingBetween(cx, cy, myx, myy) - aa)
    distanceToAALine = b2my * math.sin(hMath.DEG2RAD(angleRelativeToAA))
    ##~     verticalDistToBall = b2my * math.cos(hMath.DEG2RAD(angleRelativeToAA))

    if (raOff > 0 and abs(distanceToAALine) < raOff):
        vectorArr = aa
##~         leftAdjust = -hMath.CLIP(distanceToAALine,3)

    elif (turndir == Constant.dANTICLOCKWISE and angleFromCenToMe < 0
          and angleFromCenToMe > -90 and abs(distanceToAALine) <
          (raOff + radius)):
        sHoverToBall.DecideNextAction()
        Indicator.showFacePattern([1, 2, 1, 2, 0])
        ##~         reverse(aa,turndir,taOff,verticalDistToBall)
        return

    elif (turndir == Constant.dCLOCKWISE and angleFromCenToMe < 90
          and angleFromCenToMe > 0 and abs(distanceToAALine) <
          (raOff + radius)):
        sHoverToBall.DecideNextAction()
        Indicator.showFacePattern([1, 2, 1, 2, 0])
        ##~         reverse(aa,turndir,taOff,verticalDistToBall)
        return

    # After the vector is found, the PID controller will handle the job.

    # Note:
    # When u tune, first tune the KP to improve the rise time, then the KD to improve
    # the overshoot, finally the KI for better steady state.
    # better see http:##www.engin.umich.edu/group/ctm/PID/PID.html before u touch them

    # thisTurn - The vector that brings the dog heading to the vector arrow

    thisTurn = hMath.CLIP(hMath.normalizeAngle_180(vectorArr - myh), 30.0)

    # For normal walk , kp = 40 ki = 8 kd = 5

    KP = kp / 100.0  #0.5   ## Less Than 1
    KD = kd / 100.0  #0.1
    KI = ki / 100.0  #0.1  ## Has to be very small

    if skippedFrames > 0:
        sum_reqTurn = sum_reqTurn * math.pow(0.8, skippedFrames)
        last_reqTurn = 0

    # clip the running sum to be as most causing a 8 degree change.
    if abs(sum_reqTurn) > (3.0 / KI):
        sum_reqTurn = hMath.CLIP(sum_reqTurn, 3.0 / KI)

    # if far away, there is no I and D effects, only the P.

    if c2my > (4.0 * radius):
        sum_reqTurn = 0
        last_reqTurn = thisTurn

    # The real PID calculations
    #print thisTurn
    #print last_reqTurn
    #print sum_reqTurn

##~     print "==========new frame"
##~     print "ball pos %.2f , %.2f and my h %.2f" % (bx,by,myh)
##~     print "lp pos %.2f , %.2f and cx pos %.2f , %.2f" % (lpx,lpy,cx,cy)
##~     print "vectorArr %.2f   and thisTurn %.2f " % (vectorArr,thisTurn)
##~     print "last  %.2f and sum_reqTurn  %.2f) " % (last_reqTurn,sum_reqTurn)
##~     print "P %.5f   I %.5f    D %.5f " % (KP * thisTurn,KI * sum_reqTurn,\
##~         KD * (thisTurn - last_reqTurn))
##~
    reqTurn = (KP * thisTurn) + (KI *
                                 sum_reqTurn) + (KD *
                                                 (thisTurn - last_reqTurn))
    ##~     print "the reqTurn is %.2f" % (reqTurn)

    sum_reqTurn = sum_reqTurn + thisTurn  # The integral part
    last_reqTurn = thisTurn  # Used in the derivative part

    # Print the debugging info
    Action.walk(7, 0, hMath.CLIP(reqTurn, 30), Action.EllipticalWalk)

    ##~     print "Direction: " , turndir , "vectorArr %.2f" % (vectorArr)

    if ((angleRelativeToAA > 160 or angleRelativeToAA < -160)
            and abs(hMath.normalizeAngle_180(myh - aa)) < 20):
        sPawKick.firesPawKick(sPawKick.FIRE_PAWKICK_AUTO)
        Indicator.showFacePattern([1, 1, 1, 1, 0])