采用修正DH参数推导三菱6轴机械手逆运动学求解及c#程序

采用修正DH参数推导三菱6轴机械手逆运动学求解及c#程序

编码文章call10242025-05-12 11:13:5812A+A-

我现在正在SolidWorks中开发工业机械手动作及CT模拟的功能插件。目前实现在SolidWorks中获取机械手坐标信息,然后与三菱、爱普生品牌机械手仿真软件通信,仿真软件后台根据坐标点数据运算并反馈结果到SolidWorks中。功能基本实现,但是现在在SolidWorks中的坐标目前都是以关节坐标表示的。在SolidWorks中调试不太方便,所以研究了一下采用世界坐标参数的方法,需要用到机械手逆解方法,特记录一下逆解计算过程。

本逆解以三菱RV-13FR机械手为例。

修正DH参数如下。具体DH参数这里就不做说明了。

RV-13FR

MDH




Joint

alpha[°]

a[mm]

d[mm]

theta[°]

J1

0

0

450

0

J2

-90

130

0

-90

J3

0

410

0

-90

J4

-90

65

550

0

J5

90

0

0

0

J6

-90

0

97

180

由于采用修正DH参数法,所以连杆变换矩阵如下。

带入DH参数可以得到:

由于: (1)

其中为已知

由等式(1)可以求得

通过,计算

,可求得

具体计算过程由于比较复杂,在此不能很好地表达。如有需要完整的计算过程可私信。

此计算有4个理论解。

可用C#代码如下,C#中矩阵运算需用到免费开源的MathNet.Numerics类.

public double[] IK_MI_MDH(double[] ptdata, double[] lastPt)
        {
            double[,] thetas = new double[8, 6];//4组解,每组解六个角
            double[] bestRst = new double[6];
            double x = ptdata[0] * 0.001;
            double y = ptdata[1] * 0.001;
            double z = ptdata[2] * 0.001;
            double nx = ptdata[3] / radToAgl;
            double ny = ptdata[4] / radToAgl;
            double nz = ptdata[5] / radToAgl;

            //1.计算末端旋转矩阵
            //Matrix<double> MR = ROT_z(nz) * ROT_y(ny) * ROT_x(nx);
            Matrix<double> MR = ROT_xyz(nx, ny, nz);
            Matrix<double> M6 = new DenseMatrix(4);
            M6.SetSubMatrix(0, 0, MR);
            M6.SetColumn(3, new double[] { x, y, z, 1 });

            //2.求解
            double wx, wy, wz;
            wx = x - MR[0, 2] * d[5];
            wy = y - MR[1, 2] * d[5];
            wz = z - MR[2, 2] * d[5];
            // theta1
            thetas[0, 0] = Math.Atan2(wy, wx);
            thetas[1, 0] = thetas[0, 0];
            thetas[2, 0] = thetas[0, 0];
            thetas[3, 0] = thetas[0, 0];
            //if (wy>=0)
            //{
            //    thetas[0, 0] = thetas[0, 0] - Math.PI;
            //}
            //else
            //{
            //    thetas[0, 0] = thetas[0, 0] + Math.PI;
            //}
            ////thetas[4, 0] = Math.Atan2(-wy , -wx );
            //thetas[1, 0] = thetas[4, 0];
            //thetas[2, 0] = thetas[4, 0];
            //thetas[3, 0] = thetas[4, 0];

            //theta3
            double k1 = d[0] - wz;
            double squ1 = a[3] * a[3] + d[3] * d[3];

            //thetas2
            for (int i = 0; i < 4; i += 2)
            {
                double k2 = wx * Math.Cos(thetas[i, 0]) + wy * Math.Sin(thetas[i, 0]) - a[1];
                double squ2 = k1 * k1 + k2 * k2;
                double k3 = (squ2 - a[2] * a[2] - squ1) / a[2] / 2;
                if (squ1 - k3 * k3 < 0)
                {
                    //无解
                    continue;
                }
                if (i % 4 == 0)
                {
                    thetas[i, 2] = Math.Atan2(a[3], d[3]) - Math.Atan2(k3, Math.Sqrt(squ1 - k3 * k3));
                    thetas[i + 1, 2] = thetas[i, 2];
                    thetas[i + 2, 2] = Math.Atan2(a[3], d[3]) - Math.Atan2(k3, -Math.Sqrt(squ1 - k3 * k3));
                    thetas[i + 3, 2] = thetas[i + 2, 2];
                }

                double k4 = Math.Cos(thetas[i, 2]) * d[3] + Math.Sin(thetas[i, 2]) * a[3];
                double k5 = Math.Cos(thetas[i, 2]) * a[3] - Math.Sin(thetas[i, 2]) * d[3] + a[2];
                thetas[i, 1] = Math.Atan2((k1 * k5 - k2 * k4) / squ2, (k1 * k4 + k2 * k5) / squ2);
                thetas[i + 1, 1] = thetas[i, 1];
            }

            //theta5、theta4、theta6
            for (int i = 0; i < 4; i++)
            {
                //求T1.T2.T3的逆矩阵
                Matrix<double> M1 = MDH_T(alpha[0] / radToAgl, a[0], d[0], thetas[i, 0]);
                Matrix<double> M2 = MDH_T(alpha[1] / radToAgl, a[1], d[1], thetas[i, 1]);
                Matrix<double> M3 = MDH_T(alpha[2] / radToAgl, a[2], d[2], thetas[i, 2]);
                Matrix<double> M321 = (M1 * M2 * M3).Inverse();
                //求M456
                Matrix<double> M456 = M321 * M6;
                //theta5
                if (i % 2 == 0)
                {
                    thetas[i, 4] = Math.Acos(M456[1, 2]);
                    thetas[i + 1, 4] = -Math.Acos(M456[1, 2]);
                }
                //theta5不能为0
                if (Math.Sin(thetas[i, 4]) != 0)
                {
                    //theta4
                    thetas[i, 3] = Math.Atan2(M456[2, 2] / Math.Sin(thetas[i, 4]), -M456[0, 2] / Math.Sin(thetas[i, 4]));
                    //theta6
                    thetas[i, 5] = Math.Atan2(-M456[1, 1] / Math.Sin(thetas[i, 4]), M456[1, 0] / Math.Sin(thetas[i, 4]));
                }
                else
                {
                    thetas[i, 3] = lastPt[3] / radToAgl;
                    thetas[i, 5] = Math.Atan2(-M456[0, 1] * Math.Cos(thetas[i, 3]) - M456[0, 0] * Math.Sin(thetas[i, 3]), M456[0, 0] * Math.Cos(thetas[i, 3]) - M456[0, 1] * Math.Sin(thetas[i, 3]));
                }
                double[] theta = new double[6];
                string outstr = "";
                for (int j = 0; j < 6; j++)
                {
                    thetas[i, j] = thetas[i, j] * radToAgl - th[j];
                    thetas[i, j] = angleModify(thetas[i, j]);
                    ////输出并检验
                    theta[j] = thetas[i, j];
                    outstr = outstr + "      θ" + (j + 1).ToString() + " = " + theta[j].ToString();
                }
                Debug.WriteLine("第" + (i + 1).ToString() + "组解:" + outstr);
                FK(theta);
            }
            bestRst=IKRusltSelect_MI_MDH(thetas, lastPt);
            return bestRst;
        }

第一次在网上发文章。。。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4