Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
03b6ad7
Add Shutdown Handler
sterlinghirsh Oct 25, 2020
a9f3d24
Merge pull request #1 from sterlinghirsh/add-shutdown-handler
sterlinghirsh Oct 25, 2020
93b74f1
Add isSupported() to Device class
sterlinghirsh Oct 30, 2020
0d3c3d9
Add device-selector: auto-select a DAC + Simulator
sterlinghirsh Oct 30, 2020
1908354
Use device-selector instead of hard-coding devices
sterlinghirsh Oct 30, 2020
bbce90f
Balls: update example for device-selector
sterlinghirsh Oct 30, 2020
5a82d8f
Use device-selector in remaining examples
sterlinghirsh Oct 30, 2020
db9aee5
Merge pull request #2 from sterlinghirsh/add-device-selector
sterlinghirsh Oct 30, 2020
2928d17
Ilda: clarify types around Point
sterlinghirsh Oct 31, 2020
8a7b840
Clamp points as final step in Scene
sterlinghirsh Nov 1, 2020
85fc85b
Merge pull request #3 from sterlinghirsh/clamp-points
sterlinghirsh Nov 1, 2020
b3b1535
Helios: fix resolution
sterlinghirsh Nov 1, 2020
e2ab78a
Helios: flip Y but not X
sterlinghirsh Nov 1, 2020
3680e63
Merge pull request #4 from sterlinghirsh/fix-helios-resolution
sterlinghirsh Nov 1, 2020
6744dbe
Balls: bounce off the walls properly
sterlinghirsh Nov 2, 2020
682191d
Balls: Make animation time-based
sterlinghirsh Nov 2, 2020
8bcc2b1
Balls: use Circles instead of Rects
sterlinghirsh Nov 2, 2020
d8d1ed9
Merge pull request #5 from sterlinghirsh/improve-balls
sterlinghirsh Nov 2, 2020
5f591a7
Add transformer to convert all points to monochrome
sterlinghirsh Nov 4, 2020
7fb1a14
Merge pull request #6 from sterlinghirsh/monochrome
sterlinghirsh Nov 10, 2020
0bfb012
Add makeTransformer() and use with clamp and monochrome
sterlinghirsh Nov 10, 2020
248dd65
Merge pull request #7 from sterlinghirsh/clamp--make-transformer
sterlinghirsh Nov 10, 2020
b9ed76b
Helios: fix convertPoint declaration
sterlinghirsh Nov 4, 2020
9accea2
Helios: extract sendFrame function from stream
sterlinghirsh Nov 10, 2020
4f2187d
Helios: start tracking stats
sterlinghirsh Nov 10, 2020
eef5a13
Track some more stats
sterlinghirsh Nov 10, 2020
b49c98a
Helios: add FrameMode enum
sterlinghirsh Nov 18, 2020
83a87cb
Helios: use variable for dacNum
sterlinghirsh Nov 18, 2020
b3e9b87
Merge pull request #8 from sterlinghirsh/helios-rework-drawing
sterlinghirsh Nov 18, 2020
3af2928
Copy square interactive example to calibration
sterlinghirsh Nov 18, 2020
2f055d8
Calibration: start modifying example
sterlinghirsh Nov 28, 2020
35427cd
Calibration: update dac pointsrate in real time
sterlinghirsh Nov 28, 2020
e20649a
Calibration: add two-way communication
sterlinghirsh Nov 28, 2020
d16ecb7
Helios: replace stats.pps with pointsRate
sterlinghirsh Nov 28, 2020
e4475b9
Helios: Rework more stats
sterlinghirsh Nov 28, 2020
adb98b7
Helios: Drop printStats()
sterlinghirsh Nov 28, 2020
aed38f7
Calibration: make getStats() always return an Object for simplicity
sterlinghirsh Nov 30, 2020
0420a09
Calibration: start recording stats about frame content
sterlinghirsh Nov 30, 2020
da0ed6f
Calibration: omit initial jump from stats
sterlinghirsh Nov 30, 2020
02a1261
Calibration: live-update resolution
sterlinghirsh Dec 29, 2020
9956f8e
Drop unused RESOLUTION constant.
sterlinghirsh Jan 18, 2021
2d7faa3
Helios: Track stats no longer has ts undefined warning
sterlinghirsh Jan 18, 2021
a9c543f
Scene: store options in object
sterlinghirsh Jan 18, 2021
71c59a8
Shape: draw() accepts SceneOptions instead of resolution
sterlinghirsh Jan 19, 2021
80d940b
Replace values from constants.ts with SceneOptions
sterlinghirsh Jan 19, 2021
66e4ec8
Calibrate: allow changing blankingPoints and maxWaitPoints
sterlinghirsh Jan 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules/
dist/
*.log
*.swp
*.swo
29 changes: 16 additions & 13 deletions examples/balls/Ball.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Rect } from '@laser-dac/draw';
import { Circle } from '@laser-dac/draw';
import Victor = require('victor');

