Targets

PointTargets, StructureTargets and Aspect, the records that say where the scatterers are, how strongly they scatter, and how they move.

A Scene's meshes reflect and occlude, but they add no scatterers. Every simulation call names its scatterers with one targets record. See Scenes and targets.

from witwin.radar import Aspect, PointTargets, StructureTargets

Every record takes exactly one of rcs and amplitude. They are two forms of the same strength, related by amplitude = sqrt(4 · pi · rcs) / wavelength.

PointTargets#

class PointTargets(positions, rcs=None, amplitude=None, phase=0.0, trajectory=None, ids=None, aspect=None)

Point scatterers at world positions you give.

positionstensor (S, 3) | sequence of (x, y, z)required

World positions, m. A tensor is passed through unchanged, so a requires_grad tensor or a forward-mode dual keeps its graph. A tensor must be on Radar.device.

rcsfloat | 0-dim tensordefault None

Radar cross section, m², shared by every target. A 0-dim tensor can carry a gradient.

amplitudefloat | 0-dim tensordefault None

Dimensionless strength sqrt(4 · pi · rcs) / wavelength, instead of rcs.

phasefloatdefault 0.0

Scattering phase, rad.

trajectoryCallable[[float], tensor (S, 3)] | Nonedefault None

trajectory(t) returns the positions of the same ordered points at time t, s. None means the targets do not move. Rotation and articulation must move the points themselves.

idstuple[int, ...] | Nonedefault None

Stable world IDs, one per target. None allocates them.

aspectAspect | Nonedefault None

Aspect-dependent scattering. None scatters isotropically.

Raises

  • ValueError: both or neither of rcs and amplitude; a strength vector with more than zero dimensions and no aspect.
  • TypeError: trajectory is not callable; aspect is not an Aspect.
  • ValueError at simulation: a positions tensor on a different device than the radar; a vector rcs, even with an aspect.
PropertyReturns
countNumber of targets, int.
import torch
from witwin.radar import PointTargets
 
start = torch.tensor([[0.0, 0.0, -4.0]], device=radar.device)
 
def walk(t):
    return start + torch.tensor([[0.0, 0.0, 1.5 * t]], device=radar.device)   # 1.5 m/s toward the radar
 
targets = PointTargets(positions=start, rcs=1.0, trajectory=walk)

StructureTargets#

class StructureTargets(rcs=None, amplitude=None, structure_ids=None, phase=0.0, ids=None)

One scatterer at the world anchor Core publishes for each selected structure. The anchor exists only for a structure with rigid motion, such as a LinearTrajectory in a DynamicScene.

rcsfloat | 0-dim tensordefault None

Radar cross section, m², shared by every selected structure.

amplitudefloat | 0-dim tensordefault None

Dimensionless strength instead of rcs.

structure_idstuple[int, ...] | Nonedefault None

Structures to place a scatterer on. None takes every structure in the snapshot. Order is by ascending structure ID.

phasefloatdefault 0.0

Scattering phase, rad.

idstuple[int, ...] | Nonedefault None

Stable world IDs, one per selected structure. None allocates them.

Raises ValueError for both or neither of rcs and amplitude. NotImplementedError at simulation for a structure without rigid motion; Radar does not sample scatterers from a mesh.

targets = StructureTargets(rcs=1.0, structure_ids=(7,))
result = radar.simulate(dynamic_scene, targets, times=(0.0,), reflections=0)

Aspect#

class Aspect(axis, exponent, coherent_interval, phase_rate=0.0)

Aspect-dependent scattering for a target that is not a sphere. The response of a round trip is

amplitude * max(-dot(dir_in, axis), 0)^n * max(dot(dir_out, axis), 0)^n

so axis is the direction of strongest return and exponent sets how fast the return falls away from it. With an Aspect, PointTargets.amplitude may be a vector with one value per target. rcs must still be a scalar: a vector rcs raises ValueError at simulation.

axistensor (S, 3)required

One unit vector per target, world frame. Not normalized for you.

exponentfloatrequired

Lobe sharpness n, at least 1. Larger is narrower.

coherent_intervalfloatrequired

How long one aspect realization stays coherent, s. Must be positive.

phase_ratefloatdefault 0.0

Aspect phase drift, rad/s.

Raises ValueError for exponent < 1, a non-positive coherent_interval, or an axis whose shape is not (S, 3) for S targets.

axis = torch.tensor([[0.0, 0.0, 1.0], [0.0, 0.0, 1.0]], device=radar.device)
rcs = torch.tensor([1.0, 0.5], device=radar.device)
targets = PointTargets(
    positions=[(-0.5, 0.0, -3.0), (0.5, 0.0, -3.0)],
    amplitude=torch.sqrt(4 * torch.pi * rcs) / radar.wavelength,   # one strength per target
    aspect=Aspect(axis=axis, exponent=2.0, coherent_interval=0.1),
)