刻字机尖角补偿

2023-11-11 23:50
文章标签 补偿 尖角 刻字机

本文主要是介绍刻字机尖角补偿,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 刻字机尖角补偿原理

刀具切割直线段过渡方法在文章旋转偏心裁切刀切向跟踪及半径补偿 已经有过说明。刻字机由于刀具半径的影响,切割直角时会不直会比较圆滑,而且在闭合曲线的下刀点会容易不闭合。使用尖角补偿可以克服这些问题。

如上图所示,切割俩条相邻线段AB和BC时,刀心需要走的轨迹是从A' --> B' --> B'' -->C'。由于刻字机使用的刻刀刀尖半径都比较小,而且刀具也是固定没有转动轴控制转动,所以从B'过渡到B''时使用圆弧进行过渡。这里B2和B1都是圆弧上的过渡点。示意图中从B'B''采用小线段B'B2、B2B1、B1B''进行圆弧拟合过渡。

AB的矢量角α,则A'点坐标为(Xa+r*cosα,Ya+r*sinα)。BC的矢量角为β,则B''的坐标为(Xb+r*cosβ,Yb+r*sinβ)。C'的坐标为(Xc+r*cosβ,Yc+r*sinβ)。AB的转角为β-α。

2 尖角补偿python程序实现

import numpy
import cv2
import mathconst_ratio = 10
WIDTH = 100
HEIGHT = 60
KNIFE_CIR = 40 #plt中40个单位=1mm
ANGLE_STEP = 30 #圆弧过渡时插补间隔30度def show_img(window,img):cv2.namedWindow(window,0)cv2.resizeWindow(window,int(img.shape[1]),int(img.shape[0]))cv2.imshow(window,img)def proc_line(line):i = 0signZ = 1if len(line) == 0:return Nonewhile line[i]<'0' or line[i]>'9':if line[i] == 'U':signZ = 0if line[i] == '-':breaki = i+1if i == len(line):return Noneline = line[i:]if len(line) == 0:return Nonestrs = line.split(',')if len(strs) != 2:return Noneaxis_y = int(strs[0])axis_x = int(strs[1])if (axis_x is None) or (axis_y is None):return Nonereturn {'x':axis_x,'y':axis_y,'z':signZ}def plot_plt(cv_img,data,print_width,print_height):height_total = print_heightwidth_total = print_widthline = ""comma = 0points = []for i in range(len(data)):try:ch = chr(data[i])except:ch = data[i]if ch == ';':point = proc_line(line)if point is not None:points.append(point)line = ""comma = 0else:line = line+chif ch==',' or ch==' ':comma = comma+1if comma == 2:point = proc_line(line)if point is not None:points.append(point)line = ""comma = 0max_x = points[0]['x']max_y = points[0]['y']min_x = points[0]['x']min_y = points[0]['y']for point in points:if point['x']>max_x:max_x = point['x']if point['y']>max_y:max_y = point['y']if point['x']<min_x:min_x = point['x']if point['y']<min_y:min_y = point['y']print(max_x,max_y,min_x,min_y)pre_point = points[0]black = (0,255,0)offset_x = 10*const_ratiooffset_y = 10*const_ratiofor point in points:x = int((point['x'])*const_ratio/40+offset_x)y = int((point['y'])*const_ratio/40+offset_y)if point['z'] == 1:cv2.line(cv_img,(pre_point['x'],pre_point['y']),(width_total*const_ratio-x,height_total*const_ratio-y),black,lineType=cv2.LINE_AA)pre_point = {'x':width_total*const_ratio-x,'y':height_total*const_ratio-y}def plot_file(img,filepath):with open(filepath) as f:data = f.read()plot_plt(img,data,WIDTH,HEIGHT)def plot_plt_comp(cv_img,data,print_width,print_height):height_total = print_heightwidth_total = print_widthline = ""comma = 0points = []for i in range(len(data)):try:ch = chr(data[i])except:ch = data[i]if ch == ';':point = proc_line(line)if point is not None:points.append(point)line = ""comma = 0else:line = line+chif ch==',' or ch==' ':comma = comma+1if comma == 2:point = proc_line(line)if point is not None:points.append(point)line = ""comma = 0max_x = points[0]['x']max_y = points[0]['y']min_x = points[0]['x']min_y = points[0]['y']for point in points:if point['x']>max_x:max_x = point['x']if point['y']>max_y:max_y = point['y']if point['x']<min_x:min_x = point['x']if point['y']<min_y:min_y = point['y']print(max_x,max_y,min_x,min_y)#这里开始执行尖角补偿插补计算angleArr = []pointNum = len(points)pre_point = {'x':0,'y':0,'z':0}pre_angle = 0downPoint = NonedownAngle = 0off_x = 0off_y = 0pointsInterpArr = []for i in range(pointNum):point = points[i]angle = math.atan2(point['y']-pre_point['y'],point['x']-pre_point['x'])length = math.sqrt((point['y']-pre_point['y'])*(point['y']-pre_point['y'])+(point['x']-pre_point['x'])*(point['x']-pre_point['x']))angleArr.append(angle)angle_delta = (angle-pre_angle)*180/math.piif angle_delta >= 180:angle_delta = angle_delta-360elif angle_delta <= -180:angle_delta = angle_delta+360if angle_delta>0:angle_step = ANGLE_STEPelse:angle_step = -ANGLE_STEPprint(angle_delta,length)if length == 0:continueelif point['z'] == 0: #抬刀时不处理pointsInterpArr.append(point)elif pre_point['z'] == 0:#由抬刀变为下刀保存下刀点坐标和角度,并进行起点和终点偏移downPoint = pre_pointdownAngle = anglex1=pre_point['x']+KNIFE_CIR*math.cos(angle)y1=pre_point['y']+KNIFE_CIR*math.sin(angle)pointsInterpArr.append({'x':int(x1),'y':int(y1),'z':0})x2 = point['x']+KNIFE_CIR*math.cos(angle)y2 = point['y']+KNIFE_CIR*math.sin(angle)pointsInterpArr.append({'x':int(x2),'y':int(y2),'z':1})off_x = KNIFE_CIR*math.cos(angle)off_y = KNIFE_CIR*math.sin(angle)elif abs(angle_delta)>30:#下刀切割时线段转角大于30度时进行圆弧过渡count = math.floor(angle_delta/angle_step)remain = angle_delta-count*angle_stepfor j in range(0,count):x = pre_point['x']+KNIFE_CIR*math.cos(pre_angle+angle_step*(j+1)*math.pi/180)y = pre_point['y']+KNIFE_CIR*math.sin(pre_angle+angle_step*(j+1)*math.pi/180)pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})if abs(remain) > 0.1:x = pre_point['x']+KNIFE_CIR*math.cos(angle)y = pre_point['y']+KNIFE_CIR*math.sin(angle)pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})delta_x = KNIFE_CIR*math.cos(angle)delta_y = KNIFE_CIR*math.sin(angle)pointsInterpArr.append({'x':int(point['x']+delta_x),'y':int(point['y']+delta_y),'z':point['z']})  off_x = KNIFE_CIR*math.cos(angle)off_y = KNIFE_CIR*math.sin(angle)else:#转角小于30度直接过渡delta_x = KNIFE_CIR*math.cos(angle)delta_y = KNIFE_CIR*math.sin(angle)pointsInterpArr.append({'x':int(point['x']+delta_x),'y':int(point['y']+delta_y),'z':point['z']}) #发现是下刀点坐标时代表曲线段闭合,进行闭合圆弧过渡if downPoint != None and length > 0 and point['x'] == downPoint['x'] and point['y'] == downPoint['y']:angle_delta = (downAngle-angle)*180/math.piif angle_delta >= 180:angle_delta = angle_delta-360elif angle_delta <= -180:angle_delta = angle_delta+360if angle_delta>0:angle_step = ANGLE_STEPelse:angle_step = -ANGLE_STEPcount = math.floor(angle_delta/angle_step)remain = angle_delta-count*angle_stepfor j in range(0,count):x = point['x']+KNIFE_CIR*math.cos(angle+angle_step*(j+1)*math.pi/180)y = point['y']+KNIFE_CIR*math.sin(angle+angle_step*(j+1)*math.pi/180)pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})if abs(remain) > 0.1:x = point['x']+KNIFE_CIR*math.cos(downAngle)y = point['y']+KNIFE_CIR*math.sin(downAngle)pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})pre_point = pointpre_angle = anglepre_point = pointsInterpArr[0]black = (0,255,0)offset_x = 10*const_ratiooffset_y = 10*const_ratiomax_x = pointsInterpArr[0]['x']max_y = pointsInterpArr[0]['y']min_x = pointsInterpArr[0]['x']min_y = pointsInterpArr[0]['y']for point in pointsInterpArr:if point['x']>max_x:max_x = point['x']if point['y']>max_y:max_y = point['y']if point['x']<min_x:min_x = point['x']if point['y']<min_y:min_y = point['y']print(max_x,max_y,min_x,min_y)for point in pointsInterpArr:x = int((point['x'])*const_ratio/40+offset_x)y = int((point['y'])*const_ratio/40+offset_y)if point['z'] == 1:cv2.line(cv_img,(pre_point['x'],pre_point['y']),(width_total*const_ratio-x,height_total*const_ratio-y),black,lineType=cv2.LINE_AA)pre_point = {'x':width_total*const_ratio-x,'y':height_total*const_ratio-y}def plot_file_comp(img,filepath):with open(filepath) as f:data = f.read()plot_plt_comp(img,data,WIDTH,HEIGHT)cv_img = numpy.ones((HEIGHT*const_ratio,WIDTH*const_ratio),dtype=numpy.uint8)
cv_img = cv2.bitwise_not(cv_img)
cv2.rectangle(cv_img,(0,0),(WIDTH*const_ratio-1,HEIGHT*const_ratio-1),(0,0,0))file = 'C:/Users/liuzj/Desktop/plt/rec.plt'
plot_file(cv_img,file)
show_img('img1',cv_img)cv_img2 = numpy.ones((HEIGHT*const_ratio,WIDTH*const_ratio),dtype=numpy.uint8)
cv_img2 = cv2.bitwise_not(cv_img2)
cv2.rectangle(cv_img2,(0,0),(WIDTH*const_ratio-1,HEIGHT*const_ratio-1),(0,0,0))plot_file_comp(cv_img2,file)
show_img('img2',cv_img2)cv2.waitKey(0)

