diff options
author | rcoh <rcoh@mit.edu> | 2011-02-16 18:29:41 -0500 |
---|---|---|
committer | rcoh <rcoh@mit.edu> | 2011-02-16 18:29:41 -0500 |
commit | fffc14c4672294d9bbf8c60edfe8c309f0d54698 (patch) | |
tree | 19057b2e98735cc30fa1e0b3932d416946f8d705 | |
parent | 24aa31808de6a4dc06a651076e5b292aebd9240d (diff) | |
parent | 2df9e408a0ff74539862c4a4e562a878cc11a329 (diff) |
Merge branch 'conner5' of https://github.com/dxiao/SmootLight into dxiao-conner5
Conflicts:
config/C5Sign.xml
layouts/SpecifiedLayout.py
-rwxr-xr-x | LightInstallation.py | 5 | ||||
-rw-r--r-- | behaviors/Circle.py | 29 | ||||
-rw-r--r-- | behaviors/ModifyParam.py | 1 | ||||
-rw-r--r-- | behaviors/Oval.py | 36 | ||||
-rw-r--r-- | behaviors/TimeSwitch.py | 25 | ||||
-rw-r--r-- | behaviors/VerticalBar.py | 22 | ||||
-rw-r--r-- | config/C5Sign-dxiao.xml | 396 | ||||
-rw-r--r-- | config/C5Sign.xml | 219 | ||||
-rw-r--r-- | inputs/ContinuousCenterInput.py | 13 | ||||
-rw-r--r-- | inputs/ContinuousLocationInput.py | 20 | ||||
-rw-r--r-- | inputs/PygameInput.py | 4 | ||||
-rw-r--r-- | layouts/C5SignLayout.xml | 70 | ||||
-rw-r--r-- | layouts/SpecifiedLayout.py | 3 | ||||
-rw-r--r-- | operationscore/PixelAssembler.py | 3 | ||||
-rw-r--r-- | pixelcore/Screen.py | 2 | ||||
-rw-r--r-- | pixelmappers/C5SignMapper.py | 130 | ||||
-rw-r--r-- | pixelmappers/SimpleMapper.py | 19 | ||||
-rw-r--r-- | renderers/PygameRenderer.py | 9 | ||||
-rw-r--r-- | util/ComponentRegistry.py | 18 | ||||
-rw-r--r-- | util/Config.py | 8 |
20 files changed, 934 insertions, 98 deletions
diff --git a/LightInstallation.py b/LightInstallation.py index cca1588..19d6c54 100755 --- a/LightInstallation.py +++ b/LightInstallation.py @@ -103,9 +103,6 @@ class LightInstallation(object): for component in components: cid = compReg.registerComponent(component) main_log.info(cid + ' registered') - compReg.registerComponent(component) - main_log.info(cid + ' registered') - def initializeComponent(self, config): components = [] if config != None: @@ -164,8 +161,8 @@ class LightInstallation(object): responses = {} responses['Screen'] = [] #responses to the screen for behavior in self.behaviors: - responses[behavior['Id']] = behavior.timeStep() if behavior['RenderToScreen'] == True: + responses[behavior['Id']] = behavior.timeStep() responses['Screen'] += responses[behavior['Id']] return responses['Screen'] diff --git a/behaviors/Circle.py b/behaviors/Circle.py new file mode 100644 index 0000000..24d71f1 --- /dev/null +++ b/behaviors/Circle.py @@ -0,0 +1,29 @@ +from operationscore.Behavior import * +class Circle(Behavior): + def processResponse(self, sensors, recurs): + ret = [] + for data in sensors: + #import pdb; pdb.set_trace() + if 'CenterLoc' in data: + xLoc = data['CenterLoc'][0] + yLoc = data['CenterLoc'][1] + else: + data['CenterLoc'] = tuple(data['Location']) + xLoc = data['Location'][0] + yLoc = data['Location'][1] + if not self['Id']+'Radius' in data: + data[self['Id']+'Radius'] = self['Radius'] + rad = data[self['Id']+'Radius'] + cond = '>=' if self['Outside'] else '<=' + circleStr = 'math.sqrt(({x}-'+str(xLoc)+')**2+(({y}-'+str(yLoc)+')**2))'+cond+str(rad) + if self['Combine']: + data['Location'] += ',' + circleStr + else: + data['Location'] = circleStr + ret.append(data) + return (ret, []) + def setLastOutput(self, output): + coutput = Behavior.deepCopyPacket(output) + for data in coutput: + data['Location'] = data['CenterLoc'] + return coutput diff --git a/behaviors/ModifyParam.py b/behaviors/ModifyParam.py index 0ef3a60..6f81383 100644 --- a/behaviors/ModifyParam.py +++ b/behaviors/ModifyParam.py @@ -1,6 +1,5 @@ from operationscore.Behavior import * import math -import pdb #Class to perform a given operation on some element of an argDict. Designed to be used a recursive hook, but can serve sensor-based functions as well. Specify ParamType (Sensor or Recurse), ParamName, and ParamOp, (a valid python statement with the old value represented as {val}) class ModifyParam(Behavior): """ModifyParam is a powerful class to perform an action on a specified key in the Argument diff --git a/behaviors/Oval.py b/behaviors/Oval.py new file mode 100644 index 0000000..b7486f5 --- /dev/null +++ b/behaviors/Oval.py @@ -0,0 +1,36 @@ +from operationscore.Behavior import * +class Oval(Behavior): + def processResponse(self, sensors, recurs): + ret = [] + for data in sensors: + #import pdb; pdb.set_trace() + height = width = 1 + if 'Height' in self: + height = 1/float(self['Height']) + if 'Width' in self: + width = 1/float(self['Width']) + if 'CenterLoc' in data: + xLoc = data['CenterLoc'][0] + yLoc = data['CenterLoc'][1] + else: + data['CenterLoc'] = tuple(data['Location']) + xLoc = data['Location'][0] + yLoc = data['Location'][1] + if not self['Id']+'Radius' in data: + data[self['Id']+'Radius'] = self['Radius'] + rad = data[self['Id']+'Radius'] + cond = '>=' if self['Outside'] else '<=' + circleStr = \ + 'math.sqrt((({x}-%(xLoc)d))**2*%(width)d+(({y}-%(yLoc)d)**2)*%(height)d)%(cond)s%(rad)d' % \ + locals() + if self['Combine']: + data['Location'] += ',' + circleStr + else: + data['Location'] = circleStr + ret.append(data) + return (ret, []) + def setLastOutput(self, output): + coutput = Behavior.deepCopyPacket(output) + for data in coutput: + data['Location'] = data['CenterLoc'] + return coutput diff --git a/behaviors/TimeSwitch.py b/behaviors/TimeSwitch.py new file mode 100644 index 0000000..cfbfe4a --- /dev/null +++ b/behaviors/TimeSwitch.py @@ -0,0 +1,25 @@ +from operationscore.Behavior import * +import util.TimeOps as clock +import util.ComponentRegistry as compReg +from logger import main_log +class TimeSwitch(Behavior): + """TimeSwitch is a behavior that alternates between different behaviors for a set amount of time + (specify time in seconds. Specify in a python-style dict: + <Behaviors>{'behaviorId1':60, 'behaviorId2':120}</Behaviors> + Would alternate between the 2 behaviors, spending 1 minute on b1 and 2 minutes on b2. + """ + def behaviorInit(self): + self.keyIndex = 0 + self.currentBehaviorId = self['TimeMap'].keys()[self.keyIndex] + self.behaviorStart = clock.time() + + def processResponse(self, sensors, recurs): + if self.behaviorStart + self['TimeMap'][self.currentBehaviorId]*1000 <= clock.time(): + self.keyIndex += 1 + self.keyIndex = self.keyIndex % len(self['TimeMap']) + self.currentBehaviorId = self['TimeMap'].keys()[self.keyIndex] + self.behaviorStart = clock.time() + main_log.info('Switching behaviors') + sensors = [s for s in sensors if s['InputId'] == self['InputMap'][self.currentBehaviorId]] + return compReg.getComponent(self.currentBehaviorId).immediateProcessInput(sensors, recurs) + diff --git a/behaviors/VerticalBar.py b/behaviors/VerticalBar.py new file mode 100644 index 0000000..85960cb --- /dev/null +++ b/behaviors/VerticalBar.py @@ -0,0 +1,22 @@ +from operationscore.Behavior import * +class VerticalBar(Behavior): + + def processResponse(self, inputs, recurs): + ret = [] + inputs = list(inputs) + for inputset in inputs: + inputset = dict(inputset) + if 'xLoc' not in inputset: + inputset['xLoc'] = inputset['Location'][0] + xLoc = inputset['xLoc'] + + condition = '{x} == ' + str(xLoc) + + if self['Combine']: + inputset['Location'] += ',' + condition + else: + inputset['Location'] = condition + + ret.append(inputset) + return (ret, []) + diff --git a/config/C5Sign-dxiao.xml b/config/C5Sign-dxiao.xml new file mode 100644 index 0000000..7dc4b81 --- /dev/null +++ b/config/C5Sign-dxiao.xml @@ -0,0 +1,396 @@ +<!---All configuration items contain a "Class" tag specifying the python class they represent, and an "Args" tag specifying the args to be passed in.--> +<LightInstallation> + <InstallationConfiguration> + <Defaults> + <PixelMapper>simplemap</PixelMapper> + </Defaults> + </InstallationConfiguration> + <PixelConfiguration> + <InheritsFrom>layouts/C5SignLayout.xml</InheritsFrom> + </PixelConfiguration> + <PixelMapperConfiguration> + <!-- ****************************** --> + <PixelMapper> + <Class>pixelmappers.C5SignMapper</Class> + <Args> + <Id>c5signmapper</Id> + <CutoffDist>20</CutoffDist> + </Args> + </PixelMapper> + <!-- ****************************** --> + <PixelMapper> + <Class>pixelmappers.SimpleMapper</Class> + <Args> + <Id>simplemap</Id> + <CutoffDist>20</CutoffDist> + </Args> + </PixelMapper> + <PixelMapper> + <Class>pixelmappers.GaussianMapper</Class> + <Args> + <Id>gaussmap</Id> + <CutoffDist>30</CutoffDist> + <MinWeight>0.1</MinWeight> + <Width>7</Width> + <Height>1</Height> + </Args> + </PixelMapper> + </PixelMapperConfiguration> + <RendererConfiguration> + <Renderer> + <InheritsFrom>renderers/C5Renderer.xml</InheritsFrom> + </Renderer> + <!--Renderer> + <InheritsFrom>renderers/Pygame.xml</InheritsFrom> + </Renderer--> + </RendererConfiguration> + <InputConfiguration> + <!--InputElement> + <Class>inputs.PygameInput</Class> + <Args> + <Id>pygameclick</Id> + <RefreshInterval>10</RefreshInterval> + <Clicks>True</Clicks> + </Args> + </InputElement--> + <InputElement> + <Class>inputs.OSCInput</Class> + <Args> + <Id>osc</Id> + <Port>1234</Port> + <RefreshInterval>10</RefreshInterval> + </Args> + </InputElement> + <!--InputElement> + <Class>inputs.PygameInput</Class> + <Args> + <Id>pygamekey</Id> + <RefreshInterval>10</RefreshInterval> + <Keyboard>True</Keyboard> + </Args> + </InputElement--> + <InputElement> + <Class>inputs.UDPInput</Class> + <Args> + <Id>udp</Id> + <Port>3344</Port> + <RefreshInterval>50</RefreshInterval> + </Args> + </InputElement> + <InputElement> + <Class>inputs.ContinuousCenterInput</Class> + <Args> + <Id>center</Id> + <RefreshInterval>1800</RefreshInterval> + </Args> + </InputElement> + <!-- ****************************** --> + <InputElement> + <Class>inputs.ContinuousLocationInput</Class> + <Args> + <Id>centerleft</Id> + <xloc>left</xloc> + <yloc>center</yloc> + <RefreshInterval>1800</RefreshInterval> + </Args> + </InputElement> + <!-- ****************************** --> + <!--<InputElement> + <Class>inputs.TCPInput</Class> + <Args> + <Id>tcp</Id> + <Port>20120</Port> + <RefreshInterval>10</RefreshInterval> + </Args> + </InputElement>--> + <!--InputElement Id="followmouse" RefreshInterval="10"> + <InheritsFrom>inputs/MouseFollower.xml</InheritsFrom> + </InputElement--> + </InputConfiguration> + <BehaviorConfiguration> + <Behavior> + <Args> + <Id>touchosc</Id> + </Args> + <Class>behaviors.TouchOSC</Class> + </Behavior> + <Behavior Id="colorchange"> + <InheritsFrom>behaviors/RandomColor.xml</InheritsFrom> + <Args> + <!--ColorList> + <Val>(255,0,0)</Val> + <Val>(0,0,255)</Val> + </ColorList--> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>OSCTouchChase</Id> + <Inputs> + <Id>osc</Id> + </Inputs> + <ChainedBehaviors> + <Id>touchosc</Id> + <Id>decay</Id> + </ChainedBehaviors> + <Mapper>gaussmap</Mapper> + <RenderToScreen>False</RenderToScreen> + </Args> + </Behavior> + <Behavior Id="decay"> + <InheritsFrom>behaviors/PixelDecay.xml</InheritsFrom> + </Behavior> + <Behavior Id="singleframe"> + <InheritsFrom>behaviors/SingleFrame.xml</InheritsFrom> + </Behavior> + <!-- ****************************** --> + <Behavior Id="slowdecay"> + <InheritsFrom>behaviors/PixelDecay.xml</InheritsFrom> + <Args> + <Coefficient>.001</Coefficient> + </Args> + </Behavior> + <!-- ****************************** --> + <Behavior> + <Class>behaviors.XYMove</Class> + <Args> + <Id>xymove</Id> + <XStep>1</XStep> + <YStep>1</YStep> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.RestrictLocation</Class> + <Args> + <Id>xbounce</Id> + <Action>{val}*-1</Action> + <ParamName>XStep</ParamName> + <LocationRestriction>{x}<2 or {x}>48</LocationRestriction> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.RestrictLocation</Class> + <Args> + <Id>ybounce</Id> + <Action>{val}*-1</Action> + <ParamName>YStep</ParamName> + <LocationRestriction>{y}<2 or {y}>24</LocationRestriction> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>movebounce</Id> + <ChainedBehaviors> + <Id>xymove</Id> + <Id>ybounce</Id> + <Id>xbounce</Id> + </ChainedBehaviors> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.ModifyParam</Class> + <Args> + <Id>ysin</Id> + <ParamName>YStep</ParamName> + <ParamType>Sensor</ParamType> + <ParamOp>4*math.sin({x}/float(40))</ParamOp> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.DebugBehavior</Class> + <Args> + <Id>debug</Id> + <z-index>0</z-index> + <Inputs> + <Id>pygamekey</Id> + <Id>udp</Id> + </Inputs> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.AllPixels</Class> + <Args> + <Id>square</Id> + <Width>20</Width> + </Args> + </Behavior> + <Behavior Id="recursivedecay"> + <InheritsFrom>behaviors/LoopAndDie.xml</InheritsFrom> + <Args> + <InitialResponseCount>160</InitialResponseCount> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>runcolordecay</Id> + <Inputs> + <Id>pygameclick</Id> + </Inputs> + <ChainedBehaviors> + <Id>colorchange</Id> + <Id>mover</Id> + <!--<Id>square</Id>--> + <Id>decay</Id> + </ChainedBehaviors> + <RecursiveHooks>{'mover':'movebounce'}</RecursiveHooks> + <RenderToScreen>False</RenderToScreen> + <Mapper>gaussmap</Mapper> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.ResponseMover</Class> + <Args> + <Id>mover</Id> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.RandomWalk</Class> + <Args> + <Id>randmovement</Id> + <StepSize>2</StepSize> + </Args> + </Behavior> + <Behavior Id="accelerate"> + <InheritsFrom>behaviors/Accelerate.xml</InheritsFrom> + </Behavior> + <Behavior> + <Class>behaviors.EchoBehavior</Class> + <Args> + <Id>echo</Id> + <z-index>0</z-index> + <RenderToScreen>False</RenderToScreen> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.ColorShift</Class> + <Args> + <Id>colorshift</Id> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>mousechaser</Id> + <Inputs> + </Inputs> + <ChainedBehaviors> + <Id>echo</Id> + <Id>innercircle</Id> + <Id>outercircle</Id> + <Id>singleframe</Id> + </ChainedBehaviors> + <RenderToScreen>False</RenderToScreen> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.Circle</Class> + <Args> + <Id>innercircle</Id> + <Radius>0</Radius> + <Outside>True</Outside> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.Circle</Class> + <Args> + <Id>outercircle</Id> + <Radius>3</Radius> + <Combine>True</Combine> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.ModifyParam</Class> + <Args> + <Id>incrinner</Id> + <ParamOp>{val}+.3</ParamOp> + <ParamName>innercircleRadius</ParamName> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.ModifyParam</Class> + <Args> + <Id>incrouter</Id> + <ParamOp>{val}+.3</ParamOp> + <ParamName>outercircleRadius</ParamName> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>circle_expand</Id> + <ChainedBehaviors> + <Id>innercircle</Id> + <Id>outercircle</Id> + <Id>incrinner</Id> + <Id>incrouter</Id> + <Id>recursivedecay</Id> + </ChainedBehaviors> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>expandingcirlces</Id> + <Inputs> + <Id>centerleft</Id> + </Inputs> + <ChainedBehaviors> + <Id>colorchange</Id> + <Id>mover</Id> + <Id>decay</Id> + </ChainedBehaviors> + <RecursiveHooks>{'mover':'circle_expand'}</RecursiveHooks> + <RenderToScreen>False</RenderToScreen> + </Args> + </Behavior> + <!-- ****************************** --> + <Behavior> + <Class>behaviors.ModifyParam</Class> + <Args> + <Id>incrVertBarLoc</Id> + <ParamName>xLoc</ParamName> + <ParamOp>{val}+1</ParamOp> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.VerticalBar</Class> + <Args> + <Id>vertBar</Id> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>bar_move</Id> + <ChainedBehaviors> + <Id>vertBar</Id> + <Id>incrVertBarLoc</Id> + <Id>recursivedecay</Id> + </ChainedBehaviors> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>scanningbars</Id> + <Inputs> + <Id>centerleft</Id> + </Inputs> + <ChainedBehaviors> + <Id>colorchange</Id> + <Id>mover</Id> + <Id>slowdecay</Id> + </ChainedBehaviors> + <RecursiveHooks>{'mover':'bar_move'}</RecursiveHooks> + <RenderToScreen>True</RenderToScreen> + </Args> + </Behavior> + <!-- ****************************** --> + <Behavior Id="running"> + <InheritsFrom>behaviors/RunningBehavior.xml</InheritsFrom> + </Behavior> + </BehaviorConfiguration> +</LightInstallation> diff --git a/config/C5Sign.xml b/config/C5Sign.xml index 6550067..77f6bcc 100644 --- a/config/C5Sign.xml +++ b/config/C5Sign.xml @@ -10,7 +10,7 @@ </PixelConfiguration> <PixelMapperConfiguration> <PixelMapper> - <Class>pixelmappers.SimpleMapper</Class> + <Class>pixelmappers.C5SignMapper</Class> <Args> <Id>simplemap</Id> <CutoffDist>20</CutoffDist> @@ -22,26 +22,42 @@ <Id>gaussmap</Id> <CutoffDist>30</CutoffDist> <MinWeight>0.1</MinWeight> - <Width>10</Width> + <Width>7</Width> <Height>1</Height> </Args> </PixelMapper> + <PixelMapper> + <Class>pixelmappers.C5SignMapper</Class> + <Args> + <Id>c5signmapper</Id> + <CutoffDist>20</CutoffDist> + </Args> + </PixelMapper> </PixelMapperConfiguration> <RendererConfiguration> <Renderer> <InheritsFrom>renderers/C5Renderer.xml</InheritsFrom> </Renderer> - <Renderer> + <Renderer Scale="5"> <InheritsFrom>renderers/Pygame.xml</InheritsFrom> </Renderer> </RendererConfiguration> <InputConfiguration> <InputElement> - <Class>inputs.PygameInput</Class> + <Class>inputs.ContinuousLocationInput</Class> <Args> - <Id>pygameclick</Id> + <Id>centerleft</Id> + <xloc>left</xloc> + <yloc>center</yloc> + <RefreshInterval>1800</RefreshInterval> + </Args> + </InputElement> + <InputElement> + <Class>inputs.OSCInput</Class> + <Args> + <Id>osc</Id> + <Port>1234</Port> <RefreshInterval>10</RefreshInterval> - <Clicks>True</Clicks> </Args> </InputElement> <InputElement> @@ -60,26 +76,84 @@ <RefreshInterval>50</RefreshInterval> </Args> </InputElement> - <!--<InputElement> - <Class>inputs.TCPInput</Class> + <InputElement> + <Class>inputs.ContinuousCenterInput</Class> <Args> - <Id>tcp</Id> - <Port>20120</Port> - <RefreshInterval>10</RefreshInterval> + <Id>center</Id> + <RefreshInterval>700</RefreshInterval> </Args> - </InputElement>--> - <InputElement Id="followmouse" RefreshInterval="1000"> - <InheritsFrom>inputs/MouseFollower.xml</InheritsFrom> </InputElement> </InputConfiguration> <BehaviorConfiguration> + <Behavior> + <Args> + <Id>touchosc</Id> + </Args> + <Class>behaviors.TouchOSC</Class> + </Behavior> + <Behavior Id="slowdecay"> + <InheritsFrom>behaviors/PixelDecay.xml</InheritsFrom> + <Args> + <Coefficient>.001</Coefficient> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.ModifyParam</Class> + <Args> + <Id>incrVertBarLoc</Id> + <ParamName>xLoc</ParamName> + <ParamOp>{val}+1</ParamOp> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.VerticalBar</Class> + <Args> + <Id>vertBar</Id> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>bar_move</Id> + <ChainedBehaviors> + <Id>vertBar</Id> + <Id>incrVertBarLoc</Id> + <Id>recursivedecay</Id> + </ChainedBehaviors> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>scanningbars</Id> + <Inputs> + <Id>centerleft</Id> + </Inputs> + <ChainedBehaviors> + <Id>colorchange</Id> + <Id>mover</Id> + <Id>slowdecay</Id> + </ChainedBehaviors> + <RecursiveHooks>{'mover':'bar_move'}</RecursiveHooks> + <RenderToScreen>False</RenderToScreen> + </Args> + </Behavior> <Behavior Id="colorchange"> <InheritsFrom>behaviors/RandomColor.xml</InheritsFrom> + </Behavior> + <Behavior> + <Class>behaviors.BehaviorChain</Class> <Args> - <ColorList> - <Val>(255,0,0)</Val> - <Val>(0,0,255)</Val> - </ColorList> + <Id>OSCTouchChase</Id> + <Inputs> + <Id>osc</Id> + </Inputs> + <ChainedBehaviors> + <Id>touchosc</Id> + <Id>decay</Id> + </ChainedBehaviors> + <Mapper>gaussmap</Mapper> + <RenderToScreen>False</RenderToScreen> </Args> </Behavior> <Behavior Id="decay"> @@ -88,18 +162,12 @@ <Behavior Id="singleframe"> <InheritsFrom>behaviors/SingleFrame.xml</InheritsFrom> </Behavior> - <Behavior Id="slowdecay"> - <InheritsFrom>behaviors/PixelDecay.xml</InheritsFrom> - <Args> - <Coefficient>.01</Coefficient> - </Args> - </Behavior> <Behavior> <Class>behaviors.XYMove</Class> <Args> <Id>xymove</Id> - <XStep>5</XStep> - <YStep>2</YStep> + <XStep>1</XStep> + <YStep>1</YStep> </Args> </Behavior> <Behavior> @@ -108,7 +176,7 @@ <Id>xbounce</Id> <Action>{val}*-1</Action> <ParamName>XStep</ParamName> - <LocationRestriction>{x}<0 or {x}>200</LocationRestriction> + <LocationRestriction>{x}<2 or {x}>48</LocationRestriction> </Args> </Behavior> <Behavior> @@ -117,7 +185,7 @@ <Id>ybounce</Id> <Action>{val}*-1</Action> <ParamName>YStep</ParamName> - <LocationRestriction>{y}<0 or {y}>100</LocationRestriction> + <LocationRestriction>{y}<2 or {y}>24</LocationRestriction> </Args> </Behavior> <Behavior> @@ -126,19 +194,24 @@ <Id>movebounce</Id> <ChainedBehaviors> <Id>xymove</Id> - <Id>colorshift</Id> <Id>ybounce</Id> <Id>xbounce</Id> + <Id>longrecursivedecay</Id> </ChainedBehaviors> </Args> </Behavior> <Behavior> - <Class>behaviors.ModifyParam</Class> + <Class>behaviors.TimeSwitch</Class> <Args> - <Id>ysin</Id> - <ParamName>YStep</ParamName> - <ParamType>Sensor</ParamType> - <ParamOp>4*math.sin({x}/float(40))</ParamOp> + <Id>main</Id> + <Inputs> + <Id>centerleft</Id> + <Id>center</Id> + </Inputs> + <TimeMap>{'scanningbars':10,'runcolordecay':10,'expandingcircles':10}</TimeMap> + <InputMap>{'scanningbars':'centerleft', 'runcolordecay':'center',\ + 'expandingcircles':'center'}</InputMap> + <RenderToScreen>True</RenderToScreen> </Args> </Behavior> <Behavior> @@ -159,26 +232,24 @@ <Width>20</Width> </Args> </Behavior> - <Behavior Id="recursivedecay"> + <Behavior Id="recursivedecay" InitialResponseCount="50"> + <InheritsFrom>behaviors/LoopAndDie.xml</InheritsFrom> + </Behavior> + <Behavior Id="longrecursivedecay" InitialResponseCount="80"> <InheritsFrom>behaviors/LoopAndDie.xml</InheritsFrom> - <Args> - <InitialResponseCount>80</InitialResponseCount> - </Args> </Behavior> <Behavior> <Class>behaviors.BehaviorChain</Class> <Args> <Id>runcolordecay</Id> - <Inputs> - <Id>pygameclick</Id> - </Inputs> <ChainedBehaviors> <Id>colorchange</Id> <Id>mover</Id> + <!--<Id>square</Id>--> <Id>decay</Id> </ChainedBehaviors> <RecursiveHooks>{'mover':'movebounce'}</RecursiveHooks> - <RenderToScreen>True</RenderToScreen> + <RenderToScreen>False</RenderToScreen> <Mapper>gaussmap</Mapper> </Args> </Behavior> @@ -189,46 +260,68 @@ </Args> </Behavior> <Behavior> - <Class>behaviors.RandomWalk</Class> + <Class>behaviors.ColorShift</Class> + <Args> + <Id>colorshift</Id> + </Args> + </Behavior> + <Behavior> + <Class>behaviors.Oval</Class> <Args> - <Id>randmovement</Id> - <StepSize>2</StepSize> + <Id>innercircle</Id> + <Radius>0</Radius> + <Outside>True</Outside> </Args> </Behavior> - <Behavior Id="accelerate"> - <InheritsFrom>behaviors/Accelerate.xml</InheritsFrom> + <Behavior> + <Class>behaviors.Oval</Class> + <Args> + <Id>outercircle</Id> + <Radius>3</Radius> + <Combine>True</Combine> + </Args> </Behavior> <Behavior> - <Class>behaviors.EchoBehavior</Class> + <Class>behaviors.ModifyParam</Class> <Args> - <Id>echo</Id> - <z-index>0</z-index> - <RenderToScreen>False</RenderToScreen> + <Id>incrinner</Id> + <ParamOp>{val}+.6</ParamOp> + <ParamName>innercircleRadius</ParamName> </Args> </Behavior> <Behavior> - <Class>behaviors.ColorShift</Class> + <Class>behaviors.ModifyParam</Class> <Args> - <Id>colorshift</Id> + <Id>incrouter</Id> + <ParamOp>{val}+.6</ParamOp> + <ParamName>outercircleRadius</ParamName> </Args> </Behavior> <Behavior> <Class>behaviors.BehaviorChain</Class> <Args> - <Id>mousechaser</Id> - <Inputs> - <Id>followmouse</Id> - </Inputs> + <Id>circle_expand</Id> <ChainedBehaviors> - <Id>echo</Id> - <Id>square</Id> - <Id>singleframe</Id> + <Id>innercircle</Id> + <Id>outercircle</Id> + <Id>incrinner</Id> + <Id>incrouter</Id> + <Id>recursivedecay</Id> </ChainedBehaviors> - <RenderToScreen>False</RenderToScreen> </Args> </Behavior> - <Behavior Id="running"> - <InheritsFrom>behaviors/RunningBehavior.xml</InheritsFrom> + <Behavior> + <Class>behaviors.BehaviorChain</Class> + <Args> + <Id>expandingcircles</Id> + <ChainedBehaviors> + <Id>colorchange</Id> + <Id>mover</Id> + <Id>decay</Id> + <!--Id>singleframe</Id--> + </ChainedBehaviors> + <RecursiveHooks>{'mover':'circle_expand'}</RecursiveHooks> + </Args> </Behavior> </BehaviorConfiguration> </LightInstallation> diff --git a/inputs/ContinuousCenterInput.py b/inputs/ContinuousCenterInput.py new file mode 100644 index 0000000..88534f0 --- /dev/null +++ b/inputs/ContinuousCenterInput.py @@ -0,0 +1,13 @@ +import util.TimeOps as clock +import util.ComponentRegistry as compReg +import util.Strings as Strings +from operationscore.Input import * +class ContinuousCenterInput(Input): + def inputInit(self): + compReg.getLock().acquire() + minX,minY,maxX,maxY = compReg.getComponent('Screen').getSize() + compReg.getLock().release() + self.center = ((minX+maxX) / 2, (minY+maxY) / 2) + def sensingLoop(self): + self.respond({Strings.LOCATION: self.center}) + diff --git a/inputs/ContinuousLocationInput.py b/inputs/ContinuousLocationInput.py new file mode 100644 index 0000000..72ca8f0 --- /dev/null +++ b/inputs/ContinuousLocationInput.py @@ -0,0 +1,20 @@ +import util.TimeOps as clock +import util.ComponentRegistry as compReg +import util.Strings as Strings +from operationscore.Input import * +class ContinuousLocationInput(Input): + '''Continuously returns one of nine positions on the screen as specified by the xloc + and yloc arguments, which can take values 'min', 'max', and 'center'. ''' + def inputInit(self): + xvals = {} + yvals = {} + compReg.getLock().acquire() + xvals['left'], yvals['bottom'], xvals['right'], yvals['top'] = compReg.getComponent('Screen').getSize() + compReg.getLock().release() + (xvals['center'], yvals['center']) = ((xvals['left']+xvals['right']) / 2, (yvals['top']+yvals['bottom']) / 2) + + self.location = (xvals[self['xloc']], yvals[self['yloc']]) + + def sensingLoop(self): + self.respond({Strings.LOCATION: self.location}) + diff --git a/inputs/PygameInput.py b/inputs/PygameInput.py index 480630c..8de55f9 100644 --- a/inputs/PygameInput.py +++ b/inputs/PygameInput.py @@ -15,6 +15,10 @@ class PygameInput(Input): NB: If follow mouse is enabled, PygameInput will not return mouse and keypresses. You can, however, instantiate other PygameInputs in the XML that will capture mouse and keypresses.""" def sensingLoop(self): + if 'Scale' in self: + scale = self['Scale'] + else: + scale = 1 if self['FollowMouse']: self.respond({Strings.LOCATION: pygame.mouse.get_pos()}) return diff --git a/layouts/C5SignLayout.xml b/layouts/C5SignLayout.xml index 58310d7..353ae73 100644 --- a/layouts/C5SignLayout.xml +++ b/layouts/C5SignLayout.xml @@ -1,16 +1,70 @@ <PixelConfiguration> <PixelStrip> - <Class>layouts.ZigzagLayout</Class> + <Class>layouts.SpecifiedLayout</Class> <Args> <Id>strip1</Id> - <zigLength>10</zigLength> - <zigAxis>X</zigAxis> - <yDirection>1</yDirection> - <pixelToPixelSpacing>20</pixelToPixelSpacing> - <spacing>20</spacing> <!--we can space at any value less the - l2lspacing--> <numPixels>50</numPixels> - <originLocation>(0,0)</originLocation> + <Spacing>12</Spacing> + <pixelToPixelSpacing>12</pixelToPixelSpacing> + <originLocation>(2,2)</originLocation> + <Locations> + <!--# Left strip--> + <Loc>(2,8)</Loc> + <Loc>(2,14)</Loc> + <Loc>(2,20)</Loc> + <!--# Top strip--> + <Loc>(4, 22)</Loc> + <Loc>(10,22)</Loc> + <Loc>(16,22)</Loc> + <Loc>(22,22)</Loc> + <Loc>(27,22)</Loc> + <Loc>(33,22)</Loc> + <Loc>(39,22)</Loc> + <Loc>(44,22)</Loc> + <!--# Right strip--> + <Loc>(45,20)</Loc> + <Loc>(45,14)</Loc> + <Loc>(45,8)</Loc> + <Loc>(45,2)</Loc> + <!--# Bottom strip--> + <Loc>(44,2)</Loc> + <Loc>(39,2)</Loc> + <Loc>(34,2)</Loc> + <Loc>(27,2)</Loc> + <Loc>(22,2)</Loc> + <Loc>(16,2)</Loc> + <Loc>(10,2)</Loc> + <Loc>(4,2)</Loc> + <!--# Welcome to--> + <Loc>(12,5)</Loc> + <Loc>(13,5)</Loc> + <Loc>(16,5)</Loc> + <Loc>(18,5)</Loc> + <Loc>(21,5)</Loc> + <Loc>(23,5)</Loc> + <Loc>(26,5)</Loc> + <Loc>(27,5)</Loc> + <Loc>(30,5)</Loc> + <Loc>(34,5)</Loc> + <Loc>(37,5)</Loc> + <!--# C5 Logo--> + <Loc>(31,12)</Loc> + <Loc>(26,12)</Loc> + <Loc>(24,10)</Loc> + <Loc>(17,8)</Loc> + <Loc>(21,10)</Loc> + <!--# Conner 5--> + <Loc>(19,17)</Loc> + <Loc>(11,17)</Loc> + <Loc>(6,17)</Loc> + <Loc>(15,17)</Loc> + <Loc>(22,17)</Loc> + <Loc>(27,17)</Loc> + <Loc>(33,16)</Loc> + <Loc>(38,17)</Loc> + <Loc>(42,17)</Loc> + <Loc>(34,16)</Loc> + </Locations> </Args> </PixelStrip> </PixelConfiguration> diff --git a/layouts/SpecifiedLayout.py b/layouts/SpecifiedLayout.py index 5a6e963..b746e68 100644 --- a/layouts/SpecifiedLayout.py +++ b/layouts/SpecifiedLayout.py @@ -12,10 +12,9 @@ class SpecifiedLayout(PixelAssembler): You may put attributes on the Locs so that you don't get confused. """ - def layoutInit(self): + def initLayout(self): self.lightNum = -1 def layoutFunc(self, lastLocation): self.lightNum += 1 return self['Locations'][self.lightNum] - diff --git a/operationscore/PixelAssembler.py b/operationscore/PixelAssembler.py index 84f3b0b..8ae27c9 100644 --- a/operationscore/PixelAssembler.py +++ b/operationscore/PixelAssembler.py @@ -21,7 +21,8 @@ class PixelAssembler(SmootCoreObject): self['pixelToPixelSpacing']: raise Exception('Illegal pixel location. Distance \ between adjacent pixels must be less than \ - pixelToPixelSpacing.') + pixelToPixelSpacing. Illegal distance is between '+str(pixelIndex) + ' and'\ + + str(pixelIndex+1)) locations.append(newLocation) if self['Reverse']: locations.reverse() diff --git a/pixelcore/Screen.py b/pixelcore/Screen.py index ada8d4a..1bed4f1 100644 --- a/pixelcore/Screen.py +++ b/pixelcore/Screen.py @@ -79,7 +79,7 @@ class Screen: maxY = max(y, maxY) self.size = (0,0, maxX, maxY) self.sizeValid = True - return (0, 0, maxX, maxY) + return (minX, minY, maxX, maxY) #private def processResponse(self, responseInfo, currentTime=None): #we need to make a new dict for diff --git a/pixelmappers/C5SignMapper.py b/pixelmappers/C5SignMapper.py new file mode 100644 index 0000000..24631c4 --- /dev/null +++ b/pixelmappers/C5SignMapper.py @@ -0,0 +1,130 @@ +from operationscore.PixelMapper import * +import util.Geo as Geo +import sys +import math +class C5SignMapper(PixelMapper): + """C5SignMapper is a modification to SimpleMapper which maps events to the + nearest Pixel. In addtion, it also maps sign artifacts (letters, logo, etc) + to their representative locations if given in the form "ts rs :: conditions" + It also supports strings of the form: {x}>5, {y}<10, {x}*{y}<{x}, etc. + (Conditons, separated by commas. and and or may also be used).""" + + signPosition = { + "ls" : { + 'all' : [(2,2),(2,8), (2,14), (2,20)], + '1' : [(2,2)], + '2' : [(2,8)], + '3' : [(2,14)], + '4' : [(2,20)] }, + "ts" : { + 'all' : [(4,22), (10,22), (16,22), (22,22), (27, 22), (33, 22), (39,22), (44, 22)], + '1' : [(4,22)], + '2' : [(10,22)], + '3' : [(16,22)], + '4' : [(22,22)], + '5' : [(27,22)], + '6' : [(33,22)], + '7' : [(39,22)], + '8' : [(44,22)] }, + "rs" : { + 'all' : [(45,2), (45, 8), (45,14), (45,20)], + '1' : [(45,2)], + '2' : [(45,8)], + '3' : [(45,14)], + '4' : [(45,20)] }, + "bs" : { + 'all' : [(4,2), (10,2), (16,2), (22, 2), (27,2), (34,2), (39,2), (44,2)], + '1' : [(4,2)], + '2' : [(10,2)], + '3' : [(16,2)], + '4' : [(22,2)], + '5' : [(27,2)], + '6' : [(33,2)], + '7' : [(39,2)], + '8' : [(44,2)] }, + "wt" : { + 'all' : [(12,5), (13, 5), (16,5), (18,5), (21,5), (23,5), (26,5), (27,5), (30,5), (34,5), (37,5)], + '1' : [(12,5), (13,5)], + '2' : [(16,5)], + '3' : [(18,5)], + '4' : [(21,5)], + '5' : [(23,5)], + '6' : [(26,5),(27,5)], + '7' : [(30,5)], + '8' : [(34,5)], + '9' : [(37,5)] }, + "cl" : { + 'all' : [(17,8), (21,10), (24,10), (26,12), (31,12)], + 'in' : [(21,10),(24,10),(26,12)], + 'out' : [(17,8),(31,12)], + '1' : [(17,8)], + '2' : [(21,10)], + '3' : [(24,10)], + '4' : [(26,12)], + '5' : [(31,12)] }, + "c5" : { + 'all' : [(6,17), (11,17), (15,17), (19,17), (22, 17), (27,17), (33,16), (34, 16), (38,17), (42,17)], + 'con' : [(6,17), (11,17), (15,17), (19,17), (22, 17), (27,17)], + 'five': [(33,16), (34, 16), (38,17), (42,17)], + '1' : [(6,17)], + '2' : [(11,17)], + '3' : [(15,17)], + '4' : [(19,17)], + '5' : [(22,17)], + '6' : [(27,17)], + '7' : [(33,16)], + '8' : [(34,16)], + '9' : [(38,17)], + '10' : [(42,17)] }, + } + + def mappingFunction(self, eventLocation, screen): + if type(eventLocation) == type(tuple()): + bestDist = sys.maxint + bestPixel = None + [x,y] = eventLocation + for (x,pixel) in screen.pixelsInRange(x-self['CutoffDist'], \ + x+self['CutoffDist']): + pixelDist = Geo.dist(pixel.location, eventLocation) + if pixelDist < bestDist: + bestPixel = pixel + bestDist = pixelDist + if bestPixel != None: + return [(bestPixel,1)] + else: + return [] + else: + #pixel locs + eventLocSplit = eventLocation.split('@') + if len(eventLocSplit) == 2: + [eventLocation, signPart] = eventLocSplit + signParts = signPart.split('.') + pixelLocs = signPosition[signParts[0]][signParts[1]] + screenPixels = [p for p in screen if (p.location in pixelLocs)] + else: + screenPixels = [p for p in screen] + + + #{x}>5,{y}<k + ret = [] + eventLocation = eventLocation.replace('{x}', 'pixel.location[0]') + eventLocation = eventLocation.replace('{y}', 'pixel.location[1]') + if len(eventLocation) > 0: + conditions = eventLocation.split(',') + conditionLambdas = [eval('lambda pixel:'+condition) for condition in conditions] + else: + conditionLambdas = [] + for pixel in screenPixels: + try: + pixelValid = True + for p in conditionLambdas: + if p(pixel) == False: + pixelValid = False + continue + if pixelValid: + ret.append((pixel, 1)) + except Exception as exp: + import pdb; pdb.set_trace() + raise Exception('Bad event condition') + return ret + diff --git a/pixelmappers/SimpleMapper.py b/pixelmappers/SimpleMapper.py index 1568de3..1decdd1 100644 --- a/pixelmappers/SimpleMapper.py +++ b/pixelmappers/SimpleMapper.py @@ -1,11 +1,13 @@ from operationscore.PixelMapper import * import util.Geo as Geo +import math import sys class SimpleMapper(PixelMapper): """SimpleMapper is a PixelMapper which maps events to the nearest Pixel. It also supports strings of the form: - {x}>5, {y}<10, {x}*{y}<{x}, etc. (Conditons, separated by commas. and and or may also be - used).""" + {x}>5, {y}<10, {x}*{y}<{x}, etc. (Conditions, separated by commas. Standard python syntax such + as and and or may also be + used). You may use 'math.' functions such as math.sqrt, etc. It also accepts lists of strings""" def mappingFunction(self, eventLocation, screen): if type(eventLocation) == type(tuple()): bestDist = sys.maxint @@ -24,10 +26,14 @@ class SimpleMapper(PixelMapper): else: #{x}>5,{y}<k ret = [] - eventLocation = eventLocation.replace('{x}', 'pixel.location[0]') - eventLocation = eventLocation.replace('{y}', 'pixel.location[1]') - conditions = eventLocation.split(',') + if not isinstance(eventLocation, list): + eventLocation = eventLocation.replace('{x}', 'pixel.location[0]') + eventLocation = eventLocation.replace('{y}', 'pixel.location[1]') + conditions = eventLocation.split(',') + else: + conditions = eventLocation #TODO: check for lists of strings conditionLambdas = [eval('lambda pixel:'+condition) for condition in conditions] + for pixel in screen: try: pixelValid = True @@ -38,6 +44,7 @@ class SimpleMapper(PixelMapper): if pixelValid: ret.append((pixel, 1)) except Exception as exp: - raise Exception('Bad event condition') + exp.message += 'Bad Event Condition' + raise exp return ret diff --git a/renderers/PygameRenderer.py b/renderers/PygameRenderer.py index bc50360..8be272c 100644 --- a/renderers/PygameRenderer.py +++ b/renderers/PygameRenderer.py @@ -18,9 +18,14 @@ class PygameRenderer(Renderer): def render(self, lightSystem, currentTime=timeops.time()): self.background.fill(Color(0,0,0)) #print 'drawing color:',light.color + if 'Scale' in self: + scale = self['Scale'] + else: + scale = 1 for light in lightSystem: - pygame.draw.circle(self.background, light.state(currentTime), light.location, \ - light.radius) + scaledLoc = [l*scale for l in light.location] + pygame.draw.circle(self.background, light.state(currentTime), scaledLoc, \ + 5) self.screen.blit(self.background, (0,0)) pygame.display.flip() diff --git a/util/ComponentRegistry.py b/util/ComponentRegistry.py index be913df..1db5135 100644 --- a/util/ComponentRegistry.py +++ b/util/ComponentRegistry.py @@ -1,12 +1,17 @@ -import pdb import hashlib from logger import main_log +import thread #TODO: make component registry a singleton def initRegistry(): #TODO: don't overwrite existing registry if not 'Registry' in globals(): globals()['Registry'] = {} - + makelock() + + +def makelock(): + global utilLock + utilLock = thread.allocate_lock() def clearRegistry(): initRegistry() @@ -14,6 +19,9 @@ def removeComponent(cid): global Registry Registry.pop(cid) +def getLock(): + global utilLock + return utilLock def getComponent(cid): global Registry return Registry[cid] @@ -31,6 +39,8 @@ def registerComponent(component, cid=None): cid = getNewId() component['Id'] = cid main_log.debug(cid + 'automatically assigned') + if cid in Registry: + main_log.warn(cid + 'overwritten.') Registry[cid] = component return cid @@ -42,10 +52,6 @@ def removeComponent(cid): global Registry Registry.pop(cid) -def getComponent(cid): - global Registry - return Registry[cid] - def getNewId(): global Registry trialKey = len(Registry) diff --git a/util/Config.py b/util/Config.py index 25018a8..962aa25 100644 --- a/util/Config.py +++ b/util/Config.py @@ -26,8 +26,8 @@ def loadConfigFile(fileName): #TODO: error handling etc. resolveDocumentInheritances(config.getroot()) return config except Exception as inst: - main_log.error('Error loading config file ' + fileName)#, inst) TODO: log exception too - main_log.error(str(inst)) + main_log.info('Error loading config file ' + fileName)#, inst) TODO: log exception too + main_log.info(str(inst)) return None def getElement(el): """Takes an Element or an ElementTree. If it is a tree, it returns its root. Otherwise, just returns @@ -89,7 +89,7 @@ def fileToDict(fileName): for line in f: fileText += line.rstrip('\n').lstrip('\t') + ' ' except IOError: - exception_log.exception('Failure reading ' + fileName) + main_log.info('Failure reading ' + fileName) return {} if fileText == '': return {} @@ -98,7 +98,7 @@ def fileToDict(fileName): main_log.info(fileName + ' read and parsed') return resultDict except: - exception_log.info(fileName + ' is not a well formed python dict. Parsing failed') + main_log.exception(fileName + ' is not a well formed python dict. Parsing failed') return eval(fileText) def pullArgsFromItem(parentNode): |