Ray Tracing with raytrace(): define a reception local area instead of a single point

17 views (last 30 days)
Hi,
I'm trying to use Matlab's raytrace() function from the Communications toolbox with the Shooting & Bouncing Rays method to compute the received rays in a local area around the receiver RX, instead of just in a single point (RX).
The context is the following: I'm trying to compute reflections of RF waves on a human body, using Matlab's raytrace() function. I model the human body as a cylinder, compute a triangulation (needed for the raytrace() function) for it and feed that to the raytrace() function. Let's say I put the cylinder at the perfect angle w.r.t. the transmitter TX and the receiver RX, a ray corresponding to a single reflection is found. However if I move the cylinder of 10 cm the reflection is not found, which is logical. It is illustrated on the plot below (left: a reflection is found, right: no reflection is found):
However since the human body is not a perfect cylinder, in reality there is a high chance that for such a small displacement (10 cm) from the ideal position a reflection would still be present. That is why I would like to compute all rays arriving in a local area around RX as it is usually done in ray tracing simulations to compute the received power at RX, rather than at the RX precise point. This way I would detect rays even when the human body is not at the perfect position w.r.t. TX and RX.
I've already considered instantiating several RXs in a local area, but then I detect several rays while there should be only one, so if I add a new cylinder in the scene then I will not be able to discriminate those artificial rays from the ones coming from that new cylinder. I've also dug in the raytrace() function code. At line 405 it calls another raytrace() function, which at line 313-323 makes the test I want to perform. It defines a radius around RX and checks if the ray falls within that radius (I'm using Matlab 2021a):
% Calculate reception radius, i.e., alpha*d/sqrt(3)
radius = ((rayDist + srcPrjDist) .* maxAngularSep)/sqrt(3);
% Detect which rays hit the Rx and mitigate double counting.
% Because the first segment for LOS is already covered, no need to
% perform detection for it.
if refIdx > 1
% Flags of the rays that reach Rx. Note that intDist can be NaN
% if the ray hits a sharp edge. But (NaN > a) = 0 for any value
% of a.
isRxReached = (srcPrjDist > 0) & (rxPrjDist <= radius) & ...
(intDist >= srcPrjDist);
A way to proceed would be to extend that radius, but the function cannot be modified unfortunately, and shadowing the function with a modified local copy is usually bad practice (and doesn't work in this case since some validations are done within the function, that require code accessible only from the toolbox folder).
So does someone have an idea on how to proceed to compute rays in a local area? I include herebelow the code I use to generate TX, RX, the cylinder and the propagation model.
%% TX/RX
fc = 2.45e9;
tx = txsite("cartesian", "AntennaPosition", [0; 0; 1],"TransmitterFrequency", fc);
rx = rxsite("cartesian","AntennaPosition", [0; 3; 1]);
%figure;
scatter3(tx.AntennaPosition(1,:), tx.AntennaPosition(2,:), tx.AntennaPosition(3,:), 'sr', 'filled');hold on;
scatter3(rx.AntennaPosition(1,:), rx.AntennaPosition(2,:), rx.AntennaPosition(3,:), 'sb', 'filled');hold on;
xlabel('x');ylabel('y');zlabel('z');
legend('TX','RX');
%% Model human body as a cylinder
r = 1; % [m]
height = 1.75; % [m]
theta = linspace(0,2*pi,36).';
xc = 1.5; % center of the cylinder
yc = 1.6;
x = repmat(xc + r*cos(theta),[2 1]);
y = repmat(yc + r*sin(theta),[2 1]);
z = [0*ones(length(theta),1);height*ones(length(theta),1)];
P = [x y z];
[k,vol] = convhulln(P); % convex hull: set of points defining the boundary of the volume
trisurf(k,P(:,1),P(:,2),P(:,3),'FaceColor','magenta')
TR = triangulation(k,P);
%% Propagation model and raytracing
pm = propagationModel("raytracing","CoordinateSystem","cartesian","Method","sbr","MaxNumReflections",2,"SurfaceMaterial","perfect-reflector",...
"AngularSeparation","low");
rays = raytrace(tx, rx, pm, 'Map', TR);
noMPC = 1;
rays_n = rays{1};
if length(rays_n) > 1
refl = rays_n(2).ReflectionLocations; % the first element of rays_n is the direct path
line1 = [tx.AntennaPosition refl];
line2 = [refl rx.AntennaPosition];
plot3(line1(1,:),line1(2,:),line1(3,:),'b');
plot3(line2(1,:),line2(2,:),line2(3,:),'b');
noMPC = 0;
else
disp('No MPC, only direct path');
end
Thank you for your help!

Accepted Answer

Yue Shang
Yue Shang on 29 Apr 2021
Hi Laurent,
First, creating a finer mesh for the cylinder may help. For example, you will find one ray in the failing case if you define
theta = linspace(0,2*pi,360).';
I would suggest instantiating multiple rx sites in the local area as you mentioned, instead of modifying the reception sphere radius which can invalidate the shooting bouncing rays (SBR) method. For example, you can define 27 rx sites in a cubic around the primary rx site of interest:
[x, y,z] = meshgrid(-0.1:0.1:0.1, 2.9:0.1:3.1, 0.9:0.1:1.1);
rx = rxsite("cartesian","AntennaPosition", [x(:),y(:),z(:)]');
In the ray tracing result, rays{14} would be the "true" rays arriving at the primary rx and the other cell array elements contain the "artificial" rays arriving at the local area, for any number of cylinders in the scene.
  3 Comments
Laurent Storrer
Laurent Storrer on 3 May 2021
Hi Yue,
Ok I see so increasing the radius would give rise to false rays.
I will go for your suggested approach with the multiple RXs in a cube then, and I think I will also try other surfaces than a cylinder to model the human body.
Thank you for your help!
Best regards,
Laurent

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!