2222import sys
2323# Add show_animation flag for consistency with other planners
2424show_animation = True
25+
2526def signal_handler (sig , frame ):
2627 print ("\n Exiting..." )
2728 plt .close ("all" )
@@ -44,6 +45,7 @@ class Particle:
4445 personal_best_value: Fitness value at personal best position
4546 path: List of all positions visited by this particle
4647 """
48+
4749 def __init__ (self , search_bounds , spawn_bounds ):
4850 self .search_bounds = search_bounds
4951 self .max_velocity = np .array ([(b [1 ] - b [0 ]) * 0.05 for b in search_bounds ])
@@ -52,6 +54,7 @@ def __init__(self, search_bounds, spawn_bounds):
5254 self .personal_best_position = self .position .copy ()
5355 self .personal_best_value = np .inf
5456 self .path = [self .position .copy ()]
57+
5558 def update_velocity (self , gbest_pos , w , c1 , c2 ):
5659 """Update particle velocity using PSO equation:
5760 v = w*v + c1*r1*(personal_best - x) + c2*r2*(gbest - x)
@@ -62,6 +65,7 @@ def update_velocity(self, gbest_pos, w, c1, c2):
6265 social = c2 * r2 * (gbest_pos - self .position )
6366 self .velocity = w * self .velocity + cognitive + social
6467 self .velocity = np .clip (self .velocity , - self .max_velocity , self .max_velocity )
68+
6569 def update_position (self ):
6670 self .position = self .position + self .velocity
6771 # Keep in bounds
@@ -70,7 +74,9 @@ def update_position(self):
7074 self .position [i ], self .search_bounds [i ][0 ], self .search_bounds [i ][1 ]
7175 )
7276 self .path .append (self .position .copy ())
77+
7378class PSOSwarm :
79+
7480 def __init__ (
7581 self , n_particles , max_iter , target , search_bounds , spawn_bounds , obstacles
7682 ):
@@ -92,6 +98,7 @@ def __init__(
9298 self .gbest_value = np .inf
9399 self .gbest_path = []
94100 self .iteration = 0
101+
95102 def fitness (self , pos ):
96103 """Calculate fitness - distance to target + obstacle penalty"""
97104 dist = np .linalg .norm (pos - self .target )
@@ -104,6 +111,7 @@ def fitness(self, pos):
104111 elif obs_dist < r + 5 :
105112 penalty += 50 / (obs_dist - r + 0.1 ) # Too close
106113 return dist + penalty
114+
107115 def check_collision (self , start , end , obstacle ):
108116 """Check if path from start to end hits obstacle using line-circle intersection
109117 Args:
@@ -133,6 +141,7 @@ def check_collision(self, start, end, obstacle):
133141 t1 = (- b - sqrt_discriminant ) / (2 * a )
134142 t2 = (- b + sqrt_discriminant ) / (2 * a )
135143 return (0 <= t1 <= 1 ) or (0 <= t2 <= 1 )
144+
136145 def step (self ):
137146 """Run one PSO iteration
138147 Returns:
@@ -178,6 +187,7 @@ def step(self):
178187 f"Iteration { self .iteration } /{ self .max_iter } , Best: { self .gbest_value :.2f} "
179188 )
180189 return True
190+
181191def main ():
182192 """Run PSO path planning algorithm demonstration.
183193 This function demonstrates PSO-based path planning with the following setup:
0 commit comments