11from ...state import AllState , VehicleState , ObjectPose , ObjectFrameEnum , AgentState , AgentEnum , AgentActivityEnum
22from ..interface .gem import GEMInterface
33from ..component import Component
4- # from .perception_utils import *
4+ from .pedestrian_utils import pose_to_matrix
55from .pedestrian_utils_gem import *
66from typing import Dict , List , Optional , Tuple
77import rospy
@@ -240,15 +240,7 @@ def update(self, vehicle: VehicleState) -> Dict[str, AgentState]:
240240 self .start_pose_abs = vehicle .pose
241241 rospy .loginfo ("CombinedDetector3D latched start pose." )
242242
243- current_frame_agents = self ._fuse_bounding_boxes (yolo_bbx_array , pp_bbx_array , vehicle , current_time )
244-
245- return {}
246- # Tracking disabled for now
247- # if self.enable_tracking:
248- # self._update_tracking(current_frame_agents)
249- # else:
250- # self.tracked_agents = current_frame_agents # NOTE: No deepcopy
251- # return self.tracked_agents
243+ return self ._fuse_bounding_boxes (yolo_bbx_array , pp_bbx_array , vehicle , current_time )
252244
253245
254246 def _fuse_bounding_boxes (self ,
@@ -270,7 +262,7 @@ def _fuse_bounding_boxes(self,
270262 Dictionary of agent states
271263 """
272264 original_header = yolo_bbx_array .header
273- current_agents_in_frame : Dict [str , AgentState ] = {}
265+ agents : Dict [str , AgentState ] = {}
274266 yolo_boxes : List [BoundingBox ] = yolo_bbx_array .boxes
275267 pp_boxes : List [BoundingBox ] = pp_bbx_array .boxes
276268
@@ -335,64 +327,85 @@ def _fuse_bounding_boxes(self,
335327 quat_w = box .pose .orientation .w
336328 yaw , pitch , roll = R .from_quat ([quat_x , quat_y , quat_z , quat_w ]).as_euler ('zyx' , degrees = False )
337329
338- # Transform to start frame if needed
339- if self .use_start_frame and self .start_pose_abs is not None :
340- vehicle_pose_in_start_frame = vehicle_state .pose .to_frame (
341- ObjectFrameEnum .START , vehicle_state .pose , self .start_pose_abs
342- )
343- T_vehicle_to_start = pose_to_matrix (vehicle_pose_in_start_frame )
344- object_pose_current_h = np .array ([[pos_x ],[pos_y ],[pos_z ],[1.0 ]])
345- object_pose_start_h = T_vehicle_to_start @ object_pose_current_h
346- final_x , final_y , final_z = object_pose_start_h [:3 , 0 ]
347- else :
348- final_x , final_y , final_z = pos_x , pos_y , pos_z
330+ # Convert to start frame
331+ vehicle_pose_in_start_frame = vehicle_state .pose .to_frame (
332+ ObjectFrameEnum .START , vehicle_state .pose , self .start_pose_abs
333+ )
334+ T_vehicle_to_start = pose_to_matrix (vehicle_pose_in_start_frame )
335+ object_pose_current_h = np .array ([[pos_x ],[pos_y ],[pos_z ],[1.0 ]])
336+ object_pose_start_h = T_vehicle_to_start @ object_pose_current_h
337+ final_x , final_y , final_z = object_pose_start_h [:3 , 0 ]
349338
350- final_pose = ObjectPose (
339+ new_pose = ObjectPose (
351340 t = current_time , x = final_x , y = final_y , z = final_z ,
352341 yaw = yaw , pitch = pitch , roll = roll , frame = output_frame_enum
353342 )
354343 dims = (box .dimensions .x , box .dimensions .y , box .dimensions .z )
355- ######### Mapping based on label (integer) from BoundingBox msg
356- # Set agent type based on label
357- agent_type = AgentEnum .PEDESTRIAN if box .label == 0 else AgentEnum .UNKNOWN
358- activity = AgentActivityEnum .UNKNOWN # Placeholder
359-
360- # temp id
361- # _update_tracking assign persistent IDs
362- temp_agent_id = f"pedestrian{ i } "
363-
364- current_agents_in_frame [temp_agent_id ] = AgentState (
365- pose = final_pose , dimensions = dims , outline = None , type = agent_type ,
366- activity = activity , velocity = (0.0 ,0.0 ,0.0 ), yaw_rate = 0.0
367- # score=box.value # score
344+
345+ new_pose = ObjectPose (
346+ t = current_time , x = final_x , y = final_y , z = final_z - box .dimensions .z / 2.0 ,
347+ yaw = yaw , pitch = pitch , roll = roll , frame = output_frame_enum
348+ )
349+ dims [2 ] = dims [2 ] * 2.0 # AgentState has z center on the floor and height is full height.
350+
351+ existing_id = match_existing_pedestrian (
352+ new_center = np .array ([new_pose .x , new_pose .y , new_pose .z ]),
353+ new_dims = dims ,
354+ existing_agents = self .tracked_agents ,
355+ distance_threshold = 2.0
368356 )
357+
358+ if existing_id is not None :
359+ old_state = self .tracked_agents [existing_id ]
360+ dt = new_pose .t - old_state .pose .t
361+ vx , vy , vz = compute_velocity (old_state .pose , new_pose , dt )
362+ updated_agent = AgentState (
363+ pose = new_pose ,
364+ dimensions = dims ,
365+ outline = None ,
366+ type = AgentEnum .PEDESTRIAN ,
367+ activity = AgentActivityEnum .MOVING ,
368+ velocity = (vx , vy , vz ),
369+ yaw_rate = 0
370+ )
371+ agents [existing_id ] = updated_agent
372+ self .tracked_agents [existing_id ] = updated_agent
373+ else :
374+ agent_id = f"pedestrian{ self .ped_counter } "
375+ self .ped_counter += 1
376+ new_agent = AgentState (
377+ pose = new_pose ,
378+ dimensions = dims ,
379+ outline = None ,
380+ type = AgentEnum .PEDESTRIAN ,
381+ activity = AgentActivityEnum .MOVING ,
382+ velocity = (0 , 0 , 0 ),
383+ yaw_rate = 0
384+ )
385+ agents [agent_id ] = new_agent
386+ self .tracked_agents [agent_id ] = new_agent
387+
369388 except Exception as e :
370389 rospy .logwarn (f"Failed to convert final BoundingBox { i } to AgentState: { e } " )
371390 continue
372391
373392 self .pub_fused .publish (fused_bb_array )
374- return current_agents_in_frame
375-
376-
377- def _update_tracking (self , current_frame_agents : Dict [str , AgentState ]):
378-
379- # Todo tracking
380- ## Match 'current_frame_agents' to 'self.tracked_agents'.
381- ## - Use position (already in correct START or CURRENT frame), maybe size/type.
382- ## - Need a matching algorithm (e.g., nearest neighbor within radius, Hungarian).
383- ## For matched pairs:
384- ## - Update the existing agent in 'self.tracked_agents' (e.g., smooth pose, update timestamp).
385- ## For unmatched 'current_frame_agents':
386- ## - These are new detections. Assign a persistent ID (e.g., f"Ped_{self.ped_counter}").
387- ## - Increment self.ped_counter.
388- ## - Add them to 'self.tracked_agents'.
389- ## For unmatched 'self.tracked_agents' (agents not seen this frame):
390- ## - Increment a 'missed frames' counter or check timestamp.
391- ## - If missed for too long (e.g., > 1 second), remove from 'self.tracked_agents'.
392-
393- # return without tracking
394- self .tracked_agents = current_frame_agents
395393
394+ stale_ids = [agent_id for agent_id , agent in self .tracked_agents .items ()
395+ if current_time - agent .pose .t > 5.0 ]
396+ for agent_id in stale_ids :
397+ rospy .loginfo (f"Removing stale agent: { agent_id } \n " )
398+ for agent_id , agent in agents .items ():
399+ p = agent .pose
400+ # Format pose and velocity with 3 decimals (or as needed)
401+ rospy .loginfo (
402+ f"Agent ID: { agent_id } \n "
403+ f"Pose: (x: { p .x :.3f} , y: { p .y :.3f} , z: { p .z :.3f} , "
404+ f"yaw: { p .yaw :.3f} , pitch: { p .pitch :.3f} , roll: { p .roll :.3f} )\n "
405+ f"Velocity: (vx: { agent .velocity [0 ]:.3f} , vy: { agent .velocity [1 ]:.3f} , vz: { agent .velocity [2 ]:.3f} )\n "
406+ )
407+
408+ return agents
396409
397410
398411# Fake 2D Combined Detector for testing purposes
0 commit comments