• 开源机器人SmallRobotArm机器人源码解读


    1 SmallRobotArm简介

    开源机器人SmallRobotArm是一个开源的6轴机械臂,都由步进电机驱动,github地址:https://github.com/SkyentificGit/SmallRobotArm

     机器人长这个样子

    2 欧拉角及姿态变换

    由欧拉角求姿态矩阵

    源码中用的欧拉角是ZYZ顺组的欧拉角。

    已知世界坐标的坐标(x,y,z)和欧拉角(α,β,γ),求出对应的姿态矩阵:

    源码中实现这一功能的是pos2tran(float* Xpt, float* Tpt)函数。

    由姿态矩阵求欧拉角

    已知姿态矩阵,求对应的(x,y,z)和欧拉角(α,β,γ)为:

     

    源码中实现这一功能的是函数void tran2pos(float* Ttp, float* Xtp)。

    3 机器人D-H参数及正运动学

    由源码可以看到机械臂用的是标准DH参数,参数表:

    i

    αi

    ai

    di

    θi

    1

    -90

    r1

    d1

    t1

    2

    0

    r2

    0

    t2

    3

    -90

    r3

    d3

    t3

    4

    90

    0

    d4

    t4

    5

    -90

    0

    0

    t5

    6

    0

    0

    d6

    t6

    对于标准DH参数为(α,a,d,θ)的关节,其变换矩阵为:

    SmallRobotArm机器人6个关节的DH参数变换矩阵分别为:

    所以T06=T01*T12*T23*T34*T45*T56

    4 逆运动学求解

    SmallRobotArm源码中求逆解的函数为InverseK。它根据给出的机械臂中断的(x,y,z)坐标及欧拉角计算了6个关节角度。

    设T06为:

     欲求反求6个关节角t1,t2,t3,t4,t5,t6

    关节角t1解算

    根据等式T16=T12*T23*T34*T45*T56=inv(T01)*T06,建立等式

     取T16的元素(2,2)和(2,3)构成等式:

    可以求出: 

     ​​​

     关节角t2和t3的解算

     t1计算出来后,现在T16等式的右边矩阵都是已知数。这里用aij代指右边矩阵的对应元素。

     取T16的(0,0)元素和(1,0)元素构成等式:

     上式乘以s23,下式乘以c23,有:

     ​​​​​​​

     下式减去上式有:

     取T16的(0,1)元素和(1,1)元素构成等式有:

    变换后可得:

     

    取T16的(0,2)元素和(1,2)元素构成等式有:

     ​​​​​​​

     变换后可得:

     取T16的(0,3)元素和(1,3)元素构成等式有:

    变换后得:

    将(2-1)、(2-2)和(2-3)三式相加有:

     

     由此式子可以解出s23/c23,进而解出t2+t3

    再代入到(2-4)式中,接出t3,则t2也可求出。

    关节角t4、t5和t6的解算

     先求出T03的逆矩阵

    由inv(T03)*T06

     由T36的元素(0,2)与(1,2),可以求出t4。

    t4=atan2(-T36[1][2],-T36[0][2])

    由T36的元素(0,2)与(1,2)元素相加取平方和,再开根号,可以求出s5,再结合元素(2,2),可求出t5:

    由T36的元素(2,1)与元素(2,0),可求出t6:

    t6=atan2(-T36[2][1], T36[2][0])

    5 机器人运动控制

    如何走一条直线

    最基本的运动是如何从一个点走直线到另外一个点,源码中实现该功能的函数是

    void goStrightLine(float* xfi, float* xff, float vel0, float acc0, float velini, float velfin)。其中xfi是出发点关节角度数组,xff是目的点关节角度数组,vel0是巡航速度,acc0是加速度,velini是初速度,velfin是结束速度。

    1. void goStrightLine(float* xfi, float* xff, float vel0, float acc0, float velini, float velfin){
    2. //
    3. float lmax = max(abs(xff[0]-xfi[0]),abs(xff[1]-xfi[1]));
    4. lmax = max(lmax,abs(xff[2]-xfi[2]));
    5. lmax = max(lmax,abs(xff[3]-xfi[3]));
    6. lmax = max(lmax,abs(xff[4]-xfi[4]));
    7. lmax = max(lmax,abs(xff[5]-xfi[5]));
    8. unsigned long preMil = micros();
    9. double l = 0.0;
    10. vel0 = min(vel0,sqrt(lmax*acc0+0.5*velini*velini+0.5*velfin*velfin));
    11. unsigned long curMil = micros();
    12. unsigned long t = 0;
    13. double tap = vel0/acc0-velini/acc0;
    14. double lap = velini*tap+acc0*tap*tap/2.0;
    15. double lcsp = lmax-(vel0*vel0/2.0/acc0-velfin*velfin/2.0/acc0);
    16. double tcsp = (lcsp-lap)/vel0+tap;
    17. double tfin = vel0/acc0-velfin/acc0+tcsp;
    18. while (curMil-preMil<=tfin){
    19. t = curMil-preMil;
    20. //acceleration phase
    21. if (t<=tap) {
    22. l = velini*t+acc0*t*t/2.0;
    23. }
    24. //contant maximum speed phase
    25. if (t>tap && t<=tcsp) {
    26. l = lap+vel0*(t-tap);
    27. }
    28. //deceleration phase
    29. if (t>tcsp) {
    30. l = lcsp+vel0*(t-tcsp)-acc0*(t-tcsp)*(t-tcsp)/2.0;
    31. }
    32. //trajectory x and y as a function of l
    33. float Xx[6];
    34. Xx[0]=xfi[0]+(xff[0]-xfi[0])/lmax*l;
    35. Xx[1]=xfi[1]+(xff[1]-xfi[1])/lmax*l;
    36. Xx[2]=xfi[2]+(xff[2]-xfi[2])/lmax*l;
    37. Xx[3]=xfi[3]+(xff[3]-xfi[3])/lmax*l;
    38. Xx[4]=xfi[4]+(xff[4]-xfi[4])/lmax*l;
    39. Xx[5]=xfi[5]+(xff[5]-xfi[5])/lmax*l;
    40. goTrajectory(Xx);
    41. curMil = micros();
    42. }
    43. }

     速度规划

     goStrightLine函数中用的是梯形速度规划算法。如下图左图所示,对于初速度为V0,为Ve,巡航速度为Vm,运动距离为S的直线运动

     则加速阶段走过的距离Sa和减速段走过的距离Sd为:

     ​​​​​​​

     此时Vm为:

    若有匀速段,则Vm<=Vmm;若没有匀速段,则最大速度只能到Vmm,所以goStrightLine中取最大速度为Vmm和Vel0的较小值,将其重新赋给vel0。

    已知最,高速度vel0,可以求出加速时间:

    double tap = vel0/acc0-velini/acc0;

    进而求出加速段总距离 

    double lap = velini*tap+acc0*tap*tap/2.0;

    进而求出匀速段距离

    double lcsp = lmax-(vel0*vel0/2.0/acc0-velfin*velfin/2.0/acc0);

    从而求出匀速段时间

    double tcsp = (lcsp-lap)/vel0+tap;

     再求出减速度时间

    1. double tcsp = (lcsp-lap)/vel0+tap;
    2. double tfin = vel0/acc0-velfin/acc0+tcsp;

     对于当前的时间t,通过判断t所在的区间,可以求出当前的距离,进而求出每个关节角度xx,再调用

    电机执行函数goTrajectory(Xx)函数走到目的姿态去。

    电机执行

    电机执行函数执行函数很简单,就是根据当前电机的角度,若当前角度小于目标角度电机就发一个脉冲正走一步,若大于当前角度电机就发一个脉冲反走一步。其中dl1~dl6参数就是电机走一步对应的角度。

  • 相关阅读:
    数据库|Binlog故障处理之drainer周期性罢工
    Docker实战技巧(一):常用命令与最佳实践
    [AGC041F] Histogram Rooks(神仙题 网格 容斥计数)
    《流畅的python》阅读笔记 - 第六章:使用一等函数实现设计模式
    word中图片怎么批量缩小?超级简单好用!
    信号线上串接电阻的作用
    你已经应用了哪种服务注册和发现的模式呢?
    node.js+mysql+vue.js+vuex+echarts+elementui全栈后台管理系统
    Oracle包权限管理实例
    API 架构学习
  • 原文地址:https://blog.csdn.net/liuzhijun301/article/details/126752752