Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

import time 

import pprint 

import uuid 

import json 

from collections import OrderedDict 

from director.thirdparty import numpyjsoncoder 

from director import callbacks 

from director.utime import getUtime 

from director.uuidutil import newUUID 

 

try: 

    import bot_core as lcmbotcore 

    USE_LCM = True 

except ImportError: 

    USE_LCM = False 

 

if USE_LCM: 

    from director import lcmUtils 

 

 

class LCMObjectCollection(object): 

 

    DESCRIPTION_UPDATED_SIGNAL = 'DESCRIPTION_UPDATED_SIGNAL' 

    DESCRIPTION_REMOVED_SIGNAL = 'DESCRIPTION_REMOVED_SIGNAL' 

 

    def __init__(self, channel): 

        self.collection = OrderedDict() 

        self.collectionId = newUUID() 

        self.sentCommands = set() 

        self.sentRequest = None 

        self.channel = channel 

        self.callbacks = callbacks.CallbackRegistry([self.DESCRIPTION_UPDATED_SIGNAL, 

                                                     self.DESCRIPTION_REMOVED_SIGNAL]) 

        self.sub = None 

        self._modified() 

 

        if USE_LCM: 

            self.sub = lcmUtils.addSubscriber(self.channel, messageClass=lcmbotcore.system_status_t, callback=self._onCommandMessage) 

            self.sub.setNotifyAllMessagesEnabled(True) 

 

    def __del__(self): 

        if self.sub: 

            lcmUtils.removeSubscriber(self.sub) 

 

    def connectDescriptionUpdated(self, func): 

        return self.callbacks.connect(self.DESCRIPTION_UPDATED_SIGNAL, func) 

 

    def disconnectDescriptionUpdated(self, callbackId): 

        self.callbacks.disconnect(callbackId) 

 

    def connectDescriptionRemoved(self, func): 

        return self.callbacks.connect(self.DESCRIPTION_REMOVED_SIGNAL, func) 

 

    def disconnectDescriptionRemoved(self, callbackId): 

        self.callbacks.disconnect(callbackId) 

 

    def getDescriptionId(self, desc): 

        return desc['uuid'] 

 

    def prettyPrintCollection(self): 

        print json.dumps(json.loads(numpyjsoncoder.encode(self.collection)), indent=2) 

 

    def getDescription(self, descriptionId): 

        return self.collection[descriptionId] 

 

    def updateDescription(self, desc, publish=True, notify=True): 

        self.collection[self.getDescriptionId(desc)] = desc 

        self._modified() 

        if publish and USE_LCM: 

            msg = self._newCommandMessage('update', description=desc) 

            lcmUtils.publish(self.channel, msg) 

 

        if notify: 

            self.callbacks.process(self.DESCRIPTION_UPDATED_SIGNAL, self, self.getDescriptionId(desc)) 

 

    def removeDescription(self, descriptionId, publish=True, notify=True): 

 

        try: 

            del self.collection[descriptionId] 

            self._modified() 

        except KeyError: 

            pass 

 

        if publish and USE_LCM: 

            msg = self._newCommandMessage('remove', descriptionId=descriptionId,) 

            lcmUtils.publish(self.channel, msg) 

 

        if notify: 

            self.callbacks.process(self.DESCRIPTION_REMOVED_SIGNAL, self, descriptionId) 

 

    def sendEchoRequest(self): 

        self.sentRequest = newUUID() 

        msg = self._newCommandMessage('echo_request', requestId=self.sentRequest) 

        lcmUtils.publish(self.channel, msg) 

 

 

    def sendEchoResponse(self, requestId=None): 

        if requestId is None: 

            requestId = newUUID() 

        msg = self._newCommandMessage('echo_response', requestId=requestId, descriptions=self.collection) 

        lcmUtils.publish(self.channel, msg) 

 

    def handleEchoResponse(self, data): 

        #if data['requestId'] != self.sentRequest: 

        #    return 

 

        self.sentRequest = None 

        for desc in data['descriptions'].values(): 

            self.updateDescription(desc, publish=False) 

 

    def _modified(self): 

        self.mtime = getUtime() 

 

    def _newCommandMessage(self, commandName, **commandArgs): 

        commandId = newUUID() 

        self.sentCommands.add(commandId) 

        commandArgs['commandId'] = commandId 

        commandArgs['collectionId'] = self.collectionId 

        commandArgs['command'] = commandName 

        msg = lcmbotcore.system_status_t() 

        msg.value = numpyjsoncoder.encode(commandArgs) 

        msg.utime = getUtime() 

        return msg 

 

    def _onCommandMessage(self, msg): 

 

        data = numpyjsoncoder.decode(msg.value) 

 

        commandId = data['commandId'] 

        if commandId in self.sentCommands: 

            self.sentCommands.remove(commandId) 

            return 

 

        command = data['command'] 

 

        if command == 'update': 

            desc = data['description'] 

            self.updateDescription(desc, publish=False) 

 

        elif command == 'remove': 

            self.removeDescription(data['descriptionId'], publish=False) 

 

        elif command == 'echo_request': 

            self.sendEchoResponse(data['requestId']) 

 

        elif command == 'echo_response': 

            self.handleEchoResponse(data)