正方形尖角补偿轨迹:

三角形尖角补偿轨迹:

方圆尖角补偿轨迹:

这篇关于刻字机尖角补偿的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/393656

相关文章

svg无功补偿装置脉冲封锁怎么解除

SVG(Static Var Generator,静态无功发生器)脉冲封锁是一种保护机制,用于防止装置在异常情况下继续运行,从而避免对电力系统造成进一步的损害。如果SVG进入脉冲封锁状态,通常需要执行特定的步骤来解除封锁并恢复正常运行。以下是解除SVG脉冲封锁的一般步骤: 1. 检查故障原因 故障诊断:首先,查看SVG的故障记录或报警信息,确定导致脉冲封锁的具体原因。常见的原因包括过电流、过电

智能集成电力补偿电容器提示故障

智能集成电力补偿电容器提示故障可能由多种原因引起,这种设备通常集成了电容器、控制器、保护装置等功能,并具有自诊断和故障提示功能。以下是一些常见的故障原因及其对应的排查和处理方法: 一、电容器故障 1、电容器老化或击穿:电容器经过长时间使用后可能会出现电容值下降或击穿,导致无法正常补偿。 排查方法:使用万用表或电容表测量电容值,与额定值对比,检查是否在正常范围内。若发现明显异常,需要更换电

