Пример #1
0
def main():
	point_list = np.load('final_rrt_prune_path_coords.npy')
	print("original list:", len(point_list))

	(BC_x, BC_y) = bezierCurveTesting1(point_list, animate=False, write_path=None)
	plt.ion()
	itr = 0
	visualizeNewPath(BC_x, BC_y, point_list, animate=True, write_path='./rrt_smooth_no_obs_frames', itr=itr)
	itr += 1

	# for bcx, bcy in zip(BC_x, BC_y):
	while True:
		idx = 0
		while idx < len(BC_x):
			bcx, bcy = BC_x[idx], BC_y[idx]

			# if the current waypoint is within the obstacle space => make a new waypoint
			if obs.withinObstacleSpace(point=(bcx, bcy), radius=mn.DRONE_RADIUS, clearance=(mn.DRONE_RADIUS / 2)):
				print("within obstacle")
				break
			idx += 1

		if idx == len(BC_x):
			np.save(file='final_rrt_prune_smooth_path_coords.npy', arr=point_list)
			break

		point_list = addMidPointsToPath(point_list)
		(BC_x, BC_y) = bezierCurveTesting1(point_list, animate=False, write_path=None)
		visualizeNewPath(BC_x, BC_y, point_list, animate=True, write_path='./rrt_smooth_no_obs_frames', itr=itr)
		itr += 1
	plt.ioff()
	plt.show()
def actionMove(current_node, next_action, goal_position, clearance, plotter=plt, viz_please=False):
	Xi, Yi = current_node.getXYCoords()
	Thetai = current_node.orientation
	UL, UR = next_action

	mc = current_node.movement_cost

	t = 0
	r = 0.038
	L = 0.354
	dt = 0.1
	Xn = Xi
	Yn = Yi
	Thetan = math.radians(Thetai)

# Xi, Yi,Thetai: Input point's coordinates
# Xs, Ys: Start point coordinates for plot function
# Xn, Yn, Thetan: End point coordintes

	while t < 1:
		t = t + dt
		Xs = Xn
		Ys = Yn
		Xn += 0.5 * r * (UL + UR) * math.cos(Thetan) * dt
		Yn += 0.5 * r * (UL + UR) * math.sin(Thetan) * dt
		Thetan += (r / L) * (UR - UL) * dt

		if viz_please:
			plotter.plot([Xs, Xn], [Ys, Yn], color="blue")

		mc += utils.euclideanDistance((Xs, Ys), (Xn, Yn))

		# if the intermediate step hits a boundary
		if (Yn < MIN_COORDS[1]) or (Yn >= MAX_COORDS[1]) or (Xn < MIN_COORDS[0]) or (Xn >= MAX_COORDS[0]):
			return None

		# if the intermediate step hits an obstacle
		if (obstacles.withinObstacleSpace((Xn, Yn), radius=a_star.ROBOT_RADIUS, clearance=clearance)):
			return None

	cc = (Yn, Xn)
	pc = current_node.current_coords
	ori = math.degrees(Thetan)
	pori = current_node.orientation
	gc = utils.euclideanDistance(cc, goal_position)

	ret_val = node.Node(current_coords=cc, parent_coords=pc, orientation=ori, parent_orientation=pori, action=next_action, movement_cost=mc, goal_cost=gc)

	return ret_val
Пример #3
0
def hitsObstacle(start_node, goal_node, step_size=0.1):
	sn_x, sn_y = start_node.getXYCoords()
	gn_x, gn_y = goal_node.getXYCoords()

	theta = np.arctan2((gn_y - sn_y), (gn_x - sn_x))

	nn_x, nn_y = sn_x, sn_y
	while (utils.euclideanDistance(point_1=(nn_x, nn_y), point_2=(gn_x, gn_y)) > 0.001):
		# next node
		nn_x = nn_x + (step_size * np.cos(theta))
		nn_y = nn_y + (step_size * np.sin(theta))

		if obs.withinObstacleSpace(point=(nn_x, nn_y), radius=main.DRONE_RADIUS, clearance=main.DRONE_RADIUS / 2):
			return True

	return False
Пример #4
0
def isObstacleLine(start, end):
    pts = np.linspace(0, 1, num=100)
    obs = []

    for t in pts:

        eqn = t * start + (1 - t) * end
        # print(eqn)
        obs.append(
            obstacles.withinObstacleSpace(point=eqn, radius=0, clearance=0))

    obs = np.array(obs)
    if np.any(obs):
        return True
    else:
        return False
