unity制作机械臂

硬盘坏了,项目没了/(ㄒoㄒ)/~~幸好记录了一些步骤

一、前置知识

1.1 变换矩阵

  位置是相对的,必须先确定参考系,才能描述物体的位置。我们将定义的第一个坐标系称为参考坐标系,其他的坐标系都是相对于这个参考坐标系来描述的。从参考坐标系转换到其他坐标系上的转换关系矩阵叫变换矩阵,变换矩阵是连接两个坐标系的桥梁。具体来说,变换矩阵T是由两部分组成:旋转矩阵R和平移矩阵t。旋转矩阵R负责处理坐标系之间的旋转关系,而平移矩阵t则负责处理坐标系之间的平移关系。通过变换矩阵,我们能够准确地将物体从一个坐标系转换到另一个坐标系。
  下面举出一个例子,定义蓝色的坐标系为参考坐标系,绿色的坐标系为目标坐标系,红色的点表示空间中的一个物体。首先确定旋转矩阵R,z轴绕负方向旋转了90度,其余轴都没有进行旋转,则 R = [ 0 − 1 0 0 1 0 0 0 0 0 1 0 0 0 0 1 ] R=\begin{bmatrix}0&-1&0&0\\1&0&0&0\\0&0&1&0\\0&0&0&1\end{bmatrix} R= 0100100000100001 ,再确定平移矩阵t,x轴正向平移1单位,y轴正向平移6单位,z轴正向平移2单位, t = [ 1 0 0 1 0 1 0 6 0 0 1 2 0 0 0 1 ] t=\begin{bmatrix}1&0&0&1\\0&1&0&6\\0&0&1&2\\0&0&0&1\end{bmatrix} t= 1000010000101621 ,则从参考坐标系转换到目标坐标系的变换矩阵 T = [ 0 − 1 0 6 1 0 0 − 1 0 0 1 − 2 0 0 0 1 ] T=\begin{bmatrix}0&-1&0&6\\1&0&0&-1\\0&0&1&-2\\0&0&0&1\end{bmatrix} T= 0100100000106121 。物体在参考坐标系的坐标位置是 P = ( 3 , 2 , 4 ) P=(3,2,4) P=(3,2,4),如果要变换到目标坐标系则左乘变换矩阵T,将得到物体在目标坐标系的位置 P = ( 4 , 2 , 2 ) P=(4,2,2) P=(4,2,2)
在这里插入图片描述
  参考:旋转矩阵R、平移向量t以及变换矩阵T的定义及其下标的含义

1.2 旋转矩阵

  向量的旋转一共有三种表示方法:旋转矩阵、欧拉角和四元数。因此可以用计算旋转(旋转矩阵、欧拉角、四元数、旋转向量)+平移(平移矩阵、平移向量)的8种排列组合来表示变换矩阵,旋转矩阵+平移矩阵是表示变换矩阵最直接的,但其中的数值无法直观的体现出来,因此需要借助欧拉角表示旋转矩阵。欧拉角的计算要区分左右手坐标系以及旋转顺序,在unity中使用的是左手坐标系yxz的顺序。unity中物体的旋转用的是transform.Rotate函数,传入参数的是角度,因此欧拉角转旋转矩阵的代码如下:

Matrix4x4 eulerAnglesToRotationMatrix(Vector3 eulerAngles)
{
    double rx = eulerAngles.x / 180.0 * Math.PI;
    double ry = eulerAngles.y / 180.0 * Math.PI;
    double rz = eulerAngles.z / 180.0 * Math.PI;
    Matrix4x4 Rx = new Matrix4x4(new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, (float)Math.Cos(rx), (float)Math.Sin(rx), 0f), new Vector4(0f, -(float)Math.Sin(rx), (float)Math.Cos(rx), 0f), new Vector4(0f, 0f, 0f, 1f));
    Matrix4x4 Ry = new Matrix4x4(new Vector4((float)Math.Cos(ry), 0f, -(float)Math.Sin(ry), 0f), new Vector4(0f, 1f, 0f, 0f), new Vector4((float)Math.Sin(ry), 0f, (float)Math.Cos(ry), 0f), new Vector4(0f, 0f, 0f, 1f));
    Matrix4x4 Rz = new Matrix4x4(new Vector4((float)Math.Cos(rz), (float)Math.Sin(rz), 0f, 0f), new Vector4(-(float)Math.Sin(rz), (float)Math.Cos(rz), 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f));
    return Ry * Rx * Rz;
}

四元数转旋转矩阵的代码如下:

Matrix4x4 quaternionToRotationMatrix(Quaternion quaternion)
{
    Matrix4x4 result = new Matrix4x4();
    double w = quaternion.w;
    double rx = quaternion.x;
    double ry = quaternion.y;
    double rz = quaternion.z;
    result.m00 = (float)(1 - 2 * ry * ry - 2 * rz * rz);
    result.m01 = (float)(2 * rx * ry - 2 * w * rz);
    result.m02 = (float)(2 * rx * rz + 2 * w * ry);
    result.m10 = (float)(2 * rx * ry + 2 * w * rz);
    result.m11 = (float)(1 - 2 * rx * rx - 2 * rz * rz);
    result.m12 = (float)(2 * ry * rz - 2 * w * rx);
    result.m20 = (float)(2 * rx * rz - 2 * w * ry);
    result.m21 = (float)(2 * ry * rz + 2 * w * rx);
    result.m22 = (float)(1 - 2 * rx * rx - 2 * ry * ry);
    result.m33 = 1;
    return result;
}

参考:彻底搞懂“旋转矩阵/欧拉角/四元数”,让你体会三维旋转之美

1.3 欧拉角

旋转矩阵转欧拉角的代码如下:

Vector3 rotationMatrixToEulerAngles(Matrix4x4 T)
{
    float rx = (float)(Math.Asin(-T.m12));
    float ry = (float)(Math.Atan2(T.m02, T.m22));
    float rz = (float)(Math.Atan2(T.m10, T.m11));
    return new Vector3(rx, ry, rz);
}

四元数转欧拉角的代码如下:

var eulerAngles = rotation.eulerAngles;

1.4 四元数

旋转矩阵转四元数的代码如下:

var rotation = Quaternion.Euler(rotationMatrixToEulerAngles(T));

欧拉角转四元数的代码如下:

var rotation = Quaternion.Euler(eulerAngles);

二、unity搭建机械臂

2.1 下载机械臂模型

  unity导入的模型需要fbx格式,下载下来的是step格式,需要使用软件(如3dsmax)进行转换。将模型导入后看到模型部件的名称是乱码,且有层级关系,我们修改对应的名称并且不需要这种层级关系。创建14个空物体分别命名为机械臂、组件1-7、关节1-6,所有空物体的初始位置要在(0,0,0),并把模型部件移动到对应的组件下,如图所示。
