ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ABB机器人四元数与欧拉角转换实战:从原理到RAPID代码

ABB机器人四元数与欧拉角转换实战:从原理到RAPID代码 1. 为什么说姿态表示是ABB机器人调试里绕不过去的坎干ABB机器人调试的兄弟十有八九都遇到过这种场景示教器上手改个姿态看着是数字心里想的却是法兰盘到底朝哪边从第三方软件算出一组四元数死活填不进MoveL指令里或者姿态稍微转个角度机器人直接给你报一个“奇异点”警告现场一脸懵。这些问题绕来绕去根子都出在同一个地方——姿态表示方式搞不清楚。ABB机器人默认采用**四元数Quaternion来存储和传输姿态数据但人脑天生习惯的是欧拉角Euler Angle**这种“绕X轴转多少、绕Y轴转多少”的直观描述。这两套体系之间的换算就是姿态数据能不能顺畅落地的关键。这篇文章不玩虚的直接围绕这样一个实战场景展开我在调试一台ABB机器人时需要把离线编程软件生成的姿态数据从欧拉角转成四元数再写进机器人程序里同时还要处理旋转顺序、奇异点、工具坐标这些坑。整个过程踩了不少雷也总结了几个真正管用的转换技巧。不管你是刚接触ABB机器人、还在跟姿态表示大眼瞪小眼的新手还是已经调试过几条线、想把手头那套转换流程再理顺的老手这篇文章都值得花几分钟看完。我会把四元数和欧拉角的底层逻辑、ABB机器人里的具体用法、以及现场调试时最实用的转换步骤一次讲清楚。2. 四元数和欧拉角的本质区别以及为什么ABB选四元数2.1 欧拉角直观但“角度”只是表象欧拉角的思路很简单把一个姿态拆成绕三个轴的依次旋转。比如说“先绕Z轴转30度再绕Y轴转45度最后绕X轴转60度”这种描述方式非常符合人的直觉大家在示教器上调整姿态时也习惯用这种“绕哪个轴转多少”的方式去操作。但欧拉角有一个先天缺陷——它描述的不是一个最终姿态而是一条旋转路径。同样的最终姿态先绕X再绕Y和先绕Y再绕X得到的结果完全不同这就是所谓的“旋转顺序”问题。ABB的欧拉角通常采用ZYX顺序先绕Z、再绕Y、最后绕X如果你从别的地方拿来的数据用的是XYZ顺序直接填进去机器人姿态必然对不上。更麻烦的是欧拉角还会遇到**万向锁Gimbal Lock**问题。当绕Y轴转到正负90度时绕X轴和绕Z轴的旋转会变得无法区分姿态表示退化成两个自由度你的程序可能因此出现突然的跳变或者奇异点报错。2.2 四元数不直观但好在没有奇点四元数用四个数值w, x, y, z来描述姿态其中w是标量部分x、y、z是向量部分。它本质上是把“绕某个轴旋转多少角度”这种信息编码进了四个分量里避免了欧拉角的万向锁问题。打个比方欧拉角像是在说“我先往东走300米再往北走400米”而四元数像是直接给你一个“东北方向450度左右”的方位角和距离。前者按步骤走、直观但路径依赖后者一步到位、稳定但不那么直观。ABB机器人内部采用四元数存储姿态我看过它系统里robtarget数据结构的设计四个分量统一用num类型的变量表示这意味着你在RAPID程序里可以直接用[w, x, y, z]这样的数组下标去访问和计算非常灵活。2.3 实际使用中两套体系如何互补说到底欧拉角和四元数不是谁取代谁的关系而是互相配合的关系调试阶段用欧拉角直觉调整姿态因为你能预测“绕X轴转一点会带来什么效果”传输和存储阶段用四元数因为它没有歧义不会因为旋转顺序不同导致数据不一致离线编程与上位机通信很多第三方软件默认输出欧拉角需要转成四元数才能喂给ABB机器人所以掌握两套体系之间的换算是每个ABB机器人调试人员的必修课。3. 姿态换算的数学基础从旋转矩阵到四元数3.1 旋转矩阵是连接两套体系的关键桥梁要把欧拉角转成四元数绕开旋转矩阵几乎不可能。旋转矩阵是一个3x3的矩阵它能把一个向量从一个坐标系变换到另一个坐标系。一个绕Z轴旋转θ角的旋转矩阵长这样Rz(θ) [cosθ -sinθ 0] [sinθ cosθ 0] [0 0 1]绕X轴和绕Y轴的旋转矩阵类似只是非零元素的位置不同。当我们说“先绕Z、再绕Y、最后绕X”时总的旋转矩阵就是三个矩阵相乘R Rx(α) * Ry(β) * Rz(γ)注意这个乘法的顺序不能乱。矩阵乘法不满足交换律顺序不同结果就不同。这也是欧拉角容易出问题的根源之一。3.2 由欧拉角计算四元数的推导思路从旋转矩阵到四元数常用的方法是把四元数的四个分量用旋转矩阵的元素表示出来。假设我们已经有了总的旋转矩阵R [r11 r12 r13] [r21 r22 r23] [r31 r32 r33]那么四元数各分量可以通过以下方法求解w 0.5 * sqrt(1 r11 r22 r33)x (r32 - r23) / (4 * w)y (r13 - r31) / (4 * w)z (r21 - r12) / (4 * w)这个公式很稳定唯一需要注意的是当w接近0时也就是旋转角接近180度时公式会退化。到时候需要换用其他公式比如先求x或y或z的最大值。推导过程其实不难核心思想是通过旋转矩阵元素与四元数分量之间的已知关系式反推。但如果你不想手动推导直接用现成程序库或者编程实现也可以。3.3 四元数转欧拉角的公式及注意事项反过来四元数转欧拉角也有现成公式对于ZYX顺序α atan2(2*(wz xy), 1 - 2*(y² z²))β asin(2*(wy - zx))γ atan2(2*(wx yz), 1 - 2*(x² y²))其中α是绕Z轴转角β是绕Y轴转角γ是绕X轴转角。这里最关键的注意事项就是asin函数的值域。当β接近正负90度时asin的参数会接近正负1此时欧拉角进入万向锁区域α和γ变得不稳定。实际调试时如果发现某个轴的角度输出跳动得很厉害多半就是进入了这个区间。4. ABB RAPID程序中的四元数实操怎么读写、怎么转换4.1 RAPID中的姿态数据结构先看清楚RAPID里姿态数据长什么样。在ABB机器人程序里robtarget数据由两部分组成位置trans和姿态rot其中rot就是四元数。举个例子CONST robtarget pPick : [[300, 400, 500], [1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];这里的[1, 0, 0, 0]就是四元数w1, x0, y0, z0表示零姿态即工具坐标系与基坐标系姿态一致。在RAPID代码里访问四元数的分量是直接通过下标VAR num q_w : pPick.rot.rot1; VAR num q_x : pPick.rot.rot2; VAR num q_y : pPick.rot.rot3; VAR num q_z : pPick.rot.rot4;这里rot1到rot4分别对应w、x、y、z。4.2 在示教器上直接查看和修改四元数很多时候你不需要写代码直接在示教器上就能看到和修改姿态数据。在手动操作界面选择“姿态”查看方式时ABB示教器有两种显示模式四元数模式显示w、x、y、z四个数值欧拉角模式显示RX、RY、RZ三个角度对应ZYX顺序的欧拉角如果你是新手建议先在欧拉角模式下调整姿态到目标位置然后切换到四元数模式把四元数值记录下来。这样比直接在四元数模式下瞎猜要高效得多。4.3 一个可以直接用的RAPID函数欧拉角转四元数下面这个函数是我在项目里实际用过的把欧拉角转成四元数RAPID代码可以直接贴进你的程序里。FUNC robtarget EulerToQuat(num rx, num ry, num rz, pos position) VAR num alpha; VAR num beta; VAR num gamma; VAR num c1, c2, c3; VAR num s1, s2, s3; VAR num w, x, y, z; alpha : rz; ! 绕Z轴 beta : ry; ! 绕Y轴 gamma : rx; ! 绕X轴 c1 : cos(alpha/2); c2 : cos(beta/2); c3 : cos(gamma/2); s1 : sin(alpha/2); s2 : sin(beta/2); s3 : sin(gamma/2); w : c1 * c2 * c3 - s1 * s2 * s3; x : c1 * c2 * s3 s1 * s2 * c3; y : s1 * c2 * c3 c1 * s2 * s3; z : c1 * s2 * c3 - s1 * c2 * s3; RETURN [position, [w, x, y, z], [0,0,0,0], [0,0,0,0]]; ENDFUNC这段代码的编写逻辑就是严格按照前面提到的ZYX欧拉角转四元数公式来的。角度单位是弧度如果你从外部拿到的数据是角度记得先转成弧度rad : deg * PI / 180。4.4 四元数转欧拉角的RAPID实现反过来当你要把机器人当前姿态的四元数转成欧拉角用于记录或显示可以用下面这段代码FUNC numArray3 QuatToEuler(robtarget target) VAR num w, x, y, z; VAR num rx, ry, rz; VAR num sinr_cosp; VAR num cosr_cosp; VAR num sinp; w : target.rot.rot1; x : target.rot.rot2; y : target.rot.rot3; z : target.rot.rot4; sinp : 2 * (w * y - z * x); IF abs(sinp) 1 THEN ry : sign(sinp) * PI / 2; rz : 0; rx : atan2(2*(w*z x*y), 1 - 2*(y*y z*z)); ELSE ry : asin(sinp); rz : atan2(2*(w*z x*y), 1 - 2*(y*y z*z)); rx : atan2(2*(w*x y*z), 1 - 2*(x*x y*y)); ENDIF VAR numArray3 result; result{1} : rx * 180 / PI; result{2} : ry * 180 / PI; result{3} : rz * 180 / PI; RETURN result; ENDFUNC这段代码里我特意加了万向锁的判断。当sinp绝对值接近或等于1时直接用固定值处理避免asin函数上传入超出定义域的参数导致报错。这一点在现场调试时特别有用别问我是怎么知道的。5. 工具坐标系对姿态表示的影响一个容易忽略的大坑5.1 工具坐标不同姿态数据完全不同很多时候姿态数据对不上不是换算公式的问题而是工具坐标系Tool Coordinate System不一致导致的。同样的机器人末端位置同样的法兰盘姿态如果工具的长度、方向不同TCPTool Center Point的位置和姿态计算出来就完全不同。ABB机器人在robtarget里存的位置和姿态默认都是相对于工具坐标系的。我在项目里遇到过一次这样的情况从离线仿真软件导出的程序里姿态四元数填进去机器人TCP对不上。排查了半天最后发现是仿真软件里用的工具坐标和实际机器人的工具坐标差了一个旋转。解决方案很简单要么统一两侧的工具坐标要么在导入前用工具坐标转换矩阵把姿态数据变换一下。5.2 如何检查工具坐标是否影响姿态一个简单的验证方法把机器人手动运行到一个已知位置分别在示教器上查看当前位置和姿态。然后用离线软件计算出同一位置的姿态。如果两者四元数不一致先别急着怀疑换算公式先检查工具坐标是否一致。工具坐标的核对项包括TCP的X、Y、Z偏移量工具坐标系相对于法兰盘坐标系的旋转RX、RY、RZ工具重量和重心这个不直接影响姿态但影响负载计算5.3 工具坐标直接输入的技巧ABB机器人支持直接输入工具坐标数据但很多人不知道如何把旋转数据填正确。在示教器里进入“控制面板”-“手动操作”-“工具坐标”页面选中你要修改的工具坐标就可以直接输入工具坐标的平移和旋转数据。这里有一个技巧如果你只有一个已知的工具坐标比如一个吸盘工具你先手动TCP标定出X、Y、Z偏移然后姿态的RX、RY、RZ默认为0通常就够用了。如果你的工具本身是斜装的那就需要用三点法或四点法去标定完整姿态。5.4 多工具切换时的姿态一致性生产线上经常有多把工具自动切换的情况每把工具的工具坐标不同程序里的robtarget数据也应对应不同工具坐标下的姿态。这个很容易出错。我建议的做法是在每个工具的调用处显式地使用对应的工具坐标不要在程序中间用Tool指令切换后忘了更新姿态基准。同时在MoveL指令前打印日志记录当前工具坐标和姿态数据方便事后排查。6. 实操案例从离线编程软件导入姿态数据到ABB机器人6.1 场景描述最近这个项目我用离线编程软件规划了几十个点位的焊接路径。软件导出的姿态数据是欧拉角格式旋转顺序是ZYX角度单位是度。我需要把这些数据全部转成四元数写进ABB的RAPID程序然后跑通实际焊接。这个过程看起来简单但实际操作中有很多细节。我直接把完整的实操流程写下来你照着做基本不会出错。6.2 第一步第三方数据预处理从离线软件导出的数据一般是CSV或Excel格式里面每个点有X、Y、Z坐标以及绕X、Y、Z轴的旋转角。先把这些数据整理成一个标准表格列分别命名为point_id, x, y, z, rx, ry, rz。数据里偶尔会有异常值比如某个点的欧拉角明显跳变。我会先用Python脚本画一个姿态角度的曲线图肉眼观察有没有不连续的点把异常数据先标记出来后面单独处理。6.3 第二步用Python批量转换欧拉角到四元数这里给出一个我在实战中写好的Python脚本直接可以跑import math import csv def euler_to_quaternion(rx, ry, rz): 将ZYX顺序的欧拉角角度制转换为四元数 rx math.radians(rx) ry math.radians(ry) rz math.radians(rz) cx math.cos(rx/2) sx math.sin(rx/2) cy math.cos(ry/2) sy math.sin(ry/2) cz math.cos(rz/2) sz math.sin(rz/2) w cx * cy * cz sx * sy * sz x sx * cy * cz - cx * sy * sz y cx * sy * cz sx * cy * sz z cx * cy * sz - sx * sy * cz return w, x, y, z # 读取CSV转换输出新的CSV with open(input_poses.csv, r) as f: reader csv.DictReader(f) rows [] for row in reader: rx float(row[rx]) ry float(row[ry]) rz float(row[rz]) w, x, y, z euler_to_quaternion(rx, ry, rz) rows.append({ point_id: row[point_id], x: row[x], y: row[y], z: row[z], q_w: round(w, 6), q_x: round(x, 6), q_y: round(y, 6), q_z: round(z, 6) }) with open(output_quaternions.csv, w, newline) as f: writer csv.DictWriter(f, fieldnames[point_id, x, y, z, q_w, q_x, q_y, q_z]) writer.writeheader() writer.writerows(rows) print(转换完成共处理 {} 个点位.format(len(rows)))注意这个脚本里的四元数计算公式和前面RAPID版本有些不同。这里用的公式是w cx*cy*cz sx*sy*sz x sx*cy*cz - cx*sy*sz y cx*sy*cz sx*cy*sz z cx*cy*sz - sx*sy*cz而前面RAPID版本用的是另一套公式。你可能会问两个公式为什么看起来不一样其实两个公式都是对的区别在于旋转顺序的约定。如果你在实际项目中套用后发现姿态不对优先检查一下公式里的加法符号是否和你手里的欧拉角定义一致。6.4 第三步生成RAPID程序模板有了四元数数据后下一步就是把数据写进RAPID程序。我会用Python自动生成一个完整的RAPID文件这样几十个点位都不用手动敲。def generate_rapid(points): lines [] lines.append(MODULE AutoPoses) lines.append() lines.append( CONST robtarget p1 : [[x1, y1, z1], [q_w1, q_x1, q_y1, q_z1], [0,0,0,0], [0,0,0,0]];) # ... 实际按点位生成 lines.append(ENDMODULE) return \n.join(lines)生成的RAPID文件直接导入RobotStudio或者通过U盘加载到控制器就能在程序里直接调用了。6.5 第四步现场验证与微调程序写好后先在手动模式下低速运行到第一个点用示教器检查TCP位置和姿态是否和离线软件里一致。如果发现偏差先检查工具坐标再检查数据显示格式最后才考虑公式问题。现场微调的小技巧在示教器上手动调整到目标姿态后直接把示教器显示的四元数值抄下来替换程序里的值虽然没那么优雅但胜在简单可靠。7. 常见问题与排查技巧实录7.1 姿态数据填进去后机器人跑飞这是最严重的故障之一。常见原因是四元数没有归一化。四元数必须满足w² x² y² z² 1如果数据是从别的地方复制来的可能会出现模长不为1的情况。ABB虽然不会直接报错但运动学计算会出现偏差导致机器人位置跑偏。排查方法在程序里加一个断言检查四元数模长VAR num q_length; q_length : sqrt(q_w*q_w q_x*q_x q_y*q_y q_z*q_z); IF abs(q_length - 1) 0.001 THEN TPWrite Warning: Quaternion not normalized, length \Num:q_length; ENDIF如果发现没有归一化直接重新归一化q_w : q_w / q_length; q_x : q_x / q_length; q_y : q_y / q_length; q_z : q_z / q_length;7.2 同一姿态在示教器上显示的角度和程序里输入的角度不一致这种情况一般是角度制/弧度制混用。示教器上欧拉角显示通常用角度制但RAPID里的数学函数用弧度制。如果你直接在RAPID里用Cos(angle)angle必须为弧度否则数值完全不对。解决办法统一使用角度制显示但计算前先转弧度输出前再转回角度。我习惯在代码里定义两个函数FUNC num DegToRad(num deg) RETURN deg * PI / 180; ENDFUNC FUNC num RadToDeg(num rad) RETURN rad * 180 / PI; ENDFUNC7.3 奇异点问题当姿态接近万向锁位置时欧拉角的某个分量会剧烈变化。在示教器上手动调整或在线编程时容易遇到“奇异点”报警。这是欧拉角的固有缺陷不是机器人故障。如果在工艺上允许我会尽量把轨迹规划避开奇异点附近或者在程序里把姿态数据改用四元数直接传递避免欧拉角的计算不稳定。7.4 不同旋转顺序带来的数据差异同一条路径A软件导出的是ZYX欧拉角B软件导出的是XYZ欧拉角直接互相替换姿态必然不对。我的处理办法是在项目开始前先和离线编程软件那边确认旋转顺序统一约定为ZYX。如果无法统一就在转换代码里加上旋转顺序参数根据来源不同自动切换公式。7.5 常见问题速查表问题现象可能原因排查要点姿态填入后机器人运动轨迹不对旋转顺序不一致确认欧拉角顺序是ZYX还是其他四元数分量超出合理范围未归一化检查w²x²y²z²是否等于1角度数值看起来很大但不正常角度/弧度混用检查是否所有三角函数都用了弧度特定位置附近姿态跳变剧烈奇异点/万向锁检查RY是否接近±90度两个工具下同一程序姿态不同工具坐标系不一致核对TCP偏移和旋转从第三方软件导入四元数后对不上工具坐标或旋转顺序定义不同先用已知点做交叉验证8. 我用这套方法踩过的坑和最终心得说实话姿态换算这件事理论不难坑都在细节里。我把这几个项目里最容易翻车的地方再强调一遍都是真金白银换来的教训。第一转换之前先确认坐标定义。每个软件对欧拉角顺序、旋转轴正方向、工具坐标原点的定义都可能不同。花十分钟确认这些前提比后面排查半天要值得多。我在第一个项目里就吃过这个亏两边数据来回对不上后来发现是离线软件里把Z轴方向定义反了。第二示教器就是最好的验证工具。不要光在电脑上算跑一个点手动运行到那个位置肉眼看看法兰盘朝向再切换到四元数显示模式对比一下数值基本能筛掉90%的问题。第三归一化检查必须养成习惯。不管数据是哪来的写进RAPID之前都过一遍归一化检查成本低效果立竿见影。我在RAPID程序里写了个通用的检查函数每次加载新点位数据都跑一遍后面极少再出现跑飞的情况。目前这套流程已经用在我手头的焊接、搬运、装配好几个项目里效果稳定。建议你先拿一两个点位试跑确认逻辑无误后再批量处理。毕竟姿态这个事小数点后几位就能决定一个工件能不能装配合格稳一点总没错。
返回列表