""" Potential_Field @author: huiming zhou """ import os import sys import numpy as np import matplotlib.pyplot as plt from collections import deque sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../../Search_based_Planning/") from Search_2D import plotting from Search_2D import env class PF: def __init__(self, s_start, s_goal): self.s_start = s_start self.s_goal = s_goal self.kp = 5.0 self.eta = 400 self.r = 30.0 self.OL = 10 self.rr = 2 self.Env = env.Env() self.Plot = plotting.Plotting(s_start, s_goal) self.u_set = self.Env.motions # feasible input set self.obs = self.Env.obs # position of obstacles self.x = self.Env.x_range self.y = self.Env.y_range def run(self): pmap, minx, miny = self.calc_potential_field() d = np.hypot(self.s_start[0] - self.s_goal[0], self.s_start[1] - self.s_goal[1]) ix = self.s_start[0] - minx iy = self.s_start[1] - miny gix = self.s_goal[0] - minx giy = self.s_goal[1] - miny self.draw_heatmap(pmap) plt.gcf().canvas.mpl_connect('key_release_event', lambda event: [exit(0) if event.key == 'escape' else None]) plt.plot(ix, iy, "sk") plt.plot(gix, giy, "sm") rx, ry = [self.s_start[0]], [self.s_goal[0]] ids_rec = deque() while d >= 1: minp = float("inf") minix, miniy = -1, -1 for u in self.u_set: inx = int(ix + u[0]) iny = int(iy + u[1]) if inx >= len(pmap) or iny >= len(pmap[0]) or inx < 0 or iny < 0: p = float("inf") print("test") else: p = pmap[inx][iny] if minp > p: minp = p minix = inx miniy = iny ix = minix iy = miniy xp = ix + minx yp = iy + miny d = np.hypot(self.s_goal[0] - xp, self.s_goal[1] - yp) rx.append(xp) ry.append(yp) if self.is_oscillation(ids_rec, ix, iy): print("Oscillation detected at ({},{})!".format(ix, iy)) break plt.plot(ix, iy, ".r") plt.pause(0.01) return rx, ry def calc_potential_field(self): minx = 0 miny = 0 maxx = self.x - 1 maxy = self.y - 1 xw = maxx - minx yw = maxy - miny pmap = [[0.0 for i in range(yw)] for i in range(xw)] for ix in range(xw): x = ix + minx for iy in range(yw): y = iy + miny ug = self.calc_attractive_potential(x, y) uo = self.calc_repulsive_potential(x, y) uf = ug + uo pmap[ix][iy] = uf return pmap, minx, miny def calc_attractive_potential(self, x, y): return 0.5 * self.kp * \ np.hypot(x - self.s_goal[0], y - self.s_goal[1]) def calc_repulsive_potential(self, x, y): dmin = float("inf") for s in self.obs: d = np.hypot(x - s[0], y - s[1]) if dmin >= d: dmin = d # calc repulsive potential dq = dmin if dq <= self.rr: if dq <= 0.8: dq = 0.8 return 0.5 * self.eta * (1.0 / dq - 1.0 / self.rr) ** 2 else: return 0.0 def is_oscillation(self, ids_rec, ix, iy): ids_rec.append((ix, iy)) if len(ids_rec) > self.OL: ids_rec.popleft() ids_set = set() for s in ids_rec: if s in ids_set: return True else: ids_set.add(s) return False @staticmethod def draw_heatmap(data): data = np.array(data).T plt.pcolor(data, vmax=100.0, cmap=plt.cm.Blues) def main(): s_start = (5, 5) s_goal = (45, 25) pf = PF(s_start, s_goal) plt.grid(True) plt.axis("equal") _, _ = pf.run() plt.show() if __name__ == '__main__': print(__file__ + " start!!") main()