G代码圆弧

发布时间:2024年01月02日

圆弧总结

说明

工作中经常画图经常会遇到圆弧,开始的时候我并不是很理解,随着深入发现其实有些坑的,这里总结记录一下,可能并不是最优的解法,但肯定是自己理解后想出来的,如果这些能给你提供一些思路和帮助,那便是极好的。

G-Code的G02/G03

G02 顺时针圆弧/G03 逆时针圆弧

在这里插入图片描述

圆心的计算

I, J, K模式
G02 X20 Y10 I0 J-10
G03 X10.5 I3.0 J4.0

G02/G03指令,是已知起始点S(Xs, Ys),终止点E(Xe, Ye),相对圆心的增量(I, J),顺逆时针状态。通过这些信息我们是可以算出圆心的。

一般来说是(I, J)是圆弧起点相对圆心的增量,即圆心O坐标是(Xs + I, Ys + J)。而我遇到的情况,(I, J)的表示可能有以下几种情况:

  • 相对圆弧起点的增量
  • 相对圆弧终点的增量
  • 绝对圆弧中心
计算

这个就很简单了,针对(I, J)表示不同时计算方式也不同

  • 相对圆弧起点时,圆心坐标

O x = X s + I ; O y = Y s + J ; O_x = X_s + I;\\ O_y = Y_s + J;\\ Ox?=Xs?+I;Oy?=Ys?+J;

  • 相对圆弧终点时,圆心坐标

O x = X e + I ; O y = Y e + J ; O_x = X_e + I;\\ O_y = Y_e + J;\\ Ox?=Xe?+I;Oy?=Ye?+J;

  • 绝对圆弧中心

O x = I ; O y = J ; O_x = I;\\ O_y = J; Ox?=I;Oy?=J;

R模式
G02 X20 Y10 R10 F300

注意相同的起点、终点、半径和方向,计算出来的圆心可能有两种。其中,

  • R>0时,圆弧和中心的夹角小于180°,即圆弧段小于或等于半圆;
  • R<0时,圆弧和中心的夹角大于180°,即圆弧段大于半圆。

例如下图,G02指令时,如果R>0时,圆心是黑色圆的,如果R<0,则应该是黄色的圆。
在这里插入图片描述

以下图片是我画的分析用的简易图,方便自己理解如何计算出圆心的方法。假设以下是G02圆弧,起点为C,终点为D,半径为R,加粗圆弧部分是实际路径。

在这里插入图片描述

计算

假设存在上面的情况,已知起点C(Xc, Yc), 终点D(Xd, Yd),半径R

  1. 连接CD,求得中点A(Xa, Ya)

X a = ( X c + X d ) 2 Y a = ( Y c + Y d ) 2 (1) X_a = \frac{(X_c + X_d)}{2}\\ Y_a = \frac{(Y_c + Y_d)}{2} \tag{1} Xa?=2(Xc?+Xd?)?Ya?=2(Yc?+Yd?)?(1)

  1. 现在可以得到向量 A C ? \vec{AC} AC 的单位向量了
    ∣ A C ? ∣ = ( X a ? X c ) 2 + ( Y a ? Y c ) 2 A C ^ = A C ? ∣ A C ? ∣ (2) |\vec{AC}| = \sqrt{(X_a - X_c)^2 + (Y_a - Y_c)^2} \\ \hat{AC} = \frac{\vec{AC}}{|\vec{AC}|} \tag{2} AC =(Xa??Xc?)2+(Ya??Yc?)2 ?AC^=AC AC ?(2)

  2. 圆上两点连线的中垂线必过圆心,这是个知识点,然后根据直角三角关系,可以知道(AO)2 = R2 - (AC)2,下面用向量的方式表示,后面会用到。

∣ A O ? ∣ = R 2 ? ∣ A C ? ∣ 2 (3) |\vec{AO}| = \sqrt{R^2 - |\vec{AC}|^2} \tag{3} AO =R2?AC 2 ?(3)

  1. 现在只需要将单位向量 A C ^ \hat{AC} AC^,旋转90°后就是向量 A O ? \vec{AO} AO 的单位向量(这个没问题吧),如果旋转-90°就是向量 A P ? \vec{AP} AP 的单位向量,然后乘以AO的长度就得到圆心了,两种情况的圆心都可以认为是对的。

A O ? = A O ^ ? ? ∣ A O ? ∣ (4) \vec{AO} = \hat{AO}\ * |\vec{AO}|\tag{4} AO =AO^??AO (4)

R模式实际算法省略,因为经验有限,我并没有遇到过这个情况,当前仅讨论这个情况下计算出圆心的理论算法。

圆弧夹角的计算

这个地方,我感觉相对是比较麻烦的,因为必须要考虑圆弧方向,角度的值域范围,并不能简单粗暴的 终点角度 ? 起点角度 终点角度- 起点角度 终点角度?起点角度

#define 	PI 		3.1415926535897932384626433
#define 	EPS 	0.000001

//!< 基础点
struct Point
{
	double x;
    double y;
};
typedef Point Vector;


//!< 计算角度,值域[-π, π],这个很重要
double getAngle(const Point& p1, const Point& p2)
{
    return atan2f((p2.y - p1.y), (p2.x - p1.x));
}
//!< 计算两向量夹角
float calc2VecAngle(const Vector& v1, const Vector& v2, const int& isCw)
{
    //!< atan2 计算得到的弧度范围是[-PI, PI],可以转换成[0, 2 * PI]来计算
    float startAngNew = atan2f(v1.y, v1.x);
    float startAngNew2 = atan2f(v2.y, v2.x);

    if (startAngNew < EPS)
        startAngNew += 2 * PI;
    if (startAngNew2 < EPS)
        startAngNew2 += 2 * PI;

    float sweepNew = abs(startAngNew - startAngNew2);
    if (isCw != 0)
    {
        //!< 两向量之间的夹角,需要根据顺/逆时针,和所处角度象限判断
        if (startAngNew < startAngNew2 && isCw > EPS ||
            startAngNew > startAngNew2 && isCw < EPS)
        {
            sweepNew = abs(2 * PI - abs(sweepNew));
        }
    }
    return sweepNew;
}

//!< 已知圆弧,圆心,起点,终点,方向,计算出圆弧夹角(弧度制) 
//!< 
void calcArcAngle(Point center, Point s, Point e, bool isClockWise, double& angle)
{
    //!< 起点终点相同的情况,就是个整圆
    if (s == e)
    {
        angle = PI * 2;
    }
    else
    {
        Vector v1, v2;
        v1.x = start.x - center.x;
        v1.y = start.y - center.y;

        v2.x = end.x - center.x;
        v2.y = end.y - center.y;

        angle = calc2VecAngle(v1, v2, (cw ? 1 : -1));
    }
}

解析实现效果

在这里插入图片描述

最后

感谢各位大佬的无私奉献。

文章来源:https://blog.csdn.net/yoyo18520/article/details/135351162
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。