六轴机器人轨迹规划之五段位置s曲线插补

1.原理
五段s曲线相较于三段s曲线而言加速度也是连续变化的,能适用于平稳性要求更高的场合。分为加加速、加减速、匀速、减加速、减减速这五段。
设除匀速段以为,其余四段的时间相等都为 Ta T a ,总时间为 T T ,匀速段速度为vs,四个变速段斜率大小都为 A A ,整段轨迹的总位移L、加加速段位移 L1 L 1 、加减速段位移 L2 L 2

Ta=vsAL1=16AT3aL2=56AT3aT=4Ta+L2L12L2vs { T a = v s A L 1 = 1 6 A T a 3 L 2 = 5 6 A T a 3 T = 4 T a + L − 2 L 1 − 2 L 2 v s

则加速度分段函数为
a=At,(0tTa)A(t2Ta),(Tat2Ta)0,(2TatT2Ta)A[t(T2Ta)],(T2TatTTa)A(tT),(TTatT) a = { A t , ( 0 ≤ t ≤ T a ) − A ( t − 2 T a ) , ( T a ≤ t ≤ 2 T a ) 0 , ( 2 T a ≤ t ≤ T − 2 T a ) − A [ t − ( T − 2 T a ) ] , ( T − 2 T a ≤ t ≤ T − T a ) A ( t − T ) , ( T − T a ≤ t ≤ T )

对加速度积分可得
v=12At2,(0tTa)12A(t2Ta)2+AT2a,(Tat2Ta)vs,(2TatT2Ta)12AtT+2Ta)2+AT2a,(T2TatTTa)12A(tT)2,(TTatT) v = { 1 2 A t 2 , ( 0 ≤ t ≤ T a ) − 1 2 A ( t − 2 T a ) 2 + A T a 2 , ( T a ≤ t ≤ 2 T a ) v s , ( 2 T a ≤ t ≤ T − 2 T a ) − 1 2 A ( t − T + 2 T a ) 2 + A T a 2 , ( T − 2 T a ≤ t ≤ T − T a ) 1 2 A ( t − T ) 2 , ( T − T a ≤ t ≤ T )

对速度积分可得到位移s的分段函数
s=16At3,(0tTa)16A(t2Ta)3+AT2atAT3a,(Tat2Ta)AT2atAT3a,(2TatT2Ta)16A(tT+2Ta)3+AT2atAT2a,(T2TatTTa)16A(tT)32AT3a+AT2bT,(TTatT) s = { 1 6 A t 3 , ( 0 ≤ t ≤ T a ) − 1 6 A ( t − 2 T a ) 3 + A T a 2 t − A T a 3 , ( T a ≤ t ≤ 2 T a ) A T a 2 t − A T a 3 , ( 2 T a ≤ t ≤ T − 2 T a ) − 1 6 A ( t − T + 2 T a ) 3 + A T a 2 t − A T a 2 , ( T − 2 T a ≤ t ≤ T − T a ) 1 6 A ( t − T ) 3 − 2 A T a 3 + A T b 2 T , ( T − T a ≤ t ≤ T )

3.matlab代码实现
指定位置、速度、斜率

clc;
clear;
%初始条件
x_arry=[0,10,20,30];
v_arry=[2,2,2];
A_arry=[3,3,3];
weiyi=[x_arry(1)];sudu=[0];shijian=[0];timeall=0;jiasudu=[0]
for i=1:1:length(x_arry)-1;
%清空
    a=[];v=[];s=[];
%计算加减速段的时间和位移
    L=x_arry(i+1)-x_arry(i);
    A=A_arry(i);
    vs=v_arry(i);
    Ta=sqrt(vs/A);
    L1=A*(Ta^3)/6;
    L2=A*(Ta^3)*(5/6); 
%计算整段轨迹的总位移
    T=4*Ta+(L-2*L1-2*L2)/vs;
    for t=0:0.001:T
        if t<=Ta;%加加速度阶段
            ad=A*t;
            vd=0.5*A*t^2;
            sd=(1/6)*A*t^3;
            a=[a,ad];v=[v,vd];s=[s,sd];
        elseif t>Ta && t<=2*Ta;%加减速阶段
            ad=-A*(t-2*Ta);
            vd=-0.5*A*(t-2*Ta)^2+A*Ta^2;
            sd=-(1/6)*A*(t-2*Ta)^3+A*Ta^2*t-A*Ta^3;
            a=[a,ad];v=[v,vd];s=[s,sd];
         elseif t>2*Ta && t<=T-2*Ta;%匀速阶段
            ad=0;
            vd=vs;
            sd=A*Ta^2*t-A*Ta^3;  
            a=[a,ad];v=[v,vd];s=[s,sd];
        elseif t>T-2*Ta && t<=T-Ta;%减加度阶段
            ad=-A*(t-(T-2*Ta));
            vd=-0.5*A*(t-T+2*Ta)^2+A*Ta^2;
            sd=-(1/6)*A*(t-T+2*Ta)^3+A*Ta^2*t-A*Ta^3;
            a=[a,ad];v=[v,vd];s=[s,sd];
         elseif t>T-Ta && t<=T;%减减阶段
            ad=A*(t-T);
            vd=0.5*A*(t-T)^2;
            sd=(1/6)*A*(t-T)^3-2*A*Ta^3+A*Ta^2*T;
            a=[a,ad];v=[v,vd];s=[s,sd];
        end
    end
%时time=[timeall:0.001:timeall+T];
    timeall=timeall+T;
%连接每一段轨迹
    weiyi=[weiyi,s(2:end)+x_arry(i)];
    sudu=[sudu,v(2:end)];
    jiasudu=[jiasudu,a(2:end)];
    shijian=[shijian,time(2:end)];
end
subplot(3,1,1),plot(shijian,weiyi,'r');xlabel('t'),ylabel('position');grid on;
subplot(3,1,2),plot(shijian,sudu,'b');xlabel('t'),ylabel('velocity');grid on;
subplot(3,1,3),plot(shijian,jiasudu,'g');xlabel('t'),ylabel('accelerate');grid on;

结果如下
这里写图片描述

  • 17
    点赞
  • 169
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
六轴机器人轨迹规划算法可以分为两个部分:路径规划和插补运动。 1. 路径规划 路径规划是指将机器人从起始点移动到目标点的规划过程,主要涉及以下内容: - 确定起始点和目标点的位置信息; - 确定机器人的运动路径,例如直线、圆弧或者复杂的曲线; - 确定机器人运动的速度和加速度; - 确定机器人的运动方向,例如正向、反向或者旋转方向。 常用的路径规划算法有: - 直线插补法:通过给定的两个点之间的直线距离,计算出机器人从起始点到目标点的运动轨迹; - 圆弧插补法:通过给定的起始点、目标点和圆弧半径,计算出机器人沿着圆弧运动的轨迹; - 样条插值法:将机器人的运动轨迹抽象成一条曲线,通过对曲线进行插值运算,计算出机器人的运动轨迹。 2. 插补运动 插补运动是指机器人沿着路径规划计算出的轨迹进行运动的过程,主要涉及以下内容: - 将路径规划计算出的轨迹按照一定的时间间隔进行离散化; - 根据机器人的速度和加速度,计算机器人在每个时刻的位置和方向信息; - 将计算出的位置和方向信息转换为机器人控制系统可以理解的指令; - 通过控制系统控制机器人进行运动。 常用的插补运动算法有: - 线性插值法:将机器人沿着规划出的直线轨迹进行平滑运动; - 圆弧插值法:将机器人沿着规划出的圆弧轨迹进行平滑运动; - 匀加速直线插值法:将机器人沿着规划出的直线轨迹进行匀加速运动,以达到更好的运动效果。 以下是使用 C++ 实现的六轴机器人轨迹规划算法示例代码,其中使用了直线插补法和匀加速直线插值法: ```cpp #include <iostream> #include <vector> #include <cmath> using namespace std; // 定义机器人运动轨迹结构体 struct RobotTrajectory { double x; // 机器人当前位置的 x 坐标 double y; // 机器人当前位置的 y 坐标 double z; // 机器人当前位置的 z 坐标 double a; // 机器人当前位置的 a 角度 double b; // 机器人当前位置的 b 角度 double c; // 机器人当前位置的 c 角度 }; // 直线插补法 vector<RobotTrajectory> linearInterpolation(RobotTrajectory start, RobotTrajectory end, double step) { vector<RobotTrajectory> trajectory; // 存储机器人运动轨迹的容器 double distance = sqrt(pow(end.x-start.x, 2)+pow(end.y-start.y, 2)+pow(end.z-start.z, 2)); // 计算起始点和目标点之间的距离 int num_points = ceil(distance / step); // 根据步长计算需要插补的点的数量 double dx = (end.x - start.x) / num_points; // 计算 x 方向上的步长 double dy = (end.y - start.y) / num_points; // 计算 y 方向上的步长 double dz = (end.z - start.z) / num_points; // 计算 z 方向上的步长 double da = (end.a - start.a) / num_points; // 计算 a 角度方向上的步长 double db = (end.b - start.b) / num_points; // 计算 b 角度方向上的步长 double dc = (end.c - start.c) / num_points; // 计算 c 角度方向上的步长 // 插补运动 for (int i = 0; i < num_points; ++i) { RobotTrajectory traj; traj.x = start.x + i * dx; traj.y = start.y + i * dy; traj.z = start.z + i * dz; traj.a = start.a + i * da; traj.b = start.b + i * db; traj.c = start.c + i * dc; trajectory.push_back(traj); } return trajectory; } // 匀加速直线插值法 vector<RobotTrajectory> uniformAccelerationInterpolation(RobotTrajectory start, RobotTrajectory end, double step, double acceleration, double max_speed) { vector<RobotTrajectory> trajectory; // 存储机器人运动轨迹的容器 double distance = sqrt(pow(end.x-start.x, 2)+pow(end.y-start.y, 2)+pow(end.z-start.z, 2)); // 计算起始点和目标点之间的距离 double max_speed_squared = pow(max_speed, 2); // 计算最大速度的平方 double t_acc = max_speed / acceleration; // 计算加速时间 double t_dec = max_speed / acceleration; // 计算减速时间 double t_const = (distance - 2*t_acc*t_dec*max_speed_squared) / (2*max_speed_squared); // 计算匀速时间 double t_total = t_acc + t_dec + t_const; // 计算总时间 // 插补运动 for (double t = 0; t < t_total; t += step) { RobotTrajectory traj; double s; if (t <= t_acc) { // 加速阶段 s = 0.5 * acceleration * pow(t, 2); } else if (t <= t_total - t_dec) { // 匀速阶段 s = max_speed_squared * (t - 0.5*t_acc - 0.5*t_dec); } else { // 减速阶段 s = distance - 0.5 * acceleration * pow(t_total - t, 2); } double ratio = s / distance; // 计算当前位置占总路程的比例 traj.x = start.x + ratio * (end.x - start.x); traj.y = start.y + ratio * (end.y - start.y); traj.z = start.z + ratio * (end.z - start.z); traj.a = start.a + ratio * (end.a - start.a); traj.b = start.b + ratio * (end.b - start.b); traj.c = start.c + ratio * (end.c - start.c); trajectory.push_back(traj); } return trajectory; } int main() { RobotTrajectory start = {0, 0, 0, 0, 0, 0}; RobotTrajectory end = {1, 1, 1, 45, 45, 45}; double step = 0.01; double acceleration = 0.1; double max_speed = 0.2; cout << "Linear interpolation:" << endl; vector<RobotTrajectory> traj1 = linearInterpolation(start, end, step); for (auto t : traj1) { cout << "x: " << t.x << ", y: " << t.y << ", z: " << t.z << ", a: " << t.a << ", b: " << t.b << ", c: " << t.c << endl; } cout << "Uniform acceleration interpolation:" << endl; vector<RobotTrajectory> traj2 = uniformAccelerationInterpolation(start, end, step, acceleration, max_speed); for (auto t : traj2) { cout << "x: " << t.x << ", y: " << t.y << ", z: " << t.z << ", a: " << t.a << ", b: " << t.b << ", c: " << t.c << endl; } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值