First, I just thought I'd mention (for the sake of exact-string google searches) that the error in the UI is "Object doesn't fit print volume"
Or, as a more complete example:
Object doesn't fit print volume
Object in [something].gcode exceeds the print volume of the currently selected printer profile, be careful when printing this.
More
Object exceeds print volume in depth.
Object's bounding box: (0.00, -3.00, 0.00) × (137.87, 167.86, 4.50)
Print volume: (0.00, 0.00, 0.00) × (250.00, 210.00, 210.00)
Second, it seems to me that the relevant bits of gcode are these lines -- particularly the first one:
G1 Y-3.0 F1000.0 ; go outside print area
G92 E0.0
G1 X60.0 E9.0 F1000.0 ; intro line
G1 X100.0 E12.5 F1000.0 ; intro line
G92 E0.0
Next, the code that generates the error is in the evaluatePrintDimensions
function within static/js/app/viewmodels/files.js
(line 994, in the copy I have).
That, in turn, references data["gcodeAnalysis"]["printingArea"]
... which derives from filemanager/analysis.py
(line 487), which gets its data, in turn, from analysis["printing_area"]
, which in turn appears to get its data by running:
python -m octoprint analysis gcode [...etc...]
(ibid, line 423). Digging further, I see util/gcodeInterpreter.py
is where this comes from, and [skipping some steps], in particular it comes from the analysis done in the loop at line 278, more specifically recording the value at line 393.
Now, my first thought was to suggest is that, up around line 350 (where y
gets set from the data in the gcode), perhaps we could special-case a tweak of the y
value? More specifically, it occurs to me that a naïve solution might be something like adding a test a few lines after that y gets set that does something like:
# integer of 10x to eliminate possibility of false float inequality
if y and int(10*y) == -30 and comment == "go outside print area":
y = 0.0 # cheat y inside print area for nozzle cleaning run.
Such a solution does in fact get rid of the error. So does a workaround from another answer in the stackexchange question linked by @tedder42, which changes the dimensions of the print bed to include Y=-3.
However, both of these still consider that initial strip to effectively be part of the print, which it really isn't (it's part of the preamble in the slicer, not part of the model output, per se), so... Perhaps something more comprehensive is in order? I'm not entirely sure the best way to do things... but... well...
Here's a diff/patch of what I did for myself; feel free to incorporate this, or use it as a model for a better version, or whatever (a few more thoughts after the patch):
--- octoprint/util/gcodeInterpreter.py.orig 2021-02-24 17:43:06.202647542 -0800
+++ octoprint/util/gcodeInterpreter.py 2021-02-24 21:49:40.781844790 -0800
@@ -275,12 +275,32 @@
if len(offsets) < max_extruders:
offsets += [(0, 0)] * (max_extruders - len(offsets))
+ in_skip_zone = False
+
for line in gcodeFile:
if self._abort:
raise AnalysisAborted(reenqueue=self._reenqueue)
lineNo += 1
readBytes += len(line.encode("utf-8"))
+ # there are a few very specific lines we wish to ignore for
+ # our purposes, as they're just the printer doing an initial
+ # extrusion line to get the filament flowing, and thus are
+ # not usefully part of the "model" -- so we don't want this
+ # to show up in the "printing_area":
+ if line.strip() == "G80 ; mesh bed leveling":
+ in_skip_zone = True
+ elif in_skip_zone and (
+ # first line, gets us outside:
+ "; go outside print area" in line or
+ # 3rd and 4th lines, extrudes a bit:
+ "; intro line" in line or
+ # 2nd and 5th lines, stopping extruder:
+ line.strip() == "G92 E0.0"):
+ continue
+ else:
+ in_skip_zone = False
+
if isinstance(gcodeFile, (io.IOBase, codecs.StreamReaderWriter)):
percentage = float(readBytes) / float(self._fileSize)
elif isinstance(gcodeFile, (list)):
Using this version, not only is the error not presented, but the dimensions calculated for the model (as reported by gcodeInterpreter.gcode().load(...).get_result()['printing_area']
) reflect the dimensions without that initial "intro line".
Alas, apparently this also gets calculated somewhere else, because it isn't reflected in the GCode Viewer ("Model size" under "Model info") — that still gives me dimensions with the stripe included. So... I guess there's more to be done.
Also, if the preamble comes in any different form from the slicer, this code likely won't catch it. A more comprehensive solution might be to detect discontinuities and check them against certain parameters — if they're one-line stripes along one axis that fall on layer zero, ignore them? — or at least have a sub-option to ignore them (without entirely disabling the warning), or.... I don't know.
Anyway, this does the trick well enough to at least get rid of the error, so... I hereby submit it to the community, in hopes that others may also find it useful. If/when I come up with something that'll also update the "Model size" under "Model info" in the GCode Viewer, I'll be sure to share.