Esempio n. 1
0
def doGetToTargetPoint(targetX, targetY):
    global gTargetPointReqAccuracy

    selfX, selfY = Global.selfLoc.getX(), Global.selfLoc.getY()
    ballX, ballY, ballH = Global.ballX, Global.ballY, Global.ballH 
        
    h = hMath.normalizeAngle_0_360(hMath.RAD2DEG(math.atan2(\
                                                ballY - selfY, ballX - selfX)))
   
    #angle = hMath.absAngleBetweenTwoPointsFromPivotPoint(ballX, ballY, \
    #                                                     targetX, targetY, \
    #                                                     selfX, selfY)
        
    distSquared = hMath.getDistSquaredBetween(targetX,targetY,selfX,selfY)

    
##     if dist > 100 and angle < 80: 
##         hTrack.saGoToTarget(targetX,targetY)
##     else:
##         hTrack.saGoToTargetFacingHeading(targetX,targetY,h)
    
    hTrack.saGoToTargetFacingHeading(targetX,targetY,h)

    # Hysterisis for whether or not your at the defender point.
    if distSquared <= hMath.SQUARE(gTargetPointReqAccuracy):
        gTargetPointReqAccuracy = TARGET_PT_ACC_LARGE_CIRCLE        
        if abs(ballH) < 15:
            Action.stopLegs()
    else:
        gTargetPointReqAccuracy = TARGET_PT_ACC_SMALL_CIRCLE

    if abs(targetX - selfX) < 30 and abs(targetY - selfY) < 100:
        checkThenBlock()
Esempio n. 2
0
def saGoToTargetFacingHeading(targetX, targetY, targetH, \
        maxSpeed = Action.MAX_FORWARD, maxTurn = Action.MAX_TURN):

    # Variables relative to self localisation.
    selfPos = Global.selfLoc.getPos()
    selfH = Global.selfLoc.getHeading()
    cosSelf = math.cos(math.radians(selfH))
    sinSelf = math.sin(math.radians(selfH))

    relX = targetX - selfPos[0]
    relY = targetY - selfPos[1]
    relH = hMath.normalizeAngle_180(targetH - selfH)
    # now take into account that as we turn, the position of our head will change
    relX += Constant.DOG_LENGTH / 2.0 * (cosSelf -
                                         math.cos(math.radians(targetH)))
    relY += Constant.DOG_LENGTH / 2.0 * (sinSelf -
                                         math.sin(math.radians(targetH)))
    relD = hMath.getLength((relX, relY))

    # Calculate approximate coordinates of all the dog's legs
    legs = []
    for legNum in range(4):
        legPos = list(selfPos)

        if legNum >= 2:
            legPos[0] = legPos[0] - DOG_RECT_LENGTH * cosSelf
            legPos[1] = legPos[1] - DOG_RECT_LENGTH * sinSelf

        if (legNum % 2) == 0:
            legPos[0] = legPos[0] - DOG_RECT_WIDTH * sinSelf
            legPos[1] = legPos[1] + DOG_RECT_WIDTH * cosSelf
        else:
            legPos[0] = legPos[0] + DOG_RECT_WIDTH * sinSelf
            legPos[1] = legPos[1] - DOG_RECT_WIDTH * cosSelf

        legs.append(tuple(legPos))

    # If a leg coordinate lies within the rear wall, clip the Y movement
    clipMove = False
    for legPos in legs:
        if abs(legPos[0] - Constant.FIELD_WIDTH / 2) > Constant.GOAL_WIDTH and\
            legPos[1] < 2:
            clipMove = True

    if clipMove and (relY < 0):
        relY = 0

    if relX == 0 and relY == 0:
        #on the dog, math.atan2(0,0) give "Value Error: math domain error"
        relTheta = 0
    else:
        relTheta = hMath.normalizeAngle_180(
            hMath.RAD2DEG(math.atan2(relY, relX)) - selfH)

    forward = hMath.CLIP(relD, maxSpeed) * math.cos(hMath.DEG2RAD(relTheta))
    left = hMath.CLIP(relD, maxSpeed) * math.sin(hMath.DEG2RAD(relTheta))
    turnCCW = hMath.CLIP(relH, maxTurn)

    Action.walk(forward, left, turnCCW, minorWalkType=Action.SkeFastForwardMWT)
