Beispiel #1
0
def setup():
    """
    One time setup. Inialize pixy and set sigint handler
    """
    pixy_init_status = pixy.pixy_init()
    if pixy_init_status != 0:
        print 'Error: pixy_init() [%d] ' % pixy_init_status
        pixy.pixy_error(pixy_init_status)
        return
    else:
        print "Pixy setup OK"
    signal.signal(signal.SIGINT, handle_SIGINT)
    pixy.pixy_cam_set_brightness(BRIGHTNESS)
    pixy.pixy_rcs_set_position(PIXY_RCS_PAN_CHANNEL, PIXY_RCS_CENTER_POS)

    if chatty:
        sayNow("I may not be the fastest but I have style")
        #say("SLEEP 2")
        time.sleep(2)
Beispiel #2
0
def loop():
    """
    Main loop, Gets blocks from pixy, analyzes target location,
    chooses action for robot and sends instruction to motors
    """
    global blocks, throttle, diffDrive, diffGain, bias, advance, turnError, currentTime, lastTime, objectDist, distError, panError_prev, distError_prev, panLoop, killed, lastFire
    global targetTime, targetTimeDifference, turnErrorAccumulator, exploreTime, exploreTimeDifference, turnErrorPrevious
    #if ser.in_waiting:
    #    print "Reading line from serial.."
    #    code = ser.readline().rstrip()
    #    print "Got IR code %s" % code
    #    killed = True
    #if code=="58391E4E" or code=="9DF14DB3" or code=="68B92":
    #    killed = True
    #
    #if code=="E4F74E5A" or code=="A8FA9FFD":
    #    killed = False

    ### Don't Change this ####
    #if killed:
    #    print "I'm hit!"
    #motors.setSpeeds(0, 0)
    #time.sleep(5)

    currentTime = datetime.now()
    # If no new blocks, don't do anything
    while not pixy.pixy_blocks_are_new() and run_flag:
        pass
    count = pixy.pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks)
    if count == 0:
        print "no blocks"
    # If negative blocks, something went wrong
    if count < 0:
        print 'Error: pixy_get_blocks() [%d] ' % count
        pixy.pixy_error(count)
        sys.exit(1)
    # if more than one block
    # Check which the largest block's signature and either do target chasing or
    # line following

    time_difference = currentTime - lastFire
    if time_difference.total_seconds() >= 1:
        print "Fire!"
        ser.write("FIRE\n")
        lastFire = currentTime

    lastTime = currentTime
    # if the largest block is the object to pursue, then prioritize this behavior

    throttle = 0
    panError = 0

    #first get biggest blue block
    biggestGreenBlockIndex = 999
    biggestTeamBlockIndex = 999
    biggestOpponentBlockIndex = 999
    currentIndex = 0
    targetFound = -1
    while currentIndex < 10:
        if blocks[
                currentIndex].signature == GREEN and biggestGreenBlockIndex == 999:
            biggestGreenBlockIndex = currentIndex
        if blocks[
                currentIndex].signature == Opponent and biggestOpponentBlockIndex == 999:
            biggestOpponentBlockIndex = currentIndex
        if blocks[
                currentIndex].signature == Team and biggestTeamBlockIndex == 999:
            biggestTeamBlockIndex = currentIndex
        currentIndex = currentIndex + 1
    avoidCollision = 0
    if biggestTeamBlockIndex < 999:
        if blocks[biggestTeamBlockIndex].height > 0.666 * PIXY_MAX_Y:
            avoidCollision = 1
    targetBlockIndex = min(biggestGreenBlockIndex, biggestOpponentBlockIndex)
    targetBigEnough = 0
    if targetBlockIndex != 999:
        if blocks[targetBlockIndex].width > 30:
            targetBigEnough = 1
    #print('biggest target index', min(biggestGreenBlockIndex,biggestOpponentBlockIndex), 'time', targetTimeDifference, 'team index', biggestTeamBlockIndex);
    if ((biggestGreenBlockIndex < biggestTeamBlockIndex
         or biggestOpponentBlockIndex < biggestTeamBlockIndex)
            and targetTimeDifference < 5 and avoidCollision == 0
            and targetBigEnough == 1):
        #if blocks[biggestGreenBlockIndex].signature == GREEN or blocks[biggestOpponentBlockIndex].signature == BLUE: #do we need this if statement?
        print("attacking")
        targetBlockIndex = min(biggestGreenBlockIndex,
                               biggestOpponentBlockIndex)
        if targetTime == 0:
            targetTime = currentTime
            turnErrorAccumulator = 0
            targetTimeDifference = 0
        if targetTimeDifference <= 1:
            throttle = 0.15
            objectDist = 300
        else:
            throttle = 0.5
            objectDist = refSize / (2 * math.tan(
                math.radians(blocks[targetBlockIndex].width * pix2ang_factor)))
        diffGain = 1
        #print( "Found Green signature",targetBlockIndex);
        panError = PIXY_X_CENTER - (
            blocks[targetBlockIndex].x
        )  # +int(35*math.sin(5*targetTimeDifference))) #100 - blocks[biggestGreenBlockIndex].x
        temp = blocks[targetBlockIndex].x + 10 * math.sin(
            5 * targetTimeDifference)
        #print ('object dist', objectDist, 'width',blocks[targetBlockIndex].width, 'newX', temp)
        # amount of steering depends on how much deviation is there
        diffDrive = diffGain * abs(float(panError)) / PIXY_X_CENTER
        distError = objectDist - targetDist
        # this is in float format with sign indicating advancing or retreating
        advance = driveGain * float(
            distError
        ) / refDist  #max(1,driveGain * float(distError) / refDist)
        #print('advance', advance, 'diffDrive', diffDrive)
        targetTimeDifference = (currentTime - targetTime).total_seconds()
        exploreTime = 0
        # if none of the blocks make sense, just pause
    else:
        if exploreTime == 0:
            exploreTime = currentTime
        elif exploreTimeDifference < 1.5:
            panError = 0
            #PIXY_X_CENTER-PIXY_MAX_X
            diffDrive = 0.5  #diffGain * abs(float(PIXY_X_CENTER-PIXY_MAX_X)) / PIXY_X_CENTER
            throttle = 0.4
            bias = 1
            advance = 1
            print("spinning")
        elif exploreTimeDifference < 3:
            panError = 0
            throttle = 0.6
            bias = 0
            diffDrive = 0
            advance = 1
            print("not spinning")
        targetTime = 0
        #turnErrorAccumulator = 0
        targetTimeDifference = 0
        print('no target blocks', 'biggest red block index',
              biggestTeamBlockIndex)
        print(exploreTimeDifference)
        exploreTimeDifference = (currentTime - exploreTime).total_seconds()
        if exploreTimeDifference >= 3:
            exploreTime = 0
            exploreTimeDifference = 0

    panLoop.update(panError)
    # Update pixy's pan position
    pixy.pixy_rcs_set_position(PIXY_RCS_PAN_CHANNEL, panLoop.m_pos)

    # if Pixy sees nothing recognizable, don't move.
    time_difference = currentTime - lastTime
    if time_difference.total_seconds() >= timeout:
        throttle = 0.0
        diffDrive = 1
        #print "4"

    # this is turning to left
    if panLoop.m_pos != PIXY_RCS_CENTER_POS:
        turnError = PIXY_RCS_CENTER_POS - panLoop.m_pos
        turnErrorAccumulator += turnError
        derivative = (turnError -
                      turnErrorPrevious) / float(PIXY_RCS_CENTER_POS)
        turnErrorPrevious = turnError
        bias = float(turnError) / float(
            PIXY_RCS_CENTER_POS) * h_pgain + i_control * float(
                turnErrorAccumulator) / float(
                    PIXY_RCS_CENTER_POS) + d_control * derivative

    #print('bias', bias)


