Ejemplo n.º 1
0
 def __check_delta(self, delta):
     pos = self._position + delta
     if not pos.is_in_aabb(
             Coordinates(0.0, 0.0, 0.0, 0.0),
             Coordinates(TABLE_SIZE_X_MM, TABLE_SIZE_Y_MM, TABLE_SIZE_Z_MM,
                         0)):
         raise GMachineException("out of effective area")
Ejemplo n.º 2
0
 def home(self):
     """ Move head to park position
     """
     d = Coordinates(0, 0, -self._position.z, 0)
     self._move_linear(d, STEPPER_MAX_VELOCITY_MM_PER_MIN)
     d = Coordinates(-self._position.x, -self._position.y, 0, 0)
     self._move_linear(d, STEPPER_MAX_VELOCITY_MM_PER_MIN)
Ejemplo n.º 3
0
    def _pos_check(self, target_pos, delta_mm, velocity_mm_per_min):
        tolerance_digit = 1
        dut = PathGenerator(delta_mm, target_pos, velocity_mm_per_min)
        last_pos = Coordinates(0, 0, 0, 0)
        for px, py, pz, pe in dut:
            last_pos = Coordinates(px, py, pz, 0)

        distance_error = last_pos - target_pos
        self.assertAlmostEqual(distance_error.length(), 0.0, tolerance_digit)
Ejemplo n.º 4
0
 def reset(self):
     """ Reinitialize all program configurable thing.
     """
     self._velocity = 1000
     self._spindle_rpm = 1000
     self._pause = 0
     self._local = Coordinates(0.0, 0.0, 0.0, 0.0)
     self._convertCoordinates = 1.0
     self._absoluteCoordinates = True
     self._plane = PLANE_XY
     self._radius = Coordinates(0.0, 0.0, 0.0, 0.0)
Ejemplo n.º 5
0
 def test_position_overshoot_x(self):
     targets = [Coordinates(x, 0, 0, 0) for x in [60]]
     too_fast_speed = MAX_VELOCITY_MM_PER_MIN_X * 1.1
     velocities = [too_fast_speed]
     for target_pos in targets:
         delta_mm = target_pos
         for velocity_mm_per_min in velocities:
             self._overshoot_check(target_pos, delta_mm,
                                   velocity_mm_per_min)
Ejemplo n.º 6
0
 def radius(self, default, multiply):
     """ Get radius for circular interpolation(I, J, K or R).
     :param default: Default values, if any of coords is not specified.
     :param multiply: If value exist, multiply it by this value.
     :return: Coord object.
     """
     i = self.get('I', default.x, multiply)
     j = self.get('J', default.y, multiply)
     k = self.get('K', default.z, multiply)
     return Coordinates(i, j, k, 0)
Ejemplo n.º 7
0
 def coordinates(self, default, multiply):
     """ Get X, Y and Z values as Coord object.
     :param default: Default values, if any of coordinates is not specified.
     :param multiply: If value exist, multiply it by this value.
     :return: Coord object.
     """
     x = self.get('X', default.x, multiply)
     y = self.get('Y', default.y, multiply)
     z = self.get('Z', default.z, multiply)
     e = self.get('E', default.e, multiply)
     return Coordinates(x, y, z, e)
Ejemplo n.º 8
0
    def test_end_position(self):
        targets = [Coordinates(x, x, x, 0) for x in range(1, 101, 20)]
        too_fast_speed = math.ceil(
            max(MAX_VELOCITY_MM_PER_MIN_X, MAX_VELOCITY_MM_PER_MIN_Y,
                MAX_VELOCITY_MM_PER_MIN_Z) * 1.1)
        velocities = [1, too_fast_speed]

        for target_pos in targets:
            delta_mm = target_pos
            for velocity_mm_per_min in velocities:
                self._pos_check(target_pos, delta_mm, velocity_mm_per_min)
