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

48 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
Yue Shang
Yue Shang on 30 Apr 2021
Hi Laurent,
In the SBR ray tracing method, each ray represents a cone-shape tube whose size grows as the ray travels. The overlap between adjacent tubes should be minimal, for which the current reception sphere radius is designed. Increasing the reception sphere will likely end up with more than one ray for one rx, while there should be only one. You can refer to the following page for some description of this ray tracing method:
When you have multiple "artificial" rays, you may just pick one from them for your applications.
Hope this helps.
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 (1)

Saad Humayun
Saad Humayun on 31 Mar 2024 at 8:20
Would you by any chance know how to access this part of raytrace(0 function in the newer versions of MATLAB? I know this is super late, but I would like to see the calculation of reception sphere and flagging logic similarly in the later versions too, as some of my rays in simulations are being missed and I want to be able to explain that phenomenon.
  3 Comments
Saad Humayun
Saad Humayun on 2 Apr 2024 at 14:13
I was just exploring comm.internal.raytrace in R2023b, as that is the one I was using earlier. From what you said, that is literally the best conclusion I came up with, because unfortunately I wasn't lucky enough to find any actual flagging or computation, just that C++ line instead which obviously I don't think users have access to.
Thanks a lot Laurent, super grateful for the comment!
Saad Humayun
Saad Humayun on 2 Apr 2024 at 14:31
Aside from this, would you think logically and theoretically MATLAB would keep the calculations similar even for the later versions when it comes to reception mechanisms of rays and receiver sites? Even though the exact lines of code aren't visible in these versions.

Sign in to comment.

Categories

Find more on Propagation and Channel Models in Help Center and File Exchange

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!