Exemple #1
0
    def _handle_move_relative(
            self,
            # pylint: disable=C0103  # invalid-name
            x: Optional[float] = None,
            y: Optional[float] = None,
            z: Optional[float] = None,
            f: Optional[float] = None) -> None:
        """ Handler for the "command:move_relative" event.
        Move machine head to specified coordinates. """
        distance_mode_save = self.state.gcode_modal.get(b"distance", b"G91")

        gcode = "G91 G00 "
        if x is not None:
            gcode += "X%s " % x
        if y is not None:
            gcode += "Y%s " % y
        if z is not None:
            gcode += "Z%s " % z
        if f is not None:
            gcode += "F%s " % f

        self._handle_gcode(Line(gcode).block)

        if distance_mode_save != b"G91":
            # Restore modal distance_mode.
            self._handle_gcode(Line(distance_mode_save.decode()).block)
    def test_incoming_gcode_g92p1(self) -> None:
        """ Local G92.1 implementation.
        G92.1: GCodeResetCoordSystemOffset is not handled by pygcode's VM so we
        manually compute the offset. """

        # Use G92 to create a diff between machine_pos and work_pos.
        fake_event = ("command:gcode", Line("G92 X10 Y20").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        self.assertEqual(len(self.controller.log), 1)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 0, "y": 0, "z": 0, "a": 0, "b": 0})
        self.assertEqual(self.controller.state.work_pos,
                         {"x": 10, "y": 20, "z": 0, "a": 0, "b": 0})

        # Now G92.1
        fake_event = ("command:gcode", Line("G92.1").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        # G92.1 should have reset the diff between machine_pos and work_pos.
        self.assertEqual(len(self.controller.log), 2)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 0, "y": 0, "z": 0, "a": 0, "b": 0})
        self.assertEqual(self.controller.state.work_pos,
                         {"x": 0, "y": 0, "z": 0, "a": 0, "b": 0})
    def test_incoming_gcode_g92(self) -> None:
        """ Local G92 implementation.
        G92: GCodeCoordSystemOffset is not handled by pygcode's VM so we manually
        compute the offset. """
        fake_event = ("command:gcode", Line("G92 X10 Y20").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        # G92 should have created a diff between machine_pos and work_pos.
        self.assertEqual(len(self.controller.log), 1)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 0, "y": 0, "z": 0, "a": 0, "b": 0})
        self.assertEqual(self.controller.state.work_pos,
                         {"x": 10, "y": 20, "z": 0, "a": 0, "b": 0})

        # Now move and observe diff between machine_pos and work_pos.
        fake_event = ("command:gcode", Line("G0 X10 Y20").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        self.assertEqual(len(self.controller.log), 2)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 10, "y": 20, "z": 0, "a": 0, "b": 0})
        self.assertEqual(self.controller.state.work_pos,
                         {"x": 20, "y": 40, "z": 0, "a": 0, "b": 0})

        # Further G92's work as expected.
        fake_event = ("command:gcode", Line("G92 X0 Y0").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        self.assertEqual(len(self.controller.log), 3)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 10, "y": 20, "z": 0, "a": 0, "b": 0})
        self.assertEqual(self.controller.state.work_pos,
                         {"x": 0, "y": 0, "z": 0, "a": 0, "b": 0})

        fake_event = ("command:gcode", Line("G0 X0 Y0").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        self.assertEqual(len(self.controller.log), 4)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 0, "y": 0, "z": 0, "a": 0, "b": 0})
        self.assertEqual(self.controller.state.work_pos,
                         {"x": -10, "y": -20, "z": 0, "a": 0, "b": 0})
Exemple #4
0
    def parse_gcode_file(self, file_name):
        vector = []

        with open(file_name, 'r') as f:
            x_word_pre = Word('X0')
            y_word_pre = Word('Y0')
            z_word_pre = Word('Z0')

            for line_text in f.readlines():
                line = Line(line_text)

                self.log_display.append("GCODE = {}\n".format(str(line.block)))

                x_word = line.block.X
                y_word = line.block.Y
                z_word = line.block.Z

                if x_word is None and y_word is None and z_word is None:
                    continue

                x_word, x_word_pre = self.update_gcode_coord(
                    x_word, x_word_pre)
                y_word, y_word_pre = self.update_gcode_coord(
                    y_word, y_word_pre)
                z_word, z_word_pre = self.update_gcode_coord(
                    z_word, z_word_pre)

                point = [x_word.value, y_word.value, z_word.value]
                self.log_display.append('parse point {}'.format(point))

                vector.append(GCodePoint(point, str(line.block)))

        return vector
