#!/usr/bin/python2.7 # -*- coding: utf-8 -*- # -*- mode: Python -*- ''' LJay/LJ v0.8.0 tracer.py (was newdacp.py) Enhanced version (support for several lasers) of the etherdream python library from j4cDAC. LICENCE : CC Sam Neurohack, pclf Conversion in etherdream coordinates, geometric corrections,... Init call with a laser number and which point list to draw. Etherdream IP is found in conf file for given laser number Uses redis keys value for live inputs/outputs These redis keys are read and set at each main loop. Redis keys pulled to draw things : /order select some change to adjust /pl/lasernumber [(x,y,color),(x1,y1,color),...] A string of list of pygame points list. /resampler/lasernumber [(1.0,8), (0.25,3),(0.75,3),(1.0,10)] : a string for resampling rules. the first tuple (1.0,8) is for short line < 4000 in etherdream space (0.25,3),(0.75,3),(1.0,10) for long line > 4000 i.e (0.25,3) means go at 25% position on the line, send 3 times this position to etherdream Etherdream status reports in redis keys: /lstt/lasernumber value etherdream last_status.playback_state (0: idle 1: prepare 2: playing) /cap/lasernumber value number of empty points sent to fill etherdream buffer (up to 1799) /lack/lasernumber value "a": ACK "F": Full "I": invalid. 64 or 35 for no connection. Geometric corrections : Doctodo ''' import socket import time import struct #from gstt import debug import gstt import math from itertools import cycle #from globalVars import * import pdb import ast import redis import homographyp import numpy as np black_points = [(278.0,225.0,0),(562.0,279.0,0),(401.0,375.0,0),(296.0,454.0,0),(298.0,165.0,0)] grid_points = [(300.0,200.0,0),(500.0,200.0,65280),(500.0,400.0,65280),(300.0,400.0,65280),(300.0,200.0,65280),(300.0,200.0,0),(200.0,100.0,0),(600.0,100.0,65280),(600.0,500.0,65280),(200.0,500.0,65280),(200.0,100.0,65280)] r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0) def pack_point(x, y, r, g, b, i = -1, u1 = 0, u2 = 0, flags = 0): """Pack some color values into a struct dac_point. Values must be specified for x, y, r, g, and b. If a value is not passed in for the other fields, i will default to max(r, g, b); the rest default to zero. """ if i < 0: i = max(r, g, b) return struct.pack("> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8 #print '' return (position[0][0], position[0][1], ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8) def read(self, l): """Read exactly length bytes from the connection.""" while l > len(self.buf): self.buf += self.conn.recv(4096) obuf = self.buf self.buf = obuf[l:] return obuf[:l] def readresp(self, cmd): """Read a response from the DAC.""" data = self.read(22) response = data[0] #print "laser response", self.mylaser, response gstt.lstt_dacanswers[self.mylaser] = response cmdR = data[1] status = Status(data[2:]) r.set('/lack/'+str(self.mylaser), response) if cmdR != cmd: raise ProtocolError("expected resp for %r, got %r" % (cmd, cmdR)) if response != "a": raise ProtocolError("expected ACK, got %r" % (response, )) self.last_status = status return status def __init__(self, mylaser, PL, port = 7765): """Connect to the DAC over TCP.""" socket.setdefaulttimeout(2) #print "init" self.mylaser = mylaser self.clientkey = r.get("/clientkey") #print "Laser",self.mylaser,"Got clientkey", self.clientkey #print "DAC", self.mylaser, "Handler process, connecting to", gstt.lasersIPS[mylaser] self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.connstatus = self.conn.connect_ex((gstt.lasersIPS[mylaser], port)) #print "Connection status for", self.mylaser,":", self.connstatus # ipconn state is -1 at startup (see gstt) and modified here r.set('/lack/'+str(self.mylaser), self.connstatus) gstt.lstt_ipconn[self.mylaser] = self.connstatus self.buf = "" # Upper case PL is the Point List number self.PL = PL # Lower case pl is the actual point list coordinates self.pl = ast.literal_eval(r.get(self.clientkey + str(self.mylaser))) if r.get('/EDH/'+str(self.mylaser)) == None: #print "Laser",self.mylaser,"NO EDH !! Computing one..." homographyp.newEDH(self.mylaser) else: gstt.EDH[self.mylaser] = np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser)))) #print "Laser",self.mylaser,"found its EDH in redis" #print gstt.EDH[self.mylaser] self.xyrgb = self.xyrgb_prev = (0,0,0,0,0) self.newstream = self.OnePoint() if gstt.debug >0: print "Init laser",self.mylaser,"asked for ckey", self.clientkey+str(self.mylaser) if self.connstatus != 0: #print "" print "Connection ERROR",self.connstatus,"with laser", str(mylaser),":",str(gstt.lasersIPS[mylaser]) #print "first 10 points in PL",self.PL, self.GetPoints(10) else: print "Connection status for", self.mylaser,":", self.connstatus # Reference points # Read the "hello" message first_status = self.readresp("?") first_status.dump() position = [] def begin(self, lwm, rate): cmd = struct.pack("