刻字机尖角补偿

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.mzph.cn/news/81536.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上海亚商投顾:沪指放量反弹 医药、AI概念股集体走强

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数早间震荡反弹&#xff0c;午后集体拉升涨超1%&#xff0c;深成指一度涨超1.5%&#xff0c;随后涨幅略…

【JDK 8-Lambda】3.2 自定义函数式编程实战

一、自定义lambda接口流程 需求 : 定义一个可以使用加减乘除的接口 Stage 1&#xff1a;定义一个函数式接口 Stage 2&#xff1a;写一个方法&#xff0c;输入需要操做的数据和接口 Stage 3&#xff1a;运行结果 一、自定义lambda接口流程 需求 : 定义一个可以使用加减乘除的…

Web 器学习笔记(基础)

Filter 过滤器 概念&#xff1a;表示过滤器&#xff0c;是 JavaWeb 三大组件&#xff08;Servlet、Filter、Listener&#xff09;之一 作用&#xff1a;顾名思义可以过滤资源的请求&#xff0c;并实现特殊的需求 Filter 接口及它核心的 doFilter() 方法&#xff08;执行前就是…

激光焊接汽车PP塑料配件透光率测试仪

随着汽车主机厂对车辆轻量化的需求越来越强烈&#xff0c;汽车零部件轻量化设计、制造也成为汽车零部件生产厂商的重要技术指标。零部件企业要实现产品的轻量化&#xff0c;在材料指定的情况下&#xff0c;要通过产品设计优化、产品壁厚减小和装配方式的优化来解决。使用PP材料…

Rocketmq并发和顺序消费的失败重试机制

文章目录 问题并发消费触发时机客户端发起请求 CONSUMER_SEND_MSG_BACKBroker处理CONSUMER_SEND_MSG_BACK请求 顺序消费Q&A消费的时候是一批的消息, 如果其中某条消费失败了,是所有的消息都会被重试吗&#xff1f;用户可以自己控制重试次数、重试间隔时间吗?批量消费消息,…

Kubernetes网络揭秘:看完你就懂了

一、Master集群网络 master集群的网络比较简单&#xff0c;和通常的负载均衡集群一样。多个节点的apiserver的ip与端口(6443)使用负载均衡的ip与端口。在master/node节点join时均使用此负载均衡的ip与端口&#xff0c;这样就是master节点的集群网络。 master 节点之间的网络&a…

arm栈推导

按照栈生长方向分&#xff1a;可以分为递增栈&#xff08;向高地址生长&#xff09;&#xff1b;递减栈&#xff08;向低地址生长&#xff09; 按照sp执行位置来分&#xff1a;满栈&#xff08;sp指向栈顶元素的位置&#xff09;&#xff1b;空栈&#xff08;sp指向即将入栈的…

利用爬虫技术自动化采集汽车之家的车型参数数据

导语 汽车之家是一个专业的汽车网站&#xff0c;提供了丰富的汽车信息&#xff0c;包括车型参数、图片、视频、评测、报价等。如果我们想要获取这些信息&#xff0c;我们可以通过浏览器手动访问网站&#xff0c;或者利用爬虫技术自动化采集数据。本文将介绍如何使用Python编写…

MATLAB中findpeaks函数用法

目录 语法 说明 示例 在MATLAB中&#xff0c;findpeaks函数用于查找信号中的峰值&#xff08;peaks&#xff09;。以下是findpeaks函数的基本语法、说明以及示例&#xff1a; 语法 [pks,locs] findpeaks(x) [pks,locs] findpeaks(x, Name, Value)说明 参数说明 x&…

勒索病毒最新变种.halo勒索病毒来袭,如何恢复受感染的数据?

摘要&#xff1a; .halo勒索病毒已成为数字世界中的威胁&#xff0c;通过高级加密技术将文件锁定&#xff0c;并要求支付赎金。本文91数据恢复将深入介绍.halo勒索病毒的工作原理&#xff0c;提供解锁被感染文件的方法&#xff0c;以及探讨如何有效预防这一威胁。如果您正在经…

87 # express 应用和创建应用的分离

创建应用的过程和应用本身要进行分离。路由和创建应用的过程也做一个分离。 下面实现创建应用的过程和应用本身要进行分离&#xff1a; express.js const Application require("./application");function createApplication() {// 通过类来实现分离操作return ne…

unity UDP 通信

客户端 接收端 &#xff1a; using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine; using UnityEngine.UI;public cla…

常见音视频、流媒体开源编解码库及官网(四十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

Unity中Shader抓取屏幕并实现扭曲效果(优化)

文章目录 前言一、在之前顶点着色器的输入中&#xff0c;放弃了使用结构体传入&#xff0c;而是直接从应用程序阶段传入参数&#xff0c;这样写的话&#xff0c;对于程序来说&#xff0c;不方便扩张&#xff0c;所以需要对其进行修改实现1、定义结构体用于传入顶点坐标系2、因为…

开始撸 Android 源码

启动找工作模式&#xff0c;发现无比困难。搁在往日&#xff0c;大龄程序员找工作都是一件困难的事情&#xff0c;加上今年形势很差&#xff0c;更是难上加难。关键是我这十几年来主攻的浏览器内核方向&#xff0c;需求量更是几乎为零。在 BOSS 直聘上以 Chromium 为关键词&…

华为云云耀云服务器L实例评测|Git 私服搭建指南

前言 本文为华为云云耀云服务器L实例测评文章&#xff0c;测评内容是 云耀云服务器L实例 Git 私有服务器搭建指南 系统配置&#xff1a;2核2G 3M Ubuntu 20.04 我们平时在使用代码托管服务的时候&#xff0c;可能某些代码托管平台对成员有限制&#xff0c;或是由于内容原因会对…

教你如何清理 Docker 存储驱动的磁盘占用空间

Author&#xff1a;rab 有时候你会发现&#xff0c;你的 Docker 业务容器虽然做了数据持久化&#xff0c;且数据持久化的磁盘空间占用并不大&#xff0c;但是 Docker 的 Overlay2 目录占用却很大。我们知道 Overlay2 是 Docker 的存储驱动&#xff0c;也是 Docker 默认的存储驱…

Vue Router最佳实践,以确保你的Vue.js应用的路由管理清晰、可维护和高效

文章目录 路由结构设计命名路由动态路由参数导航守卫命名视图 (Named Views)懒加载路由错误处理 ✍创作者&#xff1a;全栈弄潮儿 &#x1f3e1; 个人主页&#xff1a; 全栈弄潮儿的个人主页 &#x1f3d9;️ 个人社区&#xff0c;欢迎你的加入&#xff1a;全栈弄潮儿的个人社区…

3D动画制作和渲染需要什么样的硬件规格?

动画是艺术与技术的令人兴奋的融合&#xff0c;为无限的创造力提供了广阔的画布。为了将创意愿景变为现实&#xff0c;动画师需要适合其工艺的强大计算资源。每个动画项目都有不同的硬件需求&#xff0c;无论是制作简单的 2D 动画还是构建复杂的 3D 世界。因此&#xff0c;有抱…

企业架构LNMP学习笔记51

企业案例使用&#xff1a; 主从模式&#xff1a; 缓存集群结构示意图&#xff1a; 去实现Redis的业务分离&#xff1a; 读的请求分配到从服务器上&#xff0c;写的请求分配到主服务器上。 Redis是没有中间件来进行分离的。 是通过业务代码直接来进行读写分离。 准备两台虚…