Example #1
0
    def opcode_filter(self, opcode):
        if opcode.command == GCODE_RELATIVE_EXTRUSION_COMMAND:
            self.relative_extrusion = True
            return

        if opcode.command == GCODE_ABSOLUTE_EXTRUSION_COMMAND:
            self.relative_extrusion = False
            return raw_to_line(GCODE_RELATIVE_EXTRUSION_COMMAND)

        if opcode.command == GCODE_SET_POSITION_COMMAND:

            # when setting position, if E is set, use it, but if there is parameter, consider E=0
            if opcode.e is not None:
                self.current_extrusion_distance = Decimal(opcode.e)
            elif opcode.x is None and opcode.y is None and opcode.z is None:
                self.current_extrusion_distance = Decimal()

            return

        if opcode.command in move_gcodes and not self.relative_extrusion and opcode.e is not None:
            # we're extruding while in absolute extrusion mode, reduce by the amount extruded so far
            # and keep track of the current e for later reuse
            opcode.e, self.current_extrusion_distance = (
            opcode.e - float(self.current_extrusion_distance), Decimal(opcode.e))
            opcode.relative_e=True
            unsplit(opcode)
            return opcode
Example #2
0
 def to_gcode(self):
     """
     translate a sequence of segments into a circular gcode command
     :return: the gcode command
     """
     result = [self.queue[0]]
     last = self.queue.pop()
     count = len(self.queue)
     end_point = self.queue[-1]
     error, circle = self.get_circle()
     extrusions = self.get_distances()
     op1 = Line()
     result.append(op1)
     op1.command = "G3" if circle.direction > 0 else "G2"  # G2 is CW, G3 CCW
     op1.x = round(circle.end.x, 3)
     op1.y = round(circle.end.y, 3)
     op1.i = round(circle.center.x - circle.start.x, 3)
     op1.j = round(circle.center.y - circle.start.y, 3)
     if end_point.relative_e:
         # calculate extrusion correction
         # arc length   b = r·alpha (alpha in radian)
         # chord length s = 2·r·sin(alpha/2)
         # resulting arc extrusion is s0*b/s
         op1.e = sum([
             s0 * (circle.radius * alpha) /
             (2 * circle.radius * sin(alpha / 2))
             for s0, alpha in zip(extrusions['filament'].values(),
                                  self.get_phase_diffs(circle))
         ])
         op1.relative_e = True
     else:
         # absolute mode: fall-back to the original length
         phase_diffs = self.get_phase_diffs(circle)
         arc_lens = [alpha * circle.radius for alpha in phase_diffs]
         arc_extrusion_length = sum(arc_lens) * extrusions['avg']['ratio']
         op1.e = self.queue[0].current_e + arc_extrusion_length
         op1.relative_e = False
         rel = arc_extrusion_length / extrusions['total']['filament']
         if (rel - 1) > EXTRUSION_CORRECTION_LIMIT:
             op2 = Line()
             op2.command = "G92"
             op2.e = op2.current_e = end_point.current_e
             unsplit(op2)
             op2.raw += "; generated as arc to path relation is %f" % rel
             result.append(op2)
     op1.f = end_point.current_f
     unsplit(op1)
     op1.raw += "; generated from %s segments" % (count - 1)
     self.valid_circle = False
     result.append(last)
     logger.info(" generated arc from %s segments" % (count - 1))
     logger.debug("arc is " + str(circle))
     return result
Example #3
0
    def opcode_filter(self, opcode):
        if opcode.command in move_gcodes:

            if self.absolute_distance_mode is None:
                logging.warn(
                    'Move detected without absolute or related mode selected first'
                )
                return

            if not self.absolute_distance_mode:

                # we're in relative mode, if the first move after a homing, translate quickly
                if self.first_move_after_home:
                    self.first_move_after_home = False
                    return [self.generate_translation(), opcode]

                return

            # at this point, we're an absolute move, we have to "hard patch" coordinate
            if opcode.x is not None and self.translate_x:
                opcode.x += self.translate_x
                unsplit(opcode)

            if opcode.y is not None and self.translate_y:
                opcode.y += self.translate_y
                unsplit(opcode)

            return opcode

        if opcode.command == GCODE_ABSOLUTE_POSITIONING_COMMAND:
            self.absolute_distance_mode = True
            return

        if opcode.command == GCODE_RELATIVE_POSITIONING_COMMAND:
            self.absolute_distance_mode = False
            return

        if opcode.command == GCODE_SET_POSITION_COMMAND:
            if opcode.x is None and opcode.y is None and opcode.z is None:
                # no coordinate given is equivalent to all 0
                opcode.x = -self.translate_x
                opcode.y = -self.translate_y

                # now, there is a new reference point, that we translated so there's nothing left to do until
                # the end of the program
                self.translate_x = self.translate_y = 0

                unsplit(opcode)
                return opcode

            if opcode.x is not None:
                opcode.x -= self.translate_x
                self.translate_x = 0

            if opcode.y is not None:
                opcode.y -= self.translate_y
                self.translate_y = 0

            unsplit(opcode)
            return opcode
