Diff of /URBasic/dataLog.py [000000] .. [c1b1c5]

Switch to unified view

a b/URBasic/dataLog.py
1
'''
2
Python 3.x library to control an UR robot through its TCP/IP interfaces
3
Copyright (C) 2017  Martin Huus Bjerge, Rope Robotics ApS, Denmark
4
5
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6
and associated documentation files (the "Software"), to deal in the Software without restriction,
7
including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
9
is furnished to do so, subject to the following conditions:
10
11
The above copyright notice and this permission notice shall be included in all copies
12
or substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL "Rope Robotics ApS" BE LIABLE FOR ANY CLAIM,
17
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20
Except as contained in this notice, the name of "Rope Robotics ApS" shall not be used
21
in advertising or otherwise to promote the sale, use or other dealings in this Software
22
without prior written authorization from "Rope Robotics ApS".
23
'''
24
__author__ = "Martin Huus Bjerge"
25
__copyright__ = "Copyright 2017, Rope Robotics ApS, Denmark"
26
__license__ = "MIT License"
27
28
import threading
29
import URBasic
30
import numpy as np
31
import time
32
import xml.etree.ElementTree as ET
33
from pkg_resources import resource_filename
34
35
class DataLog(threading.Thread):
36
    '''
37
    This module handle logging of all data signal from the robot (not event logging).
38
    '''
39
    def __init__(self, robotModel):
40
41
        if(False):
42
            assert isinstance(robotModel, URBasic.robotModel.RobotModel)  ### This line is to get code completion for RobotModel
43
        self.__robotModel = robotModel
44
        threading.Thread.__init__(self)
45
        logger = URBasic.dataLogging.DataLogging()
46
        name = logger.AddDataLogging(__name__)
47
        self.__dataLogger = logger.__dict__[name]
48
        name = logger.AddEventLogging(__name__,log2Consol=False)
49
        self.__logger = logger.__dict__[name]
50
        self.__stop_event = True
51
52
53
        configFilename = resource_filename(__name__, 'logConfig.xml')
54
        self.__config = Config
55
        self.__readConfig(configFileName=configFilename, config=self.__config)
56
57
        self.__robotModelDataDirCopy = None
58
        self.start()
59
        self.__logger.info('DataLog constructor done')
60
61
62
    def __readConfig(self, configFileName, config):
63
        tree = ET.parse(configFileName)
64
        logConfig = tree.getroot()
65
        dataLogConfig = logConfig.find('dataLogConfig')
66
        decimals = dataLogConfig.find('defaultDecimals')
67
        config.Decimals = int(decimals.text)
68
        logParameters = dataLogConfig.find('logParameters')
69
        for Child in logParameters:
70
            setattr(config, Child.tag, Child.text)
71
72
73
74
    def logdata(self, robotModelDataDir):
75
        if(self.__robotModelDataDirCopy != None):
76
            if(self.__robotModelDataDirCopy['timestamp'] != robotModelDataDir['timestamp'] or robotModelDataDir['timestamp'] is None):
77
                for tagname in robotModelDataDir.keys():
78
                    if tagname != 'timestamp' and  robotModelDataDir[tagname] is not None:
79
                        roundingDecimals = self.__config.Decimals
80
                        tp = type(robotModelDataDir[tagname])
81
                        if tp is np.ndarray:
82
                            if tagname in self.__config.__dict__:
83
                                roundingDecimals = int(self.__config.__dict__[tagname])
84
                            roundedValues = np.round(robotModelDataDir[tagname], roundingDecimals)
85
                            if self.__robotModelDataDirCopy[tagname] is None:
86
                                roundedValuesCopy = roundedValues+1
87
                            else:
88
                                roundedValuesCopy = np.round(self.__robotModelDataDirCopy[tagname], roundingDecimals)
89
                            if not (roundedValues==roundedValuesCopy).all():
90
                                if 6==len(robotModelDataDir[tagname]):
91
                                    self.__dataLogger.info((tagname+';%s;%s;%s;%s;%s;%s;%s'), robotModelDataDir['timestamp'], *roundedValues)
92
                                elif 3==len(robotModelDataDir[tagname]):
93
                                    self.__dataLogger.info((tagname+';%s;%s;%s;%s'), robotModelDataDir['timestamp'], *roundedValues)
94
                                else:
95
                                    self.__logger.warning('Logger data unexpected type in rtde.py - class URRTDElogger - def logdata Type: ' + str(tp) + ' - Len: ' + str(len(robotModelDataDir[tagname])))
96
                        elif tp is float:
97
                            if tagname in self.__config.__dict__:
98
                                roundingDecimals = int(self.__config.__dict__[tagname])
99
                            roundedValues = round(robotModelDataDir[tagname], roundingDecimals)
100
                            if self.__robotModelDataDirCopy[tagname] is None:
101
                                roundedValuesCopy = roundedValues+1
102
                            else:
103
                                roundedValuesCopy = round(self.__robotModelDataDirCopy[tagname], roundingDecimals)
104
                            if roundedValues != roundedValuesCopy:
105
                                self.__dataLogger.info((tagname+';%s;%s'), robotModelDataDir['timestamp'], roundedValues)
106
                        elif tp is bool or tp is int or tp is np.float64:
107
                            if robotModelDataDir[tagname] != self.__robotModelDataDirCopy[tagname]:
108
                                self.__dataLogger.info((tagname+';%s;%s'), robotModelDataDir['timestamp'], robotModelDataDir[tagname])
109
                        else:
110
                            self.__logger.warning('Logger data unexpected type in rtde.py - class URRTDElogger - def logdata Type: ' + str(tp))
111
        self.__robotModelDataDirCopy = robotModelDataDir
112
113
114
    def close(self):
115
        if self.__stop_event is False:
116
            self.__stop_event = True
117
            self.join()
118
119
    def run(self):
120
        self.__stop_event = False
121
        while not self.__stop_event:
122
            try:
123
                dataDirCopy = self.__robotModel.dataDir.copy()
124
                self.logdata(dataDirCopy)
125
                time.sleep(0.005)
126
            except:
127
                self.__robotModelDataDirCopy = dataDirCopy
128
                self.__logger.warning("DataLog error while running, but will retry")
129
        self.__logger.info("DataLog is stopped")
130
131
class Config(object):
132
    Decimals = 5