1010import matplotlib .patches as patches
1111import math
1212
13- class CollosionDetector :
13+ class CollisionDetector :
1414 """
1515 Simulation class to update positions of two rectangles (vehicle and pedestrian)
1616 with velocities v1 and v2, performing collision detection at each time step.
1717 All functions remain within the class, and variables defined in __init__ remain unchanged;
1818 local copies are used during simulation.
1919 """
20- def __init__ (self , x1 , y1 , t1 , x2 , y2 , t2 , v1 , v2 , total_time = 10.0 , basic_deceleration = 2.0 , max_deceleration = 8.0 ):
20+ def __init__ (self , x1 , y1 , t1 , x2 , y2 , t2 , v1 , v2 , total_time = 10.0 , desired_speed = 2.0 , acceleration = 0.5 ):
2121
2222 self .vehicle_x = x1
2323 self .vehicle_y = y1
@@ -50,8 +50,13 @@ def __init__(self, x1, y1, t1, x2, y2, t2, v1, v2, total_time=10.0, basic_decele
5050
5151 self .dt = 0.1 # seconds
5252 self .total_time = total_time # seconds
53- self .basic_deceleration = basic_deceleration
54- self .max_deceleration = max_deceleration
53+
54+ self .desired_speed = desired_speed
55+ self .acceleration = acceleration
56+
57+ def set_params (self , speed , acceleration ):
58+ self .desired_speed = speed
59+ self .acceleration = acceleration
5560
5661 def get_corners (self , x , y , w , h , theta ):
5762 """
@@ -121,13 +126,7 @@ def plot_rectangles(self, rect1, rect2, collision, ax):
121126 ax .set_title (f"Collision: { 'Yes' if collision else 'No' } " )
122127
123128 def run (self , is_displayed = False ):
124- output_deceleration = 0.0
125129 collision_distance = - 1
126- relation = "None"
127- # None: No relation
128- # Yielding: Vehicle is yielding to pedestrian
129- # Stopping: Vehicle is stopping for pedestrian
130-
131130 steps = int (self .total_time / self .dt ) + 1
132131
133132 # Create local variables for positions; these will be updated
@@ -136,6 +135,7 @@ def run(self, is_displayed=False):
136135 current_y1 = self .y1
137136 current_x2 = self .x2
138137 current_y2 = self .y2
138+ current_v1 = self .v1 [0 ]
139139
140140 if is_displayed :
141141 plt .ion () # Turn on interactive mode
@@ -180,35 +180,26 @@ def run(self, is_displayed=False):
180180
181181 # Stop simulation if collision is detected.
182182 if collision :
183- # Check if the vehicle will hit the pedestrian or can stop before hitting.
184- # Dmin = v^2 / (2 * a) => a = -v^2 / (2 * D)
185- # Minimum distance required to stop before hitting with basic_deceleration
186- minimum_distance = self .v1 [0 ]** 2 / (2 * self .basic_deceleration )
187- current_vehicle_x = current_x1 - (self .vehicle_size_x + self .vehicle_buffer_x ) * 0.5
188- current_vehicle_y = current_y1
189-
190- print ("Collision detected. Stopping simulation." )
191- print (f"Collision coordinates: ({ current_vehicle_x :.1f} , { current_vehicle_y :.1f} )" )
192- print (f"Vehicle speed: { self .v1 [0 ]:.1f} " )
193- print (f"Minimum distance required to avoid collision: { minimum_distance :.1f} " )
194-
183+ current_vehicle_x = current_x1 - (self .vehicle_size_x + self .vehicle_buffer_x ) * 0.5
184+ current_vehicle_y = current_y1
195185 collision_distance = current_vehicle_x - self .vehicle_x
196-
197- if minimum_distance > collision_distance :
198- print ("Vehicle will hit the pedestrian!!!" )
199- relation = "Stopping"
200- # Deceleration to stop at the current position > basic_deceleration
201- output_deceleration = min (self .max_deceleration , self .v1 [0 ]** 2 / (2 * (collision_distance )))
202- else :
203- print ("Vehicle can yield. Speed down with:" )
204- # Deceleration to stop at the current position < basic_deceleration
205- output_deceleration = self .v1 [0 ]** 2 / (2 * (current_vehicle_x - self .vehicle_x ))
206- print (f"Appropriate deceleration: { output_deceleration :.2f} " )
207- relation = "Yielding"
208186 break
209187
188+ # Update the vehicle's speed if it is not at the desired speed.
189+ next_v = current_v1 + self .acceleration * self .dt
190+ # Accelerating: Check if the vehicle is about to exceed the desired speed.
191+ if next_v > self .desired_speed and current_v1 <= self .desired_speed :
192+ current_v1 = self .desired_speed
193+ # Decelerating: Check if the vehicle is about to fall below the desired speed.
194+ elif next_v < self .desired_speed and current_v1 >= self .desired_speed :
195+ current_v1 = self .desired_speed
196+ else :
197+ current_v1 = next_v
198+
199+ current_v1 = 0.0 if current_v1 < 0.0 else current_v1
200+
210201 # Update local positions based on velocities.
211- current_x1 += self . v1 [ 0 ] * self .dt
202+ current_x1 += current_v1 * self .dt
212203 current_y1 += self .v1 [1 ] * self .dt
213204 current_x2 += self .v2 [0 ] * self .dt
214205 current_y2 += self .v2 [1 ] * self .dt
@@ -217,7 +208,9 @@ def run(self, is_displayed=False):
217208 plt .ioff ()
218209 plt .show (block = True )
219210
220- return relation , output_deceleration , collision_distance
211+ print ("Collision distance:" , collision_distance )
212+
213+ return collision_distance
221214
222215
223216def longitudinal_plan (path : Path , acceleration : float , deceleration : float , max_speed : float , current_speed : float ) -> Trajectory :
@@ -457,7 +450,6 @@ def longitudinal_brake(path : Path, deceleration : float, current_speed : float)
457450
458451 print ("=====LONGITUDINAL BRAKE=====" )
459452 print ("path length: " , path .length ())
460- print ("deceleration: " , deceleration )
461453 length = path .length ()
462454
463455 x0 = points [0 ][0 ]
@@ -494,9 +486,11 @@ def __init__(self):
494486 self .t_last = None
495487 self .acceleration = 0.5
496488 self .desired_speed = 2.0 # default 1.0
497- self .deceleration = 2.0
498489
499- self .max_deceleration = 8.0
490+ self .yield_speed = 0.5
491+ self .yield_deceleration = 0.5
492+ self .deceleration = 2.0
493+ self .max_deceleration = 8.0
500494 self .relation = "None"
501495
502496 def state_inputs (self ):
@@ -530,18 +524,15 @@ def update(self, state : AllState):
530524 closest_dist ,closest_parameter = state .route .closest_point_local ((curr_x ,curr_y ),[self .route_progress - 5.0 ,self .route_progress + 5.0 ])
531525 self .route_progress = closest_parameter
532526
533- lookahead_distance = max (10 , curr_v ** 2 / (2 * self .deceleration ))
527+ lookahead_distance = max (10 , curr_v ** 2 / (2 * self .yield_deceleration ))
534528 route_with_lookahead = route .trim (closest_parameter ,closest_parameter + lookahead_distance )
535529 print ("Lookahead distance:" , lookahead_distance )
536530 #extract out a 10m segment of the route
537531 # route_with_lookahead = route.trim(closest_parameter,closest_parameter+10.0)
538532
539- decel = self .deceleration
540- prev_relation = self .relation
541- should_yield = False
542-
543533 #parse the relations indicated
544534 should_brake = False
535+ should_yield = False
545536
546537 for r in state .relations :
547538 if r .type == EntityRelationEnum .YIELDING and r .obj1 == '' :
@@ -583,30 +574,50 @@ def update(self, state : AllState):
583574 # Create and run the simulation.
584575 print (f"Vehicle: ({ x1 :.1f} , { y1 :.1f} , ({ v1 [0 ]:.1f} , { v1 [1 ]:.1f} ))" )
585576 print (f"Pedestrian: ({ x2 :.1f} , { y2 :.1f} , ({ v2 [0 ]:.1f} , { v2 [1 ]:.1f} ))" )
586- sim = CollosionDetector (x1 , y1 , 0 , x2 , y2 , 0 , v1 , v2 , total_time , self .deceleration , self .max_deceleration )
587577
588- self .relation , decel , collision_distance = sim .run ()
589- print (f"Relation: { self .relation } " )
590- print (f"Deceleration: { decel :.2f} m/s^2" )
578+ # Simulate if a collision will occur when the vehicle accelerate to desired speed.
579+ sim = CollisionDetector (x1 , y1 , 0 , x2 , y2 , 0 , v1 , v2 , total_time , self .desired_speed , self .acceleration )
580+ collision_distance = sim .run ()
581+
582+ # No collision detected
583+ if collision_distance < 0 :
584+ print ("No collision detected." )
585+ self .relation = "None"
591586
592- # Update the lookahead distance based on the deceleration
593- if collision_distance >= 0 :
594- route_with_lookahead = route .trim (closest_parameter ,closest_parameter + collision_distance )
587+ # Collision detected
588+ else :
589+ # Update lookahead distance to pedestrian.
590+ route_with_lookahead = route .trim (closest_parameter , closest_parameter + collision_distance )
591+
592+ # Simulate if a collision will occur when the vehicle decelerate to yield speed.
593+ sim .set_params (self .yield_speed , self .yield_deceleration * - 1 )
594+ collision_distance_after_yield = sim .run ()
595+
596+ # Can yield to the pedestrian => Yielding
597+ if collision_distance_after_yield < 0 :
598+ print ("The vehicle can yield to the pedestrian." )
599+ self .relation = "Yielding"
600+ decel = self .yield_deceleration
601+
602+ # Cannot yield to the pedestrian => Stopping
603+ else :
604+ print ("The vehicle is Stopping." )
605+ self .relation = "Stopping"
606+ decel = max (self .deceleration , v1 [0 ]** 2 / (2 * (collision_distance )))
607+ if decel > self .max_deceleration :
608+ decel = self .max_deceleration
609+
610+ print (f"Relation: { self .relation } " )
611+ print (f"Deceleration: { decel :.2f} m/s^2" )
595612
596613 # relation: None, Yielding, Stopping
597614 # None: No need to speed down
598615 # Yielding: Speed down but not to 0 m/s
599616 # Stopping: Speed down to 0 m/s
600- # State transition:
601- # None => Yielding or Stopping
602- # Yielding => Stopping
603- # Stopping => nan
604-
605- if prev_relation == "Stopping" and self .relation == "Yielding" :
606- self .relation = "Stopping"
607617
608618 break
609619
620+
610621 if self .relation == "Yielding" :
611622 should_brake = True
612623 should_yield = True
@@ -628,11 +639,9 @@ def update(self, state : AllState):
628639 if should_accelerate :
629640 traj = longitudinal_plan (route_with_lookahead , self .acceleration , self .deceleration , self .desired_speed , curr_v )
630641 elif should_brake and not should_yield :
631- # Stopping: 2.0 < Decel < 8.0
632642 traj = longitudinal_brake (route_with_lookahead , decel , curr_v )
633643 elif should_brake and should_yield :
634- # Yielding: 0.0 < Decel < 2.0
635- traj = longitudinal_brake (route_with_lookahead , decel , curr_v )
644+ traj = longitudinal_plan (route_with_lookahead , self .acceleration , self .yield_deceleration , self .yield_speed , curr_v )
636645 else :
637646 traj = longitudinal_plan (route_with_lookahead , 0.0 , self .deceleration , self .desired_speed , curr_v )
638647
0 commit comments