Esempio n. 1
0
def get_valid_move_actions_(agent_direction: Grid4TransitionsEnum,
                            agent_position: Tuple[int, int],
                            rail: GridTransitionMap) -> Set[RailEnvNextAction]:
    """
    Get the valid move actions (forward, left, right) for an agent.

    TODO https://gitlab.aicrowd.com/flatland/flatland/issues/299 The implementation could probably be more efficient
    and more elegant. But given the few calls this has no priority now.

    Parameters
    ----------
    agent_direction : Grid4TransitionsEnum
    agent_position: Tuple[int,int]
    rail : GridTransitionMap


    Returns
    -------
    Set of `RailEnvNextAction` (tuples of (action,position,direction))
        Possible move actions (forward,left,right) and the next position/direction they lead to.
        It is not checked that the next cell is free.
    """
    valid_actions: Set[RailEnvNextAction] = OrderedSet()
    possible_transitions = rail.get_transitions(*agent_position,
                                                agent_direction)
    num_transitions = np.count_nonzero(possible_transitions)
    # Start from the current orientation, and see which transitions are available;
    # organize them as [left, forward, right], relative to the current orientation
    # If only one transition is possible, the forward branch is aligned with it.
    if rail.is_dead_end(agent_position):
        action = RailEnvActions.MOVE_FORWARD
        exit_direction = (agent_direction + 2) % 4
        if possible_transitions[exit_direction]:
            new_position = get_new_position(agent_position, exit_direction)
            valid_actions.add(
                RailEnvNextAction(action, new_position, exit_direction))
    elif num_transitions == 1:
        action = RailEnvActions.MOVE_FORWARD
        for new_direction in [(agent_direction + i) % 4 for i in range(-1, 2)]:
            if possible_transitions[new_direction]:
                new_position = get_new_position(agent_position, new_direction)
                valid_actions.add(
                    RailEnvNextAction(action, new_position, new_direction))
    else:
        for new_direction in [(agent_direction + i) % 4 for i in range(-1, 2)]:
            if possible_transitions[new_direction]:
                if new_direction == agent_direction:
                    action = RailEnvActions.MOVE_FORWARD
                elif new_direction == (agent_direction + 1) % 4:
                    action = RailEnvActions.MOVE_RIGHT
                elif new_direction == (agent_direction - 1) % 4:
                    action = RailEnvActions.MOVE_LEFT
                else:
                    raise Exception("Illegal state")

                new_position = get_new_position(agent_position, new_direction)
                valid_actions.add(
                    RailEnvNextAction(action, new_position, new_direction))
    return valid_actions
Esempio n. 2
0
    def get_altpaths_from(a_pos, a_dir):  # TODO depth
        next_actions = get_valid_move_actions_(a_dir, a_pos, distance_map.rail)

        if a_pos in cell_to_id_node:  # if this is a switch, recursive case
            paths = []
            for action in next_actions:
                first_step = WalkingElement(
                    a_pos, a_dir,
                    RailEnvNextAction(action.action, action.next_position,
                                      action.next_direction))
                recursive_altpaths = get_altpaths_from(action.next_position,
                                                       action.next_direction)

                for path in recursive_altpaths:
                    paths.append([first_step] + path)
            return paths
        else:  #Move Forward, I'm on a rail
            assert len(next_actions) == 1

            # get shortest path
            for action in next_actions:
                first_step = WalkingElement(
                    a_pos, a_dir,
                    RailEnvNextAction(action.action, action.next_position,
                                      action.next_direction))

            ret = []
            if a_pos == agent.target:
                ret = [[first_step]]
            else:
                shortest = get_shortest_paths(distance_map=distance_map,
                                              max_depth=max_depth,
                                              agent_handle=handle,
                                              position=action.next_position,
                                              direction=action.next_direction)

                if shortest[handle] != None:
                    ret = [[first_step] + shortest[handle]]

            return ret
