三维无人机航迹规划代码免费分享

最近开发了一个新的群智能优化算法,想看看在三维无人机航迹优化效果。自己不想花时间写,所以找了很多公众号和网络相关资料,要么需要付费要么就太复杂了。突然,发现一个https://ww2.mathworks.cn/matlabcentral/fileexchange/90292-spherical-vector-based-particle-swarm-optimization-spso
网站中可以找到MATLAB代码,而且看起来不是很复杂。
必须强调作者哈:

Spherical Vector-based Particle Swarm Optimization (SPSO)

版本 1.0.3 (2.9 MB) 作者: Manh Duong Phung

Implementation of the Spherical Vector-based Particle Swarm Optimization (SPSO) algorithm for UAV path planning

GitHub - duongpm/SPSO: Spherical Vector-based Particle Swarm Optimization

为了防止部分可能进不了,我就斗胆把代码搬过来了,不过如果代码对你有用,一定要去给代码原作者点个关注收藏啥的:一共这么几个模块,我将按顺序给出!不过我没运行哈,具体可不可以我不知道,反正评论表示还行。兄弟们等我几天,我把这个翻译成PYTHON语言。然后就是文章类型选的是原创,因为选另外两个挺麻烦的。

%{
This model is generated by:
- Loading terrain map
- Creating threats as cylinders
- Creating start and finish points
- Setting ranges and limits
%}
function model=CreateModel()
    H = imread('ChrismasTerrain.tif'); % Get elevation data
    H (H < 0) = 0;
    MAPSIZE_X = size(H,2); % x index: columns of H
    MAPSIZE_Y = size(H,1); % y index: rows of H
    [X,Y] = meshgrid(1:MAPSIZE_X,1:MAPSIZE_Y); % Create all (x,y) points to plot
    % Threats as cylinders
    R1=80;  % Radius
    x1 = 400; y1 = 500; z1 = 100; % center
    R2=70;  % Radius
    x2 = 600; y2 = 200; z2 = 150; % center
    
    R3=80;  % Radius
    x3 = 500; y3 = 350; z3 = 150; % center
    
    R4=70;  % Radius
    x4 = 350; y4 = 200; z4 = 150; % center
    
    R5=70;  % Radius
    x5 = 700; y5 = 550; z5 = 150; % center
    R6=80;  % Radius
    x6 = 650; y6 = 750; z6 = 150; % center
    
    % Map limits
    xmin= 1;
    xmax= MAPSIZE_X;
    
    ymin= 1;
    ymax= MAPSIZE_Y;
    
    zmin = 100;
    zmax = 200;  
 
    % Start and end position
    start_location = [200;100;150];
    end_location = [800;800;150];
    
    % Number of path nodes (not including the start position (start node))
    n=10;
    
    % Incorporate map and searching parameters to a model
    model.start=start_location;
    model.end=end_location;
    model.n=n;
    model.xmin=xmin;
    model.xmax=xmax;
    model.zmin=zmin;
    model.ymin=ymin;
    model.ymax=ymax;
    model.zmax=zmax;
    model.MAPSIZE_X = MAPSIZE_X;
    model.MAPSIZE_Y = MAPSIZE_Y;
    model.X = X;
    model.Y = Y;
    model.H = H;
    model.threats = [x1 y1 z1 R1;x2 y2 z2 R2; x3 y3 z3 R3; x4 y4 z4 R4; x5 y5 z5 R5;x6 y6 z6 R6];
    PlotModel(model);
end
%
% Create random paths (solutions)
% 
function sol=CreateRandomSolution(VarSize,VarMin,VarMax) 
    % Random path nodes
    sol.r=unifrnd(VarMin.r,VarMax.r,VarSize);
    sol.psi=unifrnd(VarMin.psi,VarMax.psi,VarSize);
    sol.phi=unifrnd(VarMin.phi,VarMax.phi,VarSize);
end
% Calculate the minimum Distance between a Point to a Segment
function dist = DistP2S(x,a,b)
d_ab = norm(a-b);
d_ax = norm(a-x);
d_bx = norm(b-x);
if d_ab ~= 0 
    if dot(a-b,x-b)*dot(b-a,x-a)>=0
        A = [b-a;x-a];
        dist = abs(det(A))/d_ab; % Formula of point - line distance       
    else
        dist = min(d_ax, d_bx); 
    end
