def move_to(self, x=None, y=None, z=None, check=False, translate=True): """ Move to an absolute cartesian coordinate :param x: Cartesian millimeter of the X axis, if None then uses current position :param y: Cartesian millimeter of the Y axis, if None then uses current position :param z: Cartesian millimeter of the Z axis, if None then uses current position :param check: If True, asks the connected uArm device if the target coordinate is within its range of movement :return: self """ logger.debug('move_to: x={0}, y={1}, z={2}'.format(x, y, z)) if not self._enabled: self.enable_all_motors() new_pos = self._pos.copy() if x is not None: new_pos['x'] = x if y is not None: new_pos['y'] = y if z is not None: new_pos['z'] = z new_pos = round_position(new_pos) if translate: real_pos = self._remove_z_offset(new_pos) else: real_pos = new_pos.copy() if not self.is_simulating(): if check and not self.can_move_to(**real_pos): raise RuntimeError( 'Coordinate not reachable by uArm: {0}'.format(new_pos)) speed_mm_per_min = self._speed * 60 self.set_position(relative=False, speed=speed_mm_per_min, **real_pos) self._pos = new_pos.copy() return self
def update_position(self, check=False): """ Retrieve the current XYZ coordinate position from the connected uArm device :return: self """ logger.debug('update_position') if self.is_simulating(): return self pos = self.get_position(wait=True) is_n = pos is None is_l = isinstance(pos, list) if is_n or not is_l or not len(pos) or not isinstance(pos[0], float): logger.debug('Not able to read position, out of bounds') return self new_pos = round_position(self._apply_z_offset({ 'x': pos[0], 'y': pos[1], 'z': pos[2] })) distance = 0 check = check and self._enabled # no need to check if motors are disabled if check: old_pos = self._pos.copy() distance, _, _ = cartesian_to_polar( **subtract_positions(new_pos, old_pos)) self._pos = new_pos if check and distance > UARM_SKIPPED_DISTANCE_THRESHOLD: raise RuntimeError( 'Detected {0}mm skipped: target={1} - actual={2}'.format( round(distance, 1), old_pos, new_pos)) logger.debug('New Position: {0}'.format(self._pos)) return self
def can_move_relative(self, x=None, y=None, z=None): logger.debug('can_move_relative: x={0}, y={1}, z={2}'.format(x, y, z)) new_pos = self._pos.copy() if x is not None: new_pos['x'] = x + new_pos['x'] if y is not None: new_pos['y'] = y + new_pos['y'] if z is not None: new_pos['z'] = z + new_pos['z'] new_pos = round_position(new_pos) return self.can_move_to(**new_pos)
def can_move_to(self, x=None, y=None, z=None): logger.debug('can_move_to: x={0}, y={1}, z={2}'.format(x, y, z)) if self.is_simulating(): return True # no way to test during simulation new_pos = self._pos.copy() if x is not None: new_pos['x'] = x if y is not None: new_pos['y'] = y if z is not None: new_pos['z'] = z new_pos = round_position(new_pos) # Send coordinates to uArm to see if they are within the limit. # This must be done on the device itself, because of it's weird # coordinate system and load-carrying ability at different positions. new_pos = self._remove_z_offset(new_pos) unreachable = self.check_pos_is_limit(list(new_pos.values())) return not bool(unreachable)
def move_relative(self, x=None, y=None, z=None, check=False): """ Move to a relative cartesian coordinate, away from it's current coordinate :param x: Cartesian millimeter of the X axis, if None then uses current position :param y: Cartesian millimeter of the Y axis, if None then uses current position :param z: Cartesian millimeter of the Z axis, if None then uses current position :param check: If True, asks the connected uArm device if the target coordinate is within its range of movement :return: self """ logger.debug('move_relative: x={0}, y={1}, z={2}'.format(x, y, z)) rel_pos = self._pos.copy() if x is not None: rel_pos['x'] = x + self._pos['x'] if y is not None: rel_pos['y'] = y + self._pos['y'] if z is not None: rel_pos['z'] = z + self._pos['z'] rel_pos = round_position(rel_pos) # using only absolute movements, because accelerations do not seem to take # affect when using relative movements (not sure if firmware or API issue) self.move_to(check=check, **rel_pos) return self