@@ -254,6 +254,29 @@ def compute_velocity(old_pose: ObjectPose, new_pose: ObjectPose, dt: float) -> t
254254 vz = (new_pose .z - old_pose .z ) / dt
255255 return (vx , vy , vz )
256256
257+ def exponential_smooth_velocity (self , raw_vel , old_smooth_vel , alpha = 0.3 ):
258+ """
259+ Applies exponential smoothing to the raw velocity.
260+
261+ v_smoothed = alpha * v_raw + (1 - alpha) * v_old_smooth
262+
263+ Args:
264+ raw_vel (tuple): The raw velocity (vx, vy, vz).
265+ old_smooth_vel (tuple): The previously smoothed velocity (vx_smooth, vy_smooth, vz_smooth).
266+ alpha (float): The smoothing factor in [0,1].
267+
268+ Returns:
269+ tuple: The new smoothed velocity (vx_smooth, vy_smooth, vz_smooth).
270+ """
271+ vx_raw , vy_raw , vz_raw = raw_vel
272+ vx_old , vy_old , vz_old = old_smooth_vel
273+
274+ vx_new = alpha * vx_raw + (1 - alpha ) * vx_old
275+ vy_new = alpha * vy_raw + (1 - alpha ) * vy_old
276+ vz_new = alpha * vz_raw + (1 - alpha ) * vz_old
277+
278+ return (vx_new , vy_new , vz_new )
279+
257280
258281def extract_roi_box (lidar_pc , center , half_extents ):
259282 """
@@ -495,6 +518,11 @@ def __init__(self, vehicle_interface: GEMInterface):
495518 self .current_agents = {}
496519 self .tracked_agents = {}
497520 self .pedestrian_counter = 0
521+
522+ # Add a dictionary to hold smoothed velocities:
523+ # Key: agent_id, Value: (vx_smooth, vy_smooth, vz_smooth)
524+ self .smoothed_velocities = {}
525+
498526 # Variables to store the most recent synchronized sensor data:
499527 self .latest_image = None
500528 self .latest_lidar = None
@@ -708,26 +736,42 @@ def update(self, vehicle: VehicleState) -> Dict[str, AgentState]:
708736 )
709737
710738 if existing_id is not None :
711- # Update the state of the matched pedestrian using the computed velocity.
739+ # 1) Get the old agent state
712740 old_agent_state = self .tracked_agents [existing_id ]
713741 dt = new_pose .t - old_agent_state .pose .t
714- '''
715- We found that the velocity calculated here is not entirely stable.
716- We are implementing a more stable method, e.g. kalman filter based one
717- '''
718- vx , vy , vz = compute_velocity (old_agent_state .pose , new_pose , dt )
719742
743+ # 2) Compute raw velocity
744+ vx_raw , vy_raw , vz_raw = compute_velocity (old_agent_state .pose , new_pose , dt )
745+
746+ # 3) Retrieve the old smoothed velocity (or initialize if not available)
747+ old_smooth_vel = self .smoothed_velocities .get (existing_id , (0.0 , 0.0 , 0.0 ))
748+
749+ # 4) Exponential smoothing
750+ alpha = 0.3 # Tweak this to find a good balance
751+ vx_smooth , vy_smooth , vz_smooth = self .exponential_smooth_velocity (
752+ (vx_raw , vy_raw , vz_raw ),
753+ old_smooth_vel ,
754+ alpha = alpha
755+ )
756+
757+ # 5) Update the dictionary with the new smoothed velocity
758+ self .smoothed_velocities [existing_id ] = (vx_smooth , vy_smooth , vz_smooth )
759+
760+ # 6) Create the updated agent with the smoothed velocity
720761 updated_agent = AgentState (
721762 pose = new_pose ,
722763 dimensions = dims ,
723764 outline = None ,
724765 type = AgentEnum .PEDESTRIAN ,
725766 activity = AgentActivityEnum .MOVING ,
726- velocity = (vx , vy , vz ),
767+ velocity = (vx_smooth , vy_smooth , vz_smooth ),
727768 yaw_rate = 0
728769 )
770+
771+ # 7) Save it in both the local dict and self.tracked_agents
729772 agents [existing_id ] = updated_agent
730773 self .tracked_agents [existing_id ] = updated_agent
774+
731775 else :
732776 # If no match is found, create a new pedestrian agent.
733777 agent_id = f"pedestrian{ self .pedestrian_counter } "
@@ -744,6 +788,7 @@ def update(self, vehicle: VehicleState) -> Dict[str, AgentState]:
744788 )
745789 agents [agent_id ] = new_agent
746790 self .tracked_agents [agent_id ] = new_agent
791+ self .smoothed_velocities [agent_id ] = (0.0 , 0.0 , 0.0 )
747792
748793 self .current_agents = agents
749794
0 commit comments