else % if a and b are identical
    dist = d_ax;
end
%
% Calculate path cost
%
function cost=MyCost(sol,model)
    
    J_inf = inf;
    n = model.n;
    H = model.H;
    
    % Input solution
    x=sol.x;
    y=sol.y;
    z=sol.z;
    
    % Start location
    xs=model.start(1);
    ys=model.start(2);
    zs=model.start(3);
    
    % Final location
    xf=model.end(1);
    yf=model.end(2);
    zf=model.end(3);
    
    x_all = [xs x xf];
    y_all = [ys y yf];
    z_all = [zs z zf];
    
    N = size(x_all,2); % Full path length
    
    % Altitude wrt sea level = z_relative + ground_level
    z_abs = zeros(1,N);
    for i = 1:N
        z_abs(i) = z_all(i) + H(round(y_all(i)),round(x_all(i)));
    end
    
    %============================================
    % J1 - Cost for path length    
    J1 = 0;
    for i = 1:N-1
        diff = [x_all(i+1) - x_all(i);y_all(i+1) - y_all(i);z_abs(i+1) - z_abs(i)];
        J1 = J1 + norm(diff);
    end
    %==============================================
    % J2 - threats/obstacles Cost   
    % Threats/Obstacles
    threats = model.threats;
    threat_num = size(threats,1);
    
    drone_size = 1;
    danger_dist = 10*drone_size;
    
    J2 = 0;
    for i = 1:threat_num
        threat = threats(i,:);
        threat_x = threat(1);
        threat_y = threat(2);
        threat_radius = threat(4);
        for j = 1:N-1
            % Distance between projected line segment and threat origin
            dist = DistP2S([threat_x threat_y],[x_all(j) y_all(j)],[x_all(j+1) y_all(j+1)]);
            if dist > (threat_radius + drone_size + danger_dist) % No collision
                threat_cost = 0;
            elseif dist < (threat_radius + drone_size)  % Collision
                threat_cost = J_inf;
            else  % danger
                threat_cost = (threat_radius + drone_size + danger_dist) - dist;
            end
            J2 = J2 + threat_cost;
        end
    end
    %==============================================
    % J3 - Altitude cost
    % Note: In this calculation, z, zmin & zmax are heights with respect to the ground
    zmax = model.zmax;
    zmin = model.zmin;
    J3 = 0;
    for i=1:n        
        if z(i) < 0   % crash into ground
            J3_node = J_inf;
        else
            J3_node = abs(z(i) - (zmax + zmin)/2); 
        end
        
        J3 = J3 + J3_node;
    end
    
    %==============================================
    % J4 - Smooth cost
    J4 = 0;
    turning_max = 45;
    climb_max = 45;
    for i = 1:N-2
        
        % Projection of line segments to Oxy ~ (x,y,0)
        for j = i:-1:1
             segment1_proj = [x_all(j+1); y_all(j+1); 0] - [x_all(j); y_all(j); 0];
             if nnz(segment1_proj) ~= 0
                 break;
             end
        end
        for j = i:N-2
            segment2_proj = [x_all(j+2); y_all(j+2); 0] - [x_all(j+1); y_all(j+1); 0];
             if nnz(segment2_proj) ~= 0
                 break;
             end
        end
     
        climb_angle1 = atan2d(z_abs(i+1) - z_abs(i),norm(segment1_proj));
        climb_angle2 = atan2d(z_abs(i+2) - z_abs(i+1),norm(segment2_proj));
       
        turning_angle = atan2d(norm(cross(segment1_proj,segment2_proj)),dot(segment1_proj,segment2_proj));
       
        if abs(turning_angle) > turning_max
            J4 = J4 + abs(turning_angle);
        end
        if abs(climb_angle2 - climb_angle1) > climb_max
            J4 = J4 + abs(climb_angle2 - climb_angle1);
        end
       
    end
    %============================================
    % Weight coeffcients
    b1 = 5;
    b2 = 1;
    b3 = 10;
    b4 = 1;
    % Overall cost
    cost = b1*J1 + b2*J2 + b3*J3 + b4*J4;
