移动机器人路径规划minimum_snap(MATLAB)笔记整理

minimum snap轨迹规划

本文代码以及其他概念可参考
https://blog.csdn.net/q597967420/article/details/76099491
本文仅对该博文程序部分做进一步解释

定义路径点、阶次

轨迹一般用n阶多项式(polynomial)来表示,即
p(t)= p 0 + p 1 ∗ t + p 2 ∗ t 2 … … + p n ∗ t n = ∑ i = 0 n p i ∗ t i p0+p1*t+p2*t^2……+pn*t^n=\sum_{i=0}^{n}pi*t^i p0+p1t+p2t2+pntn=i=0npiti
但整段轨迹通常难以用一个多项式表示,所以一般将其分为k段多项式表示。
在这里插入图片描述
机器人的平面运动路径也应该由x和y两个多项式构成,所以共有2k段多项式。
已知条件:起始点和终点的位置p、速度v、加速度a、加加速度j,每段多项式在连接点处的位置p已知,且在连接点处光滑(pvaj相等)。每一个分段都是多项式;每个分段的多项式都是相同的阶次,这样对于问题的求解比较简单;每一段的时间间隔都是已知的
在这里插入图片描述

限制条件数量: 4+4+(k-1)=k+7
首末pvaj加中间点位置
未知数数量:(N+1)*k (N为多项式阶数,k为路径的段数)
k+7<=(N+1)*k
则N>= 7 / k 7/k 7/k 表明段数越多,则提供的阶次越低。k最少是1, 所以minisnap求解中每段多项式至少有7阶,每段有八个未知数。

clc;clear;close all;
path = ginput() * 100.0;    %  返回几个点的(x,y)坐标
n_order       = 7;% 多项式的阶次 mini_snap为7 ,mini_jerk为5
n_seg         = size(path,1)-1;  % n_seg 代表路径的段数
n_poly_perseg = (n_order+1); % 多项式方程的未知量个数

时间分配

时间分配一般有两种,一种是按路径长度分配时间,一种是按梯形运动方式分配时间,此处为图简便可直接将每段时间赋值1。


% calculate time distribution in proportion to distance between 2 points
dist     = zeros(n_seg, 1);
dist_sum = 0;
T        = 25;
t_sum    = 0;

for i = 1:n_seg
    dist(i) = sqrt((path(i+1, 1)-path(i, 1))^2 + (path(i+1, 2) - path(i, 2))^2);
    dist_sum = dist_sum+dist(i);
end
for i = 1:n_seg-1
    ts(i) = dist(i)/dist_sum*T;  %前面n-1段路程都是按距离/总距离来计算时间
    t_sum = t_sum+ts(i);
end
ts(n_seg) = T - t_sum;  %而最后一段是总的时间减去前面所有时间之和

% or you can simply set all time distribution as 1
% ts=ones(5,1);

求解多项式系数


%求解x轴和y轴的多项式系数
poly_coef_x = MinimumSnapQPSolver(path(:, 1), ts, n_seg, n_order);
poly_coef_y = MinimumSnapQPSolver(path(:, 2), ts, n_seg, n_order);

function poly_coef = MinimumSnapQPSolver(waypoints, ts, n_seg, n_order)
    start_cond = [waypoints(1), 0, 0, 0];  %waypoints为 path(:, 1)即第一个点,而先对x轴求多项式系数,则waypoints(1)只提取第一个点的x轴坐标
    end_cond   = [waypoints(end), 0, 0, 0];
    
    % STEP 1: compute Q of p'Qp
    Q = getQ(n_seg, n_order, ts);
    
    % STEP 2: compute Aeq and beq 
    [Aeq, beq] = getAbeq(n_seg, n_order, waypoints, ts, start_cond, end_cond);
    f = zeros(size(Q,1),1);
    poly_coef = quadprog(Q,f,[],[],Aeq, beq); %poly_coef 为n段分轨迹多项式式子的系数的组合,长度为n_seg*8,每段8个系数
end

下面两图源自高飞老师PPT及上文参考博文中摘录
在这里插入图片描述
在这里插入图片描述

function Q = getQ(n_seg, n_order, ts)
    Q = [];
    for j = 1:n_seg  %一共有n_seg段
        Q_k = zeros(8,8); %minsnap阶数是7,系数为8

        % STEP 1.1: calculate Q_k of the k-th segment 
         for i=4:n_order
            for l=4:n_order
                L = factorial(l)/factorial(l-4);
                I = factorial(i)/factorial(i-4);             
                Q_k(i+1,l+1) = L*I/(i+l-7);
            end
         end
        Q = blkdiag(Q, Q_k);
    end
