fragmuffin / pygcode

GCODE Parser for Python
GNU General Public License v3.0
123 stars 38 forks source link

Language Variants #9

Open fragmuffin opened 6 years ago

fragmuffin commented 6 years ago

Allow multiple GCode languages to be supported (that's the only way this library is going to be practical)

To make this possible, I'll first have to: Change discovery mapping method to registration as opposed to on-demand class search

root problem identified by @revarbat in #8

Workaround

It's likely you're coming across this problem:

>>> from pygcode import text2gcodes
>>> text2gcodes('M80')
GCodeWordStrError: gcode text not fully formed, unassigned parameters: [<Word: M80>]

What the interpreter does is finds all valid G or M codes, then loops though all other Words from right to left, assigning them to their nearest valid G or M code as a parameter. This error is saying that it could not attach 'M80' as a parameter to any valid gcode (because it was not identified as a valid gcode itself)

Upon closure of this issue, the M80 code will be defined in 1 or more gcode dialects, then it will just be a matter of switching to the correct dialect.

In the meantime this workaround may get you out of trouble in some cases.

You can create your own G or M codes to be interpreted.

>>> import pygcode
>>> class PirateGCode(pygcode.GCode):
...     word_key = pygcode.Word('M', 80)  # yarrr matey!!
>>> from pygcode import text2gcodes
>>> text2gcodes('M80')
[<PirateGCode: M80>]

Tasklist

fragmuffin commented 6 years ago

Machine variants should also be implemented, so perhaps lang is the wrong name. Maybe pycode.variant and pygcode.set_variant() is more succinct.

fragmuffin commented 6 years ago

Basis for Change

variant link
linuxcnc (default) http://linuxcnc.org/docs/html/gcode.html
reprap http://reprap.org/wiki/G-code
marlin http://marlinfw.org/meta/gcode

Sample Files TODO: I'll also need to acquire a variety of sample files to parse... (linuxcnc sample files) I'll dig around online, but if anyone wants to contribute a sample, please feel free to comment here.

zultron commented 6 years ago

I've spent an enormous amount of time making changes to the LCNC interpreter, sometimes using remap, and sometimes directly modifying the source, and it's always difficult and painful. I can't say how many times I've wished that the interpreter and task could be rewritten in Python using proper OO architecture so that it could be easier to understand and easier to add new or modify existing G/M codes.

Big +1 for this project. The code looks organized in a way that subclassing codes would be possible. Off the top of my head, here are common types of LCNC interpreter changes that I've helped people with.

fragmuffin commented 6 years ago

@zultron Thank you for your insight! The examples you've listed have made me realise that a single script will definitely need to parse one language and simultaneously write another... so the library-wide pygcode.set_variant() will only serve to set the default language to interpret or write.

So all of the "read" and "write" functionality of pygcode must be switchable per function call. I can do that.

The time you spend on these changes, is that professionally, or just for yours and others' hobby projects?

My time is heavily invested in another project at the moment, so I may not get to this until next year.

zultron commented 6 years ago

@fragmuffin, very cool, allowing separate read and write dialects. My (armchair) application only requires read functionality, but there are other nifty things going on here that I've ignored.

Most of my LCNC interp and task modifications were made for commercial products. However, I've been moving away from CNC and towards other types of machine controls, so ATM it seems unlikely I'll be a contributor in the future. I just hope that someday there's a community effort to replace the LCNC interpreter, and it starts with something like this project.

BillyBumbler commented 6 years ago

@fragmuffin If I may make a suggestion...

Use XML. It's easily human readable, structured, editable and easy to read and parse with python. This way you can make g-code definition templates that any user can create, edit, and share for different machine types etc. If the templates are designed properly, they will even make it easier to add features like editing and code highlighting etc.

The more modular you make the code, the easier it will be to reuse and extend. I was checking out a gcode editor earlier where the author hard-coded the definitions for each machine type.... Not only did he have to duplicate 90% of the code for each machine, but it was in C++, so to add support for a different machine you either had to code it in yourself and recompile the whole project or request the author to make the changes... Otherwise a great editor, but not for me.

Edit: Sorry, I didn't realize I came off as such a douche until I came back and read it later. I meant it as a very humble opinion. Your coding skills are light years ahead of mine, so take it with a grain of salt. Thanks for your hard work!

fragmuffin commented 6 years ago

@BillyBumbler

If I may make a suggestion...

of course! :+1:

Use XML. It's easily human readable, structured, editable and easy to read and parse with python

That is a good idea, XML is easily readable, and you can do some fancy formatting with XSLT to make almost all browsers render them as HTML.

However, one thing that won't replace is the active nature of the classes... probably the best example is movement commands.

For example, in the GCodeMotion._process method, that one-line function is what allows tracking the machine's position. Whereas the canned cycles are a bit more complex.

So although I definitely agree with you; XML is much more accessible, it won't replace the classes that are currently in place.

However, I can document exactly how to create custom G or M codes for people to make their own dialects.

Sorry, I didn't realize I came off as such a douche until I came back and read it later

No!, I didn't read it that way! but I appreciate the courtesy :heart:

All things considered, I'll definitely keep this in mind when I'm finalising the design for this change. Thanks for the feedback!

fragmuffin commented 5 years ago

I've been away from this project for a while now, and I re-read the comment above from @BillyBumbler; I think using a non code-based format to store dialects is an excellent idea.

I have no idea what I was talking :wink:

@dickshaydle : Taggin you in from #18

Dialects needs to be split into 2 main tasks:

Dialect Design

Designing a system to accommodate all dialects, and a way of defining a dialect in a configuration file.

It will be important to get the design right to significantly reduce future maintenance, thereby increasing this library's usefulness, and longevity.

Lessons from existing bugs:

Filling & Testing Dialects

Populating the library with dialects, namely listed straight from the reprap wiki

WIll require, per above dialects:

nrosie commented 5 years ago

I'm trying to write some code that would take a file of Gcode from GibbsCAM and then send that through python to my haas 3 axis milling machine via ethernet connection. Will this code allow me to do that? If you have time I would appreciate a quick example of the proper formatting to put this in as well. Thanks in advance

For reference, below is a basic Gcode file from Gibbs I've previously made:

N1G0G17G20G40G80G90
T1M6
( OPERATION 1: CONTOUR )
( WORKGROUP )
( TOOL 1: .125 DIA. ROUGH ENDMILL )
S5250M3
G90G54G0X-2.1875Y1.5246
G43Z.35H1M8
G1Z.35F18.
Y1.5Z.3438
Y1.5615Z.3281
Y1.5Z.3125
Y1.5615Z.2969
Y1.5Z.2813
Y1.5615Z.2656
Y1.5Z.25
Y1.5615Z.2344
Y1.5Z.2188
Y1.5615Z.2031
Y1.5Z.1875
Y.8125F20.
X-.8125
Y1.5
G0Z.35
X-2.1875Y1.5246
G1Y1.5Z.3438F18.
Y1.5615Z.3281
Y1.5Z.3125
Y1.5615Z.2969
Y1.5Z.2813
Y1.5615Z.2656
Y1.5Z.25
Y1.5615Z.2344
Y1.5Z.2188
Y1.5615Z.2031
Y1.5Z.1875
Y1.5615Z.1719
Y1.5Z.1563
Y1.5615Z.1406
Y1.5Z.125
Y.8125F20.
X-.8125
Y1.5
G0Z.35
X-2.1875Y1.5246
fragmuffin commented 5 years ago

Hi @nrosie!

I'm trying to [stream gcode] through python to my haas 3 axis milling machine via ethernet connection. Will this code allow me to do that?

In a word: no This library is intended to intemperate g-code, to be used as an abstraction layer for tools to decode, and/or change g-code files in a common way.

To use an analogy, pygcode is to gcode as beautifulsoup is to html... it can read and change the file, but it can't stream/display the content... you'll need another tool for that. I'm a linux fanboy (not ashamed), so I would first research how to use LinuxCNC over ethernet, and whether it supports your drivers.