Esempio n. 3
0
def SmartSetBeacon(panLimit=90, distLimit=550):
    global localiseBeacon

    # Get shared variables from elsewhere.
    selfLoc = Global.selfLoc
    cov = VisionLink.getGPSSelfCovariance()

    # Calculate the direction of the larger axis of the self covariance
    b = -(cov[0][0] + cov[1][1])
    c = cov[0][0] * cov[1][1] - cov[1][0] * cov[1][0]
    det = b * b - 4 * c

    if (det < 0.00001):
        sol = -b / 2
    else:
        sol = (-b + math.sqrt(det)) / 2

    if abs(cov[0][0] - sol) < 0.01 and cov[0][1] < 0.01:
        # If self position variance is circular, all beacons are equally good
        # to localise off, and so choose the one closest to current heading.
        if abs(cov[1][1] - sol) < 0.01:
            head = selfLoc.getHeading()
        else:
            head = hMath.RAD2DEG(math.atan2(-cov[1][0], cov[1][1] - sol))
    else:
        head = hMath.RAD2DEG(math.atan2(sol - cov[0][0], cov[0][1]))

    # Find the beacon that is closest to the variance direction.
    beaconPos = VisionLink.getGPSCoordArray()
    curCompHead = 360
    localiseBeacon = 0

    for beacon in CHECK_BEACONS:
        relPos = map(lambda b, s: b - s, beaconPos[beacon], selfLoc.getPos())
        beaconHead = hMath.RAD2DEG(math.atan2(relPos[1], relPos[0]))
        beaconDist = hMath.getLength(relPos)
        localHead = hMath.normalizeAngle_180(beaconHead - selfLoc.getHeading())

        if abs(localHead) < panLimit and beaconDist < distLimit:
            compHead = abs(hMath.normalizeAngle_180(head - beaconHead))
            if compHead > 90:
                compHead = 180 - compHead

            if compHead < curCompHead:
                curCompHead = compHead
                localiseBeacon = beacon
Esempio n. 4
0
def getGPSBallInfo(context):
    if context == Constant.CTGlobal:
        (myx, myy, myh) = (0, 0, 0)
    else:
        (myx, myy, myh) = getSelfLocation()
        myh -= 90

    (x, y) = (ball.getX() - myx, ball.getY() - myy)
    ang = hMath.normalizeAngle_180(hMath.RAD2DEG(math.atan2(y, x)) - myh)
    return (x, y, math.sqrt(x * x + y * y), ang, ang - 90, 0)
Esempio n. 5
0
def WalkToBall(x, y, maxSpeed=12):
    global lastAction
    angle = -hMath.RAD2DEG(hMath.getHeadingToRelative(x, y))
    dist = math.sqrt(x * x + y * y)
    if math.fabs(angle) > 30:
        if dist < 30 or y < 0:  # if close or ball is hehind the camera
            Action.walk(0, 0, angle / 2)  # rotate on spot
        else:
            forward = hMath.CLIP(y, maxSpeed)
            Action.walk(forward, 0, angle / 2)
    else:
        Action.walk(FORWARD_SPEED, 0, angle)
    lastAction = WALK_FORWARD
Esempio n. 6
0
def amIInTheWay(x, y, targetX, targetY):
    myX, myY = Global.selfLoc.getPos()

    if x == None or y == None or targetX == None or targetY == None:
        return (None, None)

#    if Global.frame % 30 == 0:
#        print "amIInTheWay", x, y, targetX, targetY, "me", myX, myY