end
% Plot the terrain model and threats
function PlotModel(model)
    mesh(model.X,model.Y,model.H); % Plot the data
    colormap summer;                    % Default color map.
    set(gca, 'Position', [0 0 1 1]); % Fill the figure window.
    axis equal vis3d on;            % Set aspect ratio and turn off axis.
    shading interp;                  % Interpolate color across faces.
    material dull;                   % Mountains aren't shiny.
    camlight left;                   % Add a light over to the left somewhere.
    lighting gouraud;                % Use decent lighting.
    xlabel('x [m]');
    ylabel('y [m]');
    zlabel('z [m]');
    hold on
   
    % Threats as cylinders
    threats = model.threats;
    threat_num = size(threats,1);
    h=250; % Height
    
    for i = 1:threat_num
        threat = threats(i,:);
        threat_x = threat(1);
        threat_y = threat(2);
        threat_z = threat(3);
        threat_radius = threat(4);
        [xc,yc,zc]=cylinder(threat_radius); % create a unit cylinder
        % set the center and height 
        xc=xc+threat_x;  
        yc=yc+threat_y;
        zc=zc*h+threat_z;
        c = mesh(xc,yc,zc); % plot the cylinder 
        set(c,'edgecolor','none','facecolor','#FF0000','FaceAlpha',.3); % set color and transparency
    end
end
%{
 This function will plot:
- model with a terrain map and obstacles
- solutions with different views
%}
function PlotSolution(sol,model,smooth)
    %% Plot 3D view
    figure(1)
    PlotModel(model)
    
    x=sol.x;
    y=sol.y;
    z=sol.z;
    
    % Start location
    xs=model.start(1);
    ys=model.start(2);
    zs=model.start(3);
    
    % Final location
    xf=model.end(1);
    yf=model.end(2);
    zf=model.end(3);
    
    x_all = [xs x xf];
    y_all = [ys y yf];
    z_all = [zs z zf];
    
    N = size(x_all,2); % real path length
    
   % Path height is relative to the ground height
    for i = 1:N
        z_map = model.H(round(y_all(i)),round(x_all(i)));
        z_all(i) = z_all(i) + z_map;
    end
    
    % given data in a point matrix, xyz, which is 3 x number of points
    xyz = [x_all;y_all;z_all];
    [ndim,npts]=size(xyz);
    xyzp=zeros(size(xyz));
    for k=1:ndim
       xyzp(k,:)=ppval(csaps(1:npts,xyz(k,:),smooth),1:npts);
    end
    plot3(xyzp(1,:),xyzp(2,:),xyzp(3,:),'k','LineWidth',2);
    % plot start point
    plot3(x_all(1),y_all(1),z_all(1),'ks','MarkerSize',7,'MarkerFaceColor','k');
    % plot target point
    plot3(x_all(N),y_all(N),z_all(N),'ko','MarkerSize',7,'MarkerFaceColor','k');
    hold off;
    
    %% Plot top view
    figure(3)
    mesh(model.X,model.Y,model.H); % Plot the data
    colormap summer;                    % Default color map.
    set(gca, 'Position', [0 0 1 1]); % Fill the figure window.
    axis equal vis3d on;            % Set aspect ratio and turn off axis.
    shading interp;                  % Interpolate color across faces.
    material dull;                   % Mountains aren't shiny.
    camlight left;                   % Add a light over to the left somewhere.
    lighting gouraud;                % Use decent lighting.
    xlabel('x [m]');
    ylabel('y [m]');
    zlabel('z [m]');
    hold on
    
    % Threats as cylinders
    threats = model.threats;
    threat_num = size(threats,1);
    
    for i = 1:threat_num
        threat = threats(i,:);
        threat_x = threat(1);
        threat_y = threat(2);
        threat_z = max(max(model.H))+1;  % choose z to be the highest peak
        threat_radius = threat(4);
        for j=1:3 
        % Define circle parameters:
        % Make an array for all the angles:
        theta = linspace(0, 2 * pi, 2000);
        % Create the x and y locations at each angle:
        x = threat_radius * cos(theta) + threat_x;
        y = threat_radius * sin(theta) + threat_y;
        % Need to make a z value for every (x,y) pair:
        z = zeros(1, numel(x)) + threat_z;
        % Do the plot:
        % First plot the center:
        plot3(threat_x, threat_y, threat_z, 'o', 'color', '#752e29', 'MarkerSize', 3, 'MarkerFaceColor','#752e29');
        % Next plot the circle:
        plot3(x, y, z, '-', 'color', '#752e29', 'LineWidth', 1);
        
        % Repeat for a smaller radius
        threat_radius = threat_radius - 20;
        end
    end
    % plot path
    plot3(xyzp(1,:),xyzp(2,:),xyzp(3,:),'k','LineWidth',2);
    % plot start point
    plot3(x_all(1),y_all(1),z_all(1),'ks','MarkerSize',7,'MarkerFaceColor','k');
    % plot target point
    plot3(x_all(N),y_all(N),z_all(N),'ko','MarkerSize',7,'MarkerFaceColor','k');
    
    % Set top view
    view(0,90)
    hold off;
    
    
    %% Plot side view
    figure(5)
    mesh(model.X,model.Y,model.H); % Plot the data
    colormap summer;                    % Default color map.
    set(gca, 'Position', [0 0 1 1]); % Fill the figure window.
    axis equal vis3d on;            % Set aspect ratio and turn off axis.
    shading interp;                  % Interpolate color across faces.
    material dull;                   % Mountains aren't shiny.
    camlight left;                   % Add a light over to the left somewhere.
    lighting gouraud;                % Use decent lighting.
    xlabel('x [m]');
    ylabel('y [m]');
    zlabel('z [m]');
    hold on
    % plot path
    plot3(xyzp(1,:),xyzp(2,:),xyzp(3,:),'k','LineWidth',2);
    % plot start point
    plot3(x_all(1),y_all(1),z_all(1),'ks','MarkerSize',7,'MarkerFaceColor','k');
    % plot target point
    plot3(x_all(N),y_all(N),z_all(N),'ko','MarkerSize',7,'MarkerFaceColor','k');
    
    view(90,0);
    hold off;
