资讯详情

URScript机器人编程实战指南:从图形界面到产线交付的完整复盘

📅 2026/10/3 18:31:37 | 华诺云谱 👁 阅读
URScript机器人编程实战指南:从图形界面到产线交付的完整复盘
第一次长时间用UR协作机器人是在一条小批量装配线上。前两个礼拜我全程靠示教器的Polyscope图形界面拖拖拽拽就把“抓取-放置”的动作写完了心里还挺得意。后来项目加上视觉定位和PLC握手之后程序节点膨胀到两三百个改一个间距参数要在几十个节点里翻来找去我才意识到自己完全低估了URScript的价值。这篇文章不是照着官方手册念参数而是我跑过十几个UR项目之后对URScript的一个完整复盘它到底是什么、怎么学最顺、哪些坑是文档里不会写的。不管你是刚接触UR的新手还是已经用图形界面做过几个项目的老手这篇都值得当索引存一下。1. 图形化编程够用为什么产线项目最后都得回到URScript1.1 图形界面能覆盖80%场景剩下20%才决定项目能不能交Polyscope的图形编程确实做得很友好固定点位、固定流程、节拍宽松的上下料场景拖几个节点就能跑。但一旦流程变成“根据托盘坐标动态计算偏移”“根据来料方向切换整个动作序列”“和MES互相确认状态”图形节点的表达力就开始捉襟见肘。举个具体例子一条产线上有4种托盘每种摆法不同、料号不同、放置位置也不同。用图形节点做就是4条大分支复制粘贴参数改一个4处跟着改漏改一处就是撞机风险。URScript里一个双层for循环加一个偏移数组就解决了逻辑还清晰得多。我在现场见过太多项目卡在“图形界面也能做但改起来要命”这个阶段最后不得不回头补脚本。1.2 换个角度看图形界面只是URScript的翻译器这里有个关键认知UR控制器里真正执行的是一份URScript文本脚本。你在Polyscope上拖出的每一个节点最终都会被翻译成对应的URScript在控制器内的解释器里运行。换句话说URScript不是和图形界面平级的另一套东西它才是底层的那个“母语”。教大家一个小技巧在Polyscope任意程序界面点击“脚本”标签能看到当前图形程序的完整脚本表示。我把它当成最好的入门教材——想知道某个节点干了什么就拖一个出来再看它生成了什么代码。这个方法比死记函数列表有效得多因为每个产物都对应你手边的真实操作。1.3 URScript能做的四类事结合我在产线上接触过的项目URScript的价值集中在这四类复杂流程控制条件分支、循环、子函数把产线逻辑真正写清楚而不是用几十个节点硬拼。动态运动用变量作为目标点位根据视觉或传感器数据实时计算路径而不是死等固定点。外部通信Socket、I/O、Modbus、FTP、Dashboard Server和视觉系统、PLC、MES对话。底层控制servoj伺服运动、力控模式、输送跟踪这类高级功能只有脚本层才暴露给你。一句话总结图形界面适合“配置”URScript适合“编程”。产线项目越复杂你越需要后者。2. 基础语法快速过一遍看得懂脚本才谈得上改脚本2.1 变量、列表和位姿URScript里没有对象URScript是动态类型脚本赋值即声明不需要提前定义类型。常见类型有number、string、bool、list。位姿统一用长度为6的列表表示p[x, y, z, rx, ry, rz]位置单位是米角度单位是弧度关节位置用q[j1, j2, j3, j4, j5, j6]表示单位也是弧度。这里有个最容易翻车的点示教器界面上你习惯看到的角度单位是度但脚本里p[]的rx、ry、rz必须是弧度。新手最爱写出p[0.5, 0.0, 0.3, 90.0, 0.0, 0.0]想着让工具转90度实际解释器按90弧度处理机器人会做一个非常夸张的翻转动作。我自己就亲眼见过调试工程师被这个坑搞懵差点撞到工装。# 数字、字符串、布尔值 speed 0.25 part_name 盖板_A is_ready True # 列表 offsets [0.0, 0.0, 0.08] # 位姿位置 RPY欧拉角角度为弧度 pick_pose p[0.412, -0.218, 0.153, 3.1416, 0.0, 0.0] home_joints q[0.0, -1.5708, 0.0, -1.5708, 0.0, 0.0] # 用textmsg输出到日志方便调试 textmsg(当前速度 , speed)另外注意URScript没有字典、对象这类结构数据组织基本靠列表和并行数组。需要存多个工件的坐标时就把所有x放一个列表、所有y放一个列表或者用二维列表按索引取用。刚开始觉得别扭用久了反而觉得简单直接。2.2 分支循环与sleep控制流比想象中更像PythonURScript的控制流风格和Python非常接近if/elif/else、while、for块结束用end收尾。写起来几乎没有学习成本。下面这段是典型的双输出闪烁测试同时演示了for循环的写法# for循环range(0, 4)生成0,1,2,3 for i in range(0, 4): set_digital_out(i, True) sleep(0.5) set_digital_out(i, False) sleep(0.5) endwhile循环更常用在等待外部信号上。比如等PLC给出放行信号再开始动作# 等待PLC给出放行信号数字输入0为True while get_digital_in(0) False: sleep(0.05) end # 收到信号后开始干活 movel(pick_pose, a1.2, v0.25)注意我在while循环体里放了一个sleep(0.05)这是关键具体原因在第五章讲“假死”问题时细说。总之URScript的循环语法不需要专门学反而是控制流的“节奏”需要在实际现场里找感觉。2.3 def函数把重复逻辑收敛起来函数用def定义end结束支持参数和返回值。生产项目里抓取、放置、换工具、吹气清理这些动作会频繁复用写成函数能少写几十行重复代码也让主流程变得像一篇文章的目录一样清楚。# 定义换工具函数工具1用数字输出0工具2用数字输出1 def set_tool(tool_id): if tool_id 1: set_digital_out(0, True) set_digital_out(1, False) else: set_digital_out(0, False) set_digital_out(1, True) end end set_tool(1)作用域规则也和Python接近函数体外定义的变量是全局的函数内部默认使用局部变量如果你确实需要在函数里修改全局变量用global关键字声明一下。建议养成习惯把会复用的点位、速度、加减速都写在文件顶部做“常量区”函数里只引用不修改这样后期调参时不用翻遍整个脚本。3. 运动指令选型movej、movel、movep各管一摊3.1 关节空间与直角空间的差异URScript里最常用的运动指令是movej和movel它们的核心区别不在“走直线还是走弧线”这么简单而在于插值空间完全不同。movej是在关节空间插值每个关节独立地从当前角度运动到目标角度TCP走的是一条在笛卡尔空间看不太直观的曲线。好处是关节运动路径通常更高效不容易碰到奇异点适合只关心起点和终点、不关心中间路径的场景比如两个工位之间的转场。movel是在笛卡尔空间做直线插值TCP从当前点沿直线走到目标点工具姿态在路径中保持线性过渡。适合插拔、对位、沿边移动这类对路径有严格要求的动作。下面代码演示了从当前位置先直线下降、再直线抬起的典型取料动作above_pick p[0.412, -0.218, 0.20, 3.1416, 0.0, 0.0] pick_pose p[0.412, -0.218, 0.153, 3.1416, 0.0, 0.0] movej(above_pick, a1.4, v0.3) # 先转场到工件上方 movel(pick_pose, a1.0, v0.15) # 直线下降接近工件 sleep(0.2) set_digital_out(0, True) # 吸嘴打开 movel(above_pick, a1.0, v0.2) # 直线抬起这里还要提醒一个参数单位问题movej的a和v单位分别是关节加速度rad/s²和关节速度rad/s而movel的a和v单位是工具加速度m/s²和工具线速度m/s。同样写v0.25两种指令的含义完全不同复制代码时一定要检查。3.2 movep的关键参数r以及movec的补充如果你做过涂胶、密封、弧焊这类需要TCP按恒定速度扫过连续轨迹的项目就会发现movel不够用它每段都要减速到零再启动轨迹衔接处会一顿一顿胶线粗细不均。这时候要用movep它的设计目标就是“路径一致”——让TCP沿着一串目标点连续运动速度波动小每段之间用圆弧过渡。# 涂胶轨迹连续经过4个点末端圆弧半径为5mm seam_poses [p1, p2, p3, p4] movep(seam_poses, a0.4, v0.08, r0.005)r参数就是过渡半径单位米它决定了相邻两段之间用多大圆弧衔接。r太小会接近折线运动速度反而波动r太大会吃掉轨迹拐角精度。实际调的时候先给个0.005之类的保守值再根据工艺要求放大缩小。movec是专门走圆弧的指令需要给定途经点和终点。它的典型场景是工件的圆角轮廓、法兰外圈清胶这类需要精确圆弧的动作。三种指令配合表格看得更清楚指令插值空间适用场景关键参数movej关节空间转场、取放只关心起终点a, v, r, tmovel笛卡尔直线插拔、对位、垂直接近a, v, r, tmovep笛卡尔连续路径涂胶、密封、打磨轨迹a, v, rmovec笛卡尔圆弧圆角轮廓、圆弧过渡pose_via, pose_to, a, v, r3.3 位姿变换抓取点偏移是怎么算出来的视觉引导抓取是URScript最典型的应用之一。相机给出工件的偏移量机器人不能直接加上去就运动必须通过位姿变换把“相机坐标系下的偏移”转换成“机器人基坐标系下的目标点”。标准的做法是先示教一个基准位姿base_pose然后用pose_trans把基准位姿与偏移量合成。偏移量本身也写成位姿形式位置平移放在xyz旋转角放在rxryrz。base_pose p[0.412, -0.218, 0.153, 3.1416, 0.0, 0.0] # 视觉返回dx、dy单位米theta单位弧度 dx 0.012 dy -0.005 theta 0.03 offset p[dx, dy, 0.0, 0.0, 0.0, theta] # 合成目标位姿 target pose_trans(base_pose, offset) movel(target, a1.2, v0.25)反过来用pose_inv可以求逆位姿配合pose_trans能完成坐标系之间的互相转换。我的经验是凡是涉及“某个坐标系下的偏移”一律用pose_trans不要自己手动加减xyz。因为旋转存在之后简单的坐标加减在数学上就是错的这也是第五章要展开讲的现场坑。4. I/O与Socket让机械臂和产线“握手”4.1 数字量与模拟量的读写范式机器人从来不是单机设备和PLC、传感器、夹具的交互全靠I/O。URScript里数字量读写是set_digital_out、get_digital_in模拟量是set_analog_out、get_analog_in。里面要区分工具端I/O和控制器端I/O索引号对应接线图写之前一定要核对电气图纸。现场最常用的就是握手信号模式机器人先等外部条件满足再给出响应信号防止两个设备同时动作造成干涉。# 等待PLC放行 while get_digital_in(0) False: sleep(0.05) end # 运动到位后通知PLC可以上料了 set_digital_out(2, True) # 模拟量输出一个4.5V给比例阀 set_analog_out(0, 4.5) # 读取模拟量输入判断真空压力是否到位 vacuum_value get_analog_in(1)一个容易忽略的细节数字输出的状态在程序停止后不会自动复位。如果程序异常中断某个气缸可能保持在伸出状态这是安全隐患。稳妥的做法是在程序开头做一个“复位区”把所有输出强制清零再进入主流程。4.2 Socket通信接收视觉系统坐标UR控制器内置了Socket客户端函数能主动连接视觉系统、工控机或MES的TCP服务端。常用的四个函数分别是socket_open建立连接、socket_send_string发送字符串、socket_read_ascii_float读取浮点数、socket_read_string读取字符串。下面这段是接收视觉系统坐标的典型写法。视觉端开一个TCP服务监听9000端口机器人作为客户端连接后发送请求然后读取三个浮点数依次是x、y、thetaif socket_open(192.168.1.10, 9000, vision_socket) True: socket_send_string(REQUEST_POSE\n, vision_socket) values socket_read_ascii_float(3, vision_socket, timeout2) socket_close(vision_socket) if length(values) 3: dx values[0] dy values[1] theta values[2] textmsg(收到视觉坐标: , dx, dy, theta) else: textmsg(视觉数据超时或格式错误) end else: textmsg(Socket连接失败) end注意两点。第一socket_read_ascii_float如果超时返回的是空列表拿到结果要先判断长度否则后续越界访问会让程序异常终止。第二视觉数据往往带换行符发送端和接收端要约定好分隔符\n是常用选择否则解析时容易粘数据。4.3 30001/30002/29999三个端口该怎么记除了主动往外连UR控制器还开放了三个常用TCP端口外部系统可以通过它们往机器人发指令。很多工程师第一次看到这三个端口就晕其实用途差异很大端口名称主要用途行为特点30001Primary Client实时状态反馈 脚本注入注入的脚本会替换当前程序30002Secondary Client状态反馈 脚本注入注入的脚本与当前程序并行执行29999Dashboard Server程序加载、启动、停止、状态查询文本指令简单直接我的使用习惯是远程控制整个流程用30001把完整脚本发过去运行在线修改某个变量或临时执行一段动作用30002不影响主程序日常查询机器人是否在运行、加载哪个程序、切换程序全部走29999的Dashboard指令。有个坑必须提醒向30001发送脚本会中断当前正在运行的程序这在产线调试时容易引发意外。如果机器人正在运动中你从外部发了一整段脚本过去当前动作会被打断新手第一次遇到会以为机器人“失控”了其实只是端口机制如此。5. 现场踩过的坑时序、坐标系和异常恢复5.1 死循环与调度为什么脚本会“假死”我刚用URScript做项目时写过一个等待信号循环图省事没加sleepcount 0 while get_digital_in(0) False: count count 1 end结果机器人运行到这一段后示教器上的“停止”按钮变得非常迟钝外部查询状态也半天不回应整个程序像死机了一样。后来才明白UR控制器里脚本解释器要处理运动规划、I/O刷新、界面通信等多个任务一个没有sleep的紧密循环会抢占过多执行时间让其他任务得不到调度。解决办法很简单循环体里加sleep(0.05)或sleep(0.1)。这个休眠时间既不影响信号响应的实时性又能让控制器正常喘息。现在我写所有轮询循环无论等信号、等运动完成、等Socket数据第一件事就是检查有没有sleep。这是一条看起来不起眼、但现场价值极高的经验。5.2 坐标系偏移的暗坑手算和机械臂算不一样有次视觉引导项目相机返回偏移量我图方便直接把偏移加到目标位姿的xyz上没用pose_trans。近点抓取看起来没问题但工件放到远处料盘时误差大到肉眼可见一量差了快一厘米。原因很简单相机安装角度和机器人基坐标系有旋转偏差偏移量不能简单做笛卡尔坐标加减必须先经过旋转变换。pose_trans做的事就是把基准位姿和偏移量做完整的刚体变换包括了旋转部分。从那以后凡涉及跨坐标系计算我都坚持“三个一”原则一个基准点示教、一次pose_trans合成、一处实测验证。还有一个欧拉角约定问题。UR用的是RPY顺序也就是p[x, y, z, rx, ry, rz]里的旋转按绕固定轴依次施加。如果你从其他软件或算法库里拿到旋转矩阵必须先确认它的欧拉角约定和UR一致否则转换过来姿态是错的。验证方法很笨但有效让机器人走一个已知姿态从外部测量工具方向确认一致后再写进视觉标定代码。5.3 异常处理与安全位try-catch和看门狗思路URScript支持try...catch和很多语言一样用来捕获运行时错误。运动超程、到达奇异点、Socket读超时都可能触发异常。生产程序里不能放任异常弹出后机器人停在半空必须有一个兜底动作。我的标准写法是主流程里对关键运动包一层try...catch出错后立刻让机器人以慢速回到安全位同时点亮故障灯并把错误代码输出到日志。try: movel(target, a1.2, v0.25) catch: textmsg(运动异常回安全位) set_digital_out(7, True) # 故障灯 movej(safe_pose, a0.8, v0.2) end这里强调一个“安全位”的概念每一个新工站布局完成后的第一件事不是写生产程序而是先示教一个不会撞任何东西的safe_pose并把它放在脚本常量区。所有异常处理、手动恢复、程序启动、程序结束都以安全位为起点或终点。这是我从多次现场事故里换来的教训宁可在安全位上多花半小时也不要让异常恢复路径全靠临场发挥。6. 从Demo到交付我用URScript攒下的几条经验6.1 用注释和头部分区把脚本当成工程文件维护URScript脚本在产线上不是一次性Demo它会被客户操作工、售后工程师、后来的调试同事反复翻阅。所以我把脚本当作工程项目文件来维护文件开头固定一个头部模板# # 项目XX产线-工站2 # 版本V1.3 # 更新2024-05-12 增加视觉偏差滤波 # 更新2024-04-28 修改放置区间距 # 维护张三 # # 常量区 SAFE_POSE p[0.0, -0.6, 0.5, 0.0, 0.0, 0.0] PICK_OFFSET p[0.0, 0.0, 0.05, 0.0, 0.0, 0.0] SPEED_FAST 0.3 SPEED_SLOW 0.08版本号和更新记录看起来土但现场价值极大。很多时候问题“不知道什么时候变差的”一查版本记录就能定位到某次改动。我现在用Git管理所有UR项目脚本哪怕只有一个人开发也保留完整历史这让我敢放心改代码。6.2 URScript节点与图形节点的混合编排不要觉得学了URScript就必须把整个程序全改成脚本。我的实践是点位示教、手动测试、I/O单点调试继续用图形界面和示教器因为拖拽和摇杆在这些场景下效率最高而主流程的编排、逻辑判断、数据通信全部收敛到URScript节点里。Polyscope里可以直接插入“URScript”节点在图形程序中执行一段脚本也能用“变量”节点给脚本里的参数喂值。最舒服的配合方式是客户或工艺工程师需要调整的位置、速度、延时统统做成图形节点顶部的变量让他们在触摸屏上就能改不用进脚本。代码和界面各干各擅长的活交付后客户自己也能微调售后压力小很多。6.3 如果要系统学习URScript我的建议路线经常有人问怎么学URScript效率最高我给的建议从来不是“先去把官方手册背一遍”而是按这条路线走在Polyscope里拖一个简单程序打开“脚本”标签把生成的代码从头到尾读一遍。写一个循环运动脚本让机器人按一定顺序跑过5个示教点练习for循环、movej、movel的配合。加一段Socket通信用电脑上的TCP调试工具和机器人互相收发数据搞懂端口、超时、解析。完整阅读官方Script Manual的函数列表不需要背但要知道“URScript还有这个能力”用到时能想起来。找一个带视觉抓取的参考项目把坐标变换、异常处理、安全位这些工程细节串起来。我一直觉得UR这台机器人的上限很大程度取决于你对URScript的熟悉程度。图形界面让新手三天能上手而URScript决定你能在这个平台上走多远。带新人的时候我第一步就是让他们打开“脚本”标签把图形界面生成的代码读一遍。等哪一天他不再怕那堆ASCII字符UR机器人对他来说才算真正解锁了。这也是我写这篇长文最想传达的一件事。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