def connect(self) -> bool: """ Connect driver. : returns: True if connection stablished False if not """ try: #assert ROBODK_API_FOUND, "RoboDK API is not available." self._connection = Robolink() if self._connection: self.robot = self._connection.Item(self.controller) if self.robot: if self.robot.Valid() and self.robot.Type() == ITEM_TYPE_ROBOT: self.sendDebugInfo(f'Driver RoboDK Connected to {self.controller}...') return True else: self.sendDebugInfo(f'Item {self.controller} not found!') else: self.sendDebugInfo(f'Controler not found!') else: self.sendDebugInfo(f'Connection with Robolink not possible.') except Exception as e: self.sendDebugInfo('Exception '+str(e)) return False
def removeParameters(RDK=None): if RDK is None: RDK = Robolink() RDK.setParam(PARAM_BOX_X, b'') RDK.setParam(PARAM_BOX_Y, b'') RDK.setParam(PARAM_BOX_Z, b'') RDK.setParam(PARAM_UNITS, b'') RDK.setParam(PARAM_PARENT_NAME, b'') RDK.setParam(PARAM_CONV_PARENT_NAME, b'')
def __init__(self, RDK=None) -> None: self.RDK = RDK if self.RDK is None: self.RDK = Robolink() self.root = tk.Tk() self.radius = tk.DoubleVar(value=0) self.parent_name_text = tk.StringVar( value=odt.PARENT.Name() if odt.PARENT is not None else 'Unset') odt.loadParameters(self.RDK) self.init()
def Save(self, rdk=None, autorecover=False): # Save the class attributes as a string # Use a dictionary and the str/eval buit-in conversion attribs_list = self._getAttribsSave() if len(attribs_list) <= 0: print("Saving skipped") return print("Saving data to RoboDK station...") dict_data = {} # Important! We must save this but not show it in the UI dict_data['_FIELDS_UI'] = self._FIELDS_UI for key in attribs_list: dict_data[key] = getattr(self, key) #Protocol tips: https://docs.python.org/3/library/pickle.html import pickle bytes_data = pickle.dumps( dict_data, protocol=2 ) # protocol=2: bynary, compatible with python 2.3 and later if rdk is None: from robolink import Robolink rdk = Robolink() param_val = self._SETTINGS_PARAM param_backup = param_val + "-Backup" if autorecover: rdk.setParam(param_backup, bytes_data) else: rdk.setParam(param_val, bytes_data) rdk.setParam(param_backup, b'')
class RunApplication: """Class to detect when the terminate signal is emited to stop an action. .. code-block:: python run = RunApplication() while run.Run(): # your main loop to run until the terminate signal is detected ... """ time_last = -1 param_name = None RDK = None def __init__(self, rdk=None): if rdk is None: from robolink import Robolink self.RDK = Robolink() else: self.RDK = rdk self.time_last = time.time() if len(sys.argv) > 0: path = sys.argv[0] folder = os.path.basename(os.path.dirname(path)) file = os.path.basename(path) if file.endswith(".py"): file = file[:-3] elif file.endswith(".exe"): file = file[:-4] self.param_name = file + "_" + folder self.RDK.setParam( self.param_name, "1") # makes sure we can run the file separately in debug mode def Run(self): time_now = time.time() if time_now - self.time_last < 0.25: return True self.time_last = time_now if self.param_name is None: # Unknown start return True keep_running = not (self.RDK.getParam(self.param_name) == 0) return keep_running
def createBox(RDK=None): if RDK is None: RDK = Robolink() global BOX_SIZE_XYZ global USE_METRIC global PARENT global CONV_PARENT RDK.Render(False) x, y, z = BOX_SIZE_XYZ if USE_METRIC: new_box = RDK.AddFile(REF_BOX_MM_PATH, PARENT) new_box.setName(BOX_ITEM_NAME_MM % (x, y, z)) else: new_box = RDK.AddFile(REF_BOX_IN_PATH, PARENT) new_box.setName(BOX_ITEM_NAME_IN % (x, y, z)) new_box.setPose(eye(4)) new_box.Scale([x, y, z]) RDK.Update() if CONV_PARENT is not None: new_box.setParentStatic(CONV_PARENT) new_box.setVisible(True) RDK.Render(True)
def __init__(self, rdk=None): if rdk is None: from robolink import Robolink self.RDK = Robolink() else: self.RDK = rdk self.time_last = time.time() if len(sys.argv) > 0: path = sys.argv[0] folder = os.path.basename(os.path.dirname(path)) file = os.path.basename(path) if file.endswith(".py"): file = file[:-3] elif file.endswith(".exe"): file = file[:-4] self.param_name = file + "_" + folder self.RDK.setParam(self.param_name, "1") # makes sure we can run the file separately in debug mode
def setParameters(RDK=None): if RDK is None: RDK = Robolink() global RADIUS global PARENT RDK.setParam(PARAM_RADIUS, RADIUS) if PARENT is not None: RDK.setParam(PARAM_PARENT_NAME, PARENT.Name()) else: RDK.setParam(PARAM_PARENT_NAME, '')
def AttachCamera(): RDK = Robolink() item2station_pose = eye(4) view_pose_last = eye(4) last_item = None RDK.Render() run = RunApplication() while run.Run(): # Retrieve user selection selected_items = RDK.Selection() if len(selected_items) <= 0: last_item = None continue # Use the first selected item to attach the camera item = selected_items[0] # Prevent selecting programs or instructions or anything that doesn't move if item.type == ITEM_TYPE_ROBOT or item.type == ITEM_TYPE_TOOL or item.type == ITEM_TYPE_FRAME or item.type == ITEM_TYPE_OBJECT or item.type == ITEM_TYPE_TARGET: item_pose = item.PoseAbs( ) # Selected item pose with respect to the station reference item2station_pose = item_pose.inv() if last_item != item: # If it is the first time we select this item: update the relationship camera 2 item pose view_pose = RDK.ViewPose( ) # View Pose (camera pose with respect to the station reference) camera2item_pose = (item2station_pose * view_pose.inv()).inv() msg = 'Camera attached to %s' % item.Name() print(msg) RDK.ShowMessage(msg, False) last_item = item else: # calculate the new view pose and udpate it view_pose = camera2item_pose * item2station_pose # Only update if the view pose changed if view_pose != view_pose_last: view_pose_last = view_pose RDK.setViewPose(view_pose) RDK.Render()
def objectsInZone(RDK=None): if RDK is None: RDK = Robolink() global RADIUS global PARENT objects_in_zone = [] if PARENT is None or not PARENT.Valid(): return objects_in_zone objects = RDK.ItemList(ITEM_TYPE_OBJECT) if objects is None or len(objects) < 1: return objects_in_zone p_abs = PARENT.PoseAbs().Pos() for obj in objects: if distance(p_abs, obj.PoseAbs().Pos()) < RADIUS: objects_in_zone.append(obj) return objects_in_zone
def __init__(self, RDK=None) -> None: self.RDK = RDK if self.RDK is None: self.RDK = Robolink() self.root = tk.Tk() self.unit_options = tk.IntVar() self.units_format = '' self.box_length = tk.DoubleVar(value=0) self.box_width = tk.DoubleVar(value=0) self.box_height = tk.DoubleVar(value=0) self.box_length_text = tk.StringVar(value='') self.box_width_text = tk.StringVar(value='') self.box_height_text = tk.StringVar(value='') self.parent_name_text = tk.StringVar(value='') self.conv_parent_name_text = tk.StringVar(value='') sbt.loadParameters(self.RDK) self.init()
def Load(self, rdk=None): #, stream_data=b''): """Save the class attributes as a RoboDK binary parameter""" # Use a dictionary and the str/eval buit-in conversion attribs_list = self._getAttribsSave() #if len(attribs_list) == 0: # print("Load settings: No attributes to load") # return False print("Loading data from RoboDK station...") if rdk is None: from robolink import Robolink rdk = Robolink() param_backup = self._SETTINGS_PARAM param_backup += "-Backup" bytes_data = rdk.getParam(param_backup, False) if len(bytes_data) > 0: import robodk result = robodk.ShowMessageYesNoCancel( "Something went wrong with the last test.\nRecover lost data?", "Auto recover") if result is None: return False elif not result: bytes_data = b'' # Clear backup data rdk.setParam(param_backup, b'', False) if len(bytes_data) <= 0: bytes_data = rdk.getParam(self._SETTINGS_PARAM, False) if len(bytes_data) <= 0: print("Load settings: No data for " + self._SETTINGS_PARAM) return False import pickle saved_dict = pickle.loads(bytes_data) for key in saved_dict.keys(): # if we have a list of attributes that we want, load it only if it is in the list if len(attribs_list) > 0 and not key in attribs_list: print("Obsolete variable saved (will be deleted): " + key) else: value = saved_dict[key] setattr(self, key, value) return True
def loadParameters(RDK=None): if RDK is None: RDK = Robolink() global RADIUS global PARENT radius = RDK.getParam(PARAM_RADIUS, True) if radius is not None and radius != '': RADIUS = float(radius) parent_name = RDK.getParam(PARAM_PARENT_NAME, True) if parent_name is not None and parent_name != '': item = RDK.Item(parent_name) if item.Valid() and item.Name() == parent_name: PARENT = item if PARENT is None: PARENT = RDK.ActiveStation()
class SpawnBoxEditor: SIZE_SPINBOX_FROM = 0.1 SIZE_SPINBOX_TO = 10000 SIZE_SPINBOX_INCREMENT = 0.5 SIZE_SPINBOX_FORMAT = "%0.2f" WIDTH_ENTRY = 32 STICKY = tk.NSEW def __init__(self, RDK=None) -> None: self.RDK = RDK if self.RDK is None: self.RDK = Robolink() self.root = tk.Tk() self.unit_options = tk.IntVar() self.units_format = '' self.box_length = tk.DoubleVar(value=0) self.box_width = tk.DoubleVar(value=0) self.box_height = tk.DoubleVar(value=0) self.box_length_text = tk.StringVar(value='') self.box_width_text = tk.StringVar(value='') self.box_height_text = tk.StringVar(value='') self.parent_name_text = tk.StringVar(value='') self.conv_parent_name_text = tk.StringVar(value='') sbt.loadParameters(self.RDK) self.init() def init(self): self.unit_options.set(int(sbt.USE_METRIC)) self.units_format = '(mm)' if sbt.USE_METRIC else '(in)' self.box_length.set(sbt.BOX_SIZE_XYZ[0]) self.box_width.set(sbt.BOX_SIZE_XYZ[1]) self.box_height.set(sbt.BOX_SIZE_XYZ[2]) self.box_length_text.set('Box Length ' + self.units_format) self.box_width_text.set('Box Width ' + self.units_format) self.box_height_text.set('Box Height ' + self.units_format) self.parent_name_text.set(sbt.PARENT.Name() if sbt.PARENT is not None else 'Unset') self.conv_parent_name_text.set(sbt.CONV_PARENT.Name() if sbt.CONV_PARENT is not None else 'Unset') def switchUnitsFormat(self): use_metric = self.unit_options.get() == 1 if use_metric != sbt.USE_METRIC: # Convert units factor = 25.4 # in to mm if sbt.USE_METRIC and not use_metric: factor = 1 / 25.4 # mm to in self.box_length.set(self.box_length.get() * factor) self.box_width.set(self.box_width.get() * factor) self.box_height.set(self.box_height.get() * factor) sbt.USE_METRIC = use_metric def setBoxDimensions(self): sbt.BOX_SIZE_XYZ[0] = self.box_length.get() sbt.BOX_SIZE_XYZ[1] = self.box_width.get() sbt.BOX_SIZE_XYZ[2] = self.box_height.get() def selectParent(self): self.RDK.setSelection([]) choices = self.RDK.ItemList(ITEM_TYPE_FRAME) choices.append(self.RDK.ActiveStation()) parent = self.RDK.ItemUserPick('Select spawning location', choices) if parent is not None and parent.Valid(): sbt.PARENT = parent self.parent_name_text.set(sbt.PARENT.Name()) def selectConvParent(self): self.RDK.setSelection([]) conv_parent = self.RDK.ItemUserPick('Select conveyor relocation', ITEM_TYPE_FRAME) if conv_parent is not None and conv_parent.Valid(): sbt.CONV_PARENT = conv_parent self.conv_parent_name_text.set(sbt.CONV_PARENT.Name()) def clearConvParent(self): sbt.CONV_PARENT = None self.conv_parent_name_text.set('Unset') def saveAndClose(self): self.setBoxDimensions() # This is not called if user entered manually sbt.setParameters(self.RDK) self.root.destroy() def loadDefaults(self): sbt.loadDefaults() self.init() def show(self): # Generate the main window frame = tk.Frame(self.root) frame.pack(side=tk.TOP, fill=tk.X, padx=1, pady=1) row = -1 # Unit selection row += 1 l_units = tk.Label(frame, text='Units', anchor='w') rb_box_units_mm = tk.Radiobutton(frame, text='mm', variable=self.unit_options, value=1, command=self.switchUnitsFormat) rb_box_units_in = tk.Radiobutton(frame, text='in', variable=self.unit_options, value=0, command=self.switchUnitsFormat) l_units.grid(column=0, row=row, sticky=self.STICKY) rb_box_units_mm.grid(column=1, columnspan=1, row=row, sticky=tk.NW) rb_box_units_in.grid(column=2, columnspan=3, row=row, sticky=tk.NW) # Box length (x) row += 1 l_box_length = tk.Label(frame, textvariable=self.box_length_text, anchor='w') sb_box_length = tk.Spinbox( frame, textvariable=self.box_length, from_=self.SIZE_SPINBOX_FROM, to=self.SIZE_SPINBOX_TO, increment=self.SIZE_SPINBOX_INCREMENT, format=self.SIZE_SPINBOX_FORMAT, command=self.setBoxDimensions, ) l_box_length.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) sb_box_length.grid(column=1, columnspan=3, row=row, sticky=self.STICKY) # Box width (y) row += 1 l_box_width = tk.Label(frame, textvariable=self.box_width_text, anchor='w') sb_box_width = tk.Spinbox( frame, textvariable=self.box_width, from_=self.SIZE_SPINBOX_FROM, to=self.SIZE_SPINBOX_TO, increment=self.SIZE_SPINBOX_INCREMENT, format=self.SIZE_SPINBOX_FORMAT, command=self.setBoxDimensions, ) l_box_width.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) sb_box_width.grid(column=1, columnspan=3, row=row, sticky=self.STICKY) # Box height (z) row += 1 l_box_height = tk.Label(frame, textvariable=self.box_height_text, anchor='w') sb_box_height = tk.Spinbox( frame, textvariable=self.box_height, from_=self.SIZE_SPINBOX_FROM, to=self.SIZE_SPINBOX_TO, increment=self.SIZE_SPINBOX_INCREMENT, format=self.SIZE_SPINBOX_FORMAT, command=self.setBoxDimensions, ) l_box_height.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) sb_box_height.grid(column=1, columnspan=3, row=row, sticky=self.STICKY) # Spawn location row += 1 l_parent = tk.Label(frame, text='Spawn location (Item)', anchor='w') e_parent = tk.Entry(frame, textvariable=self.parent_name_text, state='readonly', width=self.WIDTH_ENTRY) b_parent = tk.Button(frame, text='Select', command=self.selectParent) l_parent.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) e_parent.grid(column=1, columnspan=1, row=row, sticky=self.STICKY) b_parent.grid(column=2, columnspan=2, row=row, sticky=self.STICKY, padx=1, pady=1) # Conveyor remap row += 1 l_conv_parent = tk.Label(frame, text='Conveyor relocation (Item)', anchor='w') e_conv_parent = tk.Entry(frame, textvariable=self.conv_parent_name_text, state='readonly', width=self.WIDTH_ENTRY) b_conv_parent = tk.Button(frame, text='Select', command=self.selectConvParent) b_conv_parent_clr = tk.Button(frame, text='Clear', command=self.clearConvParent) l_conv_parent.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) e_conv_parent.grid(column=1, columnspan=1, row=row, sticky=self.STICKY) b_conv_parent.grid(column=2, columnspan=1, row=row, sticky=self.STICKY, padx=1, pady=1) b_conv_parent_clr.grid(column=3, columnspan=1, row=row, sticky=self.STICKY, padx=1, pady=1) # User controls control_row = tk.Frame(self.root) control_row.pack(side=tk.BOTTOM, padx=1, pady=1) # Creating the OK button b_ok = tk.Button(control_row, text='OK', command=self.saveAndClose, width=12) b_ok.grid(column=0, row=0, sticky=self.STICKY, padx=1, pady=1) # Creating the Cancel button b_cancel = tk.Button(control_row, text='Cancel', command=self.root.destroy, width=12) b_cancel.grid(column=1, row=0, sticky=self.STICKY, padx=1, pady=1) # Creating the Default button b_defaults = tk.Button(control_row, text='Defaults', command=self.loadDefaults, width=12) b_defaults.grid(column=2, row=0, sticky=self.STICKY, padx=1, pady=1) # Set window name window_title = "Box Spawner Editor" self.root.title(window_title) # Logo icon_path = getPathIcon() if os.path.exists(icon_path): self.root.iconbitmap(icon_path) self.root.resizable(0, 0) self.root.mainloop()
def setParameters(RDK=None): if RDK is None: RDK = Robolink() global BOX_SIZE_XYZ global USE_METRIC global PARENT global CONV_PARENT RDK.setParam(PARAM_BOX_X, BOX_SIZE_XYZ[0]) RDK.setParam(PARAM_BOX_Y, BOX_SIZE_XYZ[1]) RDK.setParam(PARAM_BOX_Z, BOX_SIZE_XYZ[2]) RDK.setParam(PARAM_UNITS, USE_METRIC) if PARENT is not None: RDK.setParam(PARAM_PARENT_NAME, PARENT.Name()) else: RDK.setParam(PARAM_PARENT_NAME, '') if CONV_PARENT is not None: RDK.setParam(PARAM_CONV_PARENT_NAME, CONV_PARENT.Name()) else: RDK.setParam(PARAM_CONV_PARENT_NAME, '')
def loadParameters(RDK=None): if RDK is None: RDK = Robolink() global BOX_SIZE_XYZ global USE_METRIC global PARENT global CONV_PARENT size_x = RDK.getParam(PARAM_BOX_X, True) if size_x is not None and size_x != '': BOX_SIZE_XYZ[0] = float(size_x) size_y = RDK.getParam(PARAM_BOX_Y, True) if size_y is not None and size_y != '': BOX_SIZE_XYZ[1] = float(size_y) size_z = RDK.getParam(PARAM_BOX_Z, True) if size_z is not None and size_z != '': BOX_SIZE_XYZ[2] = float(size_z) metric = RDK.getParam(PARAM_UNITS, True) if metric is not None and metric != '': USE_METRIC = bool(metric == 'True') parent_name = RDK.getParam(PARAM_PARENT_NAME, True) if parent_name is not None and parent_name != '': item = RDK.Item(parent_name) if item.Valid() and item.Name() == parent_name: PARENT = item if PARENT is None: PARENT = RDK.ActiveStation() conv_parent_name = RDK.getParam(PARAM_CONV_PARENT_NAME, True) if conv_parent_name is not None and conv_parent_name != '': item = RDK.Item(conv_parent_name) if item.Valid() and item.Name() == conv_parent_name: CONV_PARENT = item
class robodk_api(driver): ''' This driver uses the RoboDK API to connect to a robot controller. It is based on the Robodk API (https://robodk.com/offline-programming). The driver will always provide access to the robot axis through the variable called "Axis" (float[6]). Optional variable definitions are used to access Station Parameters in RobotDK to be read or written by the driver. controller: str Robot name in RoboDK. Default = '', will take the first that founds. ''' def __init__(self, name: str, pipe: Optional[Pipe] = None): """ :param name: (optional) Name for the driver :param pipe: (optional) Pipe used to communicate with the driver thread. See gateway.py """ # Inherit driver.__init__(self, name, pipe) # Parameters self.controller = '' def connect(self) -> bool: """ Connect driver. : returns: True if connection stablished False if not """ try: #assert ROBODK_API_FOUND, "RoboDK API is not available." self._connection = Robolink() if self._connection: self.robot = self._connection.Item(self.controller) if self.robot: if self.robot.Valid() and self.robot.Type() == ITEM_TYPE_ROBOT: self.sendDebugInfo(f'Driver RoboDK Connected to {self.controller}...') return True else: self.sendDebugInfo(f'Item {self.controller} not found!') else: self.sendDebugInfo(f'Controler not found!') else: self.sendDebugInfo(f'Connection with Robolink not possible.') except Exception as e: self.sendDebugInfo('Exception '+str(e)) return False def disconnect(self): """ Disconnect driver. """ pass def addVariables(self, variables: dict): """ Add variables to the driver. Correctly added variables will be added to internal dictionary 'variables'. Any error adding a variable should be communicated to the server using sendDebugInfo() method. : param variables: Variables to add in a dict following the setup format. (See documentation) """ for var_id, var_data in variables.items(): try: if var_id == 'Axis': var_data['value'] = [None for i in range(var_data['size'])] self.variables[var_id] = var_data continue else: value = self._connection.getParam(var_id) if value is not None: var_data['value'] = None # Force first update self.variables[var_id] = var_data self.sendDebugVarInfo((f'SETUP: Variable found {var_id}', var_id)) continue except: pass self.sendDebugVarInfo((f'SETUP: Variable not found {var_id}', var_id)) def readVariables(self, variables: list) -> list: """ Read given variable values. In case that the read is not possible or generates an error BAD quality should be returned. : param variables: List of variable ids to be read. : returns: list of tupples including (var_id, var_value, VariableQuality) """ res = [] for var_id in variables: try: if var_id == 'Axis': new_value = self.robot.Joints().tr().rows[0] # robot joint rotations [Rax_1, Rax_2, Rax_3, Rax_4, Rax_5, Rax_6] new_value = [round(x,3) for x in new_value] res.append((var_id, new_value, VariableQuality.GOOD)) continue else: new_value = self._connection.getParam(var_id) if new_value is not None: new_value = self.getValueFromString(self.variables[var_id]['datatype'], new_value) res.append((var_id, new_value, VariableQuality.GOOD)) continue except: res.append((var_id, self.variables[var_id]['value'], VariableQuality.BAD)) return res def writeVariables(self, variables: list) -> list: """ Write given variable values. In case that the write is not possible or generates an error BAD quality should be returned. : param variables: List of tupples with variable ids and the values to be written (var_id, var_value). : returns: list of tupples including (var_id, var_value, VariableQuality) """ res = [] # TODO: Possible improvement can be to send multiple at once for (var_id, new_value) in variables: try: self._connection.setParam(var_id, new_value) res.append((var_id, new_value, VariableQuality.GOOD)) except: res.append((var_id, new_value, VariableQuality.BAD)) return res
def RecordProgram(): # Define the frames per second: FRAMES_PER_SECOND = 24 # Define the video extension (you may need to change the codec) #VIDEO_EXTENSION = ".avi" VIDEO_EXTENSION = ".mp4" # Choose the codec (mp4v, XVID or DIVX) #FOURCC = cv2.VideoWriter_fourcc(*'DIVX') # good quality (avi) #FOURCC = cv2.VideoWriter_fourcc(*'XVID') # low quality (avi) FOURCC = cv2.VideoWriter_fourcc(*'mp4v') # good quality (mp4) # Default screenshot style: SNAPSHOT_STYLE = "Snapshot" # Other snapshot styles are not recommended, otherwise it will create a delay and a lot of flickering # Instead, change the appearance of RoboDK in the menu Tools-Options-Display #SNAPSHOT_STYLE = "SnapshotWhite" #SNAPSHOT_STYLE = "SnapshotWhiteNoText" #SNAPSHOT_STYLE = "SnapshotNoTextNoFrames" PREFER_SOCKET = True # If available, prefer socket (usually faster) over temporary file to retrieve the image #------------------------------------------------------------------- # Use a temporary folder with tempfile.TemporaryDirectory(prefix='Record_') as td: RDK = Robolink() file_video_temp = os.path.join(td, 'RoboDK_Video' + VIDEO_EXTENSION) video = None frame = None use_socket = PREFER_SOCKET render_time_last = 0 time_per_frame = 1 / FRAMES_PER_SECOND app = RunApplication() while app.Run(): tic() # There's no need to get a new image if no render as occurred. render_time = int(RDK.Command("LastRender")) if (render_time_last != render_time): render_time_last = render_time def getSnapshot(use_socket, tempdir): fallback = False if use_socket: # Socket method. Added in version 5.3.2 try: bytes_img = RDK.Cam2D_Snapshot('', None) # None means station and will throw before version 5.3.2 if isinstance(bytes_img, bytes) and bytes_img != b'': return True, cv2.imdecode(np.frombuffer(bytes_img, np.uint8), cv2.IMREAD_UNCHANGED) except Exception: fallback = True pass # Fallback to tempfile method tf = tempdir + '/temp.png' if RDK.Command(SNAPSHOT_STYLE, tf) == 'OK': return not fallback, cv2.imread(tf) return False, None # Get the station snapshot success, frame = getSnapshot(use_socket, td) if not success: if use_socket: use_socket = False else: RDK.ShowMessage("Problems retrieving the RoboDK image buffer", False) break # Write the frame to the video file if video is None: # Requires at least one frame to extract the frame size. height, width = frame.shape[:2] video = cv2.VideoWriter(file_video_temp, FOURCC, FRAMES_PER_SECOND, (width, height)) video.write(frame) # Wait some time, if necessary, to have accurate frame rate elapsed = toc() if elapsed < time_per_frame: t_sleep = time_per_frame - elapsed print("Waiting for next frame: " + str(t_sleep)) pause(t_sleep) print("Done recording") # Check if nothing was saved if video is None: quit() video.release() # Save the file msg_str = "Saving video recording... " print(msg_str) RDK.ShowMessage(msg_str, False) # Create a suggested file name print("Saving video...") date_str = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") path_rdk = RDK.getParam('PATH_DESKTOP') # or path_rdk = RDK.getParam('PATH_OPENSTATION') file_name = "RoboDK-Video-" + date_str + VIDEO_EXTENSION # Ask the user to provide a file to save file_path = getSaveFileName(path_preference=path_rdk, strfile=file_name, defaultextension=VIDEO_EXTENSION, filetypes=[("Video file", "*" + VIDEO_EXTENSION)]) if not file_path: quit() # Save the file print("Saving video to: " + file_path) if os.path.exists(file_path): print("Deleting existing file: " + file_path) os.remove(file_path) # Move the file os.rename(file_video_temp, file_path) # Done msg_str = "Video recording saved: " + file_path print(msg_str) RDK.ShowMessage(msg_str, False)
# Type help("robolink") or help("robodk") for more information # Press F5 to run the script # Documentation: https://robodk.com/doc/en/RoboDK-API.html # Reference: https://robodk.com/doc/en/PythonAPI/index.html # Note: It is not required to keep a copy of this file, your python script is saved with the station from robolink import Robolink # RoboDK API import ObjectDeleterTools as odt RDK = Robolink() script = RDK.AddFile(odt.LOCAL_PATH + '\ObjectDeleterLoop.py') script.setName('Object Deleter (loop)')
def removeParameters(RDK=None): if RDK is None: RDK = Robolink() RDK.setParam(PARAM_RADIUS, b'') RDK.setParam(PARAM_PARENT_NAME, b'')
# Type help("robolink") or help("robodk") for more information # Press F5 to run the script # Documentation: https://robodk.com/doc/en/RoboDK-API.html # Reference: https://robodk.com/doc/en/PythonAPI/index.html # Note: It is not required to keep a copy of this file, your python script is saved with the station from robolink import Robolink # RoboDK API from robodk import pause import ObjectDeleterTools as odt RDK = Robolink() while True: odt.loadParameters(RDK) objects = odt.objectsInZone(RDK) for obj in objects: obj.Delete() pause(0.1)
# Type help("robolink") or help("robodk") for more information # Press F5 to run the script # Documentation: https://robodk.com/doc/en/RoboDK-API.html # Reference: https://robodk.com/doc/en/PythonAPI/index.html # Note: It is not required to keep a copy of this file, your python script is saved with the station from robolink import Robolink # RoboDK API import SpawnBoxTools as spt RDK = Robolink() script = RDK.AddFile(spt.LOCAL_PATH + '\SpawnBox.py') script.setName('Spawn Box')
class ObjectDeleterEditor: SIZE_SPINBOX_FROM = 0.1 SIZE_SPINBOX_TO = 10000 SIZE_SPINBOX_INCREMENT = 1 SIZE_SPINBOX_FORMAT = "%0.2f" WIDTH_ENTRY = 32 STICKY = tk.NSEW def __init__(self, RDK=None) -> None: self.RDK = RDK if self.RDK is None: self.RDK = Robolink() self.root = tk.Tk() self.radius = tk.DoubleVar(value=0) self.parent_name_text = tk.StringVar( value=odt.PARENT.Name() if odt.PARENT is not None else 'Unset') odt.loadParameters(self.RDK) self.init() def init(self): self.radius.set(odt.RADIUS) self.parent_name_text.set( odt.PARENT.Name() if odt.PARENT is not None else 'Unset') def setRadius(self): odt.RADIUS = self.radius.get() def selectParent(self): self.RDK.setSelection([]) choices = self.RDK.ItemList(ITEM_TYPE_FRAME) choices.append(self.RDK.ActiveStation()) parent = self.RDK.ItemUserPick('Select Deleter location', choices) if parent is not None and parent.Valid(): odt.PARENT = parent self.parent_name_text.set(odt.PARENT.Name()) def saveAndClose(self): self.setRadius() odt.setParameters(self.RDK) self.root.destroy() def loadDefaults(self): odt.loadDefaults() self.init() def show(self): # Generate the main window frame = tk.Frame(self.root) frame.pack(side=tk.TOP, fill=tk.X, padx=1, pady=1) row = -1 # Radius row += 1 l_radius = tk.Label(frame, text='Radius (mm)', anchor='w') sb_radius = tk.Spinbox( frame, textvariable=self.radius, from_=self.SIZE_SPINBOX_FROM, to=self.SIZE_SPINBOX_TO, increment=self.SIZE_SPINBOX_INCREMENT, format=self.SIZE_SPINBOX_FORMAT, command=self.setRadius, ) l_radius.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) sb_radius.grid(column=1, columnspan=3, row=row, sticky=self.STICKY) # Delete location row += 1 l_parent = tk.Label(frame, text='Location (Item)', anchor='w') e_parent = tk.Entry(frame, textvariable=self.parent_name_text, state='readonly', width=self.WIDTH_ENTRY) b_parent = tk.Button(frame, text='Select', command=self.selectParent, padx=1, pady=1) l_parent.grid(column=0, columnspan=1, row=row, sticky=self.STICKY) e_parent.grid(column=1, columnspan=1, row=row, sticky=self.STICKY) b_parent.grid(column=2, columnspan=2, row=row, sticky=self.STICKY, padx=1, pady=1) # User controls control_row = tk.Frame(self.root) control_row.pack(side=tk.BOTTOM, padx=1, pady=1) # Creating the OK button b_ok = tk.Button(control_row, text='OK', command=self.saveAndClose, width=12) b_ok.grid(column=0, row=0, sticky=self.STICKY, padx=1, pady=1) # Creating the Cancel button b_cancel = tk.Button(control_row, text='Cancel', command=self.root.destroy, width=12) b_cancel.grid(column=1, row=0, sticky=self.STICKY, padx=1, pady=1) # Creating the Default button b_defaults = tk.Button(control_row, text='Defaults', command=self.loadDefaults, width=12) b_defaults.grid(column=2, row=0, sticky=self.STICKY, padx=1, pady=1) # Set window name window_title = "Object Deleter Editor" self.root.title(window_title) # Logo icon_path = getPathIcon() if os.path.exists(icon_path): self.root.iconbitmap(icon_path) self.root.resizable(0, 0) self.root.mainloop()