Browse Source

feat(radar): optimize target detection and implement peak grouping

- physics: increased metal roughness in Sceneset.py to 1.5mm for better diffuse scattering
- cfar: widened guard cells to 5x5 in config.yaml to isolate clutter; threshold kept at 20dB
- signal-processing: implemented 3x3 local maximum filter (NMS) in radar_processor.py to eliminate sidelobes
- config: enabled peak_grouping toggle in config.yaml
main
RUSHIL AMBARISH KADU 4 weeks ago
parent
commit
cb91df1960
  1. 2
      scripts/ISOLATE/e2e_agent_sem_lidar2shenron_package/shenron/Sceneset.py
  2. 5
      scripts/ISOLATE/sim_radar_utils/config.yaml
  3. 21
      scripts/ISOLATE/sim_radar_utils/radar_processor.py

2
scripts/ISOLATE/e2e_agent_sem_lidar2shenron_package/shenron/Sceneset.py

@ -401,7 +401,7 @@ def get_loss_3(points, rho, az_boresight, elev_angle, angles, radar, use_spec =
wood_roughness = 0.0017 #1.7mm wood_roughness = 0.0017 #1.7mm
conc_roughness = 0.0017 #1.7mm conc_roughness = 0.0017 #1.7mm
human_roughness = 0.01 # 100um human_roughness = 0.01 # 100um
metal_roughness = 0.00005 # 100um
metal_roughness = 0.0015 # 1.5mm (Increased from 0.05mm to ensure diffuse scattering when angled/crashed)
roughness = np.array([unlabel_roughness,wood_roughness,conc_roughness,human_roughness,metal_roughness]) roughness = np.array([unlabel_roughness,wood_roughness,conc_roughness,human_roughness,metal_roughness])

5
scripts/ISOLATE/sim_radar_utils/config.yaml

@ -49,8 +49,9 @@ ROS:
timeStamp: '/time_stamp.npy' timeStamp: '/time_stamp.npy'
CFAR: CFAR:
win_param: [9, 9, 3, 3]
threshold: 20
win_param: [9, 9, 5, 5] # [Est. width, Est. height, Guard width, Guard height] - Widened guard to 11x11 to isolate nearby clutter
threshold: 20 # dB (Standard) - Reverted to 20dB as per user request to maintain baseline sensitivity
peak_grouping: true # Toggle Non-Maximum Suppression (NMS) to eliminate range/doppler sidelobes
Visualize: Visualize:

21
scripts/ISOLATE/sim_radar_utils/radar_processor.py

@ -70,6 +70,27 @@ class RadarProcessor:
# detect useful peaks using CFAR (NOW RETURNING THRESHOLD BASELINE) # detect useful peaks using CFAR (NOW RETURNING THRESHOLD BASELINE)
hit_matrix, threshold_matrix = self.cfar(rd_heatmap) hit_matrix, threshold_matrix = self.cfar(rd_heatmap)
# 2.5 Optional Peak Grouping (Non-Maximum Suppression)
# Algorithm: 3x3 Local Maximum Filter
# -----------------------------------
# This step prunes "ghost" detections by ensuring each hit is the strongest cell
# in its immediate neighborhood. In high-SNR scenarios (like metal poles),
# range/doppler sidelobes (the 'sinc' pattern) often cross the CFAR threshold,
# creating a trail of points. Peak grouping ensures only the true target centroid is kept.
if cfarCfg.get('peak_grouping', False):
# Pad the heatmap to allow comparison at the edges of the RD map
padded_rd = np.pad(rd_heatmap, 1, mode='constant', constant_values=0)
# Compare current cell against its 4 immediate neighbors (Shifted arrays)
# Logic: is_local_max = (current >= up) & (current >= down) & (current >= left) & (current >= right)
is_local_max = (rd_heatmap >= padded_rd[0:-2, 1:-1]) & \
(rd_heatmap >= padded_rd[2:, 1:-1]) & \
(rd_heatmap >= padded_rd[1:-1, 0:-2]) & \
(rd_heatmap >= padded_rd[1:-1, 2:])
# Combine the CFAR mask with the Local Maximum mask
hit_matrix = hit_matrix & is_local_max
# 3. Global Range-Azimuth Heatmap — Doppler-Slice Accumulation # 3. Global Range-Azimuth Heatmap — Doppler-Slice Accumulation
# Loop over every Doppler bin, apply a windowed Angle-FFT per slice, # Loop over every Doppler bin, apply a windowed Angle-FFT per slice,
# and incoherently sum the power. This preserves angular diversity from # and incoherently sum the power. This preserves angular diversity from

Loading…
Cancel
Save