Пример #5
0
def main():

    # User input for the start state
    start_c, start_r, start_orient = map(
        float,
        raw_input(
            "Enter starting coordinates (x y) and orientation: ").split())
    # User input for goal state
    goal_c, goal_r = map(float,
                         raw_input("Enter goal coordinates (x y): ").split())

    radius = float(input("Enter the robot radius: "))
    clearance = float(input("Enter the clearance: "))
    step_size = float(input("Enter the robot step_size: "))

    # check if the start node lies withing the map and not on obstacles
    if (start_r < actions.MIN_COORDS[1]) or (
            start_r >= actions.MAX_COORDS[1]
    ) or (start_c < actions.MIN_COORDS[0]) or (
            start_c >= actions.MAX_COORDS[0]) or obstacles.withinObstacleSpace(
                (start_c, start_r), radius, clearance):
        print(
            "ERROR: Invalid start node. It either lies outside the map boundary or within the obstacle region."
        )
        sys.exit(0)

    # check if the goal node lies withing the map and not on obstacles
    if (goal_r < actions.MIN_COORDS[1]) or (
            goal_r >= actions.MAX_COORDS[1]
    ) or (goal_c < actions.MIN_COORDS[0]) or (
            goal_c >= actions.MAX_COORDS[0]) or obstacles.withinObstacleSpace(
                (goal_c, goal_r), radius, clearance):
        print(
            "ERROR: Invalid goal node. It either lies outside the map boundary or within the obstacle region."
        )
        sys.exit(0)

    # check is step size lies between 0 and 10
    if step_size < 1 or step_size > 10:
        print("ERROR: Invalid step_size. It must lie within 1 and 10.")
        sys.exit(0)

    # write code to find the actual path using a star
    start_time = time.clock()
    path, viz_nodes = a_star.aStar(start_pos=(start_r, start_c),
                                   goal_pos=(goal_r, goal_c),
                                   robot_radius=radius,
                                   clearance=clearance,
                                   step_size=step_size,
                                   theta=30,
                                   duplicate_step_thresh=0.5,
                                   duplicate_orientation_thresh=30)
    print "Time to run A*:", time.clock() - start_time, "seconds"

    # visualize path
    goal_node = node.Node(current_coords=(goal_r, goal_c),
                          parent_coords=None,
                          orientation=None,
                          parent_orientation=None,
                          movement_cost=None,
                          goal_cost=0)
    univ.function(viz_nodes, path, goal_node, step_size)
def main():
    """
	Main function that takes user input and
	computes shortest path using the A* algorithm
	complying with the given constraints.
	"""

    # User input for the start state
    start_c, start_r, theta = map(
        float,
        raw_input(
            "Enter starting coordinates (x y) and orientation: ").split())
    start_rc = (start_r, start_c)
    # User input for goal state
    goal_c, goal_r = map(float,
                         raw_input("Enter goal coordinates (x y): ").split())
    goal_rc = (goal_r, goal_c)

    rpm1, rpm2 = map(float, raw_input("Enter rpm1 and rpm2: ").split())

    clearance = float(input("Enter the clearance: "))
    clearance = 0.2 if clearance < 0.2 else clearance  # Having a reasonable clearance

    # check if the start node lies withing the map and not on obstacles
    if ((start_r < actions_new.MIN_COORDS[1])
            or (start_r >= actions_new.MAX_COORDS[1])
            or (start_c < actions_new.MIN_COORDS[0])
            or (start_c >= actions_new.MAX_COORDS[0])
            or obstacles.withinObstacleSpace(
                (start_c, start_r), a_star.ROBOT_RADIUS, clearance)):
        print(
            "ERROR: Invalid start node. It either lies outside the map boundary or within the obstacle region."
        )
        return

    # check if the goal node lies withing the map and not on obstacles
    if ((goal_r < actions_new.MIN_COORDS[1])
            or (goal_r >= actions_new.MAX_COORDS[1])
            or (goal_c < actions_new.MIN_COORDS[0])
            or (goal_c >= actions_new.MAX_COORDS[0])
            or obstacles.withinObstacleSpace(
                (goal_c, goal_r), a_star.ROBOT_RADIUS, clearance)):
        print(
            "ERROR: Invalid goal node. It either lies outside the map boundary or within the obstacle region."
        )
        return

    # write code to find the actual path using a star
    start_time = time.clock()
    path, visited_viz_nodes = a_star.a_star(start_rc=start_rc,
                                            goal_rc=goal_rc,
                                            orientation=theta,
                                            rpm1=rpm1,
                                            rpm2=rpm2,
                                            clearance=clearance,
                                            viz_please=False)
    print "Time to run A*:", time.clock() - start_time, "seconds"

    print("Number of visited nodes:", len(visited_viz_nodes))
    print("Number of nodes in path:", len(path))

    np.save("./path_dumps/path_final.npy", path)
    np.save("./path_dumps/visited_viz_nodes_final.npy", visited_viz_nodes)

    plotter = viz.initPlot(start_rc[::-1],
                           goal_rc[::-1],
                           title="Final Plotting")
    # plt.savefig(os.path.join(a_star.OUTPUT_DIR, "1.png"))
    plt.ion()

    i = 2
    # i = viz.plotPath(path=visited_viz_nodes, rev=False, pause_time=0.001, plotter=plotter, color="blue", linewidth=1, write_path_prefix=-1, show=False, skip_frames=25)
    i = viz.plotPath(path=path,
                     rev=True,
                     pause_time=0.001,
                     plotter=plotter,
                     color="lime",
                     linewidth=3,
                     write_path_prefix=-1,
                     show=True,
                     skip_frames=5)

    plt.ioff()
    print("Done with plots.")
    plt.show()
