dxf文件在2D图形中使用广泛,将图形文件自动转换为机械手可识别的轨迹代码是机械手全自动化中一个软件衔接节点。理想的轨迹自动化转换程序可以在电脑里面直接虚拟仿真生成机械手轨迹,简化现场人员机械手示教流程,在效率和远程支持上有着实际的应用前景。

但是类似dxf格式的图形文件无法直接被机械手使用,原因是:一 存在格式解析问题;二 dxf文件需要针对不同应用进行一些参数调整和轨迹增删后才具备实用价值。开发一套能够将CAD图形文件转换为库卡机械手可识别的src格式文本的软件是有其实际的实用性。本文讨论借用现有的FreeCAD进行显示,通过编写插件解析的方式来实现dxf文件转库卡机械手src。

首先要了解dxf文件的特点:

dxf文件是以entity为单位的基本形状的组合体,较简单的图形应用中则主要以line和circle这样的基本单元,其中的line只有起点和终点,circle则由中心点,半径,起始和结束角组成。理想的dxf文件应该是人眼观察到的每个单元头尾相连构成一个完整的2D/3D图形,但是实际中图形文件可能隐含非常短的小线段或很小的面积(作图人员的随意)、各个单元的数据也可能没有按照头尾相连的顺序(里面的元素是按照作图人员画图顺序存放的),对于要求精度不高且对机械手运行速度有要求的应用场景,机械手轨迹无需考虑这些小段和面积(过多的细线段会导致更多的点发给机械手,导致机械手运行速度降低),需要算法对dxf文件的entity进行过滤、排序才可用于后续分析。

3D的stp文件则存在一个在3D曲面上选取线的问题,由于3d曲面也是由多个面组成,对面(face)的过滤规则可以考虑选用面的‘脊’来作为轨迹路线,比如限定基于Z轴方向最高的面作为轨迹选取面,可以通过求取该面两边的中值作为轨迹点的值。但是这种假设要求提供的图形必须按照这个规律做好预处理,否则无法正确提取轨迹。

不同应用对生成的轨迹要求不同,我对已知机械手的轨迹分为三类:

1 巡边类  该类轨迹并非是dxf文件展示的图形,而是由dxf的轨迹数据结合特定特征点比如拐角通过算法生成额外的空间补偿数据组合生成(自动插入额外点)。这类需求一般对走位的精度要求不高,但是要求能够自行生成dxf文件提供的额外的插补点位置,同时要求在保证合适精度前提下尽量减少点的数目以确保机械手运行速度。实现对应功能该类算法需要考虑:机械手执行速度、额外的轨迹补偿点。比如下图左上角两个空中轨迹点就是巡边过程中算法在空间插入的额外轨迹点:

2 画图类  一般是机械手在一个面上进行类似画图的移动操作,该类轨迹为以非闭合多段线为主,多数对精度有要求,故需要尽可能还原原始轨迹数据点且不能自行插入额外数据。比如下图就是机械手点的轨迹图:

3 3D 轨迹类  这类作业面为非平面,故需要对3D的图形进行分析和3D的空间轨迹规划。

三类文件的共性需求包括:

中点重新定位   生成的机械手轨迹坐标选取到目标本身是合理的,这样图形坐标系和机械手坐标系才可以进行关联和转换,在提供的dxf文件多数坐标系零点并非构建在目标物体身上,故需要进行偏移转换。

旋转  由于现场目标物体的摆放位置可能具有一定的旋转,生成的轨迹坐标也需要支持旋转功能。

进出点 对于闭合曲线,必须能够定义机械手进入和退出的点位信息。

单独编辑功能  用户应该可以自行修改生成点位的位置信息。

考虑到同时要支持2D和3D且图形编辑需要尽可能的自由性,可以选用开源软件FreeCAD作为主体软件,通过编写FreeCAD的插件实现上述各类图形文件的解析过程。不同于原始dxf信息,我们直接使用被FreeCAD转化过的图形元素。

技能要求

1 python编程含调试

2 平面和立体几何

3 了解机械手的运动特点

4 了解几种轨迹的路线要求

下面简单介绍一下python如何和FreeCAD的dxf文件进行交互。

objs=App.ActiveDocument.Objects  --->获取当前激活的dxf文档的对象数组

Gui.activateWorkbench("DraftWorkbench")-->切换到draft工作环境

Gui.ActiveDocument.ActiveView.setAxisCross(True)-->显示坐标轴

sel = FreeCADGui.Selection.getSelection()--->获取图形元素,注意dxf图像中不同层会放到sel数组不同的元素里。

Draft.move(sel[0],FreeCAD.Vector(offset_x,offset_y,0),copy=False)--->重定位图形到新的坐标位置

