Skip to content

Commit

Permalink
Handle G90/G91 and M82/M83 distinct by default
Browse files Browse the repository at this point in the history
By default G90/G91 define relativeMode, M82/M83 define relativeE. The
extruder coordinate will be viewed as relative when either
relativeMode or relativeE are set. This mirrors the implementation in
Marlin (current and legacy forks) as well as Repetier.

SmoothieWare's implementation resets the relative mode of the
extruder on a G90/G91. To still accomodate this different
implementation a new settings has been added under Settings >
Feature: "G90/G91 overrides relative extruder mode". Checking this
switches to the alternative interpretation for future gcode analysis
and visualization.

The only difference between the two of them is that the following
segment of GCODE:

    M83
    G90

will have the extruder still set to relative on Marlin and
Repetier but set to absolute on Smoothieware.

Please note that the setting in all likelihood will be moved to
the printer profile in the future, since it makes more sense to have
it on a per printer basis. It's not part of the set of features
available for auto detection since it's required for GCODE analysis
and hence needs to be known even outside of a connection to the
printer.

Implements #1818
  • Loading branch information
foosel committed May 10, 2017
1 parent f0b63a8 commit dba95ee
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 38 deletions.
4 changes: 3 additions & 1 deletion src/octoprint/server/api/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ def getSettings():
"modelSizeDetection": s.getBoolean(["feature", "modelSizeDetection"]),
"firmwareDetection": s.getBoolean(["feature", "firmwareDetection"]),
"printCancelConfirmation": s.getBoolean(["feature", "printCancelConfirmation"]),
"blockWhileDwelling": s.getBoolean(["feature", "blockWhileDwelling"])
"blockWhileDwelling": s.getBoolean(["feature", "blockWhileDwelling"]),
"g90InfluencesExtruder": s.getBoolean(["feature", "g90InfluencesExtruder"])
},
"serial": {
"port": connectionOptions["portPreference"],
Expand Down Expand Up @@ -335,6 +336,7 @@ def _saveSettings(data):
if "firmwareDetection" in data["feature"]: s.setBoolean(["feature", "firmwareDetection"], data["feature"]["firmwareDetection"])
if "printCancelConfirmation" in data["feature"]: s.setBoolean(["feature", "printCancelConfirmation"], data["feature"]["printCancelConfirmation"])
if "blockWhileDwelling" in data["feature"]: s.setBoolean(["feature", "blockWhileDwelling"], data["feature"]["blockWhileDwelling"])
if "g90InfluencesExtruder" in data["feature"]: s.setBoolean(["feature", "g90InfluencesExtruder"], data["feature"]["g90InfluencesExtruder"])

if "serial" in data.keys():
if "autoconnect" in data["serial"]: s.setBoolean(["serial", "autoconnect"], data["serial"]["autoconnect"])
Expand Down
3 changes: 2 additions & 1 deletion src/octoprint/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ def settings(init=False, basedir=None, configfile=None):
"modelSizeDetection": True,
"firmwareDetection": True,
"printCancelConfirmation": True,
"blockWhileDwelling": False
"blockWhileDwelling": False,
"g90InfluencesExtruder": False
},
"folder": {
"uploads": None,
Expand Down
44 changes: 25 additions & 19 deletions src/octoprint/static/gcodeviewer/js/Worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var firstReport;
var toolOffsets = [
{x: 0, y: 0}
];
var g90InfluencesExtruder = false;
var z_heights = {};
var model = [];
var max = {x: undefined, y: undefined, z: undefined};
Expand Down Expand Up @@ -232,8 +233,8 @@ var doParse = function () {
var center_i, center_j, direction;
var prevX = 0, prevY = 0, prevZ = 0;
var f, lastF = 4000;
var extrude = false, extrudeRelative = false, retract = 0;
var positionRelative = false;
var extrude = false, relativeE = false, retract = 0;
var relativeMode = false;
var zLift = false;
var zLiftZ = undefined;
var zLiftMoves = [];
Expand Down Expand Up @@ -273,7 +274,7 @@ var doParse = function () {
for (var j = 0; j < args.length; j++) {
switch (argChar = args[j].charAt(0).toLowerCase()) {
case 'x':
if (positionRelative) {
if (relativeMode) {
x = prevX + Number(args[j].slice(1)) + offset.x;
} else {
x = Number(args[j].slice(1)) + offset.x;
Expand All @@ -282,7 +283,7 @@ var doParse = function () {
break;

case 'y':
if (positionRelative) {
if (relativeMode) {
y = prevY + Number(args[j].slice(1)) + offset.y;
} else {
y = Number(args[j].slice(1)) + offset.y;
Expand All @@ -291,7 +292,7 @@ var doParse = function () {
break;

case 'z':
if (positionRelative) {
if (relativeMode) {
z = prevZ + Number(args[j].slice(1));
} else {
z = Number(args[j].slice(1));
Expand All @@ -306,13 +307,13 @@ var doParse = function () {
assumeNonDC = true;
numSlice = Number(args[j].slice(1));

if (!extrudeRelative) {
if (relativeMode || relativeE) {
prev_extrude[tool]["abs"] = numSlice;
prev_extrude[tool][argChar] += numSlice;
} else {
// absolute extrusion positioning
prev_extrude[tool]["abs"] = numSlice - prev_extrude[tool][argChar];
prev_extrude[tool][argChar] = numSlice;
} else {
prev_extrude[tool]["abs"] = numSlice;
prev_extrude[tool][argChar] += numSlice;
}

extrude = prev_extrude[tool]["abs"] > 0;
Expand Down Expand Up @@ -359,15 +360,19 @@ var doParse = function () {
move = true;
}
} else if (/^(?:M82)/i.test(line)) {
extrudeRelative = false;
relativeE = false;
} else if (/^(?:G91)/i.test(line)) {
positionRelative = true;
extrudeRelative = true;
relativeMode = true;
if (g90InfluencesExtruder) {
relativeE = true;
}
} else if (/^(?:G90)/i.test(line)) {
positionRelative = false;
extrudeRelative = false;
relativeMode = false;
if (g90InfluencesExtruder) {
relativeE = false;
}
} else if (/^(?:M83)/i.test(line)) {
extrudeRelative = true;
relativeE = true;
} else if (/^(?:M101)/i.test(line)) {
dcExtrude = true;
} else if (/^(?:M103)/i.test(line)) {
Expand Down Expand Up @@ -407,10 +412,10 @@ var doParse = function () {
case 'b':
case 'c':
numSlice = Number(args[j].slice(1));
if (!extrudeRelative)
prev_extrude[tool][argChar] = 0;
else {
if (relativeMode || relativeE) {
prev_extrude[tool][argChar] = numSlice;
} else {
prev_extrude[tool][argChar] = 0;
}
break;
}
Expand Down Expand Up @@ -568,7 +573,8 @@ var parseGCode = function (message) {
gcode = message.gcode;
firstReport = message.options.firstReport;
toolOffsets = message.options.toolOffsets;
if (!toolOffsets || toolOffsets.length == 0) toolOffsets = [{x: 0, y: 0}]
if (!toolOffsets || toolOffsets.length == 0) toolOffsets = [{x: 0, y: 0}];
g90InfluencesExtruder = message.options.g90InfluencesExtruder;

doParse();
gcode = [];
Expand Down
6 changes: 4 additions & 2 deletions src/octoprint/static/gcodeviewer/js/gCodeReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ GCODE.gCodeReader = (function(){
analyzeModel: false,
toolOffsets: [
{x: 0, y: 0}
]
],
g90InfluencesExtruder: false
};

var percentageTree = undefined;
Expand Down Expand Up @@ -138,7 +139,8 @@ GCODE.gCodeReader = (function(){
gcode: gcode,
options: {
firstReport: 5,
toolOffsets: gCodeOptions["toolOffsets"]
toolOffsets: gCodeOptions["toolOffsets"],
g90InfluencesExtruder: gCodeOptions["g90InfluencesExtruder"]
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/octoprint/static/js/app/viewmodels/gcode.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ $(function() {
}
});

self.settings.feature_g90InfluencesExtruder.subscribe(function() {
GCODE.ui.updateOptions({
reader: {
g90InfluencesExtruder: self.settings.feature_g90InfluencesExtruder()
}
});
});

self._retrieveBedDimensions = function(currentProfileData) {
if (currentProfileData == undefined) {
currentProfileData = self.settings.printerProfiles.currentProfileData();
Expand Down
1 change: 1 addition & 0 deletions src/octoprint/static/js/app/viewmodels/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ $(function() {
self.feature_firmwareDetection = ko.observable(undefined);
self.feature_printCancelConfirmation = ko.observable(undefined);
self.feature_blockWhileDwelling = ko.observable(undefined);
self.feature_g90InfluencesExtruder = ko.observable(undefined);

self.serial_port = ko.observable();
self.serial_baudrate = ko.observable();
Expand Down
7 changes: 7 additions & 0 deletions src/octoprint/templates/dialogs/settings/features.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: feature_g90InfluencesExtruder" id="settings-g90InfluencesExtruder"> {{ _('<code>G90</code>/<code>G91</code> overrides relative extruder mode') }} <span class="label">{{ _('Smoothieware') }}</span>
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
Expand Down
38 changes: 23 additions & 15 deletions src/octoprint/util/gcodeInterpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,9 @@ def _load(self, gcodeFile, printer_profile, throttle=None):
maxExtrusion = [0.0]
currentExtruder = 0
totalMoveTimeMinute = 0.0
absoluteE = True
relativeE = False
relativeMode = False
scale = 1.0
posAbs = True
fwretractTime = 0
fwretractDist = 0
fwrecoverTime = 0
Expand All @@ -242,6 +242,8 @@ def _load(self, gcodeFile, printer_profile, throttle=None):
feedrate = 2000
offsets = printer_profile["extruder"]["offsets"]

g90InfluencesExtruder = settings().getBoolean(["feature", "g90InfluencesExtruder"])

for line in gcodeFile:
if self._abort:
raise AnalysisAborted(reenqueue=self._reenqueue)
Expand Down Expand Up @@ -318,23 +320,25 @@ def _load(self, gcodeFile, printer_profile, throttle=None):

# Use new coordinates if provided. If not provided, use prior coordinates (minus tool offset)
# in absolute and 0.0 in relative mode.
newPos = Vector3D(x if x is not None else (pos.x - toolOffset.x if posAbs else 0.0),
y if y is not None else (pos.y - toolOffset.y if posAbs else 0.0),
z if z is not None else (pos.z - toolOffset.z if posAbs else 0.0))
newPos = Vector3D(x if x is not None else (0.0 if relativeMode else pos.x - toolOffset.x),
y if y is not None else (0.0 if relativeMode else pos.y - toolOffset.y),
z if z is not None else (0.0 if relativeMode else pos.z - toolOffset.z))

if posAbs:
# Absolute mode: scale coordinates and apply tool offsets
pos = newPos * scale + toolOffset
else:
if relativeMode:
# Relative mode: scale and add to current position
pos += newPos * scale
else:
# Absolute mode: scale coordinates and apply tool offsets
pos = newPos * scale + toolOffset

if f is not None and f != 0:
feedrate = f

if e is not None:
if absoluteE:
# make sure e is relative
if relativeMode or relativeE:
# e is already relative, nothing to do
pass
else:
e -= currentE[currentExtruder]

# If move with extrusion, calculate new min/max coordinates of model
Expand Down Expand Up @@ -389,9 +393,13 @@ def _load(self, gcodeFile, printer_profile, throttle=None):
if z is not None:
pos.z = center.z
elif G == 90: #Absolute position
posAbs = True
relativeMode = False
if g90InfluencesExtruder:
relativeE = False
elif G == 91: #Relative position
posAbs = False
relativeMode = True
if g90InfluencesExtruder:
relativeE = True
elif G == 92:
x = getCodeFloat(line, 'X')
y = getCodeFloat(line, 'Y')
Expand All @@ -417,9 +425,9 @@ def _load(self, gcodeFile, printer_profile, throttle=None):

elif M is not None:
if M == 82: #Absolute E
absoluteE = True
relativeE = False
elif M == 83: #Relative E
absoluteE = False
relativeE = True
elif M == 207 or M == 208: #Firmware retract settings
s = getCodeFloat(line, 'S')
f = getCodeFloat(line, 'F')
Expand Down

0 comments on commit dba95ee

Please sign in to comment.