ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

FANUC机器人PR[i]位置寄存器实战:坐标系转换与视觉引导全解析

FANUC机器人PR[i]位置寄存器实战:坐标系转换与视觉引导全解析 做机器人调试这些年FANUC的PR[i]位置寄存器几乎每天都在碰。但说实话真正能把PR[i]用明白、尤其是在坐标系转换场景下不出错的人并不是多数。很多朋友卡在“赋值没问题、一用就乱跑”这个阶段归根到底是对位置变量的底层逻辑缺乏完整认知。这篇东西不打算讲手册上那点皮毛我直接把从入门到接项目踩过的坑、验证过的套路全部摊开从最基础的LPOS/JPOS区别到手写坐标系转换模板再到视觉引导场景的完整案例一次说透。1. 位置变量PR[i]到底是什么东西1.1 位置数据的两种“长相”LPOS和JPOSFANUC机器人里任何位置点本质是一组数字但根据表达方式不同分成两大类关节位置JPOS和笛卡尔位置LPOS。JPOS记录的是机器人6个轴的关节角度格式是J1、J2、J3、J4、J5、J6可能还有附加轴。LPOS记录的是工具末端在某个坐标系下的空间坐标和姿态格式是X、Y、Z、W、P、R。这里W、P、R是欧拉角分别对应绕X、Y、Z轴的旋转量。很多初学者最容易犯的第一个错误就是把LPOS和JPOS当成可以随意互换的数据。实际上它们只是同一个物理位置的两种数学表达。就像同一个地址用经纬度描述和用“某市某区某街道门牌号”描述信息等价但格式完全不同。两者之间靠机器人的正解关节→笛卡尔和逆解笛卡尔→关节算法转换。1.2 PR[i]寄存器的存储结构PR[i]是FANUC专门为位置数据设计的寄存器编号从PR[1]开始一般机器人能开到几百个。每个PR[i]内部其实是一个结构体里面同时保存了LPOS和JPOS两套数据。关键点来了当你用示教器手动修改某个PR[i]的LPOS坐标时系统会自动运算更新对应的JPOS反过来你改JPOSLPOS也会同步重算。这个自动同步机制在手动操作时没问题但在程序里通过赋值语句写PR[i]时经常出现“只更新了一半”的情况后面我会详细讲这个坑。1.3 位置变量的“快照”属性PR[i]还有一个容易被忽略的属性它是“快照”型数据。当你把机器人当前点写入PR[i]时存的是那一刻的位置状态。如果之后机器人移动了PR[i]里的数据不会跟着变除非你重新写入。这听起来像废话但实际使用中很多人会犯迷糊。比如有人在循环里反复使用同一个PR作为目标点却忘了每次循环都要先更新PR的值结果机器人在第二次循环时还往第一次的位置跑。这种问题排查起来很费时间因为程序语法完全正确但逻辑上漏了“刷新”那一步。2. 位置赋值五种方式与适用场景2.1 示教器手动赋值按下示教器上的“位置”键选择PR[i]可以直接手动输入坐标值。这种方式适合单点测试、固定点位预设。操作很简单但要注意手动输入时一定要确认当前激活的用户坐标系UF和工具坐标系UT因为LPOS的X、Y、Z、W、P、R值都是相对于这两个坐标系而言的。我见过有人在UF[1]下输入了一个点的坐标然后程序调用时用的是UF[0]机器人直接跑到完全不同的位置。这个问题极其隐蔽因为PR[i]数据本身没错错的是参照系不一致。2.2 程序内LPOS直接赋值在TP程序里可以用类似这样的指令LPOS[1] LPOS[2]或者PR[10, 1] 500.0第一条是把PR[2]的笛卡尔坐标赋值给PR[1]第二条是把PR[10]的X分量直接设为500.0毫米。直接赋值的好处是灵活适合在运行中动态修改目标点。但这里有一个重要规则直接修改LPOS后PR[i]内部的JPOS数据不会自动同步。如果你后续用这个PR[i]执行关节运动J指令机器人用的是JPOS数据还是旧的结果就会跑偏。2.3 当前位置写入这个是最常用的方式TP指令是PR[i] LPOS或者带工具和用户坐标系的写法PR[i] LPOS[UT:1, UF:2]执行这行指令时机器人会把当前工具末端在指定坐标系下的笛卡尔位置写入PR[i]同时自动更新JPOS。这是最“安全”的赋值方式因为系统帮你做了完整的数据同步。2.4 运算赋值位置加减法FANUC系统里PR[i]可以直接做加减运算PR[3] PR[1] - PR[2]这条指令的含义是PR[1]的位置减去PR[2]的位置结果存到PR[3]。但这个“减法”不是简单的XYZ分量相减而是涉及旋转矩阵的复合运算。用大白话说PR[1] - PR[2]可以理解为从PR[1]出发沿着PR[2]的反方向移动后得到的新位置。这在做相对位置偏移、镜像对称位置计算时非常有用。比如你在A点抓取B点是码垛放置点如果工件在传送带上有偏差可以用“基准抓取点 偏差量”的方式动态计算实际放置点。2.5 后台逻辑/视觉系统写入很多带视觉引导的项目会通过以太网、Devicenet或机器人自身的视觉系统把视觉识别的目标坐标直接写入PR[i]。这类写入通常是后台任务完成前台TP程序只需要等待“数据刷新完成”标志位然后直接调用PR[i]运动。这里要特别提醒视觉系统写入的坐标往往基于相机坐标系的标定结果必须确认视觉输出的坐标是在哪个坐标系下表达的。一般视觉标定会直接映射到机器人USER坐标系但仍然建议在程序中加一个“坐标合理性判断”比如目标点离基准点超过一定范围就报警暂停。不要盲目相信视觉输出的每一个数。3. 坐标系转换的底层逻辑与手写模板3.1 为什么要自己写坐标系转换有人会问FANUC不是有自带的坐标系换算功能吗为什么还要手写原因有两个。第一系统自带的坐标系转换功能比如通过偏移指令OFFSET只能做固定方向的平移涉及到工具姿态变化、坐标系旋转时不够用。第二很多高级应用里你需要在自己定义的坐标系之间变换系统没有现成的按钮只能通过程序实现。举个例子机器人要在一个倾斜的平面上码放工件码放方向是斜的。如果你用全局坐标系一个个示教点费时费力而且一旦工件位置微调所有点都要重新示教。正确做法是在斜面建立用户坐标系UF然后在UF内部按行列偏移计算位置这样只需示教一个基准点其他全部程序生成。3.2 转换的数学原理旋转矩阵平移向量坐标系转换的核心是旋转矩阵R和平移向量T。假设空间有一个点P它在坐标系A中的坐标是PA想得到它在坐标系B中的坐标PB换算关系是PB R_AB * PA T_AB这里R_AB是从A系到B系的旋转矩阵T_AB是B系原点在A系中的坐标。在FANUC的PR数据里W、P、R三个欧拉角本质上就是在描述这个旋转矩阵R而X、Y、Z就是平移向量T。所以坐标系转换问题的本质就是根据两个坐标系的相对位姿关系算出R和T然后作用于目标点。FANUC系统内部其实提供了完整的矩阵运算能力通过用户宏程序里的矩阵变量M[i]来实现。但在TP程序里直接操作矩阵比较繁琐我更推荐用KAREL程序处理复杂转换TP里只做简单的加减法偏移。3.3 手写模板从A系转到B系这里分享一个我实际项目里一直在用的KAREL参考程序骨架作用是把一个PR[i]的点从用户坐标系A换算到用户坐标系BPROGRAM CONVERT_FRAME VAR source_point : POSITION result_point : POSITION frameA, frameB : FRAME rel_transform : FRAME temppos : XYZWPR BEGIN -- 读取两个用户坐标系的位姿 GET_UFRAME(frameA, 1) GET_UFRAME(frameB, 2) -- 读取源点例如PR[1] source_point GET_POS_REG(1) -- 计算从A到B的相对变换 rel_transform INVERSE(frameB) * frameA -- 应用变换 result_point rel_transform * source_point -- 写入PR[2] SET_POS_REG(2, result_point) END CONVERT_FRAME核心就是先取两个坐标系的相对变换矩阵然后用矩阵乘法把点从A系映射到B系。这个模板可以套用在几乎所有坐标系转换场景工件偏移、多工位镜像、不同夹具间的位置换算等。如果只能写TP程序一个替代方案是利用FANUC的“位置寄存器偏移”功能间接实现但灵活性差很多。原则上建议简单平移偏移用TP复杂旋转转换上KAREL。3.4 工具坐标系也对位置变量有影响很多人只关注用户坐标系忽略了工具坐标系UT对PR[i]的影响。实际上LPOS的X、Y、Z、W、P、R值都是“工具末端在什么姿态、什么位置”的完整描述而工具末端的定义就取决于UT。同一个物理点用UT[1]表示和用UT[2]表示得到的LPOS值完全不同。所以项目里要形成铁律所有涉及PR[i]的程序必须明确标注“此PR基于哪个UT、哪个UF”最好直接在程序注释里写清楚。我见过最离谱的事故是一个工装的工具坐标系参数输错导致视觉引导的所有点位全部偏移排查了整整三天。4. 实战案例视觉引导下的动态码盘偏移4.1 场景描述与工艺需求项目是一个流水线上的视觉引导分拣码盘工位。视觉相机安装在固定位置检测传送带上的工件位置通过视觉通讯把工件的XY坐标偏差和旋转角度发给机器人。机器人需要从传送带上抓取工件放置到托盘上每层放4个共3层。基本要求是抓取点随视觉结果动态变化放置点在托盘固定位置但要求根据来料角度的不同机器人末端在放置前自动旋转相应的角度。同时托盘相对机器人基座的安装位置有偏差需要通过一次标定把托盘坐标系实际定位出来。4.2 坐标系拆分与PR规划我先拆清楚了系统里需要的坐标系UF[1]机器人基坐标系默认UF[2]视觉标定坐标系也就是视觉结果直接映射后的坐标系UF[3]托盘坐标系基准点在托盘角点X轴沿托盘长边PR寄存器分配如下PR[1]视觉相机识别到的抓取点由视觉写入PR[2]抓取点经过工具/坐标系转换后的实际机器人目标PR[3]托盘放置基准点示教一次PR[4]当前位置换算到托盘坐标系后的临时值PR[10]~PR[12]码放位置运算中间量这个分配逻辑是抓取链路用PR[1]→PR[2]放置链路用PR[3]为基准动态生成PR[4]并调用运动。4.3 抓取链路实现视觉写入PR[1]后程序先做坐标系修正! 视觉坐标系转机器人基坐标系 CALL VISION_TRANSFORM这个CALL里的核心逻辑就是我3.3部分的KAREL程序。视觉系统输出的是UF[2]下的坐标机器人需要的是UF[1]下的坐标。如果不转换直接拿视觉的X、Y去运动由于相机安装角度和机器人基座有偏角机器人跑过去会偏出几十毫米。转换完成后PR[2]就是机器人基坐标系下的实际抓取点。运动指令J P[1] 100% FINE L PR[2] 500mm/s FINE这里有个小技巧先J到P[1]安全点再线性运动到PR[2]避免刀具和传送带干涉。实际调试中这个安全点的高度选择很关键要高于工件最高点同时不能碰到相机支架。4.4 放置链路实现托盘坐标驱动托盘坐标系UF[3]标定完成后所有码放位置都基于UF[3]生成。托盘每格的中心位置在UF[3]下的坐标是固定的我可以直接写死在程序里只需要考虑每层的Z高度变化。! 第2层第3格位置 PR[4] PR[3] PR[4, 1] PR[3, 1] 150 ! X方向偏移 PR[4, 2] PR[3, 2] 300 ! Y方向偏移 PR[4, 3] PR[3, 3] 80 ! Z方向抬升到第2层 PR[4, 4] PR[3, 4] ! W角不变 PR[4, 5] PR[3, 5] 45 ! P角根据来料旋转这里容易踩坑的地方是直接修改PR[4]的X、Y、Z、W、P、R分量后它只是LPOS被改了JPOS不会自动更新。执行L指令运动时由于L指令是笛卡尔空间运动系统会实时逆解计算关节角所以用L指令没问题。但如果你用J指令去PR[4]系统读的是旧的JPOS位置就会错。所以在这个项目里放盘全部用L指令明确禁止使用J指令。程序开头加了一个判断IF R[20] 1 JMP LBL[10]R[20]是模式选择开关如果处于“放置模式”强制走L指令逻辑。这不是多此一举是血的教训换来的。4.5 视觉角度补偿的细节处理视觉系统除了XY坐标还会反馈一个来料旋转角A。这个角度要在放置路径中补偿否则工件放下去是歪的。补偿逻辑是这样实现的先把PR[2]的坐标复制到临时PR[10]然后修改PR[10]的W分量或P、R取决于工件是水平旋转还是俯仰旋转PR[10] PR[2] PR[10, 4] PR[10, 4] R[30] ! R[30]是视觉反馈的角度注意这里修改的是第4个分量也就是W角。对于水平放置的工件Z轴旋转就是W角。改完之后先L到PR[10]正上方再下移到PR[2]抓取。这里有一个姿态插补的坑当起始姿态和结束姿态差异较大时L指令的姿态过渡可能不是最短路径会出现机器人“绕远路”的现象。特别是W角从接近0度突然变到接近180度时机器人会大幅回转看起来很吓人。解决办法是在路径中加中间点先让姿态转到一半再继续下探。或者用FANUC的姿态插补方式切换指令。4.6 整体程序的异常分支处理实际运行中视觉可能是超时、误检、识别出界外点等异常。我在主循环里加了分支IF R[20] 0 JMP LBL[100] ! 视觉无结果跳过抓取 IF DI[5] ON JMP LBL[200] ! 托盘满切换另外每个PR在作为目标点运动前我都加了一个坐标范围检查IF PR[2, 1] 1000 THEN CALL ALARM_PAUSE ENDIF这个范围的上下限以机器人工作空间和传送带相机覆盖范围为准。视觉偶尔会报出一个离谱的坐标如果不做检查机器人会直接冲过去——轻则撞夹具重则撞相机支架。宁可误报多停几次也不能让没验证的点直接进运动指令。5. 常见问题与排查我把做PR相关调试这些年遇到的高频问题整理成一个速查表很多问题都不是语法错误而是逻辑和坐标系的问题排查起来非常费时间。问题现象根本原因处理办法机器人运动到错误位置程序内写入LPOS后JPOS未同步又用了J指令统一用L指令或写入后用重算指令同步JPOS点位偏移几十毫米PR参考的UF/UT与运动指令不一致建立程序头注释规范标清坐标系ID视觉点偶发偏出视觉标定或通讯偶发错误加坐标范围判断超限报警姿态突然“绕大弯”W/P/R变化量过大L指令姿态插补路径异常增加过渡点分两步转姿态码垛层高累积误差Z值直接在原PR上累加产生浮点舍入误差用基准PR加偏移量的方式不累加镜像对称点位错乱直接对XYZ取反未处理旋转矩阵使用PR相减或KAREL矩阵运算5.1 程序内修改PR后位置不更新这个问题的本质就是前面反复强调的LPOS和JPOS不同步。直接对PR[i, n]赋值或者对PR[i]做加减运算系统并不会自动重算另一种表达方式。解决思路有两个一是处理完后用重算指令强制同步。KAREL里可以用rel_point GET_POS_REG(i) SET_POS_REG(i, rel_point)这样会触发系统重新计算JPOS。二是在运动指令层面规避只使用L类指令不用J类指令。L指令按笛卡尔坐标执行运动每次都会实时逆解所以LPOS正确即可。5.2 坐标系混淆导致的“幽灵偏移”这类问题最难排查因为程序语法完全正确PR数值看着也对但机器人就是不在预期位置。排查思路是先确认运动指令里指定的是什么UT/UF。比如L PR[5]后面跟了UT:3, UF:4但PR[5]当初写入时用的是UT:1, UF:1那结果必然错。检查手动示教时页面顶部的UF/UT显示状态。检查视觉或上位机写入PR时基于哪个坐标系。一个比较彻底的预防方案是在项目程序开头把所有涉及到的坐标系全部显式初始化一遍UFRAME_NUM 1 UTOOL_NUM 1这样至少保证程序启动时坐标系是确定的不会受示教器残留状态影响。5.3 PR数值超出范围FANUC位置寄存器的数值范围有限制。如果写入的坐标值过大或者角度值超出正常范围有些版本的系统会表现为PR值变为“########”溢出显示程序运行会报错。这种情况经常出现在视觉给出异常值时。所以前面说的坐标范围检查不只是防撞机也能防止数据溢出导致系统崩溃。5.4 断电后再上电PR被重置老旧一些的FANUC机型PR寄存器有部分存储区域在断电后不保持。需要确认PR[i]是否被分配到保持型存储区。通常控制柜内的主板电池保证SRAM不掉电但电池耗尽或更换时可能导致数据丢失。重要点位和标定数据不能只存在PR里必须定期备份或者写在一个自动执行的$MORGRP初始化程序里每次上电自动写入。这个习惯能避免很多“早上开机点位全丢了”的抓狂现场。6. 一点个人体会位置变量PR[i]在FANUC系统里看着就是个简单的数据存储真正让它有威力的是你对坐标系的掌控能力。我接触过不少调试工程师PR指令背得很熟但一到坐标系转换就发怵看到WPR角度就头大。其实坐标系转换没有想象的那么玄核心就是先搞明白“这个点是谁在什么坐标系下观察到的”再找到两个坐标系之间的相对位姿关系剩下就是矩阵乘法的功夫。我建议刚入门的朋友不要急着抄现成模板先花一个下午在机器人旁边做一次坐标变换实验示教几个点、手动改改UF的旋转角度亲眼看看X、Y、Z、W、P、R是怎么变化的。这个感性认识比看十遍手册都管用。等你真正理解了“所有位置都是相对的”这句话PR[i]基本就能随心所欲了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进