Example #4
0
 def to_gcode(self):
     """
     translate a sequence of segments into a circular gcode command
     :return: the gcode command
     """
     result=[self.queue[0]]
     last = self.queue.pop()
     count = len(self.queue)
     end_point = self.queue[-1]
     error, circle = self.get_circle()
     extrusions = self.get_distances()
     op1 = Line()
     result.append(op1)
     op1.command = "G3" if circle.direction >0 else "G2" # G2 is CW, G3 CCW
     op1.x = round(circle.end.x, 3)
     op1.y = round(circle.end.y, 3)
     op1.i = round(circle.center.x - circle.start.x, 3)
     op1.j = round(circle.center.y - circle.start.y, 3)
     if end_point.relative_e:
         # calculate extrusion correction
         # arc length   b = r·alpha (alpha in radian)
         # chord length s = 2·r·sin(alpha/2)
         # resulting arc extrusion is s0*b/s
         op1.e = sum([ s0*(circle.radius*alpha)/(2*circle.radius*sin(alpha/2))
               for s0, alpha in zip(extrusions['filament'].values(), self.get_phase_diffs(circle))])
         op1.relative_e = True
     else:
         # absolute mode: fall-back to the original length
         phase_diffs=self.get_phase_diffs(circle)
         arc_lens=[ alpha*circle.radius for alpha in phase_diffs]
         arc_extrusion_length=sum(arc_lens)*extrusions['avg']['ratio']
         op1.e=self.queue[0].current_e+arc_extrusion_length
         op1.relative_e=False
         rel = arc_extrusion_length/extrusions['total']['filament']
         if (rel - 1) > EXTRUSION_CORRECTION_LIMIT:
             op2= Line()
             op2.command="G92"
             op2.e = op2.current_e = end_point.current_e
             unsplit(op2)
             op2.raw += "; generated as arc to path relation is %f" % rel
             result.append(op2)
     op1.f = end_point.current_f
     unsplit(op1)
     op1.raw += "; generated from %s segments" % (count - 1)
     self.valid_circle = False
     result.append(last)
     logger.info(" generated arc from %s segments" % (count - 1))
     logger.debug("arc is "+str(circle))
     return result
Example #5
0
    def opcode_filter(self, opcode):
        if opcode.command in move_gcodes:

            if self.absolute_distance_mode is None:
                logging.warn('Move detected without absolute or related mode selected first')
                return

            if not self.absolute_distance_mode:

                # we're in relative mode, if the first move after a homing, translate quickly
                if self.first_move_after_home:
                    self.first_move_after_home = False
                    return [self.generate_translation(), opcode]

                return

            # at this point, we're an absolute move, we have to "hard patch" coordinate
            if opcode.x is not None and self.translate_x:
                opcode.x += self.translate_x
                unsplit(opcode)

            if opcode.y is not None and self.translate_y:
                opcode.y += self.translate_y
                unsplit(opcode)

            return opcode

        if opcode.command == GCODE_ABSOLUTE_POSITIONING_COMMAND:
            self.absolute_distance_mode = True
            return

        if opcode.command == GCODE_RELATIVE_POSITIONING_COMMAND:
            self.absolute_distance_mode = False
            return

        if opcode.command == GCODE_SET_POSITION_COMMAND:
            if opcode.x is None and opcode.y is None and opcode.z is None:
                # no coordinate given is equivalent to all 0
                opcode.x = - self.translate_x
                opcode.y = - self.translate_y

                # now, there is a new reference point, that we translated so there's nothing left to do until
                # the end of the program
                self.translate_x = self.translate_y = 0

                unsplit(opcode)
                return opcode

            if opcode.x is not None:
                opcode.x -= self.translate_x
                self.translate_x = 0

            if opcode.y is not None:
                opcode.y -= self.translate_y
                self.translate_y = 0

            unsplit(opcode)
            return opcode
Example #6
0
    def get_stretched_line_from_index_location(self, indexPreviousStart, indexNextStart, location, original_line):
        """Get stretched gcode line from line index and location."""
        crossIteratorForward = self.line_forward_iterator(indexNextStart, self.current_layer)
        crossIteratorBackward = self.line_backward_iterator(indexPreviousStart, self.current_layer)
        iteratorForward = self.line_forward_iterator(indexNextStart, self.current_layer)
        iteratorBackward = self.line_backward_iterator(indexPreviousStart, self.current_layer)

        locationComplex = location.dropAxis()

        logging.debug("original point to stretch: %s", locationComplex)

        relativeStretch = self.get_relative_stretch(locationComplex, iteratorForward) \
                          + self.get_relative_stretch(locationComplex, iteratorBackward)
        relativeStretch *= 0.8
        relativeStretch = self.get_cross_limited_stretch(relativeStretch, crossIteratorForward, locationComplex)
        relativeStretch = self.get_cross_limited_stretch(relativeStretch, crossIteratorBackward, locationComplex)

        relativeStretchLength = abs(relativeStretch)

        if relativeStretchLength > 1.0:
            relativeStretch /= relativeStretchLength

        logging.debug("relativeStretchLength: %f", relativeStretchLength)

        absoluteStretch = relativeStretch * self.thread_maximum_absolute_stretch
        stretchedPoint = location.dropAxis() + absoluteStretch

        result = Line()
        result.command = original_line.command
        result.x = stretchedPoint.real
        result.y = stretchedPoint.imag
        result.z = original_line.z
        result.f = self.feedRateMinute

        # TODO improve new extrusion length computation. It's clearly a very rough estimate
        if original_line.e is not None:
            result.e = original_line.e * (1 - abs(absoluteStretch))

        unsplit(result)

        logging.debug("stretched point: %f %f", result.x, result.y)

        return result