def draw(self, scale=0.01, cm=False): self.dat.scale(scale, point=False) self.page = self.page.scale(scale) b = self.dat.bounds() limits = Rect(0, 0, 11, 8.5) if cm: limits = limits.scale(2.54) if b.x >= 0 and b.y >= 0 and b.w <= limits.w and b.h <= limits.h: print("Drawing!") else: print("Too big!", b) return False ad = axidraw.AxiDraw() ad.interactive() ad.options.units = 1 if cm else 0 ad.options.speed_pendown = 10 ad.options.speed_penup = 50 ad.options.pen_rate_raise = 10 ad.connect() ad.penup() self.ad = ad tp = TransformPen(self, (1, 0, 0, -1, 0, self.page.h)) self.dat.replay(tp) time.sleep(MOVE_DELAY) ad.penup() ad.moveto(0, 0) ad.disconnect()
def __init__( self, svg_path=None, image_savedir=None, plot_id=None, cam=None, camera_index=None, ): if plot_id == None: plot_id = fn.get_current_plot_id() self.plot_id = plot_id if svg_path == None: svg_path = Path( gp.SVG_SAVEDIR).joinpath(plot_id).with_suffix('.svg') self.svg_path = svg_path self.ad = axidraw.AxiDraw() self.ad.plot_setup(self.svg_path) self.ad.options.mode = "layers" self.ad.options.units = 2 self.ad.update() self.doc = vpype.read_multilayer_svg(self.svg_path, 0.1) self.image_savedir = image_savedir self.camera_index = camera_index self.cam = cam
def draw(self, scale=0.01, dry=True, cm=False): if dry: with viewer() as v: dp = DATPen().record(self.dat).attr(fill=None, stroke=0) v.send(SVGPen.Composite([dp], self.page), self.page) else: self.dat.scale(scale, center=False) self.page = self.page.scale(scale) b = self.dat.bounds() limits = Rect(0, 0, 11, 8.5) if cm: limits = limits.scale(2.54) if b.x >= 0 and b.y >= 0 and b.w <= limits.w and b.h <= limits.h: print("Drawing!") else: print("Too big!", b) return False ad = axidraw.AxiDraw() ad.interactive() ad.options.units = 1 if cm else 0 ad.options.speed_pendown = 50 ad.options.speed_penup = 50 ad.connect() ad.penup() self.ad = ad tp = TransformPen(self, (1, 0, 0, -1, 0, self.page.h)) self.dat.replay(tp) time.sleep(MOVE_DELAY) ad.penup() ad.moveto(0, 0) ad.disconnect()
def init_plotter_interactive(spd, spu): ad = axidraw.AxiDraw() ad.interactive() ad_connected = ad.connect() if not ad_connected: return None ad.options.units = 1 # Bruker cm i stedet for inches ad.options.speed_pendown = spd ad.options.speed_penup = spu ad.update() print(f'Fant trolig plotter...') return ad
class AxiPrinter(App): ad = axidraw.AxiDraw() filename = "None" head_pos = [0.0, 0.0] def build(self): self.ad.interactive() self.head_pos = [0.0, 0.0] self.ad.turtle_x = 0.0 self.ad.turtle_y = 0.0 self.ad.f_curr_x = 0.0 self.ad.f_curr_y = 0.0 return Builder.load_file('AxiPrinter.kv')
def drawSVG(): ad = axidraw.AxiDraw() # Create class instance ad.plot_setup("portrait.svg") # Load file & configure plot context # Plotting options can be set, here after plot_setup(). ad.options.report_time = True ad.options.accel = 50 ad.plot_run() # Plot the file print('Pencils down!') c.connect(('127.0.0.1', 5005)) oscmsg = OSC.OSCMessage() oscmsg.setAddress("/test/") oscmsg.append(1) c.send(oscmsg)
def svg_plot_preview(svg_input, outp_name='gensvg.svg', layer=None): """ """ ad = axidraw.AxiDraw() ad.plot_setup(svg_input) ad.options.preview = True ad.options.report_time = True if layer: ad.options.mode = "layers" ad.options.layer = layer output_svg = ad.plot_run(True) save_file(output_svg, outp_name) print("{0}".format(ad.pt_estimate))
def setup(self): t.clear() self._reset_plot_state() if self.plotter_enabled: self.ad = axidraw.AxiDraw() self.ad.interactive() self.ad.options.const_speed = True for k, v in self.options.items(): setattr(self.ad.options, k, v) if not self.ad.connect(): raise RuntimeError('plotter not connected') self.options = self.ad.options
def homeX(): ad = axidraw.AxiDraw() # Create class instance ad.plot_setup("./axidraw/homing_test.svg") ad.serial_connect() ioString = ad.readIO() xHomeStatus = int(ioString.split(',')[2]) & 0b00001000 # X while xHomeStatus == 0: ad.moveXBack() ioString = ad.readIO() xHomeStatus = int(ioString.split(',')[2]) & 0b00001000 # X ad.disconnect()
def test_version_check(self): ''' connected to machine and internet ''' ad = axidraw.AxiDraw() # mocks axidraw_control.axidraw.versions.get_versions_online = MagicMock( return_value=versions.Versions("10", "10", "10")) ad.plot_document = MagicMock() self._mock_AxiDraw_connection(ad) ad.getoptions([]) ad.options.mode = "sysinfo" ad.parse('test/assets/AxiDraw_trivial.svg') ad.effect() self.assertEqual( len(axidraw_control.axidraw.versions.get_versions_online.mock_calls ), 1, "should query the 'internet' for version info") self.assertEqual(len(ad.plot_document.mock_calls), 0, "does not do any plotting with sysinfo mode")
def test_version_check_without_internet(self): ''' connected to machine but not internet ''' ad = axidraw.AxiDraw() self._mock_AxiDraw_connection(ad) axidraw.versions.get_versions_online = MagicMock( side_effect=RuntimeError("an error")) ad.error_log = MagicMock() ad.getoptions([]) ad.options.mode = "sysinfo" ad.parse('test/assets/AxiDraw_trivial.svg') ad.effect() self.assertEqual(len(axidraw.versions.get_versions_online.mock_calls), 1, "ensure mock was used") self.assertEqual( len(axidraw.versions.ebb_serial.queryVersion.mock_calls), 1, "ensure mock was used") self.assertTrue( len(ad.error_log.mock_calls) > 0, "No Internet is an error")
def draw(): # x = int(request.form['x']) # y = int(request.form['y']) json = request.get_json() print(json) ad = axidraw.AxiDraw() # Initialize class ad.interactive() # Enter interactive context ad.connect() # Open serial port to AxiDraw ad.options.units = 2 # Millimeters ad.options.pen_pos_up = 30 ad.options.pen_pos_down = 60 ad.update() ad.moveto(0,0) ad.moveto(json[0][0],json[0][1]) for point in json: time.sleep(0.1) ad.lineto(point[0],point[1]) print(point) print("Finished") ad.penup() ad.moveto(0,0) # ad.pendown() ad.disconnect() # Close serial port to AxiDraw return "YAY"
Copyright 2020 Windell H. Oskay, Evil Mad Scientist Laboratories The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ''' from pyaxidraw import axidraw ad = axidraw.AxiDraw() # Create class instance ad.plot_setup() # Run setup without input file ad.options.mode = "toggle" ad.plot_run() # Execute the command
def setupUi(self, SpottingExp): self.connection = False # variable to see the connection status of the axidraw self.ad = axidraw.AxiDraw() # Initialize class self.ad.interactive() # Enter interactive context self.ad.options.units = 1 # change units to centimeters SpottingExp.setObjectName("SpottingExp") SpottingExp.resize(578, 380) SpottingExp.setWindowOpacity(1) self.centralwidget = QtWidgets.QWidget(SpottingExp) self.centralwidget.setObjectName("centralwidget") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(10, 0, 281, 51)) font_16 = QtGui.QFont() font_16.setFamily("Yu Gothic UI Semilight") font_16.setPointSize(16) self.label.setFont(font_16) self.label.setObjectName("label") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(10, 50, 75, 23)) font_10 = QtGui.QFont() font_10.setFamily("Yu Gothic UI Light") font_10.setPointSize(10) self.pushButton.setFont(font_10) self.pushButton.setObjectName("pushButton") self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_2.setGeometry(QtCore.QRect(100, 50, 75, 23)) self.pushButton_2.setFont(font_10) self.pushButton_2.setObjectName("pushButton_2") self.spinBox = QtWidgets.QSpinBox(self.centralwidget) self.spinBox.setGeometry(QtCore.QRect(180, 100, 61, 21)) font_12 = QtGui.QFont() font_12.setFamily("Yu Gothic Light") font_12.setPointSize(12) self.spinBox.setFont(font_12) self.spinBox.setButtonSymbols(QtWidgets.QAbstractSpinBox.PlusMinus) self.spinBox.setMaximum(500) self.spinBox.setSingleStep(10) self.spinBox.setObjectName("spinBox") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(10, 90, 161, 31)) self.label_2.setFont(font_12) self.label_2.setObjectName("label_2") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(10, 140, 161, 21)) self.label_3.setFont(font_12) self.label_3.setObjectName("label_3") self.spinBox_2 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_2.setGeometry(QtCore.QRect(250, 100, 61, 22)) self.spinBox_2.setFont(font_12) self.spinBox_2.setMaximum(500) self.spinBox_2.setSingleStep(10) self.spinBox_2.setObjectName("spinBox_2") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(10, 170, 151, 31)) self.label_4.setFont(font_12) self.label_4.setObjectName("label_4") self.spinBox_3 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_3.setGeometry(QtCore.QRect(320, 100, 61, 22)) self.spinBox_3.setFont(font_12) self.spinBox_3.setMaximum(500) self.spinBox_3.setSingleStep(10) self.spinBox_3.setObjectName("spinBox_3") self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setGeometry(QtCore.QRect(10, 220, 161, 21)) self.label_5.setFont(font_12) self.label_5.setObjectName("label_5") self.spinBox_4 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_4.setGeometry(QtCore.QRect(180, 140, 61, 22)) self.spinBox_4.setFont(font_12) self.spinBox_4.setMaximum(500) self.spinBox_4.setSingleStep(10) self.spinBox_4.setObjectName("spinBox_4") self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_3.setGeometry(QtCore.QRect(460, 50, 81, 31)) self.pushButton_3.setFont(font_12) self.pushButton_3.setObjectName("pushButton_3") self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_4.setGeometry(QtCore.QRect(460, 90, 81, 31)) self.pushButton_4.setFont(font_12) self.pushButton_4.setObjectName("pushButton_4") self.pushButton_8 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_8.setGeometry(QtCore.QRect(460, 130, 81, 31)) self.pushButton_8.setFont(font_12) self.pushButton_8.setObjectName("pushButton_8") self.pushButton_9 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_9.setObjectName("pushButton_9") self.pushButton_9.setGeometry(QtCore.QRect(460, 170, 81, 31)) self.pushButton_9.setFont(font_12) self.spinBox_5 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_5.setGeometry(QtCore.QRect(250, 140, 61, 22)) self.spinBox_5.setFont(font_12) self.spinBox_5.setMaximum(500) self.spinBox_5.setSingleStep(10) self.spinBox_5.setObjectName("spinBox_5") self.spinBox_6 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_6.setGeometry(QtCore.QRect(320, 140, 61, 22)) self.spinBox_6.setFont(font_12) self.spinBox_6.setMaximum(500) self.spinBox_6.setSingleStep(10) self.spinBox_6.setObjectName("spinBox_6") self.spinBox_7 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_7.setGeometry(QtCore.QRect(180, 180, 101, 22)) self.spinBox_7.setFont(font_12) self.spinBox_7.setMaximum(100) self.spinBox_7.setProperty("value", 60) self.spinBox_7.setObjectName("spinBox_7") self.spinBox_8 = QtWidgets.QSpinBox(self.centralwidget) self.spinBox_8.setGeometry(QtCore.QRect(180, 220, 101, 22)) self.spinBox_8.setFont(font_12) self.spinBox_8.setMaximum(100) self.spinBox_8.setProperty("value", 40) self.spinBox_8.setObjectName("spinBox_8") self.label_6 = QtWidgets.QLabel(self.centralwidget) self.label_6.setGeometry(QtCore.QRect(20, 300, 371, 31)) self.label_6.setFont(font_12) self.label_6.setObjectName("label_6") self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_5.setGeometry(QtCore.QRect(190, 50, 171, 23)) self.pushButton_5.setFont(font_10) self.pushButton_5.setObjectName("pushButton_5") self.pushButton_6 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_6.setGeometry(QtCore.QRect(380, 300, 75, 30)) font_bold12 = QtGui.QFont() font_bold12.setFamily("Yu Gothic UI Semibold") font_bold12.setPointSize(12) font_bold12.setBold(True) font_bold12.setWeight(75) self.pushButton_6.setFont(font_bold12) self.pushButton_6.setObjectName("pushButton_6") self.pushButton_10 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_10.setGeometry(QtCore.QRect(470, 300, 75, 30)) self.pushButton_10.setFont(font_12) self.pushButton_10.setObjectName("pushButton_10") self.label_7 = QtWidgets.QLabel(self.centralwidget) self.label_7.setGeometry(QtCore.QRect(20, 260, 341, 31)) self.label_7.setFont(font_12) self.label_7.setObjectName("label_7") self.label_8 = QtWidgets.QLabel(self.centralwidget) self.label_8.setGeometry(QtCore.QRect(250, 260, 341, 31)) self.label_8.setFont(font_12) self.label_8.setObjectName("label_8") self.lineEdit_1 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_1.setGeometry(QtCore.QRect(170, 265, 51, 23)) self.lineEdit_1.setFont(font_12) self.lineEdit_1.setObjectName("lineEdit_1") self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(275, 265, 51, 23)) self.lineEdit_2.setFont(font_12) self.lineEdit_2.setObjectName("lineEdit_2") self.pushButton_7 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_7.setGeometry(QtCore.QRect(350, 265, 40, 25)) self.pushButton_7.setFont(font_12) self.pushButton_7.setObjectName("pushButton_7") SpottingExp.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(SpottingExp) self.menubar.setGeometry(QtCore.QRect(0, 0, 578, 22)) self.menubar.setObjectName("menubar") SpottingExp.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(SpottingExp) self.statusbar.setObjectName("statusbar") SpottingExp.setStatusBar(self.statusbar) self.retranslateUi(SpottingExp) QtCore.QMetaObject.connectSlotsByName(SpottingExp) # Connect buttons to events and functions self.pushButton.clicked.connect(self.connectAxi) self.pushButton_3.clicked.connect(lambda: self.ad.penup()) self.pushButton_4.clicked.connect(lambda: self.ad.pendown()) self.pushButton_8.clicked.connect(lambda: self.ad.goto(0, 0)) self.pushButton_9.clicked.connect(self.updateSettings) self.pushButton_2.clicked.connect(self.disconnectAxi) self.pushButton_5.clicked.connect(self.DrawChip) self.pushButton_7.clicked.connect(self.moveto_xy) self.pushButton_6.clicked.connect(self.runSpotter) # modifySettings will be a function that brings the user to a pop up # window where they can specify how many rows of spots they want and # how many columns they want of each pen delay. # It's a work in progress srry. LMK if it's nice tho. self.pushButton_10.clicked.connect(self.openModifyWin)
# dist /= RADIUS # return math.sqrt(1-dist*dist) img = Image.open('depth_maps/pyramid.png') def get_weight(x, y): return max(0, remap(sample_image(img, x/100, (100-y)/100), 0.4, 1, 0, 1)) def onclick(x, y): t.getscreen().getcanvas().postscript(file='pyramid.eps') if __name__ == '__main__': t.tracer(500) t.setworldcoordinates(0, 8, 8, 0) t.hideturtle() ad = axidraw.AxiDraw() ad.interactive() ad.options.const_speed = True ad.connect() ad.pendown() order = 6 size = .032 # size = 100 / (2 ** order) - 2 # 2 8 26 points_gen = hilbert_gen(order, size, heading=t.Vec2D(1, 0)) rx = random.uniform(-1, 1) ry = random.uniform(-1, 1) for (x, y) in points_gen: # weight = get_weight(x, y) * size * 2 # rx = lerp(rx, random.uniform(-1, 1), 0.6)
def svg_plot(svg_input): ad = axidraw.AxiDraw() ad.plot_setup(svg_input) ad.plot_run()
import boto3 import time from moviepy.editor import * from pseyepy import Camera, Display, Stream from pyaxidraw import axidraw BUCKET_NAME = 'plotguydatastore' TABLE = 'plotguy_v0' AD = axidraw.AxiDraw() S3 = boto3.client('s3', aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY) DB = boto3.client('dynamodb', aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY, region_name='us-west-1') class Cam: def __init__(self): self.camera = Camera() def startRecording(self): self.stream = Stream(self.camera, file_name=self.file_name) def stopRecording(self): self.stream.end() self.camera.end()
keeping the black wire towards the back of the machine. ''' import sys import time from pyaxidraw import axidraw pen_up_percent = 75 # Percent height that we will use for pen up pen_down_percent = 25 # Percent height that we will use for pen down wait_time_s = 3 # Time, in seconds, before switching to next position port_pin = 6 # Logical pin RP6 drives the output labeled "B3", from # docs at: http://evil-mad.github.io/EggBot/ebb.html#S2 ad = axidraw.AxiDraw() # Initialize class ad.interactive() # Enter interactive mode connected = ad.connect() # Open serial port to AxiDraw if not connected: sys.exit() # end script pen_is_up = False # Initial value of pen state # Lowest allowed position; "0%" on the scale. Default value: 10800 units, or 0.818 ms. servo_min = ad.params.servo_min # Highest allowed position; "100%" on the scale. Default value: 25200 units, or 2.31 ms. servo_max = ad.params.servo_max
def axidraw_CLI(dev=False): ''' The core of axicli ''' desc = 'AxiDraw Command Line Interface.' parser = argparse.ArgumentParser(description=desc, usage=quick_help) parser.add_argument("svg_in", nargs='?', \ help="The SVG file to be plotted") parser.add_argument("-f", "--config", type=str, dest="config", help="Filename for the custom configuration file.") parser.add_argument("-m","--mode", \ metavar='MODENAME', type=str, \ help="Mode. One of: [plot, layers, align, toggle, manual, " \ + "sysinfo, version, res_plot, res_home, reorder]. Default: plot.") parser.add_argument("-s","--speed_pendown", \ metavar='SPEED', type=int, \ help="Maximum plotting speed, when pen is down (1-100)") parser.add_argument("-S","--speed_penup", \ metavar='SPEED', type=int, \ help="Maximum transit speed, when pen is up (1-100)") parser.add_argument("-a","--accel", \ metavar='RATE', type=int, \ help="Acceleration rate factor (1-100)") parser.add_argument("-d","--pen_pos_down", \ metavar='HEIGHT', type=int, \ help="Height of pen when lowered (0-100)") parser.add_argument("-u","--pen_pos_up", \ metavar='HEIGHT', type=int, \ help="Height of pen when raised (0-100)") parser.add_argument("-r","--pen_rate_lower", \ metavar='RATE', type=int, \ help="Rate of lowering pen (1-100)") parser.add_argument("-R","--pen_rate_raise", \ metavar='RATE', type=int, \ help="Rate of raising pen (1-100)") parser.add_argument("-z","--pen_delay_down", \ metavar='DELAY',type=int, \ help="Optional delay after pen is lowered (ms)") parser.add_argument("-Z","--pen_delay_up", \ metavar='DELAY',type=int, \ help="Optional delay after pen is raised (ms)") parser.add_argument("-N","--no_rotate", \ action="store_const", const='True', \ help="Disable auto-rotate; preserve plot orientation") parser.add_argument("-C","--const_speed",\ action="store_const", const='True', \ help="Use constant velocity when pen is down") parser.add_argument("-T","--report_time", \ action="store_const", const='True', \ help="Report time elapsed") parser.add_argument("-M","--manual_cmd", \ metavar='COMMAND', type=str, \ help="Manual command. One of: [ebb_version, lower_pen, raise_pen, "\ + "walk_x, walk_y, enable_xy, disable_xy, bootload, strip_data, " \ + "read_name, list_names, write_name]. Default: ebb_version") parser.add_argument("-w","--walk_dist", \ metavar='DISTANCE', type=float, \ help="Distance for manual walk (inches)") parser.add_argument("-l","--layer", \ type=int, \ help="Layer(s) selected for layers mode (1-1000). Default: 1") parser.add_argument("-c","--copies", \ metavar='COUNT', type=int, \ help="Copies to plot, or 0 for continuous plotting. Default: 1") parser.add_argument("-D","--page_delay", \ metavar='DELAY', type=int,\ help="Optional delay between copies (s).") parser.add_argument("-v","--preview", \ action="store_const", const='True', \ help="Preview mode; simulate plotting only.") parser.add_argument("-g","--rendering", \ metavar='RENDERCODE', type=int, \ help="Preview mode rendering option (0-3). 0: None. " \ + "1: Pen-down movement. 2: Pen-up movement. 3: All movement.") parser.add_argument("-G","--reordering", \ metavar='GROUP_CODE', type=int, \ help="SVG reordering group handling option (0-3)."\ + "0: No reordering. 1: Reorder but preserve groups. " \ + "2: Reorder within groups. 3: Break apart. Default: 0") parser.add_argument("-L","--model",\ metavar='MODELCODE', type=int,\ help="AxiDraw Model (1-3). 1: AxiDraw V2 or V3. " \ + "2:AxiDraw V3/A3. 3: AxiDraw V3 XLX.") parser.add_argument("-p","--port",\ metavar='PORTNAME', type=str,\ help="Serial port or named AxiDraw to use") parser.add_argument("-P","--port_config",\ metavar='PORTCODE', type=int,\ help="Port use code (0-3)."\ +" 0: Plot to first unit found, unless port is specified"\ + "1: Plot to first AxiDraw Found. "\ + "2: Plot to specified AxiDraw. "\ + "3: Plot to all AxiDraw units. ") parser.add_argument("-o","--output_file",\ metavar='FILE', \ help="Optional SVG output file name") args = parser.parse_args() # Handle trivial cases from pyaxidraw import axidraw ad = axidraw.AxiDraw() utils.handle_info_cases(args.svg_in, quick_help, cli_version, "AxiDraw", ad.version_string) if args.mode == "options": quit() if args.mode == "timing": quit() # Detect certain "trivial" cases that do not require an input file use_trivial_file = False if args.mode == "align" or args.mode == "toggle" \ or args.mode == "version" or args.mode == "sysinfo" \ or args.mode == "manual": use_trivial_file = True svg_input = args.svg_in if not use_trivial_file or args.output_file: utils.check_for_input( svg_input, """usage: axicli svg_in [OPTIONS] Input file required but not found. For help, use: axicli --help""") if args.mode == "reorder": from pyaxidraw import axidraw_svg_reorder adc = axidraw_svg_reorder.ReorderEffect() adc.getoptions([]) utils.effect_parse(adc, svg_input) if args.reordering is not None: adc.options.reordering = args.reordering print("Re-ordering SVG File.") print("This can take a while for large files.") exit_status.run(adc.effect) # Sort the document if args.output_file: writeFile = open(args.output_file, 'w') # Open output file for writing. writeFile.write(adc.get_output()) writeFile.close() print("Done") quit() # For nontrivial cases, import the axidraw module and go from there: config_dict = utils.load_configs( [args.config, 'axidrawinternal.axidraw_conf']) combined_config = utils.FakeConfigModule(config_dict) from pyaxidraw import axidraw_control adc = axidraw_control.AxiDrawWrapperClass(params=combined_config) adc.getoptions([]) if use_trivial_file: trivial_svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg15158" viewBox="0 0 297 210" height="210mm" width="297mm"> </svg> """ svg_string = trivial_svg.encode('utf-8') # Need consistent encoding. p = etree.XMLParser(huge_tree=True, encoding='utf-8') adc.document = etree.ElementTree(etree.fromstring(svg_string, parser=p)) adc.original_document = copy.deepcopy(adc.document) else: utils.effect_parse(adc, svg_input) # assign command line options to adc's options. # additionally, look inside the config to see if any command line options were set there option_names = [ "mode", "speed_pendown", "speed_penup", "accel", "pen_pos_down", "pen_pos_up", "pen_rate_lower", "pen_rate_raise", "pen_delay_down", "pen_delay_up", "reordering", "no_rotate", "const_speed", "report_time", "manual_cmd", "walk_dist", "layer", "copies", "page_delay", "preview", "rendering", "model", "port", "port_config" ] utils.assign_option_values(adc.options, args, [config_dict], option_names) # The following options are deprecated and should not be used. # adc.options.setup_type = args.setup_type # Legacy input; not needed # adc.options.smoothness = args.smoothness # Legacy input; not needed # adc.options.cornering = args.cornering # Legacy input; not needed # adc.options.resolution = args.resolution # Legacy input; not needed # adc.options.resume_type = args.resume_type # Legacy input; not needed # adc.options.auto_rotate = args.auto_rotate # Legacy input; not needed exit_status.run(adc.effect) # Plot the document if utils.has_output(adc) and not use_trivial_file: utils.output_result(args.output_file, adc.outdoc) return adc if dev else None # returning adc is useful for tests
def axidraw_CLI(): desc = 'AxiDraw Command Line Interface.' parser = argparse.ArgumentParser(description=desc, usage=quickhelp()) parser.add_argument("inputfile", \ help="The SVG file to be plotted") parser.add_argument("-m","--mode", \ metavar='MODENAME', type=str, \ help="Mode. One of: [plot, layers, align, toggle, manual, " \ + "sysinfo, version, res_plot, res_home, reorder]. Default: plot.") parser.add_argument("-s","--speed_pendown", \ metavar='SPEED', type=int, \ help="Maximum plotting speed, when pen is down (1-100)") parser.add_argument("-S","--speed_penup", \ metavar='SPEED', type=int, \ help="Maximum transit speed, when pen is up (1-100)") parser.add_argument("-a","--accel", \ metavar='RATE', type=int, \ help="Acceleration rate factor (1-100)") parser.add_argument("-d","--pen_pos_down", \ metavar='HEIGHT', type=int, \ help="Height of pen when lowered (0-100)") parser.add_argument("-u","--pen_pos_up", \ metavar='HEIGHT', type=int, \ help="Height of pen when raised (0-100)") parser.add_argument("-r","--pen_rate_lower", \ metavar='RATE', type=int, \ help="Rate of lowering pen (1-100)") parser.add_argument("-R","--pen_rate_raise", \ metavar='RATE', type=int, \ help="Rate of raising pen (1-100)") parser.add_argument("-z","--pen_delay_down", \ metavar='DELAY',type=int, \ help="Optional delay after pen is lowered (ms)") parser.add_argument("-Z","--pen_delay_up", \ metavar='DELAY',type=int, \ help="Optional delay after pen is raised (ms)") parser.add_argument("-N","--no_rotate", \ action="store_true",\ help="Disable auto-rotate; preserve plot orientation") parser.add_argument("-C","--const_speed",\ action="store_true",\ help="Use constant velocity when pen is down") parser.add_argument("-T","--report_time", \ action="store_true", \ help="Report time elapsed") parser.add_argument("-M","--manual_cmd", \ metavar='COMMAND', type=str, \ help="Manual command. One of: [ebb_version, lower_pen, raise_pen, "\ + "walk_x, walk_y, enable_xy, disable_xy, bootload, strip_data, " \ + "read_name, list_names, write_name]. Default: ebb_version") parser.add_argument("-w","--walk_dist", \ metavar='DISTANCE', type=float, \ help="Distance for manual walk (inches)") parser.add_argument("-l","--layer", \ type=int, \ help="Layer(s) selected for layers mode (1-1000). Default: 1") parser.add_argument("-c","--copies", \ metavar='COUNT', type=int, \ help="Copies to plot, or 0 for continuous plotting. Default: 1") parser.add_argument("-D","--page_delay", \ metavar='DELAY', type=int,\ help="Optional delay between copies (s).") parser.add_argument("-v","--preview", \ action="store_true", \ help="Preview mode; simulate plotting only.") parser.add_argument("-g","--rendering", \ metavar='RENDERCODE', type=int, \ help="Preview mode rendering option (0-3). 0: None. " \ + "1: Pen-down movement. 2: Pen-up movement. 3: All movement.") parser.add_argument("-G","--group_sorting", \ metavar='GROUP_CODE', type=int, \ help="SVG sorting group handling option (0-2). 0: Preserve. " \ + "1: Sort within groups. 2: Break apart. Default: 1") parser.add_argument("-L","--model",\ metavar='MODELCODE', type=int,\ help="AxiDraw Model (1-3). 1: AxiDraw V2 or V3. " \ + "2:AxiDraw V3/A3. 3: AxiDraw V3 XLX.") parser.add_argument("-p","--port",\ metavar='PORTNAME', type=str,\ help="Serial port or named AxiDraw to use") parser.add_argument("-P","--port_config",\ metavar='PORTCODE', type=int,\ help="Port use code (0-3)."\ +" 0: Plot to first unit found, unless port is specified"\ + "1: Plot to first AxiDraw Found. "\ + "2: Plot to specified AxiDraw. "\ + "3: Plot to all AxiDraw units. ") parser.add_argument("-o","--output_file",\ metavar='FILE', \ help="Optional SVG output file name") args = parser.parse_args() # Handle trivial cases: if args.inputfile == "help": print(quickhelp()) quit() if args.inputfile == "version": from pyaxidraw import axidraw ad = axidraw.AxiDraw() print(cli_version) print(ad.version_string) quit() if args.mode == "options": quit() if args.mode == "timing": quit() if not os.path.isfile(args.inputfile): # If the input file does not exist, return an error. print("Input file not located. For help, try:") print(" python axicli.py --help") quit() if args.mode == "reorder": from pyaxidraw import axidraw_svg_reorder adc = axidraw_svg_reorder.ReorderEffect() adc.getoptions([]) adc.parse(args.inputfile) if args.rendering is not None: if args.rendering > 1: adc.options.rendering = True if args.group_sorting is not None: adc.options.group_handling = args.group_sorting print("Re-ordering SVG File.") print("This can take a while for large files.") adc.effect() # Sort the document if args.output_file: writeFile = open(args.output_file, 'w') # Open output file for writing. writeFile.write(adc.get_output()) writeFile.close() print("Done") quit() # For nontrivial cases, import the axidraw module and go from there: from pyaxidraw import axidraw_control adc = axidraw_control.AxiDrawWrapperClass() adc.getoptions([]) adc.parseFile(args.inputfile) # Pass through each parameter that has been specified. # Do NOT pass through parameters that are not specified; # That will ensure that they are properly given default values. if args.mode is not None: adc.options.mode = args.mode if args.speed_pendown is not None: adc.options.speed_pendown = args.speed_pendown if args.speed_penup is not None: adc.options.speed_penup = args.speed_penup if args.accel is not None: adc.options.accel = args.accel if args.pen_pos_down is not None: adc.options.pen_pos_down = args.pen_pos_down if args.pen_pos_up is not None: adc.options.pen_pos_up = args.pen_pos_up if args.pen_rate_lower is not None: adc.options.pen_rate_lower = args.pen_rate_lower if args.pen_rate_raise is not None: adc.options.pen_rate_raise = args.pen_rate_raise if args.pen_delay_down is not None: adc.options.pen_delay_down = args.pen_delay_down if args.pen_delay_up is not None: adc.options.pen_delay_up = args.pen_delay_up if args.no_rotate is not None: adc.options.no_rotate = args.no_rotate if args.const_speed is not None: adc.options.const_speed = args.const_speed if args.report_time is not None: adc.options.report_time = args.report_time if args.manual_cmd is not None: adc.options.manual_cmd = args.manual_cmd if args.walk_dist is not None: adc.options.walk_dist = args.walk_dist if args.layer is not None: adc.options.layer = args.layer if args.copies is not None: adc.options.copies = args.copies if args.page_delay is not None: adc.options.page_delay = args.page_delay if args.preview is not None: adc.options.preview = args.preview if args.rendering is not None: adc.options.rendering = args.rendering if args.model is not None: adc.options.model = args.model if args.port is not None: adc.options.port = args.port if args.port_config is not None: adc.options.port_config = args.port_config # The following options are deprecated and should not be used. # adc.options.setup_type = args.setup_type # Legacy input; not needed # adc.options.smoothness = args.smoothness # Legacy input; not needed # adc.options.cornering = args.cornering # Legacy input; not needed # adc.options.resolution = args.resolution # Legacy input; not needed # adc.options.resume_type = args.resume_type # Legacy input; not needed # adc.options.auto_rotate = args.auto_rotate # Legacy input; not needed adc.effect() # Plot the document if args.output_file: writeFile = open(args.output_file, 'w') # Open output file for writing. writeFile.write(adc.outdoc) writeFile.close()