第一次接触ABB的IRB 1600-6/1.45机器人时,我被要求解决一个实际问题:如何根据已知的笛卡尔空间坐标点,反推出机器人各个关节的状态。这个问题在工业自动化领域非常常见,比如在焊接、装配等应用中,我们需要精确控制机器人末端执行器的位置和姿态。
IRB 1600-6/1.45是ABB的一款6轴工业机器人,最大负载1.45kg,工作半径1.6米。要解决这个问题,首先需要获取正确的机器人运动学参数。这里就涉及到DH(Denavit-Hartenberg)参数,更准确地说,是改进DH(Modified DH,简称MDH)参数。
在实际项目中,我发现直接从ABB官方文档获取的DH参数并不完全准确,特别是在空间位置计算上存在偏差。经过多次尝试和验证,最终通过其他途径获得了正确的MDH参数。这个经历让我深刻体会到:机器人运动学参数的准确性直接决定了后续正解(Forward Kinematics,FK)和逆解(Inverse Kinematics,IK)计算的可靠性。
刚开始接触机器人运动学时,我经常混淆标准DH和改进DH参数。经过多次实践,我总结出它们的主要区别:
对于ABB机器人,特别是IRB 1600-6/1.45,使用改进DH参数能获得更准确的计算结果。我收集到的该型号的MDH参数如下:
| 关节 | α(i-1) | a(i-1) | d(i) | θ(i) |
|---|---|---|---|---|
| 1 | 0° | 0 | d1 | θ1 |
| 2 | -90° | a1 | 0 | θ2 |
| 3 | 0° | -a2 | 0 | θ3 |
| 4 | 90° | 0 | d4 | θ4 |
| 5 | -90° | 0 | 0 | θ5 |
| 6 | 90° | 0 | d6 | θ6 |
获取参数后,我进行了严格的验证。首先在RobotStudio中随机选取几个位姿,记录下关节角度和末端位姿。然后使用MDH参数编写正解计算程序,将关节角度转换为末端位姿,与RobotStudio的记录进行对比。
验证过程中发现,最初的参数在欧拉角计算上是正确的,但空间位置存在偏差。经过多次调整和测试,最终确定了正确的参数值。这个过程让我明白:机器人参数验证不能只看部分结果,必须进行全面的位姿验证。
根据改进DH参数,每个关节的变换矩阵可以表示为:
cpp复制Eigen::Matrix4d dh_matrix(double alpha, double a, double d, double theta) {
Eigen::Matrix4d T;
T << cos(theta), -sin(theta), 0, a,
sin(theta)*cos(alpha), cos(theta)*cos(alpha), -sin(alpha), -sin(alpha)*d,
sin(theta)*sin(alpha), cos(theta)*sin(alpha), cos(alpha), cos(alpha)*d,
0, 0, 0, 1;
return T;
}
对于IRB 1600-6/1.45机器人,完整的正解计算就是将6个关节的变换矩阵按顺序相乘:
cpp复制vector<double> fk_robot(vector<double> joints_alpha, vector<double> joints_a,
vector<double> joints_d, vector<double> joints_theta) {
Eigen::Matrix4d T = Eigen::Matrix4d::Identity();
for (int i = 0; i < 6; i++) {
T = T * dh_matrix(joints_alpha[i]*M_PI/180.0, joints_a[i],
joints_d[i], joints_theta[i]*M_PI/180.0);
}
// 提取位置和欧拉角
vector<double> pose(6);
pose[0] = T(0,3); // x
pose[1] = T(1,3); // y
pose[2] = T(2,3); // z
// 旋转矩阵转欧拉角(ZYX顺序)
double sy = sqrt(T(0,0)*T(0,0) + T(1,0)*T(1,0));
pose[3] = atan2(T(2,1), T(2,2)) * 180.0/M_PI; // A
pose[4] = atan2(-T(2,0), sy) * 180.0/M_PI; // B
pose[5] = atan2(T(1,0), T(0,0)) * 180.0/M_PI; // C
return pose;
}
在RobotStudio中验证正解时,我总结了几个实用技巧:
对于6轴串联机器人,逆解通常有8组解(不考虑关节限位)。我采用了几何法求解IRB 1600-6/1.45的逆解,主要步骤如下:
cpp复制vector<vector<double>> ik_robot(Eigen::Matrix4d trans) {
vector<vector<double>> solutions;
// 1. 提取位置和姿态
Eigen::Vector3d p = trans.block<3,1>(0,3);
Eigen::Matrix3d R = trans.block<3,3>(0,0);
// 2. 计算腕部中心点
Eigen::Vector3d wrist_center = p - d6 * R.col(2);
// 3. 求解前三个关节
double theta1_1 = atan2(wrist_center[1], wrist_center[0]);
double theta1_2 = theta1_1 + M_PI;
// 这里简化处理,实际需要完整推导
// ...
// 4. 对每组前三个关节解,计算后三个关节
for (auto &theta123 : theta123_solutions) {
// 计算T03
Eigen::Matrix4d T03 = /*...*/;
// 计算T36 = inv(T03)*T06
Eigen::Matrix4d T36 = T03.inverse() * trans;
// 从T36提取欧拉角得到theta4,5,6
// ...
solutions.push_back({theta1, theta2, theta3, theta4, theta5, theta6});
}
return solutions;
}
逆解验证比正解更复杂,需要注意:
在RobotStudio中验证FK/IK计算结果的步骤如下:
通过多组数据验证,发现:
验证过程中还发现,机器人的实际零位与理论模型可能存在微小差异,这在实际应用中需要考虑。
在完成这个项目后,我总结了几个实用经验:
在实际项目中,我还发现有时候需要根据具体任务选择最合适的逆解,而不仅仅是数学上的解。例如,在连续路径规划中,应该选择与上一状态最接近的解,以减少关节的剧烈运动。