# We have a line in two point form, find offset of selfLoc from the line
    dist = ((targetX - x)*(y - myY) - (x - myX)*(targetY - y)) / \
            math.sqrt(hMath.SQUARE(targetX - x) + hMath.SQUARE(targetY - y))

    #    if Global.frame % 30 == 0:
    #        print "I'm", dist, "away from in the way",

    # If we're not between the points return None
    dx = x - targetX
    dy = y - targetY
    if abs(dx) > abs(dy) and \
            ((myX > x and myX > targetX) or (myX < x and myX < targetX)):
        #        if Global.frame % 30 == 0:
        #            print "but not between the points (X)"
        return (None, None)
    elif abs(dy) > abs(dx) and \
            ((myY > y and myY > targetY) or (myY < y and myY < targetY)):
        #        if Global.frame % 30 == 0:
        #            print "but not between the points (Y)"
        return (None, None)

    # The heading away is perpendicular to the target line
    if dy == 0:
        dy += 0.1  # prevent division by zero
    head = -dx / dy
    head = hMath.RAD2DEG(math.atan(head))

    # Which way along the line is away? If dist is positive we are to the left
    # of the line and want heading in the left half
    if (dist > 0):
        head += 180
    head = hMath.normalizeAngle_180(head)

    if Global.frame % 30 == 0:
        print "dx =", dx, "dy =", dy, "head =", head


#    if Global.frame % 30 == 0:
#        print "and between the points. Head", head, "to escape"

    return (dist, head)
Esempio n. 7
0
def perform(paw=AUTO_PAW_KICK):

    global pawKickType

    if Global.lostBall > Constant.LOST_BALL_GPS:
        return Constant.STATE_FAILED

    # Head ball tracking movement
    sFindBall.perform(True)

    PAW_KICK_Y_OFFSET = Constant.BallRadius
    PAW_KICK_X_OFFSET = 7.0

    ballX = math.sin(hMath.DEG2RAD(Global.ballH)) * Global.ballD
    ballY = math.cos(hMath.DEG2RAD(Global.ballH)) * Global.ballD

    # The 2003 offset is 6 and it is not too bad.
    if paw == AUTO_PAW_KICK:
        if pawKickType == LEFT_PAW_KICK and ballX < -PAW_KICK_X_OFFSET / 2:
            pawKickType = RIGHT_PAW_KICK
        elif pawKickType == RIGHT_PAW_KICK and ballX > PAW_KICK_X_OFFSET / 2:
            pawKickType = LEFT_PAW_KICK
    else:
        pawKickType = paw

    if pawKickType == RIGHT_PAW_KICK:
        targetX = ballX + PAW_KICK_X_OFFSET
    else:
        targetX = ballX - PAW_KICK_X_OFFSET

    targetY = ballY - PAW_KICK_Y_OFFSET
    targetD = math.sqrt(hMath.SQUARE(targetX) + hMath.SQUARE(targetY))
    targetH = hMath.RAD2DEG(math.asin(targetX / targetD))

    # Once the ball is lined up and well within range for the forward, the
    # robot should commit to charge at the ball at full speed.
    if abs(targetX) <= 1.0 and targetD < Constant.BallRadius * 1.5:
        turnccw = hMath.CLIP(targetH, 10)
        Action.walk(Action.MAX_FORWARD,
                    0,
                    turnccw,
                    minorWalkType=Action.SkeFastForwardMWT)

    else:
        sFindBall.walkToBall(targetD,
                             targetH,
                             getBehind=sFindBall.GET_BEHIND_LOTS)

    return Constant.STATE_EXECUTING
Esempio n. 8
0
def saGoToTargetFacingHeading(targetX, targetY, targetH, \
                maxSpeed = Action.MAX_FORWARD, maxTurn = Action.MAX_TURN):

    # ariables relative to self localisation.
    selfX = Global.selfLoc.getX()
    selfY = Global.selfLoc.getY()
    selfH = Global.selfLoc.getHeading()
    relX = targetX - selfX
    relY = targetY - selfY
    relH = hMath.normalizeAngle_180(targetH - selfH)
    relX            += Constant.DOG_LENGTH/2.0/10.0*(math.cos(math.radians(selfH)) \
                            - math.cos(math.radians(targetH)))
    relY            += Constant.DOG_LENGTH/2.0/10.0*(math.sin(math.radians(selfH)) \
                            - math.sin(math.radians(targetH)))
    relD = hMath.getLength((relX, relY))
    distanceSquared = hMath.getDistSquaredBetween(targetX, targetY, selfX,
                                                  selfY)
    inCircle = distanceSquared <= hMath.SQUARE(40)
    faceH = hMath.getHeadingToFaceAt(Global.selfLoc, targetX, targetY)

    ##~     print "faceH: ", faceH

    if not inCircle:
        if abs(faceH) >= 30:
            Action.walk(0, 0, faceH)
        else:
            #if sStealthDog.stealthDog(True):
            #    hFWHead.compulsoryAction = hFWHead.mustSeeBall
            #    hTrack.trackVisualBall()
            #    return
            Action.walk(maxSpeed, 0, hMath.CLIP(faceH / 1.5, maxTurn))

    else:
        if relX == 0 and relY == 0:
            # On the dog, math.atan2(0,0) give "Value Error: math domain error".
            relTheta = 0
        else:
            relTheta = hMath.normalizeAngle_180(
                hMath.RAD2DEG(math.atan2(relY, relX)) - selfH)

        forward = hMath.CLIP(relD, maxSpeed) * math.cos(
            hMath.DEG2RAD(relTheta))
        left = hMath.CLIP(relD, maxSpeed) * math.sin(hMath.DEG2RAD(relTheta))
        turnCCW = hMath.CLIP(relH, maxTurn)
        Action.walk(forward, left, turnCCW)
