aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar rcoh <rcoh@mit.edu>2010-12-15 00:18:24 -0500
committerGravatar rcoh <rcoh@mit.edu>2010-12-15 00:18:24 -0500
commita89c772cd64c6790906734f7128947e0f453c7e3 (patch)
tree250e0b0d235e1215fa7b40fcfd24b74028ccf643
parent8cecf83f16fcdec5b3ee68cc40c2b360e0f845d0 (diff)
About halfway done with the Util cleanup. Some stuff left to do with scoping etc.
-rw-r--r--.gitignore2
-rw-r--r--LightInstallation.py14
-rw-r--r--Util.py140
-rw-r--r--behaviors/ColorChangerBehavior.py7
-rw-r--r--operationscore/PixelEvent.py3
-rw-r--r--operationscore/SmootCoreObject.py3
-rw-r--r--pixelcore/Pixel.py9
-rw-r--r--pixelevents/DecayEvent.py5
-rw-r--r--renderers/IndoorRenderer.py16
-rw-r--r--util/ColorOps.py11
-rw-r--r--util/Config.py53
-rw-r--r--util/NetworkOps.py6
-rw-r--r--util/PacketComposition.py59
-rw-r--r--util/TimeOps.py19
-rw-r--r--util/__init__.py0
15 files changed, 181 insertions, 166 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c9b568f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+*.swp
diff --git a/LightInstallation.py b/LightInstallation.py
index e4adab7..5f12abf 100644
--- a/LightInstallation.py
+++ b/LightInstallation.py
@@ -3,11 +3,13 @@ from pixelcore.Screen import *
from pixelcore.PixelStrip import *
import pdb, sys, time, Util, thread
from pygame.locals import *
+import util.TimeOps as clock
+import util.Config as configGetter
#Python class to instantiate and drive a Screen through different patterns,
#and effects.
class LightInstallation:
def __init__(self, configFileName):
- self.timer = Util.Stopwatch()
+ self.timer = clock.Stopwatch()
self.timer.start()
self.inputs = {} #dict of inputs and their bound behaviors, keyed by InputId
self.behaviors = {}
@@ -22,7 +24,7 @@ class LightInstallation:
Util.setComponentDict(self.componentDict)
self.screen = Screen()
Util.setScreen(self.screen)
- config = Util.loadConfigFile(configFileName)
+ config = configGetter.loadConfigFile(configFileName)
#read configs from xml
rendererConfig = config.find('RendererConfiguration')
pixelConfig = config.find('PixelConfiguration')
@@ -75,7 +77,7 @@ class LightInstallation:
for configItem in config.getchildren():
[module,className] = configItem.find('Class').text.split('.')
exec('from ' + module+'.'+className + ' import *')
- args = Util.generateArgDict(configItem.find('Args'))
+ args = configGetter.generateArgDict(configItem.find('Args'))
args['parentScope'] = self #TODO: we shouldn't give away scope
#like this, find another way.
components.append(eval(className+'(args)')) #TODO: doesn't error
@@ -85,12 +87,12 @@ class LightInstallation:
return True
def mainLoop(self):
#self.screen.allOn()
- lastLoopTime = Util.time()
+ lastLoopTime = clock.time()
refreshInterval = 30
runCount = 10000
while runCount > 0:
runCount -= 1
- loopStart = Util.time()
+ loopStart = clock.time()
responses = self.evaluateBehaviors() #inputs are all queued when they
#happen, so we only need to run the behaviors
self.timer.start()
@@ -98,7 +100,7 @@ class LightInstallation:
response != []]
self.screen.timeStep()
[r.render(self.screen) for r in self.renderers]
- loopElapsed = Util.time()-loopStart
+ loopElapsed = clock.time()-loopStart
sleepTime = max(0,refreshInterval-loopElapsed)
self.timer.stop()
#print self.timer.elapsed()
diff --git a/Util.py b/Util.py
index 07ce545..2973e33 100644
--- a/Util.py
+++ b/Util.py
@@ -6,15 +6,8 @@ from bisect import *
import socket
import random
from pygame.locals import *
-import time as clock
from pixelevents.StepEvent import *
-VERSION = 0x0001
-MAGIC = 0x4adc0104
-MOREMAGIC = 0xdeadbeef
-DEEPMAGIC = 0xc001d00d
-MAGICHASH = 0x69000420
-PORTOUT = 0x0108
classArgsMem = {}
UNI = 0
colorByteMem = {}
@@ -52,39 +45,6 @@ def gaussian(x,height,center,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))]))
-def time():
- return clock.time()*1000
-def randomColor():
- return [random.randint(0,255) for i in range(3)]
-def chooseRandomColor(colorList):
- return random.choice(colorList)
-def loadParamRequirementDict(className):
- if not className in classArgsMem: #WOO CACHING
- classArgsMem[className] = fileToDict(CONFIG_PATH + className)
- return classArgsMem[className]
-def loadConfigFile(fileName):
- try:
- fileName = CONFIG_PATH + fileName
- if '.params' in fileName:
- return fileToDict(fileName)
- if '.xml' in fileName:
- config = ElementTree()
- config.parse(fileName)
- return config
- except:
- return None
-def fileToDict(fileName):
- fileText = ''
- try:
- print 'File Read'
- with open(fileName) as f:
- for line in f:
- fileText += line.rstrip('\n').lstrip('\t') + ' '
- except IOError:
- return {}
- if fileText == '':
- return {}
- return eval(fileText)
def find_le(a, x):
'Find rightmost value less than or equal to x'
return bisect_right(a, x)-1
@@ -92,35 +52,6 @@ def find_le(a, x):
def find_ge(a, x):
'Find leftmost value greater than x'
return bisect_left(a, x)
-def safeColor(c):
- return [min(channel,255) for channel in c]
-def combineColors(c1,c2):
- return safeColor([c1[i]+c2[i] for i in range(min(len(c1),len(c2)))])
-def multiplyColor(color, percent):
- return safeColor([channel*(percent) for channel in color])
-#parses arguments into python objects if possible, otherwise leaves as strings
-def generateArgDict(parentNode, recurse=False):
- args = {}
- for arg in parentNode.getchildren():
- key = arg.tag
- if arg.getchildren() != []:
- value = generateArgDict(arg, True)
- else:
- #convert into python if possible, otherwise don't
- try:
- value = eval(arg.text)
- except (NameError,SyntaxError):
- value = str(arg.text)
- if key in args: #build of lists of like-elements
- if type(args[key]) != type([]):
- args[key] = [args[key]]
- args[key].append(value)
- else:
- args[key]=value
- #if we should be a list but we aren't:
- if len(args.keys()) == 1 and recurse:
- return args[args.keys()[0]]
- return args
#Given a dictionary of connections, returns their topological ordering -- (the
#order in which they can be visited such that all parents have been visited
#before their children. Returns the order or None if no such ordering exists
@@ -149,83 +80,12 @@ def topologicalSort(adjacencyDict):
def topoTest():
adj = {'a':['d','c'], 'b':['c'], 'c':['e'], 'd':['e'], 'e':[]}
print topologicalOrdering(adj)
-def getConnectedSocket(ip,port):
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- print (ip, port)
- sock.connect((ip, port))
- return sock
-def composePixelStripData(pixelStrip):
- packet = bytearray()
- for light in pixelStrip:
- color = light.state()
- for channel in color: #skip the last value, its an
- #alpha value
- packet.append(struct.pack('B', channel))
- return packet
-# packet = [0]*len(pixelStrip.pixels)*3 #preallocate for speed
-# for i in range(len(pixelStrip.pixels)):
-#color = pixelStrip.pixels[i].state()
-#packet[i:i+2] = color
-# return bytearray(packet)
-def composePixelStripPacket(pixelStrip,port):
- packet = bytearray()
- data = composePixelStripData(pixelStrip)
- subDict = dict(kinetDict)
- subDict['len'] = 38000 #I have no idea why this works.
- subDict['port'] = port
- #pdb.set_trace()
- packet.extend(kinetPortOutPacket(subDict))
- packet.append(0x0)
- packet.extend(data)
- return packet
-def kinetHeader():
- header = bytearray()
- header.extend(struct.pack('L', MAGIC))
- header.extend(struct.pack('H', VERSION))
- header.extend(struct.pack('H', PORTOUT))
- header.extend(struct.pack('L', 0))
- return header
-def kinetPortOut():
- header = kinetHeader()
- header.extend(struct.pack('L', UNI))
- return header
-def kinetPortOutPayload(argDict):
- payload = bytearray()
- payload.extend(struct.pack('B', argDict['port']))
- #payload.append(0x00) #somepadding? lolwtf.
- payload.extend(struct.pack('H', argDict['flags']))
- #payload.append(0x00) #somepadding? lolwtf.
- payload.extend(struct.pack('H', argDict['len']))
- payload.extend(struct.pack('H', argDict['startcode']))
- #pdb.set_trace()
- return payload
-def kinetPortOutPacket(payloadArgs):
- packet = bytearray()
- packet.extend(kinetPortOut())
- packet.extend(kinetPortOutPayload(payloadArgs))
- return packet
def testXMLParse(fileName):
#pdb.set_trace()
config = ElementTree()
config.parse(fileName)
print generateArgDict(config.find('ChildElement'))
print generateArgDict(config.find('Renderer'))
-class Stopwatch:
- def __init__(self):
- self.running = False
- self.startTime = -1
- self.stopTime = -1
- def start(self):
- self.startTime = Util.time()
- self.running = True
- def elapsed(self):
- if self.running:
- return Util.time()-self.startTime
- else:
- return self.stopTime - self.startTime
- def stop(self):
- self.stopTime = Util.time()
- self.running = False
##CONSTANTS##
location = 'Location'
diff --git a/behaviors/ColorChangerBehavior.py b/behaviors/ColorChangerBehavior.py
index a3b1739..e1827eb 100644
--- a/behaviors/ColorChangerBehavior.py
+++ b/behaviors/ColorChangerBehavior.py
@@ -1,5 +1,5 @@
from operationscore.Behavior import *
-import Util
+import util.ColorOps as color
import pdb
class ColorChangerBehavior(Behavior):
def processResponse(self, sensorInputs, recursiveInputs):
@@ -7,9 +7,8 @@ class ColorChangerBehavior(Behavior):
for sensory in sensorInputs:
newDict = dict(sensory) #don't run into shallow copy issues
if self['ColorList'] != None:
- newDict['Color'] = Util.chooseRandomColor(self['ColorList']) #TODO: this doesn't work.
+ newDict['Color'] = color.chooseRandomColor(self['ColorList']) #TODO: this doesn't work.
else:
- newDict['Color'] = Util.randomColor()
-#newDict['Color'] = (255,0,0)
+ newDict['Color'] = color.randomColor()
ret.append(newDict)
return (ret, recursiveInputs)
diff --git a/operationscore/PixelEvent.py b/operationscore/PixelEvent.py
index 66b6fdf..27e6e4a 100644
--- a/operationscore/PixelEvent.py
+++ b/operationscore/PixelEvent.py
@@ -2,6 +2,7 @@
#which should return a color, or None if the response is complete. Consider
#requiring a generate event.
from operationscore.SmootCoreObject import *
+import util.ColorOps as color
class PixelEvent(SmootCoreObject):
def init(self):
self.validateArgs('PixelEvent.params')
@@ -11,7 +12,7 @@ class PixelEvent(SmootCoreObject):
#Returns a new PixelEvent, but with a response scaled by c.
def scale(self,c):
newDict = dict(self.argDict)
- newDict['Color'] = Util.multiplyColor(newDict['Color'], c)
+ newDict['Color'] = color.multiplyColor(newDict['Color'], c)
return self.__class__(newDict)
def state(self,timeDelay):
pass
diff --git a/operationscore/SmootCoreObject.py b/operationscore/SmootCoreObject.py
index 8514b3e..10df299 100644
--- a/operationscore/SmootCoreObject.py
+++ b/operationscore/SmootCoreObject.py
@@ -2,6 +2,7 @@ import Util
import pdb
import threading
import thread
+import util.Config as configGetter
class SmootCoreObject(threading.Thread):
def __init__(self, argDict, skipValidation = False):
self.argDict = argDict
@@ -29,7 +30,7 @@ class SmootCoreObject(threading.Thread):
def __getiter__(self):
return self.argDict.__getiter__()
def validateArgs(self, argFileName):
- self.validateArgDict(Util.loadParamRequirementDict(argFileName))#util
+ self.validateArgDict(configGetter.loadParamRequirementDict(argFileName))#util
#caches for us, woo!
def validateArgDict(self, validationDict):
for item in validationDict:
diff --git a/pixelcore/Pixel.py b/pixelcore/Pixel.py
index ba87dff..f66d0bb 100644
--- a/pixelcore/Pixel.py
+++ b/pixelcore/Pixel.py
@@ -1,6 +1,7 @@
-import Util
+import util.ColorOps as color
import pdb
from pixelevents.StepEvent import *
+import util.TimeOps as clock
#Pixel keeps a queue of events (PixelEvent objects) (actually a dictionary
#keyed by event time). Every time is state is
#requested, it processes all the members of its queue. If a member returns none,
@@ -24,7 +25,7 @@ class Pixel:
#arg
#Add a pixelEvent to the list of active events
def processInput(self,pixelEvent,zindex): #consider migrating arg to dict
- self.events[Util.time()] = (zindex, pixelEvent)
+ self.events[clock.time()] = (zindex, pixelEvent)
def clearAllEvents(self):
self.events = {}
#Combines all PixelEvents currently active and computes the current color of
@@ -37,13 +38,13 @@ class Pixel:
if len(self.events) == 0:
return (0,0,0)
deadEvents = []
- currentTime = Util.time()
+ currentTime = clock.time()
resultingColor = (0,0,0)
for eventTime in self.events: #TODO: right color weighting code
(zindex,event) = self.events[eventTime]
eventResult = event.state(currentTime-eventTime)
if eventResult != None:
- resultingColor = Util.combineColors(eventResult, resultingColor)
+ resultingColor = color.combineColors(eventResult, resultingColor)
else:
deadEvents.append(eventTime)
[self.events.pop(event) for event in deadEvents]
diff --git a/pixelevents/DecayEvent.py b/pixelevents/DecayEvent.py
index 9a7c600..0b4c820 100644
--- a/pixelevents/DecayEvent.py
+++ b/pixelevents/DecayEvent.py
@@ -1,5 +1,6 @@
from operationscore.PixelEvent import *
-import Util, math
+import math
+from util.ColorOps import *
class DecayEvent(PixelEvent):
def initEvent(self):
self['Coefficient'] = abs(self['Coefficient'])
@@ -8,7 +9,7 @@ class DecayEvent(PixelEvent):
decay = math.exp(timeDelay*-1*self['Coefficient'])
if self['DecayType'] == 'Proportional':
decay = float(self['Coefficient']) / timeDelay
- color = Util.multiplyColor(self['Color'], decay)
+ color = multiplyColor(self['Color'], decay)
return color if sum(color) > 5 else None
@staticmethod
def generate(decayType, coefficient, color):
diff --git a/renderers/IndoorRenderer.py b/renderers/IndoorRenderer.py
index efe2b3a..2eac162 100644
--- a/renderers/IndoorRenderer.py
+++ b/renderers/IndoorRenderer.py
@@ -1,15 +1,15 @@
from operationscore.Renderer import *
-import socket, Util
-import pdb
-kinetPort = 6038
+import util.PacketComposition as composer
+import util.NetworkOps as network
+import socket,pdb
+port = 6038
+#Renderer for a Specific Light System.
class IndoorRenderer(Renderer):
def initRenderer(self):
- #pdb.set_trace()
self.stripLocations = {} #Dict that stores info necessary to render to
#strips
- self.sockets = {} #dict of (IP,port)->Socket
+ self.sockets = {} #dict of (IP)->Socket
#a strip
-# g self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
powerSupplies = self.argDict['PowerSupply']
if not type(powerSupplies) == type([]):
powerSupplies = [powerSupplies]
@@ -25,7 +25,7 @@ class IndoorRenderer(Renderer):
(ip, port) = self.stripLocations[stripId]
if not ip in self.sockets: #do we have a socket to this
#strip? if not, spin off a new one
- self.sockets[ip] = Util.getConnectedSocket(ip,kinetPort)
- packet = Util.composePixelStripPacket(pixelStrip, port)
+ self.sockets[ip] = network.getConnectedSocket(ip,port)
+ packet = composer.composePixelStripPacket(pixelStrip, port)
self.sockets[ip].send(packet, 0x00)
diff --git a/util/ColorOps.py b/util/ColorOps.py
new file mode 100644
index 0000000..b0d64a7
--- /dev/null
+++ b/util/ColorOps.py
@@ -0,0 +1,11 @@
+import random
+def randomColor():
+ return [random.randint(0,255) for i in range(3)]
+def chooseRandomColor(colorList):
+ return random.choice(colorList)
+def safeColor(c):
+ return [min(channel,255) for channel in c]
+def combineColors(c1,c2):
+ return safeColor([c1[i]+c2[i] for i in range(min(len(c1),len(c2)))])
+def multiplyColor(color, percent):
+ return safeColor([channel*(percent) for channel in color])
diff --git a/util/Config.py b/util/Config.py
new file mode 100644
index 0000000..4cf2ed5
--- /dev/null
+++ b/util/Config.py
@@ -0,0 +1,53 @@
+from xml.etree.ElementTree import ElementTree
+classArgsMem = {}
+CONFIG_PATH = 'config/'
+def loadParamRequirementDict(className):
+ if not className in classArgsMem: #WOO CACHING
+ classArgsMem[className] = fileToDict(CONFIG_PATH + className)
+ return classArgsMem[className]
+def loadConfigFile(fileName): #TODO: error handling etc.
+ try:
+ fileName = CONFIG_PATH + fileName
+ if '.params' in fileName:
+ return fileToDict(fileName)
+ if '.xml' in fileName:
+ config = ElementTree()
+ config.parse(fileName)
+ return config
+ except:
+ return None
+def fileToDict(fileName):
+ fileText = ''
+ try:
+ print 'File Read'
+ with open(fileName) as f:
+ for line in f:
+ fileText += line.rstrip('\n').lstrip('\t') + ' '
+ except IOError:
+ return {}
+ if fileText == '':
+ return {}
+ return eval(fileText)
+#parses arguments into python objects if possible, otherwise leaves as strings
+def generateArgDict(parentNode, recurse=False):
+ args = {}
+ for arg in parentNode.getchildren():
+ key = arg.tag
+ if arg.getchildren() != []:
+ value = generateArgDict(arg, True)
+ else:
+ #convert into python if possible, otherwise don't
+ try:
+ value = eval(arg.text)
+ except (NameError,SyntaxError):
+ value = str(arg.text)
+ if key in args: #build of lists of like-elements
+ if type(args[key]) != type([]):
+ args[key] = [args[key]]
+ args[key].append(value)
+ else:
+ args[key]=value
+ #if we should be a list but we aren't:
+ if len(args.keys()) == 1 and recurse:
+ return args[args.keys()[0]]
+ return args
diff --git a/util/NetworkOps.py b/util/NetworkOps.py
new file mode 100644
index 0000000..a247090
--- /dev/null
+++ b/util/NetworkOps.py
@@ -0,0 +1,6 @@
+import socket
+def getConnectedSocket(ip,port):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ print (ip, port)
+ sock.connect((ip, port))
+ return sock
diff --git a/util/PacketComposition.py b/util/PacketComposition.py
new file mode 100644
index 0000000..5133459
--- /dev/null
+++ b/util/PacketComposition.py
@@ -0,0 +1,59 @@
+import struct
+VERSION = 0x0001
+MAGIC = 0x4adc0104
+MOREMAGIC = 0xdeadbeef
+DEEPMAGIC = 0xc001d00d
+MAGICHASH = 0x69000420
+PORTOUT = 0x0108
+UNI = 0
+kinetDict = {'flags': 0, 'startcode': 0, 'pad':0}
+def composePixelStripData(pixelStrip):
+ packet = bytearray()
+ for light in pixelStrip:
+ color = light.state()
+ for channel in color: #skip the last value, its an
+ #alpha value
+ packet.append(struct.pack('B', channel))
+ return packet
+# packet = [0]*len(pixelStrip.pixels)*3 #preallocate for speed
+# for i in range(len(pixelStrip.pixels)):
+#color = pixelStrip.pixels[i].state()
+#packet[i:i+2] = color
+# return bytearray(packet)
+def composePixelStripPacket(pixelStrip,port):
+ packet = bytearray()
+ data = composePixelStripData(pixelStrip)
+ subDict = dict(kinetDict)
+ subDict['len'] = 38000 #I have no idea why this works.
+ subDict['port'] = port
+ #pdb.set_trace()
+ packet.extend(kinetPortOutPacket(subDict))
+ packet.append(0x0)
+ packet.extend(data)
+ return packet
+def kinetHeader():
+ header = bytearray()
+ header.extend(struct.pack('L', MAGIC))
+ header.extend(struct.pack('H', VERSION))
+ header.extend(struct.pack('H', PORTOUT))
+ header.extend(struct.pack('L', 0))
+ return header
+def kinetPortOut():
+ header = kinetHeader()
+ header.extend(struct.pack('L', UNI))
+ return header
+def kinetPortOutPayload(argDict):
+ payload = bytearray()
+ payload.extend(struct.pack('B', argDict['port']))
+ #payload.append(0x00) #somepadding? lolwtf.
+ payload.extend(struct.pack('H', argDict['flags']))
+ #payload.append(0x00) #somepadding? lolwtf.
+ payload.extend(struct.pack('H', argDict['len']))
+ payload.extend(struct.pack('H', argDict['startcode']))
+ #pdb.set_trace()
+ return payload
+def kinetPortOutPacket(payloadArgs):
+ packet = bytearray()
+ packet.extend(kinetPortOut())
+ packet.extend(kinetPortOutPayload(payloadArgs))
+ return packet
diff --git a/util/TimeOps.py b/util/TimeOps.py
new file mode 100644
index 0000000..dcd5038
--- /dev/null
+++ b/util/TimeOps.py
@@ -0,0 +1,19 @@
+import time as clock
+def time():
+ return clock.time()*1000 #all times in MS
+class Stopwatch:
+ def __init__(self):
+ self.running = False
+ self.startTime = -1
+ self.stopTime = -1
+ def start(self):
+ self.startTime = time()
+ self.running = True
+ def elapsed(self):
+ if self.running:
+ return time()-self.startTime
+ else:
+ return self.stopTime - self.startTime
+ def stop(self):
+ self.stopTime = time()
+ self.running = False
diff --git a/util/__init__.py b/util/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/util/__init__.py