I am creating random starting and ending points. I want to plot those who cross/intersect with a rectangular which is placed at the origin. I found out that my code misses some lines, as shown in the figure. After that, I want to count were the tracks hit the rectangle. For expample the track came from top side and exited from right side etc.
My code is
function [hot, cold, h] = MuonTracks(tracks)%#eml
% NOTE: no variables larger than 1x1 are initialized
width = 1e-4;
height = 2e-4;
% constant used for Laplacian noise distribution
bL = 15 / sqrt(2);
% Loop through all tracks
X = [];
bhit= [];
hot = 0;
ii = 0;
TopBottom= 0;
LeftRight= 0;
TopRight= 0;
TopLeft= 0;
LeftBottom= 0;
RightBottom= 0;
ihit= 0;
while ii <= tracks
ii = ii + 1;
% Note that I've inlined (== copy-pasted) the original laprnd()
% function call. This was necessary to work around limitations
% in loops in Matlab, and prevent the nececessity of those HUGE
% variables.
%
% Of course, you can still easily generalize all of this:
% the new data
u = rand-0.5;
Ystart = 15;
Xstart = 80*rand-40;
Xend = Xstart - bL*sign(u)*log(1-2*abs(u));
%Xend=laprnd(tracks,1,Xstart,15);
b = (Ystart*Xend)/(Xend-Xstart);
% the test
if ((b < height && b > 0)) ||...
(Xend < width/2 && Xend > -width/2)
hot = hot+1;
% growing an array is perfectly fine when the chances of it
% happening are so slim
X = [X [Xstart; Xend]]; %#ok
bhit=b;
end
end
% This is trivial to do here, and prevents an 'else'
cold = tracks - hot;
% Now plot the chosen ones
h = figure;
hold all
%Y = bsxfun(#times, 15, ones(size(X)));
if (size(X)==0)
%Disp('No hits were found');
msgbox('No tracks were found','Result','warn');
elseif (size(X)>1)
Y = bsxfun(#times, [15; 0], ones(size(X)));
plot(X, Y, 'r');
msgbox( [num2str(hot) ' tracks were found'],'Result','help',num2str(hot));
else
Y = bsxfun(#times, [15; 0], ones(size(X)));
plot(X, Y, 'r');
msgbox( [num2str(hot) ' track was found'],'Result','help',num2str(hot));
end
%X;
%Y;
%size(X,2)
while ihit<size(X,2)
ihit=ihit+1
%X(2,ihit)
if ((X(2,ihit)==-width && (bhit<=0 && bhit<=height))&&(bhit==0 && (X(2,ihit)>=-width && X(2,ihit)>=width)))
LeftBottom=LeftBottom+1;
elseif ((bhit==height && (X(2,ihit)>=-width && X(2,ihit)>=width)) && (X(2,ihit)==width && (bhit<=0 && bhit<=height)))
TopRight=TopRight+1;
elseif ((bhit==height && (X(2,ihit)>=-width && X(2,ihit)>=width)) && (bhit==0 && (X(2,ihit)>=-width && X(2,ihit)>=width)))
TopBottom=TopBottom+1;
elseif ((X(2,ihit)==-width && (bhit<=0 && bhit<=height)) && (X(2,ihit)==width && (bhit<=0 && bhit<=height)))
LeftRight=LeftRight+1;
elseif ((X(2,ihit)==-width && (bhit<=0 && bhit<=height)) && (bhit==height && (X(2,ihit)>=-width && X(2,ihit)>=width)))
TopLeft=TopLeft+1;
elseif ((X(2,ihit)==width && (bhit<=0 && bhit<=height)) && (bhit==0 && (X(2,ihit)>=-width && X(2,ihit)>=width)))
RightBottom=RightBottom+1;
else
display('sth is wrong');
end
X(2,ihit)
end
%X(1,:);
%Y(1,:);
LeftBottom
TopRight
TopBottom
LeftRight
TopLeft
RightBottom
%display('sdfghjk');
end
Any ideas would be more than welcome!
Here you have a function that is capable of intersecting whole groups of segments and returning the intersection points. I hope it helps.
Related
I'm trying to write a program that bounces a square around the environment.
It should be changing it's velocity when it collides with the 'walls' and the central square.
I am fairly sure I am close to getting it right but there seems to be a real issue with the collision detection which I can't figure out.
Would greatly appreciate anyone having a look and giving some pointers.
fps = 40;
dt = 1/fps;
tmax = 10;
t = 0;
theta = 0;
dtheta = 1/20;
p = transpose([20,20,1]);
v = transpose([50,25,1]);
Vobj = transpose([2, -2, 1; 2,2,1; -2, 2, 1; -2, -2, 1]);
Vobj2 = transpose([60,60,1; 60,40,1; 40, 40, 1; 40, 60, 1]);
while t < tmax
x = p + t*v;
if x(1)<= 5 || x(1) >= 95
v(1)=-v(1);
elseif x(2)<= 5 || x(2) >= 95
v(2)=-v(2);
elseif ((40<=x(1)) && (x(1)<= 60)) && ((x(2) == 40) || (x(2) == 60))
v(2)=-v(2);
elseif ((40<=x(2)) && (x(2)<= 60)) && ((x(1) == 40) || (x(1) == 60))
v(1)=-v(1);
end
p = x;
% Transformations
T = [1,0,p(1);0,1,p(2);0,0,1];
S = [1+0.2*sin(2*t),0,0; 0,1+0.2*sin(2*t),0;0,0,1];
R = [cos(theta),sin(theta),0 ;-sin(theta),cos(theta),0;0,0,1];
L = R*S*T;
% Application of Transformations
V = L*Vobj;
fill(V(1,:),V(2,:),'r')
hold on
fill(Vobj2(1,:),Vobj2(2,:),'g')
axis([0,100,0,100])
hold off
shg;
pause(0.1);
% Updates
t = t + dt;
theta = theta + dtheta;
end
There are a couple things not entirely correct.
Your numerical integration should multiply with dt instead of t, if you are using a forward Euler method.
You are now checking for collision at the center of the moving block, but perhaps you actually want to check for collision of the corners of the block. If that's the case, you could loop over the coordinates of the corner of the block, and check them individually with the working collision detection if statement. So instead of checking once, do the check four times for the corners. Or even multiple times, if add points by interpolating the edges of the block.
The transformation of the block is incorrect. The location of V is not centered about the position p. If you try to simplify the problem, and just take the center of the block, you will see that the collision detection is in fact working.
fps = 40;
dt = 1/fps;
tmax = 10;
t = 0;
theta = 0;
dtheta = 1/20;
p = transpose([20,20,1]);
v = transpose([50,25,1]);
Vobj2 = transpose([60,60,1; 60,40,1; 40, 40, 1; 40, 60, 1]);
while t < tmax
x = p + dt*v;
if x(1)<= 5 || x(1) >= 95
v(1)=-v(1);
elseif x(2)<= 5 || x(2) >= 95
v(2)=-v(2);
elseif ((40<=x(1)) && (x(1)<= 60)) && ((x(2) == 40) || (x(2) == 60))
v(2)=-v(2);
elseif ((40<=x(2)) && (x(2)<= 60)) && ((x(1) == 40) || (x(1) == 60))
v(1)=-v(1);
end
p = x;
% plot the center of the block
scatter(p(1),p(2))
% plot the obstacle
hold on
fill(Vobj2(1,:),Vobj2(2,:),'g')
axis([0,100,0,100])
hold off
shg;
pause(0.1);
% Updates
t = t + dt;
theta = theta + dtheta;
end
Try to fix your transformation, by just applying some angle and translation, to a point where you know where your corners should end up (for example 90 degree rotation, or translation of a known value). This way you can check if the transformation is correct. Then incorporate this again in the simulation.
I have tried to write a code, part of a bigger program, that would return value of z at every point of s. However, when I run the code I only get z=0, or if last else is ignored code returns zero vector.
Does someone have a clue where I made mistake? I have used method 1 from this source. Any help will be greatly appreciated, I have trying to get this work for months now.
% clc;close all; %// not generally appreciated
%initial values
b=1.25;
h=0.313;
%define the s coordinate
s= 0:0.001:2*(b+h);
%create zero matrix for speed
z=zeros(size(s));
%calculate z at every point of s coordinate
for i =length(s)
if 0 <= s(i) && s(i) <=b %0<=s<=b
z=0.5*h;
elseif b <= s(i) && s(i) <=(b+h) %b<=s<=(b+h)
z=0.5*h+((-0.5*h)/(b+h-b))*(s-b);
elseif b <= s(i) && s(i) <=(b+h) %(h+b)<=s<=(b+h)
z=-0.5*h;
elseif b <= s(i) && s(i) <=(b+h) %(h+2b)<=s<=(2b+2h)
z=-0.5*h+((-0.5*h)/(b+h-b))*(s-b);
else z=0;
end
end
For further reference, this solved my problem. Thank you #Dan!
%// initial values
b=1.25;
h=0.313;
%// define the s coordinate
s= 0:0.001:2*(b+h);
%// Create z
z = zeros(size(s));
idx1 = 0 <= s & s <=b;
idx2 = b <= s & s <=(b+h);
idx3 = (b+h) <= s & s <= (2*b+h);
idx4 = (2*b+h) <= s & s <=(2*b+2*h);
z(idx1) = 0.5*h;
z(idx2) = 0.5*h+((-0.5*h-0.5*h)/(b+h-b))*(s(idx2)-b);
z(idx3) = -0.5*h;
z(idx4) =-0.5*h+((0.5*h+0.5*h)/((2*b+2*h-b)-(h+b+b)))*(s(idx4)-b)
There are many issues with your code. You need to assign to an index of z otherwise you're just overwirting a scalar every time (i.e. z(i)=...). You need to loop over a vector so fori=1:length(s) and your last three loop conditions are identical!
%// initial values
b=1.25;
h=0.313;
%// define the s coordinate
s= 0:0.001:2*(b+h);
%// create zero matrix for speed
z=zeros(size(s));
%// calculate z at every point of s coordinate
for i = 1:length(s)
if 0 <= s(i) && s(i) <=b %// 0<=s<=b
z=0.5*h;
elseif b <= s(i) && s(i) <=(b+h) %// b<=s<=(b+h)
z(i)=0.5*h+((-0.5*h)/(b+h-b))*(s-b);
elseif (b+h) <= s(i) && s(i) <= (2*b+h) %// (h+b)<=s<=(2b+h)
z(i)=-0.5*h;
elseif (2*b+h) <= s(i) && s(i) <=(2*b+2*h) %// (h+2b)<=s<=(2b+2h)
z(i)=-0.5*h+((-0.5*h)/(b+h-b))*(s-b);
else z(i)=0;
end
end
With all the said, in MATLAB you don't even need a loop at all to do this and it is usually preferable not to use one:
%// initial values
b=1.25;
h=0.313;
%// define the s coordinate
s= 0:0.001:2*(b+h);
%// Create z
z = zeros(size(s));
idx1 = 0 <= s && s <=b;
idx2 = b <= s && s <=(b+h);
idx3 = (b+h) <= s && s <= (2*b+h);
idx4 = (2*b+h) <= s && s <=(2*b+2*h);
z(idx1) = 0.5*h;
z(idx2) = 0.5*h+((-0.5*h)/(b+h-b))*(s(idx2)-b);
z(idx3) = -0.5*h;
z(idx4) = -0.5*h+((-0.5*h)/(b+h-b))*(s(idx4)-b);
b=1.25;
h=0.313;
%define the s coordinate
s= 0:0.001:2*(b+h);
%create zero matrix for speed
z=zeros(size(s));
%calculate z at every point of s coordinate
for ii =1:length(s)
if 0 <= s(ii) && s(ii) <=b %0<=s<=b
z(ii)=0.5*h;
elseif b <= s(ii) && s(ii) <=(b+h) %b<=s<=(b+h)
z(ii)=0.5*h+((-0.5*h)/(b+h-b))*(s(ii)-b);
elseif b <= s(ii) && s(ii) <=(b+h) %(h+b)<=s<=(b+h)
z(ii)=-0.5*h;
elseif b <= s(ii) && s(ii) <=(b+h) %(h+2b)<=s<=(2b+2h)
z(ii)=-0.5*h+((-0.5*h)/(b+h-b))*(s(ii)-b);
else z(ii)=0;
end
end
Let your for loop run over more than 1 iteration, hence the for ii = 1:length(s).
Use allocation per element, thus z(ii) = some function
Don't use i as a variable.
The value for the columns is 51 and 50, but when we use anything more than that the waitbar freezes due to index out of bound exception since its a large image and it wont fit in there, so the matlab dosent shut using the waitbar or anything. Need a way to shut the matlab when it encounters any error.
h = waitbar(0,'Progress','Name','Calculating Feature Heights...',...
'CreateCancelBtn','setappdata(gcbf,''canceling'',1)');
setappdata(h,'canceling',0); %initiallizes waitbar
s1 = size(A);
s2 = size(B);
if (s1(1) < s2(1))
n = s1(1);
else
n = s2(1); % ensures that bounds of i are within the bounds of both images
end
for i = 21:1:n % sets bounds for rows
if getappdata(h,'canceling') %checks for user pushing the cancel button on the waitbar
break
end
waitbar(i/(n-1),h) %progress bar
for j = 61:1:(m-60) % sets bounds for columns
if A(i,j) == A(i,j-1) %if adjacent pixels are the same,
Z(i,j) = Z(i,j-1); %they have the same height
disp(i,j) = disp(i,j-l);
elseif A((i), j) == B(i, j) && A(i,j) ~= A(i,j-1) && A(i,j-1) == B(i,j-1)
Z(i,j) = Z0; %condiions for pixels/features in the 'focal plane'
disp(i,j) = 0;
else
for l = 1:1:20 %sets scan range in rows for disparity
for k = 1:1:60 %sets disparity scan range in cols
if (A(i,j) == B(i-l, j-k) && B(i-l, j-k-1) == B(i-l, j-k))
Z(i,j) = Z(i-l,(j-k-1)); %allows for multipixel features
disp(i,j) = disp(i-l,(j-k-1));
break
elseif (A(i, j) == B(i-l, j-k) && B(i-l, j-k-1) ~= B(i-l, j-k))
xA = [i j];
xB = [i-l j-k];
d = xB-xA;
Z(i,j) = Z0 - (fl*shift)/sqrt((d(1)^2)+(d(2)^2));
disp(i,j) = sqrt((d(1)^2)+(d(2)^2));
break
elseif (A(i,j) == B(i-l, j+k) && B(i-l, j+k-1) == B(i-l, j+k))
Z(i,j) = Z(i-l,(j+k-1));
disp(i,j) = disp(i-l,(j+k-1));
break
elseif (A(i, j) == B(i-l, j+k) && B(i-l, j+k-1) ~= B(i-l, j+k))
xA = [i j];
xB = [i-l j+k];
d = xB-xA;
Z(i,j) = Z0 - (fl*shift)/sqrt((d(1)^2)+(d(2)^2));
disp(i,j) = sqrt((d(1)^2)+(d(2)^2));
break
else
continue
end
end
end
end
end
end
delete(h)
Use a try/catch block.
try
% whatever that might error
catch
delete(h)
end
I am trying to implement a wireless sensor network simulator on matlab and I need your help.
This is exactly what I want to do:
Deploy nodes randomly in a 2D plane.
Model a group leader election algorithm using two conditions:
a) Energy: generate random energy values associated with each of the sensors, the sensor node with the maximum energy has higher probability of being selected as leader.
b) Proximity: the sensor node that is mostly surrounded by neighboring nodes has higher probability of being selected.
So, for a random node that has maximum energy and more neighbors can be selected as leader and plotted with the rest of the nodes in a different color.
I have been working on this, trying to develop my code all to no avail. I am not really good with matlab coding, I am still learning.
Please guys, I need any help I can get on this, my deadline is imminent.
Thanks,
Ike
First of all building a wireless networks simulator using matlab is by far not the best choice to do. its better to use specialized simulators such as NS2 or Omnet++. however, I have developed once a simple m-file code to randomly deploy points in a square are and try to link between these points according to the distance between these points. the points are assumed to be sensor nodes.
try to modify on it to get what you need. please vote up if this answer was useful to you:
W=0;X=0;Y=0;Z=0;
nodedistance = zeros();
maxx = 400; maxy=400; maxn = 50;
q = zeros(maxn);
e = rand(maxn,1)*100;
nodeloc = rand(maxn, 2)* maxx;
node(maxn) = struct('NodeNum',zeros(maxn),'nEnergy',zeros(maxn),'Loc',[zeros(maxn,1), zeros(maxn,2)]);
rss(maxn,maxn) = struct('NodeNumber',zeros(maxn),'NodeDistance',zeros(maxn));
for a = 1:100,
m = 2;
node = struct();
rss = struct();
nodedistance = zeros();
maxx = 400; maxy=400; maxn = 50;
q = zeros(maxn);
e = rand(maxn,1)*100;
nodeloc = rand(maxn, 2)* maxx;
for i = 1: maxn,
node(i)=struct('NodeNum',i,'nEnergy',e(i),'Loc',[nodeloc(i, 1), nodeloc(i, 2)]);
end
for i = 1:maxn,
for j = 1:maxn,
rss(i,j) = struct('NodeNumber',i,'NodeDistance',sqrt((node(i).Loc(1)- node(j).Loc(1))^2+(node(i).Loc(2)-node(j).Loc(2))^2));
end
end
for i = 1:maxn,
for j = 1:maxn,
nodedistance(i,j)=rss(i,j).NodeDistance;
end
end
for i = 1:maxn,
for j = 1:maxn,
if (node(i).nEnergy > 0) && (node (j).nEnergy > 0) && (0 < nodedistance(i,j) && nodedistance(i,j) <= 30)
if (node(i).nEnergy < node (j).nEnergy) %|| ( (node(i).nEnergy == node (j).nEnergy )&& (0 < nodedistance(i,j) && nodedistance(i,j)) < 30) %|| (0 < nodedistance(i,j) && nodedistance(i,j) <= 30)
q(i,j) = 1;
elseif node(i).nEnergy == node (j).nEnergy && 0 < nodedistance(i,j) && nodedistance(i,j) < 30
q(i,j) = 1;
else if 0 < nodedistance(i,j) && nodedistance(i,j) <= 30
q(i,j) = 1;
else
q(i,j) = 0;
end
end
end
end
end
end
for i = 1:maxn,
for j = 1:maxn,
if q(i,j) == 1
q(j,i) = 1;
end
end
end
colordef white,
figure(1);
axis equal
for i = 1:maxn,
hold on
box on;
plot(nodeloc(i, 1), nodeloc(i, 2), 'k.', 'MarkerSize', 5);
lscatter(nodeloc(i, 1),nodeloc(i, 2),i);
grid on;
end
gplot(q,nodeloc,'r-');
c = q;
b = 0; zeros(maxn);
check = 1;
while (check)
for m = 2:30
p = size(b)
b = zeros(maxn,maxn);
for i = 1:maxn,
for j = 1:maxn,
if i ~= j
if c(i,j) == 0
for k = 1:maxn,
if c(i,k) >0 && q(k,j) >0
b(i,j) = m;
break
else b(i,j) = 0;
end
end
end
end
end
end
f = size(b)
c = c + b;
if b ==0
check = 0;
else b = 0;% while loop here the condition.
m = m + 1;
end
end
k = 0;
for i = 1:maxn,
for j = 1:maxn,
k = k + c(i,j);
end
end
average_hop = k/(maxn*(maxn-1));
o = 0;
for i = 1:maxn,
for j = 1:maxn,
if c(i,j) ~= 0
o = o + 1;
end
end
end
c(~c) = nan;
r=max(max(c));
t=min(min(c));
clear
end
formatSpec1 = 'The number of hops from node %d to node %d is %d \n';
formatSpec2 = 'The average number of hops is %.4f, the maximum hop-count is %d, the minimum hop-count is %d \n';
formatSpec3 = 'The number of created paths is %d \n';
fileID = fopen('Paths11.txt','w');
fprintf(fileID,formatSpec1,i,j,c(i,j));
fprintf(fileID,formatSpec2,average_hop,r,t);
fprintf(fileID,formatSpec3,o);
clear;
X = X+average_hop;
Y = Y+r;
z = Z+t;
W = W+o;
end;
formatSpec1 = 'The number of hops from node %d to node %d is %d \n';
formatSpec2 = 'The average number of hops is %.4f, the average maximum hop-count is %.2f, the minimum hop-count is %d \n';
formatSpec3 = 'The average number of created paths is %.2f \n';
fileID = fopen('Energy-50-AODV.txt','w');
fprintf(fileID,formatSpec1,i,j,c(i,j));
fprintf(fileID,formatSpec2,X/a,Y/a,t);
fprintf(fileID,formatSpec3,W/a);
clear;
This is not a get-your-homework-done-for-free site; you'll have to do most of the work yourself. Here are my tips:
Don't leave your assignments to the last minute.
Study the MATLAB code of other people working in your field, and refer to the MATLAB help files (hit F1) when you get stuck. Here's a fruitful search query to point you in the right direction: wsn OR "sensor network" clustering matlab code site:edu
I have implemented the Clarke-Wright huristic to solve TSP (based on the pseudo-code here). I have attached my implementation in Matlab. However it is not fast enough for me and takes O(n2) space (because of pairwise distances). I wonder if there is any theoretic or practical optimization I can apply to reduce the complexity (specially, space complexity).
It would be grateful if anyone can help me.
function [tour, length] = clarke_wright (data)
n=size(data,1); % number of records
center = mean(data,1); % mean of data
hubIdx = knnsearch(data,center,'k',1); % nearest record to center
distances = dist(data,data'); % this requires O(n^2) space :(
savings = zeros(n); % place to store the saving after adding an edge %
% Can be more vectorized? %
for i=1:n
if i==hubIdx
continue;
end
savings(i,(i+1):n)=distances(i,hubIdx)+distances(hubIdx,(i+1):n)-distances(i,(i+1):n);
end
minParent = 1:n;
[~,si] = sort(savings(:),'descend');
si=si(1:(end/2));
Vh = zeros(1,n);
Vh(hubIdx) = 1;
VhCount = n-1;
degrees = zeros(1,n);
selectedIdx = 1; % edge to try for insertion
tour = zeros(n,2);
curEdgeCount = 1;
while VhCount>2
i = mod(si(selectedIdx)-1,n)+1;
j = floor((si(selectedIdx)-1)/n)+1;
if Vh(i)==0 && Vh(j)==0 && (minParent(i)~=minParent(j)) && i~=j && i~=hubIdx && j~=hubIdx % always all degrees are <= 2, so it is not required to check them
% if (minParent(i)~=minParent(j)) && isempty(find(degrees>2, 1)) && i~=j && i~=hubIdx && j~=hubIdx && Vh(i)==0 && Vh(j)==0
degrees(i)=degrees(i)+1;
degrees(j)=degrees(j)+1;
tour(curEdgeCount,:) = [i,j];
if minParent(i)<minParent(j)
minParent(minParent==minParent(j))=minParent(i);
else
minParent(minParent==minParent(i))=minParent(j);
end
curEdgeCount = curEdgeCount + 1;
if degrees(i)==2
Vh(i) = 1;
VhCount = VhCount - 1;
end
if degrees(j)==2
Vh(j) = 1;
VhCount = VhCount - 1;
end
end
selectedIdx = selectedIdx + 1;
end
remain = find(Vh==0);
n1=remain(1);
n2=remain(2);
tour(curEdgeCount,:) = [hubIdx n1];
curEdgeCount = curEdgeCount + 1;
tour(curEdgeCount,:) = [hubIdx n2];
tour = stitchTour(tour);
tour=tour(:,1)';
length=distances(tour(end),tour(1));
for i=1:n-1 % how can I vectorize these lines?
length=length+distances(tour(i),tour(i+1));
end
end
function tour = stitchTour(t) % uniforms the tour [a b; b c; c d; d e;.... ]
n=size(t,1);
[~,nIdx] = sort(t(:,1));
t=t(nIdx,:);
tour(1,:) = t(1,:);
t(1,:) = -t(1,:);
lastNodeIdx = tour(1,2);
for i=2:n
nextEdgeIdx = find(t(:,1)==lastNodeIdx,1);
if ~isempty(nextEdgeIdx)
tour(i,:) = t(nextEdgeIdx,:);
t(nextEdgeIdx,:)=-t(nextEdgeIdx,:);
else
nextEdgeIdx = find(t(:,2)==lastNodeIdx,1);
tour(i,:) = t(nextEdgeIdx,[2 1]);
t(nextEdgeIdx,:)=-t(nextEdgeIdx,:);
end
lastNodeIdx = tour(i,2);
end
end
This is what you can do if space is an issue (will probably reduce calculation speed a bit).
I have not really looked into your code, but judging from the pseudo code this should do the trick:
For each pair or points, calculate the savings created by connecting them.
If this is better than the best savings found so far, update the best savings, and remember the two points.
After checking all pairs just implement the best savings.
This way you will barely require extra space at all.