def findShortestPath(start_x, start_y, start_theta, goal_x, goal_y, rpm1, rpm2,
                     clearance):
    start_r = start_y
    start_c = start_x
    start_rc = (start_r, start_c)

    goal_r = goal_y
    goal_c = goal_x
    goal_rc = (goal_r, goal_c)

    # check if the start node lies withing the map and not on obstacles
    if ((start_r < actions_new.MIN_COORDS[1])
            or (start_r >= actions_new.MAX_COORDS[1])
            or (start_c < actions_new.MIN_COORDS[0])
            or (start_c >= actions_new.MAX_COORDS[0])
            or obstacles.withinObstacleSpace(
                (start_c, start_r), a_star.ROBOT_RADIUS, clearance)):
        print(
            "ERROR: Invalid start node. It either lies outside the map boundary or within the obstacle region."
        )
        return

    # check if the goal node lies withing the map and not on obstacles
    if ((goal_r < actions_new.MIN_COORDS[1])
            or (goal_r >= actions_new.MAX_COORDS[1])
            or (goal_c < actions_new.MIN_COORDS[0])
            or (goal_c >= actions_new.MAX_COORDS[0])
            or obstacles.withinObstacleSpace(
                (goal_c, goal_r), a_star.ROBOT_RADIUS, clearance)):
        print(
            "ERROR: Invalid goal node. It either lies outside the map boundary or within the obstacle region."
        )
        return

    # write code to find the actual path using a star
    start_time = time.clock()
    path, visited_viz_nodes = a_star.a_star(start_rc=start_rc,
                                            goal_rc=goal_rc,
                                            orientation=start_theta,
                                            rpm1=rpm1,
                                            rpm2=rpm2,
                                            clearance=clearance,
                                            viz_please=False)
    print "Time to run A*:", time.clock() - start_time, "seconds"

    print("Number of visited nodes:", len(visited_viz_nodes))
    print("Number of nodes in path:", len(path))

    plotter = viz.initPlot(start_rc[::-1],
                           goal_rc[::-1],
                           title="Final Plotting")
    # plt.savefig(os.path.join(a_star.OUTPUT_DIR, "1.png"))
    plt.ion()

    i = 2
    # i = viz.plotPath(path=visited_viz_nodes, rev=False, pause_time=0.001, plotter=plotter, color="blue", linewidth=1, write_path_prefix=-1, show=False, skip_frames=25)
    i = viz.plotPath(path=path,
                     rev=True,
                     pause_time=0.001,
                     plotter=plotter,
                     color="lime",
                     linewidth=3,
                     write_path_prefix=-1,
                     show=True,
                     skip_frames=5)

    plt.ioff()
    print("Done with plots.")
    plt.show()

    return path