Esempio n. 9
0
def AlternateSetBeacon(panLimit=90, distLimit=550):
    global localiseBeacon, lastBeacon

    selfLoc = Global.selfLoc
    beaconPos = getBeaconCoords()
    curCompHead = panLimit
    localiseBeacon = None

    for beacon in beaconPos:
        relPos = map(lambda b, s: b - s, beacon, selfLoc.getPos())
        beaconHead = hMath.RAD2DEG(math.atan2(relPos[1], relPos[0]))
        beaconDist = hMath.getLength(relPos)
        localHead = hMath.normalizeAngle_180(beaconHead - selfLoc.getHeading())

        if abs(localHead) < curCompHead and beaconDist < distLimit:
            curCompHead = localHead
            localiseBeacon = beacon

    lastBeacon = localiseBeacon
Esempio n. 10
0
def saGoToTarget(targetX, targetY, maxSpeed=None, maxTurn=None):

    if maxSpeed == None:
        maxSpeed = Action.MAX_FORWARD
    if maxTurn == None:
        maxTurn = Action.MAX_TURN

    selfPos = Global.selfLoc.getPos()
    selfH = Global.selfLoc.getHeading()
    relX = targetX - selfPos[0]
    relY = targetY - selfPos[1]
    relD = hMath.getLength((relX, relY))

    if relX == 0 and relY == 0:
        relH = 0
    else:
        relH = hMath.normalizeAngle_180(
            hMath.RAD2DEG(math.atan2(relY, relX)) - selfH)

    forward = 0
    left = 0
    turnccw = 0
    if relD < CLOSE_WALK_RANGE and abs(relH) > 50:
        forward = relY
        left = relX
        turnccw = relH * 0.8
#        print "close walk and turn",relY,left,turnccw
    else:
        if abs(relH) > 80:  # stop and turn
            turnccw = relH * 0.8
        elif abs(relH) > 25:  # walk and turn
            turnccw = relH * 0.8
            forward = hMath.CLIP(relD, maxSpeed) * math.cos(
                hMath.DEG2RAD(relH))
#            print "walk and turn",forward, 0, turnccw
        else:  # ellipticalwalk and turn
            turnccw = hMath.CLIP(relH * 0.8, 25)
            forward = hMath.CLIP(relD, maxSpeed) * math.cos(
                hMath.DEG2RAD(relH))
    # finally, we walk
    Action.walk(forward, left, turnccw, minorWalkType=Action.SkeFastForwardMWT)
