I am doing a random walk particle tracking simulation. In my problem, I have to implement a reflected boundary on the cylinder. In this code, the check implies that if particles enter into the cylinder, their previous position should not change. I mean, if a particle crosses the solid boundary, such a move is rejected, and the tracer stays at its previous position during the current iteration. For clarification, I have attached an image where you can see particle sitting in the circle.
However, particles still entering into the cylinder. Below is my code.
%% loop starts
for i = 1:T % T is the total computation time of simulation
t = i*dt; % dt is the time step
%% Particle tracking starts
x_ out = x_previous + u.dt + sqrt(2Ddt); % x_out--> current position
% x_previous--> previous position
% u -> x-velocity component
y_ out = y_previous + v.dt + sqrt(2Ddt); % y_out--> current position
% y_previous--> previous position
% v -> y-velocity component
%% Check whether particle is inside the cylinder obstacle
% x_c and y_c is the center location for cylinder (obstacle) in the flow
Incircle = sqrt((x_out - x_c).^2 + (y_out - y_c).^2);
Particle_enter = find (Incircle < D/2); % Particle entered in obstacle
% having diameter (D)
%% if particle cross cylinder boundary, do not update its position
if ismember(Particle_enter,1)
kk1 = find(ismember(isIncircle, 1) == 1);
x_out(kk1) = x_previous(kk1); % Do not update location
y_out(kk1) = y_previous(kk1);
end
x_previous = x_out;
y_previous = y_out;
end
Any modification/correction will be helpful
Thanks
Due to rounding error, when comparing float or double, use
a-b > tol % tol = some error tolerance, say, 1e-10
instead of
a > b
Also, sqrt can introduce some numerical error, comparing the squared distance is more accurate.
Try to change these lines in your code into
Incircle = (x_out - x_c).^2 + (y_out - y_c).^2;
Particle_enter = find (abs(Incircle - D^2/4) < tol);
If you randomly generate the initial positions of the particles, make sure they are not inside the obstacle in the first place.
Finally, if a particle hits a reflected boundary, shouldn't it be reflected, instead of returning to where it was?
Related
I deployed number of random points with their speed and displacement, how can I make these point move frequently each second,
since the Euclidean distance between these points is updated each time interval (second) based on the coordinates of new positions?
NumNode=2;
ro=1000;
center=[0 0];
Initial_Direction = rand(NumNode, 1) * 2 *pi; v = 15/3.6; % [m/s] velocity of node
theta_Node=2*pi*(rand(NumNode,1));
% let the Nodes deployed away from the center of circle network layout
g = 0.5 * ro + 0.5 * ro * rand(NumNode,1);
PosNode_x=center(1)+g.*cos(theta_Node); % Initial positions
PosNode_y=center(2)+g.*sin(theta_Node);
PosNode = [PosNode_x ,PosNode_y];
DX2 = [cos(Initial_Direction(:)) .* v,sin(Initial_Direction(:)) .* v]; % displacement of Node
PosNodeNew = PosNode + DX2; % New position of node without rotating
rotaion2 = [cosd(Initial_Direction), -sind(Initial_Direction); sind(Initial_Direction), cosd(Initial_Direction)]; % Rotation matrix to make the movement of node similar to move on arc
% Index approach to multiply different matrix dimensions
index=1:numel(PosNode);
xyRotated1 = rotaion2;
xyRotated1(index)= rotaion2(index).*PosNode(index); % rotated matrix multiply by position of node
index2 = 1:numel(DX2);
Newposss=xyRotated1;
NewPosss(index2) = xyRotated1(index2) + DX2(index2);
gg= NewPosss(index2); % New position of node with rotating on arc
figure(1)
scatter(PosDrone_x,PosDrone_x,'r+')
figure(2)
scatter(PosDroneNew(:,1),PosDroneNew(:,2),'b*')
figure (3)
scatter (xyRotated1(:,1),xyRotated1(:,2),'r.')
axis equal
figure (4)
scatter(NewPosss(1,:),NewPosss(1,:),'b*')
axis equal
I want to write a code where an arc stops rotating as soon as it comes in contact with a semi-circle.
I have written a code to do so, my arc does not just touch the circle but it slightly intersects it.
I have put rotation of arc inside a while loop by using linspace() to change theta. I used polyxpoly() for finding intersection. Condition for the while loop is that as long as I have empty array the loop continues, but as soon as I get a value from polyxpoly() my loop stops.
However, at the place of touch the theta value exceeds what I needed, so as a result I get an intersection.
How do I modify the code so that the arc will touch the semi-circle and not intersect it?
Here is the output. Click the link below
Image of intersection but I need touch and not intersection
clc,clear
R = 5; % radius of a circle
r = 10; % radius of arc
aa = 60*pi/180; % arc angle
ap = 0*pi/180; % arc position angle
% defining the semi-circle about the origin
t = linspace(0,pi);
[x,y] = pol2cart(t,R); % circle data
% Shifting circle centre to (3.5,0)
x=x+3.5;
y=y+0;
% defining the arc about the origin
t1 = linspace(0,aa)-aa/2+ap;
[x1,y1] = pol2cart(t1,r); % arc data
% shifting arc-lower-end to (14,0)
delx=14-x1(1); % Finding the x difference between arc-lower-end x-coordinate & 14
dely=0-y1(1); % Finding the y difference between arc-lower-end y-coordinate & 0
x1=x1+delx;
y1=y1+dely;
theta =linspace(0,pi,1000);
i=1;
xc=[];
yc=[];
while isempty(xc)&& isempty(yc)
% create a matrix of these points, which will be useful in future calculations
v = [x1;y1];
% choose a point which will be the center of rotation
x_center = 14;
y_center = 0;
% create a matrix which will be used later in calculations
center = repmat([x_center; y_center], 1, length(x1));
% define a 60 degree counter-clockwise rotation matrix
R = [cos(theta(i)) -sin(theta(i)); sin(theta(i)) cos(theta(i))];
% do the rotation...
s = v - center; % shift points in the plane so that the center of rotation is at the origin
so = R*s; % apply the rotation about the origin
vo = so + center; % shift again so the origin goes back to the desired center of rotation
% this can be done in one line as:
% vo = R*(v - center) + center
% pick out the vectors of rotated x- and y-data
x_rotated = vo(1,:);
y_rotated = vo(2,:);
[xc,yc] = polyxpoly(x_rotated,y_rotated,x,y)
[xc1,yc1] = polyxpoly(x1,y1,x,y)
i=i+1;
end
% make a plot
plot(x,y)
hold on
plot(x1, y1, 'k-', x_rotated, y_rotated, 'r-', x_center, y_center, 'bo');
axis equal
I need to find way it contacts a circle and does not intersect it.
The code is in matlab.
Any suggestions are welcome.
This is the problem of collision detection. Most, if not all, methods I know of in collision detection requires the computer to check for intersections of some sort. It's very difficult (if not impossible) to have two objects "just touch" in simulations, because you'll need the precise (analytically solved) location of the boundaries of those objects.
polyxpoly() is a function to return the intersection of two polygons. So unfortunately, if you insist that the arc cannot touch, then you cannot use polyxpoly(). In that extreme case, you'll have to solve some mathematical equation for when the tip of the arc coincides with a point on the circle perfectly, then simulate up until that point in time.
But realistically, what you need is a finer simulation (although I personally think what you have alone is good enough). So in every simulation step, you calculate a smaller movement, so that when the arc eventually intersects, only a very small amount of the arc intersects.
I know it's not the best wording but I really need some help here..
I have a PingPong game that I want to make automated. I want to try make the paddle's centre coordinate ((Py1 + Py2) / 2) {Top Y + Bottom Y / 2} equal to the ball's centre coordinate ((By1 + By2) / 2){Same as paddle}.
I want to know if there's a way to constantly change the paddle coordinates to adjust to the ball's coordinates. The whole program uses 'Thrusters' as direction and speed.
Thruster(2) = Fast
Thruster(1) = Slows down, and eventually changes direction
Thruster(0) = Keeps momentum
Thruster(-1) = Changes direction.
http://www.mathworks.com/matlabcentral/fileexchange/45619-pingpong-game
Pretty sure this is the original file..
I'm new to the whole coding thing, in case that wasn't obvious..
Thanks
The code:
function GAME_PINGPONG
% PingPong game
% Every time the player gets 2 correct deflections the speed of play
% increases.
% [x,y] = Get_Ball_Coordinates()
% This function returns the x and y coordinates of the ball
% [y,V] = Get_Paddle_Info()
% This will return the y coordinates of the paddle (y) and its speed (V)
% Thruster()
% This controls the speed of the paddle.
% Thruster(2) increases the speed of the paddle in the up
% direction/decreases in down
% Thruster(1) decreases the speed of the paddle in the up direction/
% increases in down
% Thruster(0) maintains the speed of the paddle
% Thruster(-1) reverses the direction of the paddle (maintains speed)
%% Set up simulation
global Game_Over Mode h
close all;clc;
SET_UP_SIM; % Set up the simulation and associated timers etc.
Game_Over =0; % When this changes to 1 the game is over!!!
%% Mode of operation
% Auto mode: write a script to control the bat
% Manual mode: use uparrow and downarrow to control the bat
Mode = 0; % Mode= 1 is AUTO, Mode=0 is MANUAL
%% Auto mode: Control algorithm
while(Mode==1) % While auto mode is selected the following actions will be carried out
[Bx,By] = Get_Ball_Coordinates(); % Use function Get_Ball_Coordinates() to return x and y values of the ball
[Py,PV] = Get_Paddle_Info(); % Use function Get_Paddle_Info() to return the y coordinates of the paddle and it's speed.
if Game_Over==1 % Suggest a logic test to break out of continuous auto mode when the game is over!
break
end
end
I'm attempting to animate a rotating sphere in Matlab, however the lighting on the sphere rotates with it. I instead want the sphere to rotate while the lighting remains fixed with the coordinate system. Here's a gif of what my code is currently producing: Animation. And here is my code:
% Simulation Time
dt = 0.05;
time = 0:dt:5;
% Prep Figure
figure('Color',[1 1 1],'Renderer','zbuffer','ColorMap', [1,0,0; 0,0,1])
% Generate Sphere
[X,Y,Z] = sphere(20);
r = 0.75*25.4;
h = surf(r*X,r*Y,r*Z,Z,'FaceColor','interp');
hold on
% Adjust Axes, Lighting, and Shading
axis equal
view([40 25]);
light('Position',[1 1 1])
set(findobj(gca,'type','surface'),...
'FaceLighting','phong',...
'AmbientStrength',.3,'DiffuseStrength',.8,...
'SpecularStrength',.9,'SpecularExponent',25,...
'BackFaceLighting','unlit','EdgeColor','k')
filename = 'Rotation.gif';
for n = 1:36
rotate(h,[0 0 1],10,[0 0 0])
im = frame2im(getframe(1));
[imind,cm] = rgb2ind(im,256);
if n == 1;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',dt);
else
imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',dt);
end
end
As already mentioned in the comments:
Seems like it might be an issue with the surface VertexNormals not
updating.
The solution was to download the rotate.m function fixed File Exchange submission.
The description:
Bug evidence:
[x,y,z] = sphere(20);
hs=surf(x,y,z,'facecolor','y');
view(2)
axis equal
hl=light;
lightangle(hl,0,0)
% light is on -Y axis, thus at the
% bottom
rotate(hs,[0 0 1],30)
% rotate sphere to the right from 30°
It looks like the light has moved. This is due to a bug in rotate.m
function. The "VertexNormals" property of the surf object is not
updated as "xdata", "ydata" and "zdata" properties are.
This is fixed in the submitted version of rotate.m.
I have data that records the x and y positions of an animal in a 2D assay over time stored in a matlab matrix. I can plot these co-ordinates over time, and extract the velocity information and plot this using cline.
The problem I am having at the moment is calculating the heading angle. It should be a trivial trigonometry question, but I am drawing a blank on the best way to start.
The data is stored in a matrix xy representing x and y co-ordinates:
796.995391705069 151.755760368664
794.490825688073 150.036697247706
788.098591549296 145.854460093897
786.617021276596 144.327659574468
781.125000000000 140.093750000000
779.297872340426 138.072340425532
775.294642857143 133.879464285714
What I would like to be able to do is know the angle of the line drawn from (796.995, 151.755) to (794.490, 150.036), and so on. My research suggests atan2 will be the appropriate function, but I am unsure how to call it correctly to give useful information.
difx = xy(1,1) - xy(2,1);
dify = xy(1,2) - xy(2,2);
angle = atan2(dify,difx);
angle = angle*180/pi % convert to degrees
The result is 34.4646. Is this correct?
If it is correct, how do I get the value to be in the range 0-360?
You can use the diff function to get all the differences at once:
dxy = diff(xy); % will contain [xy(2,1)-xy(1,1) xy(2,2)-xy(1,2); ...
Then you compute the angle using the atan2 function:
a = atan2(dxy(:,2), dxy(:,1));
You convert to degrees with
aDeg = 180 * a / pi;
And finally take the angle modulo 360 to get it between 0 and 360:
aDeg = mod(aDeg, 360);
So - you pretty much got it right, yes. Except that you have calculated the heading from point 2 to point 1, and I suspect you want to start at 1 and move towards 2. That would give you a negative number - or modulo 360, an angle of about 325 degrees.
Also, using the diff function gets you the entire array of headings all at once which is a slight improvement over your code.
[rc mi]=
EDIT the problem of "phase wrapping" - when the heading goes from 359 to 0 - is quite a common problem. If you are interested in knowing when a large change happens, you can try the following trick (using aDeg from above - angle in degrees).
dDeg1 = diff(aDeg); % the change in angle
dDeg2 = diff(mod(aDeg + 90, 360)); % we moved the phase wrap point by 180 degrees
dDeg12 = [dDeg1(:) dDeg2(:)]';
[rc mi]= min(abs(dDeg12));
indx = sub2ind(size(dDeg12), mi, 1:size(dDeg12, 2));
result = dDeg12(ii);
What I did there: one of the variables (dDeg or dDeg2) does not see the phase wrap, and the min function finds out which one (it will have a smaller absolute difference). The sub2ind looks up that number (it is either positive or negative - but it's the smaller one of the two), and that is the value that ends up in result.
You can verify the angle by plotting a little line that starts at the first point and end in the direction of the heading. If the angle is correct, it will point in the direction of the next point in xy. Everything depends on where yo define 0 degrees at (straight up, say) from and whether positive degrees is rotation counterclockwise (I do) or clockwise. In MATLAB you can get the numbers between 0 and 360 but using modulo---or you can just add 180 to your results but this will change the definition of where the 0 degree mark is.
I made the following script that is a bit complex but shows how to calculate the heading/angle for all points in vector format and then displays them.
xy =[ 796.995391705069 151.755760368664
794.490825688073 150.036697247706
788.098591549296 145.854460093897
786.617021276596 144.327659574468
781.125000000000 140.093750000000
779.297872340426 138.072340425532
775.294642857143 133.879464285714];
% t = linspace(0,3/2*pi, 14)';
% xy = [sin(t), cos(t)];
% calculate the angle:
myDiff = diff(xy);
myAngle = mod(atan2(myDiff(:,1), myDiff(:,2))*180/pi, 360);
% Plot the original Data:
figure(1);
clf;
subplot(1,3,1);
plot(xy(:,1), xy(:,2), '-bx', 'markersize', 12);
hold all
axis equal;grid on;
title('Original Data');
% Plot the calculated angle:
subplot(1,3,2);
plot(myAngle);
axis tight; grid on;
title('Heading');
% Now plot the result with little lines pointing int he heading:
subplot(1,3,3);
plot(xy(:,1), xy(:,2), '-bx', 'markersize', 12);
hold all
% Just for visualization:
vectorLength = max(.8, norm(xy(1,:)- xy(2,:)));
for ind = 1:length(xy)-1
startPoint = xy(ind,:)';
endPoint = startPoint + vectorLength*[sind(myAngle(ind)); cosd(myAngle(ind))];
myLine = [startPoint, endPoint];
plot(myLine(1,:), myLine(2, :), ':r ', 'linewidth', 2)
end
axis equal;grid on;
title('Original Data with Heading Drawn On');
For example, if you use my test data
t = linspace(0,3/2*pi, 14)';
xy = [sin(t), cos(t)];
You get the following:
and if you do yours you get
Note how the little red line starts at the original data point and moves in the direction of the next point---just like the original blue line connecting the points.
Also note that the use of diff in the code to difference all the points properly at once. This is faster and avoids any problems with the direction--looks like in your case it's swapped.