在这里插入图片描述
参考:资料下载

2.2 确定用于动画的旋转坐标系

  把关节的初始位置设置在关节的圆形切面的中心位置,如图所示。
在这里插入图片描述
参考:unity制作机械臂

2.3 关节旋转动画的设计与实现

  将第i+1个组件放入第i个关节中,如图所示。
在这里插入图片描述
  此时,改变inspector界面中的rotation就可以实现关节的旋转了,如果动画实现错误,将组件、关节拖动到一个层级上,检查组件的初始位置是否为(0,0,0),关节的初始位置是否在关节圆形切面的中心位置。
请添加图片描述
  接下来,为每个关节实现旋转的代码。

public class Joint : MonoBehaviour
{
    public TextMeshProUGUI text;		//用于可视化界面显示角度的文本框
    public Vector3 rotationAxis;		//xyz哪个轴进行旋转才能实现动画效果
    public Vector2 rotationLimit;		//对关节的角度进行限制
    float angle = 0f;					//用于存储当前关节的角度
    float rotationAnglePerSencond = 45f;//每秒旋转多少角度
    int isRotation = 0;					//按钮是否被按下,有-1,0,1三个值,分别表示逆向旋转,暂停,正向旋转
    // 如果按钮被按下,则按照按钮对应的值进行旋转
    void Update(){if (isRotation != 0) jointRotation(rotationAnglePerSencond * Time.deltaTime * isRotation);}
    //获取当前关节的角度
    public float getAngle(){return angle;}
    //检查关节能否继续旋转△角度
    public bool jointCheck(float deltaAngle)
    {
        if (angle + deltaAngle < rotationLimit.x)
            return false;
        if (angle + deltaAngle > rotationLimit.y)
            return false;
        return true;
    }
    //检查关节是否可以旋转,若可以更新角度和UI
    public void jointRotation(float deltaAngle)
    {
        if (jointCheck(deltaAngle))
        {
            angle += deltaAngle;
            transform.Rotate(deltaAngle * rotationAxis);
            text.SetText(text.text.Substring(0, 12) + String.Format("{0:F2}", angle).PadLeft(7, ' '));
        }
    }
    //绑定按钮+按下事件
    public void rotationDirectionAdd(){isRotation = 1;}
    //绑定按钮-按下事件
    public void rotationDirectionSub(){isRotation = -1;}
    //绑定按钮+-弹起事件
    public void rotationDirectionStop(){isRotation = 0;}
}

  将脚本拖动到每个关节中,设置脚本中的初始值,并将UI界面的按钮事件与脚本绑定,最终就可以实现如3.1 正移动学中的动画效果了。

参考:基于 Unity 的5自由度机械臂运动仿真

2.4 确定用于建模的变换坐标系

这一部分需要理解参考中的方法才能实现,如果机械臂的大致位置朝向和本文类似,可以试着跟着做。本文用的是SDH法,具体流程如下:
1、创建7个空物体分别命名为参考系1-7,所有空物体的初始位置要在(0,0,0)。
2、移动7个空物体到其相应的位置,精确位置的数值可以参考2.2旋转坐标系的位置。
具体操作:
①往上(绿色y轴正方向)移动得到②
②往上(绿色y轴正方向)移动得到③
③往上(绿色y轴正方向)移动得到④
④往右(蓝色z轴正方向)移动得到⑤
⑤往上(绿色y轴正方向)移动得到⑥
⑥往右(蓝色z轴正方向)移动得到⑦
3、旋转7个空物体到其相应的朝向,朝向的规则为:绿色y轴与其对应的关节圆形切面垂直;红色x轴与屏幕平面垂直。
具体操作:
②红色x轴正向旋转90度
③红色x轴正向旋转90度
④红色x轴正向旋转90度
⑥红色x轴正向旋转90度
⑦红色x轴正向旋转90度
4、确定SDH法中的参数,可以描述为:参考系i的红色x轴(xoz平面)绕其绿色y轴offset度得到参考系i+1的红色x轴(xoz平面)相同朝向;再将参考系i的原点沿绿色y轴平移d单位得到参考系i+1的原点相同高度;再将参考系i的绿色y轴(yoz平面)绕其红色x轴alpha度得到参考系i+1的绿色y轴(yoz平面)相同朝向;再将参考系i的原点沿蓝色z轴平移a单位得到参考系i+1的原点相同位置。
具体操作:
①依次通过rotation.y转动0度,position.y平移1.22单位,rotation.x转动90度,position.z平移0单位得到②
②依次通过rotation.y转动0度,position.y平移0单位,rotation.x转动0度,position.z平移-4.07单位得到③
③依次通过rotation.y转动0度,position.y平移0单位,rotation.x转动0度,position.z平移-3.77单位得到④
④依次通过rotation.y转动0度,position.y平移1.21单位,rotation.x转动-90度,position.z平移0单位得到⑤
⑤依次通过rotation.y转动0度,position.y平移1.03单位,rotation.x转动90度,position.z平移0单位得到⑥
⑥依次通过rotation.y转动0度,position.y平移0.95单位,rotation.x转动0度,position.z平移0单位得到⑦
请添加图片描述
参考:机器人工程师进阶之路(二)6轴机械臂D-H法建模

2.5 正逆运动学的设计与实现

2.5.1 正运动学

正运动学的推导如4.2描述,因此正运动学的代码如下:

Matrix4x4 forward(double[] joint_theta)
{
    Matrix4x4 T = Matrix4x4.identity;
    // 公式T=T1T2T3T4T5T6
    for (int i = 0; i < 6; i++) T *= SDH(new Vector3((float)alpha[i], (float)(joint_theta[i]+offset[i]), 0), new Vector3(0, (float)d[i], (float)a[i]));
    return T;
}

其中SDH函数的代码如下:

Matrix4x4 SDH(Vector3 eulerAngles, Vector3 position = new Vector3())
{
    double rx = eulerAngles.x / 180.0 * Math.PI;
    double ry = eulerAngles.y / 180.0 * Math.PI;
    double rz = eulerAngles.z / 180.0 * Math.PI;
    double x = position.x;
    double y = position.y;
    double z = position.z;
    Matrix4x4 Rx = new Matrix4x4(new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, (float)Math.Cos(rx), (float)Math.Sin(rx), 0f), new Vector4(0f, -(float)Math.Sin(rx), (float)Math.Cos(rx), 0f), new Vector4(0f, 0f, 0f, 1f));
    Matrix4x4 Ry = new Matrix4x4(new Vector4((float)Math.Cos(ry), 0f, -(float)Math.Sin(ry), 0f), new Vector4(0f, 1f, 0f, 0f), new Vector4((float)Math.Sin(ry), 0f, (float)Math.Cos(ry), 0f), new Vector4(0f, 0f, 0f, 1f));
    Matrix4x4 Rz = new Matrix4x4(new Vector4((float)Math.Cos(rz), (float)Math.Sin(rz), 0f, 0f), new Vector4(-(float)Math.Sin(rz), (float)Math.Cos(rz), 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f));
    Matrix4x4 Tx = new Matrix4x4(new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, 1f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4((float)x, 0f, 0f, 1f));
    Matrix4x4 Ty = new Matrix4x4(new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, 1f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, (float)y, 0f, 1f));
    Matrix4x4 Tz = new Matrix4x4(new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, 1f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, (float)z, 1f));
    return Ry * Ty * Rx * Tx * Rz * Tz;
}

返回的T变换矩阵包含了旋转和位置的信息,可以通过1.3 变换矩阵转欧拉角来获取旋转信息,T.m03,T.m13,T.m23则是位置信息。

2.5.2 逆运动学

逆运动学的推导如4.3描述,因此逆运动学的代码如下:

List<np.array> inverseKinematics(Matrix4x4 T)
{
    double d1 = d[0], a2 = a[1], a3 = a[2], d4 = d[3], d5 = d[4], d6 = d[5];
    double nx = T.m00, ox = T.m01, ax = T.m02, px = T.m03;
    double ny = T.m10, oy = T.m11, ay = T.m12, py = T.m13;
    double nz = T.m20, oz = T.m21, az = T.m22, pz = T.m23;
    var ans = new np.array[6];
    for (int i = 0; i < ans.Length; i++) ans[i] = new np.array();
    double m1 = pz - d6 * oz;
    double n1 = d6 * ox - px;
    ans[0][0, 4] = new np.array(np.arctan2(m1, n1) - np.arctan2(d4, np.pow(np.pow(m1, 2) + np.pow(n1, 2) - np.pow(d4, 2), 0.5)), 4);
    ans[0][4, 8] = new np.array(np.arctan2(m1, n1) - np.arctan2(d4, -np.pow(np.pow(m1, 2) + np.pow(n1, 2) - np.pow(d4, 2), 0.5)), 4);
    var s1 = np.sin(ans[0]);
    var c1 = np.cos(ans[0]);
    ans[4][0, 2] = np.arccos(s1[0, 2] * ox + oz * c1[0, 2]);
    ans[4][2, 4] = -np.arccos(s1[2, 4] * ox + oz * c1[2, 4]);
    ans[4][4, 6] = np.arccos(s1[4, 6] * ox + oz * c1[4, 6]);
    ans[4][6, 8] = -np.arccos(s1[6, 8] * ox + oz * c1[6, 8]);
    var s5 = np.sin(ans[4]);
    var c5 = np.cos(ans[4]);
    var m2 = s1 * ax + az * c1;
    var n2 = s1 * nx + nz * c1;
    ans[5] = np.arctan2(m2, n2) + np.arctan2(0, -s5);
    var s6 = np.sin(ans[5]);
    var c6 = np.cos(ans[5]);
    var m3 = d5 * (-(c1 * nx - nz * s1) * s6 + c6 * (c1 * ax - az * s1)) - d6 * (c1 * ox - oz * s1) + (c1 * px - pz * s1);
    var n3 = d5 * (ny * s6 - ay * c6) + oy * d6 - py + d1;
    ans[2][0, 8, 2] = np.arccos(np.clip((np.pow(m3[0, 8, 2], 2) + np.pow(n3[0, 8, 2], 2) - np.pow(a2, 2) - np.pow(a3, 2)) / (2 * a2 * a3), -1, 1));
    ans[2][1, 8, 2] = -np.arccos(np.clip((np.pow(m3[1, 8, 2], 2) + np.pow(n3[1, 8, 2], 2) - np.pow(a2, 2) - np.pow(a3, 2)) / (2 * a2 * a3), -1, 1));
    var s3 = np.sin(ans[2]);
    var c3 = np.cos(ans[2]);
    var s2 = ((a3 * c3 + a2) * m3 - a3 * s3 * n3) / (np.pow(a2, 2) + np.pow(a3, 2) + 2 * a2 * a3 * c3);
    var c2 = (n3 + a3 * s3 * s2) / (a3 * c3 + a2);
    ans[1] = np.arctan2(s2, c2);
    var m4 = (-ny * c6 - ay * s6) * (-c5) + s5 * oy;
    var n4 = (ny * s6 - ay * c6);
    ans[3] = np.arctan2(m4, n4) - ans[1] - ans[2];
    return ans;
}

其中np类是对一些计算的封装,array类是对double[]的一个封装,方便用于计算,给出部分代码。

class np
{
    public class array
    {
        public double[] data;
        public int Length;
		public array(double[] data){this.data = data;this.Length = data.Length;}
		public static array operator +(array a, array b)
		{
		    array ans = new array(new double[a.Length]);
		    for (int i = 0; i < a.Length; i++){ans[i] = a[i] + b[i];}
		    return ans;
		}
		public array this[int begin, int end, int sep]
		{
		    get{array ans = new array(new double[(end - begin + 1) / sep]);for (int i = 0; i < ans.Length; i++){ans[i] = this[begin + i * sep];}return ans;}
		    set{for (int i = begin; i < end; i += sep){this[i] = value[(i - begin) / sep];}}
		}
	}
	public static array arctan2(array a, array b)
	{
	    array ans = new array(new double[a.Length]);
	    for (int i = 0; i < a.Length; i++){ans[i] = Math.Atan2(a[i], b[i]);}
	    return ans;
	}
}

参考:UR机械臂正逆运动学求解

2.6 机械臂示教器的设计与实现

2.6.1 回顾之前的工作

我们在第一章实现了旋转矩阵、欧拉角和四元数的互相转换。在2.5节实现了正逆移动学的代码,可以将(6个关节的角度)和(末端位置的旋转和平移)进行互相转换。在2.3节实现了单个关节的旋转动画。因此在这一节将实现机械臂示教器的模拟。

2.6.2 UI界面的制作

从下幅图片中可以看出,对机械臂的控制按钮有24个,分别是6个轴、3个姿态、3个位置的正向和反向变化。
请添加图片描述
创建一个UI相机;创建一个UI图层,包括显示机械臂所在环境的image,显示当前帧和下一帧的变化矩阵的text,6个轴、3个姿态、3个位置的正向和反向button及text。
在这里插入图片描述

2.6.3 机械臂脚本的制作

