Beispiel #1
0
def go_tiles_simple(tiles):
    """
    Drives the robot n tiles forward
    """
    global wheel_distance
    st.forward()
    st.set_speed(AUTO_MODE, st.speeds[st.DEFAULT])
    start_dist = wheel_distance
    
    while wheel_distance - start_dist < 40 * tiles:
        get_distance()

    st.set_speed(AUTO_MODE, 0)
Beispiel #2
0
def stop_tower(num_hall_reads):
    """
    Stops the rotating tower when it points backwards
    """
    
    st.set_speed(AUTO_MODE, 0)
    st.set_speed(AUTO_MODE, 25, "tower")

    while num_hall_reads.value < 1:
        pass

    while num_hall_reads.value > 0:
        pass
    while num_hall_reads.value < 1:
        pass

    print('TOWER STOPPED')
    st.set_speed(AUTO_MODE, 0, "tower")
Beispiel #3
0
def turn(turn_deg, side, ir_values):
    global robot_dir, robot_pos, state, verified_grids, wheel_distance, x_gain, y_gain, ir_grid, ir_enabled
    st.set_speed(AUTO_MODE, 0)

    adjust_to_walls(ir_values)

    if ir_enabled:
        for i in range(4):
            while has_new_ir.value == 0:
                pass
            map_ir_neighbors(ir_grid, robot_pos, robot_dir, ir_values, tile_wall_count, has_new_ir)
    
    # Set turn direction
    if side == 'left' or side == LEFT:
        st.left()
        robot_dir = (robot_dir - (turn_deg//90)) % 4
    elif side == 'right' or side == RIGHT:
        st.right()
        robot_dir = (robot_dir + (turn_deg//90)) % 4
    else:
        return

    # Init turn regulator
    turn_pid = control.PID(turn_deg, 0.6, 0, 0)
    turn_pid.set_output_limits(70, 180)
    start_angle = gyro_value.value

    # Keep turning until the robot has reached 'turn_deg' angle
    while abs(gyro_value.value - start_angle) < turn_deg:
        turn_speed = turn_pid.compute(float(abs(gyro_value.value - start_angle)))
        st.set_speed(AUTO_MODE, turn_speed)

    # Break reset speed and driving direction
    st.set_speed(AUTO_MODE, 0)
    st.forward()
    st.steering_port.flushInput()
    time.sleep(0.1)
    wheel_distance = 0
   
    if travel_commands:
        state = TRAVEL
    else:
        state = WALL
Beispiel #4
0
def adjust_to_walls(ir_values):
    wall_side = detect_walls(ir_values)
    if wall_side == LEFT:
        while ir_values[IR_ID[FORWARD_LEFT]] - ir_values[IR_ID[BACKWARD_LEFT]] > 0:
            st.left()
            st.set_speed(AUTO_MODE, 80)
            time.sleep(0.03)
            st.set_speed(AUTO_MODE, 0)
            while has_new_ir.value == 0:
                time.sleep(0.01)
            has_new_ir.value = 0
            
        st.set_speed(AUTO_MODE, 0)
        while ir_values[IR_ID[FORWARD_LEFT]] - ir_values[IR_ID[BACKWARD_LEFT]] < 0:
            st.right()
            st.set_speed(AUTO_MODE, 80)
            time.sleep(0.03)
            st.set_speed(AUTO_MODE, 0)
            while has_new_ir.value == 0:
                time.sleep(0.01)
            has_new_ir.value = 0

        st.set_speed(AUTO_MODE, 0)
        st.forward()
        
    elif wall_side == RIGHT:
        while ir_values[IR_ID[FORWARD_RIGHT]] - ir_values[IR_ID[BACKWARD_RIGHT]] > 0:
            st.right()
            st.set_speed(AUTO_MODE, 80)
            time.sleep(0.03)
            st.set_speed(AUTO_MODE, 0)
            while has_new_ir.value == 0:
                time.sleep(0.01)
            has_new_ir.value = 0

        st.set_speed(AUTO_MODE, 0)
        while ir_values[IR_ID[FORWARD_RIGHT]] - ir_values[IR_ID[BACKWARD_RIGHT]] < 0:
            st.left()
            st.set_speed(AUTO_MODE, 80)
            time.sleep(0.03)
            st.set_speed(AUTO_MODE, 0)
            while has_new_ir.value == 0:
                time.sleep(0.01)
            has_new_ir.value = 0

        st.set_speed(AUTO_MODE, 0)
        st.forward()
        time.sleep(0.1)
Beispiel #5
0
def slam(ir_values, laser_values, mode, steering_cmd_man, pid_cons, gyro_value, num_laser_values, num_hall_reads, grid, shared_pos, move_cmd, has_new_ir):
    """
    Main loop for driving the robot.
    """
    global pid, state, robot_pos, robot_dir, travel_commands, verified_grids, wheel_distance, driven_path, tile_wall_count, update_ir_map, first_laser_read, ir_grid, ir_enabled

    # Open and clear the uart port to the steering module
    st.open_port()
    st.steering_port.flushInput()
    st.set_speed(AUTO_MODE, 0)
    st.forward()

    # PID vars
    pid_side = RIGHT
    control.forward_sensor = IR_ID[FORWARD_RIGHT]
    control.backward_sensor = IR_ID[BACKWARD_RIGHT]
    full_turn_start = time.time()

    # Laser vars
    adjusted_laser = []
    last_laser_list = []

    # Position vars
    start_pos = [pos for pos in robot_pos]
    driven_path = []
    prev_state = MANUAL

    # SLAM vars
    laser_counter = 0
    mapper = sm.Mapping()

    # Other
    search_mode = LASER
    debug_print = True
    

    laser_floor = [[0 for x in range(31)] for y in range(31)]
    
    
    while True:
        get_distance()
        update_path(robot_pos, shared_pos)

        #Updates final map with ir values
        update_final_ir(grid, ir_grid)

        
        if not mode.value:
            state = MANUAL
        
        if state != prev_state and debug_print:
            print('---------------')
            print('CURRENT STATE: ' + STATES[state])
            print('CURRENT DIRECTION: ' + DIRECTIONS[robot_dir])
            print('CURRENT POSITION: ' + str(robot_pos))
            print('PID SIDE: ' + str(pid_side))
            

        # Update pid values from the laptop program
        with pid_cons.get_lock():
            if pid_cons[0] != -1:
                if pid_cons[0] == 0:
                    pid.Kp = pid_cons[1]
                elif pid_cons[0] == 1:
                    pid.Ki = pid_cons[1]
                elif pid_cons[0] == 2:
                    pid.Kd = pid_cons[1]
                pid_cons[0] = -1
                print("PID: " + str(pid.Kp) + " " + str(pid.Ki) + " " + str(pid.Kd)) 

        # Initial state. Should not enter here again        
        if state == START:
            prev_state = START

            # Assign values to surrounding tiles from START position
            set_grid_value_2d(15, 14, EMPTY_TILE, ir_grid)
            set_grid_value_2d(15, 15, EMPTY_TILE, ir_grid)
            set_grid_value_2d(15, 16, WALL_TILE, ir_grid)
            set_grid_value_2d(14, 15, WALL_TILE, ir_grid)
            set_grid_value_2d(16, 15, WALL_TILE, ir_grid)
            # Enter WALL to exit the starting cell
            state = WALL
            continue

        # Main state when following walls
        elif state == WALL:
            prev_state = WALL

            # If the room is closed, go home
            if path.closed_room(grid, robot_pos):
                state = TRAVEL
                ir_enabled = False
                continue
            
            # Update map
            if has_new_ir.value == 1 and check_centered() and ir_enabled:
                update_ir_map = True
                map_ir_neighbors(ir_grid, robot_pos, robot_dir, ir_values, tile_wall_count, has_new_ir)
            # Enters SLAM state if there arent any walls around
            if search_mode == LASER and not [ir_values[i] for i in range(NUM_SENSORS) if ir_values[i] != EMPTY_CHECK and i != 1]:
                state = SLAM
                # Break and start the laser tower
                st.set_speed(AUTO_MODE, 0, 'both')
                continue

            # Check for a wall in front of the robot
            if ir_values[IR_ID[FORWARD]] <= FORWARD_CHECK:
                #set front as wall
                _x, _y = GRID_INDEX_VALUES[robot_dir][0]
                set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
                tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
                # Switch to dead end state if there are walls on both sides of the robot
                if ir_values[IR_ID[FORWARD_RIGHT]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD_LEFT]] < EMPTY_CHECK:
                    state = DEAD_END

                # Switch to turn left state if there is a wall on the right
                elif ir_values[IR_ID[FORWARD_RIGHT]] < EMPTY_CHECK:
                    state = TURN_LEFT

                # Switch to turn right state if there is a wall on the left
                elif ir_values[IR_ID[FORWARD_LEFT]] < EMPTY_CHECK:
                    state = TURN_RIGHT

                # Find closest unexplored if there are no walls on the sides
                else:
                    #map_ir_neighbors(ir_grid, robot_pos, robot_dir, ir_values, tile_wall_count)
                    _x, _y = GRID_INDEX_VALUES[robot_dir][2]
                    set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, EMPTY_TILE, ir_grid)
                    tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,0,100]
                    _x, _y = GRID_INDEX_VALUES[robot_dir][3]
                    set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, EMPTY_TILE, ir_grid)
                    tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,0,100]
                    update_ir_map = True
                    state = TRAVEL
                continue

            # Check if the wall ends on the left side
            if ir_values[IR_ID[FORWARD_LEFT]] == EMPTY_CHECK and ir_values[IR_ID[BACKWARD_LEFT]] < EMPTY_CHECK:
                num_closed_walls = 0  # Number of closed walls in turn
                st.set_speed(AUTO_MODE, st.speeds[st.DEFAULT])
                # Drive out past walls and stop
                while ir_values[IR_ID[BACKWARD_LEFT]] != EMPTY_CHECK:
                    get_distance()

                # Check forward distance
                if ir_values[IR_ID[FORWARD]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD]] > 12:
                    _x, _y = GRID_INDEX_VALUES[robot_dir][0]
                    set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
                    tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
                    print('FRONT WALL DETECTED')
                    num_closed_walls += 1
                    while ir_values[IR_ID[FORWARD]] > 12:
                        pass
                else:
                    go_tiles_simple(0.3)

                st.set_speed(AUTO_MODE, 0)
                    
                if ir_values[IR_ID[FORWARD_RIGHT]] < EMPTY_CHECK and ir_values[IR_ID[BACKWARD_RIGHT]] < EMPTY_CHECK:
                    print('RIGHT WALL DETECTED')
                    num_closed_walls += 1

                st.set_speed(AUTO_MODE, 0)

                # Update the map
                #for i in range(100):
                print('Waiting for new ir')
                if ir_enabled:
                    while has_new_ir.value == 0:
                        pass
                        map_ir_neighbors(ir_grid, robot_pos, robot_dir, ir_values, tile_wall_count, has_new_ir)
                        update_ir_map = True
                    
                # Stay here if the robot is using the laser
                if search_mode == LASER and num_closed_walls < 2: 
                    print('LASER SEARCH ACTIVE, SKIPPING REST AND ENTER SLAM')
                    state = SLAM
                    continue

                # Wall continues on the right side: Follow it
                else:
                    print('WALL CONTINUES ON THE RIGHT SIDE, FOLLOW IT')
                    pid_side = RIGHT
                    continue
                """
                # Wall continues on the right side: Follow it
                if ir_values[IR_ID[FORWARD_RIGHT]] <= RIGHT_CHECK and ir_values[IR_ID[BACKWARD_RIGHT]] <= RIGHT_CHECK:
                    print('WALL CONTINUES ON THE RIGHT SIDE, FOLLOW IT')
                    pid_side = RIGHT
                    continue
                
                # The robot is either standing in a t-turn or a four-turn
                else:
                    print('T OR 4 TURN')
                    state = TRAVEL
                    continue
                """
                continue

            # Check if the wall ends on the right side
            if ir_values[IR_ID[FORWARD_RIGHT]] == EMPTY_CHECK and ir_values[IR_ID[BACKWARD_RIGHT]] < EMPTY_CHECK:
                num_closed_walls = 0  # Number of closed walls in turn
                st.set_speed(AUTO_MODE, st.speeds[st.DEFAULT])
                # Drive out past walls and stop
                while ir_values[IR_ID[BACKWARD_RIGHT]] != EMPTY_CHECK:
                    get_distance()

                # Check forward distance
                if ir_values[IR_ID[FORWARD]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD]] > 12:
                    _x, _y = GRID_INDEX_VALUES[robot_dir][0]
                    set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
                    tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
                    num_closed_walls += 1
                    while ir_values[IR_ID[FORWARD]] > 12:
                        pass
                else:
                    go_tiles_simple(0.3) 

                st.set_speed(AUTO_MODE, 0)

                if ir_values[IR_ID[FORWARD_LEFT]] < EMPTY_CHECK and ir_values[IR_ID[BACKWARD_LEFT]] < EMPTY_CHECK:
                    print('LEFT WALL DETECTED')
                    num_closed_walls += 1

                # Update the map
                if ir_enabled:
                    while has_new_ir.value == 0:
                        pass
                        map_ir_neighbors(ir_grid, robot_pos, robot_dir, ir_values, tile_wall_count, has_new_ir)
                        update_ir_map = True
                # Stay here if the robot is using the laser
                if search_mode == LASER and num_closed_walls < 2:
                    print('LASER SEARCH ACTIVE, SKIPPING REST AND ENTER SLAM')
                    state = SLAM
                    continue
                
                # Wall continues on the left side: Follow it
                else:
                    print('WALL CONTINUES ON THE LEFT SIDE, FOLLOW IT')
                    pid_side = LEFT
                    continue
                """
                
                if ir_values[IR_ID[FORWARD_LEFT]] <= LEFT_CHECK and ir_values[IR_ID[BACKWARD_LEFT]] <= LEFT_CHECK:
                    print('WALL CONTINUES ON THE LEFT SIDE, FOLLOW IT')
                    pid_side = LEFT
                    continue

                
                # The robot is either standing in a t-turn or a four-turn
                else:
                    print('T OR 4 TURN')
                    state = TRAVEL
                    continue
                """
                continue


            # Use pid to follow the wall
            pid_side = detect_walls(ir_values)
            if pid_side == LEFT:
                pid.reversed = True
            elif pid_side == RIGHT:
                pid.reversed = False

            if pid_side != None:
                pid.enabled = True
                turn_factor = pid.compute(ir_values)

                if st.speeds[st.LEFT] != abs(int(st.speeds[st.DEFAULT] - turn_factor)):
                    st.set_speed(AUTO_MODE, abs(st.speeds[st.DEFAULT] - turn_factor), "left")
                if st.speeds[st.RIGHT] != abs(int(st.speeds[st.DEFAULT] + turn_factor)):
                    st.set_speed(AUTO_MODE, abs(st.speeds[st.DEFAULT] + turn_factor), "right")
            else:
                pid.enabled = False
                if st.speeds[st.LEFT] != abs(int(st.speeds[st.DEFAULT])):
                    st.set_speed(AUTO_MODE, abs(st.speeds[st.DEFAULT]), "left")
                if st.speeds[st.RIGHT] != abs(int(st.speeds[st.DEFAULT])):
                    st.set_speed(AUTO_MODE, abs(st.speeds[st.DEFAULT]), "right")

            continue

        elif state == TRAVEL:
            prev_state = TRAVEL
            
            # Generate robot commands which, when executed,
            # will drive the robot to the nearest unexplored tile
            if not travel_commands:
                if path.closed_room(grid, robot_pos):
                    p = path.a_star(grid, robot_pos, [15, 15])
                    ir_enabled = False
                else:
                    p = path.find_closest_unexplored(grid, robot_pos)
                travel_commands = path.follow_path(p, robot_dir)
                print('GENERATED COMMANDS: ' + str(travel_commands))

            # Excute travel commands
            if travel_commands:
                c = travel_commands.pop(0)
                move_cmd.value = c
                
                parts = c.split('_')
                if parts[0] == "go":
                    tiles = int(parts[2])
                    go_tiles(tiles, ir_values, shared_pos, ir_grid)
                elif parts[0] == "turn":
                    turn_deg = int(parts[2])
                    turn(turn_deg, parts[1], ir_values)
                time.sleep(0.2)

                # Check if home
                print('CHECKING IF HOME', str(robot_pos))
                if not travel_commands and int_robot_pos(robot_pos) == int_robot_pos(start_pos):
                    st.set_speed(AUTO_MODE, 0)
                    mode.value = 0
                    state = MANUAL
                    continue

                elif not travel_commands:
                    if ir_values[IR_ID[FORWARD_LEFT]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD_RIGHT]] < EMPTY_CHECK:
                        state = WALL
                    elif (ir_values[IR_ID[FORWARD_LEFT]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD]] < EMPTY_CHECK) or \
                       (ir_values[IR_ID[FORWARD_RIGHT]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD]] < EMPTY_CHECK):
                        for i in range(4):
                            while has_new_ir.value == 0:
                                pass
                            current_ir_values = [ir for ir in ir_values]
                            map_ir_neighbors(ir_grid, robot_pos, robot_dir, current_ir_values, tile_wall_count, has_new_ir)
                            update_ir_map = True
                            update_final_ir(grid, ir_grid)
                        state = TRAVEL
                    else:
                        state = SLAM
                    continue
                    
            else:
                state = WALL
            continue

        elif state == TURN_LEFT:
            prev_state = TURN_LEFT
            turn(90, 'left', ir_values)
            # Reset verify counter on neighbour tiles so they are verified again after the turn
            reset_neighbors(robot_pos, tile_wall_count)
            
            # Force a new position after a turn to keep the robot aligned with the grid
            
            int_x = int(robot_pos[0])
            int_y = int(robot_pos[1])

            robot_pos[0] = int_x + 0.5
            robot_pos[1] = int_y + 0.5
            
            state = WALL
            continue
            
        elif state == TURN_RIGHT:
            prev_state = TURN_RIGHT
            turn(90, 'right', ir_values)
            # Reset verify counter on neighbour tiles so they are verified again after the turn
            reset_neighbors(robot_pos, tile_wall_count)

            # Force a new position after a turn to keep the robot aligned with the grid
            int_x = int(robot_pos[0])
            int_y = int(robot_pos[1])

            robot_pos[0] = int_x + 0.5
            robot_pos[1] = int_y + 0.5
            
            state = WALL
            continue
            
        elif state == DEAD_END:
            prev_state = DEAD_END
            #front
            _x, _y = GRID_INDEX_VALUES[robot_dir][0]
            set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
            tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
            #right
            _x, _y = GRID_INDEX_VALUES[robot_dir][2]
            set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
            tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
            #left
            _x, _y = GRID_INDEX_VALUES[robot_dir][3]
            set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
            tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
            turn(180, 'left', ir_values)
            state = WALL
            continue

        elif state == SLAM:
            prev_state = SLAM
            pid.enabled = False

            if not laser_counter:
                for i in range(4):
                    while has_new_ir.value == 0:
                        pass
                    current_ir_values = [ir for ir in ir_values]
                    map_ir_neighbors(ir_grid, robot_pos, robot_dir, current_ir_values, tile_wall_count, has_new_ir)
                update_ir_map = True
                update_final_ir(grid, ir_grid)
            if not first_laser_read:
                for y in range(MAP_SIZE):
                    for x in range(MAP_SIZE):
                        set_grid_value(x,y, ir_grid[y][x], grid)

            

            
            #print('\nIN SLAM STATE, SET SPEED 0')
            st.set_speed(AUTO_MODE, 0)
            time.sleep(0.5)
            if path.closed_room(grid, robot_pos):
                # Find closest path home
                print('ROOM IS CLOSED, GO HOME')
                stop_tower(num_hall_reads)
                path_home = path.a_star(grid, robot_pos, [15.5, 15.5])
                travel_commands = path.follow_path(path_home, robot_dir)
                print("Path home: " + str(travel_commands))
                state = TRAVEL
                ir_enabled = False
                continue
            else:
                # Check if closest unexplored tile is too far away, if so then go there
                unexplored_tiles = path.bfs(grid, robot_pos, find_unidentified=True)
                if unexplored_tiles and len(path.a_star(grid, robot_pos, unexplored_tiles[0])) > 7:
                    state = TRAVEL
                    continue
                    
                st.set_speed(AUTO_MODE, 50, 'tower')
            
            #  Wait for new laser values
            while 0 < num_laser_values.value < 520 and num_hall_reads.value == 0:
                pass

            
            if laser_counter < mapper.maxiter:
                #print('NOT ENOUGH READS, UPDATING MAP')
                # Copy laser sensor reads from shared array if there are less then 520 reads
                laser_list = []

                with laser_values.get_lock():
                    if num_laser_values.value > 520:
                        with num_laser_values.get_lock():
                            num_laser_values.value = 0
                        continue
                    laser_list = [laser_values[i] for i in range(num_laser_values.value)]

                # Update map based on the new sensor values
                if laser_list:
                    laser_counter += 1
                    
                    # Generate submap
                    generated_map = slammer.mapper(laser_list)

                    # Add the submap to the 'final' one
                    mapper.add_submap(generated_map[0], generated_map[1], (int(robot_pos[0]), int(robot_pos[1])), robot_dir)

                    fingrid = [[UNKNOWN_TILE for x in range(MAP_SIZE)] for y in range(MAP_SIZE)]
                    for y in range(MAP_SIZE):
                        for x in range(MAP_SIZE):
                            fingrid[y][x] = get_grid_value(x,y,grid)
                    
                    mapper.generate_map(fingrid)
                    
                    
                   
            elif laser_counter >= mapper.maxiter:


                if (not first_laser_read):
                    first_laser_read = True
                
                print('\nENOUGH LASER READS, STOPPING TOWER', laser_counter)
                laser_counter = 0
                stop_tower(num_hall_reads)

                raycast_map = [[0 for i in range(MAP_SIZE)] for j in range(MAP_SIZE)]
                for y in range(31):
                    for x in range(31):
                        value = 0
                        if (mapper.submaps):
                            value = float(mapper.finalmap[y][x]) / len(mapper.submaps)
                        tile_value = UNKNOWN_TILE
                        if (value >= 0.5):
                            tile_value = WALL_TILE
                        raycast_map[y][x] = tile_value
                

                subp = sm.slice_submap(ir_grid, (int(robot_pos[0]), int(robot_pos[1])))

                raycast_map = sm.returnFinal(raycast_map, subp[0], subp[1], (int(robot_pos[0]), int(robot_pos[1])))
                ray_floor = sm.raycast_floor(raycast_map,(int(robot_pos[0]), int(robot_pos[1])))
                
                for y in range(31):
                    for x in range(31):
                        ray_val = raycast_map[y][x]
                        #las_val = laser_floor[y][x]
                        rayflorval = ray_floor[y][x]
                        if (rayflorval == 1):
                            laser_floor[y][x] = rayflorval
                        las_val = laser_floor[y][x]
                        if (las_val == 1):
                            if (ray_val < 2):
                                raycast_map[y][x] = 1

                
                for i in range(31):
                    for j in range(31):                            
                        value = raycast_map[i][j]
                        if (value >= 2):
                            value = 2
                        set_grid_value(j, i, value, grid)

                mapper.remove_bad_values()

                        
                if path.closed_room(grid, robot_pos):
                    # Find closest path home
                    print('ROOM IS CLOSED, GO HOME')
                    path_home = path.a_star(grid, robot_pos, [15.5, 15.5])
                    travel_commands = path.follow_path(path_home, robot_dir)
                    print("Path home: " + str(travel_commands))
                    state = TRAVEL
                    ir_enabled = False
                else:
                    print('ROOM IS NOT CLOSED, ENTER TRAVEL')
                    state = TRAVEL
                
            #state = WALL
            continue

        # Executes commands sent from the laptop
        elif state == MANUAL:
            st.set_speed(AUTO_MODE, 0)
            prev_state = MANUAL
            stop_tower(num_hall_reads)
            time.sleep(1)
            
            # Enter autonomous mode
            if mode.value == 1:
                state = START
                continue

            # Disable pid and start recieving commands
            pid.enabled = False
            st.steering_serial(steering_cmd_man, mode, ir_values)  # Blocks
            
            st.steering_port.flushInput()
            st.forward()
            continue