Esempio n. 3
0
    def _shortest_path_for_agent(agent, a_position, a_direction):
        if a_position == None:
            if agent.status == RailAgentStatus.READY_TO_DEPART:
                a_position = agent.initial_position
            elif agent.status == RailAgentStatus.ACTIVE:
                a_position = agent.position
            elif agent.status == RailAgentStatus.DONE:
                a_position = agent.target
            else:
                shortest_paths[agent.handle] = None
                return
        if a_direction == None:
            a_direction = agent.direction

        shortest_paths[agent.handle] = []
        distance = math.inf
        depth = 0

        while (a_position != agent.target
               and (max_depth is None or depth < max_depth)):
            next_actions = get_valid_move_actions_(a_direction, a_position,
                                                   distance_map.rail)
            best_next_action = None
            for next_action in next_actions:
                next_action_distance = distance_map.get()[
                    agent.handle, next_action.next_position[0],
                    next_action.next_position[1], next_action.next_direction]
                if next_action_distance < distance:
                    best_next_action = next_action
                    distance = next_action_distance

            shortest_paths[agent.handle].append(
                WalkingElement(a_position, a_direction, best_next_action))
            depth += 1

            # if there is no way to continue, the rail must be disconnected!
            # (or distance map is incorrect)
            if best_next_action is None:
                shortest_paths[agent.handle] = None
                return

            a_position = best_next_action.next_position
            a_direction = best_next_action.next_direction
        if max_depth is None or depth < max_depth:
            shortest_paths[agent.handle].append(
                WalkingElement(
                    a_position, a_direction,
                    RailEnvNextAction(RailEnvActions.STOP_MOVING, a_position,
                                      a_direction)))
Esempio n. 4
0
def get_altpaths(handle, distance_map, max_depth,
                 cell_to_id_node):  # TODO max_depth
    agent = distance_map.agents[handle]

    if agent.status == RailAgentStatus.READY_TO_DEPART:
        position = agent.initial_position
    elif agent.status == RailAgentStatus.ACTIVE:
        position = agent.position
    elif agent.status == RailAgentStatus.DONE:
        position = agent.target
    else:  #Agent arrived
        return []

    direction = agent.direction
    distance = math.inf
    depth = 0

    assert position != agent.target

    def get_altpaths_from(a_pos, a_dir):  # TODO depth
        next_actions = get_valid_move_actions_(a_dir, a_pos, distance_map.rail)

        if a_pos in cell_to_id_node:  # if this is a switch, recursive case
            paths = []
            for action in next_actions:
                first_step = WalkingElement(
                    a_pos, a_dir,
                    RailEnvNextAction(action.action, action.next_position,
                                      action.next_direction))
                recursive_altpaths = get_altpaths_from(action.next_position,
                                                       action.next_direction)

                for path in recursive_altpaths:
                    paths.append([first_step] + path)
            return paths
        else:  #Move Forward, I'm on a rail
            assert len(next_actions) == 1

            # get shortest path
            for action in next_actions:
                first_step = WalkingElement(
                    a_pos, a_dir,
                    RailEnvNextAction(action.action, action.next_position,
                                      action.next_direction))

            ret = []
            if a_pos == agent.target:
                ret = [[first_step]]
            else:
                shortest = get_shortest_paths(distance_map=distance_map,
                                              max_depth=max_depth,
                                              agent_handle=handle,
                                              position=action.next_position,
                                              direction=action.next_direction)

                if shortest[handle] != None:
                    ret = [[first_step] + shortest[handle]]

            return ret

    next_actions = get_valid_move_actions_(direction, position,
                                           distance_map.rail)

    ret = []
    for action in next_actions:
        new_position = action.next_position
        new_direction = action.next_direction
        first_action = WalkingElement(
            position, direction,
            RailEnvNextAction(RailEnvActions.MOVE_FORWARD, new_position,
                              new_direction))

        altpaths = get_altpaths_from(new_position, new_direction)

        for altpath in altpaths:
            ret.append([first_action] + altpath)

    return ret