机械臂脚本的核心代码如下,在Start函数中限制帧率并初始化关节位置,在Update函数中的步骤如下:
1、获取每个关节的角度
2、正运动学求解获取x、y、z、rx、ry、rz
3、更新示教器UI
4、有无示教器操作,若无返回1
5、逆运动学求解获取j1、j2、j3、j4、j5、j6
6、选择最优解
7、移动每个关节到相应角度
8、更新示教器UI

void Start()
{
    // 限制帧率,初始化关节位置
    Application.targetFrameRate = 60;
    joint1.GetComponent<Joint>().jointRotation(0f);
    joint2.GetComponent<Joint>().jointRotation(-10f);
    joint3.GetComponent<Joint>().jointRotation(-50f);
    joint4.GetComponent<Joint>().jointRotation(-30f);
    joint5.GetComponent<Joint>().jointRotation(90f);
    joint6.GetComponent<Joint>().jointRotation(90f);
}
void Update()
{
    theta = getTheta();                     //获取每个关节的角度
    T = forward(theta);                     //正运动学求解
    updateUI();                             //更新示教器UI
    if (teachingPendant())                  //有无示教器操作
    {
        var ans = inverseKinematics(nextT); //逆运动学求解
        if (ans.Count > 0)
        {
            var cnt = chooseBest(ans);      //选择最优解
            moveJ(ans[cnt].data);           //通过轴动实现运动
        }
    }
}

其中updateUI函数是读取变量并更新到UI界面上;teachingPendant函数是判断有无键鼠操作,有操作修改下一帧的T,无操作返回false;chooseBest函数是从8组解中选择与当前关节角度最接近的解。
参考:unity制作机械臂

三、结果展示

3.1 正移动学

请添加图片描述

3.2 逆移动学

  初版代码有bug,导致有时关节直接进行转跳,后来采用double的高精度浮点型数据类型进行计算可以避免bug。
请添加图片描述

四、原理解释

不同的坐标系和参数算出来的结果都不一样,下面的符号只适用于本文的情况进行推导,其中的区别是unity用的是左手坐标系y轴朝上,教程是右手坐标系z轴朝上。
参考:[机器人工程师进阶之路(二)6轴机械臂D-H法建模UR机械臂正逆运动学求解]。

4.1 符号解释

  • T i T_{i} Ti表示从 i − 1 i-1 i1个坐标系变换到 i i i个坐标系的变换矩阵。
  • 定义所有的y轴与关节活动处的圆形平面垂直
  • α i \alpha_{i} αi表示从 i − 1 i-1 i1个坐标系的y轴(yoz平面)绕其x轴旋转多少度能得到 i i i个坐标系的y轴(yoz平面)
  • θ i \theta_{i} θi表示 i i i个关节的转动角度。
  • o f f s e t i offset_{i} offseti表示对 i i i个关节的补偿角度。
  • d i d_{i} di表示从 i − 1 i-1 i1个坐标系的原点沿其y轴平移多少距离能得到 i i i个坐标系的原点
  • a i a_{i} ai表示从 i − 1 i-1 i1个坐标系的原点沿其z轴平移多少距离能得到 i i i个坐标系的原点
  • Rx,Ry,Rz表示旋转矩阵,tx,ty,tz表示平移矩阵。
  • s i n ( θ 1 ) sin(\theta_{1}) sin(θ1)简化为s1,将 c o s ( θ 1 ) cos(\theta_{1}) cos(θ1)简化为c1,其他下标依次类推。

4.2 正运动学

重新推导变换矩阵为:
T i = R y ∗ t y ∗ R x ∗ t z = [ c o s ( θ ) s i n ( θ ) s i n ( α ) s i n ( θ ) c o s ( α ) z ∗ s i n ( θ ) c o s ( α ) 0 c o s ( α ) − s i n ( α ) − z ∗ s i n ( α ) + y − s i n ( θ ) c o s ( θ ) s i n ( α ) c o s ( θ ) c o s ( α ) z ∗ c o s ( θ ) c o s ( α ) 0 0 0 1 ] T_{i}=Ry*ty*Rx*tz= \begin{bmatrix} cos(\theta) & sin(\theta)sin(\alpha) & sin(\theta)cos(\alpha) & z*sin(\theta)cos(\alpha)\\ 0 & cos(\alpha) & -sin(\alpha) & -z*sin(\alpha)+y\\ -sin(\theta) & cos(\theta)sin(\alpha) & cos(\theta)cos(\alpha) & z*cos(\theta)cos(\alpha)\\ 0 & 0 & 0 & 1 \end{bmatrix} Ti=RytyRxtz= cos(θ)0sin(θ)0sin(θ)sin(α)cos(α)cos(θ)sin(α)0sin(θ)cos(α)sin(α)cos(θ)cos(α)0zsin(θ)cos(α)zsin(α)+yzcos(θ)cos(α)1
绘制参数表格:

i α \alpha α(x轴) θ \theta θ(y轴)d(y轴)a(z轴)offset(y轴)
190j11.2200
20j20-4.070
30j30-3.770
4-90j41.2100
590j51.0300
60j60.9500

将每个变量代入得:
T 1 = [ c 1 s 1 0 0 0 0 − 1 d 1 − s 1 c 1 0 0 0 0 0 1 ] , T 2 = [ c 2 0 s 2 a 2 ∗ s 2 0 1 0 0 − s 2 0 c 2 a 2 ∗ c 2 0 0 0 1 ] , T 3 = [ c 3 0 s 3 a 3 ∗ s 3 0 1 0 0 − s 3 0 c 3 a 3 ∗ c 3 0 0 0 1 ] , T 4 = [ c 4 − s 4 0 0 0 0 1 d 4 − s 4 − c 4 0 0 0 0 0 1 ] , T 5 = [ c 5 s 5 0 0 0 0 − 1 d 5 − s 5 c 5 0 0 0 0 0 1 ] , T 6 = [ c 6 0 s 6 0 0 1 0 d 6 − s 6 0 c 6 0 0 0 0 1 ] T_{1}= \begin{bmatrix} c1 & s1& 0 & 0\\ 0 & 0 & -1 & d1\\ -s1 & c1& 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}, T_{2}= \begin{bmatrix} c2& 0 & s2 & a2*s2\\ 0 & 1 & 0 & 0\\ -s2 & 0 & c2 & a2*c2\\ 0 & 0 & 0 & 1 \end{bmatrix}, T_{3}= \begin{bmatrix} c3& 0 & s3 & a3*s3\\ 0 & 1 & 0 & 0\\ -s3 & 0 & c3 & a3*c3\\ 0 & 0 & 0 & 1 \end{bmatrix}, T_{4}= \begin{bmatrix} c4& -s4& 0 & 0\\ 0 & 0 & 1 & d4\\ -s4 & -c4& 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}, T_{5}= \begin{bmatrix} c5 & s5 & 0 & 0\\ 0 & 0 & -1 & d5\\ -s5 & c5 & 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}, T_{6}= \begin{bmatrix} c6 & 0 & s6 & 0\\ 0 & 1 & 0 & d6\\ -s6 & 0 & c6 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} T1= c10s10s10c1001000d101 T2= c20s200100s20c20a2s20a2c21 T3= c30s300100s30c30a3s30a3c31 T4= c40s40s40c4001000d401 T5= c50s50s50c5001000d501 T6= c60s600100s60c600d601
设T为:
T = [ n x o x a x p x n y o y a y p y n z o z a z p z 0 0 0 1 ] T= \begin{bmatrix} nx & ox & ax & px \\ ny & oy & ay & py \\ nz & oz & az & pz \\ 0 & 0 & 0 & 1 \end{bmatrix} T= nxnynz0oxoyoz0axayaz0pxpypz1
正运动学公式为
T = T 1 T 2 T 3 T 4 T 5 T 6 T=T_{1}T_{2}T_{3}T_{4}T_{5}T_{6} T=T1T2T3T4T5T6

