找到你要的答案

Q:Random Direction in Matlab

Q:在MATLAB随机方向

I am programming in matlab. A point moves using random direction into a circle. When the point reaches the limit of the area, the point must change its angle between 0-180. I can find when the point reaches the limit. But I do not know how to change the angle and continue to the process because when I change angles the point appears at another coordinate (x, y) -- I do not want that. When the point reaches the limit at position (x, y), I want to change the angle and have the point continue from that (x, y).

Here's what I have so far:

function [ X ] = random_direction( )
    bs = rsmak('circle',500,[0 0]);
    fnplt(bs,'b'), axis square;
    hold on
    magnitud=0;
    x=0;
    y=0;

    base_station(1:10)=struct('id',0,'position_x',0, 'position_y',0);
    dis=rand()*500;
    angulo=2*pi*rand();
    base_station(1).position_x =dis*cos(angulo);
    base_station(1).position_y =dis*sin(angulo);
    bandera=0;

    for i=1:100

        magnitud = sqrt(base_station(1).position_x^2+base_station(1).position_y^2);
        angulo=atan(base_station(1).position_y/base_station(1).position_x);

        if magnitud >= 500
            if bandera==0
                angulo=2*pi*rand();
            end
            x=10 * cos(angulo);  
            y=10 * sin(angulo);

            base_station(1).position_x= base_station(1).position_x+x;
            base_station(1).position_y=base_station(1).position_y+y;                           
            bandera=1;
        end

        if magnitud <500 && bandera==0
            base_station(1).position_x= base_station(1).position_x+10;
            base_station(1).position_y=base_station(1).position_y+10;
        end

        bs = rsmak('circle',10,[base_station(1).position_x base_station(1).position_y ]);
        fnplt(bs,'g'), axis square;
    end
end 

我在MATLAB编程。一个点移动使用随机方向成一个圆圈。当到达该地区的限制,这一点必须在0-180角度的变化。我可以找到当点达到极限。但我不知道如何改变角度和继续的过程,因为当我改变角度的点出现在另一个坐标(x,y)-我不希望。当点达到极限的位置(x,y),我想改变的角度,并有点继续从(x,y)。

这就是我迄今所拥有的:

function [ X ] = random_direction( )
    bs = rsmak('circle',500,[0 0]);
    fnplt(bs,'b'), axis square;
    hold on
    magnitud=0;
    x=0;
    y=0;

    base_station(1:10)=struct('id',0,'position_x',0, 'position_y',0);
    dis=rand()*500;
    angulo=2*pi*rand();
    base_station(1).position_x =dis*cos(angulo);
    base_station(1).position_y =dis*sin(angulo);
    bandera=0;

    for i=1:100

        magnitud = sqrt(base_station(1).position_x^2+base_station(1).position_y^2);
        angulo=atan(base_station(1).position_y/base_station(1).position_x);

        if magnitud >= 500
            if bandera==0
                angulo=2*pi*rand();
            end
            x=10 * cos(angulo);  
            y=10 * sin(angulo);

            base_station(1).position_x= base_station(1).position_x+x;
            base_station(1).position_y=base_station(1).position_y+y;                           
            bandera=1;
        end

        if magnitud <500 && bandera==0
            base_station(1).position_x= base_station(1).position_x+10;
            base_station(1).position_y=base_station(1).position_y+10;
        end

        bs = rsmak('circle',10,[base_station(1).position_x base_station(1).position_y ]);
        fnplt(bs,'g'), axis square;
    end
end 
answer1: 回答1:

As pointed in some of the comments that have been provided, the two main problems are:

the way the new angle is computed

a bug in the "if" block "if magnitud <500 && bandera==0" in which "x" and "y" are not multiplied by, respectively cos(angulo) and sin(angulo)

A possible solution for the computation of the new angle is adding to "angulo":

pi (180°) just to reverse the trajectory

an random angle offset to differentiate the new trajectory from the previous one to avoid going up and down along the same line)

the angle offset is defined as the product of a fixed angle and a random number between "-0.5 and 0.5".

When the new angle is computed, a validity check is made in order to verify if the new trajectory will "exit" the circle. If so, the sign of the offset angle in changed.

The proposed solution has been implemented in the code that follows.

In the code, the original lines of code modified have been "commented" with "%%%"(three %).

Also, some redundant / uncecessary lines of code have been commented too.

Some features have been also added:

the trajectory markers can be either be plot "interactively" (at each iteratiion") or all together at the end of the functions.

Plotting the trajectory at the end of the script makes the script faster (of course), 30000 iterations are computed in about 1.5 seconds

the trajectoty points are stored in the "X" output varaible

the number of iteration is defined by a parameter

the comments in the script should clarify the modifications.

The script has been tested up to 30000 iterations.

function [ X ] = random_direction( )
% updated plot of the circle
%%%bs = rsmak('circle',500,[0 0]);
%%%fnplt(bs,'b'), axis square;
plot([cos([0:.01:2*pi])*500],[sin([0:.01:2*pi])*500],'b')
hold on
daspect([1 1 1])
set(gca,'xlim',[-600 600],'ylim',[-600 600])
grid on

magnitud=0;
x=0;
y=0;

% added interactive plot mode flag:
% interactive=1 plots a mark at each iteraton
% interactive=0 plots the whole trajectory at the end of the run
%               trajectory points are also stored in the X output
%               variable
interactive=0;
% added setting of the number of iterations
n_iterations=30000;
X=zeros(n_iterations,2);

% location from 2 to 10 are not used
base_station(1:10)=struct('id',0,'position_x',0, 'position_y',0);
dis=rand()*500;
angulo=2*pi*rand();
base_station(1).position_x =dis*cos(angulo);
base_station(1).position_y =dis*sin(angulo);
bandera=0;
% off_angle is used when the point has to invert its direction. its
% value is multiplied by (rand_numb -0.5). The desired effect is to
% avoid the point just comes back in the opposite direction
off_angle=120*pi/180;

for i=1:n_iterations

    magnitud = sqrt(base_station(1).position_x^2+base_station(1).position_y^2);
    % added reset of bandera if magnitud < 500
    if(magnitud < 500)
       bandera=0;
    end
    % angulo changes only when magnitud is >= 500, so it does not need
    % to be calculated at each iteration
    %%%angulo=atan(base_station(1).position_y/base_station(1).position_x);

    if magnitud >= 500
        if bandera==0
            % updated computation of the new angulo
            %%%angulo=2*pi*rand();
            n_rand=rand();
            rand_off_angle=off_angle*(n_rand - 0.5);
            % added check for new angle validity
            tmp_x=base_station(1).position_x + 10*3 * cos(angulo + pi + rand_off_angle);
            tmp_y=base_station(1).position_y + 10*3 * sin(angulo + pi + rand_off_angle);
            tmp_d=sqrt(tmp_x^2+tmp_y^2);
            if(tmp_d > 500)
               rand_off_angle= - rand_off_angle;
            end
            angulo=angulo + pi + rand_off_angle;
            % added check for new angle > 360°
            if(angulo > 2*pi)
               angulo=angulo-2*pi;
            end
        end
        x=10 * cos(angulo);  
        y=10 * sin(angulo);

        base_station(1).position_x= base_station(1).position_x+x;
        base_station(1).position_y=base_station(1).position_y+y;                           
        bandera=1;
    end

    if magnitud <500 && bandera==0
        % positions are respectively multiplied by cos(angulo) and
        % sin(angulo)
        %%%base_station(1).position_x= base_station(1).position_x+10;
        %%%base_station(1).position_y=base_station(1).position_y+10;
        base_station(1).position_x= base_station(1).position_x + 10 * cos(angulo);
        base_station(1).position_y=base_station(1).position_y + 10  * sin(angulo);
    end

    % not neede to re-plot the circle at each iteration
    %%%bs = rsmak('circle',10,[base_station(1).position_x base_station(1).position_y ]);
    %%%fnplt(bs,'g'), axis square;
    % check for interactive plot
    if(interactive)
       plot(base_station(1).position_x , base_station(1).position_y,'xr') 
       pause(0.001);
    end
    % added storing of trajectory points
    X(i,1)=base_station(1).position_x;
    X(i,2)=base_station(1).position_y;
    % added "pause" command just to slow down the plot
end
% added plot of trajectory if not interactive has not been selected
if(~interactive)
   plot(X(:,1),X(:,2),'r')
end
end

The following images show the results for: 300, 3000, 10000 and 30000 iterations.

Hope this helps.

正如提供的一些评论所指出的,两个主要问题是:

新角度的计算方法

错误的“如果”块“如果震级& lt;500 &;&;班德拉= = 0”中的“X”和“Y”不乘,分别COS(安古洛)和罪恶(安古洛)

一个可能的解决方案的计算新的角度是添加到“安古洛”:

圆周率(180°)正好扭转轨迹

an random angle offset to differentiate the new trajectory from the previous one to avoid going up and down along the same line)

角偏移被定义为“0.5和0.5”之间的固定角度和随机数的乘积。