Пример #8
0
def rrt(start_coords, goal_coords, radius, clearance):

    x_start, y_start = start_coords
    x_goal, y_goal = goal_coords

    start_node = node.Node(current_coords=start_coords,
                           parent_coords=None,
                           distance=None)
    goal_node = node.Node(current_coords=goal_coords,
                          parent_coords=None,
                          distance=None)

    print(start_node.printNode())
    print(goal_node.printNode())

    tree = []
    path = []

    # tree.append(start_node)
    tree.append([0, start_node.current_coords, (0, 0)])

    N = 0
    while (N < MAX_ITER):
        print("N:", N)
        x_random = (np.random.uniform(X_LIM[0], X_LIM[1]),
                    np.random.uniform(Y_LIM[0], Y_LIM[1]))
        # print("x_random", x_random)
        ##########################################
        #put a check if x_random is repeated
        ##########################################
        # print("<<<<<<<<<<<<Before updating the distance<<<<")
        # print("tree", tree)

        # print("<<<<<<<<<<<<After updating the distance<<<<<")
        for i in tree:
            # while True:
            distance = utils.euclideanDistance(point_1=i[1], point_2=x_random)
            i[0] = distance
            # print("tree", i)

        heapq.heapify(tree)

        # Finding the node in the tree which is the nearest to the x_random
        min_node = heapq.heappop(tree)

        # print("len(tree)", len(tree))
        heapq.heappush(tree, [min_node[0], min_node[1], min_node[2]])
        # sys.exit(0)

        # print("min node", min_node)
        # print("next_node", next_node)
        # print("distance", distance)
        # path.append(add_node)
        # tree.append([min_node[0], x_random, min_node[1]])
        # print("<<<<<<<<<<<After apending the latest x random<<<<<")
        # print("tree", tree)

        # if the random node is within the step size
        if min_node[0] <= STEP_SIZE:

            # create a node with this value and add it to the path
            obstacle_status = obstacles.withinObstacleSpace(
                point=min_node[1], radius=radius, clearance=clearance)
            if (obstacle_status == False):
                add_node = node.Node(current_coords=x_random,
                                     parent_coords=min_node[1],
                                     distance=min_node[0])
                path.append(add_node)
                # print("<<<<<<<<<<<<<_before<<<<<<<<<,")
                # print("len(tree)", len(tree))
                heapq.heappush(tree, [
                    add_node.distance, add_node.current_coords,
                    add_node.parent_coords
                ])
                # print("<<<<<<<<<<<<after<<<<<<<<<<,")
                # print("len(tree)", len(tree))
                # tree.append([add_node.distance, add_node.current_coords, add_node.parent_coords])

        else:
            # Find an intermediate point in between a and b
            x1, y1 = min_node[1]
            x2, y2 = x_random

            slope = (y2 - y1) / (x2 - x1)
            theta = math.atan(slope)

            x_near = (x1 + (STEP_SIZE * math.cos(theta)),
                      y1 + (STEP_SIZE * math.sin(theta)))

            obstacle_status = obstacles.withinObstacleSpace(
                point=min_node[1], radius=radius, clearance=clearance)
            if (obstacle_status == False):
                add_node = node.Node(current_coords=x_near,
                                     parent_coords=min_node[1],
                                     distance=STEP_SIZE)
                # print("<<<<<<<<<<<<<_before<<<<<<<<<,")
                # print("len(tree)", len(tree))
                path.append(add_node)
                heapq.heappush(tree, [
                    add_node.distance, add_node.current_coords,
                    add_node.parent_coords
                ])
                # print("<<<<<<<<<<<<<_before<<<<<<<<<,")
                # print("len(tree)", len(tree))

                # tree.append([add_node.distance, add_node.current_coords, add_node.parent_coords])

        goal_status = utils.goal_reached(
            current_node=add_node,
            goal_node=goal_node,
            goal_reach_threshold=GOAL_REACH_THRESH)
        if (goal_status):
            print("Reached Goal!")
            return path, goal_node
            # break

        N += 1
        # print("-------------------")
        # print(path)
    return path, goal_node