4.3 逆运动学

4.3.1 求解156轴

这个公式成立:
T 1 − 1 T T 6 − 1 = T 2 T 3 T 4 T 5 T_{1}^{-1}TT_{6}^{-1}=T_{2}T_{3}T_{4}T_{5} T11TT61=T2T3T4T5
其中1和6的逆为:
T 1 − 1 = [ c 1 0 − s 1 0 s 1 0 c 1 0 0 − 1 0 d 1 0 0 0 1 ] , T 6 − 1 = [ c 6 0 − s 6 0 0 1 0 − d 6 s 6 0 c 6 0 0 0 0 1 ] T_{1}^{-1}= \begin{bmatrix} c1&0&-s1&0\\ s1&0&c1&0\\ 0&-1&0&d1\\ 0&0&0&1 \end{bmatrix}, T_{6}^{-1}= \begin{bmatrix} c6&0&-s6&0\\ 0&1&0&-d6\\ s6&0&c6&0\\ 0&0&0&1 \end{bmatrix} T11= c1s1000010s1c10000d11 T61= c60s600100s60c600d601

左边等于:
T 1 − 1 T T 6 − 1 = [ ( c 1 ∗ n x − n z ∗ s 1 ) ∗ c 6 + s 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ( c 1 ∗ o x − o z ∗ s 1 ) − ( c 1 ∗ n x − n z ∗ s 1 ) ∗ s 6 + c 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) − d 6 ∗ ( c 1 ∗ o x − o z ∗ s 1 ) + ( c 1 ∗ p x − p z ∗ s 1 ) ( s 1 ∗ n x + n z ∗ c 1 ) ∗ c 6 + s 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) ( s 1 ∗ o x + o z ∗ c 1 ) − ( s 1 ∗ n x + n z ∗ c 1 ) ∗ s 6 + c 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) − d 6 ∗ ( s 1 ∗ o x + o z ∗ c 1 ) + ( s 1 ∗ p x + p z ∗ c 1 ) − n y ∗ c 6 − a y ∗ s 6 − o y n y ∗ s 6 − a y ∗ c 6 o y ∗ d 6 − p y + d 1 0 0 0 1 ] T_{1}^{-1}TT_{6}^{-1}= \begin{bmatrix} (c1*nx-nz*s1)*c6+s6*(c1*ax-az*s1)&(c1*ox-oz*s1)&-(c1*nx-nz*s1)*s6+c6*(c1*ax-az*s1)&-d6*(c1*ox-oz*s1)+(c1*px-pz*s1)\\ (s1*nx+nz*c1)*c6+s6*(s1*ax+az*c1)&(s1*ox+oz*c1)&-(s1*nx+nz*c1)*s6+c6*(s1*ax+az*c1)&-d6*(s1*ox+oz*c1)+(s1*px+pz*c1)\\ -ny*c6-ay*s6&-oy&ny*s6-ay*c6&oy*d6-py+d1\\ 0&0&0&1 \end{bmatrix} T11TT61= (c1nxnzs1)c6+s6(c1axazs1)(s1nx+nzc1)c6+s6(s1ax+azc1)nyc6ays60(c1oxozs1)(s1ox+ozc1)oy0(c1nxnzs1)s6+c6(c1axazs1)(s1nx+nzc1)s6+c6(s1ax+azc1)nys6ayc60d6(c1oxozs1)+(c1pxpzs1)d6(s1ox+ozc1)+(s1px+pzc1)oyd6py+d11
右边等于:
T 2 T 3 T 4 T 5 = [ c 234 ∗ c 5 c 234 ∗ s 5 s 234 − s 234 ∗ d 5 + a 3 ∗ s 23 + a 2 ∗ s 2 − s 5 c 5 0 d 4 − s 234 ∗ c 5 − s 234 ∗ s 5 c 234 − c 234 ∗ d 5 + a 3 ∗ c 23 + a 2 ∗ c 2 0 0 0 1 ] T_{2}T_{3}T_{4}T_{5}= \begin{bmatrix} c234*c5& c234*s5 & s234 & -s234*d5+a3*s23+a2*s2\\ -s5 & c5 & 0 & d4\\ -s234*c5 & -s234*s5 & c234 & -c234*d5+a3*c23+a2*c2\\ 0 & 0 & 0 & 1 \end{bmatrix} T2T3T4T5= c234c5s5s234c50c234s5c5s234s50s2340c2340s234d5+a3s23+a2s2d4c234d5+a3c23+a2c21
其中有3条方程为:
{ − d 6 ∗ ( s 1 ∗ o x + o z ∗ c 1 ) + ( s 1 ∗ p x + p z ∗ c 1 ) = d 4           ① ( s 1 ∗ o x + o z ∗ c 1 ) = c 5                                                          ② ( s 1 ∗ n x + n z ∗ c 1 ) ∗ c 6 + s 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) = − s 5  ③ \left\{\begin{matrix} -d6*(s1*ox+oz*c1)+(s1*px+pz*c1)=d4 \text{ } \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }①\\ (s1*ox+oz*c1)=c5 \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }②\\ (s1*nx+nz*c1)*c6+s6*(s1*ax+az*c1)=-s5\text{ }③\\ \end{matrix}\right. d6(s1ox+ozc1)+(s1px+pzc1)=d4          (s1ox+ozc1)=c5                                                         (s1nx+nzc1)c6+s6(s1ax+azc1)=s5 


