diff --git a/config/sample-macros.cfg b/config/sample-macros.cfg index fcb144e0..97e39016 100644 --- a/config/sample-macros.cfg +++ b/config/sample-macros.cfg @@ -186,3 +186,55 @@ gcode: {% if params.K is not defined and params.L is defined %}SDCARD_LOOP_BEGIN COUNT={params.L|int}{% endif %} {% if params.K is not defined and params.L is not defined %}SDCARD_LOOP_END{% endif %} {% if params.K is defined and params.L is not defined %}SDCARD_LOOP_DESIST{% endif %} + +# Cancel object (aka Marlin/RRF M486 commands) support +# +# Enable object exclusion +[exclude_object] + +[gcode_macro M486] +gcode: + # Parameters known to M486 are as follows: + # [C] Cancel the current object + # [P] Cancel the object with the given index + # [S] Set the index of the current object. + # If the object with the given index has been canceled, this will cause + # the firmware to skip to the next object. The value -1 is used to + # indicate something that isn’t an object and shouldn’t be skipped. + # [T] Reset the state and set the number of objects + # [U] Un-cancel the object with the given index. This command will be + # ignored if the object has already been skipped + + {% if 'exclude_object' not in printer %} + {action_raise_error("[exclude_object] is not enabled")} + {% endif %} + + {% if 'T' in params %} + EXCLUDE_OBJECT RESET=1 + + {% for i in range(params.T | int) %} + EXCLUDE_OBJECT_DEFINE NAME={i} + {% endfor %} + {% endif %} + + {% if 'C' in params %} + EXCLUDE_OBJECT CURRENT=1 + {% endif %} + + {% if 'P' in params %} + EXCLUDE_OBJECT NAME={params.P} + {% endif %} + + {% if 'S' in params %} + {% if params.S == '-1' %} + {% if printer.exclude_object.current_object %} + EXCLUDE_OBJECT_END NAME={printer.exclude_object.current_object} + {% endif %} + {% else %} + EXCLUDE_OBJECT_START NAME={params.S} + {% endif %} + {% endif %} + + {% if 'U' in params %} + EXCLUDE_OBJECT RESET=1 NAME={params.U} + {% endif %} diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index c5347394..8d58e562 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -1435,6 +1435,20 @@ Enable the "M118" and "RESPOND" extended # override the "default_type". ``` +### [exclude_object] +Enables support to exclude or cancel individual objects during the printing +process. + +See the [exclude objects guide](Exclude_Object.md) and +[command reference](G-Codes.md#excludeobject) +for additional information. See the +[sample-macros.cfg](../config/sample-macros.cfg) file for a +Marlin/RepRapFirmware compatible M486 G-Code macro. + +``` +[exclude_object] +``` + ## Resonance compensation ### [input_shaper] diff --git a/docs/Exclude_Object.md b/docs/Exclude_Object.md new file mode 100644 index 00000000..d2681489 --- /dev/null +++ b/docs/Exclude_Object.md @@ -0,0 +1,99 @@ +# Exclude Obects + +The `[exclude_object]` module allows Klipper to exclude objects while a print is +in progress. To enable this feature include an [exclude_object config +section](Config_Reference.md#exclude_object) (also see the [command +reference](G-Codes.md#exclude-object) and +[sample-macros.cfg](../config/sample-macros.cfg) file for a +Marlin/RepRapFirmware compatible M486 G-Code macro.) + +Unlike other 3D printer firmware options, a printer running Klipper utilizes a +suite of components and users have many options to choose from. Therefore, in +order to provide a a consistent user experience, the `[exclude_object]` module +will establish a contract or API of sorts. The contract covers the contents of +the gcode file, how the internal state of the module is controlled, and how that +state is provided to clients. + +## Workflow Overview +A typical workflow for printing a file might look like this: +1. Slicing is completed and the file is uploaded for printing. During the + upload, the file is processed and `[exclude_object]` markers are added to + the file. Alternately, slicers may be configured to prepare object exclusion + markers natively, or in it's own pre-processing step. +2. When printing starts, Klipper will reset the `[exclude_object]` + [status](Status_Reference.md#exclude_object). +3. When Klipper processes the `EXCLUDE_OBJECT_DEFINE` block, it will update the + status with the known objects and pass it on to clients. +4. The client may use that information to present a UI to the user so that + progress can be tracked. Klipper will update the status to include the + currently printing object which the client can use for display purposes. +5. If the user requests that an object be cancelled, the client will issue an + `EXCLUDE_OBJECT NAME=` command to Klipper. +6. When Klipper process the command, it will add the object to the list of + excluded objects and update the status for the client. +7. The client will receive the updated status from Klipper and can use that + information to reflect the object's status in the UI. +8. When printing finishes, the `[exclude_object]` status will continue to be + available until another action resets it. + +## The GCode File +The specialized gcode processing needed to support excluding objects does not +fit into Klipper's core design goals. Therefore, this module requires that the +file is processed before being sent to Klipper for printing. Using a +post-process script in the slicer or having middleware process the file on +upload are two possibilities for preparing the file for Klipper. A reference +post-processing script is available both as an executable and a python library, +see +[cancelobject-preprocessor](https://github.com/kageurufu/cancelobject-preprocessor). + +### Object Definitions + +The `EXCLUDE_OBJECT_DEFINE` command is used to provide a summary of each object +in the gcode file to be printed. Provides a summary of an object in the file. +Objects don't need to be defined in order to be referenced by other commands. +The primary purpose of this command is to provide information to the UI without +needing to parse the entire gcode file. + +Object definitions are named, to allow users to easily select an object to be +excluded, and additional metadata may be provided to allow for graphical +cancellation displays. Currently defined metadata includes a `CENTER` X,Y +coordinate, and a `POLYGON` list of X,Y points representing a minimal outline of +the object. This could be a simple bounding box, or a complicated hull for +showing more detailed visualizations of the printed objects. Especially when +gcode files include multiple parts with overlapping bounding regions, center +points become hard to visually distinguish. `POLYGONS` must be a json-compatible +array of point `[X,Y]` tuples without whitespace. Additional parameters will be +saved as strings in the object definition and provided in status updates. + +`EXCLUDE_OBJECT_DEFINE NAME=calibration_pyramid CENTER=50,50 +POLYGON=[[40,40],[50,60],[60,40]]` + +All available G-Code commands are documented in the [G-Code +Reference](./G-Codes.md#excludeobject) + +## Status Information +The state of this module is provided to clients by the [exclude_object +status](Status_Reference.md#exclude_object). + +The status is reset when: +- The Klipper firmware is restarted. +- There is a reset of the `[virtual_sdcard]`. Notably, this is reset by Klipper + at the start of a print. +- When an `EXCLUDE_OBJECT_DEFINE RESET=1` command is issued. + +The list of defined objects is represented in the `exclude_object.objects` +status field. In a well defined gcode file, this will be done with +`EXCLUDE_OBJECT_DEFINE` commands at the beginning of the file. This will +provide clients with object names and coordinates so the UI can provide a +graphical representation of the objects if desired. + +As the print progresses, the `exclude_object.current_object` status field will +be updated as Klipper processes `EXCLUDE_OBJECT_START` and `EXCLUDE_OBJECT_END` +commands. The `current_object` field will be set even if the object has been +excluded. Undefined objects marked with a `EXCLUDE_OBJECT_START` will be added +to the known objects to assist in UI hinting, without any additional metadata. + +As `EXCLUDE_OBJECT` commands are issued, the list of excluded objects is +provided in the `exclude_object.excluded_objects` array. Since Klipper looks +ahead to process upcoming gcode, there may be a delay between when the command +is issued and when the status is updated. diff --git a/docs/G-Codes.md b/docs/G-Codes.md index eedb84cc..74757a48 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -320,6 +320,57 @@ parameter is provided it arranges for the given endstop phase setting to be written to the config file (in conjunction with the SAVE_CONFIG command). +### [exclude_object] + +The following commands are available when an +[exclude_object config section](Config_Reference.md#exclude_object) is +enabled (also see the [exclude object guide](Exclude_Object.md)): + +#### `EXCLUDE_OBJECT` +`EXCLUDE_OBJECT [NAME=object_name] [CURRENT=1] [RESET=1]`: +With no parameters, this will return a list of all currently excluded objects. + +When the `NAME` parameter is given, the named object will be excluded from +printing. + +When the `CURRENT` parameter is given, the current object will be excluded from +printing. + +When the `RESET` parameter is given, the list of excluded objects will be +cleared. Additionally including `NAME` will only reset the named object. This +**can** cause print failures, if layers were already skipped. + +#### `EXCLUDE_OBJECT_DEFINE` +`EXCLUDE_OBJECT_DEFINE [NAME=object_name [CENTER=X,Y] [POLYGON=[[x,y],...]] +[RESET=1] [JSON=1]`: +Provides a summary of an object in the file. + +With no parameters provided, this will list the defined objects known to +Klipper. Returns a list of strings, unless the `JSON` parameter is given, +when it will return object details in json format. + +When the `NAME` parameter is included, this defines an object to be excluded. + + - `NAME`: This parameter is required. It is the identifier used by other + commands in this module. + - `CENTER`: An X,Y coordinate for the object. + - `POLYGON`: An array of X,Y coordinates that provide an outline for the + object. + +When the `RESET` parameter is provided, all defined objects will be cleared, and +the `[exclude_object]` module will be reset. + +#### `EXCLUDE_OBJECT_START` +`EXCLUDE_OBJECT_START NAME=object_name`: +This command takes a `NAME` parameter and denotes the start of the gcode for an +object on the current layer. + +#### `EXCLUDE_OBJECT_END` +`EXCLUDE_OBJECT_END [NAME=object_name]`: +Denotes the end of the object's gcode for the layer. It is paired with +`EXCLUDE_OBJECT_START`. A `NAME` parameter is optional, and will only warn when +the provided name does not match the current object. + ### [extruder] The following commands are available if an diff --git a/docs/Overview.md b/docs/Overview.md index 1bd85eb1..6b9a6cd9 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -54,6 +54,8 @@ communication with the Klipper developers. perfectly square. - [PWM tools](Using_PWM_Tools.md): Guide on how to use PWM controlled tools such as lasers or spindles. +- [Exclude Object](Exclude_Object.md): The guide to the Exclude Objecs + implementation. ## Developer Documentation diff --git a/docs/Status_Reference.md b/docs/Status_Reference.md index aac6fec0..a515901b 100644 --- a/docs/Status_Reference.md +++ b/docs/Status_Reference.md @@ -69,6 +69,44 @@ The following information is available in the forward direction minus the total number of steps taken in the reverse direction since the micro-controller was last restarted. +## exclude_object + +The following information is available in the +[exclude_object](Exclude_Object.md) object: + +- `objects`: An array of the known objects as provided by the + `EXCLUDE_OBJECT_DEFINE` command. This is the same information provided by + the `EXCLUDE_OBJECT VERBOSE=1` command. The `center` and `polygon` fields will + only be present if provided in the original `EXCLUDE_OBJECT_DEFINE` + + Here is a JSON sample: +``` +[ + { + "polygon": [ + [ 156.25, 146.2511675 ], + [ 156.25, 153.7488325 ], + [ 163.75, 153.7488325 ], + [ 163.75, 146.2511675 ] + ], + "name": "CYLINDER_2_STL_ID_2_COPY_0", + "center": [ 160, 150 ] + }, + { + "polygon": [ + [ 146.25, 146.2511675 ], + [ 146.25, 153.7488325 ], + [ 153.75, 153.7488325 ], + [ 153.75, 146.2511675 ] + ], + "name": "CYLINDER_2_STL_ID_1_COPY_0", + "center": [ 150, 150 ] + } +] +``` +- `excluded_objects`: An array of strings listing the names of excluded objects. +- `current_object`: The name of the object currently being printed. + ## fan The following information is available in diff --git a/docs/_klipper3d/mkdocs.yml b/docs/_klipper3d/mkdocs.yml index b2a59827..313f60c5 100644 --- a/docs/_klipper3d/mkdocs.yml +++ b/docs/_klipper3d/mkdocs.yml @@ -113,6 +113,7 @@ nav: - Multi_MCU_Homing.md - Slicers.md - Skew_Correction.md + - Exclude_Object.md - Using_PWM_Tools.md - Developer Documentation: - Code_Overview.md