end
%_________________________________________________________________________________%
%  Spherical Vector-based Particle Swarm Optimization (SPSO) source codes demo 1.0%
%                                                                                 %
%  Developed in MATLAB 2020b                                              %
%                                                                         %
%  Author and programmer: Manh Duong Phung                                %
%                                                                         %
%         e-Mail: [email protected]                                       %
%                 [email protected]                                      %
%                                                                         %
%       Homepage: https://uet.vnu.edu.vn/~duongpm/                        %
%                                                                         %
%   Main paper: Manh Duong Phung, Quang Phuc Ha                           %
%               "Safety-enhanced UAV Path Planning with                   %
%                Spherical Vector-based Particle Swarm Optimization",     %
%               Applied soft computing                                    %
%                                                                         %
%                                                                         %
%_________________________________________________________________________%
%
% Find a path that maximizes the probability of finding object
% 
clc;
clear;
close all;
%% Problem Definition
model = CreateModel(); % Create search map and parameters
CostFunction=@(x) MyCost(x,model);    % Cost Function
nVar=model.n;       % Number of Decision Variables = searching dimension of PSO = number of path nodes
VarSize=[1 nVar];   % Size of Decision Variables Matrix
% Lower and upper Bounds of particles (Variables)
VarMin.x=model.xmin;           
VarMax.x=model.xmax;           
VarMin.y=model.ymin;           
VarMax.y=model.ymax;           
VarMin.z=model.zmin;           
VarMax.z=model.zmax;                 
VarMax.r=2*norm(model.start-model.end)/nVar;           
VarMin.r=0;
% Inclination (elevation)
AngleRange = pi/4; % Limit the angle range for better solutions
VarMin.psi=-AngleRange;            
VarMax.psi=AngleRange;          
% Azimuth 
% Determine the angle of vector connecting the start and end points
dirVector = model.end - model.start;
phi0 = atan2(dirVector(2),dirVector(1));
VarMin.phi=phi0 - AngleRange;           
VarMax.phi=phi0 + AngleRange;           
% Lower and upper Bounds of velocity
alpha=0.5;
VelMax.r=alpha*(VarMax.r-VarMin.r);    
VelMin.r=-VelMax.r;                    
VelMax.psi=alpha*(VarMax.psi-VarMin.psi);    
VelMin.psi=-VelMax.psi;                    
VelMax.phi=alpha*(VarMax.phi-VarMin.phi);    
VelMin.phi=-VelMax.phi;                    
%% PSO Parameters
MaxIt=200;          % Maximum Number of Iterations
nPop=500;           % Population Size (Swarm Size)
w=1;                % Inertia Weight
wdamp=0.98;         % Inertia Weight Damping Ratio
c1=1.5;             % Personal Learning Coefficient
c2=1.5;             % Global Learning Coefficient
%% Initialization
% Create Empty Particle Structure
empty_particle.Position=[];
empty_particle.Velocity=[];
empty_particle.Cost=[];
empty_particle.Best.Position=[];
empty_particle.Best.Cost=[];
% Initialize Global Best
GlobalBest.Cost=inf; % Minimization problem
% Create an empty Particles Matrix, each particle is a solution (searching path)
particle=repmat(empty_particle,nPop,1);
% Initialization Loop
isInit = false;
while (~isInit)
        disp("Initialising...");
   for i=1:nPop
        % Initialize Position
        particle(i).Position=CreateRandomSolution(VarSize,VarMin,VarMax);
        % Initialize Velocity
        particle(i).Velocity.r=zeros(VarSize);
        particle(i).Velocity.psi=zeros(VarSize);
        particle(i).Velocity.phi=zeros(VarSize);
        % Evaluation
        particle(i).Cost= CostFunction(SphericalToCart(particle(i).Position,model));
        % Update Personal Best
        particle(i).Best.Position=particle(i).Position;
        particle(i).Best.Cost=particle(i).Cost;
        % Update Global Best
        if particle(i).Best.Cost < GlobalBest.Cost
            GlobalBest=particle(i).Best;
            isInit = true;
        end
    end