end

下为 m i n ∑ i = 1 k p T Q i p min\sum_{i=1}^{k}p^TQip mini=1kpTQip的等式约束,即1.起始点和终点的位置p、速度v、加速度a、加加速度j 已知。
2.每段多项式在连接点处的位置p已知。
3.在连接点处前后两段多项式pvaj相等
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述这里两个式子描述的是段与段之间的连接点,这个连接点在前后两段多项式中应该p v a j数值一样。两个式子时间Tj相同,但是却一个乘以系数pj,i,一个乘以系数pj+1,i ,在前一个多项式中,此连接点处于末尾点,时间为ts,而后一个多项式中,连接点处于起始点,时间为0。注意!不同的轨迹段享有不一样的多项式方程系数,所以时间计算可以不共享,每一段的起始点都可以视为这一段的时间0,这样计算每一段的p,v,a,j时,就会发现系数为阶乘。

function [Aeq beq]= getAbeq(n_seg, n_order, waypoints, ts, start_cond, end_cond)
    n_all_poly = n_seg*(n_order+1);%未知量总数
    % p,v,a,j constraint in start, 
    Aeq_start = zeros(4, n_all_poly);
    beq_start = zeros(4, 1);
    % STEP 2.1: write expression of Aeq_start and beq_start
    for k= 0:3
        Aeq_start(k+1,k+1) = factorial(k);
        %求4个阶次的情况,起始点时间t为0,那么位置就是p0,速度就是p1,加速度就是2p2,多项式系数是我二次规划要求的未知数,
                                          %所以,此处起始点每个阶次,要求的p前的常数项系数为n的阶乘
    end
    beq_start = start_cond'; 
    % p,v,a constraint in end
    Aeq_end = zeros(4, n_all_poly);
    beq_end = zeros(4, 1);
    % STEP 2.2: write expression of Aeq_end and beq_end
    start_idx_2 = (n_order + 1)*(n_seg - 1);
    for k=0 : 3
        for i=k : 7   %总共0-3 4个阶次,k到7意思是八个系数求导之后,前面几个系数都消失了,
             Aeq_end(k+1,start_idx_2 + 1 + i ) = factorial(i)/factorial(i-k)*ts(n_seg)^(i-k);
        end
    end
    beq_end = end_cond';
    % position constrain in all middle waypoints
    Aeq_wp = zeros(n_seg-1, n_all_poly);
    beq_wp = zeros(n_seg-1, 1);
    % STEP 2.3: write expression of Aeq_wp and beq_wp
    for i=0:n_seg-2  %一共n_seg-1个中间点
        start_idx_2 = (n_order + 1)*(i+1);  %前面几段有多少个系数
        Aeq_wp(i+1,start_idx_2+1) = 1;%
        beq_wp(i+1,1) = waypoints(i+2);%右端为 本段分轨迹的末点的坐标(已知量)
    end
    % position continuity constrain between each 2
    % segments,连接点处前后两段在此点的位置、速度、加速度、加加速度相等
    Aeq_con = zeros((n_seg-1)*4, n_all_poly);
    beq_con = zeros((n_seg-1)*4, 1);
    % STEP 2.4: write expression of Aeq_con_p and beq_con_p
     for k=0:3
        for j=0:n_seg-2   %n_seg-1个中间点
            for i = k:7   %循环顺序不重要,只是遍历 n-1个中间点,的4个阶次pvaj,以及使i>=7的情况下遍历8次
                start_idx_1 = (n_seg-1)*k;
                start_idx_2 = (n_order+1)*j;
                Aeq_con(start_idx_1 + j + 1,start_idx_2 + i+1)=...
                    factorial(i)/factorial(i-k)*ts(j+1)^(i-k);   %代表同一个连接点在前一段的多项式方程的末尾点pvaj(求k阶导),此时时间在前一段中为ts
                if(i == k)   %因为后一段的起始点时间为0,所以求导后,除了i==k时,其他部分都为0,所以不用算
                    Aeq_con(start_idx_1+j+1,start_idx_2+(n_order+1)+i+1) = ...
                                                            -factorial(i);%代表同一个连接点在后一段的多项式方程中的计算,此时时间在后一段中为0
                                                            
                end  %两者相减等于0                                        % %因为在后一个连接点的多项式中,t为0,所以pi前的系数只有阶乘
            end
        end
    end
    
    Aeq = [Aeq_start; Aeq_end; Aeq_wp; Aeq_con];
    beq = [beq_start; beq_end; beq_wp; beq_con];
