目录
任务描述
机器人拆垛与码垛工作站创建
机器人拆垛与码垛工作流程分析
机器人位置偏移函数介绍
机器人拆垛与码垛应用示教编程
机器人拆垛与码垛虚拟仿真
任务描述
在RobotStudio软件中创建ABB机器人拆垛与码垛工作站,并示教机器人拆垛与码垛程序,实现机器人拆垛与码垛应用虚拟仿真。ABB机器人的型号规格、工具等外围设备根据实际需要自行选定。
拆垛垛块排序如下图所示,垛块长度为600mm,宽度为200mm,高度也为200mm。垛块共码放了3层,每一层码放8块。每一层的垛块横向摆放6块,竖向摆放2块,并且层与层之间垛块采用混合交叉方式码放。
码垛垛块排序与拆垛垛块排序方式基本一致,也是码放3层,每层横竖码放共8块,层与层之间也是采用混合交叉码放方式,只是码垛垛块的码放位置与拆垛垛块的码放位置为镜像对称码放,如下图所示。
机器人拆垛与码垛工作站创建
在RobotStudio软件中创建虚拟仿真项目,添加一台ABB机器人模型,机器人使用吸盘工具,可从外部导入设计好的三维模型。再添加两个托盘,并布局到合适位置,其中一个用于码放拆垛垛块,另一个用于码放码垛垛块。
按照任务描述要求,使用软件自带的模型创建功能创建码垛垛块。垛块创建好后,将垛块一层一层地码放到拆垛托盘上。在码垛托盘上也分别横竖码放两个垛块,作为机器人示教编程的位置参考。模型全部布局完成后,其效果如下图所示。
从布局创建ABB机器人虚拟系统,然后添加动态吸盘Smart组件,用来吸取与释放垛块。动态吸盘Smart组件的添加方法可参考之前发布过的文章《RobotStudio软件:机床上下料工作站机器人工具Smart组件添加》,这里不再过多介绍。
机器人拆垛与码垛工作流程分析
机器人码垛应用其实也是一种搬运应用,只是这种应用是机器人按照一定的规律重复点对点的运动路径的搬运应用。机器人拆垛应用可以看作是机器人码垛运动的逆运行。
一般情况下,机器人码垛的垛块规格、码垛的层数以及每一层垛块的码放个数、码放样式都是固定的,并且具备一定的数学运算关系,通过这个数学运算关系就能规划出机器人拆垛与码垛应用的运动路径。
如下图所示,是本例ABB机器人拆垛与码垛应用的工作原理示意图。机器人位于拆垛垛块与码垛垛块中间,也就是大地坐标系位置处,两边的垛块码放位置关于大地坐标系YZ轴所在平面镜像对称。工作时,机器人先由左侧的拆垛托盘上从右向左、从上向下依次吸取垛块;然后运动到右侧的码垛托盘处从右向左、从下向上依次释放垛块。
如果将码垛托盘上序号为1的垛块与序号为7的垛块分别作为机器人吸取垛块的示教点,以大地坐标系为参考,那么其余的垛块的示教点就可以看作是这两个垛块的示教点沿着大地坐标系X、Y、Z轴按照一定的距离的动态偏移。
机器人拆垛运动过程与码垛运动过程基本相同,只是示教点的偏移方向与码垛示教点的偏移方向在大地坐标系Y轴与Z轴方向上相反。
机器人位置偏移函数介绍
根据上述分析可知,在对机器人示教编程时,除了要用到机器人的常规运动指令外,还要用到另外一种运动功能,即机器人位置偏移函数。
市面上常见的工业机器人都具备这种位置偏移函数,当然,ABB机器人也不例外。“Offs”就是ABB机器人的位置偏移函数,它的功能是用于在已有的机器人位置的工件坐标系中添加一个偏移量。这里一定要注意,它是在机器人的工件坐标系中叠加的偏移量,其完整的函数语句格式如下图所示。
函数Offs中Point的数据类型为robtarget,其余三个偏移量的数据类型均为num。
机器人拆垛与码垛应用示教编程
在ABB机器人虚拟示教器中创建机器人拆垛与码垛例行程序,首先将机器人各个关节手动运行到合适位置,然后将当前姿态示教为机器人HOME点程序,示教点名称为pHome。
再将机器人分别手动运行到拆垛托盘上的1号、7号垛块处,以及码垛托盘上的1号、7号垛块处,并示教出这4个机器人姿态的点位程序,4个示教点分别命名为pLPick、pLPick90、pRPlace、pRPlace90。
在示教过程中,机器人TCP使用标定好的吸盘工具TCP,工件坐标系使用默认的工件坐标系(wobj0)。当然,工件坐标系也可以分别在拆垛托盘和码垛托盘上分别标定。这里要注意的是,一般情况下,在RobotStudio软件中ABB机器人默认工件坐标系(wobj0)通常与虚拟仿真环境中的大地坐标系重合。
机器人拆垛与码垛程序关键点示教完成后,根据上述工作流程分析即可编写出机器人工作逻辑判断程序以及垛块吸取与释放位置偏移程序,完整的程序代码如下图所示。
完整的ABB机器人拆垛与码垛程序代码如下所示。
MODULE Module1
CONST robtarget pHome:=[[1405.50,0.00,1620.00],[2.35481E-8,-7.53893E-9,1,-1.77528E-16],[0,0,-1,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
CONST robtarget pLPick:=[[1600.00,-1100.00,740.00],[1.01751E-7,-1.31278E-7,1,-7.4175E-8],[-1,-1,-1,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
CONST robtarget pRPlace:=[[1600.00,1100.00,340.00],[9.86443E-9,-1.70914E-8,1,-1.23181E-8],[0,-1,0,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
CONST robtarget pLPick90:=[[1400.00,-700.00,740.00],[1.50459E-7,0.707107,0.707107,-6.22807E-8],[-1,-1,0,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
CONST robtarget pRPlace90:=[[1400.00,700.00,340.00],[8.97325E-9,0.707107,0.707107,4.92759E-9],[0,-1,1,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
PERS robtarget pLPickSafety:=[[800,-700,640],[1.50459E-7,0.707107,0.707107,-6.22807E-8],[-1,-1,0,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
PERS robtarget pRPlaceSafety:=[[800,700,1040],[8.97325E-9,0.707107,0.707107,4.92759E-9],[0,-1,1,0],[9E+9,9E+9,9E+9,9E+9,9E+9,9E+9]];
CONST num L:=600;
CONST num W:=200;
CONST num H:=200;
CONST num LHNum:=6;
CONST num LVNum:=2;
CONST num Layer:=3;
PROC main()
MoveJ pHome, v1500, fine, tVacuume;
Reset doVacuume;
FOR i FROM 1 TO (LHNum+LVNum)*Layer DO
!First layer horizontal
IF i<=LHNum THEN
!Pick
pLPickSafety:=Offs(Offs(pLPick,-W*(i-1),0,-H*(Layer-3)),0,0,300);
MoveJ pLPickSafety, v1500, z50, tVacuume;
MoveL Offs(pLPick,-W*(i-1),0,-H*(Layer-3)), v1000, fine, tVacuume;
Set doVacuume;
WaitDI diVacuumeOK,1;
MoveL pLPickSafety, v1000, fine, tVacuume;
!Place
pRPlaceSafety:=Offs(Offs(pRPlace,-W*(i-1),0,H*(Layer-3)),0,0,300);
MoveJ pRPlaceSafety, v1500, z50, tVacuume;
MoveL Offs(pRPlace,-W*(i-1),0,H*(Layer-3)), v1000, fine, tVacuume;
Reset doVacuume;
WaitDI diVacuumeOK,0;
MoveL pRPlaceSafety, v1000, fine, tVacuume;
!First layer vertical
ELSEIF i>LHNum AND i<=(LHNum+LVNum) THEN
!Pick
pLPickSafety:=Offs(Offs(pLPick90,-L*(i-LHNum-1),0,-H*(Layer-3)),0,0,300);
MoveJ pLPickSafety, v1500, z50, tVacuume;
MoveL Offs(pLPick90,-L*(i-LHNum-1),0,-H*(Layer-3)), v1000, fine, tVacuume;
Set doVacuume;
WaitDI diVacuumeOK,1;
MoveL pLPickSafety, v1000, fine, tVacuume;
!Place
pRPlaceSafety:=Offs(Offs(pRPlace90,-L*(i-LHNum-1),0,H*(Layer-3)),0,0,300);
MoveJ pRPlaceSafety, v1500, z50, tVacuume;
MoveL Offs(pRPlace90,-L*(i-LHNum-1),0,H*(Layer-3)), v1000, fine, tVacuume;
Reset doVacuume;
WaitDI diVacuumeOK,0;
MoveL pRPlaceSafety, v1000, fine, tVacuume;
!Second layer horizontal
ELSEIF i>LHNum+LVNum AND i<=2*(LHNum+LVNum)-LVNum THEN
!Pick
pLPickSafety:=Offs(Offs(pLPick,-W*(i-LHNum-LVNum-1),W,-H*(Layer-2)),0,0,300);
MoveJ pLPickSafety, v1500, z50, tVacuume;
MoveL Offs(pLPick,-W*(i-LHNum-LVNum-1),W,-H*(Layer-2)), v1000, fine, tVacuume;
Set doVacuume;
WaitDI diVacuumeOK,1;
MoveL pLPickSafety, v1000, fine, tVacuume;
!Place
pRPlaceSafety:=Offs(Offs(pRPlace,-W*(i-LHNum-LVNum-1),-W,H*(Layer-2)),0,0,300);
MoveJ pRPlaceSafety, v1500, z50, tVacuume;
MoveL Offs(pRPlace,-W*(i-LHNum-LVNum-1),-W,H*(Layer-2)), v1000, fine, tVacuume;
Reset doVacuume;
WaitDI diVacuumeOK,0;
MoveL pRPlaceSafety, v1000, fine, tVacuume;
!Second layer vertical
ELSEIF i>2*(LHNum+LVNum)-LVNum AND i<=2*(LHNum+LVNum) THEN
!Pick
pLPickSafety:=Offs(Offs(pLPick90,-L*(i-2*LHNum-LVNum-1),-L,-H*(Layer-2)),0,0,300);
MoveJ pLPickSafety, v1500, z50, tVacuume;
MoveL Offs(pLPick90,-L*(i-2*LHNum-LVNum-1),-L,-H*(Layer-2)), v1000, fine, tVacuume;
Set doVacuume;
WaitDI diVacuumeOK,1;
MoveL pLPickSafety, v1000, fine, tVacuume;
!Place
pRPlaceSafety:=Offs(Offs(pRPlace90,-L*(i-2*LHNum-LVNum-1),L,H*(Layer-2)),0,0,300);
MoveJ pRPlaceSafety, v1500, z50, tVacuume;
MoveL Offs(pRPlace90,-L*(i-2*LHNum-LVNum-1),L,H*(Layer-2)), v1000, fine, tVacuume;
Reset doVacuume;
WaitDI diVacuumeOK,0;
MoveL pRPlaceSafety, v1000, fine, tVacuume;
!Third layer horizontal
ELSEIF i>2*(LHNum+LVNum) AND i<=3*(LHNum+LVNum)-LVNum THEN
!Pick
pLPickSafety:=Offs(Offs(pLPick,-W*(i-2*LHNum-2*LVNum-1),0,-H*(Layer-1)),0,0,300);
MoveJ pLPickSafety, v1500, z50, tVacuume;
MoveL Offs(pLPick,-W*(i-2*LHNum-2*LVNum-1),0,-H*(Layer-1)), v1000, fine, tVacuume;
Set doVacuume;
WaitDI diVacuumeOK,1;
MoveL pLPickSafety, v1000, fine, tVacuume;
!Place
pRPlaceSafety:=Offs(Offs(pRPlace,-W*(i-2*LHNum-2*LVNum-1),0,H*(Layer-1)),0,0,300);
MoveJ pRPlaceSafety, v1500, z50, tVacuume;
MoveL Offs(pRPlace,-W*(i-2*LHNum-2*LVNum-1),0,H*(Layer-1)), v1000, fine, tVacuume;
Reset doVacuume;
WaitDI diVacuumeOK,0;
MoveL pRPlaceSafety, v1000, fine, tVacuume;
!Third layer vertical
ELSE
!Pick
pLPickSafety:=Offs(Offs(pLPick90,-L*(i-3*LHNum-2*LVNum-1),0,-H*(Layer-1)),0,0,300);
MoveJ pLPickSafety, v1500, z50, tVacuume;
MoveL Offs(pLPick90,-L*(i-3*LHNum-2*LVNum-1),0,-H*(Layer-1)), v1000, fine, tVacuume;
Set doVacuume;
WaitDI diVacuumeOK,1;
MoveL pLPickSafety, v1000, fine, tVacuume;
!Place
pRPlaceSafety:=Offs(Offs(pRPlace90,-L*(i-3*LHNum-2*LVNum-1),0,H*(Layer-1)),0,0,300);
MoveJ pRPlaceSafety, v1500, z50, tVacuume;
MoveL Offs(pRPlace90,-L*(i-3*LHNum-2*LVNum-1),0,H*(Layer-1)), v1000, fine, tVacuume;
Reset doVacuume;
WaitDI diVacuumeOK,0;
MoveL pRPlaceSafety, v1000, fine, tVacuume;
ENDIF
ENDFOR
MoveJ pHome, v1500, fine, tVacuume;
ENDPROC
ENDMODULE
机器人拆垛与码垛虚拟仿真
在RobotStudio软件中对ABB机器人仿真运行,其中一段的仿真运行效果如下方动态图所示,可以看到机器人从拆垛托盘上吸取垛块,并按照一定的码放顺序将其码放到码垛托盘上。
The End
上一篇:ABB机器人:工件坐标系介绍以及标定操作与使用方法