• G代码简单解释


    公司的切割机用的是梅塞尔的等离子切割机,技术部在下发套料图的时候,会将指令文件做简化处理,形式如下:

    %
    N4G92X0Y0
    N6F5000
    N8G71
    N10G91
    N12G00X561.243Y1277.726
    N14M11
    N16M09
    N18G01X75.071Y160.966
    N20G01X-44.119Y75.746
    N22G01X86.386Y14.882
    N24G01X75.071Y160.966
    N26M10
    N28G00X53.516Y-0.015
    N30M09
    N32G01X-75.071Y-160.966
    N34G01X44.119Y-75.746
    N36G01X-86.386Y-14.882
    N38G01X-75.071Y-160.966
    N40M10
    N42G00X15.005Y495.332
    N44M09
    N46G01X94.148Y237.483
    N48G01X-48.505Y73.015
    N50G01X85.359Y19.946

    N168G03X2.562Y9.562I-3.5J6.062

     查了一下手册,%表示指令文件开始;N指令表示行号,但是我没弄明白为什么行号都是偶数;G命令表示切割与定位。XYIJ表示坐标命令,XY为相对相对坐标增量,IJ表示圆心(由于我公司加工的钢板零件都是直线和圆弧形式,且切割点都为相对增量模式,所以其他命令暂时没有研究)

      以N168G03X2.562Y9.562I-3.5J6.062 这句指令为例:N168,表示是第168个指令行,对切割机无实际作用,可忽略;G03,表示以顺时针方向切割圆弧,起始点为上一命令的切割点,终止点为此命令行的坐标点,即为X2.562Y9.562,圆心为I-3.5J6.062。注意:坐标值皆以上一命令点为基准作增量运算。

      命令代码绝大多数为 G00(走空直线,即切割嘴不点火定位)、G01(切割直线,即切割嘴点火切割定位)、G02/G03(切割圆弧,G02为顺时针切割,G03为逆时针切割)

      I和J为圆心坐标。

    下面用C#解析G代码文件:

      1. 先把指令文件中与切割无关的命令过滤掉,生成一个临时的指令文件:

     1 public static string GenFile(string filename)
     2         {
     3             StreamReader r_sReader = new StreamReader(filename);
     4             StreamWriter w_sWriter = new StreamWriter(filename + ".tmp");
     5 
     6             string r_Line = string.Empty;
     7             int g_index = -1;
     8             r_Line = r_sReader.ReadLine();
     9             if (r_Line != "%")
    10             {
    11                 r_sReader.Close();
    12                 w_sWriter.Close();
    13                 throw new Exception("命令: " + filename + " 的格式不在本程序处理范围内,请联系软件开发人员!");
    14             }
    15             for (; r_Line != null; r_Line = r_sReader.ReadLine())
    16             {
    17                 if (Lex.FindKey(r_Line, "G0") && Lex.FindKey(r_Line, 'X'))
    18                 {
    19                     g_index = r_Line.IndexOf("G0");
    20                     r_Line = r_Line.Substring(g_index);
    21                     w_sWriter.WriteLine(r_Line);
    22                 }
    23             }
    24             r_sReader.Close();
    25             w_sWriter.Close();
    26             return filename + ".tmp";
    27         }

    生成的临时指令文件类似于:

    G01X-733.139Y129.272
    G01X-61.743Y-62.224
    G01X-36.738Y79.589

    G03X7.0Y7.0I0.0J7.0
    G01X0.0Y534.0
    G03X35.0Y35.0I0.0J35.0
    G01X185.0Y0.0

    这样看起来就清晰多了。只需要处理G命令和相应的坐标了:

     1 public static void CalculateLength(string filename, out double CuttingLength, out Double WalkLength, out int FireTimes)
     2         {
     3             CuttingLength = 0.0;
     4             WalkLength = 0.0;
     5             FireTimes = 0;
     6 
     7             Point2D p_start = new Point2D(0.0, 0.0);
     8             Point2D p_end = new Point2D(0.0, 0.0);
     9             Point2D p_center = new Point2D(0.0, 0.0);
    10 
    11             Arc2D tmp_arc = new Arc2D(p_center, p_start, p_end);
    12             LineSegment2D tmp_seg = new LineSegment2D(p_start, p_end);
    13             StreamReader r_sReader = new StreamReader(filename);
    14             // read line.
    15             string r_Line = string.Empty;
    16             // instruction appearing in current line.
    17             string instruction = string.Empty;
    18             #region Relative Coordinate
    19             Point2D p_current = new Point2D();
    20             for (int i=0; r_Line != null; r_Line = r_sReader.ReadLine(), i++)
    21             {
    22                 if (r_Line == string.Empty)
    23                     continue;
    24 
    25                 instruction = GetAxisValue(r_Line, 'G');
    26                 p_current.X = Convert.ToDouble(GetAxisValue(r_Line, 'X'));
    27                 p_current.Y = Convert.ToDouble(GetAxisValue(r_Line, 'Y'));
    28 
    29                 switch (instruction)
    30                 {
    31                     case "00":
    32                         tmp_seg.EndPt.X = p_current.X;
    33                         tmp_seg.EndPt.Y = p_current.Y;
    34                         WalkLength += tmp_seg.Length;
    35                         FireTimes++;
    36                         break;
    37                     case "01":
    38                         tmp_seg.EndPt.X = p_current.X;
    39                         tmp_seg.EndPt.Y = p_current.Y;
    40                         CuttingLength += tmp_seg.Length;
    41                         break;
    42                     case "02":
    43                         tmp_arc.CenterPt.X = Convert.ToDouble(GetAxisValue(r_Line, 'I'));
    44                         tmp_arc.CenterPt.Y = Convert.ToDouble(GetAxisValue(r_Line, 'J'));
    45                         tmp_arc.EndPt.X = p_current.X;
    46                         tmp_arc.EndPt.Y = p_current.Y;
    47                         CuttingLength += tmp_arc.ClockWiseLength;
    48                         break;
    49                     case "03":
    50                         tmp_arc.CenterPt.X = Convert.ToDouble(GetAxisValue(r_Line, 'I'));
    51                         tmp_arc.CenterPt.Y = Convert.ToDouble(GetAxisValue(r_Line, 'J'));
    52                         tmp_arc.EndPt.X = p_current.X;
    53                         tmp_arc.EndPt.Y = p_current.Y;
    54                         CuttingLength += tmp_arc.CounterClockWiseLength;
    55                         break;
    56                 }
    57             }
    58             #endregion
    59             r_sReader.Close();
    60         }

    上面的代码有我自定义的几个类,用于计算线段长度和圆弧长度:

      1 public static class m_Math
      2     {
      3         public const Double Pi = 3.1415926535;
      4         public const Double E = 2.7182818284;
      5         public const Double _precision = 0.00001;
      6 
      7         public static Double sqrt(Double n)
      8         {
      9             double result = 0.0, delta = 0.0;
     10             double x = 0.618 * n;
     11             do
     12             {
     13                 result = 0.5 * (x + (n / x));
     14                 delta = Math.Abs(x - result);
     15                 x = result;
     16             } while (delta > m_Math._precision);
     17             return result;
     18         }
     19 
     20         public static Double RadianToAngle(Double radian)
     21         {
     22             return (180.0 * radian) / m_Math.Pi;
     23         }
     24 
     25         public static Double AngleToRadian(Double angle)
     26         {
     27             return (m_Math.Pi * angle) / 180.0;
     28         }
     29 
     30         public static double[,] MatrixProduction(double[,] a, double[,] b)
     31         {
     32             int Length=a.Length;
     33             double[,] c=new double[Length,Length];
     34             return c;
     35         }
     36     }
     37 
     38     public class Point2D
     39     {
     40         public Point2D() { }
     41         public Point2D(Double x,Double y)
     42         {
     43             this.X = x;
     44             this.Y = y;
     45         }
     46 
     47         /// <summary>
     48         /// X coordinate figure
     49         /// </summary>
     50         private Double _X;
     51 
     52         /// <summary>
     53         /// Y coordinate figure
     54         /// </summary>
     55         private Double _Y;
     56 
     57         public Double X
     58         {
     59             get
     60             {
     61                 return this._X;
     62             }
     63 
     64             set
     65             {
     66                 this._X = value;
     67             }
     68         }
     69 
     70         public Double Y
     71         {
     72             get
     73             {
     74                 return this._Y;
     75             }
     76 
     77             set
     78             {
     79                 this._Y = value;
     80             }
     81         }
     82 
     83         public Double GetDistanceTo(Point2D p)
     84         {
     85             Double dx = this.X - p.X;
     86             Double dy = this.Y - p.Y;
     87             return Math.Sqrt(dx * dx + dy * dy);
     88         }
     89 
     90         public Vector2D GetVector2DTo(Point2D p)
     91         {
     92             return new Vector2D(p.X - this.X, p.Y - this.Y);
     93         }
     94 
     95         public void SetValueTo(Point2D p)
     96         {
     97             this.X = p.X;
     98             this.Y = p.Y;
     99         }
    100 
    101         public bool IsEqualTo(Point2D p)
    102         {
    103             return (this.X == p.X && this.Y == p.Y);
    104         }
    105 
    106         public bool IsOnSeg(LineSegment2D seg)
    107         {
    108             if (this.IsOnSegLine(seg))
    109             {
    110                 return (this.X <= Math.Max(seg.StartPt.X, seg.EndPt.X)) && (this.X >= Math.Min(seg.StartPt.X, seg.EndPt.X));
    111             }
    112 
    113             return false;
    114         }
    115 
    116         public bool IsOnSegLine(LineSegment2D seg)
    117         {
    118             Vector2D vseg = seg.StartPt.GetVector2DTo(seg.EndPt);
    119             Vector2D vthis = seg.StartPt.GetVector2DTo(this);
    120             return Math.Abs(vseg.CrossProductTo(vthis)) < m_Math._precision;
    121         }
    122 
    123         public static Point2D operator + (Point2D a, Point2D b)
    124         {
    125             return new Point2D((a.X + b.X), (a.Y + b.Y));
    126         }
    127 
    128         public static Point2D operator - (Point2D a, Point2D b)
    129         {
    130             return new Point2D((a.X - b.X), (a.Y - b.Y));
    131         }
    132 
    133         public override String ToString()
    134         {
    135             return "(" + this.X + "," + this.Y + ")";
    136         }
    137     }
    138 
    139     public class LineSegment2D
    140     {
    141         public LineSegment2D()
    142         {
    143             this.StartPt = new Point2D();
    144             this.EndPt = new Point2D();
    145 
    146         }
    147         public LineSegment2D(Point2D p1, Point2D p2)
    148         {
    149             this.StartPt = new Point2D();
    150             this.EndPt = new Point2D();
    151             this.StartPt.SetValueTo(p1);
    152             this.EndPt.SetValueTo(p2);
    153         }
    154 
    155         private Point2D _StartPt;
    156         private Point2D _EndPt;
    157 
    158         public Point2D StartPt
    159         {
    160             get
    161             {
    162                 return this._StartPt;
    163             }
    164 
    165             set
    166             {
    167                 this._StartPt = value;
    168             }
    169         }
    170 
    171         public Point2D EndPt
    172         {
    173             get
    174             {
    175                 return this._EndPt;
    176             }
    177 
    178             set
    179             {
    180                 this._EndPt = value;
    181             }
    182         }
    183 
    184         public Double Length
    185         {
    186             get
    187             {
    188                 return StartPt.GetDistanceTo(EndPt);
    189             }
    190         }
    191 
    192         public void SetPt(Point2D p1, Point2D p2)
    193         {
    194             this.StartPt.X = p1.X;
    195             this.StartPt.Y = p1.Y;
    196             this.EndPt.X = p2.X;
    197             this.EndPt.Y = p2.Y;
    198         }
    199 
    200         public bool IsIntersectionWith(LineSegment2D seg)
    201         {
    202             Vector2D s1s2 = this.StartPt.GetVector2DTo(seg.StartPt);
    203             Vector2D s1e2 = this.StartPt.GetVector2DTo(seg.EndPt);
    204             Vector2D s1e1 = this.StartPt.GetVector2DTo(this.EndPt);
    205             double straddle1 = (s1e1.CrossProductTo(s1s2)) * (s1e1.CrossProductTo(s1e2));
    206             Vector2D s2s1 = seg.StartPt.GetVector2DTo(this.StartPt);
    207             Vector2D s2e1 = seg.StartPt.GetVector2DTo(this.EndPt);
    208             Vector2D s2e2 = seg.StartPt.GetVector2DTo(seg.EndPt);
    209             double straddle2 = (s2e2.CrossProductTo(s2s1)) * (s2e2.CrossProductTo(s2e1));
    210 
    211             if (straddle1 < 0 && straddle2 < 0)
    212             {
    213                 return true;
    214             }
    215             else 
    216             {
    217                 return (this.StartPt.IsOnSeg(seg) || this.EndPt.IsOnSeg(seg) || seg.StartPt.IsOnSeg(this) || seg.EndPt.IsOnSeg(this));
    218             }
    219         }
    220     }
    221 
    222     public class Vector2D
    223     {
    224         public Vector2D() { }
    225         public Vector2D(Double x, Double y)
    226         {
    227             this.X = x;
    228             this.Y = y;
    229         }
    230         /// <summary>
    231         /// X coordinate figure
    232         /// </summary>
    233         private Double _X;
    234         /// <summary>
    235         /// Y coordinate figure
    236         /// </summary>
    237         private Double _Y;
    238 
    239         public Double X
    240         {
    241             get
    242             {
    243                 return this._X;
    244             }
    245 
    246             set
    247             {
    248                 this._X = value;
    249             }
    250         }
    251 
    252         public Double Y
    253         {
    254             get
    255             {
    256                 return this._Y;
    257             }
    258 
    259             set
    260             {
    261                 this._Y = value;
    262             }
    263         }
    264 
    265         public Double Length
    266         {
    267             get
    268             {
    269                 return Math.Sqrt(this.X * this.X + this.Y * this.Y);
    270             }
    271         }
    272 
    273         public Double StartAngle
    274         {
    275             get
    276             {
    277                 Double angle = Math.Acos(this.X / this.Length);
    278                 if (this.Y<0)
    279                 {
    280                     return 2 * m_Math.Pi - angle;
    281                 }
    282                 return angle;
    283             }
    284         }
    285 
    286         /// <summary>
    287         /// Counter clock wise Cross-Production to Vector2D(v)
    288         /// as the two vectors are both on X-Y plane, their Cross-Production is on Z-Axis
    289         /// </summary>
    290         public Double CrossProductTo(Vector2D v)
    291         {
    292             return (this.X * v.Y - this.Y * v.X);
    293         }
    294 
    295         public Double GetNormalAngleTo(Vector2D v)
    296         {
    297             Double DotProduction = this * v;
    298             // may be "projection" is 1.00000000002 or some other, in this case, the Math.Acos() method will return NaN(Not a Number).
    299             // so if |projection| > 1 and | |projection| - 1 |< _precision, must set it to 1.
    300             Double projection = (DotProduction) / (this.Length * v.Length);
    301             if (Math.Abs(projection) > 1)
    302             {
    303                 double delta = Math.Abs(Math.Abs(projection) - 1);
    304                 if (delta < m_Math._precision)
    305                 {
    306                     if (projection > 1)
    307                     {
    308                         projection = 1;
    309                     }
    310                     else if (projection < -1)
    311                     {
    312                         projection = -1;
    313                     }
    314                 }
    315             }
    316             return Math.Acos(projection);
    317         }
    318 
    319         public bool IsSameDirectionTo(Vector2D v)
    320         {
    321             Double DeltaAngle = Math.Abs(v.StartAngle-this.StartAngle) ;
    322             return DeltaAngle > 0 && DeltaAngle < m_Math._precision;
    323         }
    324 
    325         public bool IsOppositeDirectionTo(Vector2D v)
    326         {
    327             Double DeltaAngle = Math.Abs(Math.Abs(v.StartAngle - this.StartAngle)-m_Math.Pi);
    328             return DeltaAngle > 0 && DeltaAngle < m_Math._precision;
    329         }
    330 
    331         public bool IsClockWiseTo(Vector2D v)
    332         {
    333             return this.CrossProductTo(v) < 0;
    334         }
    335 
    336         public bool IsCounterClockWiseTo(Vector2D v)
    337         {
    338             return this.CrossProductTo(v) > 0;
    339         }
    340 
    341         public Double GetCounterClockWiseAngleTo(Vector2D v)
    342         {
    343             Double Angle = this.GetNormalAngleTo(v);
    344             if (this.IsClockWiseTo(v))
    345             {
    346                 return 2 * m_Math.Pi - Angle;
    347             }
    348             return Angle;
    349         }
    350 
    351         public override String ToString()
    352         {
    353             return "(" + this.X + "," + this.Y + ")";
    354         }
    355 
    356         public static Vector2D operator + (Vector2D a, Vector2D b)
    357         {
    358             return new Vector2D((a.X + b.X), (a.Y + b.Y));
    359         }
    360 
    361         public static Vector2D operator - (Vector2D a, Vector2D b)
    362         {
    363             return new Vector2D((a.X - b.X), (a.Y - b.Y));
    364         }
    365 
    366         public static Double operator * (Vector2D a, Vector2D b)
    367         {
    368             return (a.X * b.X + a.Y * b.Y);
    369         }
    370     }
    371 
    372     public class Arc2D
    373     {
    374         public Arc2D()
    375         {
    376             this.CenterPt = new Point2D();
    377             this.StartPt = new Point2D();
    378             this.EndPt = new Point2D();
    379         }
    380 
    381         public Arc2D(Point2D center, Point2D start, Point2D end)
    382         {
    383             if (Math.Abs(center.GetDistanceTo(start) - center.GetDistanceTo(end)) > m_Math._precision)
    384             {
    385                 //throw new Exception("Radius length is not equal!");
    386                 throw new Exception("半径长度不相等, 不能构成圆!");
    387             }
    388 
    389             this.CenterPt = new Point2D();
    390             this.StartPt = new Point2D();
    391             this.EndPt = new Point2D();
    392 
    393             this.CenterPt.SetValueTo(center);
    394             this.StartPt.SetValueTo(start);
    395             this.EndPt.SetValueTo(end);
    396         }
    397 
    398         private Point2D _CenterPt;
    399         private Point2D _StartPt;
    400         private Point2D _EndPt;
    401 
    402         public Point2D CenterPt
    403         {
    404             get
    405             {
    406                 return this._CenterPt;
    407             }
    408 
    409             set
    410             {
    411                 this._CenterPt = value;
    412             }
    413         }
    414 
    415         public Point2D StartPt
    416         {
    417             get
    418             {
    419                 return this._StartPt;
    420             }
    421 
    422             set
    423             {
    424                 this._StartPt = value;
    425             }
    426         }
    427 
    428         public Point2D EndPt
    429         {
    430             get
    431             {
    432                 return this._EndPt;
    433             }
    434 
    435             set
    436             {
    437                 this._EndPt = value;
    438             }
    439         }
    440 
    441         public Vector2D StartRadius
    442         {
    443             get
    444             {
    445                 return this.CenterPt.GetVector2DTo(this.StartPt);
    446             }
    447         }
    448 
    449         public Vector2D EndRadius
    450         {
    451             get
    452             {
    453                 return this.CenterPt.GetVector2DTo(this.EndPt);
    454             }
    455         }
    456 
    457         public Double RadiusLength
    458         {
    459             get
    460             {
    461                 return this.StartRadius.Length;
    462             }
    463         }
    464 
    465         public Double StartAngle
    466         {
    467             get
    468             {
    469                 return this.StartRadius.StartAngle;
    470             }
    471         }
    472 
    473         public Double EndAngle
    474         {
    475             get
    476             {
    477                 return this.EndRadius.StartAngle;
    478             }
    479         }
    480 
    481         /// <summary>
    482         /// Angle is from StartAngle to EndAngle in Counter-Clock-Wise
    483         /// </summary>
    484         public Double Angle
    485         {
    486             get
    487             {
    488                 Double angle = this.StartRadius.GetCounterClockWiseAngleTo(this.EndRadius);
    489                 return angle;
    490             }
    491         }
    492 
    493         public Double Bulge
    494         {
    495             get
    496             {
    497                 return Math.Tan((this.EndAngle - this.StartAngle) / 4.0);
    498             }
    499         }
    500 
    501         public Double CounterClockWiseLength
    502         {
    503             get
    504             {
    505                 return this.StartRadius.Length * this.Angle;
    506             }
    507         }
    508 
    509         public Double ClockWiseLength
    510         {
    511             get
    512             {
    513                 return 2 * m_Math.Pi * this.StartRadius.Length - this.CounterClockWiseLength;
    514             }
    515         }
    516 
    517         public Double CounterClockWiseArea
    518         {
    519             get
    520             {
    521                 return RadiusLength * RadiusLength * this.Angle;
    522             }
    523         }
    524 
    525         public Double ClockWisePatchArea
    526         {
    527             get
    528             {
    529                 return 2 * m_Math.Pi * this.RadiusLength * this.RadiusLength - this.CounterClockWiseArea;
    530             }
    531         }
    532     }

    Point2D 是二维点类,方便计算线段长度;LineSegment2D是线段类,没有方向,只用于计算长度;

    Vector2D二维向量类,用于计算圆弧的圆心角;Arc2D圆弧类,用于计算顺时针与逆时针的圆弧长度。

    还有两个方法:

    用于检验是否是数字:

    public static bool IsDigit(char ch)
            {
                return (ch >= '0' && ch <= '9');
            }

    用于获取指令值与坐标值:

     1 public static string GetAxisValue(string inLine, char AxisSymbol)
     2         {
     3             string Line = Lex.TrimAllSpace(inLine);
     4             int pos = Line.IndexOf(AxisSymbol);
     5             if (pos == -1)
     6             {
     7                 // if the current line has no AxisSymbol, then it contains no this AxisSymbol value at all.
     8                 return string.Empty;
     9             }
    10 
    11             //scan the current line until it meets a char that is not a digit.
    12             bool DecimalPointFound = false;
    13             string m_value = string.Empty;
    14             for (int i = pos + 1; i < Line.Length; i++)
    15             {
    16                 if (Lex.IsDigit(Line[i]))
    17                 {
    18                     m_value += Line[i];
    19                 }
    20                 // check whether the '-' is a negative sign or not.
    21                 else if (Line[i] == '-')
    22                 {
    23                     if (i < Line.Length - 1)
    24                     {
    25                         if ((Line[i - 1] == AxisSymbol) && Lex.IsDigit(Line[i + 1]))
    26                         {
    27                             m_value += Line[i];
    28                         }
    29                     }
    30                 }
    31                 // if the current char is a dot('.') , and both its previous and latter char are digit,
    32                 // then it is a decimal point.
    33                 else if (Line[i] == '.')
    34                 {
    35                     if (i < Line.Length - 1)
    36                     {
    37                         if (Lex.IsDigit(Line[i - 1]) && Lex.IsDigit(Line[i + 1]))
    38                         {
    39                             if (DecimalPointFound)
    40                             {
    41                                 // if Decimal Point is Found previously, 
    42                                 // then the digits set found is not a digit string(e.g. : 2011.04.17).
    43                                 // that is, decimal point only appear once.
    44                                 return string.Empty;
    45                             }
    46                             DecimalPointFound = true;
    47                             m_value += Line[i];
    48                         }
    49                         else if (Lex.IsAlpha(Line[i]))
    50                         {
    51                             return string.Empty;
    52                         }
    53                     }
    54                 }
    55                 else
    56                 {
    57                     // if the current char is not a digit, then the left ones are not necessary to be scanned.
    58                     break;
    59                 }
    60             }
    61             return m_value;
    62         }

    程序还有好多漏洞,待完善。

  • 相关阅读:
    LeetCode
    LeetCode
    ELK系列(5)
    ELK系列(4)
    ELK系列(3)
    ELK系列(2)
    ELK系列(1)
    计算机网络常见面试题总结
    mosquitto启动时Address already in use 和 一般的 Address already in use
    size和STL中的size_type
  • 原文地址:https://www.cnblogs.com/freudshow/p/3311086.html
Copyright © 2020-2023  润新知