Пример #9
0
def main():
    # point_list = np.random.randint(0, 100, (10, 2))
    # print(point_list)
    # point_list.sort(axis=0)
    # print(point_list)
    point_list = np.load('rrt_prune_smooth_path_coords.npy')

    (BC_x, BC_y) = bezierCurveTesting1(point_list,
                                       animate=True,
                                       write_path='./rrt_prune_smooth_frames')

    # for bcx, bcy in zip(BC_x, BC_y):
    idx = 0
    while idx < len(BC_x):
        bcx, bcy = BC_x[idx], BC_y[idx]

        if obs.withinObstacleSpace(point=(bcx, bcy),
                                   radius=mn.DRONE_RADIUS,
                                   clearance=(mn.DRONE_RADIUS / 2)):
            _, closest_wp_idx = findClosestWayPoint(ref_point=(bcx, bcy),
                                                    point_list=point_list)

            if closest_wp_idx > 0:
                prev_cwp = point_list[closest_wp_idx - 1]
            else:
                prev_cwp = None

            if closest_wp_idx < len(point_list) - 1:
                next_cwp = point_list[closest_wp_idx + 1]
            else:
                next_cwp = None

            if prev_cwp is None and next_cwp is None:
                continue
            elif prev_cwp is not None and next_cwp is None:
                other_wp_idx = closest_wp_idx - 1
                other_cwp = prev_cwp
            elif next_cwp is not None and prev_cwp is None:
                other_wp_idx = closest_wp_idx + 1
                other_cwp = next_cwp
            else:
                _, other_wp_idx = findClosestWayPoint(
                    ref_point=(bcx, bcy), point_list=[prev_cwp, next_cwp])

                if other_wp_idx == 0:
                    other_wp_idx = closest_wp_idx - 1
                    other_cwp = prev_cwp
                else:
                    other_wp_idx = closest_wp_idx + 1
                    other_cwp = next_cwp

            closest_wp = point_list[closest_wp_idx]
            if other_wp_idx < closest_wp_idx:
                mid_wp = (closest_wp + other_cwp) / 2
                point_list = np.insert(point_list,
                                       other_wp_idx,
                                       mid_wp,
                                       axis=0)
            else:
                mid_wp = (closest_wp + other_cwp) / 2
                point_list = np.insert(point_list,
                                       closest_wp_idx,
                                       mid_wp,
                                       axis=0)
            print("intermediate list:", len(point_list))

            (BC_x, BC_y) = bezierCurveTesting1(point_list,
                                               animate=False,
                                               write_path=None)

            idx = -1

        idx += 1
Пример #10
0
def main_no():
	# point_list = np.random.randint(0, 100, (10, 2))
	# print(point_list)
	# point_list.sort(axis=0)
	# print(point_list)
	point_list = np.load('rrt_prune_smooth_path_coords.npy')
	print("original list:", len(point_list))

	(BC_x, BC_y) = bezierCurveTesting1(point_list, animate=True, write_path='./rrt_prune_smooth_frames')

	# for bcx, bcy in zip(BC_x, BC_y):
	idx = 0
	while idx < len(BC_x):
		bcx, bcy = BC_x[idx], BC_y[idx]

		# if the current waypoint is within the obstacle space => make a new waypoint
		if obs.withinObstacleSpace(point=(bcx, bcy), radius=mn.DRONE_RADIUS, clearance=(mn.DRONE_RADIUS / 2)):

			# find the 2 closest original waypoints
			_, closest_wp_idx = findClosestWayPoint(ref_point=(bcx, bcy), point_list=point_list)

			if closest_wp_idx > 0:
				prev_cwp = point_list[closest_wp_idx - 1]
			else:
				prev_cwp = None

			if closest_wp_idx < len(point_list) - 1:
				next_cwp = point_list[closest_wp_idx + 1]
			else:
				next_cwp = None

			if prev_cwp is None and next_cwp is None:
				continue
			elif prev_cwp is not None and next_cwp is None:
				other_wp_idx = closest_wp_idx - 1
				other_cwp = prev_cwp
			elif next_cwp is not None and prev_cwp is None:
				other_wp_idx = closest_wp_idx + 1
				other_cwp = next_cwp
			else:
				_, other_wp_idx = findClosestWayPoint(ref_point=(bcx, bcy), point_list=[prev_cwp, next_cwp])

				if other_wp_idx == 0:
					other_wp_idx = closest_wp_idx - 1
					other_cwp = prev_cwp
				else:
					other_wp_idx = closest_wp_idx + 1
					other_cwp = next_cwp

			# create a push the new wawypoint in the original list
			closest_wp = point_list[closest_wp_idx]
			if other_wp_idx < closest_wp_idx:
				mid_wp = (closest_wp + other_cwp) / 2
				point_list = np.insert(point_list, other_wp_idx, mid_wp, axis=0)
			else:
				mid_wp = (closest_wp + other_cwp) / 2
				point_list = np.insert(point_list, closest_wp_idx, mid_wp, axis=0)
			print("intermediate list:", len(point_list))

			(BC_x, BC_y) = bezierCurveTesting1(point_list, animate=False, write_path=None)

			if len(point_list) == 30:
				break

			idx = -1

		idx += 1

	print("new list:", len(point_list))
	visualizeNewPath(BC_x, BC_y, point_list)
