def signal_handler(signal, frame): print('\nexiting...') if DMX: DMX.exit() if Arms: Arms.exit() if Prinboo: Prinboo.exit() if Video: Video.exit() exit()
def modAngle(self, type, inc): dim = self.ServoDims[type] for id in self.selected(): try: a = Arms.getAngle(id, dim) except IndexError: return angle = Arms.fitServoRange(a) Arms.setAngle(id, dim, angle + inc)
def run(self, immediate=False): #try: # load the file again in case it has changed since the cuesheet was loading self.load() timestep = .05 printPeriodPeriod = .25 printPeriodTimestepCount = printPeriodPeriod / timestep # Light Arms - may be absent # TODO fade light arms! try: if self.armData: Arms.load(self.armData) except: pass # DMX if self.targetDMX: target = self.targetDMX current = DMX.get() vel = [0] * len(current) # calculate delta for each timestep # -1 means don't change for i in range(len(target)): if target[i] >= 0: vel[i] = (target[i] - current[i]) * (timestep / self.period) print(' fading for', self.period, 'seconds..', end='', flush=True) startTime = time.time() endTime = startTime + self.period nextTime = startTime + timestep nextPrintTime = startTime + printPeriodPeriod while 1: # calculate new channel values and transmit for i in range(len(current)): current[i] += vel[i] channels = [round(x) for x in current] DMX.setAndSend(0, channels) now = time.time() # print a period every so often if now >= nextPrintTime: print('.', end='', flush=True) nextPrintTime += printPeriodPeriod if now > endTime: break nexTime += timestep time.sleep(nextTime - time.time()) # make sure we arrive at the target numbers, as rounding error may creep in DMX.setAndSend(0, target) print('DONE')
def run(self, immediate=False): # load the file again in case it has changed since the cuesheet was loading self.load() if self.targetDMX: DMX.setAndSend(0, self.targetDMX) # Light Arms - may be absent try: if self.armData: Arms.load(self.armData) except: pass
def run(self, immediate=False): # load the file again in case it has changed since the cuesheet was loading self.load() if self.targetDMX: DMX.setAndSend(0, self.targetDMX) if self.limbs: #TODO figure out if we have a pose or an animation Prinboo.limbs.setAngle(self.limbs) if self.armData: Arms.load(self.armData)
def handleChar(self, ch): ch = ch.lower() if ch == 'x': self.toggleMode() if ch == 'q': for id in self.selected(): Arms.relax(id) if ch == '0': pass #Arms.setAngles(self.selected(), [Arms.ServoCenter] * len(self.ServoDims)) elif ch == 'w': self.modAngle('y', self.inc()) elif ch == 's': self.modAngle('y', -self.inc()) elif ch == 'a': self.modAngle('x', self.inc()) elif ch == 'd': self.modAngle('x', -self.inc()) elif ch == 'r': self.modI(self.inc(), 0 + self.iyCursor*3) elif ch == 'f': self.modI(-self.inc(), 0 + self.iyCursor*3) elif ch == 't': self.modI(self.inc(), 1 + self.iyCursor*3) elif ch == 'g': self.modI(-self.inc(), 1 + self.iyCursor*3) elif ch == 'y': self.modI(self.inc(), 2 + self.iyCursor*3) elif ch == 'h': self.modI(-self.inc(), 2 + self.iyCursor*3) elif ch == '<' or ch == ',': self.inc.prev() elif ch == '>' or ch == '.': self.inc.next() elif ch == '\x1b': seq = getch() + getch() if seq == '[C': # left arrow if self.inSingleMode(): self.ixCursor += 1 else: self.ixCursor = self.ixCursor - self.ixCursor % self.PageWidth + self.PageWidth self.ixCursor = min(self.numArms()-1, self.ixCursor) elif seq == '[D': # right arrow if self.inSingleMode(): self.ixCursor -= 1 else: self.ixCursor = self.ixCursor - self.ixCursor % self.PageWidth - self.PageWidth self.ixCursor = max(0, self.ixCursor) elif seq == '[A': #pass # up arrow self.iyCursor = max(0, self.iyCursor - 1) elif seq == '[B': #pass # down arrow self.iyCursor = min(self.VerticalGroups - 1, self.iyCursor + 1) print(self.iyCursor)
def display(self): clearScreen() numArms = self.PageWidth #self.numArms() def printHSep(firstColBlank=True): if firstColBlank: print(' |', end='') else: print('---|', end='') if self.inSingleMode(): for i in range(numArms): if i == self.ixCursor: print('===|', end='') else: print('---|', end='') else: for i in range(numArms): if self.inGroup(i): if self.inGroup(i+1, i): print('====', end='') else: print('===|', end='') else: print('---|', end='') print('') def printAngle(dim, index): try: angle = self.getAngle(dim, index) if angle < 1: print('XXX|', end='') else: print('{0:^3}|'.format(angle), end='') except: print('---|', end='') print(' Light Arm View') printHSep(False) print('x: |', end='') for i in range(numArms): printAngle('x', i) print('') printHSep() print('y: |', end='') for i in range(numArms): printAngle('y', i) print('') printHSep() names = '' for i in range(self.VerticalGroups): if i == self.iyCursor: names += 'BGR' else: names += 'bgr' for channel in range(Arms.MaxChannels): print(names[channel] + ': |', end='') for i in range(numArms): try: print('{0:^3}|'.format(Arms.getChannel(i, channel)), end='') except: print('---|', end='') print('') printHSep(channel+1 != Arms.MaxChannels)
def __init__(self): super().__init__() self.VerticalGroups = int(Arms.MaxChannels / 3) print(self.VerticalGroups) self.PageWidth = min(Arms.num(), 32) self.mode = 1 # index into self.Modes self.ixCursor = 0 self.iyCursor = 0 self.inc = LinearStateMachine([1, 5, 20])
def __init__(self, duration, timestep, armData): self.armData = armData self.target = [] self.current = [] self.vel = [] # map each address to an index for address, arm in self.armData.items(): i = Arms.arms.index(Arms.findArm(address)) self.target.append(arm.get('channels', [])) for i in range(Arms.num()): self.current.append(Arms.getChannels(i)) # calculate delta for each timestep # -1 means don't change for i in range(len(self.target)): self.vel.append([]) for j in range(len(self.target[i])): if self.target[i][j] >= 0: self.vel[i].append((self.target[i][j] - self.current[i][j]) * (timestep / duration)) else: self.vel[i].append(0)
def modI(self, inc, channel): #print('ids:', self.selected()) for id in self.selected(): try: v = Arms.getChannel(id, channel) except IndexError: return Arms.setChannel(id, channel, Arms.fitChannelRange(v + inc))
def getAngle(self, type, index=None): if index is None: index = self.ixCursor dim = self.ServoDims[type] return Arms.getAngle(index, dim)
def numArms(self): return Arms.num() # returns a list of the selected arms' indices def selected(self):
except ImportError: Video = None print('No Video') try: from lightarm import Arms except ImportError: Arms = None print('No LightArms') try: from dmx import DMX except KeyError: DMX = None print('No DMX') # call initialize outside of try-except to show errors to user if Arms: Arms.initialize(config) if DMX: DMX.initialize(config) if Video: Video.initialize(config) print("\n\n") # these functions define the min and max values for robot spotlight parameters #def fitServoRange(v): return max(212, min(812, v)) #def fitChannelRange(v): return max(0, min(MaxPWM, v)) def restAfterWord(word, line): return line[line.find(word) + len(word):].strip() class LinearStateMachine: """A faux iterator on an ordered list that can move forward or backward and clamps at the ends. There is probably a more Pythonic way to do this."""
def finish(self): # make sure we arrive at the target numbers, as rounding error may creep in Arms.load(self.armData)
def step(self): # calculate new channel values and transmit for i in range(len(self.current)): self.current[i] = [a+b for a,b in zip(self.current[i], self.vel[i])] Arms.setChannels(i, self.current[i])