##    if panLoop.m_pos > PIXY_RCS_CENTER_POS:
##        # should be still int32_t
##        turnError = panLoop.m_pos - PIXY_RCS_CENTER_POS
##        # <0 is turning left; currently only p-control is implemented
##        turnErrorAccumulator -= turnError
##        derivative = (turnError - turnErrorPrevious)/float(PIXY_RCS_CENTER_POS);
##        turnErrorPrevious = turnError;
##        bias = - float(turnError) / float(PIXY_RCS_CENTER_POS) * h_pgain + i_control*float(turnErrorAccumulator)/float(PIXY_RCS_CENTER_POS)
##        print('turn left bias', bias)
##        #print "5"
##
##    # this is turning to right
##    elif panLoop.m_pos < PIXY_RCS_CENTER_POS:
##        # should be still int32_t
##        turnError = PIXY_RCS_CENTER_POS - panLoop.m_pos
##        # >0 is turning left; currently only p-control is implemented
##        turnErrorAccumulator += turnError
##        bias = float(turnError) / float(PIXY_RCS_CENTER_POS) * h_pgain+i_control*float(turnErrorAccumulator) / float(PIXY_RCS_CENTER_POS) + d_control*
##        print('turn right bias', bias)
# print "6"
    drive()
    return run_flag
