Skip to content

Commit 9d6d0fc

Browse files
committed
Add TargetsManager for mesh target simulation
Introduces the TargetsManager C++ class and integrates it into the mesh simulation workflow. Updates Cython and Python interfaces to use a shared_ptr to TargetsManager for managing multiple mesh targets, refactors target addition logic, and updates the mesh simulator to accept the new manager. This enables more flexible and efficient handling of mesh targets in radar simulations.
1 parent ca82867 commit 9d6d0fc

File tree

5 files changed

+217
-5
lines changed

5 files changed

+217
-5
lines changed

src/radarsimcpp

src/radarsimpy/includes/radarsimc.pxd

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Template Parameters:
3939
from libcpp cimport bool
4040
from libcpp.complex cimport complex as cpp_complex
4141
from libcpp.string cimport string
42+
from libcpp.memory cimport shared_ptr
4243

4344
#------------------------------------------------------------------------------
4445
# RadarSimPy Type Definitions
@@ -284,6 +285,24 @@ cdef extern from "simulator_point.hpp":
284285
void Run(Radar[H, L] & radar, # Radar configuration
285286
vector[Point[L]] & points) # Array of point targets
286287

288+
# Targets Manager
289+
# Manager class for handling multiple mesh targets in simulations
290+
cdef extern from "targets_manager.hpp":
291+
cdef cppclass TargetsManager[T]:
292+
TargetsManager() except +
293+
# Add a new target
294+
void AddTarget(const T * points, # Vertex coordinates array
295+
const int_t * cells, # Cell connectivity array
296+
const int_t & cell_size, # Number of cells in mesh
297+
const Vec3[T] & origin, # Target reference origin
298+
const vector[Vec3[T]] & location_array, # Time-varying locations
299+
const vector[Vec3[T]] & speed_array, # Time-varying velocities
300+
const vector[Vec3[T]] & rotation_array, # Time-varying rotations
301+
const vector[Vec3[T]] & rotation_rate_array, # Time-varying rotation rates
302+
const cpp_complex[T] & ep, # Relative permittivity (material property)
303+
const cpp_complex[T] & mu, # Relative permeability (material property)
304+
const bool & skip_diffusion) except +
305+
287306
# Mesh-based Ray Tracing Simulation
288307
# Physics-based 3D mesh target simulation using ray tracing and physical optics
289308
# Usage: For realistic simulation of complex targets with detailed geometry.
@@ -294,7 +313,7 @@ cdef extern from "simulator_mesh.hpp":
294313

