Better docs
This commit is contained in:
parent
356755c486
commit
cd93efa04f
12 changed files with 560 additions and 29 deletions
|
|
@ -9,7 +9,7 @@ BOOM | WIIIIIZ :: PHHHHHRACKRACKRACK ~~ WOOP ~~###~~ WIIT
|
|||
|
||||
## The basic loop
|
||||
```
|
||||
python3 generators/dummy.py -f 2 | python3 filters/kaleidoscope.py | python3 exports/toRedis.py -v
|
||||
python3 generators/dummy.py -f 2 | python3 filters/kaleidoscope.py | python3 exports/tonano.py -v
|
||||
------------------------------ --------------------- -------------------
|
||||
\/ \/ \/
|
||||
Generator Filter Export
|
||||
|
|
@ -55,7 +55,11 @@ These do listen and read on STDIN and do the same print'n'flush on STDOUT.
|
|||
|
||||
### Export
|
||||
|
||||
Read from STDIN and send to redis mostly
|
||||
Read from STDIN and send to LJnano.
|
||||
|
||||
* tonano.py
|
||||
|
||||
When your chain is ready and tested with LJnano going with real lasers needs LJ running and you simply change the export with :
|
||||
|
||||
* toRedis.py : provide a key, server IP, etc.
|
||||
|
||||
|
|
|
|||
BIN
clitools/exports/.DS_Store
vendored
BIN
clitools/exports/.DS_Store
vendored
Binary file not shown.
|
|
@ -26,7 +26,7 @@ import time
|
|||
argsparser = argparse.ArgumentParser(description="Redis exporter LJ")
|
||||
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
|
||||
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
|
||||
argsparser.add_argument("-k","--key",help="Redis key to update",default="0",type=str)
|
||||
argsparser.add_argument("-k","--key",help="Redis key to update",default="/pl/0/0",type=str)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,20 @@
|
|||
|
||||
'''
|
||||
tonano
|
||||
input space for X & Y : -1500,+1500
|
||||
exporter to LJ nano
|
||||
v0.1b
|
||||
|
||||
a la place de ast.literal_eval(line) : ?
|
||||
|
||||
>>> a = "[[111.121, 45.8783, 0.0],[110.936, 44.8368, 0.0],[374.849, 673.228, 230.536]]"
|
||||
>>> import json
|
||||
>>> b = json.loads(a)
|
||||
>>> b
|
||||
[[111.121, 45.8783, 0.0], [110.936, 44.8368, 0.0], [374.849, 673.228, 230.536]]
|
||||
>>> b[0]
|
||||
[111.121, 45.8783, 0.0]
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import websocket
|
||||
|
|
@ -17,6 +28,7 @@ import sys
|
|||
import random
|
||||
from websocket_server import WebsocketServer
|
||||
from socket import *
|
||||
#import ast
|
||||
|
||||
try:
|
||||
import thread
|
||||
|
|
@ -35,7 +47,8 @@ argsparser = argparse.ArgumentParser(description="tonano v0.1b help mode")
|
|||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-s","--server",help="WS server IP (127.0.0.1 by default)", type=str)
|
||||
argsparser.add_argument("-p","--port",help="WS port to bind to (9001 by default)", type=str)
|
||||
argsparser.add_argument("-k","--key",help="Redis key to update",default="0",type=str)
|
||||
argsparser.add_argument("-k","--key",help="Redis key to update",default="/pl/0/0",type=str)
|
||||
argsparser.add_argument("-o","--old",help="Coordinates in old school 0-800 space",action="store_true")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
key = args.key
|
||||
|
|
@ -55,6 +68,15 @@ if args.port:
|
|||
else:
|
||||
wsPORT = 9001
|
||||
|
||||
if args.old:
|
||||
inspace = [0,800]
|
||||
else:
|
||||
inspace = [-1500,1500]
|
||||
|
||||
|
||||
outspace = [-1500,1500]
|
||||
zoom = (outspace[1]-outspace[0])/(inspace[1]-inspace[0])
|
||||
|
||||
debug("")
|
||||
debug("tonano v0.1b")
|
||||
|
||||
|
|
@ -74,7 +96,7 @@ def sendbroadcast():
|
|||
cs = socket(AF_INET, SOCK_DGRAM)
|
||||
cs.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||
cs.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
cs.sendto("LJ tonano 0.1".encode(), ("255.255.255.255", 54545))
|
||||
cs.sendto("LJ tonano v0.1".encode(), ("255.255.255.255", 54545))
|
||||
|
||||
|
||||
#
|
||||
|
|
@ -109,10 +131,18 @@ def on_open(ws):
|
|||
line = line.replace("]",')')
|
||||
#debug(line)
|
||||
line = "[{}]".format(line)
|
||||
|
||||
if zoom != 1.0:
|
||||
shape = []
|
||||
pointsList = ast.literal_eval(line)
|
||||
for point in pointsList:
|
||||
shape.append(((point[0]*zoom)+outspace[0],(point[1]*zoom)+outspace[0], point[2]))
|
||||
line = str(shape)
|
||||
|
||||
debug("CLI proccess sending : /simul" +" "+ line)
|
||||
#sendWSall("/simul" +" "+ str(points[laserid].decode('ascii')))
|
||||
ws.send("/simul "+line)
|
||||
#debug("exports::tosimuCLIent "+str(key)+" "+line)
|
||||
|
||||
|
||||
except EOFError:
|
||||
debug("tonano break")# no more information
|
||||
|
|
|
|||
BIN
clitools/filters/.DS_Store
vendored
BIN
clitools/filters/.DS_Store
vendored
Binary file not shown.
BIN
clitools/generators/.DS_Store
vendored
BIN
clitools/generators/.DS_Store
vendored
Binary file not shown.
359
clitools/generators/fromildb.py
Normal file
359
clitools/generators/fromildb.py
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromild
|
||||
v0.1.0
|
||||
|
||||
Read/display once an .ild animation file and quit ??
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
Heavy u-se of :
|
||||
|
||||
ILDA.py
|
||||
|
||||
Python module for dealing with the ILDA Image Data Transfer Format,
|
||||
an interchange format for laser image frames.
|
||||
|
||||
Copyright (c) 2008 Micah Dowty
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import struct
|
||||
import argparse
|
||||
import sys
|
||||
import random
|
||||
|
||||
name="generator::fromild"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description=".ild file frame generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-i","--ild",help=".ild file",default="book2.ild",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
# Format codes
|
||||
FORMAT_3D = 0
|
||||
FORMAT_2D = 1
|
||||
FORMAT_COLOR_TABLE = 2
|
||||
|
||||
# Mapping from FORMAT_* codes to struct format strings
|
||||
formatTable = (
|
||||
'>hhhH',
|
||||
'>hhH',
|
||||
'>BBB',
|
||||
)
|
||||
|
||||
# Header values
|
||||
HEADER_MAGIC = b"ILDA\0\0\0"
|
||||
HEADER_RESERVED = 0
|
||||
HEADER_FORMAT = ">7sB16sHHHBB"
|
||||
HEADER_LEN = struct.calcsize(HEADER_FORMAT)
|
||||
|
||||
|
||||
class Table(object):
|
||||
"""Container object for one ILDA table: either a frame (table of points)
|
||||
or a palette (table of colors).
|
||||
|
||||
The 'items' list contains the data within this table. Each item
|
||||
is a tuple, corresponding to the raw values within that row of the
|
||||
table.
|
||||
|
||||
2D frame: (x, y, status)
|
||||
3D frame: (x, y, z, status)
|
||||
Color: (r, g, b)
|
||||
|
||||
"""
|
||||
def __init__(self, format=FORMAT_2D, name="",
|
||||
length=0, number=0, total=0, scanHead=0):
|
||||
self.__dict__.update(locals())
|
||||
self.items = []
|
||||
self.itemsproducer = None
|
||||
|
||||
def __repr__(self):
|
||||
return ("<ILDA.Table format=%d name=%r "
|
||||
"length=%d number=%d total=%d scanHead=%d>" %
|
||||
(self.format, self.name, self.length, self.number,
|
||||
self.total, self.scanHead))
|
||||
|
||||
def unpackHeader(self, data):
|
||||
magic, self.format, self.name, self.length, \
|
||||
self.number, self.total, self.scanHead, \
|
||||
reserved = struct.unpack(HEADER_FORMAT, data)
|
||||
print(magic, HEADER_MAGIC)
|
||||
if magic != HEADER_MAGIC:
|
||||
raise ValueError("Bad ILDA header magic. Not an ILDA file?")
|
||||
if reserved != HEADER_RESERVED:
|
||||
raise ValueError("Reserved ILDA field is not zero.")
|
||||
|
||||
def packHeader(self):
|
||||
return struct.pack(HEADER_FORMAT, HEADER_MAGIC, self.format,
|
||||
self.name, self.length, self.number,
|
||||
self.total, self.scanHead, HEADER_RESERVED)
|
||||
|
||||
def readHeader(self, stream):
|
||||
self.unpackHeader(stream.read(HEADER_LEN))
|
||||
|
||||
def writeHeader(self, stream):
|
||||
stream.write(self.packHeader())
|
||||
|
||||
def _getItemFormat(self):
|
||||
try:
|
||||
return formatTable[self.format]
|
||||
except IndexError:
|
||||
raise ValueError("Unsupported format code")
|
||||
|
||||
def read_stream(self, stream):
|
||||
"""Read the header, then read all items in this table."""
|
||||
self.readHeader(stream)
|
||||
if self.length:
|
||||
fmt = self._getItemFormat()
|
||||
itemSize = struct.calcsize(fmt)
|
||||
self.items = [struct.unpack(fmt, stream.read(itemSize))
|
||||
for i in range(self.length)]
|
||||
self.itemsproducer = self.produce()
|
||||
|
||||
def write(self, stream):
|
||||
"""Write the header, then write all items in this table."""
|
||||
self.writeHeader(stream)
|
||||
if self.length:
|
||||
fmt = self._getItemFormat()
|
||||
itemSize = struct.calcsize(fmt)
|
||||
stream.write(''.join([struct.pack(fmt, *item)
|
||||
for item in self.items]))
|
||||
|
||||
def iterPoints(self):
|
||||
"""Iterate over Point instances for each item in this table.
|
||||
Only makes sense if this is a 2D or 3D point table.
|
||||
"""
|
||||
for item in self.items:
|
||||
p = Point()
|
||||
p.decode(item)
|
||||
yield p
|
||||
|
||||
|
||||
def produce(self):
|
||||
"""Iterate over Point instances for each item in this table.
|
||||
Only makes sense if this is a 2D or 3D point table.
|
||||
"""
|
||||
while True:
|
||||
for item in self.items:
|
||||
p = Point()
|
||||
p.decode(item)
|
||||
yield p.encode()
|
||||
#yield (p.x, p.y, p.z, p.color, p.blanking)
|
||||
|
||||
def read(self, cap):
|
||||
"""yields what dac.play_stream() needs (x, y, z, ?, ?)
|
||||
"""
|
||||
return [next(self.itemsproducer) for i in range(cap)]
|
||||
|
||||
|
||||
class Point:
|
||||
"""Abstraction for one vector point. The Table object, for
|
||||
completeness and efficiency, stores raw tuples for each
|
||||
point. This is a higher level interface that decodes the status
|
||||
bits and represents coordinates in floating point.
|
||||
"""
|
||||
def __init__(self, x=0.0, y=0.0, z=0.0, color=0, blanking=False):
|
||||
self.__dict__.update(locals())
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
return "%s, %s, %s, %s, %s" % (
|
||||
self.x, self.y, self.z, self.color, self.blanking)
|
||||
#return "<ILDA.Point (%s, %s, %s) color=%s blanking=%s>" % (
|
||||
# self.x, self.y, self.z, self.color, self.blanking)
|
||||
|
||||
def encode(self):
|
||||
status = self.color & 0xFF
|
||||
if self.blanking:
|
||||
status |= 1 << 14
|
||||
|
||||
return (
|
||||
int( min(0x7FFF, max(-0x7FFF, self.x * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.y * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.z * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.color * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.blanking * 0x7FFF)) )
|
||||
)
|
||||
|
||||
def decode(self, t):
|
||||
#print "~~ Decoding, t of len "+ str(len(t)) +" is: " + str(t)
|
||||
self.x = t[0] / 0x7FFF
|
||||
self.y = t[1] / 0x7FFF
|
||||
if len(t) > 3:
|
||||
self.z = t[2] / 0x7FFF
|
||||
# self.color = t[3] & 0xFF
|
||||
# self.blanking = (t[3] & (1 << 14)) != 0
|
||||
else:
|
||||
self.z = 0.0
|
||||
|
||||
self.color = t[-1] & 0xFF
|
||||
self.blanking = (t[-1] & (1 << 14)) != 0
|
||||
|
||||
|
||||
def read(stream):
|
||||
"""Read ILDA data from a stream until we hit the
|
||||
end-of-stream marker. Yields a sequence of Table objects.
|
||||
"""
|
||||
while True:
|
||||
t = Table()
|
||||
t.read_stream(stream)
|
||||
if not t.length:
|
||||
# End-of-stream
|
||||
break
|
||||
yield t
|
||||
|
||||
|
||||
def write(stream, tables):
|
||||
"""Write a sequence of tables in ILDA format,
|
||||
terminated by an end-of-stream marker.
|
||||
"""
|
||||
for t in tables:
|
||||
t.write(stream)
|
||||
Table().write(stream)
|
||||
|
||||
|
||||
def readFrames(stream):
|
||||
"""Read ILDA data from a stream, and ignore
|
||||
all non-frame tables. Yields only 2D or 3D
|
||||
point tables.
|
||||
"""
|
||||
for t in read(stream):
|
||||
if t.format in (FORMAT_2D, FORMAT_3D):
|
||||
yield t
|
||||
|
||||
|
||||
def readFirstFrame(stream):
|
||||
"""Read only a single frame from an ILDA stream."""
|
||||
for frame in readFrames(stream):
|
||||
return frame
|
||||
|
||||
'''
|
||||
|
||||
#LD = LaserDisplay()
|
||||
LD = LaserDisplay({"server":"localhost","port": 50000})
|
||||
LD.set_scan_rate(37000)
|
||||
LD.set_blanking_delay(0)
|
||||
'''
|
||||
|
||||
WIDTH=700
|
||||
HEIGHT=700
|
||||
|
||||
ilda_file = open(args.ild, 'rb')
|
||||
ilda_frames = readFrames(ilda_file)
|
||||
|
||||
frames = []
|
||||
|
||||
for myframe in ilda_frames:
|
||||
frame = []
|
||||
debug("Frame", myframe.number, "/",myframe.total, "length", myframe.length)
|
||||
for mypoint in myframe.iterPoints():
|
||||
frame.append([WIDTH/2 + (WIDTH/2)*mypoint.x, HEIGHT/2 + (HEIGHT/2)*mypoint.y])
|
||||
#debug(frame)
|
||||
frames.append(frame)
|
||||
if myframe.number +1 == myframe.total:
|
||||
debug("last frame", myframe.number, myframe.total)
|
||||
break
|
||||
|
||||
|
||||
ilda_file.close()
|
||||
debug(len(frames))
|
||||
#debug(frame)
|
||||
#LD.set_color(YELLOW)
|
||||
'''
|
||||
for frame in frames:
|
||||
for _ in range(2):
|
||||
shape =[]
|
||||
for point in frame:
|
||||
#LD.set_color(p.color)
|
||||
if random.random()<=0.5:
|
||||
shape.append([point[0], point[1],0])
|
||||
#debug(shape)
|
||||
#shape =[]
|
||||
'''
|
||||
'''
|
||||
while True:
|
||||
LD.messageBuffer = m
|
||||
LD.show_frame()
|
||||
|
||||
|
||||
|
||||
f = open(args.ild, 'rb')
|
||||
myframe = readFirstFrame(f)
|
||||
|
||||
while myframe.number +1< myframe.total:
|
||||
|
||||
start = time.time()
|
||||
shape =[]
|
||||
|
||||
if myframe is None:
|
||||
f.close()
|
||||
sys.exit() # does not quit ????
|
||||
|
||||
debug(name,"Frame", myframe.number, "/",myframe.total, "length", myframe.length)
|
||||
|
||||
for p in myframe.iterPoints():
|
||||
p2 = str(p)
|
||||
point = p2.split(',')
|
||||
|
||||
x = float(point[0])
|
||||
y = float(point[1])
|
||||
z = float(point[2])
|
||||
color = int(point[3])
|
||||
blanking = point[4][1:]
|
||||
|
||||
if blanking == "True":
|
||||
shape.append([300+(x*300),300+(-y*300),0])
|
||||
else:
|
||||
shape.append([300+(x*300),300+(-y*300),65535])
|
||||
|
||||
print(shape, flush=True);
|
||||
#debug(shape)
|
||||
myframe = readFirstFrame(f)
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
f.close()
|
||||
'''
|
||||
|
|
@ -32,6 +32,7 @@ from HersheyFonts import HersheyFonts
|
|||
|
||||
name="generator::text"
|
||||
|
||||
Position = [-1500,0]
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
|
|
@ -42,7 +43,7 @@ def debug(*args, **kwargs):
|
|||
argsparser = argparse.ArgumentParser(description="Text generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-t","--text",help="Text to display",default="hello",type=str)
|
||||
argsparser.add_argument("-t","--text",help="Text to display",default="proton",type=str)
|
||||
argsparser.add_argument("-p","--police",help="Herschey font to use",default="futural",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
|
|
@ -73,14 +74,18 @@ Allfonts = ['futural', 'astrology', 'cursive', 'cyrilc_1', 'cyrillic', 'futuram'
|
|||
thefont = HersheyFonts()
|
||||
#thefont.load_default_font()
|
||||
thefont.load_default_font(fontname)
|
||||
thefont.normalize_rendering(120)
|
||||
thefont.normalize_rendering(300)
|
||||
|
||||
for (x1, y1), (x2, y2) in thefont.lines_for_text(text):
|
||||
shape.append([x1, -y1+400, color])
|
||||
shape.append([x2 ,-y2+400, color])
|
||||
|
||||
shape.append([Position[0]+x1, Position[1]-y1, color])
|
||||
shape.append([Position[0]+x2, Position[1]-y2, color])
|
||||
'''
|
||||
shape.append([x1+ScreenX[0]+Position[0], -y1+ScreenY[0]+Position[1], color])
|
||||
shape.append([x2+ScreenX[0]+Position[0] ,-y2+ScreenY[0]+Position[1], color])
|
||||
'''
|
||||
while True:
|
||||
|
||||
debug(shape)
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue