当前位置:   UNITY > 正文

UnityVR--机械臂场景8-三自由度逆向解算3-应用在ABB机械臂_三自由度机械臂

三自由度机械臂

目录

1. ABB机械臂形态

2. ABB机械臂数学模型分析

3. 初步程序实现

4. 误差分析

5. 最终实现


  前文已经在Unity中,将3自由度机械臂的数学模型实现出来了,现在我们将它实际应用于机械臂中。选用的机械臂3D模型是ABB IRB 4600工业机器人,来自AssetStore。

  

(图片来自ABB官网)

1. ABB机械臂形态

  模型中总共有六个旋转轴,为了继承上一章内容和分析方法,仅使用其中的3个自由度。

   

2. ABB机械臂数学模型分析

  但是与上一章的数学模型不同的是,这里的base和Arm0两个节点坐标不同,因此在上一章的基础上,需要分两步来考虑:

  第一步:以base为原点来计算θ3,这一步与上一章相同;

 

或者θ3=arctan(x/z)

  第二步:以Arm0为原点计算θ1和θ2。

  这里用二维图作示意,将坐标轴偏移一个距离,这时候Target的坐标变成了与Arm0节点的差值(x',y',z')

按照上一章的计算方式,重新计算W‘、A'、θT、θ2、θ1:

 

  

 

 

 

3. 初步程序实现

  1. 准备工作:首先要拿到上述计算需要用到的变量:

  1. public Transform Base,Arm0,Arm1,Hand,Target;
  2. float X, Y, Z; //记录目标Target的位置,相对于Base
  3. float x_plus, y_plus, z_plus; //Target的位置,相对于Arm0
  4. private float L1,L2;
  5. private float sita_1, sita_2, sita_3, sita_T, W, A;

  2. 准备工作:计算出L1、L2的值,这是固定不变的

  1. L1 = Vector3.Distance(Arm0.position, Arm1.position);
  2. L2 = Vector3.Distance(Arm1.position, Hand.position);

  3. 先在以base为原点的坐标系中计算出θ3,套公式:

  1. X = Target.position.x - Base.transform.position.x;
  2. Y = Target.position.y - Base.transform.position.y;
  3. Z = Target.position.z - Base.transform.position.z;
  4. sita_3 = Mathf.Atan2(X, Z);
  5. sita_3 = Mathf.Rad2Deg * sita_3;

  4. 再以Arm0为原点,计算x',y',z',W‘、A'、θT、θ2、θ1,套公式:

  1. x_plus = Target.position.x - Arm0.position.x;
  2. y_plus = Target.position.y - Arm0.position.y;
  3. z_plus = Target.position.z - Arm0.position.z;
  4. W = Mathf.Sqrt(square(x_plus) + square(z_plus));
  5. A = Mathf.Sqrt(square(W) + square(y_plus));
  6. sita_T = Mathf.Acos(W / A);
  7. sita_1 = Mathf.Acos((square(L1) + square(W) + square(y_plus) - square(L2)) / (2 * L1 * A)) + sita_T;
  8. sita_2 = Mathf.Acos((square(W) + square(y_plus) - square(L1) - square(L2)) / (2 * L1 * L2));
  9. sita_1 *= Mathf.Rad2Deg;
  10. sita_2 *= Mathf.Rad2Deg;

  好了,运行试试看:

   结果中可以看到,虽然机械臂随着Target移动,但是却有一定的误差:Target和手爪之间错位了一段距离。这是为什么呢?下面分析一下误差产生的原因。

4. 误差分析

  将这几个旋转节点单独拿出来观察,从XY平面来看,在机械臂的初始状态,Arm0到Arm1,以及Arm1到Hand,并不是完全地与Y轴平行的,XZ平面也是如此。这一点从Arm0和Arm1的本地坐标上也能看出来。但上述数学模型是简化了的,没有考虑到这些问题。

  

   因此,在一开始还需要计算出初始角度,并在之后实际旋转时减去。sita_L1和sita_L2分别是两条手臂L1和L2的初始偏移角度。

  1. sita_L1 =(Mathf.Asin(Arm1.localPosition.x / L1))*Mathf.Rad2Deg;
  2. var temp = Hand.position.x - Arm1.position.x;
  3. sita_L2=(Mathf.Asin(temp/ L2)) * Mathf.Rad2Deg;

5. 最终实现

 完整代码如下:

  1. public Transform Base,Arm0,Arm1,Hand,Target;
  2. private float L1,L2;
  3. private float sita_L1, sita_L2;//L1、L2初始位置的偏移角
  4. private float[] moveAngle;
  5. void Start()
  6. { //在ABB机械臂中,L1改成(S_Axis_2)到Arm1节点(U_Axis_3)的距离
  7. L1 = Vector3.Distance(Arm0.position, Arm1.position);
  8. L2 = Vector3.Distance(Arm1.position, Hand.position);
  9. sita_L1 =(Mathf.Asin(Arm1.localPosition.x / L1))*Mathf.Rad2Deg;
  10. var temp = Hand.position.x - Arm1.position.x;
  11. sita_L2=(Mathf.Asin(temp/ L2)) * Mathf.Rad2Deg;
  12. }
  13. void Update()
  14. {
  15. moveAngle=IKCaculator(Target,moveAngle);
  16. Vector3 euler0 = Base.transform.localEulerAngles;
  17. euler0.y = moveAngle[0];
  18. //插值旋转举例
  19. Base.localRotation = Quaternion.Slerp(Base.localRotation, Quaternion.Euler(Euler0), 0.9f * Time.deltaTime);
  20. if (Quaternion.Angle(Base.localRotation, Quaternion.Euler(Euler0)) < 0.5f)
  21. Base.transform.localEulerAngles = Euler0;
  22. Vector3 euler1 = Arm0.transform.localEulerAngles;
  23. euler1.z = moveAngle[1];
  24. Arm0.localEulerAngles = euler1;
  25. Vector3 euler2 = Arm1.transform.localEulerAngles;
  26. euler2.z =moveAngle[2];
  27. Arm1.localEulerAngles = euler2;
  28. }
  29. float[] IKCaculator(Transform target,float[] Scara)
  30. {
  31. float sita_1, sita_2, sita_3, sita_T, X, Y, Z, W, A,x_plus,y_plus,z_plus;
  32. //计算目标Target和第一个关节Base距离的三个分量X、Y、Z
  33. X = target.position.x - Base.transform.position.x;
  34. Y = target.position.y - Base.transform.position.y;
  35. Z = target.position.z - Base.transform.position.z;
  36. //计算目标Target和Arm0距离的三个分量x_plus、y_plus、z_plus
  37. x_plus = target.position.x - Arm0.position.x;
  38. y_plus = target.position.y - Arm0.position.y;
  39. z_plus = target.position.z - Arm0.position.z;
  40. //计算W和A,在图中为W'和A'
  41. W = Mathf.Sqrt(square(x_plus) + square(z_plus));
  42. A = Mathf.Sqrt(square(W) + square(y_plus)); //A的长度=根号(W平方+Y平方)
  43. sita_T = Mathf.Acos(W / A); //辅助角T
  44. sita_1 = Mathf.Acos((square(L1) + square(W) + square(y_plus) - square(L2)) / (2 * L1 * A)) + sita_T;
  45. sita_2 = Mathf.Acos((square(W) + square(y_plus) - square(L1) - square(L2)) / (2 * L1 * L2));
  46. sita_3 = Mathf.Atan2(X, Z);
  47. sita_1 *= Mathf.Rad2Deg;
  48. sita_2 *= Mathf.Rad2Deg;
  49. sita_3 *= Mathf.Rad2Deg;
  50. Scara[0] = sita_3-90; //ABB机械臂的误差排除
  51. Scara[1] =-(90- sita_1+sita_L1);
  52. Scara[2] = -(sita_2-sita_L2);
  53. return Scara;
  54. }
  55. static float square(float f)
  56. {
  57. return f * f;
  58. }

或者在旋转时加入球形插值,让它转得丝滑一些。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/UNITY/detail/33314
推荐阅读
相关标签
  

闽ICP备14008679号

        
cppcmd=keepalive&