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

from director import objectmodel as om 

from director import affordanceitems 

from director import lcmobjectcollection 

from director import visualization as vis 

from director.timercallback import TimerCallback 

from director.uuidutil import newUUID 

from director import vtkAll as vtk 

from director.thirdparty import numpyjsoncoder 

import traceback 

 

class AffordanceObjectModelManager(object): 

 

    def __init__(self, view): 

        self.collection = lcmobjectcollection.LCMObjectCollection(channel='AFFORDANCE_COLLECTION_COMMAND') 

        self.collection.connectDescriptionUpdated(self._onDescriptionUpdated) 

        self.collection.connectDescriptionRemoved(self._onDescriptionRemoved) 

        self.view = view 

        self.notifyFrequency = 30 # throttle lcm messages per second sent for affordance updates 

        self._ignoreChanges = False 

 

        self._pendingUpdates = set() 

        self.timer = TimerCallback() 

        self.timer.callback = self._notifyPendingUpdates 

 

        self.affordanceUpdater = None 

 

    def setAffordanceUpdater(self, affordanceUpdater): 

        self.affordanceUpdater = affordanceUpdater 

 

    def getAffordances(self): 

        return [obj for obj in om.getObjects() if isinstance(obj, affordanceitems.AffordanceItem)] 

 

 

    def getCollisionAffordances(self): 

        affs = [] 

        for aff in self.getAffordances(): 

            if aff.getProperty('Collision Enabled'): 

                affs.append(aff) 

        return affs 

 

    def getAffordanceId(self, aff): 

        return aff.getProperty('uuid') 

 

    def newAffordanceFromDescription(self, desc): 

        if 'uuid' not in desc: 

            desc['uuid'] = newUUID() 

        self.collection.updateDescription(desc) 

        return self.getAffordanceById(desc['uuid']) 

 

    def getAffordanceById(self, affordanceId): 

        for aff in self.getAffordances(): 

            if self.getAffordanceId(aff) == affordanceId: 

                return aff 

 

    def getAffordanceDescription(self, aff): 

        return aff.getDescription() 

 

    def registerAffordance(self, aff, notify=True): 

        aff.connectRemovedFromObjectModel(self._onAffordanceRemovedFromObjectModel) 

        aff.properties.connectPropertyChanged(self._onAffordancePropertyChanged) 

        aff.getChildFrame().connectFrameModified(self._onAffordanceFrameChanged) 

        if notify: 

            self.notifyAffordanceUpdate(aff) 

 

    def removeAffordance(self, aff): 

        self.collection.removeDescription(aff.getProperty('uuid'), notify=False) 

 

    def notifyAffordanceUpdate(self, aff): 

 

        if not isinstance(aff, affordanceitems.AffordanceItem): 

            return 

 

        shouldNotify = not self._pendingUpdates and not self.timer.singleShotTimer.isActive() 

        self._pendingUpdates.add(aff) 

        if shouldNotify: 

            self._notifyPendingUpdates() 

 

    def _notifyPendingUpdates(self): 

 

        if self._pendingUpdates: 

            self.timer.singleShot(1.0/self.notifyFrequency) 

 

        for aff in self._pendingUpdates: 

            try: 

                self.collection.updateDescription(self.getAffordanceDescription(aff), notify=False) 

            except: 

                print traceback.format_exc() 

 

        self._pendingUpdates.clear() 

 

    def _onAffordancePropertyChanged(self, propertySet, propertyName): 

        if self._ignoreChanges: 

            return 

        self.notifyAffordanceUpdate(self.getAffordanceById(propertySet.getProperty('uuid'))) 

 

    def _onAffordanceFrameChanged(self, frameObj): 

        if self._ignoreChanges: 

            return 

        aff = frameObj.parent() 

        self.notifyAffordanceUpdate(aff) 

 

    def _onAffordanceRemovedFromObjectModel(self, objectModel, aff): 

        if self._ignoreChanges: 

            return 

        self.removeAffordance(aff) 

 

    def _loadAffordanceFromDescription(self, desc): 

        className = desc['classname'] 

        cls = getattr(affordanceitems, className) 

        aff = cls(desc['Name'], self.view) 

        om.addToObjectModel(aff, parentObj=om.getOrCreateContainer('affordances')) 

        frame = vis.addChildFrame(aff) 

        frame.setProperty('Deletable', False) 

        aff.loadDescription(desc, copyMode=aff.COPY_MODE_ALL) 

        self.registerAffordance(aff, notify=False) 

 

    def _onDescriptionUpdated(self, collection, descriptionId): 

        aff = self.getAffordanceById(descriptionId) 

        desc = collection.getDescription(descriptionId) 

 

        if aff: 

            self._ignoreChanges = True 

            aff.loadDescription(desc, copyMode=aff.COPY_MODE_SKIP_LOCAL) 

            self._ignoreChanges = False 

 

        else: 

            aff = self._loadAffordanceFromDescription(desc) 

 

    def _onDescriptionRemoved(self, collection, descriptionId): 

        self._ignoreChanges = True 

        om.removeFromObjectModel(self.getAffordanceById(descriptionId)) 

        self._ignoreChanges = False