end
% Array to Hold Best Cost Values at Each Iteration
BestCost=zeros(MaxIt,1);
%% PSO Main Loop
for it=1:MaxIt
    % Update Best Cost Ever Found
    BestCost(it)=GlobalBest.Cost;
    for i=1:nPop          
        % r Part
        % Update Velocity
        particle(i).Velocity.r = w*particle(i).Velocity.r ...
            + c1*rand(VarSize).*(particle(i).Best.Position.r-particle(i).Position.r) ...
            + c2*rand(VarSize).*(GlobalBest.Position.r-particle(i).Position.r);
        % Update Velocity Bounds
        particle(i).Velocity.r = max(particle(i).Velocity.r,VelMin.r);
        particle(i).Velocity.r = min(particle(i).Velocity.r,VelMax.r);
        % Update Position
        particle(i).Position.r = particle(i).Position.r + particle(i).Velocity.r;
        % Velocity Mirroring
        % If a particle moves out of the range, it will moves backward next
        % time
        OutOfTheRange=(particle(i).Position.r<VarMin.r | particle(i).Position.r>VarMax.r);
        particle(i).Velocity.r(OutOfTheRange)=-particle(i).Velocity.r(OutOfTheRange);
        % Update Position Bounds
        particle(i).Position.r = max(particle(i).Position.r,VarMin.r);
        particle(i).Position.r = min(particle(i).Position.r,VarMax.r);
        % psi Part
        % Update Velocity
        particle(i).Velocity.psi = w*particle(i).Velocity.psi ...
            + c1*rand(VarSize).*(particle(i).Best.Position.psi-particle(i).Position.psi) ...
            + c2*rand(VarSize).*(GlobalBest.Position.psi-particle(i).Position.psi);
        % Update Velocity Bounds
        particle(i).Velocity.psi = max(particle(i).Velocity.psi,VelMin.psi);
        particle(i).Velocity.psi = min(particle(i).Velocity.psi,VelMax.psi);
        % Update Position
        particle(i).Position.psi = particle(i).Position.psi + particle(i).Velocity.psi;
        % Velocity Mirroring
        OutOfTheRange=(particle(i).Position.psi<VarMin.psi | particle(i).Position.psi>VarMax.psi);
        particle(i).Velocity.psi(OutOfTheRange)=-particle(i).Velocity.psi(OutOfTheRange);
        % Update Position Bounds
        particle(i).Position.psi = max(particle(i).Position.psi,VarMin.psi);
        particle(i).Position.psi = min(particle(i).Position.psi,VarMax.psi);
        % Phi part
        % Update Velocity
        particle(i).Velocity.phi = w*particle(i).Velocity.phi ...
            + c1*rand(VarSize).*(particle(i).Best.Position.phi-particle(i).Position.phi) ...
            + c2*rand(VarSize).*(GlobalBest.Position.phi-particle(i).Position.phi);
        % Update Velocity Bounds
        particle(i).Velocity.phi = max(particle(i).Velocity.phi,VelMin.phi);
        particle(i).Velocity.phi = min(particle(i).Velocity.phi,VelMax.phi);
        % Update Position
        particle(i).Position.phi = particle(i).Position.phi + particle(i).Velocity.phi;
        % Velocity Mirroring
        OutOfTheRange=(particle(i).Position.phi<VarMin.phi | particle(i).Position.phi>VarMax.phi);
        particle(i).Velocity.phi(OutOfTheRange)=-particle(i).Velocity.phi(OutOfTheRange);
        % Update Position Bounds
        particle(i).Position.phi = max(particle(i).Position.phi,VarMin.phi);
        particle(i).Position.phi = min(particle(i).Position.phi,VarMax.phi);
        % Evaluation
        particle(i).Cost=CostFunction(SphericalToCart(particle(i).Position,model));
        % Update Personal Best
        if particle(i).Cost < particle(i).Best.Cost
            particle(i).Best.Position=particle(i).Position;
            particle(i).Best.Cost=particle(i).Cost;
            % Update Global Best
            if particle(i).Best.Cost < GlobalBest.Cost
                GlobalBest=particle(i).Best;
            end
        end
    end
    % Inertia Weight Damping
    w=w*wdamp;
    % Show Iteration Information
    disp(['Iteration ' num2str(it) ': Best Cost = ' num2str(BestCost(it))]);
