Esempio n. 1
0
def avg_distance_traveled_test(paths):
    total_dist = 0
    for path in paths:
        path_dist = 0
        for i in range(1, len(path)):
            path_dist += line.distance(path[i].end_effector_pos,
                                       path[i - 1].end_effector_pos)
        total_dist += path_dist

    return total_dist / len(paths)
Esempio n. 2
0
def find_path(target_end_point,
              start_angles,
              obs,
              n_iter=150,
              radius=.01,
              step_size=.1):
    """Executes the Optimistic Predictive Cost algorithm to find a collision-free path between two configurations.
    Arguments:
        end_node: A Node representing the target arm configuration.
        start_angles: A float array representing the initial angles of the arm.
        obs: An array of float arrays representing obstacles.
        n_iter: The maximum amount of iterations to find a path.
        radius: The maximum distance from the target end effector position needed to converge.
        step_size: The distance, in radians, between each edge in the graph.
    Returns:
        A graph g containing a collision-free path if success = True, or no path if success = False.
      """
    g = Graph(start_angles, None, target_end_point)
    g.ranking.append(g.start_node)
    g.end_node = Node.from_point(target_end_point)

    close_to_end = False

    for i in range(n_iter):
        try:
            best_node = g.ranking.pop(0)
        except IndexError:
            global stack_empty_error
            stack_empty_error += 1
            return g

        if arm_is_colliding_prisms(best_node, obs):
            continue

        dist_to_goal = line.distance(best_node.end_effector_pos,
                                     target_end_point)
        if dist_to_goal < radius:
            g.end_node = best_node
            g.success = True
            return g

        # if dist_to_goal < 10 * radius and not close_to_end:
        #     step_size /= 10
        #     close_to_end = True

        expand(best_node, 4, step_size, g)

    return g
Esempio n. 3
0
def generate_linear_path(start_angles, end_angles, num_iter):
    """Generates a linear path of arm configurations that moves an arm configuration from start_angles to end_angles.

    Args:
        start_angles: The initial angles of the arm.
        end_angles: The desired angles of the arm.
        num_iter: The number of angle configurations to be generated on the path in between the start and end positions.
    Returns:
        a path of nodes from start_pos to end_pos, with [num_iter] iterations of equal length.
    """

    step_sizes = compute_step_sizes(start_angles, end_angles, num_iter)

    g = Graph(start_angles, end_angles)

    current_angles = start_angles
    current_idx = 0
    current_node = g.nodes[0]
    for i in range(num_iter):
        new_angles = np.add(current_angles, step_sizes)
        new_angles = np.mod(new_angles, math.pi * 2)

        new_node = Node(new_angles)

        new_idx = g.add_vex(new_node, current_node)

        dist = line.distance(new_node.end_effector_pos,
                             current_node.end_effector_pos)

        current_angles = new_angles
        current_idx = new_idx
        current_node = new_node

        if i == num_iter - 1:
            rounded_current = np.around(current_angles, decimals=4)
            rounded_end = np.around(end_angles, decimals=4)

            if not np.array_equal(rounded_current, rounded_end):
                return g, False
    return g, True
Esempio n. 4
0
    def add_vex(self, node, parent):
        try:
            idx = self.node_to_index[node]
        except KeyError:
            parent_idx = self.node_to_index[parent]
            idx = len(self.nodes)

            dist = parent.optimistic_cost + Node.distance(parent, node)
            node.optimistic_cost = dist

            self.neighbors[idx] = []

            self.add_edge(idx, parent_idx, Node.distance(parent, node))

            self.nodes.append(node)
            self.node_to_index[node] = idx
            self.ranking.append(node)
            self.ranking.sort(key=lambda n: dist + line.distance(
                n.end_effector_pos, self.target_end_pos))
            self.end_effectors = np.vstack(
                [self.end_effectors, node.end_effector_pos])
        return idx
 def distance(cls, node1, node2):
     return line.distance(node1.end_effector_pos, node2.end_effector_pos)
def rrt(start_angles,
        end_angles,
        obstacles,
        n_iter=300,
        radius=0.02,
        angle_threshold=1,
        stepSize=.05,
        heuristic_threshold=10):
    """Uses the RRT algorithm to determine a collision-free path from start_angles to end_angles.

    Args:
        start_angles: An array of length 5 representing the initial angle configuration of the arm.
        end_angles: An array of length 5 representing the desired angle configuration.
        obstacles: An array of float arrays representing cube obstacles.
        n_iter: Maximum number of iterations to find a path.
        radius: Maximum distance between the final end effector position and the second-to-last position in a path.
        angle_threshold: Maximum distance between the final angles and the second-to-last angles in a path.
        stepSize: Distance between nodes in the graph.
        heuristic_threshold: Maximum number of times a new node can fail to expand from any given node in the graph.

    Returns:
        An instance of rrtgraph.Graph containing a list of instances of Node, and a path of Node instances between
        the start and end nodes, if successful.
        A boolean indicator representing whether a path was found.
    """
    G = Graph(start_angles, end_angles)

    for i in range(n_iter):
        rand_node = Node(None)
        if arm_is_colliding_prisms(rand_node, obstacles):
            continue

        if i % 2 == 0 or not G.ranking:
            nearest_node, nearest_node_index = nearest(
                G, rand_node.end_effector_pos)
            if nearest_node is None:
                continue

            new_node = steer(rand_node.angles, nearest_node.angles, stepSize)

            if arm_is_colliding_prisms(
                    new_node, obstacles) or not new_node.valid_configuration():
                continue

            nearest_to_new, _ = nearest(G, new_node.end_effector_pos)

            G.add_vex(new_node, nearest_to_new)
            # dist = line.distance(new_node.end_effector_pos, nearest_to_new.end_effector_pos)
            # G.add_edge(newidx, nearest_to_new_idx, dist)

        else:
            new_node, newidx = extend_heuristic(G, rand_node, stepSize,
                                                heuristic_threshold, obstacles)
            if arm_is_colliding_prisms(new_node, obstacles):
                continue

        end_eff_dist_to_goal = line.distance(new_node.end_effector_pos,
                                             G.end_node.end_effector_pos)
        angle_dist_to_goal = np.linalg.norm(
            true_angle_distances_arm(new_node.angles, G.end_node.angles))

        if end_eff_dist_to_goal < radius and not G.success:
            if arm_is_colliding_prisms(G.end_node, obstacles):
                raise Exception("Adding a colliding node")
            desired_position = G.end_node.end_effector_pos
            if angle_dist_to_goal > angle_threshold:
                # tries to get a closer arm configuration to the second-to-last arm configration with inverse kinematics
                G.end_node = Node.from_point(desired_position,
                                             start_config=new_node.angles)

            endidx = G.add_vex(G.end_node, new_node)
            # G.add_edge(newidx, endidx, end_eff_dist_to_goal)
            G.success = True
            print("Iterations:", i)
            break
    return G
Esempio n. 7
0
 def dist_to_end(self, node):
     return line.distance(node.end_effector_pos,
                          self.end_node.end_effector_pos)