x264 编码器 AArch64汇编系列:运动补偿之MBtree相关汇编函数

x264_mbtree_propagate_cost_neon c 语言对应的实现函数: 函数参数: dst:指向int16_t类型的指针,用于存储传播成本的结果。propagate_in:指向uint16_t类型的指针,包含输入的传播成本。intra_costs:指向uint16_t类型的指针,包含帧内预测成本。inter_costs:指向uint16_t类型的指针,包含帧间预测成本。

WPS回应“崩了”:提供15天会员补偿,另有新羊毛,你还不来薅?

近期,“WPS崩了”这一话题在时隔两个月后,再次因多名用户反馈软件使用问题而登上微博热搜。 WPS官方微博随后发布消息称,经过工程师的紧急修复,WPS服务已经恢复正常。 为了补偿用户,在8月22日0点至24点期间,可领取15天的免费会员。 在评论区,不少用户急切地催促官方尽快修复,有用户表示“下午要汇报工作,现在所有在线文档都打不开了”,还有用户说“赶快修修吧,着急用文档”,“快点快点,

安科瑞智慧型动态无功补偿的工业应用——以江苏某陶瓷生产企业配电房改造为例

摘要:低压配电系统的无功补偿是电能质量治理的重要环节。在传统无功补偿中,响应速度较慢,补偿电流呈阶梯式,存在过补或欠补的现象,有时未必能到达理想的效果。为了解决这一问题,人们提出了一种无功补偿综合控制方法,通过采集电力系统中的电压、电流及功率,实时协调控制LC(电容电抗)和SVG(静止无功发生器)模块进行混合补偿,又称智慧型动态无功补偿,可以实现补偿电流的连续输出。将此方案应用于工程实际中,结果表

