-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Proposal: Conditional Gcode Syntax for Custom Gcode #3390
Comments
Conditional statements in gcode would be wonderful! I think Cura supports IF statements, where when true, the line is included and if false the line is excluded. I use Slic3r because it processes thin walls better. I'd suspect this simple conditional argument could take care of 99% of the circumstances printer would encounter. It would also greatly simplify wipe and prime code, and could easily be used to trigger certain operations (such as bed temp adjustments) at certain layers. Something like: IF ([layernum] == 25) M190 S45; Is there any way to get slic3r to process these without the post-processing step? It would be ideal if this were built-in, but I understand I might be asking too much. Overall though, thanks for looking into this. I think it will make Slic3r better! |
A post processor is the cleanest and easiest to debug. Slic3r's post
process facilities are decent and most information is all that information
is available.
We can put it in the utility directory and add it to the default options
for post-processing scripts.
|
script is available at https://github.com/lordofhyphens/Slic3r/blob/conditional-gcode/utils/slic3r-conditional.pl |
I remember discussing this in another issue here in GitHub. I was considering a syntax like this:
|
What appealed to me with the leading semicolon is that if it goes unprocessed you see the results in the output gcode and the gcode is not executed. |
I appreciate the thing, but I'm not happy to have |
@alexrj agreed re: security hole; I just am inexperienced at writing safe parsers in Perl. I will not merge the open PR until you're at least satisfied with it or I can reliably show that there will not be a security problem with the final project. Some have asked about this going into the main executable; do you have any preferences w/r/t that? |
I still prefer the
For avoding eval in the post-processing script you can define a set of valid constructs (var + operator + value) and implement them as strict regexes. |
Well, it was more important when it was running as a post-processing script, as a parser failure would mean that it doesn't do anything (at least in my limited experience with them). If we pack it into the C++ side your syntax makes more sense. If we're going the C++ route, I'd like to come up with a few variants on the syntax so we can do some more arbitrary math operations, mostly along the lines of returning the value of, say {nozzle_diameter - layer_z}. |
For writing C++ parsers, the usual pair of tools: Lex & Yacc (flex and bison in the GNU world) are suitable. I used these tools to write a domain specific interpreted language. |
I think this is an important feature. I personally prefer an implementation in C++ because I expect this to be a frequently used feature. |
I think something like this Vojtech |
or maybe the boost::spirit library |
@bubnikv Here is a more comprehensive listing: https://github.com/ArashPartow/math-parser-benchmark-project |
@ArashPartow I see you made yourself an advertisement :-) I have to look into your library then. |
Let's draft a syntax spec. Conditional expressions
Value expressions
What do you think? Would this cover all the possible needs? We should try to list all the possible usage cases before implementing in order to make sure it's correctly designed. @lordofhyphens, @platsch, what did you use the script for?
I can't think about examples of using math. Do we actually need it? It's much more work than just plain conditionals. (FYI, LinuxCNC supports another syntax but it looks like there's no true standard.) |
By the way, one can use the perl Safe module to sandbox an eval Also looking at the very cool library by @ArashPartow , it does much more than just expression evaluation. It contains quite a powerfull conditional processor and it could do expressions over strings. Only it seems to me that the library in current form cannot return strings as a result of an expression, only numeric values. |
@alexrj the OR combination works for your example, but if both conditions are true, the gcode would be inserted twice. That is no problem for a temperature command, but could be e.g. for priming / retraction. As for the use cases: I'm running a multi-extruder setup with very different materials (normal plastic and conductive ink from a syringe extruder). I need to clean the ink-extruder after each toolchange by swiping it with a sponge, but I can not execute the same toolchange commands for the plastic extruder since the hot nozzle would burn my cleaning area. Currently, I see only one reason for math expressions: solving the extruder numbering issue #3574... |
@platsch another use case for math expressions is for relative coordinates.
And relative temperatures, primarily to efficiently overlap heating
commands.
|
With respect to you development guys, I would like to refer to a very simple use case, that I need myself very bad: If layer = n, move extruder to x=zero and pause the printer, keep all temps as they are. This would allow me to predefine all points where a color change would be necessary. It would skipp the need to stay awake and guard the printer not to miss the exact layer. I think that conditional Gcode could solve this, but a separate {'Change Filament at 'n' } function could do the job too :-) Thanks |
@alexrj the OR part of the spec has a hidden surprise in it -- the code will be executed multiple times if multiple conditions match, which can be dangerous depending on the code. I think it would be safer (in terms of user expectations) to borrow I'd also like add a I am fine with leaving an else structure out of the clause if we have a general negation. |
I've adapted the spec by @alexrj and added my comments: https://github.com/alexrj/Slic3r/wiki/Conditional-Gcode-Syntax-Spec We can add comments at the bottom there or just revise the page. |
https://github.com/taocpp/PEGTL looks promising. Header-only. Longer compile times for the grammar, but looks pretty simple. |
I did some experimenting around with the calculator sample and I think I have something workable w/r/t parsing. |
* Prototype gcode infix math, very basic. * Adding exprtk math parser library, header only. @ArashPartow https://github.com/ArashPartow/exprtk@4e1315a87dcc99a1ccad21fae1def0c2d4913c0f * Now evaluating strings with exprtk, only support no variables in input strings. * Moved executable code to cpp file, stubbed out xsp and let the testing begin... * Added conditional gcode parser into export path, added tests. * Added one more test to ensure that {if0} only removes up to newlines. * Test failure to parse * Add some compiler flags to compile out stuff from exprtk * Fix debug messages to be more specific, don't use deleted stringstream = method. * Trade expression speed for apparently around 50MB of object size. * Removed an extra trim that was breaking existing tests. * fix test Fixes #3390
So, since @alexrj has not updated the Slic3r manual..... how much of this is actually implemented, as of commit 6dd4009? I tried a simple expression in my filament g-code: ...but Slic3r just evaluates the |
I would love the conditional G-code processor to be ported from the Prusa3D
fork to the upstream slic3r, as our conditional G-code processor uses a
real parser written using the Boost::spirit framework, is extensible, fast,
and accesses the configuration layer values directly, it knows the types of
the configuration values, it provides reasonable error reporting etc. We
don't have resources to port the code upstream, but I will be most than
happy to answer questions.
…On Fri, Jan 26, 2018 at 9:27 AM, Vanessa Dannenberg < ***@***.***> wrote:
So, since @alexrj <https://github.com/alexrj> has not updated the Slic3r
manual..... how much of this is actually implemented, as of commit 6dd4009
<6dd4009>
?
I tried a simple expression in my filament g-code: {if
[solid_infill_speed] < 241}M900 K35
...but Slic3r just evaluates the [solid_infill_speed] placeholder, and
then writes the resulting expression into the g-code, instead of just the
conditional part. Literally, {if 240 < 241}M900 K35 appears in the file.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3390 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AFj5Iz2LNFLUQD7nGZKtHa1O_PCObmCIks5tOYxWgaJpZM4JCaMd>
.
|
@VanessaE I missed one of the application points, it should work now. |
layer_height's uppercase equivalent is absent from env | grep ^SLIC3R ...min_layer_height and max_layer_height are present however. I hope this is the right place to comment, I see references to other places that don't exist or don't seem to be commentable. |
Has this feature been implemented? It looks like (from the more recent references and merges linked on the history) math expressions are evaluated, but conditional expression are not? I'm interested in this for SoC this year. I'm also on IRC if someone wants to discuss there. |
Which version should I download to play with/ test/use conditional expressions ? rgrd Thomas |
@3daybreaker https://github.com/slic3r/Slic3r-Manual/blob/master/src/advanced/conditional-gcode.md is the manual entry for it, mostly copied from the wiki. @curieos yes, it has been implemented by me and separately by @bubnikv for the prusa3d fork. His implementation is likely better than mine. @bubnikv I'm going to close this issue here and open a separate issue to port the prusa3d version over. |
I almost managed to use this to make a smooth-varying nozzle temperature test tower. But I needed a way to cast to integers. Could we add a way to turn floats into int? |
As @lordofhyphens considers to port the Prusa3D expression evaluator to upstream, I thing my response fits. If you try the Prusa3D fork, the ints are converted to floats when used in a float context. For example, adding a float to int results to a float. https://github.com/prusa3d/Slic3r/wiki/Slic3r-Prusa-Edition-Macro-Language |
I just tried it anyway, despite not seeming to match the format, it looks like my printer does consume floats in the nozzle temperature field. So my gcode worked despite looking like it shouldn't. |
So with a simple post-processing script like the one below, I'm looking at proposing a simple grammar for some conditional statements in gcode. What I was thinking about was coming up with a simple grammar with references that can be added by the post-processor. It'd be based around parsing the numerical result and parsing everything around the statement and variable/value and running the comparison in perl. If the condition is false, the line is removed. Starting with a semicolon means that if it breaks the gcode itself isn't run.
No consideration for else is currently proposed, and also planning to limit to single-variable, although I think the grammar could be extended to arbitrary numbers of evaluations.
Just in case, I want to avoid just calling eval() and do some basic sensitization to avoid someone doing weird things to your system through this mechanism.
[variable] is some slic3r variable and the value will be filled in. We'll use ; to delineate the blocks.
Example, set the speed factor to 50% if the current_extruder is 2 (for toolchange or layer change or even start/stop gcode).
;_if [current_extruder] == 2; M220 S50
if [current_extruder] is 2, then the processor would see:
;_if 2 == 2; M220 S50
and print:
M220 S50
in the resulting gcode.I believe the leading _ in the keyword is important to make it less likely that an actual comment doesn't trigger the logic; additionally the leading ; (indicates the start of a comment for most, if not all, gcode parsers ) means that the default state of execution is no execution.
The text was updated successfully, but these errors were encountered: