@@ -276,7 +276,16 @@ def _predict_collision(self, entering_car: CarUpdate, highway_car: CarUpdate) ->
276276
277277 def _on_car_update (self , payload : str ):
278278 try :
279- update = CarUpdate .from_dict (json .loads (payload ))
279+ data = json .loads (payload )
280+
281+ # Handle test cleanup
282+ if data .get ("_test_cleanup" ):
283+ car_id = data .get ("car_id" )
284+ if car_id :
285+ self ._cleanup_car (car_id )
286+ return
287+
288+ update = CarUpdate .from_dict (data )
280289 except Exception as e :
281290 logger .error (f"Failed to parse car update: { e } " )
282291 return
@@ -318,6 +327,9 @@ def _on_car_update(self, payload: str):
318327 if dist_to_merge < self .MERGE_POINT_DETECTION_M :
319328 logger .info (f"[ENTRY DETECTION] Car { update .car_id } is approaching merge point (distance: { dist_to_merge :.1f} m)" )
320329
330+ # Track if we found any highway cars in detection zone
331+ found_highway_car_in_zone = False
332+
321333 # Check for potential collisions with highway cars
322334 for highway_car_id in self .highway_cars :
323335 if highway_car_id not in self .cars :
@@ -339,6 +351,7 @@ def _on_car_update(self, payload: str):
339351 )
340352
341353 if dist_highway_to_merge < self .ENTRY_ZONE_M :
354+ found_highway_car_in_zone = True
342355 logger .info (f"[ENTRY DETECTION] Analyzing collision: entering { update .car_id } vs highway { highway_car_id } , dist={ dist_highway_to_merge :.1f} m" )
343356 # Predict collision
344357 collision , ttc , min_dist = self ._predict_collision (update , highway_car )
@@ -391,6 +404,51 @@ def _on_car_update(self, payload: str):
391404 f"can safely merge. Min distance to { highway_car_id } : { min_dist :.1f} m"
392405 )
393406 self .alerted_pairs .add (pair_key )
407+
408+ # If no highway cars found in detection zone, it's safe to enter
409+ if not found_highway_car_in_zone :
410+ # Only alert once per entering car
411+ if update .car_id not in [pair [0 ] for pair in self .alerted_pairs ]:
412+ alert = {
413+ "alert_type" : "highway_entry_safe" ,
414+ "entering_car_id" : update .car_id ,
415+ "highway_car_id" : None ,
416+ "entering_speed_kmh" : update .speed_kmh ,
417+ "highway_speed_kmh" : None ,
418+ "predicted_min_distance_m" : None ,
419+ "status" : "safe" ,
420+ "timestamp" : time .time (),
421+ "latitude" : update .latitude ,
422+ "longitude" : update .longitude ,
423+ }
424+
425+ self .mqtt .publish (self .alert_topic , json .dumps (alert ))
426+ logger .info (
427+ f"[HIGHWAY ENTRY - SAFE] Car { update .car_id } "
428+ f"can safely merge - no highway traffic detected in entry zone"
429+ )
430+ # Mark this entering car as alerted
431+ self .alerted_pairs .add ((update .car_id , "no-traffic" ))
432+
433+ def _cleanup_car (self , car_id : str ):
434+ """Remove all state for a specific car (used for test cleanup)."""
435+ # Remove from cars dictionary
436+ if car_id in self .cars :
437+ del self .cars [car_id ]
438+ logger .info (f"[CLEANUP] Removed car state: { car_id } " )
439+
440+ # Remove from classification sets
441+ self .highway_cars .discard (car_id )
442+ self .entering_cars .discard (car_id )
443+
444+ # Remove from alerted pairs
445+ pairs_to_remove = {
446+ pair for pair in self .alerted_pairs
447+ if car_id in pair
448+ }
449+ self .alerted_pairs -= pairs_to_remove
450+ if pairs_to_remove :
451+ logger .info (f"[CLEANUP] Removed { len (pairs_to_remove )} alert pairs for { car_id } " )
394452
395453 def run (self ):
396454 logger .info ("Starting Highway Entry Detector..." )
0 commit comments