From 294203ffd5704933aedda385f364229047053bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 1 Jul 2016 17:54:26 +0200 Subject: [PATCH] Add absolute jog mode to printer API --- docs/api/printer.rst | 11 +++-- src/octoprint/printer/__init__.py | 10 +++-- src/octoprint/printer/standard.py | 45 ++++++++++++++----- src/octoprint/server/api/printer.py | 6 ++- src/octoprint/static/js/app/client/printer.js | 15 ++++--- 5 files changed, 62 insertions(+), 25 deletions(-) diff --git a/docs/api/printer.rst b/docs/api/printer.rst index 666f8029..f514a414 100644 --- a/docs/api/printer.rst +++ b/docs/api/printer.rst @@ -208,9 +208,14 @@ Issue a print head command jog Jogs the print head (relatively) by a defined amount in one or more axes. Additional parameters are: - * ``x``: Optional. Amount to jog print head on x axis, must be a valid number corresponding to the distance to travel in mm. - * ``y``: Optional. Amount to jog print head on y axis, must be a valid number corresponding to the distance to travel in mm. - * ``z``: Optional. Amount to jog print head on z axis, must be a valid number corresponding to the distance to travel in mm. + * ``x``: Optional. Amount/coordinate to jog print head on x axis, must be a valid number corresponding to the distance to travel in mm. + * ``y``: Optional. Amount/coordinate to jog print head on y axis, must be a valid number corresponding to the distance to travel in mm. + * ``z``: Optional. Amount/coordinate to jog print head on z axis, must be a valid number corresponding to the distance to travel in mm. + * ``absolute``: Optional. Boolean value specifying whether to move relative to current position (provided + axes values are relative amounts) or to absolute position (provided axes values are coordinates) + * ``speed``: Optiona. Speed at which to move. If not provided, minimum speed for all selected axes from printer + profile will be used. If provided but ``false``, no speed parameter will be appended to the command. Otherwise + interpreted as an integer signifying the speed in mm/s, to append to the command. home Homes the print head in all of the given axes. Additional parameters are: diff --git a/src/octoprint/printer/__init__.py b/src/octoprint/printer/__init__.py index 9ce08a98..a8621d8e 100644 --- a/src/octoprint/printer/__init__.py +++ b/src/octoprint/printer/__init__.py @@ -142,13 +142,17 @@ class PrinterInterface(object): """ raise NotImplementedError() - def jog(self, axis, amount): + def jog(self, axes, relative=True, speed=None, *args, **kwargs): """ Jogs the specified printer ``axis`` by the specified ``amount`` in mm. Arguments: - axis (str): The axis to jog, will be converted to lower case, one of "x", "y", "z" or "e" - amount (int, float): The amount by which to jog in mm + axes (dict): Axes and distances to jog, keys are axes ("x", "y", "z"), values are distances in mm + relative (bool): Whether to interpret the distance values as relative (true, default) or absolute (false) + coordinates + speed (int, bool or None): Speed at which to jog (F parameter). If set to ``False`` no speed will be set + specifically. If set to ``None`` (or left out) the minimum of all involved axes speeds from the printer + profile will be used. """ raise NotImplementedError() diff --git a/src/octoprint/printer/standard.py b/src/octoprint/printer/standard.py index aedaf36d..b9fa8dda 100644 --- a/src/octoprint/printer/standard.py +++ b/src/octoprint/printer/standard.py @@ -243,19 +243,42 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): if not result: raise UnknownScript(name) - def jog(self, axis, amount): - if not isinstance(axis, (str, unicode)): - raise ValueError("axis must be a string: {axis}".format(axis=axis)) + def jog(self, axes, relative=True, speed=None, *args, **kwargs): + if isinstance(axes, basestring): + # legacy parameter format, there should be an amount as first anonymous positional arguments too + axis = axes - axis = axis.lower() - if not axis in PrinterInterface.valid_axes: - raise ValueError("axis must be any of {axes}: {axis}".format(axes=", ".join(PrinterInterface.valid_axes), axis=axis)) - if not isinstance(amount, (int, long, float)): - raise ValueError("amount must be a valid number: {amount}".format(amount=amount)) + if not len(args) >= 1: + raise ValueError("amount not set") + amount = args[0] + if not isinstance(amount, (int, long, float)): + raise ValueError("amount must be a valid number: {amount}".format(amount=amount)) - printer_profile = self._printerProfileManager.get_current_or_default() - movement_speed = printer_profile["axes"][axis]["speed"] - self.commands(["G91", "G1 %s%.4f F%d" % (axis.upper(), amount, movement_speed), "G90"]) + axes = dict() + axes[axis] = amount + + if not axes: + raise ValueError("At least one axis to jog must be provided") + + for axis in axes: + if not axis in PrinterInterface.valid_axes: + raise ValueError("Invalid axis {}, valid axes are {}".format(axis, ", ".join(PrinterInterface.valid_axes))) + + command = "G1 {}".format(" ".join(["{}{}".format(axis.upper(), amount) for axis, amount in axes.items()])) + + if speed is None: + printer_profile = self._printerProfileManager.get_current_or_default() + speed = min([printer_profile["axes"][axis]["speed"] for axis in axes]) + + if speed and not isinstance(speed, bool): + command += " F{}".format(speed) + + if relative: + commands = ["G91", command, "G90"] + else: + commands = ["G90", command] + + self.commands(commands) def home(self, axes): if not isinstance(axes, (list, tuple)): diff --git a/src/octoprint/server/api/printer.py b/src/octoprint/server/api/printer.py index d22aefff..50e74fcc 100644 --- a/src/octoprint/server/api/printer.py +++ b/src/octoprint/server/api/printer.py @@ -244,9 +244,11 @@ def printerPrintheadCommand(): return make_response("Not a number for axis %s: %r" % (axis, value), 400) validated_values[axis] = value + absolute = "absolute" in data and data["absolute"] in valid_boolean_trues + speed = data.get("speed", None) + # execute the jog commands - for axis, value in validated_values.iteritems(): - printer.jog(axis, value) + printer.jog(validated_values, relative=not absolute, speed=speed) ##~~ home command elif command == "home": diff --git a/src/octoprint/static/js/app/client/printer.js b/src/octoprint/static/js/app/client/printer.js index c5190d6f..baf8b891 100644 --- a/src/octoprint/static/js/app/client/printer.js +++ b/src/octoprint/static/js/app/client/printer.js @@ -91,13 +91,16 @@ return OctoPrint.get(sdUrl, opts); }, - jog: function (amounts, opts) { - amounts = amounts || {}; + jog: function (params, opts) { + params = params || {}; - var payload = {}; - if (amounts.x) payload.x = amounts.x; - if (amounts.y) payload.y = amounts.y; - if (amounts.z) payload.z = amounts.z; + var absolute = params.absolute || false; + + var payload = {absolute: absolute}; + if (params.x) payload.x = params.x; + if (params.y) payload.y = params.y; + if (params.z) payload.z = params.z; + if (params.speed !== undefined) payload.speed = params.speed; return issuePrintheadCommand("jog", payload, opts); },