Skip to content

Commit

Permalink
- Updates to ExcludeRegionState
Browse files Browse the repository at this point in the history
  * Extended Gcode processing to ensure consistent execution order of pending commands when exiting an excluded region
  * Renamed _appendPendingCommands to _processPendingCommands
  * Removed returnCommands parameter from recordRetraction, recordRetractionIfNeeded, _recoverRetraction, enterExcludedRegion, exitExcludedRegion, _processPendingCommands, and _processNonMove
  * Removed feedRate parameter from _processNonMove (use feedRate object property instead)
  * Restored priorE local, as it was necessary to ensure the correct extrusion delta is calculated
  * Added tests for exitExcludedRegion, _processNonMove, _processPendingCommands
  * Moved tests for extended Gcodes into separate test file
  * Added tests for processLinearMoves
- RetractionState
  * The originalCommand and firmwareRetract initializer arguments are now required
  * Renamed addRetractCommands/addRecoverCommands to generateRetractCommands/generateRecoverCommands and removed returnCommands parameters
- Moved create_position method from test_ExcludeRegionState into test utils
  • Loading branch information
bradcfisher committed May 17, 2019
1 parent ff74478 commit 41bec99
Show file tree
Hide file tree
Showing 13 changed files with 1,523 additions and 633 deletions.
18 changes: 13 additions & 5 deletions README.md
Expand Up @@ -160,6 +160,13 @@ that are not otherwise interpreted by the plugin (see the
[Inspected Gcode Commands](#inspected-gcode-commands) section below for a list of Gcodes that will
not be affected by these settings).

If inside an excluded region, the commands defined here will be excluded from being processed when
they are encountered. Depending on how they are configured, the command execution may be deferred
until after the tool leaves the exclusion region. If commands are deferred for later processing
using the First or Last options, they will be executed in the general order they are encountered.
For the Merge option, the merged command will be executed at the position of the last instance
encountered.

You can add a new entry at the bottom by entering a Gcode (e.g. "G4", "M204", etc), selecting the
exclusion mode to apply, providing an optional description for the entry, and clicking the "+"
button.
Expand All @@ -171,7 +178,7 @@ Each entry has the following properties:

**Gcode**

A Gcode command to intercept when excluding (e.g. G4)
A Gcode command to intercept when excluding (e.g. G4).

**Mode**

Expand All @@ -198,15 +205,16 @@ One of the following processing modes
> when exiting the excluded region.
- _**Merge**_ - When a matching command is encountered in an excluded region, record the parameter
values, overwriting any matching parameters previously encountered for that command. When
exiting the excluded region, execute a single instance of the command with those collected
values, potentially overwriting any matching parameters previously encountered for that command.
When exiting the excluded region, execute a single instance of the command with those collected
parameters.

> M204 (Set default accelerations) and M205 (Advanced settings) are assigned this processing
> type by default. Slicers can output a large number of these commands, and sending each one
> to the printer while inside and excluded region causes extra delay due to that communication.
> to the printer while inside an excluded region causes extra delay due to that communication.
> By accumulating the latest parameter value for each M204/M205 command instance encountered
> while excluding, and outputting a single merged command after exiting the excluded region.
> while excluding and outputting a single merged command after exiting the excluded region,
> an excluded region can be processed much more quickly.
**Description**

Expand Down
221 changes: 105 additions & 116 deletions octoprint_excluderegion/ExcludeRegionState.py

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions octoprint_excluderegion/ExcludedGcode.py
Expand Up @@ -4,9 +4,16 @@
from __future__ import absolute_import
from .CommonMixin import CommonMixin

# Filter out the command when in an exclude region and do not send it to the printer.
EXCLUDE_ALL = "exclude"

# Execute the first instance of a command from an exclude region when exiting the region.
EXCLUDE_EXCEPT_FIRST = "first"

# Execute the last instance of a command from an exclude region when exiting the region.
EXCLUDE_EXCEPT_LAST = "last"

# Execute command with last encountered value of each argument when exiting an exclude region.
EXCLUDE_MERGE = "merge"


Expand Down
19 changes: 13 additions & 6 deletions octoprint_excluderegion/GcodeHandlers.py
Expand Up @@ -15,13 +15,21 @@
from .RetractionState import RetractionState
from .AtCommandAction import ENABLE_EXCLUSION, DISABLE_EXCLUSION

# Pattern matching a typical floating point number value.
REGEX_FLOAT_PATTERN = "[-+]?[0-9]*\\.?[0-9]+"

# Pattern for parsing a Gcode parameter with a floating point value.
REGEX_FLOAT_ARG = re.compile("^(?P<label>[A-Za-z])\\s*(?P<value>%s)" % REGEX_FLOAT_PATTERN)

# Pattern for splitting a Gcode command into its constituent arguments.
REGEX_SPLIT = re.compile("(?<!^)\\s*(?=[A-Za-z])")

# A unit multiplier for converting logical units in inches to millimeters.
INCH_TO_MM_FACTOR = 25.4

# The length of individual generated arc segments.
MM_PER_ARC_SEGMENT = 1

TWO_PI = 2 * math.pi


Expand Down Expand Up @@ -339,13 +347,12 @@ def _handle_G10(self, cmd, gcode, subcode=None): # pylint: disable=unused-argum
self._logger.debug("_handle_G10: firmware retraction: cmd=%s", cmd)
returnCommands = self.state.recordRetraction(
RetractionState(
firmwareRetract=True,
originalCommand=cmd
),
None
originalCommand=cmd,
firmwareRetract=True
)
)