Ejemplo n.º 9
0
 def _circular(self, delta, radius, velocity, direction):
     delta = delta.round(1.0 / STEPPER_PULSES_PER_MM_X,
                         1.0 / STEPPER_PULSES_PER_MM_Y,
                         1.0 / STEPPER_PULSES_PER_MM_Z,
                         1.0 / STEPPER_PULSES_PER_MM_E)
     self.__check_delta(delta)
     # get delta vector and put it on circle
     circle_end = Coordinates(0, 0, 0, 0)
     if self._plane == PLANE_XY:
         circle_end.x, circle_end.y = self.__adjust_circle(
             delta.x, delta.y, radius.x, radius.y, direction,
             self._position.x, self._position.y, TABLE_SIZE_X_MM,
             TABLE_SIZE_Y_MM)
         circle_end.z = delta.z
     elif self._plane == PLANE_YZ:
         circle_end.y, circle_end.z = self.__adjust_circle(
             delta.y, delta.z, radius.y, radius.z, direction,
             self._position.y, self._position.z, TABLE_SIZE_Y_MM,
             TABLE_SIZE_Z_MM)
         circle_end.x = delta.x
     elif self._plane == PLANE_ZX:
         circle_end.z, circle_end.x = self.__adjust_circle(
             delta.z, delta.x, radius.z, radius.x, direction,
             self._position.z, self._position.x, TABLE_SIZE_Z_MM,
             TABLE_SIZE_X_MM)
         circle_end.y = delta.y
     circle_end.e = delta.e
     circle_end = circle_end.round(1.0 / STEPPER_PULSES_PER_MM_X,
                                   1.0 / STEPPER_PULSES_PER_MM_Y,
                                   1.0 / STEPPER_PULSES_PER_MM_Z,
                                   1.0 / STEPPER_PULSES_PER_MM_E)
     hal.move_circular(circle_end, radius, self._plane, velocity, direction)
     # if finish coords is not on circle, move some distance linearly
     linear_delta = delta - circle_end
     if not linear_delta.is_zero():
         logging.info(
             "Moving additionally {} to finish circle command".format(
                 linear_delta))
         hal.move_linear(linear_delta, velocity)
     # save position
     self._position = self._position + circle_end + linear_delta
Ejemplo n.º 10
0
    def _speed_check(self, velocity_mm_per_min, delta_mm):
        #print("testing {:.2f} mm/min".format(velocity_mm_per_min))
        new_pos = delta_mm
        dut = PathGenerator(delta_mm, new_pos, velocity_mm_per_min)
        old_pos = Coordinates(0, 0, 0, 0)
        max_speed = 0
        for px, py, pz, pe in dut:
            p = Coordinates(px, py, pz, 0)
            delta = p - old_pos
            old_pos = p
            v = delta.length() / REAL_TIME_DT
            max_speed = max(max_speed, v)

        self.assertNotEqual(
            dut.linear_time_s, 0.0,
            "Not enough space to reach the max speed ({:.2f}mm/min) given that acceleration"
            .format(velocity_mm_per_min))
        self.assertAlmostEqual(
            max_speed, velocity_mm_per_min / SECONDS_IN_MINUTE, 1,
            "Effective max speed not correct when trying {:f} mm/min".format(
                velocity_mm_per_min))
Ejemplo n.º 11
0
 def __init__(self):
     """ Initialization.
     """
     self._position = Coordinates(0.0, 0.0, 0.0, 0.0)
     # init variables
     self._velocity = 0
     self._spindle_rpm = 0
     self._pause = 0
     self._local = None
     self._convertCoordinates = 0
     self._absoluteCoordinates = 0
     self._plane = None
     self._radius = None
     self.reset()
     hal.init()
Ejemplo n.º 12
0
    def _overshoot_check(self, target_pos, delta_mm, velocity_mm_per_min):
        tolerance_digit = 1
        dut = PathGenerator(delta_mm, target_pos, velocity_mm_per_min)
        max_pos = Coordinates(0, 0, 0, 0)
        for px, py, pz, pe in dut:
            p = Coordinates(px, py, pz, 0)
            max_pos.x = max(max_pos.x, p.x)
            max_pos.y = max(max_pos.y, p.y)
            max_pos.z = max(max_pos.z, p.z)

        distance_error = max_pos - target_pos
        self.assertAlmostEqual(distance_error.length(), 0.0, tolerance_digit)
