My loop does not produce the results I want, due to coding errors

I have this code I am developing a random walks model for a mammal and analysing a receive level heard from this mammal, however when producing the loop code for several positions it does not show exactly what I need, as the for loop in my eyes is not completing.
A quick run throught the code:
clc;
clear;
x0 = 0;
y0 = 0;
Sr = [x0 y0]; %Source coordinates
a = 0.25; %Attenuation - FIND SOME VALUES
IL = 180; %Impact Level
v = 2; %Speed
t = 5; %seconds
T = 5400; %Total Time
s = v*t; %metres
iter = T/t; %number of positions
Tv = 0:t:(T-t);
SL = 212 + 10*log10(10);
X = zeros(iter,1);
Y = zeros(iter,1);
RL = zeros(iter,1);
Pre set parameters, although the X, Y and RL may be wrong, here I am trying to store values in these matrices to be used later in graphs and figures.
% starting condition - random position start
Z = [randi([-10 10]) randi([-10 10])];
d = sqrt((Z(1)-x0)^2+(Z(2)-y0)^2); % Pythagoras Theorem for distance between the Source and initial Reciever points
A random coordinate is generated for the first initial position and the distance between this position/ coordinate from the source (0,0).
%Random Walks Loop Code
for i = 1:iter
if i == 1
F = [randi([0 360])];
x = Z(1) + s*cos(F);
y = Z(2) + s*sin(F);
end
%Update for distance
s1 = sqrt((x-x0)^2+(y-y0)^2); % Pythagoras Theorem for distance between the 2 (Source and Reciever) point
TL = 20*log10(s1); %Transmission Loss
RL(i,:) = SL - TL; % Receive Level
% save result
X(i,:) = x(:,1);
Y(i,:) = y(:,2);
end
This is my loop, the F is a random number between 0 and 360 corresponding a degree to be used for a new position and coordinates the mammal will move towards to be used in the loop to calculate values for RL. I need this for every position / iter howver my code does not do this. The functions labelled x and y are the new positions and coordinates, but now going through it i see an error. The values for Z(1) and Z(2) need to change for each loop to be the previous x and y coordinates, rather than the initial random coordinates.
s1 shows the new distance between the coordinates, however I have just noticed the value for d earlier, also needs to be used here for the RL of the intial coordinates, so that itself has its own RL and TL, and then all the new coordinates within the loop has its own, all to be stored in a iter x 1 matrix, i.e., for each positional coordinates.
The save results shows all the results as a matrix to be used in figures and models. Also how do i sotre all the values from the function TL and s1 also.
figure
plot(x,y, '-*')
title('Random Walks')
xlabel('Distance from the Source (m)')
ylabel('Distance from the Source (m)')
ax = gca; %the change of the axes location to origin
ax.XAxisLocation = 'origin';
ax.YAxisLocation = 'origin';
A graph for the results which should showcase a random walks of a mammal moving based in different degree directions

 Accepted Answer

I have made numerous corrections in your code. I think this is now at least closer to what you want
clc;
clear;
x0 = 0;
y0 = 0;
Sr = [x0 y0]; %Source coordinates
a = 0.25; %Attenuation - FIND SOME VALUES
IL = 180; %Impact Level
v = 2; %Speed
t = 5; %seconds
T = 5400; %Total Time
s = v*t; %metres
iter = T/t; %number of positions
Tv = 0:t:(T-t);
SL = 212 + 10*log10(10);
X = zeros(iter,1);
Y = zeros(iter,1);
RL = zeros(iter,1);
% starting condition - random position start
Z = [randi([-10 10]) randi([-10 10])];
d = sqrt((Z(1)-x0)^2+(Z(2)-y0)^2); % Pythagoras Theorem for distance between the Source and initial Reciever points
%Random Walks Loop Code
for i = 1:iter
% % % if i == 1
F = [randi([0 360])];
x = Z(1) + s*cosd(F); % use cosd for angle in degrees
y = Z(2) + s*sind(F); % use sind for angle in degrees
Z = [x y]; % update current location
% % % end
%Update for distance
s1 = sqrt((x-x0)^2+(y-y0)^2); % Pythagoras Theorem for distance between the 2 (Source and Reciever) point
TL = 20*log10(s1); %Transmission Loss
% % % RL(i,:) = SL - TL; % Receive Level
RL(i) = SL - TL; % Receive Level
% save result
% % % X(i,:) = x(:,1);
% % % Y(i,:) = y(:,2);
X(i) = x;
Y(i) = y;
end
figure
% % % plot(x,y, '-*')
plot(X,Y, '-*')
title('Random Walks')
xlabel('Distance from the Source (m)')
ylabel('Distance from the Source (m)')
ax = gca; %the change of the axes location to origin
ax.XAxisLocation = 'origin';
ax.YAxisLocation = 'origin';

