• 自动驾驶算法(九):多项式轨迹与Minimun Snap原理与Matab代码详解


    目录

    1 为什么需要轨迹优化

    2 代码解析

    3 完整代码


    1 为什么需要轨迹优化

            我们利用前八篇所学的博客可以利用RRT、A*、遗传算法等设计出一条折线轨迹,轨迹优化就是在路径优化的基础上将折线优化成曲线,这样更加有利于无人机的飞行。

            那么什么是多项式轨迹呢?

            每段轨迹的路程以t为变量的函数表示出来就是多项式轨迹。

            我们用三段轨迹表示这段路程(以时间t作为自变量):

            那么我们的任务就是求解参数向量p确定轨迹,t_0,t_1,t_2与路程成正比的因此我们可以提前算出。

            那么我们轨迹的要求是什么呢?

            优化目标为:

            这个优化的目的是使加速度尽可能的小:那么速度也是尽可能地小,对无人机动力要求就不那么大了。

            具体推导如下:

            其实我们就要算出来个Q矩阵,里面的r是rows的意思,c是cols的意思。

            其实就是一个二次规划问题?

            也就是求在Ap=b约束下最小的p^TQp

    2 代码解析

            我们先来运行一下:

            所在位置为*的就是我们航行的路径点,不同颜色的就是几段。

            我们因此要先设置起点的速度和加速度、终点的速度和加速度、还有总时间、我们根据总时间还有路径的长度去分配时间:

    1. function demo1_minimum_snap_simple()
    2. clear,clc;
    3. % condition
    4. % 航路点 起点、终点、中间的这些点
    5. waypts = [0,0;
    6. 1,2;
    7. 2,0;
    8. 4,5;
    9. 5,2]';
    10. % 起点、终点速度加速度
    11. v0 = [0,0];
    12. a0 = [0,0];
    13. v1 = [0,0];
    14. a1 = [0,0];
    15. % 总时间
    16. T = 5;
    17. % 计算每一段轨迹的时间
    18. % 输入参数为航路点 + 总时间
    19. ts = arrangeT(waypts,T);
    20. % 设置多项式的阶数
    21. n_order = 5;

            我们看一下怎么给各段路程分配时间的:

    1. function ts = arrangeT(waypts,T)
    2. % 这一行代码计算了相邻路径点之间的差值。假设 waypts 是一个矩阵,每一列代表一个路径点的坐标,
    3. % 那么 waypts(:,2:end) 选择了除了第一个路径点之外的所有路径点,waypts(:,1:end-1) 选择了除了最后一个路径点之外的所有路径点,
    4. % 然后两者相减,得到了相邻路径点之间的位移。
    5. % waypts:
    6. % 0 1 2 4 5
    7. % 0 2 0 5 2
    8. % waypts(:,2:end)
    9. % 冒号表示取到了所有的行,取到了2到最后一列
    10. % 1 2 4 5
    11. % 2 0 5 2
    12. % 0 1 2 4 = 1 1 2 1
    13. % 0 2 0 5 = 2 -2 5 -3 其实就是相邻的点进行相减
    14. x = waypts(:,2:end) - waypts(:,1:end-1);
    15. % 计算了相邻路径点之间的欧几里得距离。x.^2 将 x 中的每个元素平方,然后 sum(x.^2,1) 对每列进行求和,
    16. % 最后 .^0.5 对每个和取平方根,得到相邻路径点之间的欧几里得距离。
    17. dist = sum(x.^2,1).^0.5;
    18. % 计算了一个缩放因子 k,它是总时间 T 与所有相邻路径点之间的距离之和的比值。
    19. k = T/sum(dist);
    20. % 构建了时间戳 ts。cumsum(dist*k) 计算了距离的累积和,然后在前面加了一个零,以确保起始时间戳为零。
    21. ts = [0 cumsum(dist*k)];
    22. end

            我们指定了总时间T=5秒,这里做的就是根据路程进行线性分段。

    1. %% XY轴分开计算
    2. % 传入参数 第一行的所有列就是所有的x 每一段的时间 多项式阶 起点终点的加速度
    3. polys_x = minimum_snap_single_axis_simple(waypts(1,:),ts,n_order,v0(1),a0(1),v1(1),a1(1));
    4. polys_y = minimum_snap_single_axis_simple(waypts(2,:),ts,n_order,v0(2),a0(2),v1(2),a1(2));

            这里就是重头戏了,进行路径规划,包括求Q矩阵与约束的构建。

    1. % 传入参数 第一行的所有列就是所有的x 每一段的时间 多项式阶 起点终点的加速度
    2. function polys = minimum_snap_single_axis_simple(waypts,ts,n_order,v0,a0,ve,ae)
    3. % 起点终点的位置
    4. p0 = waypts(1);
    5. pe = waypts(end);
    6. % 多项式的段数:航路点-1
    7. n_poly = length(waypts)-1;
    8. % 参数个数 = 阶数+1
    9. n_coef = n_order+1;
    10. % 构建优化目标 优化目标的数量为多项式的段数
    11. Q_all = [];
    12. for i=1:n_poly
    13. % 构建对角矩阵(有几个多项式就有几个Q)
    14. % 在每次循环中,它调用了一个名为 computeQ 的函数
    15. % 传递了四个参数:n_order(多项式的阶数)、3(对jack 4阶导数进行优化)、ts(i)这一段的起始时间 和 ts(i+1)这一段的结束时间。
    16. % computeQ 函数的返回值是一个对角矩阵,这个对角矩阵将会被加入到 Q_all 中,通过 blkdiag 函数实现对 Q_all 的更新。
    17. Q_all = blkdiag(Q_all,computeQ(n_order,3,ts(i),ts(i+1)));

            这里我们传进来了起点和终点的x坐标。n_poly表示多项式的段数,也就是我们求的路程有几段,为航路点个数-1 = 4段。n_coef就是p矩阵的阶数,我们采用5阶(n_order)项+一个常数项的表示方法,即:

    % 传入参数 个体的路径 地图 一行有多少个元素x
    % 它告诉 MATLAB 这是一个名为 generate_continuous_path 的函数,它接受三个输入参数 single_pop,G 和 x,并且它会返回一个名为 single_new_pop 的变量。
    function [single_new_pop] = generate_continuous_path(single_pop, G, x)
    i = 1;
    single_new_pop = single_pop;
    % 这行代码调用了 size 函数来获取变量 single_new_pop 的大小,并将结果存储在了 single_path_num 变量中。
    % 在这里,使用了波浪线 ~ 来表示忽略了 size 函数返回的第一个值(也就是行数),只保留了列数。
    % single_new_pop 是一个 1 * 20的向量
    % single_path_num 存储了路径经过的点的数量
    [~, single_path_num] = size(single_new_pop);

    % 遍历每一列 1-20
    while i ~= single_path_num
        % 点i所在列 (从左到右编号)
        x_now = mod(single_new_pop(1, i), x) + 1; 
        % 点i所在行 (从上到下编号)
        y_now = fix(single_new_pop(1, i) / x) + 1;
        % 点i+1所在行 (从上到下编号)
        x_next = mod(single_new_pop(1, i + 1), x) + 1;
        y_next = fix(single_new_pop(1, i + 1) / x) + 1;
        
        % 初始化最大迭代次数
        max_iteration = 0;
        
        % 如果他们不相连的话
        while max(abs(x_next - x_now), abs(y_next - y_now)) > 1
            x_insert = floor((x_next + x_now) / 2);
            y_insert = floor((y_next + y_now) / 2);
            
            % 取得两者中点值
            if G(y_insert, x_insert) == 0  
                % 栅格值
                num_insert = (x_insert - 1) + (y_insert - 1) * x;
                % single_new_pop 是一个数组,这段代码的目的是将 num_insert 插入到 single_new_pop 的第 i 个位置之后。
                % single_new_pop(1, 1:i) 表示取 single_new_pop 中第1行,从第1列到第i列的元素。
                % single_new_pop(1, i+1:end) 表示取 single_new_pop 中第1行,从第i+1列到最后一列的元素。
                single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                
            % 如果是障碍物的话
            else   
                % 它检查该点左面是否有路径 
                % (x_insert - 2) + (y_insert - 1) * x 是否不等于 single_new_pop(1, i)。
                if G(y_insert, x_insert - 1) == 0 && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i)) && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i+1))
                    x_insert = x_insert - 1;
                    % 索引号
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    % 插入
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                                   
                elseif G(y_insert, x_insert + 1) == 0 && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i)) && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i+1))
                    x_insert = x_insert + 1;
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                    
                elseif G(y_insert + 1, x_insert) == 0 && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i)) && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i+1))
                    y_insert = y_insert + 1;
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];

                elseif  G(y_insert - 1, x_insert) == 0 && ((x_insert - 1) + (y_insert - 2) * x ~= single_new_pop(1, i)) && ((x_insert - 1) + (y_insert-2) * x ~= single_new_pop(1, i+1))
                    y_insert = y_insert - 1;
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                    
                % 左右上下都是占据的则删去路径
                else
                    %break_pop = single_new_pop
                    single_new_pop = [];
                    break
                end    
            end
            
            x_next = x_insert;
            y_next = y_insert;
            max_iteration = max_iteration + 1;
            if max_iteration > 20000
                single_new_pop = [];
                break
            end
            
        end
        
        if isempty(single_new_pop)
            break
        end
        
        [~, single_path_num] = size(single_new_pop);
        i = i + 1;
    end

            了解这些后,我们通过ComputeQ计算Q矩阵,并通过blkdiag合并一个个Q矩阵,最终组成如下形式:

    Q = \begin{bmatrix} Q_1 & & & & \\ & Q_2& & & \\ & & ... & & \\ & & &... & \\ & & & & Q_k \end{bmatrix}

            其中k为多项式的段数,也就是说有几段路程,就有几个Q矩阵。

            我们看一下Q矩阵的计算方法:

    1. % n:polynormial order
    2. % r:derivertive order, 1:minimum vel 2:minimum acc 3:minimum jerk 4:minimum snap
    3. % t1:start timestamp for polynormial
    4. % t2:end timestap for polynormial
    5. % n=5 五次多项式拟合路径 r=3 用jerk模拟 t1 t2
    6. function Q = computeQ(n,r,t1,t2)
    7. % (n-r)*2+1 = (5-3)*2+1 = 5
    8. T = zeros((n-r)*2+1,1);
    9. for i = 1:(n-r)*2+1
    10. T(i) = t2^i-t1^i;
    11. end
    12. % 理论说过Q是n+1 * n+1的维度 也就是7*7的维度 r是3 表示用jerk进行优化
    13. % 它的矩阵就右下角有值
    14. Q = zeros(n+1);
    15. for i = r+1:n+1 % 行 从r+1开始,因为前r行都是0,在PPT中r=4。在我们的实例中r=3
    16. for j = i:n+1 % 列 从r+1开始
    17. k1 = i-r-1; %对应r-3 行-r-1
    18. k2 = j-r-1; %对应c-3 列-r-1
    19. k = k1+k2+1;% r-3+c-3+1
    20. % prod是连乘的意思 prod(k1+1:k1+r)= r-3+1 *...* r-3+3 =
    21. % (r-3)(r-2)(r-1)r (c-3)(c-2)(c-1)c k就是参数
    22. Q(i,j) = prod(k1+1:k1+r)*prod(k2+1:k2+r)/k*T(k);
    23. Q(j,i) = Q(i,j);
    24. end
    25. end
    26. %Q

            这里我们传来的n=5,即用五次项拟合曲线,r=4用三阶导数去求极值。

            T矩阵就是后面的那块:t_{i}^{r+c-7}-t_{i-1}^{r+c-7}

            这里是对应于4阶snap来说的,我们用三阶作为优化目标那么我们的T矩阵就应当是t_{i}^{r-3+c-3+1}-t_{i-1}^{r-3+c-3+1}。前三排前三列是0的,因此有值的就是第4行到第n+1=6行。因为是对角矩阵,我们只需算出其中的一半也就是6个值。如下Q矩阵:

          我们初始化Q矩阵为(n+1,n+1)的方阵,从r+1行也就是3+1=4行开始赋值,比如第四行,从第四列一直到第n+1列也就是第6列,再比如第五行,从第五列一直到第n+1列也就是第6列。

            首先计算r-3,也就是行-3,i表示遍历哪一行,j表示遍历哪一列,因此我们不妨想想当i与j都为4的时候,行-3对应4-3-1!=0,我们补足-1就是0了。k对应r-3+c-3+1。t_{i}^{r-3+c-3+1}-t_{i-1}^{r-3+c-3+1}就是T(k)。

            这里我们就理解T矩阵的赋值了,因为它所包含的最高项的次数为r-3+c-3+1的max r和c,r和cmax也就是n+1,因此它的最高项次数也就是 (n-3)*2 + 1。到此,我们的Q矩阵就构造完毕啦。

            我们打印一下Q矩阵:

            我们来建立约束方程:

    % 传入参数 个体的路径 地图 一行有多少个元素x
    % 它告诉 MATLAB 这是一个名为 generate_continuous_path 的函数,它接受三个输入参数 single_pop,G 和 x,并且它会返回一个名为 single_new_pop 的变量。
    function [single_new_pop] = generate_continuous_path(single_pop, G, x)
    i = 1;
    single_new_pop = single_pop;
    % 这行代码调用了 size 函数来获取变量 single_new_pop 的大小,并将结果存储在了 single_path_num 变量中。
    % 在这里,使用了波浪线 ~ 来表示忽略了 size 函数返回的第一个值(也就是行数),只保留了列数。
    % single_new_pop 是一个 1 * 20的向量
    % single_path_num 存储了路径经过的点的数量
    [~, single_path_num] = size(single_new_pop);

    % 遍历每一列 1-20
    while i ~= single_path_num
        % 点i所在列 (从左到右编号)
        x_now = mod(single_new_pop(1, i), x) + 1; 
        % 点i所在行 (从上到下编号)
        y_now = fix(single_new_pop(1, i) / x) + 1;
        % 点i+1所在行 (从上到下编号)
        x_next = mod(single_new_pop(1, i + 1), x) + 1;
        y_next = fix(single_new_pop(1, i + 1) / x) + 1;
        
        % 初始化最大迭代次数
        max_iteration = 0;
        
        % 如果他们不相连的话
        while max(abs(x_next - x_now), abs(y_next - y_now)) > 1
            x_insert = floor((x_next + x_now) / 2);
            y_insert = floor((y_next + y_now) / 2);
            
            % 取得两者中点值
            if G(y_insert, x_insert) == 0  
                % 栅格值
                num_insert = (x_insert - 1) + (y_insert - 1) * x;
                % single_new_pop 是一个数组,这段代码的目的是将 num_insert 插入到 single_new_pop 的第 i 个位置之后。
                % single_new_pop(1, 1:i) 表示取 single_new_pop 中第1行,从第1列到第i列的元素。
                % single_new_pop(1, i+1:end) 表示取 single_new_pop 中第1行,从第i+1列到最后一列的元素。
                single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                
            % 如果是障碍物的话
            else   
                % 它检查该点左面是否有路径 
                % (x_insert - 2) + (y_insert - 1) * x 是否不等于 single_new_pop(1, i)。
                if G(y_insert, x_insert - 1) == 0 && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i)) && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i+1))
                    x_insert = x_insert - 1;
                    % 索引号
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    % 插入
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                                   
                elseif G(y_insert, x_insert + 1) == 0 && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i)) && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i+1))
                    x_insert = x_insert + 1;
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                    
                elseif G(y_insert + 1, x_insert) == 0 && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i)) && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i+1))
                    y_insert = y_insert + 1;
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];

                elseif  G(y_insert - 1, x_insert) == 0 && ((x_insert - 1) + (y_insert - 2) * x ~= single_new_pop(1, i)) && ((x_insert - 1) + (y_insert-2) * x ~= single_new_pop(1, i+1))
                    y_insert = y_insert - 1;
                    num_insert = (x_insert - 1) + (y_insert - 1) * x;
                    single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
                    
                % 左右上下都是占据的则删去路径
                else
                    %break_pop = single_new_pop
                    single_new_pop = [];
                    break
                end    
            end
            
            x_next = x_insert;
            y_next = y_insert;
            max_iteration = max_iteration + 1;
            if max_iteration > 20000
                single_new_pop = [];
                break
            end
            
        end
        
        if isempty(single_new_pop)
            break
        end
        
        [~, single_path_num] = size(single_new_pop);
        i = i + 1;
    end

    1. %求解F(不等式) 构建全是0的向量
    2. b_all = zeros(size(Q_all,1),1);
    3. % 构建等式约束 4K+2 多项式的个数*每个项的系数
    4. Aeq = zeros(4*n_poly+2,n_coef*n_poly);
    5. beq = zeros(4*n_poly+2,1);
    6. % 起点/终点的位置速度和加速度 (6 equations)
    7. % 1-3行 第一个参数到n_order+1=6 位置、速度、加速度
    8. Aeq(1:3,1:n_coef) = [calc_tvec(ts(1),n_order,0);
    9. calc_tvec(ts(1),n_order,1);
    10. calc_tvec(ts(1),n_order,2)];
    11. % 终点约束4-6
    12. Aeq(4:6,n_coef*(n_poly-1)+1:n_coef*n_poly) = ...
    13. [calc_tvec(ts(end),n_order,0);
    14. calc_tvec(ts(end),n_order,1);
    15. calc_tvec(ts(end),n_order,2)];
    16. beq(1:6,1) = [p0,v0,a0,pe,ve,ae]';

    1. % r=0:pos 1:vel 2:acc 3:jerk
    2. % n_order 多项式的阶数
    3. % t 第i段占据的时间
    4. % r 0 1 2 对应 位置 速度 加速度
    5. function tvec = calc_tvec(t,n_order,r)
    6. tvec = zeros(1,n_order+1);
    7. for i=r+1:n_order+1
    8. tvec(i) = prod(i-r:i-1)*t^(i-r-1);
    9. end
    10. end

            回顾一下,我们n_poly,它的值为多项式的段数也就是航路点-1,本例中n_poly =4

            n_coef为多项式的次数+1,这里我们为6。

            先看一下它的形式吧:我们打印一下约束方程的Aeq

            它的行数为18(4*n_poly+2),列数为24(n_coef *n_poly )。我们看看它里面存储的是什么吧!

            1-6行我们加入起点和终点的约束(位移、速度、加速度):

    1. % 起点/终点的位置速度和加速度 (6 equations)
    2. % 1-3行 第一个参数到n_order+1=6 位置、速度、加速度
    3. Aeq(1:3,1:n_coef) = [calc_tvec(ts(1),n_order,0);
    4. calc_tvec(ts(1),n_order,1);
    5. calc_tvec(ts(1),n_order,2)];
    6. % 终点约束4-6
    7. Aeq(4:6,n_coef*(n_poly-1)+1:n_coef*n_poly) = ...
    8. [calc_tvec(ts(end),n_order,0);
    9. calc_tvec(ts(end),n_order,1);
    10. calc_tvec(ts(end),n_order,2)];

            起点约束放在起点的位置上,因为一个约束是有5阶+1个常数项的,因此一个约束占据6列。一共4段路线,是这么来的24行。

            从第七行开始固定中间的点。从第七行开始到第十行。

    1. neq = 6;
    2. % 从第七行开始
    3. for i=1:n_poly-1
    4. neq=neq+1;
    5. Aeq(neq,n_coef*i+1:n_coef*(i+1)) = calc_tvec(ts(i+1),n_order,0);
    6. beq(neq) = waypts(i+1);
    7. end

            位置为行数,一个占据自己的六个位置,如下:

            下面开始连续性约束:

    1. % 段数-1 continuous constraints ((n_poly-1)*3 equations)
    2. for i=1:n_poly-1
    3. tvec_p = calc_tvec(ts(i+1),n_order,0);
    4. tvec_v = calc_tvec(ts(i+1),n_order,1);
    5. tvec_a = calc_tvec(ts(i+1),n_order,2);
    6. neq=neq+1;
    7. Aeq(neq,n_coef*(i-1)+1:n_coef*(i+1))=[tvec_p,-tvec_p];
    8. neq=neq+1;
    9. Aeq(neq,n_coef*(i-1)+1:n_coef*(i+1))=[tvec_v,-tvec_v];
    10. neq=neq+1;
    11. Aeq(neq,n_coef*(i-1)+1:n_coef*(i+1))=[tvec_a,-tvec_a];
    12. end

            对位移、速度、加速度进行约束。n_coef*(i-1)+1:n_coef*(i+1)代表每一次处理一个点,如下:

            圈起来的就是一对邻接点的位移、速度、加速度。

            我们添加完约束之后,开始求解

    1. Aieq = [];
    2. bieq = [];
    3. p = quadprog(Q_all,b_all,Aieq,bieq,Aeq,beq);
    4. polys = reshape(p,n_coef,n_poly);

            我们这里没有不等式约束,故设置Q_all,b_all为空,我们求解的变量就是p。

            是不是很简单呢?

            看一下运行结果:

    3 完整代码

    1. % 传入参数 个体的路径 地图 一行有多少个元素x
    2. % 它告诉 MATLAB 这是一个名为 generate_continuous_path 的函数,它接受三个输入参数 single_pop,G 和 x,并且它会返回一个名为 single_new_pop 的变量。
    3. function [single_new_pop] = generate_continuous_path(single_pop, G, x)
    4. i = 1;
    5. single_new_pop = single_pop;
    6. % 这行代码调用了 size 函数来获取变量 single_new_pop 的大小,并将结果存储在了 single_path_num 变量中。
    7. % 在这里,使用了波浪线 ~ 来表示忽略了 size 函数返回的第一个值(也就是行数),只保留了列数。
    8. % single_new_pop 是一个 1 * 20的向量
    9. % single_path_num 存储了路径经过的点的数量
    10. [~, single_path_num] = size(single_new_pop);
    11. % 遍历每一列 1-20
    12. while i ~= single_path_num
    13. % 点i所在列 (从左到右编号)
    14. x_now = mod(single_new_pop(1, i), x) + 1;
    15. % 点i所在行 (从上到下编号)
    16. y_now = fix(single_new_pop(1, i) / x) + 1;
    17. % 点i+1所在行 (从上到下编号)
    18. x_next = mod(single_new_pop(1, i + 1), x) + 1;
    19. y_next = fix(single_new_pop(1, i + 1) / x) + 1;
    20. % 初始化最大迭代次数
    21. max_iteration = 0;
    22. % 如果他们不相连的话
    23. while max(abs(x_next - x_now), abs(y_next - y_now)) > 1
    24. x_insert = floor((x_next + x_now) / 2);
    25. y_insert = floor((y_next + y_now) / 2);
    26. % 取得两者中点值
    27. if G(y_insert, x_insert) == 0
    28. % 栅格值
    29. num_insert = (x_insert - 1) + (y_insert - 1) * x;
    30. % single_new_pop 是一个数组,这段代码的目的是将 num_insert 插入到 single_new_pop 的第 i 个位置之后。
    31. % single_new_pop(1, 1:i) 表示取 single_new_pop 中第1行,从第1列到第i列的元素。
    32. % single_new_pop(1, i+1:end) 表示取 single_new_pop 中第1行,从第i+1列到最后一列的元素。
    33. single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
    34. % 如果是障碍物的话
    35. else
    36. % 它检查该点左面是否有路径
    37. % (x_insert - 2) + (y_insert - 1) * x 是否不等于 single_new_pop(1, i)。
    38. if G(y_insert, x_insert - 1) == 0 && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i)) && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i+1))
    39. x_insert = x_insert - 1;
    40. % 索引号
    41. num_insert = (x_insert - 1) + (y_insert - 1) * x;
    42. % 插入
    43. single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
    44. elseif G(y_insert, x_insert + 1) == 0 && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i)) && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i+1))
    45. x_insert = x_insert + 1;
    46. num_insert = (x_insert - 1) + (y_insert - 1) * x;
    47. single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
    48. elseif G(y_insert + 1, x_insert) == 0 && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i)) && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i+1))
    49. y_insert = y_insert + 1;
    50. num_insert = (x_insert - 1) + (y_insert - 1) * x;
    51. single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
    52. elseif G(y_insert - 1, x_insert) == 0 && ((x_insert - 1) + (y_insert - 2) * x ~= single_new_pop(1, i)) && ((x_insert - 1) + (y_insert-2) * x ~= single_new_pop(1, i+1))
    53. y_insert = y_insert - 1;
    54. num_insert = (x_insert - 1) + (y_insert - 1) * x;
    55. single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];
    56. % 左右上下都是占据的则删去路径
    57. else
    58. %break_pop = single_new_pop
    59. single_new_pop = [];
    60. break
    61. end
    62. end
    63. x_next = x_insert;
    64. y_next = y_insert;
    65. max_iteration = max_iteration + 1;
    66. if max_iteration > 20000
    67. single_new_pop = [];
    68. break
    69. end
    70. end
    71. if isempty(single_new_pop)
    72. break
    73. end
    74. [~, single_path_num] = size(single_new_pop);
    75. i = i + 1;
    76. end

  • 相关阅读:
    Linux思维导图
    chmod,rwx Linux文件属性笔记221107
    腾讯云服务器地域是什么?地域选择看着一篇就够了
    深入了解C++中各种不同意义的new和delete
    探索ChatGPT的Fine-tuning和Embeddings
    字符函数和字符串函数(C语言进阶)
    Vue 最简单路由 页面路由 配置路由
    JavaScript中判断数据类型,浅拷贝和深拷贝详解
    实验7(MPLS实验)
    MySQL数据库之索引
  • 原文地址:https://blog.csdn.net/qq_41694024/article/details/134282282