Esempio n. 11
0
def saGoToTarget(targetX, targetY, maxSpeed = Action.MAX_FORWARD, \
                    maxTurn = Action.MAX_TURN):

    selfX, selfY = Global.selfLoc.getPos()
    selfH = Global.selfLoc.getHeading()
    relX = targetX - selfX
    relY = targetY - selfY
    relD = hMath.getLength((relX, relY))
    distanceSquared = hMath.getDistSquaredBetween(targetX, targetY, selfX,
                                                  selfY)
    inCircle = distanceSquared <= hMath.SQUARE(40)
    faceH = hMath.getHeadingToFaceAt(Global.selfLoc, targetX, targetY)

    if not inCircle and abs(faceH) >= 30:
        Action.walk(0, 0, hMath.CLIP(faceH, maxTurn))

    elif not inCircle:

        #if sStealthDog.stealthDog(True):
        #    hFWHead.compulsoryAction = hFWHead.mustSeeBall
        #    hTrack.trackVisualBall()
        #    return

        Action.walk(maxSpeed, 0, hMath.CLIP(faceH / 1.5, maxTurn))

    else:
        if relX == 0 and relY == 0:
            relTheta = 0
        else:
            relTheta = hMath.normalizeAngle_180(
                hMath.RAD2DEG(math.atan2(relY, relX)) - selfH)

        forward = hMath.CLIP(relD, maxSpeed) * math.cos(
            hMath.DEG2RAD(relTheta))
        left = hMath.CLIP(relD, maxSpeed) * math.sin(hMath.DEG2RAD(relTheta))
        turnCCW = hMath.CLIP(relTheta, maxTurn)
        Action.walk(forward, left, turnCCW)
Esempio n. 12
0
def saGoToTargetFacingHeading(targetX, targetY, targetH, \
                            maxSpeed = None, maxTurn = None):

    if maxSpeed == None:
        maxSpeed = Action.MAX_FORWARD
    if maxTurn == None:
        maxTurn = Action.MAX_TURN

    # Variables relative to self localisation.
    selfPos = Global.selfLoc.getPos()
    selfH = Global.selfLoc.getHeading()
    relX = targetX - selfPos[0]
    relY = targetY - selfPos[1]
    relH = hMath.normalizeAngle_180(targetH - selfH)

    # take into account that as we turn, the position of our head will change
    relX  += Constant.DOG_NECK_TO_BODY_CENTER_OFFSET * \
             (math.cos(math.radians(selfH)) - math.cos(math.radians(targetH)))
    relY  += Constant.DOG_NECK_TO_BODY_CENTER_OFFSET * \
             (math.sin(math.radians(selfH)) - math.sin(math.radians(targetH)))
    relD = hMath.getLength((relX, relY))

    if relX == 0 and relY == 0:
        relTheta = 0
    else:
        relTheta = hMath.normalizeAngle_180(
            hMath.RAD2DEG(math.atan2(relY, relX)) - selfH)

    forward = hMath.CLIP(relD, maxSpeed) * math.cos(hMath.DEG2RAD(relTheta))
    left = hMath.CLIP(relD, maxSpeed) * math.sin(hMath.DEG2RAD(relTheta))
    turnccw = hMath.CLIP(relH, maxTurn)

    Action.walk(forward,
                left,
                turnccw,
                "ssd",
                minorWalkType=Action.SkeFastForwardMWT)
Esempio n. 13
0
def walk(target, selfPos, selfH):
    relX    = target[0] - selfPos[0]
    relY    = target[1] - selfPos[1]
    relD     = hMath.getLength((relX, relY))
    
    if relX == 0 and relY == 0:
        relThetaRad = 0
    else:
        relThetaRad = hMath.DEG2RAD(hMath.normalizeAngle_180(hMath.RAD2DEG(math.atan2(relY, relX)) - selfH))

    sinTheta = math.sin(relThetaRad)
    cosTheta = math.cos(relThetaRad)
    
    leftSign = relD * sinTheta
    leftAbs1 = abs(leftSign)    #leftAbs1: the distance left component
    if cosTheta != 0:        #leftAbs2: the max capping due to max forward
        leftAbs2 = abs(maxFwd * (sinTheta / cosTheta))
    else:
        leftAbs2 = 100000 # huge number
    #print "left1:", leftAbs1, "left2:", leftAbs2
    leftAbs = min(leftAbs1, leftAbs2, maxLeft)        
    left = hMath.getSign(leftAbs, leftSign)

    if sinTheta != 0:
        forward = left * (cosTheta / sinTheta)
    else:
        fwdSign = relD
        fwdAbs = min(maxFwd, abs(relD))
        forward = hMath.getSign(fwdAbs, fwdSign)

    if turningLeft:
        turnCCW = maxTurn
    else:
        turnCCW = -maxTurn
        
    print __name__, forward, left, turnCCW  
    Action.walk(forward, left, turnCCW,walkType=Action.SkellipticalWalkWT)