Draft.rotate(sel[0], rotation-current_angle, FreeCAD.Vector(0.0, 0.0, 0.0), axis=FreeCAD.Vector(0.0, 0.0, 1.0), copy=False)  旋转图形到指定角度

w0 =sel[0][0].Shape  获取shape

shape是由许多edge组成,比如下面代码段可以提取长度超过1的edges。

for e in w0.Edges:

if e.Length >=1:

useful_edges.append(e)

对提取的edges数组可以进行拼接:
cedges=OpenSCAD2Dgeom.findConnectedEdges(useful_edges,eps=1)

对拼接的cedges进行分析拆出里面具体元素的信息:

for edges in cedges:

tmp_points=[]

last_points=None  #used for decide if that segment should be reversed.

for e in edges:

typ=None

center=None

if (str(e.Curve)[1:5] == "Line"):

points = [e.Vertexes[0].Point, e.Vertexes[1].Point]

typ='LIN'

elif (str(e.Curve)[0:6]  == "Circle"):

points=e.discretize(Number=3)

typ='CIRC'

center=e.Curve.Center

if last_points!=None:

if self.pointsequals(last_points[-1],points[-1]):

points.reverse()

last_points=points

tmp_points.append((typ,accurate_vertexs(points),center))

if revers ==0:

for i in tmp_points:

i[1].reverse()

tmp_points.reverse()

contour_points=[]

end_point=None

end_angle=None

for cp in tmp_points:  #calculate the angle

if cp[0]=='LIN':

v=cp[1][1].sub(cp[1][0])

angle=self.get_relative_angle(v)

contour_points.append((cp[0],cp[1][0],round(angle,2)))

end_point=cp[1][1]

end_angle=angle

#self.place_arrow(cp[1][0],angle)

elif cp[0]=='CIRC':

clockwise=self.Is3PointClockWise(cp[2],cp[1][0],cp[1][1])

v1=cp[1][0].sub(cp[2])

v2=cp[1][1].sub(cp[2])

v3=cp[1][1].sub(cp[1][0])

angle1=v2.getAngle(v1)*180/pi

rangle=self.get_relative_angle(v3)

if clockwise:

angle1=rangle+angle1/2

else:

angle1=rangle-angle1/2

v1=cp[1][1].sub(cp[2])

v2=cp[1][2].sub(cp[2])

v3=cp[1][2].sub(cp[1][1])

angle2=v2.getAngle(v1)*180/pi

rangle=self.get_relative_angle(v3)

if clockwise:

angle2=angle2/2+rangle

else:

angle2=rangle-angle2/2

contour_points.append((cp[0],cp[1][0],round(angle1,2),cp[1][1],round(angle2,2)))

end_point=cp[1][2]

end_angle=round(angle2,2)

#self.place_arrow(cp[1][0],angle1)

#self.place_arrow(cp[1][1],angle2)

self.progressBar.setValue(cedges.index(edges)+1)

contour_points.append(('LIN',end_point,end_angle)) #since there are only one point available, we use 'lin' to implement it.

layout_contours.append(contour_points)

layout_contours=self.sortTracks(layout_contours)

进一步对layout_contours数据分析并转化为机械手的代码(这里以库卡机械手为例):

def get_layout_data(self):

targetData=''

index=0

seq=0

point=layout_contours[0][0][1]

angle=layout_contours[0][0][2]

stmp='LIN {E6POS: X '+str(point.x)+', Y '+str(point.y)+', Z 30.000, A '+str(angle) +', B 0.000, C 0.000, E1 0.000} C_VEL'+';'

targetData=targetData+stmp+'\n'

seq+=1

stmp='LIN {E6POS: X '+str(point.x)+', Y '+str(point.y)+', Z 0.000, A '+str(angle)+', B 0.000, C 0.000, E1 0.000} C_VEL'+';'+str(seq)

targetData=targetData+stmp+'\n'

seq+=1

for tr in layout_contours:

targetData+=';*******************track:'+str(layout_contours.index(tr))+'*************************'+'\n'

for e in tr:

if e[0]=='LIN':

point=e[1]

angle=e[2]

stmp='LIN {E6POS: X '+str(point.x)+', Y '+str(point.y)+', Z 0.000, A '+str(angle)+', B 0.000, C 0.000, E1 0.000} C_VEL'+';'+str(seq)

targetData=targetData+stmp+'\n'

seq+=1

elif e[0]=='CIRC':

point1=e[1]

angle1=e[2]

point2=e[3]

angle2=e[4]

stmp ='CIRC {POS: X ' + str(point1.x) + ', Y ' + str(point1.y) + ', Z 0.0, A ' +str(angle1) + ', B 0.0, C 0.0},'+'{POS: X ' + str(point2.x) + ', Y ' + str(point2.y) + ', Z 0.0, A ' + str(angle2) + ', B 0.0, C 0.0} C_VEL' + ';' + str(seq)