Exemple #5
0
 def readGcode(self, filepath):
     m = Machine()
     with open(filepath, 'r') as fh:
         for line_text in fh.readlines():
             self.traj.append((m.pos.values['X'], m.pos.values['Y']))
             line = Line(line_text)
             m.process_block(line.block)
Exemple #6
0
    def from_string(cls, string: str, *args, **kwargs):
        prev_gui_end = kwargs.get('prev_gui_end', Point2())
        prev_gcode_end = kwargs.get('prev_gcode_end', Point2())
        cnc_lines = [Line(l) for l in string.strip().split('\n')]
        assert len(cnc_lines) == 3

        line1, line2, line3 = cnc_lines

        index = line1.gcodes[0].number
        spill = line1.block.modal_params[1].value
        speed = line2.gcodes[0].word.value

        params = line3.gcodes[0].params
        geom_end_point = Point2(params['X'].value, params['Y'].value)

        x = geom_end_point.x
        y = geom_end_point.y

        return cls(index=index,
                   x=x,
                   y=y,
                   speed=speed,
                   spill=spill,
                   prev_gui_end=prev_gui_end,
                   prev_gcode_end=prev_gcode_end)
Exemple #7
0
 def _raw_gcode(self, raw_gcode: str) -> bool:
     try:
         line = Line(str(raw_gcode).strip())
     except GCodeWordStrError:
         return False
     self.publish("command:gcode", line.block)
     # print(line.block)
     return True
Exemple #8
0
def unpack_contents(filename):
    return_list = []
    with open(filename, 'r') as r_gcode:
        for this_line in r_gcode.readlines():
            try:
                line = Line(this_line)
                return_list.append(str(line))
            except:
                continue
    return return_list
Exemple #9
0
def process_g1(line: str, params: PrintParams):
    if "Z" in line:
        x = Line(line)
        g1: GCodeLinearMove = first(x.gcodes, condition=find_linear_move)
        fr: GCodeFeedRate = first(x.gcodes,
                                  condition=find_feed_rate,
                                  default=None)
        z_value = g1.params["Z"].value - params.width + 0.001
        f_value = fr.word.value if fr and fr.word else 900
        return f"G1 Z{z_value:.3f} F{f_value:.3f}\n"
    return line
Exemple #10
0
    def from_string(cls, string: str):
        cnc_lines = [Line(l) for l in string.strip().split('\n')]
        assert len(cnc_lines) == 2

        line1, line2 = cnc_lines
        assert line1.gcodes[0].word_letter == 'N'
        assert line2.gcodes[0].word == 'G04'

        index = line1.gcodes[0].number
        spill = line1.block.modal_params[1].value
        delay = line1.block.modal_params[2].value * 1000
        return cls(index=index, spill=spill, delay=delay)
Exemple #11
0
    def _gcode_parse_line(self,
                          last_point: np.array,
                          count: int,
                          line: str) -> (str, Any, Any, ParsedLine):
        section_name = ""
        errors = []
        point = np.array([np.nan, np.nan, np.nan])
        gcode_word_key = None
        distance = None
        gcode_line = None
        enabled = None
        expanded = None
        try:
            gcode_line = Line(line)
        except GCodeWordStrError:
            errors.append("Invalid gcode")

        if gcode_line:
            point, point_errors, gcode_word_key = self._gcode_to_point(gcode_line, last_point)
            errors += point_errors

            distance = self._dist_between_points(last_point, point)
            if np.isnan(distance):
                distance = None

            if isinstance(gcode_line, Line) and not gcode_line.block and gcode_line.comment:
                # Only a comment in this line. No other gcode.
                comment = str(gcode_line.comment)
                if comment.upper().replace(" ", "").startswith("(BLOCK-NAME:"):
                    new_section_name = comment.split(":", 1)[1].rstrip(")").strip()
                    section_name = self._increment_name(new_section_name)
                elif comment.upper().replace(" ", "").startswith("(BLOCK-ENABLE:"):
                    value = comment.split(":", 1)[1].rstrip(")").strip()
                    try:
                        enabled = bool(int(value))
                    except ValueError:
                        enabled = False
                elif comment.upper().replace(" ", "").startswith("(BLOCK-EXPAND:"):
                    value = comment.split(":", 1)[1].rstrip(")").strip()
                    try:
                        expanded = bool(int(value))
                    except ValueError:
                        expanded = False

        metadata = GcodeMetadata(point, distance)
        gcode_iteration = GcodeIteration(gcode_line, errors, metadata)
        return (section_name,
                enabled,
                expanded,
                ParsedLine(line, gcode_word_key, count, [gcode_iteration]))