Esempio n. 14
0
 def calcTheta(self):
     if (self.__x == 0 or self.__y == 0):
         self.__theta = 0
     else:
         self.__theta = hMath.RAD2DEG(math.atan2(self.__y, self.__x))
Esempio n. 15
0
def continue_(desiredBH):
    global lastDBH, currentBopMode, cornerCut

    lastDBH = desiredBH
    box  = (Global.selfLoc.getPos()[1] < ((Constant.GOALBOX_DEPTH) + 25)) \
            or  (((currentBopMode == Constant.AVOIDBOX_BOP) \
                or (currentBopMode == Constant.POSTAVOID_BOP)) \
            and (Global.selfLoc.getPos()[1] < ((Constant.GOALBOX_DEPTH) + 50)))

    # Alex Osaka - don't do goal box avoidance but we quit the bird earlier
    box = False

    #if box:
    #    Global.myRole = Constant.DEFENDERGOALBOX

    # Global coordinate of where exactly I am heading at.
    desiredHeading = hMath.normalizeAngle_0_360(Global.selfLoc.getHeading() + \
                     (targetH - desiredBH))

    # Move with goalbox avoidance
    if (box and (desiredBH > 0) and (Global.selfLoc.getPos()[0] < \
          ((Constant.FIELD_WIDTH + Constant.GOALBOX_WIDTH) / 2.0) - cornerCut) \
          and (desiredHeading > 180) and (desiredHeading < (350))):
        print "box avoid 1, desiredHeading =", desiredHeading
        currentBopMode = Constant.AVOIDBOX_BOP
        px = ((Constant.FIELD_WIDTH + Constant.GOALBOX_WIDTH) / 2.0) \
                + boxPointOffset
        py = (Constant.GOALBOX_DEPTH) + boxPointOffset
        phead = hMath.normalizeAngle_180(hMath.RAD2DEG(math.atan2(py \
                    - Global.selfLoc.getPos()[1], \
                px - Global.selfLoc.getPos()[0])) - \
                    Global.selfLoc.getHeading())

        Action.walk(Action.MAX_FORWARD, 0, hMath.CLIP(phead / 2.0, maxTurn), \
                    minorWalkType=Action.SkeFastForwardMWT)
        return

    elif (box and (desiredBH < 0) and (Global.selfLoc.getPos()[0] > \
          ((Constant.FIELD_WIDTH - Constant.GOALBOX_WIDTH) / 2.0) + cornerCut) \
          and (desiredHeading > 190)):

        print "box avoid 2, desiredHeading =", desiredHeading
        currentBopMode = Constant.AVOIDBOX_BOP
        px = ((Constant.FIELD_WIDTH - Constant.GOALBOX_WIDTH) / 2.0) - \
                boxPointOffset
        py = (Constant.GOALBOX_DEPTH) + boxPointOffset

        phead = hMath.normalizeAngle_180(hMath.RAD2DEG(math.atan2(py - \
                    Global.selfLoc.getPos()[1],\
                px - Global.selfLoc.getPos()[0])) - Global.selfLoc.getHeading())

        Action.walk(Action.MAX_FORWARD, 0, hMath.CLIP(phead / 2.0, maxTurn), \
                    minorWalkType=Action.SkeFastForwardMWT)
        return

    elif (box and ((currentBopMode == Constant.AVOIDBOX_BOP) or \
            (currentBopMode == Constant.POSTAVOID_BOP))):
        currentBopMode = Constant.POSTAVOID_BOP
        relh = targetH - desiredBH
        if abs(relh) < 10:
            currentBopMode = Constant.NORMAL_BOP
        else:
            Action.walk(Action.MAX_FORWARD,
                        0,
                        hMath.CLIP(relh / 2.0, maxTurn),
                        minorWalkType=Action.SkeFastForwardMWT)
            if Debug.defenderDebug:
                print "!!!!!"
            return
    else:
        currentBopMode = Constant.NORMAL_BOP

    if Debug.defenderDebug:
        print "Before hoverToBall - currentBopMode: %f" % currentBopMode

    # Hover To Ball
    #relH    = Global.ballH - desiredBH
    relH = targetH - desiredBH

    if Debug.defenderDebug:
        print "relH: %f" % relH

    #Global.ballH = relH # ARGH I HATE LAST YEAR'S TEAM! SERIOUSLY, WTF?!?!
    # I agree! =p

    distSquared = True
    sHoverToBall.perform(targetDSquared, relH, distSquared)

    if gUseDodgyDog and sDodgyDog.shouldIBeDodgyAlongHeading(relH):
        sDodgyDog.dodgyDogAlongHeading(relH)