Beispiel #6
0
def go_tiles(tiles, ir_values, shared_pos, ir_grid, enable_pid=True):
    """
    Drives the robot n tiles forward.
    It uses two pid regulators. One for controlling the speed
    when there are no walls around and one for keeping a distance from walls.
    """
    global robot_pos, robot_dir, wheel_distance, test_pos, tile_wall_count, update_ir_map, first_laser_read, ir_enabled
    prev_pos = int_robot_pos(robot_pos)
    st.set_speed(AUTO_MODE, 0)
    st.forward()

    adjust_to_walls(ir_values)

    compare_axis = None
    sign = 0
    if robot_dir == NORTH:
        compare_axis = 1
        sign = -1
    elif robot_dir == EAST:
        compare_axis = 0
        sign = 1
    elif robot_dir == SOUTH:
        compare_axis = 1
        sign = 1
    elif robot_dir == WEST:
        compare_axis = 0
        sign = -1

    start = robot_pos[compare_axis]
    dest = 0

    if sign == 1:
        dest = math.ceil(robot_pos[compare_axis]) + (sign * 0.5)
    elif sign == -1:
        dest = int(round(robot_pos[compare_axis],1)) + (sign * 0.5)

    
    to_drive = abs(round(dest - start, 1)) + (tiles - 1)  # Distance to drive in tiles
    wheel_distance = 0
    speed_pid = control.PID(to_drive * 40, 0.6, 0, 0)
    speed_pid.set_output_limits(st.speeds[st.DEFAULT], 125)
    print('Attempting to move %f from pos %s %f' % (to_drive, str(robot_pos), dest))

    pid_side = None
    current_ir_values = [25 for i in range(6)]
    prev_ir_values = [25 for i in range(6)]

    # Clear distance inputs and set default speed
    st.steering_port.flushInput()
    st.set_speed(AUTO_MODE, st.speeds[st.DEFAULT])
    
    # Move until correct number of tiles are traversed
    while wheel_distance < to_drive * 40:
        get_distance()
        # Update map when centered
        if has_new_ir.value == 1:
            with ir_values.get_lock():
                current_ir_values = [ir for ir in ir_values]
            with has_new_ir.get_lock():
                has_new_ir.value = 0
        else:
            continue
        
        if check_centered() and ir_enabled:
            map_ir_neighbors(ir_grid, robot_pos, robot_dir, current_ir_values, tile_wall_count, has_new_ir)
            update_ir_map = True
            update_final_ir(grid, ir_grid)
        update_path(robot_pos, shared_pos)
        
        # Break if the robot is about to drive into a wall
        if current_ir_values[IR_ID[FORWARD]] < 8:
            st.set_speed(AUTO_MODE, 0)
            _x, _y = GRID_INDEX_VALUES[robot_dir][0]
            set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
            tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]

            st.backward()
            while has_new_ir.value == 0:
                time.sleep(0.1)
            # Back
            while ir_values[IR_ID[FORWARD]] < 5:
                st.set_speed(AUTO_MODE, 60)
                time.sleep(0.03)
                st.set_speed(AUTO_MODE, 0)
                while has_new_ir.value == 0:
                    time.sleep(0.01)
                has_new_ir.value = 0
                
            st.set_speed(AUTO_MODE, 0)
            st.steering_port.flushInput()
            st.forward()
            break

        # Enable pid if the robot is driving close to a wall
        pid_side = detect_walls(current_ir_values, pid_side)
        
        if enable_pid and pid_side != None:
            #st.set_speed(AUTO_MODE, st.speeds[st.DEFAULT])
            if pid_side == LEFT:
                pid.reversed = True
                if abs(current_ir_values[IR_ID[FORWARD_LEFT]] - prev_ir_values[IR_ID[FORWARD_LEFT]]) > 4:
                    prev_ir_values = [ir for ir in current_ir_values]
                    continue
            elif pid_side == RIGHT:
                pid.reversed = False
                if abs(current_ir_values[IR_ID[FORWARD_RIGHT]] - prev_ir_values[IR_ID[FORWARD_RIGHT]]) > 4:
                    prev_ir_values = [ir for ir in current_ir_values]
                    continue

                
            pid.enabled = True
            turn_factor = pid.compute(current_ir_values)
            
            if st.speeds[st.LEFT] != abs(int(st.speeds[st.DEFAULT] - turn_factor)):
                st.set_speed(AUTO_MODE, abs(st.speeds[st.DEFAULT] - turn_factor), "left")
            if st.speeds[st.RIGHT] != abs(int(st.speeds[st.DEFAULT] + turn_factor)):
                st.set_speed(AUTO_MODE, abs(st.speeds[st.DEFAULT] + turn_factor), "right")

        # No walls nearby. Use pid to determine forward speed
        else:
            pid.enabled = False
            speed = speed_pid.compute(float(wheel_distance))
            st.set_speed(AUTO_MODE, speed)

        # Update driven distance
        get_distance()
        prev_ir_values = [ir for ir in current_ir_values]

    pid.enabled = False
    
    if ir_values[IR_ID[FORWARD]] < EMPTY_CHECK and ir_values[IR_ID[FORWARD]] > 12:
        st.set_speed(AUTO_MODE, 80)
        _x, _y = GRID_INDEX_VALUES[robot_dir][0]
        set_grid_value_2d(int(robot_pos[0])+_x, int(robot_pos[1])+_y, WALL_TILE, ir_grid)
        tile_wall_count[(int(robot_pos[0]) + _x, int(robot_pos[1]) + _y)] = [100,100,0]
        while ir_values[IR_ID[FORWARD]] > 12:
            pass

    # The robot has reached its target, set speed to 0
    st.set_speed(AUTO_MODE, 0)