interface BallOptions {
Expand All @@ -12,8 +12,8 @@ export class Ball {
x: number;
y: number;
vector: Victor = new Victor(
(Math.random() - 0.5) / 200,
(Math.random() - 0.5) / 200
(Math.random() - 0.5) / 2,
(Math.random() - 0.5) / 2
);

constructor(options: BallOptions) {
Expand All @@ -22,41 +22,44 @@ export class Ball {
this.radius = options.radius;
}

update = () => {
this.x += this.vector.x;
this.y += this.vector.y;
update = (timeStep: number) => {
this.x += this.vector.x * timeStep;
this.y += this.vector.y * timeStep;

this.updateBounds();
};

updateBounds = () => {
// Left bound.
if (this.x - this.radius <= 0) {
this.x = this.radius;
this.vector.invertX();
}

// Right bound.
if (this.x + this.radius >= 1) {
if (this.x + this.radius > 1) {
this.x = 1 - this.radius;
this.vector.invertX();
}

// Top bound.
if (this.y - this.radius <= 0) {
this.y = this.radius;
this.vector.invertY();
}

// Bottom bound.
if (this.y + this.radius >= 1) {
if (this.y + this.radius > 1) {
this.y = 1 - this.radius;
this.vector.invertY();
}
};

draw = () =>
new Rect({
x: this.x - this.radius,
y: this.y - this.radius,
width: this.radius * 2,
height: this.radius * 2,
new Circle({
x: this.x,
y: this.y,
radius: this.radius,
color: [0, 1, 0]
});
}
19 changes: 10 additions & 9 deletions examples/balls/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { DAC } from '@laser-dac/core';
import { Simulator } from '@laser-dac/simulator';
import { EtherDream } from '@laser-dac/ether-dream';
import { getDevices } from '@laser-dac/device-selector';
import { Scene, Rect } from '@laser-dac/draw';
import { Ball } from './Ball';

const NUMBER_OF_BALLS = 4;

(async () => {
const dac = new DAC();
dac.use(new Simulator());
if (process.env.DEVICE) {
dac.use(new EtherDream());
}
dac.useAll(await getDevices());
await dac.start();

const balls: Ball[] = [];
for (let i = 0; i < NUMBER_OF_BALLS; i++) {
balls.push(
new Ball({
x: 0.5,
y: 0.5,
x: Math.random(),
y: Math.random(),
radius: Math.random() / 5 + 0.05
})
);
Expand All @@ -28,6 +24,8 @@ const NUMBER_OF_BALLS = 4;
const scene = new Scene({
resolution: 70
});

let lastTime = Date.now();
function renderFrame() {
const bounds = new Rect({
x: 0,
Expand All @@ -38,10 +36,13 @@ const NUMBER_OF_BALLS = 4;
});
scene.add(bounds);

const curTime = Date.now();
const timeStep = (curTime - lastTime) / 1000;
balls.forEach(ball => {
ball.update();
ball.update(timeStep);
scene.add(ball.draw());
});
lastTime = curTime;
}

scene.start(renderFrame);
Expand Down
54 changes: 54 additions & 0 deletions examples/calibration/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as express from 'express';
import { Server as WebSocketServer } from 'ws';
import * as http from 'http';
import * as path from 'path';
import { Renderer } from './renderer';

const PORT = 8321;

const renderer = new Renderer();

const server = http.createServer();
const app = express();
app.use(express.static(path.join(__dirname, '/public')));
const wss = new WebSocketServer({ server });

server.on('request', app);
server.listen(PORT, function() {
console.log(`Started Square Interactive demo on http://localhost:${PORT}`);
});

wss.on('connection', function connection(ws, req) {
const id = req.url!.replace('/?id=', '');

function send(type: string, data: any) {
ws.send(JSON.stringify({ type, data }));
}

function sendSettings() {
send("SettingsToClient", renderer.getParams());
}

function sendStats() {
send("stats", renderer.getStats());
};

const statsInterval = setInterval(sendStats, 300);
sendSettings();
sendStats();

ws.on('message', function incoming(message) {
// TODO: should handle illegal JSON so the server can't crash...
const payload = JSON.parse(message as string);
if (payload.type === 'UPDATEPARAMS') {
console.log('Updating Parameters', payload.data);
renderer.updateParams(payload.data);
} else {
console.log('Unknown websocket message', payload);
}
});

ws.on('close', function incoming(message) {
clearInterval(statsInterval);
});
});
19 changes: 19 additions & 0 deletions examples/calibration/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Laser Calibration</title>
<style>
</style>
</head>
<body>
<form id="calibration-form">
<label>PPS: <input id="pps" type="number" min="7" max="65535" value="" step="100"></label><br>
<label>Resolution: <input id="resolution" type="number" value="70"></label><br>
<label>Blanking Points: <input id="blankingPoints" type="number" min="0" max="100" value="24"></label><br>
<label>Max Wait Points: <input id="maxWaitPoints" type="number" min="0" max="50" value="10"></label><br>

</form>
<pre id="stats-table"></pre>
<script src="./index.js" type="module"></script>
</body>
</html>
62 changes: 62 additions & 0 deletions examples/calibration/public/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import WebsocketClient from './websocket.js';
import uuid from './uuid.js';

const host = window.document.location.host.replace(/:.*/, '');
const ws = new WebsocketClient();

const ppsInput = document.getElementById('pps');
const resolutionInput = document.getElementById('resolution');
const blankingPointsInput = document.getElementById('blankingPoints');
const maxWaitPointsInput = document.getElementById('maxWaitPoints');

const statsTable = document.getElementById('stats-table');

function sendMessage(msg) {
console.log("Sending:", msg.data);
ws.send(JSON.stringify(msg));
}

function sendFormValues() {
sendMessage({
type: 'UPDATEPARAMS',
data: {
pps: parseInt(ppsInput.value, 10),
resolution: parseInt(resolutionInput.value, 10),
blankingPoints: parseInt(blankingPointsInput.value, 10),
maxWaitPoints: parseInt(maxWaitPointsInput.value, 10)
}
});
}

ws.onopen = function() {
console.log('Websocket connection opened.');

ppsInput.addEventListener('input', sendFormValues);
resolutionInput.addEventListener('input', sendFormValues);
blankingPointsInput.addEventListener('input', sendFormValues);
maxWaitPointsInput.addEventListener('input', sendFormValues);
};

function displayStats(stats) {
statsTable.innerText = JSON.stringify(stats, null, 2);
}

function updateSettings(settings) {
ppsInput.value = settings.pps;
resolutionInput.value = settings.resolution;
blankingPointsInput.value = settings.blankingPoints;
maxWaitPointsInput.value = settings.maxWaitPoints;
}

ws.onmessage = function(ev) {
const message = JSON.parse(ev.data);
switch (message.type) {
case 'stats': displayStats(message.data); break;
case 'SettingsToClient': updateSettings(message.data); break;
default: console.error("Unknown message type: " + message.type, message)
}
};

const uniqueId = uuid();

ws.open(`ws://${host}:8321?id=${uniqueId}`);
24 changes: 24 additions & 0 deletions examples/calibration/public/uuid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function guid() {
return (
s4() +
s4() +
'-' +
s4() +
'-' +
s4() +
'-' +
s4() +
'-' +
s4() +
s4() +
s4()
);
}

function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}

export default guid;
62 changes: 62 additions & 0 deletions examples/calibration/public/websocket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function WebSocketClient() {
this.autoReconnectInterval = 1 * 1000; // ms
}
WebSocketClient.prototype.open = function(url) {
this.url = url;
this.instance = new WebSocket(this.url);
this.instance.onopen = this.onopen;
this.instance.onmessage = event => {
this.onmessage(event);
};
this.instance.onclose = e => {
switch (e.code) {
case 1000: // CLOSE_NORMAL
console.log('WebSocket: closed');
break;
default:
// Abnormal closure
this.reconnect(e);
break;
}
this.onclose(e);
};
this.instance.onerror = e => {
switch (e.code) {
case 'ECONNREFUSED':
this.reconnect(e);
break;
default:
this.onerror(e);
break;
}
};
};
WebSocketClient.prototype.send = function(data, option) {
try {
this.instance.send(data, option);
} catch (e) {
console.warn('Failed sending websocket msg', e);
}
};
WebSocketClient.prototype.reconnect = function(e) {
console.log(`WebSocketClient: retry in ${this.autoReconnectInterval}ms`, e);
var that = this;
setTimeout(function() {
console.log('WebSocketClient: reconnecting...');
that.open(that.url);
}, this.autoReconnectInterval);
};
WebSocketClient.prototype.onopen = function(e) {
console.log('WebSocketClient: open', arguments);
};
WebSocketClient.prototype.onmessage = function(e) {
console.log('WebSocketClient: message', arguments);
};
WebSocketClient.prototype.onerror = function(e) {
console.log('WebSocketClient: error', arguments);
};
WebSocketClient.prototype.onclose = function(e) {
console.log('WebSocketClient: closed', arguments);
};

export default WebSocketClient;
Loading