Esempio n. 16
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)
Esempio n. 17
0
def SmartSetBeacon(panLimit=90, distLimit=550):
    global localiseBeacon, lastBeacon

    # Get shared variables from elsewhere.
    selfLoc = Global.selfLoc
    cov = VisionLink.getGPSSelfCovariance()

    # Calculate the direction of the larger axis of the self covariance
    b = -(cov[0][0] + cov[1][1])
    c = cov[0][0] * cov[1][1] - cov[1][0] * cov[1][0]
    det = b * b - 4 * c

    if (det < 0.00001):
        sol = -b / 2
    else:
        sol = (-b + math.sqrt(det)) / 2

#    chooseCov = False   # Are we choosing a beacon to reduce covariance?
    if abs(cov[0][0] - sol) < 0.01 and cov[0][1] < 0.01:
        # If self position variance is circular, all beacons are equally good
        # to localise off, and so choose the one closest to current heading.
        # dHead is global heading we desire to stay close to
        if abs(cov[1][1] - sol) < 0.01:
            dHead = selfLoc.getHeading()
        else:
            dHead = hMath.RAD2DEG(math.atan2(-cov[1][0], cov[1][1] - sol))

    else:
        #chooseCov = True
        dHead = hMath.RAD2DEG(math.atan2(sol - cov[0][0], cov[0][1]))

    # Find the beacon that is closest to the variance direction.
    beaconPos = getBeaconCoords()
    bestHead = nextBestHead = 360
    localiseBeacon = None  # a tuple (x, y)
    nextBestBeacon = None

    #print beaconPos

    for beacon in beaconPos:
        relPos = map(lambda b, s: b - s, beacon, selfLoc.getPos())
        beaconHead = hMath.RAD2DEG(math.atan2(relPos[1], relPos[0]))
        beaconDist = hMath.getLength(relPos)
        localHead = hMath.normalizeAngle_180(beaconHead - selfLoc.getHeading())

        if abs(localHead) < panLimit and beaconDist < distLimit:
            #print beacon, localHead, beaconHead, dHead
            compHead = abs(hMath.normalizeAngle_180(dHead - beaconHead))
            if compHead > 90:
                compHead = 180 - compHead

            if compHead < bestHead:
                nextBestBeacon = localiseBeacon
                nextBestHead = bestHead
                localiseBeacon = beacon
                bestHead = compHead
            elif compHead < nextBestHead:
                nextBestBeacon = beacon
                nextBestHead = compHead

    #print "sActiveLocalise best =", localiseBeacon, "next =", nextBestBeacon

    # Don't choose the same beacon twice to reduce covariance. If we chose it
    # last time based on covariance and the covariance is still large that way
    # we likely didn't see it, so choose the next best
    if localiseBeacon == lastBeacon and nextBestBeacon != None:
        # print "Choosing a different beacon to last time"
        localiseBeacon = nextBestBeacon
        nextBestBeacon = None

    # Prefer not to look at a really close beacon - we don't get good
    # information
    if nextBestBeacon != None and \
        hMath.getDistanceBetween(selfLoc.getX(), selfLoc.getY(),\
                localiseBeacon[0], localiseBeacon[1]) < MIN_BEACON_DIST:
        # print "Choosing not to use close beacon"
        localiseBeacon = nextBestBeacon

    #print "Choosing beacon at", localiseBeacon, "frame", Global.frame
    lastBeacon = localiseBeacon

    if localiseBeacon == None:
        return False
    else:
        return True
Esempio 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])