diff options
-rw-r--r-- | LightInstallation.py | 11 | ||||
-rw-r--r-- | TestProfile.py | 36 | ||||
-rw-r--r-- | behaviors/AllPixelsLeft.py | 2 | ||||
-rw-r--r-- | behaviors/BehaviorChain.py | 6 | ||||
-rw-r--r-- | behaviors/DebugBehavior.py | 2 | ||||
-rw-r--r-- | config/Outdoor.xml | 2 | ||||
-rw-r--r-- | docs/designDocs.tex | 9 | ||||
-rw-r--r-- | pixelevents/DecayEvent.py | 3 | ||||
-rw-r--r-- | pixelevents/SingleFrameEvent.py | 8 | ||||
-rw-r--r-- | pixelmappers/SimpleMapper.py | 14 | ||||
-rw-r--r-- | tests/TestComponentRegistry.py | 11 | ||||
-rw-r--r-- | util/ComponentRegistry.py | 47 | ||||
-rw-r--r-- | util/Geo.py | 6 | ||||
-rw-r--r-- | util/PacketComposition.py | 15 |
14 files changed, 112 insertions, 60 deletions
diff --git a/LightInstallation.py b/LightInstallation.py index 6e3c093..aaedcf2 100644 --- a/LightInstallation.py +++ b/LightInstallation.py @@ -101,27 +101,26 @@ class LightInstallation: except Exception as inst: main_log.error('Error importing ' + module+'.'+'.className. Component not\ initialized.') - main_log.error(str(inst)) #TODO: exception logging - continue #TODO: verify functions as expected + main_log.error(str(inst)) + continue args = configGetter.pullArgsFromItem(configItem) args['parentScope'] = self #TODO: we shouldn't give away scope #like this, find another way. try: - components.append(eval(className+'(args)')) #TODO: doesn't error + components.append(eval(className+'(args)')) main_log.debug(className + 'initialized with args ' + str(args)) #right except Exception as inst: main_log.error('Failure while initializing ' + className + ' with ' + str(args)) - main_log.error(str(inst)) #TODO: exception logging + main_log.error(str(inst)) return components def alive(self): return True def mainLoop(self): - #self.screen.allOn() lastLoopTime = clock.time() refreshInterval = 30 - runCount = 2000 + runCount = 200 while runCount > 0: runCount -= 1 loopStart = clock.time() diff --git a/TestProfile.py b/TestProfile.py index 342def6..663e57b 100644 --- a/TestProfile.py +++ b/TestProfile.py @@ -1,8 +1,9 @@ -#import cProfile +import cProfile import struct import random +import math #from LightInstallation import main -numiter = 10000000 +numiter = 1000000 def main1(): for i in xrange(0,numiter): if 'abc' == 'def': @@ -37,14 +38,27 @@ def dictlookup(): lookup[i] = struct.pack('B', random.randint(0,255)) for i in xrange(0,numiter): b = lookup[random.randint(0,255)] -print('starting') -abc1() -print('starting') -abc2() -print('done') -#command = """abc1()""" -#cProfile.runctx(command, globals(), locals()) +def dist1(): + l1 = [21.43, 5423.123] + l2 = [123, 12312345] + for i in xrange(0,numiter): + d = math.sqrt(sum([(l1[i]-l2[i])**2 for i in range(len(l1))])) +def dist2(): + l1 = [21.43, 5423.123] + l2 = [123, 12312345] + for i in xrange(0,numiter): + d = math.sqrt((l1[0]-l2[0])**2+(l1[1]-l2[1])**2) +def exptest(): + for i in xrange(0, numiter): + a = math.exp(-1) + print a +def expapprox(): + for i in xrange(0, numiter): + a = 1+-1+(-1)**2/float(2) + print a +command = """exptest()""" +cProfile.runctx(command, globals(), locals()) -#command = """abc2()""" -#cProfile.runctx(command, globals(), locals()) +command = """expapprox()""" +cProfile.runctx(command, globals(), locals()) diff --git a/behaviors/AllPixelsLeft.py b/behaviors/AllPixelsLeft.py index e1f4080..b48bfc1 100644 --- a/behaviors/AllPixelsLeft.py +++ b/behaviors/AllPixelsLeft.py @@ -5,5 +5,5 @@ class AllPixelsLeft(Behavior): def processResponse(self, sensorInputs, recursiveInputs): for sensory in sensorInputs: xLoc = sensory['Location'][0] - sensory['Location'] = '[{x}<' + str(xLoc) + ']' + sensory['Location'] = '{x}<' + str(xLoc) return (sensorInputs, recursiveInputs) diff --git a/behaviors/BehaviorChain.py b/behaviors/BehaviorChain.py index ce161f9..0170fa8 100644 --- a/behaviors/BehaviorChain.py +++ b/behaviors/BehaviorChain.py @@ -1,6 +1,6 @@ from operationscore.Behavior import * import util.ComponentRegistry as compReg -import logging as main_log +from logger import main_log import pdb class BehaviorChain(Behavior): def behaviorInit(self): @@ -8,6 +8,7 @@ class BehaviorChain(Behavior): self.hooks = self['RecursiveHooks'] if self.hooks == None: self.hooks = {} + def processResponse(self, sensorInputs, recursiveInputs): response = sensorInputs for behaviorId in self['ChainedBehaviors']: @@ -27,6 +28,7 @@ class BehaviorChain(Behavior): []) if hookRecurrence != []: main_log.warn('Hook recurrences are not currently supported. Implement it\ - yourself or bug russell') +yourself or bug russell') self.feedback[behaviorId] = recurrence return response + diff --git a/behaviors/DebugBehavior.py b/behaviors/DebugBehavior.py index 8e9bbdb..eb525e7 100644 --- a/behaviors/DebugBehavior.py +++ b/behaviors/DebugBehavior.py @@ -4,5 +4,5 @@ import pdb class DebugBehavior(Behavior): def processResponse(self, sensorInputs, recursiveInputs): if sensorInputs != []: - main_log.debug('Sensor Inputs: ', str(sensorInputs)) + main_log.debug('Sensor Inputs: '+ str(sensorInputs)) return [] diff --git a/config/Outdoor.xml b/config/Outdoor.xml index c2a2c3c..f0995b1 100644 --- a/config/Outdoor.xml +++ b/config/Outdoor.xml @@ -133,7 +133,7 @@ <Id>pixelsleft</Id> <Id>decay</Id> </ChainedBehaviors> - <RenderToScreen>False</RenderToScreen> + <RenderToScreen>True</RenderToScreen> </Args> </Behavior> <Behavior Id="running"> diff --git a/docs/designDocs.tex b/docs/designDocs.tex index 0690d3f..9b47d7d 100644 --- a/docs/designDocs.tex +++ b/docs/designDocs.tex @@ -162,10 +162,10 @@ argument. This will be passed in via recursive inputs.} \item Constants: \texttt{ALL\_CAPS\_WITH\_UNDERSCORES} \end{itemize} \subsection{Time} - For time, use the \texttt{Util.time()} method to return the current + For time, use the \texttt{util.TimeOps.time()} method to return the current time in ms. \subsection{Acessing a Component Given an Id} - Use \texttt{Util.getComponentById(id)}. This provides any + Use \texttt{util.ComponentRegistry.getComponent(id)}. This provides any component access to any other components. We may consider a way to make this read-only. \subsection{Acessing Pixels} @@ -174,7 +174,7 @@ argument. This will be passed in via recursive inputs.} acceptable method. \subsection{Determining the state of a \texttt{Pixel}} The best practice for determining the color of a \texttt{Pixel} is to call - \texttt{lightState} (may be renamed to State TODO). This ensures + \texttt{state}. This ensures all current active responses running on the Pixel contribute correctly. \subsection{Color} For color, use a tuple of (R,G,B) 0-255 for each. Colors can be @@ -182,4 +182,7 @@ argument. This will be passed in via recursive inputs.} \subsection{Locations} Locations are stored (x,y), in whatever unit you light system is in. (Whatever unit you use when you define spacing). + \subsection{Constant Strings (key strings, 'Location', 'Color', etc.)} + Use the util.Strings module. It contains many currently in use + Strings, and ensures consistency. \end{document} diff --git a/pixelevents/DecayEvent.py b/pixelevents/DecayEvent.py index c1166d6..3767729 100644 --- a/pixelevents/DecayEvent.py +++ b/pixelevents/DecayEvent.py @@ -1,6 +1,7 @@ from operationscore.PixelEvent import * import math from util.ColorOps import * +import util.Geo as Geo class DecayEvent(PixelEvent): def initEvent(self): self.coefficient = float(abs(self['Coefficient'])) @@ -13,7 +14,7 @@ class DecayEvent(PixelEvent): #SUBVERTING DESIGN FOR THE SAKE OF EFFICIENCY -- RUSSELL COHEN (2011-01-03-23:18) def state(self,timeDelay): if self.decayType == 1: - decay = math.exp(timeDelay*-1*self.coefficient) + decay = Geo.approxexp(timeDelay*-1*self.coefficient) if self.decayType == 2: decay = self.coefficient / timeDelay color = multiplyColor(self.color, decay) diff --git a/pixelevents/SingleFrameEvent.py b/pixelevents/SingleFrameEvent.py new file mode 100644 index 0000000..1c6239f --- /dev/null +++ b/pixelevents/SingleFrameEvent.py @@ -0,0 +1,8 @@ +from operationscore.PixelEvent import * +class SingleFrameEvent(PixelEvent): + def initEvent(self): + self.rendered = False + def state(self): + if !self.rendered: + return self['Color'] + return None diff --git a/pixelmappers/SimpleMapper.py b/pixelmappers/SimpleMapper.py index 4d12fe4..2df24e0 100644 --- a/pixelmappers/SimpleMapper.py +++ b/pixelmappers/SimpleMapper.py @@ -14,17 +14,21 @@ class SimpleMapper(PixelMapper): bestPixel = pixel bestDist = pixelDist return [(bestPixel,1)] - elif type(type(str)): - #[{x}>5,{y}<k] + else: + #{x}>5,{y}<k #TODO: we should probably encapsulate this somewhere ret = [] eventLocation = eventLocation.replace('{x}', 'pixel.location[0]') eventLocation = eventLocation.replace('{y}', 'pixel.location[1]') + conditions = eventLocation.split(',') + conditionLambdas = [eval('lambda pixel:'+condition) for condition in conditions] for pixel in screen: try: - preValid = eval(eventLocation) - pixelValid = sum(preValid) == len(preValid) #TODO: some - #optimizations possible. This might be slow in the long run + pixelValid = True + for p in conditionLambdas: + if p(pixel) == False: + pixelValid = False + continue if pixelValid: ret.append((pixel, 1)) except Exception as exp: diff --git a/tests/TestComponentRegistry.py b/tests/TestComponentRegistry.py new file mode 100644 index 0000000..1acd0c8 --- /dev/null +++ b/tests/TestComponentRegistry.py @@ -0,0 +1,11 @@ +import unittest +import util.ComponentRegistry as compReg +class TestComponentRegistry(unittest.TestCase): + def setUp(self): + compReg.initRegistry() + def tearDown(self): + compReg.clearRegistry() + def test_register_component(self): + comp = SmootCoreObject({'Id': obj1}) + compReg.registerComponent(comp) + diff --git a/util/ComponentRegistry.py b/util/ComponentRegistry.py index 119ce18..0518f56 100644 --- a/util/ComponentRegistry.py +++ b/util/ComponentRegistry.py @@ -1,43 +1,40 @@ import pdb -#component registry, a singleton -import thread -#class ComponentRegistry: -# def __init__(self): -# self.regDict = {} -# @staticmethod -# def getRegistry(self): -# if self.instance == None: -# self.instance = self.__class__() -# return self.instance -# def registerComponent(component, cid=None): -# if cid != None: -# globals()['Registry'][cid] = component -# else: -# try: -# cid = component['Id'] -# globals()['Registry'][cid] = component -# except: -# raise Exception('Must specify Id, component did not store it') -#def registerDefault( +import hashlib +from logger import main_log +#TODO: make component registry a singleton +def initRegistry(): + #TODO: don't overwrite existing registry + globals()['Registry'] = {} + +def clearRegistry(): + initRegistry() def removeComponent(cid): globals()['Registry'].pop(cid) def getComponent(cid): return globals()['Registry'][cid] #Registry of all components of the light system #TODO: pick a graceful failure behavior and implement it -def initRegistry(): - globals()['Registry'] = {} def registerComponent(component, cid=None): if cid != None: globals()['Registry'][cid] = component else: try: cid = component['Id'] - globals()['Registry'][cid] = component - except: - raise Exception('Must specify Id, component did not store it') + except KeyError: + cid = getNewId() + component['Id'] = cid + main_log.debug(cid + 'automatically assigned') + globals()['Registry'][cid] = component + return cid #def registerDefault( def removeComponent(cid): globals()['Registry'].pop(cid) def getComponent(cid): return globals()['Registry'][cid] +def getNewId(): + trialKey = len(globals()['Registry']) + trialId = hashlib.md5(str(trialKey)).hexdigest() + while trialId in globals()['Registry']: + trialKey += 1 + trialId = hashlib.md5(str(trialKey)).hexdigest() + return trialId diff --git a/util/Geo.py b/util/Geo.py index a9243de..be3e93e 100644 --- a/util/Geo.py +++ b/util/Geo.py @@ -4,7 +4,6 @@ from bisect import * import random def pointWithinBoundingBox(point, bb): #this could be in 4 lines, but I'm lazy. return sum([(point[i % 2] <= bb[i]) == (i>1) for i in range(4)]) == 4 -print pointWithinBoundingBox((118,21), (10,8,298,42)) def addLocations(l1,l2): return tuple([l1[i]+l2[i] for i in range(len(l1))]) def gaussian(x,height,center,width): @@ -13,9 +12,12 @@ def gaussian(x,height,center,width): c=width return a*math.exp(-((x-b)**2)/(2*c**2)) def dist(l1, l2): - return math.sqrt(sum([(l1[i]-l2[i])**2 for i in range(len(l1))])) + return math.sqrt((l1[0]-l2[0])**2+(l1[1]-l2[1])**2) + #return math.sqrt(sum([(l1[i]-l2[i])**2 for i in range(len(l1))])) def randomLoc(boundingBox): #TODO: make less shitty loc = [] loc.append(random.randint(0, boundingBox[0])) loc.append(random.randint(0, boundingBox[1])) return tuple(loc) +def approxexp(x): + return 1+x+x**2/2+x**3/6 diff --git a/util/PacketComposition.py b/util/PacketComposition.py index b323d54..3574170 100644 --- a/util/PacketComposition.py +++ b/util/PacketComposition.py @@ -22,14 +22,25 @@ def composePixelStripData(pixelStrip,currentTime=timeops.time()): #color = pixelStrip.pixels[i].state() #packet[i:i+2] = color # return bytearray(packet) -def composePixelStripPacket(pixelStrip,port, currentTime): +cache = {} +def memoize(f): + def helper(x): + if x not in cache: + cache[x] = f(x) + return cache[x] + return helper +@memoize +def cachePacketHeader(port): packet = bytearray() - data = composePixelStripData(pixelStrip, currentTime) subDict = dict(kinetDict) subDict['len'] = 38000 #I have no idea why this works. subDict['port'] = port packet.extend(kinetPortOutPacket(subDict)) packet.append(0x0) + return packet +def composePixelStripPacket(pixelStrip,port, currentTime): + packet = bytearray(cachePacketHeader(port)) + data = composePixelStripData(pixelStrip, currentTime) packet.extend(data) return packet def kinetHeader(): |