targetData=targetData+stmp+'\n'

seq+=2

targetData=targetData+'END\n'

return targetData

转换过程由于需要输入参数,可以自己设计一个界面:

最后生成的src文件大致如下:

基于FreeCAD的dxf转机械手代码的一种实现方法相关推荐

  1. 代码的两种命名方法:驼峰命名、匈牙利命名(优缺点)

    代码的两种命名方法:驼峰命名.匈牙利命名(优缺点) 一.骆驼命名法: 小驼峰法(camel方法)变量一般用小驼峰法标识. 第一个单词以小写字母开始:第二个单词的首字母大写或每一个单词的首字母都采用大写 ...

  2. html语言空格怎么写,html中如何插入空格字符代码的6种书写方法

    在学习插入空格字符代码书写方法之前,我们要知道,html代码的空格字符,在浏览器中,总会被压缩为一个字符!也就是说,你在html文本中输入多个空格,但在浏览器中,只会保留显示一个字符,其余的都将被浏览 ...

  3. VScode——无法调试代码的一种解决方法

    原因: 直接打开这个代码文件,未从项目文件夹中打开. 解决方法: 利用VScode打开该项目的文件夹,之后再从文件夹下面打开该文件.

  4. ASP代码的2种调试方法

    2种方式调试ASP 代码 1, 去找这个软件 ASPStudio 可以调试您的ASP代码, 还可以将您的ASP代码保护封装成DLL,支持ASP代码设置断点!比较牛的一个软件 2. 用Visual St ...

  5. 基于jQuery垂直多级导航菜单代码

    基于jQuery垂直多级导航菜单代码是一款黑色风格的jQuery竖直导航菜单特效下载.效果图如下: 在线预览    源码下载 实现的代码. html代码: <ul class="ce& ...

  6. 基于jQuery图片自适应排列显示代码

    基于jQuery图片自适应排列显示代码.这是一款基于jquery.flex-images插件实现的类似谷歌图片流效果.效果图如下: 在线预览    源码下载 实现的代码. html代码: <di ...

  7. 基于ceres的后端优化的代码实现

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 来源丨从零开始搭SLAM 作者丨李太白lx 由于g2o天然是进行位姿图优化的, 所以十分契合karto ...

  8. java字典写实例,基于JAVA的新华字典接口调用代码实例

    基于JAVA的新华字典接口调用代码实例 接口描述:基于JA V A的新华字典接口调用代码实例 接口平台:聚合数据 import java.io.BufferedReader; import java. ...

  9. cpu java poi 导出_java基于poi导出excel透视表代码实例

    这篇文章主要介绍了java基于poi导出excel透视表代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从前,我是一个前端程序猿,怀着对打通 ...

最新文章

  1. 软工作业 5:词频统计——增强功能
  2. 无法提升彼此,夫妻关系就要终结?
  3. Oracle的DECODE函数
  4. 使用注解方式进行aop编程(代码)
  5. [蓝桥杯2016初赛]密码脱落
  6. COM, COM+ and .NET 程序集的区别
  7. request获取各种路径总结
  8. Windowstelnet服务怎么开启 Win11telnet服务怎么开启详细介绍
  9. 科研院所推进6S管理的难点及推进手段分析
  10. Linux的sh脚本编写基础知识
  11. 夏季养生要以“清”为贵
  12. David Silver强化学习公开课自学笔记——Lec2马尔科夫决策过程
  13. SpringBoot整合Thymeleaf+EasyExcel实现excel文件的读取并展示,附加swagger2配置(超详细示范!)
  14. 数据结构个人笔记 第12课 数组
  15. ErrMsg:server is DOWN now, please try again later!
  16. Task 03 python与word
  17. Python函数:np.sum()以及axis=0、axis=1用法
  18. MarbleGame优化解法
  19. 手把手教你获取x信本地数据库(利用Sqlcipher查看)
  20. 王红 中国民航大学计算机学院,计算机编程(王红)

热门文章

  1. chrome浏览器快速切换搜索引擎
  2. 获取中国知网第一页论文的所有摘要
  3. 3D建模学习需要使用Zbrush软件,对电脑配置的要求是什么?
  4. 【西瓜书+南瓜书】学习笔记2
  5. 使用js实现二级菜单栏切换
  6. 电脑系统崩溃重装系统
  7. Android开发-动态获取电视盒子U盘的插拔状态和路径
  8. 【防火墙静态NAT转换】
  9. 平时996,生病ICU!杭州90后小伙昨晚晕倒在之江大桥上,同事说他天天加班
  10. 深度学习测试-DeepXplore