Beispiel #3
0
def hailmary(block_count):
    global throttle, diffDrive, diffGain, bias, advance, turnError, currentTime, lastTime, objectDist, distError, panError_prev, distError_prev
    if len(block_count) == 0:
        print "can't do hailmary with no blocks"
        return

    print "Attempting to hail Mary with %d block history" % len(block_count)
    leftTotal = 0.0
    rightTotal = 0.0
    for (left, right) in block_count:
        leftTotal += left
        rightTotal += right
    avgLeft = leftTotal / len(block_count)
    avgRight = rightTotal / len(block_count)
    print "Past %d frames had avg red blocks on (left=%d, right=%d)" % (
        AVG_N, avgLeft, avgRight)
    # Turn towards the preponderance of red blocks
    lastTime = currentTime
    if avgLeft > avgRight:
        print "Executing blind left turn"
        bias = -1
    elif avgRight > avgLeft:
        print "Executing blind right turn"
        bias = 1
    else:
        bias = 0
    if bias != 0:
        # Slow forward turn
        advance = 1
        throttle = 0.5
        diffDrive = 1
        # Reset pixy's head
        pixy.pixy_rcs_set_position(PIXY_RCS_PAN_CHANNEL, PIXY_RCS_CENTER_POS)
        normalDrive = False
    #If hailmary didn't work, hold on to your rosary beads, we're going hunting!
    else:
        # Need some kind of hunting behavior here
        #This situation usally arises when we're on a curve in one direction and want to sharply turn in the other direction
        #pan the camera until we find a red block, then go straight toward it.
        print "Execute search and destroy"
        i = 0
        noRedBlocks = True
        advance = -1  #if we can't find it, retreat
        while (noRedBlocks == True and i <= PIXY_RCS_MAX_POS):
            #while redblock not found
            #pan for red block
            print "Panning for red block. i:%d" % (i)
            pixy.pixy_rcs_set_position(PIXY_RCS_PAN_CHANNEL, i)
            count = pixy.pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks)
            largestBlock = blocks[0]
            #code stolen from earlier in file, maybe turn it into a function?
            if largestBlock.signature == 2:
                noRedBlocks = False
                panError = PIXY_X_CENTER - blocks[0].x
                p = panError / 40.0
                if p < 0:
                    p = -p
                if p > 0.8:
                    p = 0.8
                throttle = 0.9 - p
                diffDrive = 0.6
                print "p: %f, panError: %d, turnError: %d" % (p, panError,
                                                              turnError)
                advance = 1
            i = i + 10
Beispiel #4
0
def loop():
    """
    Main loop, Gets blocks from pixy, analyzes target location,
    chooses action for robot and sends instruction to motors
    """
    global startTime, throttle, diffDrive, diffGain, bias, advance, turnError, currentTime, lastTime, objectDist, distError, panError_prev, distError_prev, firstPass, pid_bias, last_turn

    currentTime = datetime.now()
    # If no new blocks, don't do anything
    while not pixy.pixy_blocks_are_new() and run_flag:
        pass

    if firstPass:
        say("Here goes")
        startTime = time.time()
        firstPass = False

    scene.get_frame()
    if scene.blocksSeen():
        lastTime = currentTime

    if finale:
        refuseToPlay()
        return False

    p = scene.panError
    if p < 0:
        p = -p
    incr = p / 300.0
    #print "panError: %f, incr: %f" % (scene.panError, incr)
    #if incr > 0.65:
    #    incr = 0.65
    throttle = initThrottle  # - incr / 1.5
    diffDrive = diffDriveStraight + incr

    # amount of steering depends on how much deviation is there
    #diffDrive = diffGain * abs(float(turnError)) / PIXY_X_CENTER
    # use full available throttle for charging forward
    advance = 1

    panLoop.update(scene.panError)

    # Update pixy's pan position
    pixy.pixy_rcs_set_position(PIXY_RCS_PAN_CHANNEL, panLoop.m_pos)

    # if Pixy sees nothing recognizable, don't move.
    # time_difference = currentTime - lastTime
    if not scene.seeCenter():  #time_difference.total_seconds() >= timeout:
        print "Stopping since see nothing"
        throttle = 0.0
        diffDrive = 1

    turn = 0

    # this is turning to left
    if panLoop.m_pos > PIXY_RCS_CENTER_POS:
        # should be still int32_t
        turnError = panLoop.m_pos - PIXY_RCS_CENTER_POS
        # <0 is turning left; currently only p-control is implemented
        turn = float(turnError) / float(PIXY_RCS_CENTER_POS)

    # this is turning to right
    elif panLoop.m_pos < PIXY_RCS_CENTER_POS:
        # should be still int32_t
        turnError = PIXY_RCS_CENTER_POS - panLoop.m_pos
        # >0 is turning left; currently only p-control is implemented
        turn = -float(turnError) / float(PIXY_RCS_CENTER_POS)

    pid.setPoint(0)
    pid_bias = pid.update(turn)
    #print "PID controller: SP=%2.2f PV=%2.2f -> OP=%2.2f" % (0, turn, pid_bias)
    last_turn = turn
    bias = pid_bias  # use PID controller on turn bias
    # TODO: parameterize drive()

    if bias < -0.3:
        say("Going left")
    if bias > 0.3:
        say("Going right")

    drive()
    return run_flag