end

绘制minimum snap的路径

% display the trajectory
X_n = [];
Y_n = [];
k = 1;
tstep = 0.01;
for i=0:n_seg-1
    
    % STEP 3: get the coefficients of i-th segment of both x-axis
    % and y-axis
    start_idx = n_poly_perseg * i;
    Pxi = poly_coef_x(start_idx + 1 : start_idx + n_poly_perseg,1);
    Pxi = flipud(Pxi);%得到多项式系数
    Pyi = poly_coef_y(start_idx + 1 : start_idx + n_poly_perseg,1);
    Pyi = flipud(Pyi);   %多项式从阶数高的开头
    for t = 0:tstep:ts(i+1)  %以0.01的步长遍历所有时间   (ts(i+1)就是时间结尾)
        X_n(k)  = polyval(Pxi, t); %计算多项式Pxi在t点处的每一个值
        Y_n(k)  = polyval(Pyi, t);
        k = k + 1;
    end
end
 
plot(X_n, Y_n , 'Color', [0 1.0 0], 'LineWidth', 2);  %画出所有轨迹
hold on
scatter(path(1:size(path, 1), 1), path(1:size(path, 1), 2));  

### MiniSnap 路径规划算法实现方法 MiniSnap 是一种用于多旋翼飞行器和其他移动机器人的高效路径规划技术,其核心在于通过最小化高阶导数(如 Jerk 或 Snap)来生成平滑且能量高效的轨迹。该方法利用微分平坦性原理将复杂的十二维状态空间简化为四个独立参数,并基于这些参数构建多项式轨迹。 #### 构建目标函数 在 MiniSnap 中,通常采用 Minimum Jerk 函数作为优化标准之一。然而,在某些应用场景下也可以选择其他形式的目标函数,比如 Minimum Snap 来进一步减少振动效应[^1]。具体来说: - **定义变量**:设 \( \mathbf{p}(t)=[x(t),y(t),z(t)]^\top \),表示三维空间内的位置向量;\( p^{(i)}_d \) 表示第 i 阶导数值。 - **建立模型**:假设整个航程由多个线段组成,则每一线段上的位移可以表达成关于时间 t 的七次或更高次数的多项式: \[ \begin{aligned} &\text{{Position}} && :&&& x(t)=a_xt^7+b_xt^6+c_xt^5+d_xt^4+e_xt^3+f_xt^2+g_xt+h_x \\ &\text{{Velocity}} && :&&& v(t)=7a_xt^6+6b_xt^5+...\\ &\text{{Acceleration}} && :&&& a(t)=42a_xt^5+... \end{aligned} \] - **设定边界条件**:对于每一个阶段,除了指定起始点和结束点的位置外,还需要提供初始时刻的速度、加速度以及终端时刻相同属性的信息。值得注意的是,在实际应用过程中往往会对超过三阶以上的导数施加零值约束以降低计算复杂度并提高稳定性[^3]。 #### 时间分配策略 考虑到不同路段可能存在不同的动态特性需求,合理安排各段之间的时间间隔至关重要。常见的做法有两种:一是依据几何距离比例划分时间段;二是模仿物理系统的惯性行为模式设计梯形加速曲线来进行时间配置。后者更贴近实际情况,有助于提升整体性能表现[^4]。 #### MATLAB 实现案例分析 下面给出了一段简单的MATLAB代码片段用来展示如何绘制一条经过特定控制点集后的连续光滑曲线。这段程序首先对输入数据进行了预处理操作,接着运用矩阵运算快速求得各个离散采样瞬间对应的坐标值,最后调用绘图命令完成可视化输出工作[^5]。 ```matlab function plot_path(qX,qY,M,T,N) Roll=N+1; qX=reshape(qX,Roll,M); qY=reshape(qY,Roll,M); hold on for j=1:M qXj=qX(:,j); qYj=qY(:,j); Tj=T(j); index=0; for t=0:0.001:Tj index=index+1; time(index)=t; t_exp=zeros(N+1,1); for n=0:N t_exp(n+1)=t^n; end x(index)=qXj'*t_exp; y(index)=qYj'*t_exp; end plot(x,y,'r.'); end hold off ``` 此部分展示了从理论到实践的具体转换过程,帮助理解 MiniSnap 如何应用于真实世界的问题解决当中。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值