当新的角度计算,有效性检查,以验证是否新的轨迹将“退出”圆。如果是这样,偏移角的符号在改变。

建议的解决方案已实施的代码如下。

在代码中,修改过的原始代码行被“注释”为“%”(三%)。

另外,一些代码冗余/支付额外线路已经评论过。

还增加了一些功能:

the trajectory markers can be either be plot "interactively" (at each iteratiion") or all together at the end of the functions.

在脚本的结尾绘制轨迹使脚本更快(当然),30000次迭代在大约1.5秒内计算

的trajectoty点存储在“X”输出变量

迭代次数由参数定义

脚本中的注释应澄清修改。

该脚本已测试多达30000次迭代。

function [ X ] = random_direction( )
% updated plot of the circle
%%%bs = rsmak('circle',500,[0 0]);
%%%fnplt(bs,'b'), axis square;
plot([cos([0:.01:2*pi])*500],[sin([0:.01:2*pi])*500],'b')
hold on
daspect([1 1 1])
set(gca,'xlim',[-600 600],'ylim',[-600 600])
grid on

magnitud=0;
x=0;
y=0;

% added interactive plot mode flag:
% interactive=1 plots a mark at each iteraton
% interactive=0 plots the whole trajectory at the end of the run
%               trajectory points are also stored in the X output
%               variable
interactive=0;
% added setting of the number of iterations
n_iterations=30000;
X=zeros(n_iterations,2);

% location from 2 to 10 are not used
base_station(1:10)=struct('id',0,'position_x',0, 'position_y',0);
dis=rand()*500;
angulo=2*pi*rand();
base_station(1).position_x =dis*cos(angulo);
base_station(1).position_y =dis*sin(angulo);
bandera=0;
% off_angle is used when the point has to invert its direction. its
% value is multiplied by (rand_numb -0.5). The desired effect is to
% avoid the point just comes back in the opposite direction
off_angle=120*pi/180;

for i=1:n_iterations

    magnitud = sqrt(base_station(1).position_x^2+base_station(1).position_y^2);
    % added reset of bandera if magnitud < 500
    if(magnitud < 500)
       bandera=0;
    end
    % angulo changes only when magnitud is >= 500, so it does not need
    % to be calculated at each iteration
    %%%angulo=atan(base_station(1).position_y/base_station(1).position_x);

    if magnitud >= 500
        if bandera==0
            % updated computation of the new angulo
            %%%angulo=2*pi*rand();
            n_rand=rand();
            rand_off_angle=off_angle*(n_rand - 0.5);
            % added check for new angle validity
            tmp_x=base_station(1).position_x + 10*3 * cos(angulo + pi + rand_off_angle);
            tmp_y=base_station(1).position_y + 10*3 * sin(angulo + pi + rand_off_angle);
            tmp_d=sqrt(tmp_x^2+tmp_y^2);
            if(tmp_d > 500)
               rand_off_angle= - rand_off_angle;
            end
            angulo=angulo + pi + rand_off_angle;
            % added check for new angle > 360°
            if(angulo > 2*pi)
               angulo=angulo-2*pi;
            end
        end
        x=10 * cos(angulo);  
        y=10 * sin(angulo);

        base_station(1).position_x= base_station(1).position_x+x;
        base_station(1).position_y=base_station(1).position_y+y;                           
        bandera=1;
    end

    if magnitud <500 && bandera==0
        % positions are respectively multiplied by cos(angulo) and
        % sin(angulo)
        %%%base_station(1).position_x= base_station(1).position_x+10;
        %%%base_station(1).position_y=base_station(1).position_y+10;
        base_station(1).position_x= base_station(1).position_x + 10 * cos(angulo);
        base_station(1).position_y=base_station(1).position_y + 10  * sin(angulo);
    end

    % not neede to re-plot the circle at each iteration
    %%%bs = rsmak('circle',10,[base_station(1).position_x base_station(1).position_y ]);
    %%%fnplt(bs,'g'), axis square;
    % check for interactive plot
    if(interactive)
       plot(base_station(1).position_x , base_station(1).position_y,'xr') 
       pause(0.001);
    end
    % added storing of trajectory points
    X(i,1)=base_station(1).position_x;
    X(i,2)=base_station(1).position_y;
    % added "pause" command just to slow down the plot
end
% added plot of trajectory if not interactive has not been selected
if(~interactive)
   plot(X(:,1),X(:,2),'r')
end
end

下面的图像显示的结果为:300,3000,10000和30000次迭代。

希望这有助于。

matlab