根据①式解得: θ 1 = a r c t a n 2 ( m 1 , n 1 ) − a r c t a n 2 ( d 4 , ± m 1 2 + n 1 2 − d 4 2 ) \theta_{1}=arctan2(m_{1},n_{1})-arctan2(d4,\pm \sqrt{m_{1}^{2}+n_{1}^{2}-d_{4}^{2}} ) θ1=arctan2(m1,n1)arctan2(d4,±m12+n12d42 )
其中 m 1 = p z − d 6 ∗ o z , n 1 = d 6 ∗ o x − p x m_{1}=pz-d6*oz,n_{1}=d6*ox-px m1=pzd6ozn1=d6oxpx
* θ 1 \theta_{1} θ1有两个解,得到两组解。


根据②式解得: θ 5 = ± a r c c o s ( s 1 ∗ o x + o z ∗ c 1 ) \theta_{5}=\pm arccos(s1*ox+oz*c1) θ5=±arccos(s1ox+ozc1)
* θ 5 \theta_{5} θ5有两个解,得到四组解。


根据③式解得: θ 6 = a r c t a n 2 ( m 2 , n 2 ) + a r c t a n 2 ( 0 , − s 5 ) \theta_{6}=arctan2(m_{2},n_{2})+arctan2(0,-s5) θ6=arctan2(m2,n2)+arctan2(0,s5)
其中 m 2 = s 1 ∗ a x + a z ∗ c 1 , n 2 = s 1 ∗ n x + n z ∗ c 1 m_{2}=s1*ax+az*c1,n_{2}=s1*nx+nz*c1 m2=s1ax+azc1n2=s1nx+nzc1
*arctan2(0,-s5)根据第5个轴的正负使其相差180°。


4.3.2 求解234轴

这个公式成立:
T 1 − 1 T T 6 − 1 T 5 − 1 = T 2 T 3 T 4 T_{1}^{-1}TT_{6}^{-1}T_{5}^{-1}=T_{2}T_{3}T_{4} T11TT61T51=T2T3T4
其中5的逆为:
T 5 − 1 = [ c 5 0 − s 5 0 s 5 0 c 5 0 0 − 1 0 d 5 0 0 0 1 ] T_{5}^{-1}= \begin{bmatrix} c5&0&-s5&0\\ s5&0&c5&0\\ 0&-1&0&d5\\ 0&0&0&1 \end{bmatrix} T51= c5s5000010s5c50000d51

左边等于:
T 1 − 1 T T 6 − 1 T 5 − 1 = [ ( ( c 1 ∗ n x − n z ∗ s 1 ) ∗ c 6 + s 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ) ∗ c 5 + s 5 ∗ ( c 1 ∗ o x − o z ∗ s 1 ) ( c 1 ∗ n x − n z ∗ s 1 ) ∗ s 6 − c 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ( ( c 1 ∗ n x − n z ∗ s 1 ) ∗ c 6 + s 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ) ∗ ( − s 5 ) + c 5 ∗ ( c 1 ∗ o x − o z ∗ s 1 ) d 5 ∗ ( − ( c 1 ∗ n x − n z ∗ s 1 ) ∗ s 6 + c 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ) − d 6 ∗ ( c 1 ∗ o x − o z ∗ s 1 ) + ( c 1 ∗ p x − p z ∗ s 1 ) ( ( s 1 ∗ n x + n z ∗ c 1 ) ∗ c 6 + s 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) ) ∗ c 5 + s 5 ∗ ( s 1 ∗ o x + o z ∗ c 1 ) ( s 1 ∗ n x + n z ∗ c 1 ) ∗ s 6 − c 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) ( ( s 1 ∗ n x + n z ∗ c 1 ) ∗ c 6 + s 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) ) ∗ ( − s 5 ) + c 5 ∗ ( s 1 ∗ o x + o z ∗ c 1 ) d 5 ∗ ( − ( s 1 ∗ n x + n z ∗ c 1 ) ∗ s 6 + c 6 ∗ ( s 1 ∗ a x + a z ∗ c 1 ) ) − d 6 ∗ ( s 1 ∗ o x + o z ∗ c 1 ) + ( s 1 ∗ p x + p z ∗ c 1 ) ( − n y ∗ c 6 − a y ∗ s 6 ) ∗ c 5 + s 5 ∗ ( − o y ) − ( n y ∗ s 6 − a y ∗ c 6 ) ( − n y ∗ c 6 − a y ∗ s 6 ) ∗ ( − s 5 ) + c 5 ∗ ( − o y ) d 5 ∗ ( n y ∗ s 6 − a y ∗ c 6 ) + o y ∗ d 6 − p y + d 1 0 0 0 1 ] T_{1}^{-1}TT_{6}^{-1}T_{5}^{-1}= \begin{bmatrix} ((c1*nx-nz*s1)*c6+s6*(c1*ax-az*s1))*c5+s5*(c1*ox-oz*s1)&(c1*nx-nz*s1)*s6-c6*(c1*ax-az*s1)&((c1*nx-nz*s1)*c6+s6*(c1*ax-az*s1))*(-s5)+c5*(c1*ox-oz*s1)&d5*(-(c1*nx-nz*s1)*s6+c6*(c1*ax-az*s1))-d6*(c1*ox-oz*s1)+(c1*px-pz*s1)\\ ((s1*nx+nz*c1)*c6+s6*(s1*ax+az*c1))*c5+s5*(s1*ox+oz*c1)&(s1*nx+nz*c1)*s6-c6*(s1*ax+az*c1)&((s1*nx+nz*c1)*c6+s6*(s1*ax+az*c1))*(-s5)+c5*(s1*ox+oz*c1)&d5*(-(s1*nx+nz*c1)*s6+c6*(s1*ax+az*c1))-d6*(s1*ox+oz*c1)+(s1*px+pz*c1)\\ (-ny*c6-ay*s6)*c5+s5*(-oy)&-(ny*s6-ay*c6)&(-ny*c6-ay*s6)*(-s5)+c5*(-oy)&d5*(ny*s6-ay*c6)+oy*d6-py+d1\\ 0&0&0&1 \end{bmatrix} T11TT61T51= ((c1nxnzs1)c6+s6(c1axazs1))c5+s5(c1oxozs1)((s1nx+nzc1)c6+s6(s1ax+azc1))c5+s5(s1ox+ozc1)(nyc6ays6)c5+s5(oy)0(c1nxnzs1)s6c6(c1axazs1)(s1nx+nzc1)s6c6(s1ax+azc1)(nys6ayc6)0((c1nxnzs1)c6+s6(c1axazs1))(s5)+c5(c1oxozs1)((s1nx+nzc1)c6+s6(s1ax+azc1))(s5)+c5(s1ox+ozc1)(nyc6ays6)(s5)+c5(oy)0d5((c1nxnzs1)s6+c6(c1axazs1))d6(c1oxozs1)+(c1pxpzs1)d5((s1nx+nzc1)s6+c6(s1ax+azc1))d6(s1ox+ozc1)+(s1px+pzc1)d5(nys6ayc6)+oyd6py+d11
右边等于:
T 2 T 3 T 4 = [ c 234 − s 234 0 a 3 ∗ s 23 + a 2 ∗ s 2 0 0 1 d 4 − s 234 − c 234 0 a 3 ∗ c 23 + a 2 ∗ c 2 0 0 0 1 ] T_{2}T_{3}T_{4}= \begin{bmatrix} c234& -s234 & 0 & a3*s23+a2*s2\\ 0 & 0 & 1 & d4\\ -s234 & -c234 & 0 & a3*c23+a2*c2\\ 0 & 0 & 0 & 1 \end{bmatrix} T2T3T4= c2340s2340s2340c23400100a3s23+a2s2d4a3c23+a2c21
其中有4条方程为:
{ d 5 ∗ ( − ( c 1 ∗ n x − n z ∗ s 1 ) ∗ s 6 + c 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ) − d 6 ∗ ( c 1 ∗ o x − o z ∗ s 1 ) + ( c 1 ∗ p x − p z ∗ s 1 ) = a 3 ∗ s 23 + a 2 ∗ s 2 ④ d 5 ∗ ( n y ∗ s 6 − a y ∗ c 6 ) + o y ∗ d 6 − p y + d 1 = a 3 ∗ c 23 + a 2 ∗ c 2                                                                                                         ⑤ − s 234 = ( − n y ∗ c 6 − a y ∗ s 6 ) ∗ c 5 + s 5 ∗ ( − o y )                                                                                                                                     ⑥ − c 234 = − ( n y ∗ s 6 − a y ∗ c 6 )                                                                                                                                                                   ⑦ \left\{\begin{matrix} d5*(-(c1*nx-nz*s1)*s6+c6*(c1*ax-az*s1))-d6*(c1*ox-oz*s1)+(c1*px-pz*s1)=a3*s23+a2*s2④\\ d5*(ny*s6-ay*c6)+oy*d6-py+d1=a3*c23+a2*c2\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }⑤\\ -s234=(-ny*c6-ay*s6)*c5+s5*(-oy)\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }⑥\\ -c234=-(ny*s6-ay*c6)\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }⑦\\ \end{matrix}\right. d5((c1nxnzs1)s6+c6(c1axazs1))d6(c1oxozs1)+(c1pxpzs1)=a3s23+a2s2④d5(nys6ayc6)+oyd6py+d1=a3c23+a2c2                                                                                                        s234=(nyc6ays6)c5+s5(oy)                                                                                                                                    c234=(nys6ayc6)                                                                                                                                                                  