16 Comments

this is perfect, thank you. It seems i over complicated it including an if loop within the for loop and the update of the coordinates makes sense.
You can actually do it without any loops as follows
x0 = 0;
y0 = 0;
Sr = [x0 y0]; %Source coordinates
a = 0.25; %Attenuation - FIND SOME VALUES
IL = 180; %Impact Level
v = 2; %Speed
t = 5; %seconds
T = 5400; %Total Time
s = v*t; %metres
iter = T/t; %number of positions
Tv = 0:t:(T-t);
SL = 212 + 10*log10(10);
% starting condition - random position start
Z0 = [randi([-10 10]) randi([-10 10])];
% random incremental moves
F = randi([0,360],[iter,1]);
deltaZ = s*[cosd(F) sind(F)];
% sum up the moves to create overall walk
Z = cumsum(deltaZ,1);
% calculate position relative to receiver
Zr = Z - Sr;
% calcuate distance to receiver
d = sqrt(Z(:,1).^2 +Z(:,2).^2);
% transmission loss
TL = 20*log10(d);
% receive level
RL = SL - TL;
figure
plot(Z(:,1),Z(:,2), '-*')
title('Random Walks')
xlabel('Distance from the Source (m)')
ylabel('Distance from the Source (m)')
ax = gca; %the change of the axes location to origin
ax.XAxisLocation = 'origin';
ax.YAxisLocation = 'origin';
figure
plot(RL)
title('Receive Level');
xlabel('step number')
ylabel('Level db')
You may also want to consider whether you really want to only have the animal move along whole number (integer degree headings) as you have with your line of code
F = [randi([0 360])];
instead you could move along a value which could take on any real value (uniformly distributed) between 0 and 360 using
F = 360*rand;
or in my vectorized (no loop) solution
F = 360*rand(iter,1)
I appreciate the alternate approach in this, allows for coding comparison and learn further when i do this again. I was thinking about the real value approach and was going to look into this, but you have provided a solution here so thank you. I will definitely use this so thanks again
I have another query, lets say i want the animal to move in a biased approach, i.e. to move away from the sound source (origin) on a random biased path for some time until a moment has been reached. So when RL > IL it moves in this random biased path away from the source until RL < IL and then moves randomly as achieved until RL > IL again and so on until the end. This random bias approach i had the idea of using degrees again but a range of degrees that ensure the animal moves away. so lets say the animal is at the coordinates (0,5) it would move upwards i.e. the range of angles would be of 0 - 180 degrees.
I hope this makes sense
I'm sure there are many ways of modeling the fleeing behavior. I'm sorry, but at the moment I don't have time to think about the actual modelling approach. If you come up with a mathematical representation of how you want to model the fleeing behavior and need help figuring out how to implement it in MATLAB I (or others) could probably help you with that part.
Absolutely no worries, I still have time to configure the model and I may just perfectly execute how I would like it, if not I will mesasge back on this thread. Thanks for the help
back to the original code, i have just noticed the code below for the random initial coordinate is not included in the results, but only used to begin the model. is there a way it can be included, as well as its own RL based on its transmission loss?
% starting condition - random position start
Z = [randi([-10 10]) randi([-10 10])];
d = sqrt((Z(1)-x0)^2+(Z(2)-y0)^2); % Pythagoras Theorem for distance between the Source and initial Reciever points
You could reorganize your code like this
x0 = 0;
y0 = 0;
Sr = [x0 y0]; %Source coordinates
a = 0.25; %Attenuation - FIND SOME VALUES
IL = 180; %Impact Level
v = 2; %Speed
t = 5; %seconds
T = 5400; %Total Time
s = v*t; %metres
iter = T/t; %number of positions
Tv = 0:t:(T-t);
SL = 212 + 10*log10(10);
X = zeros(iter,1);
Y = zeros(iter,1);
RL = zeros(iter,1);
% starting condition - random position start
Z = [randi([-10 10]) randi([-10 10])];
d = sqrt((Z(1)-x0)^2+(Z(2)-y0)^2); % Pythagoras Theorem for distance between the Source and initial Reciever points
%Random Walks Loop Code
for i = 1:iter
% assign position coordinates
x = Z(1);
y = Z(2);
% save current position
X(i) = x;
Y(i) = y;
%Update for distance
s1 = sqrt((x-x0)^2+(y-y0)^2); % Pythagoras Theorem for distance between the 2 (Source and Reciever) point
TL = 20*log10(s1); %Transmission Loss
RL(i) = SL - TL; % Receive Level
% calculate new position
F = [randi([0 360])];
x = Z(1) + s*cosd(F); % use cosd for angle in degrees
y = Z(2) + s*sind(F); % use sind for angle in degrees
Z = [x y]; % update current location
end
figure
% % % plot(x,y, '-*')
plot(X,Y, '-*')
title('Random Walks')
xlabel('Distance from the Source (m)')
ylabel('Distance from the Source (m)')
ax = gca; %the change of the axes location to origin
ax.XAxisLocation = 'origin';
ax.YAxisLocation = 'origin';
You could also do something similar with the vectorized (no loop) version.
I have managed to code that problem i had earlier to encorporate a flee response based on RL > IL, however i just wanted to double check it. The code to me looks correct however the results for RL does not suggest this as the RL rarely goes below the IL value.
clc;
clear;
x0 = 0;
y0 = 0;
Sr = [x0 y0]; %Source coordinates
a = 0.25; %Attenuation - FIND SOME VALUES
IL = 180; %Impact Level
v = 2; %Speed
t = 5; %seconds
T = 5400; %Total Time
s = v*t; %metres
iter = T/t; %number of positions
TV = 0:t:(T-t);
SL = 212 + 10*log10(10);
X = zeros(iter,1);
Y = zeros(iter,1);
RL = zeros(iter,1);
% starting condition - random position start
Z = [randi([-10 10]) randi([-10 10])];
d = sqrt((Z(1)-x0)^2+(Z(2)-y0)^2); % Pythagoras Theorem for distance between the Source and initial Reciever points
for i = 1:iter
% assign position coordinates
x = Z(1);
y = Z(2);
% save current position
X(i) = x;
Y(i) = y;
%Prpoagation Loss
s1 = sqrt((x-x0)^2+(y-y0)^2); % Pythagoras Theorem for distance between the 2 (Source and Reciever) point
theta = atand(y/x);
TL = 20*log10(s1); %Transmission Loss
RL(i) = SL - TL; % Receive Level
RL(i) = RL(i) + 10.*log10(t); %encorporate the energy exposure at the position for t(s), (assumption)
if RL > IL
%Update for position based on random biased flee direction
alpha = (-90-90) * rand + 90;
x = Z(1) + s*cosd(theta + alpha); % use cosd for angle in degrees
y = Z(2) + s*sind(theta + alpha); % use sind for angle in degrees
Z = [x y]; % update current location
else
%Update for position based on random direction
alpha = 360*rand;
x = Z(1) + s*cosd(theta + alpha); % use cosd for angle in degrees
y = Z(2) + s*sind(theta + alpha); % use sind for angle in degrees
Z = [x y]; % update current location
end
% save result
X(i) = x;
Y(i) = y;
end
Rlin = 10.^(RL./20); %Receive Linear
RlinS = cumsum(Rlin);
RLS = 20.*log10(RlinS);
CEE = RLS(end); %Cumalative Energy Exposure
%RANDOM WALKS MODEL
figure
plot(X,Y)
title('Random Walks')
xlabel('Distance from the Source (m)')
ylabel('Distance from the Source (m)')
ax = gca; %the change of the axes location to origin
ax.XAxisLocation = 'origin';
ax.YAxisLocation = 'origin';
I haven't had a chance to look into your code in detail, but one quick thing to look at is your use of atand to get the direction to the source (and then I guess to determine the fleeing dirction, 180 degrees away). The function atand only returns answers in the range -90 to 90. I would suggest instead to use atan2d, which gives results in all 4 quadrants.
oh yes of course, i had not even realised i was not working within the 4 quadrants but only 3. thank you for this spot. i am still trying to analyse my code and to see where it may have gone wrong. if i spot it before, i will add the code
You also have an error on your if statement, you should compare the current value of RL, that is RL(i) to IL not the entire vector, so you should use
if RL(i) > IL
when you compare the whole vector of RL to IL the if statement will only be evaluated as true if every element of RL is greater than IL, of course this won't be the case until possibly the very last step because otherwise most of the elements of RL will be zero
ahhh yes, now this is where i went wrong, the graph now looks more to like what i wanted. thank you

Sign in to comment.

More Answers (0)

Asked:

on 3 Aug 2022

Commented:

on 5 Aug 2022

Community Treasure Hunt

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

Start Hunting!