Exemple #12
0
def read_line(line_text: str):
    '''Parse a single line of GCODE using pygcode.Line

    Args:
        line: A single line of GCODE

    Returns:
        A Line object, or None
    '''
    try:
        line = Line(line_text)
        return line
    except (GCodeWordStrError, AttributeError):
        print("Warning: Could not read line!")
    def test_incoming_event(self) -> None:
        """ Incoming events gets processed by controller. """
        fake_event = ("command:gcode", Line("G0 X10 Y20").block)
        self.controller._delivered.append(fake_event)
        self.controller.update()
        self.controller._delivered.clear()

        self.assertEqual(len(self.controller.log), 1)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 10, "y": 20, "z": 0, "a": 0, "b": 0})

        # Further calls to self.controller.update() should have no affect as
        # there is no new data.
        self.controller.update()
        self.assertEqual(len(self.controller.log), 1)
        self.assertEqual(self.controller.state.machine_pos,
                         {"x": 10, "y": 20, "z": 0, "a": 0, "b": 0})
Exemple #14
0
def main(args):
  gcodes = []
  offset = 0
  line_no = 0
  line = args.input.readline()
  while line:
    for gcode in Line(line).block.gcodes:
      gcodes.append({'line_no': line_no+1, 'offset':offset, 'line': line, 'gcode':gcode,})
    offset = args.input.tell()
    line_no+=1
    line = args.input.readline()
    
  clearance_height = getClearanceHeight(gcodes)
  print("GCode Z clearance_height is {}".format(clearance_height))
  
  if args.command=="list": list(args, gcodes, clearance_height)
      
  if args.command=="cut":  cut(args, gcodes, clearance_height)
Exemple #15
0
 def test_omit_redundant_modes(self):
     lines = [
         Line(line_str) for line_str in re.split(
             r'\s*\n\s*', '''
             g1 x0 y0 ; yes
             g1 x10 y-20 ; no
             g0 x-3 y2 ; yes
             g0 x0 y0 ; no
             g0 x1 y1 ; no
             g1 x20 y20 z5 ; yes
         ''') if line_str
     ]
     gcodes = [l.gcodes[0] for l in lines]
     comments = [l.comment for l in lines]
     for (i, g) in enumerate(omit_redundant_modes(gcodes)):
         comment = comments[i].text if comments[i] else None
         if comment == 'no':
             self.assertIsNotNone(re.search(r'^\s', str(g)))
         elif comment == 'yes':
             self.assertIsNone(re.search(r'^\s', str(g)))
Exemple #16
0
    def parse(self):
        # use the machine to populate the all_positions variable with xyz coordinates
        t1 = dt.now()

        previous_position = []

        for i in self.gcode.split('\n'):
            line = Line(i)
            block = line.block.gcodes
            for g in block:
                self.machine.process_gcodes(g)
                keys = []
                for key in self.machine.pos.values.keys():
                    keys.append(self.machine.pos.values[key])
                this_position = self.machine.pos.values
                if this_position != previous_position:
                    self.all_positions.append(this_position)

                previous_position = this_position
        timer(t1, 'parsing')
        self.get_cities()
        return self.all_positions
Exemple #17
0
    def from_string(cls, string: str, *args, **kwargs):
        prev_gui_end = kwargs.get('prev_gui_end', Point2())
        prev_gcode_end = kwargs.get('prev_gcode_end', Point2())
        cnc_lines = [Line(l) for l in string.strip().split('\n')]
        assert len(cnc_lines) == 4

        line1, line2, line3, line4 = cnc_lines

        index = line1.gcodes[0].number
        spill = line1.block.modal_params[1].value
        speed = line2.gcodes[0].word.value

        params1 = line3.gcodes[0].params
        params2 = line4.gcodes[0].params

        arc1_end = Point2(float(params1['X'].value), float(params1['Y'].value))
        arc1_center = Point2(float(params1['I'].value),
                             float(params1['J'].value))
        arc2_end = Point2(float(params2['X'].value), float(params2['Y'].value))
        arc2_center = Point2(float(params2['I'].value),
                             float(params2['J'].value))

        geom_end_point = arc2_end
        r = math.sqrt(
            pow(geom_end_point.x - arc1_center.x, 2) +
            pow(geom_end_point.y - arc1_center.y, 2))

        x = geom_end_point.x
        y = geom_end_point.y

        return cls(index=index,
                   x=x,
                   y=y,
                   r=r,
                   speed=speed,
                   spill=spill,
                   prev_gui_end=prev_gui_end,
                   prev_gcode_end=prev_gcode_end)
