Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Language Variants #9

Open
2 tasks
fragmuffin opened this issue Nov 10, 2017 · 10 comments
Open
2 tasks

Language Variants #9

fragmuffin opened this issue Nov 10, 2017 · 10 comments

Comments

@fragmuffin
Copy link
Owner

fragmuffin commented Nov 10, 2017

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

  • Split conflicting GCodes by language in a sub-module pygcode.lang
  • Allow "switching" between language variants with pygcode.set_lang("reprap")

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
Copy link
Owner Author

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

@fragmuffin
Copy link
Owner Author

fragmuffin commented Nov 10, 2017

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
Copy link

zultron commented Nov 20, 2017

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.

  • M6: Custom tool changer controls probably the # 1 most common use of LCNC remap
  • Compatibility with FANUC/Haas/other industrial controller G code: add M98/M99, add G52, FANUC lathe tool wear offsets (not possible with simple remap)
  • Compatibility with Marlin/other 3D printer G code: Heater M codes, etc.
  • Emulate old controller instructions in retrofit: e.g. safety feature to disable spindle amp during M19 spindle orient

@fragmuffin
Copy link
Owner Author

@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
Copy link

zultron commented Nov 21, 2017

@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
Copy link

BillyBumbler commented Dec 6, 2017

@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
Copy link
Owner Author

@BillyBumbler

If I may make a suggestion...

of course! 👍

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 ❤️

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

@fragmuffin fragmuffin added this to To do in Dialects Apr 12, 2018
@fragmuffin fragmuffin moved this from To do to In progress in Dialects Apr 27, 2018
@fragmuffin
Copy link
Owner Author

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 😉

@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.

  • Configuration file format: yaml
  • Config files may reference Machine callbacks (gets around my original concern with GCodeMotion._process, see above)
  • Config files may explicitly reference a Machine class to use, to automate instantiation of the correct virtual machine.
  • Config files will be stored in the library folder (installed alongside pygcode)
  • Additional dialects can be added by explicitly referencing a yaml file.
    (allowing users to add their own functions for their machines if they want to, without a library change)

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

  • FiveD
  • Teacup
  • Sprinter
  • Marlin
  • Repetier
  • Smoothie
  • RepRapFirmware
  • Machinekit
  • BFB
  • MakerBot
  • grbl
  • Redeem
  • MK4duo

WIll require, per above dialects:

  • configuration file (<name>.yaml)
  • possible complementary functional code changes to support specialised functionality

@nrosie
Copy link

nrosie commented Jun 6, 2019

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
Copy link
Owner Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Dialects
  
In progress
Development

No branches or pull requests

4 participants