Exemple #1
0
    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
Exemple #2
0
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()
Exemple #3
0
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 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
Exemple #5
0
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
Exemple #6
0
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)