1717
1818sys .path .append (str (pathlib .Path (__file__ ).parent .parent .parent ))
1919
20- from Mapping .DistanceMap .distance_map import compute_sdf
20+ from Mapping .DistanceMap .distance_map import compute_sdf_scipy
2121
2222# Elastic Bands Params
2323MAX_BUBBLE_RADIUS = 100
@@ -45,8 +45,8 @@ def __init__(self, position, radius):
4545
4646
4747class ElasticBands :
48- def __init__ (self , initial_path , obstacles , rho0 = RHO0 , kc = 0.05 , kr = - 0.1 ):
49- self .distance_map = compute_sdf (obstacles )
48+ def __init__ (self , initial_path , obstacles , rho0 = RHO0 , kc = KC , kr = KR ):
49+ self .distance_map = compute_sdf_scipy (obstacles )
5050 self .bubbles = [
5151 Bubble (p , self .compute_rho (p )) for p in initial_path
5252 ] # Initialize bubble chain
@@ -73,7 +73,7 @@ def contraction_force(self, i):
7373 dir_next = (next_ - current ) / (np .linalg .norm (next_ - current ) + 1e-6 )
7474 return self .kc * (dir_prev + dir_next )
7575
76- def external_force (self , i ):
76+ def repulsive_force (self , i ):
7777 """Calculate external repulsive force for the i-th bubble"""
7878 h = STEP_SIZE # Step size
7979 b = self .bubbles [i ].pos
@@ -99,7 +99,7 @@ def update_bubbles(self):
9999 new_bubbles .append (self .bubbles [i ]) # Fixed start and end points
100100 continue
101101
102- f_total = self .contraction_force (i ) + self .external_force (i )
102+ f_total = self .contraction_force (i ) + self .repulsive_force (i )
103103 alpha = self .bubbles [i ].radius # Adaptive step size
104104 new_pos = self .bubbles [i ].pos + alpha * f_total
105105 new_pos = np .clip (new_pos , 0 , 499 )
@@ -146,10 +146,11 @@ def __init__(self):
146146 self .obstacles = np .zeros ((500 , 500 ))
147147 self .path_points = []
148148 self .elastic_band = None
149+ self .running = True
149150
150151 if ENABLE_PLOT :
151152 self .fig , self .ax = plt .subplots (figsize = (8 , 8 ))
152- # Set the display range of the graph
153+ self . fig . canvas . mpl_connect ( "close_event" , self . on_close )
153154 self .ax .set_xlim (0 , 500 )
154155 self .ax .set_ylim (0 , 500 )
155156
@@ -164,15 +165,32 @@ def __init__(self):
164165
165166 self .plot_background ()
166167
168+ def on_close (self , event ):
169+ """Handle window close event"""
170+ self .running = False
171+ plt .close ("all" ) # Close all figure windows
172+
167173 def plot_background (self ):
168174 """Plot the background grid"""
169- if not ENABLE_PLOT :
175+ if not ENABLE_PLOT or not self . running :
170176 return
171177
172178 self .ax .cla ()
173179 self .ax .set_xlim (0 , 500 )
174180 self .ax .set_ylim (0 , 500 )
175181 self .ax .grid (True )
182+
183+ if ENABLE_INTERACTIVE :
184+ self .ax .set_title (
185+ "Elastic Bands Path Planning\n "
186+ "Left click: Add obstacles\n "
187+ "Right click: Add path points\n "
188+ "Middle click: Start planning" ,
189+ pad = 20 ,
190+ )
191+ else :
192+ self .ax .set_title ("Elastic Bands Path Planning" , pad = 20 )
193+
176194 if self .path_points :
177195 self .ax .plot (
178196 [p [0 ] for p in self .path_points ],
@@ -242,4 +260,4 @@ def plan_path(self):
242260if __name__ == "__main__" :
243261 _ = ElasticBandsVisualizer ()
244262 if ENABLE_PLOT :
245- plt .show ()
263+ plt .show (block = True )
0 commit comments