99
1010"""
1111
12+ from collections import deque
1213import numpy as np
1314import matplotlib .pyplot as plt
1415
1516# Parameters
1617KP = 5.0 # attractive potential gain
1718ETA = 100.0 # repulsive potential gain
1819AREA_WIDTH = 30.0 # potential area width [m]
20+ # the number of previous positions used to check oscillations
21+ OSCILLATIONS_DETECTION_LENGTH = 3
1922
2023show_animation = True
2124
2225
23- def calc_potential_field (gx , gy , ox , oy , reso , rr ):
24- minx = min (ox ) - AREA_WIDTH / 2.0
25- miny = min (oy ) - AREA_WIDTH / 2.0
26- maxx = max (ox ) + AREA_WIDTH / 2.0
27- maxy = max (oy ) + AREA_WIDTH / 2.0
26+ def calc_potential_field (gx , gy , ox , oy , reso , rr , sx , sy ):
27+ minx = min (min ( ox ), sx , gx ) - AREA_WIDTH / 2.0
28+ miny = min (min ( oy ), sy , gy ) - AREA_WIDTH / 2.0
29+ maxx = max (max ( ox ), sx , gx ) + AREA_WIDTH / 2.0
30+ maxy = max (max ( oy ), sy , gy ) + AREA_WIDTH / 2.0
2831 xw = int (round ((maxx - minx ) / reso ))
2932 yw = int (round ((maxy - miny ) / reso ))
3033
@@ -84,10 +87,26 @@ def get_motion_model():
8487 return motion
8588
8689
90+ def oscillations_detection (previous_ids , ix , iy ):
91+ previous_ids .append ((ix , iy ))
92+
93+ if (len (previous_ids ) > OSCILLATIONS_DETECTION_LENGTH ):
94+ previous_ids .popleft ()
95+
96+ # check if contains any duplicates by copying into a set
97+ previous_ids_set = set ()
98+ for index in previous_ids :
99+ if index in previous_ids_set :
100+ return True
101+ else :
102+ previous_ids_set .add (index )
103+ return False
104+
105+
87106def potential_field_planning (sx , sy , gx , gy , ox , oy , reso , rr ):
88107
89108 # calc potential field
90- pmap , minx , miny = calc_potential_field (gx , gy , ox , oy , reso , rr )
109+ pmap , minx , miny = calc_potential_field (gx , gy , ox , oy , reso , rr , sx , sy )
91110
92111 # search path
93112 d = np .hypot (sx - gx , sy - gy )
@@ -106,14 +125,17 @@ def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):
106125
107126 rx , ry = [sx ], [sy ]
108127 motion = get_motion_model ()
128+ previous_ids = deque ()
129+
109130 while d >= reso :
110131 minp = float ("inf" )
111132 minix , miniy = - 1 , - 1
112133 for i , _ in enumerate (motion ):
113134 inx = int (ix + motion [i ][0 ])
114135 iny = int (iy + motion [i ][1 ])
115- if inx >= len (pmap ) or iny >= len (pmap [0 ]):
136+ if inx >= len (pmap ) or iny >= len (pmap [0 ]) or inx < 0 or iny < 0 :
116137 p = float ("inf" ) # outside area
138+ print ("outside potential!" )
117139 else :
118140 p = pmap [inx ][iny ]
119141 if minp > p :
@@ -128,6 +150,10 @@ def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):
128150 rx .append (xp )
129151 ry .append (yp )
130152
153+ if (oscillations_detection (previous_ids , ix , iy )):
154+ print ("Oscillation detected at ({},{})!" .format (ix , iy ))
155+ break
156+
131157 if show_animation :
132158 plt .plot (ix , iy , ".r" )
133159 plt .pause (0.01 )
0 commit comments