def aStar(start_pos,
          goal_pos,
          robot_radius,
          clearance,
          step_size,
          theta=30,
          duplicate_step_thresh=0.5,
          duplicate_orientation_thresh=30):

    start_r, start_c = start_pos
    goal_r, goal_c = goal_pos

    start_node = node.Node(current_coords=(start_r, start_c),
                           parent_coords=None,
                           orientation=0,
                           parent_orientation=None,
                           movement_cost=0,
                           goal_cost=utils.euclideanDistance(
                               start_pos, goal_pos))
    goal_node = node.Node(current_coords=(goal_r, goal_c),
                          parent_coords=None,
                          orientation=None,
                          parent_orientation=None,
                          movement_cost=None,
                          goal_cost=0)

    # Saving a tuple with total cost and the state node
    minheap = [((start_node.movement_cost + start_node.goal_cost), start_node)]
    heapq.heapify(minheap)

    # defining the visited node like this avoids checking if two nodes are duplicate. because there is only 1 position to store the visited information for all the nodes that lie within this area.
    visited = {}
    visited[(utils.valRound(start_r), utils.valRound(start_c),
             0)] = start_node  # marking the start node as visited

    viz_visited_coords = [start_node]

    while len(minheap) > 0:
        _, curr_node = heapq.heappop(minheap)

        # if curr_node.isDuplicate(goal_node):
        if curr_node.goal_cost < (1.5 * step_size):
            print("Reached Goal!")
            print("Current node:---")
            curr_node.printNode()
            print("Goal node:---")
            goal_node.printNode()

            # backtrack to get the path
            path = actions.backtrack(curr_node, visited)
            # path = None 	# FOR NOW FOR DEBUGGING PURPOSES

            return (path, viz_visited_coords)

        # for row_step, col_step in movement_steps:
        for angle in range(-60, 61, theta):
            # Action Move
            # next_node = actions.actionMove(curr_node, row_step, col_step)
            next_node = actions.actionMove(
                current_node=curr_node,
                theta_step=angle,
                linear_step=step_size,
                goal_position=goal_node.current_coords)

            if next_node is not None:
                # if hit an obstacle, ignore this movement
                if obstacles.withinObstacleSpace(
                    (next_node.current_coords[1], next_node.current_coords[0]),
                        robot_radius, clearance):
                    continue

                # Check if the current node has already been visited.
                # If it has, then see if the current path is better than the previous one
                # based on the total cost = movement cost + goal cost
                node_state = (utils.valRound(next_node.current_coords[0]),
                              utils.valRound(next_node.current_coords[1]),
                              utils.orientationBin(next_node.orientation,
                                                   theta))

                if node_state in visited:
                    # if current cost is a better cost
                    # if (next_node.movement_cost + next_node.goal_cost) < (visited[node_state].movement_cost + visited[node_state].goal_cost):
                    if (next_node < visited[node_state]):
                        visited[
                            node_state].current_coords = next_node.current_coords
                        visited[
                            node_state].parent_coords = next_node.parent_coords
                        visited[node_state].orientation = next_node.orientation
                        visited[
                            node_state].parent_orientation = next_node.parent_orientation
                        visited[
                            node_state].movement_cost = next_node.movement_cost
                        visited[node_state].goal_cost = next_node.goal_cost

                        h_idx = utils.findInHeap(next_node, minheap)
                        if (h_idx > -1):
                            minheap[h_idx] = ((next_node.movement_cost +
                                               next_node.goal_cost), next_node)
                else:
                    # visited.append(next_node)
                    visited[node_state] = next_node
                    heapq.heappush(minheap, ((next_node.movement_cost +
                                              next_node.goal_cost), next_node))

                    viz_visited_coords.append(next_node)

        heapq.heapify(minheap)