if (returnCommands is None):
if (not returnCommands):
return self.state.ignoreGcodeCommand()

return returnCommands
Expand All @@ -357,7 +364,7 @@ def _handle_G11(self, cmd, gcode, subcode=None): # pylint: disable=unused-argum
S parameter is for Repetier (0 = short unretract, 1 = long unretract)
"""
returnCommands = self.state.recoverRetractionIfNeeded(cmd, True)
if (returnCommands is None):
if (not returnCommands):
return self.state.ignoreGcodeCommand()

return returnCommands
Expand Down
71 changes: 27 additions & 44 deletions octoprint_excluderegion/RetractionState.py
Expand Up @@ -15,51 +15,46 @@ class RetractionState(CommonMixin):
Attributes
----------
recoverExcluded : boolean
Whether the recovery for this retraction was excluded or not. If it was excluded, it will
need to be processed later.
originalCommand : string
Original retraction gcode
firmwareRetract : boolean
This was a firmware retraction (G10)
extrusionAmount : float | None
Amount of filament to extrude when recovering a previous retraction, in millimeters. Will
be None if firmwareRetract is True.
feedRate : float
be None if firmwareRetract is True and a float otherwise.
feedRate : float | None
Feed rate in millimeters/minute for filament recovery. Will be None if firmwareRetract
is True.
originalCommand : string
Original retraction gcode
is True and a float otherwise.
recoverExcluded : boolean
Whether the recovery for this retraction was excluded or not (default False). If it was
excluded, it will need to be processed later.
"""

def __init__(
self, firmwareRetract=None, extrusionAmount=None, feedRate=None, originalCommand=None
self, originalCommand, firmwareRetract, extrusionAmount=None, feedRate=None
):
"""
Initialize the instance properties.
Parameters
----------
originalCommand : string
The original Gcode command for the retraction
firmwareRetract : boolean
Whether this was a firmware retraction (G10) or not (G0/G1 with no XYZ move)
extrusionAmount : float | None
Amount of filament to extrude when recovering a previous retraction, in millimeters.
Will be None if firmwareRetract is True.
feedRate : float
Feed rate in millimeters/minute for filament recovery. Will be None if firmwareRetract
is True.
originalCommand : string
The original Gcode command for the retraction
Must be None if firmwareRetract is True, and a float otherwise.
feedRate : float | None
Feed rate in millimeters/minute for filament recovery. Must be None if firmwareRetract
is True, and a float otherwise.
"""
nonFirmwareRetract = (extrusionAmount is not None) or (feedRate is not None)
if (firmwareRetract is not None):
if (nonFirmwareRetract):
if (firmwareRetract):
if (extrusionAmount is not None) or (feedRate is not None):
raise ValueError(
"You cannot provide a value for extrusionAmount or feedRate if " +
"firmwareRetract is specified"
)
elif (not nonFirmwareRetract):
raise ValueError(
"You must provide a value for firmwareRetract or extrusionAmount and feedRate"
)
elif ((extrusionAmount is None) or (feedRate is None)):
raise ValueError(
"You must provide values for both extrusionAmount and feedRate together"
Expand All @@ -71,47 +66,39 @@ def __init__(
self.feedRate = feedRate
self.originalCommand = originalCommand

def addRetractCommands(self, position, returnCommands=None):
def generateRetractCommands(self, position):
"""
Add the necessary commands to perform a retraction for this instance.
Parameters
----------
position : Position
The tool position state to apply the retraction to.
returnCommands : List of gcode commands
The Gcode command list to append the new command(s) to. If None, a new list will be
created.
Returns
-------
List of gcode commands
The Gcode command list provided in *returnCommands* or a newly created list. The
retraction command(s) will be appended to the returned list.
A list containing the retraction command(s) to execute.
"""
return self._addCommands(1, position, returnCommands)
return self._addCommands(1, position)

def addRecoverCommands(self, position, returnCommands=None):
def generateRecoverCommands(self, position):
"""
Add the necessary commands to perform a recovery for this instance.
Parameters
----------
position : Position
The tool position state to apply the retraction to.
returnCommands : List of gcode commands
The Gcode command list to append the new command(s) to. If None, a new list will be
created.
Returns
-------
List of gcode commands
The Gcode command list provided in *returnCommands* or a newly created list. The
recovery command(s) will be appended to the returned list.
A list containing the recovery command(s) to execute.
"""
return self._addCommands(-1, position, returnCommands)
return self._addCommands(-1, position)

def _addCommands(self, direction, position, returnCommands):
def _addCommands(self, direction, position):
"""
Add the necessary commands to perform a retraction or recovery for this instance.
Expand All @@ -122,18 +109,13 @@ def _addCommands(self, direction, position, returnCommands):
amount. Use 1 for retract, -1 for recover.
position : Position
The tool position state to apply the retraction to.
returnCommands : List of gcode commands
The Gcode command list to append the new command(s) to. If None, a new list will be
created.
Returns
-------
List of gcode commands
The Gcode command list provided in *returnCommands* or a newly created list. The
new command(s) will be appended to the returned list.
A list containing the new command(s).
"""
if (returnCommands is None):
returnCommands = []
returnCommands = []

if (self.firmwareRetract):
cmd = "G11" if (direction == -1) else "G10"
Expand All @@ -154,6 +136,7 @@ def _addCommands(self, direction, position, returnCommands):

eAxis.current -= amount

# Use "G1" over "G0", since an extrusion amount is being supplied
returnCommands.append(
"G1 F{f} E{e}".format(
e=eAxis.nativeToLogical(),
Expand Down
2 changes: 1 addition & 1 deletion octoprint_excluderegion/__init__.py
Expand Up @@ -90,7 +90,7 @@ def __plugin_load__():
}


class ExcludeRegionPlugin(
class ExcludeRegionPlugin( # pylint: disable=too-many-instance-attributes
octoprint.plugin.AssetPlugin,
octoprint.plugin.TemplatePlugin,
octoprint.plugin.SettingsPlugin,
Expand Down

0 comments on commit 41bec99

Please sign in to comment.