根据④⑤式解得: θ 3 = ± a r c c o s ( m 3 2 + n 3 2 − a 2 2 − a 3 2 2 ∗ a 2 ∗ a 3 ) \theta_{3}=\pm arccos(\frac{m_{3}^{2}+n_{3}^{2}-a2^{2}-a3^{2}}{2*a2*a3}) θ3=±arccos(2a2a3m32+n32a22a32)
其中 m 3 = d 5 ∗ ( − ( c 1 ∗ n x − n z ∗ s 1 ) ∗ s 6 + c 6 ∗ ( c 1 ∗ a x − a z ∗ s 1 ) ) − d 6 ∗ ( c 1 ∗ o x − o z ∗ s 1 ) + ( c 1 ∗ p x − p z ∗ s 1 ) , n 3 = d 5 ∗ ( n y ∗ s 6 − a y ∗ c 6 ) + o y ∗ d 6 − p y + d 1 m_{3}=d5*(-(c1*nx-nz*s1)*s6+c6*(c1*ax-az*s1))-d6*(c1*ox-oz*s1)+(c1*px-pz*s1),n_{3}=d5*(ny*s6-ay*c6)+oy*d6-py+d1 m3=d5((c1nxnzs1)s6+c6(c1axazs1))d6(c1oxozs1)+(c1pxpzs1)n3=d5(nys6ayc6)+oyd6py+d1
* θ 3 \theta_{3} θ3有两个解,得到八组解。但 m 3 2 + n 3 2 − a 2 2 − a 3 2 2 ∗ a 2 ∗ a 3 > 1 \frac{m_{3}^{2}+n_{3}^{2}-a2^{2}-a3^{2}}{2*a2*a3}>1 2a2a3m32+n32a22a32>1,使某几组解解不出???最终解为2组的概率为24.5%,为4组的概率为73.2%,为6组的概率为1.7%,为8组的概率为0.6%。


根据④⑤式解得: θ 2 = a r c t a n 2 ( s 2 , c 2 ) \theta_{2}=arctan2(s2,c2) θ2=arctan2(s2,c2)
其中 s 2 = ( a 3 ∗ c 3 + a 2 ) ∗ m 3 − a 3 ∗ s 3 ∗ n 3 a 2 2 + a 3 2 + 2 ∗ a 2 ∗ a 3 ∗ c 3 , c 2 = n 3 + a 3 ∗ s 3 ∗ s 2 a 3 ∗ c 3 + a 2 s2=\frac{(a3*c3+a2)*m_{3}-a3*s3*n_{3}}{a2^{2}+a3^{2}+2*a2*a3*c3} ,c2=\frac{n_{3}+a3*s3*s2}{a3*c3+a2} s2=a22+a32+2a2a3c3(a3c3+a2)m3a3s3n3c2=a3c3+a2n3+a3s3s2


根据⑥⑦式解得: θ 4 = a r c t a n 2 ( m 4 , n 4 ) − θ 2 − θ 3 \theta_{4}=arctan2(m_{4},n_{4})-\theta_{2}-\theta_{3} θ4=arctan2(m4,n4)θ2θ3
其中 m 4 = ( − n y ∗ c 6 − a y ∗ s 6 ) ∗ ( − c 5 ) + s 5 ∗ o y , n 4 = ( n y ∗ s 6 − a y ∗ c 6 ) m_{4}=(-ny*c6-ay*s6)*(-c5)+s5*oy,n_{4}=(ny*s6-ay*c6) m4=(nyc6ays6)(c5)+s5oyn4=(nys6ayc6)


4.4 用python进行验证