网易云音乐故障 2 小时,这次到底谁背锅?(今天记得领补偿)

大家好,我是程序员鱼皮,8 月 19 日下午,网易云音乐突发严重故障,并登顶微博热搜,跟黑神话悟空抢了热度。 根据用户的反馈,故障的具体表现为:用户无法登录、歌单加载失败、播放信息获取失败、无法搜索歌曲等等,几乎是无法使用了,妥妥的 P0 级事故! 根据官方发布的说明,本次故障的主要原因是基础设施,导致网易云音乐各端无法正常使用: 什么是基础设施?是指支持整个系统运行的基础性服务

永磁同步电机驱动死区补偿

1 死区效应及补偿 1. 1 死区效应 在本文的电机控制嵌入式系统中,逆变器为三 相电压型桥式逆变电路,如图 1 所示。 在理想状态 下,上桥臂和下桥臂的控制信号满足互补通断原则, 即上桥臂开通时,下桥臂关断,反之亦然。 而在实际 应用中,开关管的通断需要一定的开通时间 t on 和关 断时间 t off。 为避免上桥臂和下桥臂发生短路,在 PWM 控制信号中加入死区时间 t d ,驱动信号如

绝地求生PUBG联名补偿奖励来了 补偿奖励介绍详情解析

《绝地求生》(PUBG) 作为一款战术竞技型射击类沙盒游戏,从上线以来就深受玩家小伙伴们的喜爱,即便是没有玩过的小伙伴,对“吃 鸡”二字想必也是很耳熟的,这正是《绝地求生》(PUBG) 的别称。 在北京时间6月12日,由于绝地求生官方团队疏忽而导致了NewJeans典藏箱保底规则显示错误,而该问题也是给广大的游戏玩家带来了一些困扰。为了表示歉意,以及感谢广大玩家们对游戏的信任,游戏官方也是给出了

模块[camera]_摄影基础知识: 曝光补偿完全指南

 转自:http://hd3g.gxnews.com.cn/viewthread.php?t=7410090 摄影基础知识: 曝光补偿完全指南 作者:苞谷汁儿[1楼] 用过数码相机的朋友也许会注意到一个细节,在相机的手册里或者菜单里都可以发现一个叫“EV”的可变参数,EV就是曝光补偿,这个不起眼的EV参数你会使用吗?什么是“曝光补偿”的含义呢?这就是本文所要讲的主题。

外汇天眼:金融服务补偿计划(FSCS)确认已任命清算人为TenetConnect Services有限公司

2024年6月5日,Tenet Group有限公司的董事们任命了Interpath有限公司的Ed Boyle、Howard Smith和Rob Spence为联合清算人。Ed Boyle和Rob Spence也被任命为其子公司Tenet有限公司、TenetConnect有限公司和TenetConnect Services有限公司的联合清算人。Tenet Mortgage Services有限公司和