end
%% Plot results
% Best solution
BestPosition = SphericalToCart(GlobalBest.Position,model);
disp("Best solution...");
BestPosition
smooth = 0.95;
PlotSolution(BestPosition,model,smooth);
% Best cost  
figure;
plot(BestCost,'LineWidth',2);
xlabel('Iteration');
ylabel('Best Cost');
grid on;
% Convert the solution from spherical space to Cartesian coordinates
function position = SphericalToCart(sol,model)
    % Start location
    xs = model.start(1);
    ys = model.start(2);
    zs = model.start(3);
    
    % Solution in Sperical space
    r = sol.r;
    psi = sol.psi;
    phi = sol.phi;
    
    % First Cartesian coordinate
    x(1) = xs + r(1)*cos(psi(1))*sin(phi(1));
    
    % Check limits
    if x(1) > model.xmax
        x(1) = model.xmax;
    end
    if x(1) < model.xmin
        x(1) = model.xmin;
    end 
    
    y(1) = ys + r(1)*cos(psi(1))*cos(phi(1));
    if y(1) > model.ymax
        y(1) = model.ymax;
    end
    if y(1) < model.ymin
        y(1) = model.ymin;
    end
    
    z(1) = zs + r(1)*sin(psi(1));
    if z(1) > model.zmax
        z(1) = model.zmax;
    end
    if z(1) < model.zmin
        z(1) = model.zmin;
    end 
    
    % Next Cartesian coordinates
    for i = 2:model.n
        x(i) = x(i-1) + r(i)*cos(psi(i))*sin(phi(i));
        if x(i) > model.xmax
            x(i) = model.xmax;
        end
        if x(i) < model.xmin
            x(i) = model.xmin;
        end 
        y(i) = y(i-1) + r(i)*cos(psi(i))*cos(phi(i));
        if y(i) > model.ymax
            y(i) = model.ymax;
        end
        if y(i) < model.ymin
            y(i) = model.ymin;
        end
       % z(i) = z(i-1) + r(i)*cos(psi(i));
        z(i) = z(i-1) + r(i)*sin(psi(i));
        if z(i) > model.zmax
            z(i) = model.zmax;
        end
        if z(i) < model.zmin
            z(i) = model.zmin;
        end 
    end
    
    position.x = x;
    position.y = y;
    position.z = z;
end