Exemple #18
0
def get_positions(data):
    t1 = dt.now()
    machine = Machine()
    positions = []
    last = []
    for i in data.split('\n'):
        line = Line(i)
        block = line.block.gcodes
        for g in block:
            machine.process_gcodes(g)
            keys = []
            for key in machine.pos.values.keys():

                keys.append(machine.pos.values[key])
            #positions.append(keys)
            position = machine.pos.values
            if position != last:
                positions.append(position)
            last = position
    timer(t1, "processing gcode")


    return positions
Exemple #19
0
	#print(waypoint)
	if waypoint != "":
		ax.plot([last_recorder_x,recorder_x], [last_recorder_y,recorder_y], "y", linewidth='1', markersize=1)
		pose_list.append(waypoint)
	#UR5_pose = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	#UR5_pose.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	#UR5_pose.bind(('', PORT2)) # Bind to the port


#read gcode file
with open('/home/eason/桌面/UR5/dynami_0002.ngc', 'r') as fh:
	print('Open file')

	for line_text in fh.readlines():
		#print line_text,
		line = Line(line_text)
		#print(line)  # will print the line (with cosmetic changes)
		line.block.gcodes  # is your list of gcodes
		line.block.modal_params  # are all parameters not assigned to a gcode, assumed to be motion modal parameters
		line.block.words
		waypoint = ''
		if len(line.block.words) != 0:
			a = words.words2dict(line.block.words)

			if 'G' in a.keys():

				if a['G']==0:

					if 'X' in a.keys():
						offset_x = a.get('X',0)
						last_pose_x = offset_x
Exemple #20
0
def processFile(infile, mods, modStartZ):
    m = Machine()
    outfile = getOutputFilename(infile, mods)
    print("Processing {inf} to {outf}".format(inf=infile, outf=outfile))
    with open(infile, 'r') as fhIn:
        fhOut = open(outfile, 'w')
        lineNumber = 0
        # Set all initial positions to 0
        curE = prevX = prevY = prevZ = prevE = lastZ = float(0)
        for line_text in fhIn.readlines():
            lineNumber = lineNumber + 1
            line = Line(line_text)
            if (line.comment is not None):
                debug("{line}: {comment}".format(line=lineNumber,
                                                 comment=line.comment))

            if (line.block.words is not None):
                hasX = hasY = hasZ = hasE = False
                origX, origY, origZ, origE = float(0)
                for word in line.block.words:
                    isMovement = False
                    if word.letter == "G" and word.value == 1:
                        isMovement = True
                    if (word.letter == "G" & word.value == 92):
                        prevE = 0  # Simplify3D resets E to 0 for each layer, so if we see a G92 we should consider the current position to be 0

                    hasX, origX = wordHasLetter(word, "X")
                    hasY, origY = wordHasLetter(word, "Y")
                    hasZ, origZ = wordHasLetter(word, "Z")
                    hasE, origE = wordHasLetter(word, "E")
                    if hasZ:
                        lastZ = origZ  # save last seen Z

                if isMovement:
                    # start by assuming the new XYZE will be the same as in the file
                    newX, newY, newE = origX, origY, origE
                    if (hasZ):
                        newZ = origZ
                    else:
                        # the line didn't specify Z so we have to use the last one we saw
                        origZ = lastZ
                        newZ = lastZ

                    for mod in mods:
                        adjustRoutine = mod["mod"]
                        extrudeOnly = mod["extrudeOnly"]
                        if (newZ >= modStartZ) and hasX and hasY and (
                                hasE or not extrudeOnly):
                            newX, newY, newZ, newE = adjustRoutine(
                                mod, modStartZ, m.abs_pos.X, m.abs_pos.Y,
                                m.abs_pos.Z, prevE, newX, newY, newZ, newE)

                    line = replaceOrAddLetter(line, "X", "{:.3f}".format(newX))
                    line = replaceOrAddLetter(line, "Y", "{:.3f}".format(newY))
                    line = replaceOrAddLetter(line, "Z", "{:.3f}".format(newZ))
                    line = replaceOrAddLetter(line, "E", "{:.4f}".format(newE))

                    #debug("*** X: {X} -> {nX}, Y: {Y} -> {nY}, Z: {Z} -> {nZ}, E: {E} -> {nE}".format(X = origX, Y=origY, Z= origZ, E=origE, nX = newX, nY = newY, nZ = newZ, nE = newE))
                    if (origZ != newZ) or (not hasZ):
                        line.comment = "; z {oz} to {nz}".format(oz=origZ,
                                                                 nz=newZ)

                    prevX, prevY, prevZ, prevE = newX, newY, newZ, newE

            try:
                m.process_block(line.block)
            except MachineInvalidState:
                #debug("here")
                continue
            finally:
                print(str(line), file=fhOut)