295314
# Run mesh simulation with configurable fidelity
296315
RadarSimErrorCode Run(Radar[H, L] & radar, # Radar configuration
297-
vector[Target[L]] targets, # Array of mesh targets
316+
const shared_ptr[TargetsManager[L]] & targets_manager, # Array of mesh targets
298317
int level, # Simulation level (0=LOW, 1=MEDIUM, 2=HIGH)
299318
L density, # Ray density for physical optics
300319
Vec2[int_t] ray_filter, # Ray index filter [min, max]
@@ -314,6 +333,7 @@ cdef extern from "simulator_interference.hpp":
314333
void Run(Radar[H, L] & radar, # Victim radar
315334
Radar[H, L] & interf_radar) # Interfering radar
316335

336+
317337
#------------------------------------------------------------------------------
318338
# End of RadarSimPy C++ Interface Declarations
319339
#------------------------------------------------------------------------------

src/radarsimpy/lib/cp_radarsimc.pxd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ with support for both trial and full versions with appropriate limitations.
3434
from radarsimpy.includes.radarsimc cimport Radar
3535
from radarsimpy.includes.radarsimc cimport Target
3636
from radarsimpy.includes.radarsimc cimport Point
37+
from radarsimpy.includes.radarsimc cimport TargetsManager
3738
from radarsimpy.includes.type_def cimport float_t, int_t
3839
from libcpp.complex cimport complex as cpp_complex
3940

@@ -62,6 +63,11 @@ cdef Target[float_t] cp_Target(radar, target, timestamp, mesh_module) except *
6263
# Raises ValueError for invalid params, RuntimeError for mesh/FreeTier issues
6364
cdef Target[float_t] cp_RCS_Target(target, mesh_module) except *
6465

66+
cdef void cp_AddTarget(radar,
67+
target,
68+
timestamp,
69+
mesh_module,
70+
TargetsManager[float_t] * targets_manager) except *
6571

6672
# ============================================================================
6773
# Helper Functions for Internal Use

src/radarsimpy/lib/cp_radarsimc.pyx

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ from libcpp cimport bool
3232
# Local imports
3333
from radarsimpy.includes.radarsimc cimport (
3434
Transmitter, Receiver, TxChannel, RxChannel,
35-
Radar, Target, Point, Mem_Copy, Mem_Copy_Vec3,
35+
Radar, Target, Point, TargetsManager, Mem_Copy, Mem_Copy_Vec3,
3636
Mem_Copy_Complex, IsFreeTier
3737
)
3838
from radarsimpy.includes.rsvector cimport Vec3
@@ -859,6 +859,185 @@ cdef Target[float_t] cp_Target(radar,
859859
mu_c,
860860
<bool> target.get("skip_diffusion", False))
861861

862+
863+
@cython.cdivision(True)
864+
@cython.boundscheck(False)
865+
@cython.wraparound(False)
866+
cdef void cp_AddTarget(radar,
867+
target,
868+
timestamp,
869+
mesh_module,
870+
TargetsManager[float_t] * targets_manager):
871+
"""
872+
cp_Target((radar, target, ts_shape)
873+
874+
Creat Target object in Cython
875+
876+
:param Radar radar:
877+
Radar object
878+
:param dict target:
879+
Target properties
880+
:param tuple ts_shape:
881+
Shape of the time matrix
882+
883+
:return: C++ object of a target
884+
:rtype: Target
885+
"""
886+
# vector of location, speed, rotation, rotation rate
887+
cdef vector[Vec3[float_t]] loc_vt
888+
cdef vector[Vec3[float_t]] spd_vt
889+
cdef vector[Vec3[float_t]] rot_vt
890+
cdef vector[Vec3[float_t]] rrt_vt
891+
892+
cdef float_t[:, :, :] locx_mv, locy_mv, locz_mv
893+
cdef float_t[:, :, :] spdx_mv, spdy_mv, spdz_mv
894+
cdef float_t[:, :, :] rotx_mv, roty_mv, rotz_mv
895+
cdef float_t[:, :, :] rrtx_mv, rrty_mv, rrtz_mv
896+
897+
cdef cpp_complex[float_t] ep_c, mu_c
898+
899+
cdef int_t ch_idx, ps_idx, sp_idx
900+
ts_shape = np.shape(timestamp)
901+
cdef int_t bbsize_c = <int_t>(ts_shape[0]*ts_shape[1]*ts_shape[2])
902+
903+
cdef float_t scale
904+
cdef float_t[:, :] points_mv
905+
cdef int_t[:, :] cells_mv
906+
907+
# Enhanced mesh validation and loading with improved error messages
908+
unit = target.get("unit", "m")
909+
try:
910+
scale = _safe_unit_conversion(unit)
911+
except ValueError as e:
912+
raise ValueError(f"Invalid unit in target configuration: {e}")
913+
914+
try:
915+
mesh_data = load_mesh(target["model"], scale, mesh_module)
916+
points_mv = mesh_data["points"].astype(np_float)
917+
cells_mv = mesh_data["cells"].astype(np.int32)
918+
except Exception as e:
919+
raise RuntimeError(f"Failed to load mesh model '{target.get('model', 'unknown')}': {e}")
920+
921+
# Enhanced FreeTier validation using helper function
922+
_validate_mesh_for_free_tier(cells_mv.shape[0])
923+
924+
cdef float_t[:] origin_mv = np.array(target.get("origin", (0, 0, 0)), dtype=np_float)
925+
926+
location = list(target.get("location", [0, 0, 0]))
927+
speed = list(target.get("speed", [0, 0, 0]))
928+
rotation = list(target.get("rotation", [0, 0, 0]))
929+
rotation_rate = list(target.get( "rotation_rate", [0, 0, 0]))
930+
931+
cdef float_t[:] location_mv, speed_mv, rotation_mv, rotation_rate_mv
932+
933+
permittivity = target.get("permittivity", 1e38)
934+
permeability = target.get("permeability", 1)
935+
if permittivity == "PEC":
936+
ep_c = cpp_complex[float_t](<float_t>1e38, <float_t>0.0)
937+
mu_c = cpp_complex[float_t](<float_t>1.0, <float_t>0.0)
938+
else:
939+
ep_c = cpp_complex[float_t](<float_t>np.real(permittivity), <float_t>np.imag(permittivity))
940+
mu_c = cpp_complex[float_t](<float_t>np.real(permeability), <float_t>np.imag(permeability))
941+
942+
if any(np.size(var) > 1 for var in location + speed + rotation + rotation_rate):
943+
if np.size(location[0]) > 1:
944+
locx_mv = location[0].astype(np_float)
945+
else:
946+
locx_mv = (location[0] + speed[0]*timestamp).astype(np_float)
947+
948+
if np.size(location[1]) > 1:
949+
locy_mv = location[1].astype(np_float)
950+
else:
951+
locy_mv = (location[1] + speed[1]*timestamp).astype(np_float)
952+
953+
if np.size(location[2]) > 1:
954+
locz_mv = location[2].astype(np_float)
955+
else:
956+
locz_mv = (location[2] + speed[2]*timestamp).astype(np_float)
957+
958+
if np.size(speed[0]) > 1:
959+
spdx_mv = speed[0].astype(np_float)
960+
else:
961+
spdx_mv = np.full(ts_shape, speed[0], dtype=np_float)
962+
963+
if np.size(speed[1]) > 1:
964+
spdy_mv = speed[1].astype(np_float)
965+
else:
966+
spdy_mv = np.full(ts_shape, speed[1], dtype=np_float)
967+
968+
if np.size(speed[2]) > 1:
969+
spdz_mv = speed[2].astype(np_float)
970+
else:
971+
spdz_mv = np.full(ts_shape, speed[2], dtype=np_float)
972+
973+
if np.size(rotation[0]) > 1:
974+
rotx_mv = np.radians(rotation[0]).astype(np_float)
975+
else:
976+
rotx_mv = np.radians(
977+
rotation[0] + rotation_rate[0]*timestamp).astype(np_float)
978+
979+
if np.size(rotation[1]) > 1:
980+
roty_mv = np.radians(rotation[1]).astype(np_float)
981+
else:
982+
roty_mv = np.radians(
983+
rotation[1] + rotation_rate[1]*timestamp).astype(np_float)
984+
985+
if np.size(rotation[2]) > 1:
986+
rotz_mv = np.radians(rotation[2]).astype(np_float)
987+
else:
988+
rotz_mv = np.radians(
989+
rotation[2] + rotation_rate[2]*timestamp).astype(np_float)
990+
991+
if np.size(rotation_rate[0]) > 1:
992+
rrtx_mv = np.radians(rotation_rate[0]).astype(np_float)
993+
else:
994+
rrtx_mv = np.full(ts_shape, np.radians(rotation_rate[0]), dtype=np_float)
995+
996+
if np.size(rotation_rate[1]) > 1:
997+
rrty_mv = np.radians(rotation_rate[1]).astype(np_float)
998+
else:
999+
rrty_mv = np.full(ts_shape, np.radians(rotation_rate[1]), dtype=np_float)
1000+
1001+
if np.size(rotation_rate[2]) > 1:
1002+
rrtz_mv = np.radians(rotation_rate[2]).astype(np_float)
1003+
else:
1004+
rrtz_mv = np.full(ts_shape, np.radians(rotation_rate[2]), dtype=np_float)
1005+
1006+
Mem_Copy_Vec3(&locx_mv[0,0,0], &locy_mv[0,0,0], &locz_mv[0,0,0], bbsize_c, loc_vt)
1007+
Mem_Copy_Vec3(&spdx_mv[0,0,0], &spdy_mv[0,0,0], &spdz_mv[0,0,0], bbsize_c, spd_vt)
1008+
Mem_Copy_Vec3(&rotx_mv[0,0,0], &roty_mv[0,0,0], &rotz_mv[0,0,0], bbsize_c, rot_vt)
1009+
Mem_Copy_Vec3(&rrtx_mv[0,0,0], &rrty_mv[0,0,0], &rrtz_mv[0,0,0], bbsize_c, rrt_vt)
1010+
1011+
else:
1012+
location_mv = np.array(location, dtype=np_float)
1013+
loc_vt.push_back(Vec3[float_t](&location_mv[0]))
1014+
1015+
speed_mv = np.array(speed, dtype=np_float)
1016+
spd_vt.push_back(Vec3[float_t](&speed_mv[0]))
1017+
1018+
rotation_mv = np.radians(np.array(rotation, dtype=np_float)).astype(np_float)
1019+
rot_vt.push_back(Vec3[float_t](&rotation_mv[0]))
1020+
1021+
rotation_rate_mv = np.radians(np.array(rotation_rate, dtype=np_float)).astype(np_float)
1022+
rrt_vt.push_back(Vec3[float_t](&rotation_rate_mv[0]))
1023+
1024+
# Handle deprecated parameter with enhanced warning
1025+
if "is_ground" in target:
1026+
target["skip_diffusion"] = target["is_ground"]
1027+
_warn_deprecated_parameter("is_ground", "skip_diffusion")
1028+
1029+
targets_manager[0].AddTarget(&points_mv[0, 0],
1030+
&cells_mv[0, 0],
1031+
<int_t> cells_mv.shape[0],
1032+
Vec3[float_t](&origin_mv[0]),
1033+
loc_vt,
1034+
spd_vt,
1035+
rot_vt,
1036+
rrt_vt,
1037+
ep_c,
1038+
mu_c,
1039+
<bool> target.get("skip_diffusion", False))
1040+
8621041
@cython.cdivision(True)
8631042
@cython.boundscheck(False)
8641043
@cython.wraparound(False)

src/radarsimpy/simulator_radar.pyx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ cimport cython
3535

3636
# C++ type definitions
3737
from libcpp.string cimport string
38+
from libcpp.memory cimport shared_ptr, make_shared
3839
from radarsimpy.includes.type_def cimport (
3940
vector,
4041
float_t,
@@ -47,6 +48,7 @@ from radarsimpy.includes.radarsimc cimport (
4748
Radar,
4849
Point,
4950
Target,
51+
TargetsManager,
5052
MeshSimulator,
5153
PointSimulator,
5254
InterferenceSimulator,
@@ -58,7 +60,8 @@ from radarsimpy.includes.radarsimc cimport (
5860
from radarsimpy.lib.cp_radarsimc cimport (
5961
cp_Radar,
6062
cp_Target,
61-
cp_Point
63+
cp_Point,
64+
cp_AddTarget
6265
)
6366

6467
from radarsimpy.mesh_kit import import_mesh_module
@@ -252,6 +255,8 @@ cpdef sim_radar(radar, targets, frame_time=None, density=1, level=None, interf=N
252255
vector[Point[float_t]] point_vt
253256
vector[Target[float_t]] target_vt
254257
Vec2[int_t] ray_filter_c
258+
259+
cdef shared_ptr[TargetsManager[float_t]] targets_manager = make_shared[TargetsManager[float_t]]()
255260

256261
# Simulator instances
257262
cdef:
@@ -330,6 +335,8 @@ cpdef sim_radar(radar, targets, frame_time=None, density=1, level=None, interf=N
330335
if mesh_module is None:
331336
mesh_module = import_mesh_module()
332337
target_vt.emplace_back(cp_Target(radar, tgt, timestamp, mesh_module))
338+
339+
cp_AddTarget(radar, tgt, timestamp, mesh_module, targets_manager.get())
333340
else:
334341
# Extract point target parameters with defaults
335342
loc = tgt["location"]
@@ -386,7 +393,7 @@ cpdef sim_radar(radar, targets, frame_time=None, density=1, level=None, interf=N
386393
# Run scene simulation
387394
err = mesh_sim_c.Run(
388395
radar_c,
389-
target_vt,
396+
targets_manager,
390397
level_id,
391398
<float_t> density,
392399
ray_filter_c,

0 commit comments

Comments
 (0)