Beispiel #5
0
def loop():
    """
    Main loop, Gets blocks from pixy, analyzes target location,
    chooses action for robot and sends instruction to motors
    """
    global blocks, throttle, diffDrive, diffGain, bias, advance, turnError, currentTime, lastTime, objectDist, distError, panError_prev, distError_prev, panLoop, killed, lastFire

    if ser.in_waiting:
        print "Reading line from serial.."
        code = ser.readline().rstrip()
        print "Got IR code %s" % code
        killed = True
        #if code=="58391E4E" or code=="9DF14DB3" or code=="68B92":
        #    killed = True
        #
        #if code=="E4F74E5A" or code=="A8FA9FFD":
        #    killed = False

    if killed:
        print "I'm hit!"
        motors.setSpeeds(0, 0)
        time.sleep(5)

    currentTime = datetime.now()
    # If no new blocks, don't do anything
    while not pixy.pixy_blocks_are_new() and run_flag:
        pass
    count = pixy.pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks)
    # If negative blocks, something went wrong
    if count < 0:
        print 'Error: pixy_get_blocks() [%d] ' % count
        pixy.pixy_error(count)
        sys.exit(1)
    # if more than one block
    # Check which the largest block's signature and either do target chasing or
    # line following
    if count > 0:

        time_difference = currentTime - lastFire
        if time_difference.total_seconds() >= 1:
            print "Fire!"
            ser.write("FIRE\n")
            lastFire = currentTime

        lastTime = currentTime
        # if the largest block is the object to pursue, then prioritize this behavior
        if blocks[0].signature == 1:
            panError = PIXY_X_CENTER - blocks[0].x
            objectDist = refSize1 / (2 * math.tan(math.radians(blocks[0].width * pix2ang_factor)))
            throttle = 0.5
            # amount of steering depends on how much deviation is there
            diffDrive = diffGain * abs(float(panError)) / PIXY_X_CENTER
            distError = objectDist - targetDist
            # this is in float format with sign indicating advancing or retreating
            advance = driveGain * float(distError) / refDist
        # if Pixy sees a guideline, perform line following algorithm
        elif blocks[0].signature == 2:
            panError = PIXY_X_CENTER-blocks[0].x
            throttle = 1.0
            diffDrive = 0.6
            # amount of steering depends on how much deviation is there
            # diffDrive = diffGain * abs(float(turnError)) / PIXY_X_CENTER
            # use full available throttle for charging forward
            advance = 1            
        # if none of the blocks make sense, just pause
        else:
            panError = 0
            throttle = 0.0
            diffDrive = 1
        panLoop.update(panError)

    # Update pixy's pan position
    pixy.pixy_rcs_set_position(PIXY_RCS_PAN_CHANNEL, panLoop.m_pos)

    # if Pixy sees nothing recognizable, don't move.
    time_difference = currentTime - lastTime
    if time_difference.total_seconds() >= timeout:
        throttle = 0.0
        diffDrive = 1

    # this is turning to left
    if panLoop.m_pos > PIXY_RCS_CENTER_POS:
        # should be still int32_t
        turnError = panLoop.m_pos - PIXY_RCS_CENTER_POS
        # <0 is turning left; currently only p-control is implemented
        bias = - float(turnError) / float(PIXY_RCS_CENTER_POS) * h_pgain
    # this is turning to right
    elif panLoop.m_pos < PIXY_RCS_CENTER_POS:
        # should be still int32_t
        turnError = PIXY_RCS_CENTER_POS - panLoop.m_pos
        # >0 is turning left; currently only p-control is implemented
        bias = float(turnError) / float(PIXY_RCS_CENTER_POS) * h_pgain
    drive()
    return run_flag