Exemple #21
0
 def _gcode_append_comment(self, line: Line, comment: str) -> None:
     """ Add new comment or append to existing comment. """
     line.comment = "%s ; %s" % (line.comment, comment)
Exemple #22
0
def cut(args, gcodes, clearance_height):
  non_motion = []
  
  # Select where to cut
  m = Machine()
  last = m.pos
  checkpoint = {'gcode': None, 'pos': m.pos, 'mode': m.mode.distance}
  for idx, gcode in enumerate(gcodes):
    m.process_gcodes(gcode['gcode'])
    if gcode["line_no"] > args.line:
      break
    if m.pos == last: non_motion.append(gcode)
    last = m.pos
    if clearance_height == m.pos._value['Z']:
      checkpoint = {'idx': idx, 'gcode': gcode, 'pos': m.pos, 'mode': m.mode.distance}
      
  #print("Checkpoint at {}".format(checkpoint))
  
  # If the user wants to cut before the first clearance height, do nothing
  if checkpoint['gcode'] is None:
    print("The provided line is not a valid one, use list subcommand for more info. Exiting")
    return
    
  # Dump the non motion commands first
  for gcode in non_motion:
   # if not isinstance(gcode['gcode'], GCodeFeedRate):  # Ignore feedrates please
      print(FORMAT.format(str(gcode['gcode']), str(gcode['line_no']), gcode['gcode'].__class__.__name__), file=args.output)
   
  # Insert the travel until the checkpoint position
  gcode = GCodeAbsoluteDistanceMode()
  print(FORMAT.format(str(gcode), "Cut comp.", gcode.__class__.__name__), file=args.output)
  gcode = GCodeRapidMove(Z=clearance_height)
  print(FORMAT.format(str(gcode), "Cut comp.", gcode.__class__.__name__), file=args.output)
  gcode = GCodeRapidMove(X=checkpoint['pos']._value['X'], Y=checkpoint['pos']._value['Y'], Z=checkpoint['pos']._value['Z'])
  print(FORMAT.format(str(gcode), "Cut comp.", gcode.__class__.__name__), file=args.output)
  gcode = checkpoint['mode']
  print(FORMAT.format(str(gcode), "Cut comp.", gcode.__class__.__name__), file=args.output)
  print(CHECKPOINT_TAG, file=args.output)
      
  # Dump the rest of the codes from the original file (to preserve formatting)
  try: 
    args.input.seek(gcodes[checkpoint['idx']+1]['offset'])
    for line in args.input:
      print(line, file=args.output, end="")
  except: pass
  
  if args.verify:
    s = Machine()
    t = Machine()
    
    # Run input gcodes until the selected
    for gcode in gcodes[:checkpoint['idx']+1]:
      s.process_gcodes(gcode['gcode'])
    
    # Run output gcodes until checkpoint
    args.output.seek(0)
    line = args.output.readline()
    while line:
      if CHECKPOINT_TAG in line:
        break
      for gcode in Line(line).block.gcodes:
        t.process_gcodes(gcode)
      line = args.output.readline()

    args.input.seek(gcodes[checkpoint['idx']+1]['offset'])
    sline = args.output.readline()
    tline = args.input.readline()
    while sline and tline:
      for gcode in Line(sline).block.gcodes: s.process_gcodes(gcode)
      for gcode in Line(tline).block.gcodes: t.process_gcodes(gcode)
      if s.pos!=t.pos:
        print("\nOutput gcode not verified (source: {}, target: {})".format(s.pos, t.pos))
        return
      sline = args.output.readline()
      tline = args.input.readline()
        
    print("\nOutput gcode verified")