Ejemplo n.º 13
0
 def do_command(self, gcode):
     """ Perform action.
     :param gcode: GCode object which represent one gcode line
     """
     if gcode is None:
         return
     logging.debug("got command " + str(gcode.params))
     # read command
     c = gcode.command()
     if c is None and gcode.has_coordinates():
         c = 'G1'
     # read parameters
     if self._absoluteCoordinates:
         coord = gcode.coordinates(self._position, self._convertCoordinates)
         coord = coord + self._local
         delta = coord - self._position
     else:
         delta = gcode.coordinates(Coordinates(0.0, 0.0, 0.0, 0.0),
                                   self._convertCoordinates)
         coord = self._position + delta
     velocity = gcode.get('F', self._velocity)
     spindle_rpm = gcode.get('S', self._spindle_rpm)
     pause = gcode.get('P', self._pause)
     radius = gcode.radius(self._radius, self._convertCoordinates)
     # check parameters
     if velocity <= 0 or velocity > STEPPER_MAX_VELOCITY_MM_PER_MIN:
         raise GMachineException("bad feed speed")
     if spindle_rpm < 0 or spindle_rpm > SPINDLE_MAX_RPM:
         raise GMachineException("bad spindle speed")
     if pause < 0:
         raise GMachineException("bad delay")
     # select command and run it
     if c == 'G0':  # rapid move
         self._move_linear(delta, STEPPER_MAX_VELOCITY_MM_PER_MIN)
     elif c == 'G1':  # linear interpolation
         self._move_linear(delta, velocity)
     elif c == 'G2':  # circular interpolation, clockwise
         self._circular(delta, radius, velocity, CW)
     elif c == 'G3':  # circular interpolation, counterclockwise
         self._circular(delta, radius, velocity, CCW)
     elif c == 'G4':  # delay in s
         hal.join()
         time.sleep(pause)
     elif c == 'G17':  # XY plane select
         self._plane = PLANE_XY
     elif c == 'G18':  # ZX plane select
         self._plane = PLANE_ZX
     elif c == 'G19':  # YZ plane select
         self._plane = PLANE_YZ
     elif c == 'G20':  # switch to inches
         self._convertCoordinates = 25.4
     elif c == 'G21':  # switch to mm
         self._convertCoordinates = 1.0
     elif c == 'G28':  # home
         self.home()
     elif c == 'G53':  # switch to machine coords
         self._local = Coordinates(0.0, 0.0, 0.0, 0.0)
     elif c == 'G90':  # switch to absolute coords
         self._absoluteCoordinates = True
     elif c == 'G91':  # switch to relative coords
         self._absoluteCoordinates = False
     elif c == 'G92':  # switch to local coords
         self._local = self._position - \
                       gcode.coordinates(Coordinates(0.0, 0.0, 0.0, 0.0),
                                         self._convertCoordinates)
     elif c == 'M3':  # spinle on
         self._spindle(spindle_rpm)
     elif c == 'M5':  # spindle off
         self._spindle(0)
     elif c == 'M2' or c == 'M30':  # program finish, reset everything.
         self.reset()
     elif c == 'M111':  # enable debug
         logging.getLogger().setLevel(logging.DEBUG)
     elif c is None:  # command not specified(for example, just F was passed)
         pass
     else:
         raise GMachineException("unknown command")
     # save parameters on success
     self._velocity = velocity
     self._spindle_rpm = spindle_rpm
     self._pause = pause
     self._radius = radius
     logging.debug("position {}".format(self._position))
Ejemplo n.º 14
0
 def test_max_speed_x(self):
     max_possible_speed = MAX_VELOCITY_MM_PER_MIN_X
     delta_mm = Coordinates(60, 0, 0, 0)
     for speed in (1, int(math.floor(max_possible_speed))):
         self._speed_check(speed, delta_mm)