import numpy as np
def eulerAnglesToRotationMatrix(alpha,theta,beta,x,y,z):
    alpha = alpha/180.0*np.pi
    theta = theta/180.0*np.pi
    beta = beta/180.0*np.pi
    Rx=np.array([
       [1, 0,             0,              0],
       [0, np.cos(alpha), -np.sin(alpha), 0],
       [0, np.sin(alpha), np.cos(alpha),  0],
       [0, 0,             0,              1]
    ])
    Ry=np.array([
       [np.cos(theta),  0, np.sin(theta), 0],
       [0,              1,             0, 0],
       [-np.sin(theta), 0, np.cos(theta), 0],
       [0,              0,             0, 1]
    ])
    Rz=np.array([
       [np.cos(beta), -np.sin(beta), 0, 0],
       [np.sin(beta), np.cos(beta),  0, 0],
       [0,             0,              1, 0],
       [0,             0,              0, 1]
    ])
    Tx=np.array([
       [1, 0, 0, x],
       [0, 1, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 1]
    ])
    Ty=np.array([
       [1, 0, 0, 0],
       [0, 1, 0, y],
       [0, 0, 1, 0],
       [0, 0, 0, 1]
    ])
    Tz=np.array([
       [1, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 0, 1, z],
       [0, 0, 0, 1]
    ])
    return Ry@Ty@Rx@Tx@Rz@Tz
pq = lambda x: 180 - (180 - x) % 360
pr = lambda x: print(np.round(x,4))
num_ans = []
for epoch in range(10):
    #======================init=======================
    a = [0,-4.07,-3.77,0,0,0]
    d = [1.22,0,0,1.21,1.03,0.95]
    d1,a2,a3,d4,d5,d6 = d[0],a[1],a[2],d[3],d[4],d[5]
    theta = (np.random.rand(6)*2-1)*180/np.pi
    #====================forward======================
    T = np.eye(4)
    T = T@eulerAnglesToRotationMatrix(90,theta[0],0,0,d[0],a[0])
    T = T@eulerAnglesToRotationMatrix(0,theta[1],0,0,d[1],a[1])
    T = T@eulerAnglesToRotationMatrix(0,theta[2],0,0,d[2],a[2])
    T = T@eulerAnglesToRotationMatrix(-90,theta[3],0,0,d[3],a[3])
    T = T@eulerAnglesToRotationMatrix(90,theta[4],0,0,d[4],a[4])
    T = T@eulerAnglesToRotationMatrix(0,theta[5],0,0,d[5],a[5])
    (nx,ox,ax,px),(ny,oy,ay,py),(nz,oz,az,pz),_= T
    print("6个关节旋转的角度:",np.round(theta,4))
    print("===>正运动学解:\n",np.round(T,4))
    #======================156轴=======================
    ans = np.zeros((8,6))
    m1 = pz-d6*oz
    n1 = d6*ox-px
    ans[0:4,0]=np.arctan2(m1,n1)-np.arctan2(d4,(m1**2+n1**2-d4**2)**0.5)
    ans[4:8,0]=np.arctan2(m1,n1)-np.arctan2(d4,-(m1**2+n1**2-d4**2)**0.5)
    s1 = np.sin(ans[:,0])
    c1 = np.cos(ans[:,0])
    # pr(-d6*(s1*ox+oz*c1)+(s1*px+pz*c1)-d4)
    ans[0:2,4]=np.arccos(s1[0:2]*ox+oz*c1[0:2])
    ans[2:4,4]=-np.arccos(s1[2:4]*ox+oz*c1[2:4])
    ans[4:6,4]=np.arccos(s1[4:6]*ox+oz*c1[4:6])
    ans[6:8,4]=-np.arccos(s1[6:8]*ox+oz*c1[6:8])
    s5 = np.sin(ans[:,4])
    c5 = np.cos(ans[:,4])
    # pr(s1*ox+oz*c1-c5)
    m2 = s1*ax+az*c1
    n2 = s1*nx+nz*c1
    ans[:,5]=np.arctan2(m2,n2)+np.arctan2(0,-s5)
    s6 = np.sin(ans[:,5])
    c6 = np.cos(ans[:,5])
    # pr(n*c6+s6*m+s5)
    #======================234轴=======================
    m3 = d5*(-(c1*nx-nz*s1)*s6+c6*(c1*ax-az*s1))-d6*(c1*ox-oz*s1)+(c1*px-pz*s1)
    n3 = d5*(ny*s6-ay*c6)+oy*d6-py+d1
    ans[0::2,2] = np.arccos(np.clip((m3[0::2]**2+n3[0::2]**2-a2**2-a3**2)/(2*a2*a3), -1, 1))
    ans[1::2,2] = -np.arccos(np.clip((m3[1::2]**2+n3[1::2]**2-a2**2-a3**2)/(2*a2*a3), -1, 1))
    s3 = np.sin(ans[:,2])
    c3 = np.cos(ans[:,2])
    s2 = ((a3*c3+a2)*m3-a3*s3*n3)/(a2**2+a3**2+2*a2*a3*c3)
    c2 = (n3+a3*s3*s2)/(a3*c3+a2)
    ans[:,1]=np.arctan2(s2,c2)
    m4=(-ny*c6-ay*s6)*(-c5)+s5*oy
    n4=(ny*s6-ay*c6)
    ans[:,3]=np.arctan2(m4,n4)-ans[:,1]-ans[:,2]
    #======================验证========================
    print("===>逆运动学解: ")
    cnt=0
    for theta_ans in ans:
        theta_ans = theta_ans*180.0/np.pi
        t1 = eulerAnglesToRotationMatrix(90,theta_ans[0],0,0,d[0],a[0])
        t2 = eulerAnglesToRotationMatrix(0,theta_ans[1],0,0,d[1],a[1])
        t3 = eulerAnglesToRotationMatrix(0,theta_ans[2],0,0,d[2],a[2])
        t4 = eulerAnglesToRotationMatrix(-90,theta_ans[3],0,0,d[3],a[3])
        t5 = eulerAnglesToRotationMatrix(90,theta_ans[4],0,0,d[4],a[4])
        t6 = eulerAnglesToRotationMatrix(0,theta_ans[5],0,0,d[5],a[5])
        if np.all(np.isclose(t1@t2@t3@t4@t5@t6,T)):
            pr(pq(theta_ans))
            cnt+=1
    print("="*64)
    num_ans.append(cnt)
print(np.unique(num_ans,return_counts=True))

代码实现了:随机给定一组6轴关节旋转角度,根据正运动学解得末端位置坐标系相对于参考坐标系的变换矩阵;给定变换矩阵,根据逆运动学解得6轴关节旋转角度。具体结果如下图所示:

在这里插入图片描述

*注意区分角度和弧度,以上结果均为角度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值