From fff51f78c8c6b466ff22de87a3bed4a307078119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Thu, 25 Jan 2018 13:03:38 -0800 Subject: [PATCH 01/11] implementing artnet --- LightWork_Mapper/Animator.pde | 2 +- LightWork_Mapper/Interface.pde | 54 ++++++++++++++++++++++++++-------- LightWork_Mapper/UI.pde | 11 +++---- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/LightWork_Mapper/Animator.pde b/LightWork_Mapper/Animator.pde index 8d4f1c7..03978bd 100644 --- a/LightWork_Mapper/Animator.pde +++ b/LightWork_Mapper/Animator.pde @@ -74,7 +74,7 @@ public class Animator { // Return pixels (to update OPC or PixelPusher) --Changed to array, arraylist wasn't working on return color[] getPixels() { - color[] l = new color[leds.size()]; + color[] l = new color[leds.size()]; //<>// for (int i = 0; i// +/* //<>// //<>// * LED * * This class handles connecting to and switching between PixelPusher, FadeCandy and ArtNet devices. @@ -19,6 +19,9 @@ import com.heroicrobot.dropbit.registry.*; import java.util.*; import java.io.*; +// ArtNet +import artnetP5.*; + enum device { FADECANDY, PIXELPUSHER, ARTNET, NULL }; @@ -30,18 +33,25 @@ public class Interface { //LED defaults String IP = "fade2.local"; int port = 7890; - int ledsPerStrip = 64; // TODO: DOn't hardcode this - int numStrips = 8; + int ledsPerStrip = 9; // TODO: DOn't hardcode this + int numStrips = 1; int numLeds = ledsPerStrip*numStrips; int ledBrightness; + + int numArtnetChannels = 5; // Channels per ArtNet fixture + int numArtnetFixtures = 9; // Number of ArtNet DMX fixtures (each one can have multiple channels and LEDs - //Pixelpusher objects + // Pixelpusher objects DeviceRegistry registry; TestObserver testObserver; - //Fadecandy Objects + // Fadecandy Objects OPC opc; + // ArtNet objects + ArtnetP5 artnet; + byte artnetPacket[]; + boolean isConnected =false; ////////////////////////////////////////////////////////////// @@ -136,6 +146,7 @@ public class Interface { IP = pp.getIp().toString(); numStrips = pp.getNumberOfStrips(); ledsPerStrip = pp.getPixelsPerStrip(); + numLeds = numStrips*ledsPerStrip; } } } @@ -153,10 +164,12 @@ public class Interface { // Create new LEDS println("Creating LED Array"); for (int i = 0; i < numLeds; i++) { - LED temp= new LED(); + LED temp = new LED(); leds.add(temp); leds.get(i).setAddress(i); } + + numLeds = leds.size(); } ////////////////////////////////////////////////////////////// @@ -200,6 +213,20 @@ public class Interface { case ARTNET: { + for (int i = 0; i < colors.length; i++) { //<>// + int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) + int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) + int b = colors[i] & 0xFF; // Faster way of getting blue(argb) + + int index = i*numArtnetChannels; + artnetPacket[index] = byte(r); // Red + artnetPacket[index+1] = byte(g); // Green + artnetPacket[index+2] = byte(b); // Blue + artnetPacket[index+3] = byte(0); // White + artnetPacket[index+4] = (byte(0)); // Unused channnel + } + + artnet.broadcast(artnetPacket); } case NULL: @@ -209,7 +236,7 @@ public class Interface { } void clearLeds() { - color[] col = new color[numLeds]; + color[] col = new color[numLeds]; //<>// for (color c : col) { c = color(0); } @@ -220,9 +247,7 @@ public class Interface { void connect(PApplet parent) { if (isConnected) { shutdown(); - } - - if (mode == device.FADECANDY) { + } else if (mode == device.FADECANDY) { if (opc== null || !opc.isConnected) { opc = new OPC(parent, IP, port); int startTime = millis(); @@ -262,9 +287,7 @@ public class Interface { opc.setPixelCount(numLeds); populateLeds(); } - } - - if (mode == device.PIXELPUSHER ) { + } else if (mode == device.PIXELPUSHER ) { // does not like being instantiated a second time if (registry == null) { registry = new DeviceRegistry(); @@ -305,6 +328,10 @@ public class Interface { registry.setLogging(false); populateLeds(); + } else if (mode == device.ARTNET) { + artnet = new ArtnetP5(); + isConnected = true; + artnetPacket = new byte[numArtnetChannels*numArtnetFixtures]; // Reusing numLeds to indicate the number of fixtures (even though } } @@ -321,6 +348,7 @@ public class Interface { isConnected = false; } if (mode==device.ARTNET) { + //artnet = null; } if (mode==device.NULL) { } diff --git a/LightWork_Mapper/UI.pde b/LightWork_Mapper/UI.pde index 118203d..927aec7 100644 --- a/LightWork_Mapper/UI.pde +++ b/LightWork_Mapper/UI.pde @@ -1,4 +1,4 @@ -/* //<>// +/* //<>// //<>// * UI * * This class builds the UI for the application @@ -145,7 +145,7 @@ void buildUI() { println("listing drivers"); //draw after text boxes so the dropdown overlaps properly - List driver = Arrays.asList("PixelPusher", "Fadecandy"); //"ArtNet" removed for now - throws errors + List driver = Arrays.asList("PixelPusher", "Fadecandy", "ArtNet"); //"ArtNet" removed for now - throws errors println("adding scrollable list for drivers"); cp5.addScrollableList("driver") .setPosition(0, 0) @@ -335,7 +335,7 @@ void buildUI() { .getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE, CENTER).setPadding(5, 5) ; - //Refresh connected cameras + // Refresh connected cameras println("cp5: adding refresh button"); cp5.addButton("refresh") .setPosition(int(buttonWidth*1.5)+uiSpacing, 0) @@ -343,6 +343,7 @@ void buildUI() { .setGroup("top") ; + println("Enumerating cameras"); String[] cams = enumerateCams(); // made last - enumerating cams will break the ui if done earlier in the sequence println("cp5: adding camera dropdown list"); @@ -401,7 +402,7 @@ void driver(int n) { cp5.get(Textfield.class, "strips").setVisible(false); println("network: PixelPusher"); } - if (label.equals("FADECANDY")) { + else if (label.equals("FADECANDY")) { if (network.isConnected) { network.shutdown(); cp5.get("connect").setCaptionLabel("Connect"); @@ -412,7 +413,7 @@ void driver(int n) { cp5.get(Textfield.class, "strips").setVisible(true); println("network: Fadecandy"); } - if (label.equals("ARTNET")) { + else if (label.equals("ARTNET")) { network.setMode(device.ARTNET); println("network: ArtNet"); } From 9c644f3eb789da6a4d3c3c037c7a5ac61195a78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Thu, 25 Jan 2018 14:22:28 -0800 Subject: [PATCH 02/11] sending hardcoded color values via artnet --- LightWork_Mapper/Animator.pde | 2 +- LightWork_Mapper/Interface.pde | 19 ++++++++++++------- LightWork_Mapper/LightWork_Mapper.pde | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/LightWork_Mapper/Animator.pde b/LightWork_Mapper/Animator.pde index 03978bd..c1b9645 100644 --- a/LightWork_Mapper/Animator.pde +++ b/LightWork_Mapper/Animator.pde @@ -1,4 +1,4 @@ -/* //<>// +/* * Animator * * This Class handles timing and generates the state and color of all connected LEDs diff --git a/LightWork_Mapper/Interface.pde b/LightWork_Mapper/Interface.pde index 396df10..edb4046 100644 --- a/LightWork_Mapper/Interface.pde +++ b/LightWork_Mapper/Interface.pde @@ -1,4 +1,4 @@ -/* //<>// //<>// +/* //<>// * LED * * This class handles connecting to and switching between PixelPusher, FadeCandy and ArtNet devices. @@ -213,10 +213,15 @@ public class Interface { case ARTNET: { - for (int i = 0; i < colors.length; i++) { //<>// - int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) - int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) - int b = colors[i] & 0xFF; // Faster way of getting blue(argb) + color cols[] = new int[9]; + for (int i = 0; i < cols.length; i++) { + cols[i] = color(254, 254, 254); + } + color c = color(254, 254, 254); + for (int i = 0; i < cols.length; i++) { + int r = (c >> 16) & 0xFF; // Faster way of getting red(argb) + int g = (c >> 8) & 0xFF; // Faster way of getting green(argb) + int b = c & 0xFF; // Faster way of getting blue(argb) int index = i*numArtnetChannels; artnetPacket[index] = byte(r); // Red @@ -226,7 +231,7 @@ public class Interface { artnetPacket[index+4] = (byte(0)); // Unused channnel } - artnet.broadcast(artnetPacket); + artnet.broadcast(artnetPacket); //<>// } case NULL: @@ -236,7 +241,7 @@ public class Interface { } void clearLeds() { - color[] col = new color[numLeds]; //<>// + color[] col = new color[numLeds]; for (color c : col) { c = color(0); } diff --git a/LightWork_Mapper/LightWork_Mapper.pde b/LightWork_Mapper/LightWork_Mapper.pde index 707124f..7400900 100644 --- a/LightWork_Mapper/LightWork_Mapper.pde +++ b/LightWork_Mapper/LightWork_Mapper.pde @@ -106,8 +106,8 @@ void setup() // Network println("setting up network Interface"); network = new Interface(); - network.setNumStrips(3); - network.setNumLedsPerStrip(50); // TODO: Fix these setters... + network.setNumStrips(1); + network.setNumLedsPerStrip(9); // TODO: Fix these setters... // Animator println("creating animator"); From bd656697dbdb0088a4466e7c2941bbe0aa7ca40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Thu, 25 Jan 2018 14:48:48 -0800 Subject: [PATCH 03/11] successfully sending binary color valueson RGB channels via ArtNet. --- LightWork_Mapper/Animator.pde | 8 ++++---- LightWork_Mapper/Interface.pde | 17 ++++++----------- LightWork_Mapper/LightWork_Mapper.pde | 2 +- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/LightWork_Mapper/Animator.pde b/LightWork_Mapper/Animator.pde index c1b9645..aa61b01 100644 --- a/LightWork_Mapper/Animator.pde +++ b/LightWork_Mapper/Animator.pde @@ -74,11 +74,11 @@ public class Animator { // Return pixels (to update OPC or PixelPusher) --Changed to array, arraylist wasn't working on return color[] getPixels() { - color[] l = new color[leds.size()]; //<>// + color[] l = new color[leds.size()]; for (int i = 0; i// //<>// } @@ -132,13 +132,13 @@ public class Animator { leds.get(i).setColor(col); } - if (frameCounter == 0) return; // Avoid the first LED going off too quickly //<>// + if (frameCounter == 0) return; // Avoid the first LED going off too quickly //<>// //<>// if (frameCounter%this.frameSkip==0)ledIndex++; // use frameskip to delay animation updates // Stop at end of LEDs if (ledIndex >= leds.size()) { this.setMode(AnimationMode.OFF); - } //<>// + } //<>// //<>// } // Set all LEDs to the same colour (useful to turn them all on or off). diff --git a/LightWork_Mapper/Interface.pde b/LightWork_Mapper/Interface.pde index edb4046..73f4da0 100644 --- a/LightWork_Mapper/Interface.pde +++ b/LightWork_Mapper/Interface.pde @@ -212,16 +212,11 @@ public class Interface { } case ARTNET: - { - color cols[] = new int[9]; - for (int i = 0; i < cols.length; i++) { - cols[i] = color(254, 254, 254); - } - color c = color(254, 254, 254); - for (int i = 0; i < cols.length; i++) { - int r = (c >> 16) & 0xFF; // Faster way of getting red(argb) - int g = (c >> 8) & 0xFF; // Faster way of getting green(argb) - int b = c & 0xFF; // Faster way of getting blue(argb) + { //<>// + for (int i = 0; i < colors.length; i++) { + int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) + int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) + int b = colors[i] & 0xFF; // Faster way of getting blue(argb) int index = i*numArtnetChannels; artnetPacket[index] = byte(r); // Red @@ -231,7 +226,7 @@ public class Interface { artnetPacket[index+4] = (byte(0)); // Unused channnel } - artnet.broadcast(artnetPacket); //<>// + artnet.broadcast(artnetPacket); } case NULL: diff --git a/LightWork_Mapper/LightWork_Mapper.pde b/LightWork_Mapper/LightWork_Mapper.pde index 7400900..6c1a1d6 100644 --- a/LightWork_Mapper/LightWork_Mapper.pde +++ b/LightWork_Mapper/LightWork_Mapper.pde @@ -1,4 +1,4 @@ -/* //<>// +/* //<>// //<>// * Lightwork-Mapper * * This sketch uses computer vision to automatically generate mapping for LEDs. From b3f52fcbd38fe62b0d34223fa1d0b7dfd7db0d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Thu, 25 Jan 2018 16:43:36 -0800 Subject: [PATCH 04/11] implementing artnet in scraper --- LightWork_Scraper/Interface.pde | 93 +++++++++----- LightWork_Scraper/LightWork_Scraper.pde | 4 +- LightWork_Scraper/data/layout.csv | 159 ++---------------------- 3 files changed, 76 insertions(+), 180 deletions(-) diff --git a/LightWork_Scraper/Interface.pde b/LightWork_Scraper/Interface.pde index a0ea771..6f87c45 100644 --- a/LightWork_Scraper/Interface.pde +++ b/LightWork_Scraper/Interface.pde @@ -18,6 +18,9 @@ import com.heroicrobot.dropbit.registry.*; import java.util.*; import java.io.*; +// ArtNet +import artnetP5.*; + enum device { FADECANDY, PIXELPUSHER, ARTNET, NULL }; @@ -34,6 +37,7 @@ public class Interface { int numLeds = ledsPerStrip*numStrips; int ledBrightness; + //Pixelpusher objects DeviceRegistry registry; TestObserver testObserver; @@ -41,39 +45,55 @@ public class Interface { //Fadecandy Objects OPC opc; + // ArtNet objects + ArtnetP5 artnet; + byte artnetPacket[]; + int numArtnetChannels = 5; // Channels per ArtNet fixture + int numArtnetFixtures = 9; // Number of ArtNet DMX fixtures (each one can have multiple channels and LEDs + + boolean isConnected =false; ////////////////////////////////////////////////////////////// //Constructors ///////////////////////////////////////////////////////////// - + Interface() { mode = device.NULL; //populateLeds(); println("Interface created"); } - + //setup for fadecandy - Interface(device m, String ip, int strips, int leds){ + Interface(device m, String ip, int strips, int leds) { mode = m; IP = ip; - numStrips =strips; + numStrips = strips; ledsPerStrip = leds; numLeds = ledsPerStrip*numStrips; //populateLeds(); println("Interface created"); } - - //setup for pixel pusher (no address required) - Interface(device m, int strips, int leds){ + + // Setup for PixelPusher and ArtNet (no address required) + // strips and leds are from PIXELPUSHER + // numFixtures and numChans are for ARTNET + Interface(device m, int strips, int leds, int numFixtures, int numChans) { mode = m; - numStrips =strips; - ledsPerStrip = leds; - numLeds = ledsPerStrip*numStrips; + if (mode == device.PIXELPUSHER) { + numStrips = strips; + ledsPerStrip = leds; + numLeds = ledsPerStrip*numStrips; + } else if (mode == device.ARTNET) { + numArtnetFixtures = numFixtures; + numArtnetChannels = numChans; // Number of channels per fixture + } + //populateLeds(); println("Interface created"); } + ////////////////////////////////////////////////////////////// // Setters and getters ////////////////////////////////////////////////////////////// @@ -105,9 +125,9 @@ public class Interface { int getNumStrips() { return numStrips; } - + //TODO: rework this to work in mapper and scraper - + //void setLedBrightness(int brightness) { //TODO: set overall brightness? // ledBrightness = brightness; @@ -127,26 +147,24 @@ public class Interface { println(IP); return IP; } - + void setInterpolation(boolean state) { if (mode == device.FADECANDY) { opc.setInterpolation(state); - } - else { - println("Interpolation only supported for FADECANDY."); + } else { + println("Interpolation only supported for FADECANDY."); } } - + void setDithering(boolean state) { if (mode == device.FADECANDY) { opc.setDithering(state); opc.setInterpolation(state); - } - else { - println("Dithering only supported for FADECANDY."); + } else { + println("Dithering only supported for FADECANDY."); } } - + boolean isConnected() { return isConnected; } @@ -162,9 +180,9 @@ public class Interface { } } } - + //TODO: rework this to work in mapper and scrapergit - + // Reset the LED vector //void populateLeds() { @@ -188,7 +206,7 @@ public class Interface { void update(color[] colors) { - switch(mode) { + switch(mode) { //<>// case FADECANDY: { //check if opc object exists and is connected before writing data @@ -223,6 +241,20 @@ public class Interface { case ARTNET: { + for (int i = 0; i < colors.length; i++) { + int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) + int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) + int b = colors[i] & 0xFF; // Faster way of getting blue(argb) + + int index = i*numArtnetFixtures; + artnetPacket[index] = byte(r); // Red + artnetPacket[index+1] = byte(g); // Green + artnetPacket[index+2] = byte(b); // Blue + artnetPacket[index+3] = byte(0); // White + artnetPacket[index+4] = (byte(0)); // Unused channnel + } + + artnet.broadcast(artnetPacket); } case NULL: @@ -278,9 +310,7 @@ public class Interface { opc.setPixelCount(numLeds); } //populateLeds(); - } - - if (mode == device.PIXELPUSHER ) { + } else if (mode == device.PIXELPUSHER ) { // does not like being instantiated a second time if (registry == null) { registry = new DeviceRegistry(); @@ -313,7 +343,7 @@ public class Interface { if (testObserver.hasStrips) { isConnected =true; - + // Clear LEDs //animator.setAllLEDColours(off); update(scrape.getColors()); @@ -321,7 +351,12 @@ public class Interface { registry.setLogging(false); //populateLeds(); - } + } else if (mode == device.ARTNET) { + artnet = new ArtnetP5(); + isConnected = true; + artnetPacket = new byte[numArtnetFixtures*numArtnetChannels]; // Reusing numLeds to indicate the number of fixtures (even though + update(scrape.getColors()); + } // Turn off LEDs // Turn off LEDs first diff --git a/LightWork_Scraper/LightWork_Scraper.pde b/LightWork_Scraper/LightWork_Scraper.pde index 7556064..5601719 100644 --- a/LightWork_Scraper/LightWork_Scraper.pde +++ b/LightWork_Scraper/LightWork_Scraper.pde @@ -21,7 +21,9 @@ void setup() { //initialize connection to LED driver - replace with adress and LED config for your setup //(Device type, address (not required for PixelPusher), number of strips, LEDs per strip) //network = new Interface(device.PIXELPUSHER, 1,100); - network = new Interface(device.FADECANDY, "fade2.local", 3, 50); + //network = new Interface(device.FADECANDY, "fade2.local", 3, 50); + network = new Interface(device.ARTNET, 0, 0, 9, 5); + network.connect(this); //update scraper after network connects diff --git a/LightWork_Scraper/data/layout.csv b/LightWork_Scraper/data/layout.csv index 05cf89d..cf857a9 100644 --- a/LightWork_Scraper/data/layout.csv +++ b/LightWork_Scraper/data/layout.csv @@ -1,151 +1,10 @@ address,x,y,z -0,0.047393188,0.001,0.0 -1,0.043269347,0.05254173,0.0 -2,0.04017647,0.11014719,0.0 -3,0.03605263,0.16623673,0.0 -4,0.030897833,0.22232625,0.0 -5,0.025743034,0.28144762,0.0 -6,0.023681115,0.33905312,0.0 -7,0.020588236,0.3981745,0.0 -8,0.060795665,0.39969042,0.0 -9,0.10409598,0.39514264,0.0 -10,0.14636533,0.40120637,0.0 -11,0.18657276,0.39969042,0.0 -12,0.24533747,0.4027223,0.0 -13,0.24843034,0.3436009,0.0 -14,0.25152323,0.28296357,0.0 -15,0.25358513,0.22535813,0.0 -16,0.256678,0.1692686,0.0 -17,0.25770897,0.113179065,0.0 -18,0.26286379,0.001,0.0 -19,0.0,0.0,0.0 -20,0.0,0.0,0.0 -21,0.3185356,0.52399695,0.0 -22,0.359774,0.52399695,0.0 -23,0.40410528,0.5255129,0.0 -24,0.44843653,0.5255129,0.0 -25,0.48967493,0.5118695,0.0 -26,0.51751083,0.46942335,0.0 -27,0.5257585,0.40878603,0.0 -28,0.5236966,0.3481487,0.0 -29,0.52782047,0.29054323,0.0 -30,0.52782047,0.2329378,0.0 -31,0.52782047,0.1783642,0.0 -32,0.5288514,0.12227467,0.0 -33,0.486582,0.12227467,0.0 -34,0.44740555,0.12227467,0.0 -35,0.40616715,0.11772686,0.0 -36,0.3669907,0.1419818,0.0 -37,0.3360619,0.1783642,0.0 -38,0.31956655,0.23142186,0.0 -39,0.3185356,0.2890273,0.0 -40,0.33296904,0.3436009,0.0 -41,0.36286688,0.38301516,0.0 -42,0.40204334,0.40575415,0.0 -43,0.4443127,0.40423822,0.0 -44,0.48142725,0.3799833,0.0 -45,0.6082353,0.41030198,0.0 -46,0.6020495,0.35118055,0.0 -47,0.6061734,0.2935751,0.0 -48,0.6061734,0.23748559,0.0 -49,0.6072044,0.17684825,0.0 -50,0.6061734,0.013127466,0.0 -51,0.6061734,0.069217,0.0 -52,0.6061734,0.12227467,0.0 -53,0.642257,0.14956145,0.0 -54,0.67834055,0.12682246,0.0 -55,0.7206099,0.12985432,0.0 -56,0.76081735,0.1465296,0.0 -57,0.79071516,0.18594386,0.0 -58,0.8082415,0.23900151,0.0 -59,0.8113343,0.29963884,0.0 -60,0.8144272,0.35876024,0.0 -61,0.8133963,0.41788164,0.0 -62,0.0,0.0,0.0 -63,0.84535605,0.12682246,0.0 -64,0.8814396,0.0191912,0.0 -65,0.8824706,0.067701064,0.0 -66,0.9680403,0.13137026,0.0 -67,0.9288638,0.1283384,0.0 -68,0.8876254,0.1283384,0.0 -69,0.8876254,0.18442792,0.0 -70,0.8907182,0.24051745,0.0 -71,0.8917492,0.29963884,0.0 -72,0.90205884,0.3572443,0.0 -73,0.93092567,0.40423822,0.0 -74,0.97216403,0.4209135,0.0 -75,0.0,0.0,0.0 -76,0.82164395,0.5755387,0.0 -77,0.8237059,0.63314414,0.0 -78,0.8237059,0.6907496,0.0 -79,0.9659783,0.6937815,0.0 -80,0.9329876,0.7241001,0.0 -81,0.897935,0.7544188,0.0 -82,0.8618514,0.7817056,0.0 -83,0.8257678,0.7483551,0.0 -84,0.8288607,0.80899245,0.0 -85,0.8298917,0.8726616,0.0 -86,0.8298917,0.93329895,0.0 -87,0.8329845,0.99696815,0.0 -88,0.8628824,0.8484067,0.0 -89,0.896904,0.886305,0.0 -90,0.92989475,0.92420334,0.0 -91,0.9659783,0.9636176,0.0 -92,1.0,1.0,0.0 -93,0.0,0.0,0.0 -94,0.0,0.0,0.0 -95,0.7680341,0.68771774,0.0 -96,0.72885764,0.6907496,0.0 -97,0.691743,0.71500456,0.0 -98,0.65669036,0.6846859,0.0 -99,0.65669036,0.74229133,0.0 -100,0.65669036,0.80596054,0.0 -101,0.65669036,0.863566,0.0 -102,0.6597833,0.9272352,0.0 -103,0.6587523,0.9939363,0.0 -104,0.5927709,0.83173144,0.0 -105,0.58658516,0.8908528,0.0 -106,0.5618421,0.9423945,0.0 -107,0.5288514,0.9818088,0.0 -108,0.487613,0.99545217,0.0 -109,0.44843653,0.98787254,0.0 -110,0.41132197,0.9605857,0.0 -111,0.38451704,0.9120759,0.0 -112,0.37008357,0.85447043,0.0 -113,0.3721455,0.7968649,0.0 -114,0.38864085,0.7392595,0.0 -115,0.41647676,0.69681334,0.0 -116,0.45359135,0.6725584,0.0 -117,0.49379876,0.66649467,0.0 -118,0.5309133,0.6846859,0.0 -119,0.56390405,0.72258425,0.0 -120,0.58658516,0.77261,0.0 -121,0.0,0.0,0.0 -122,0.0,0.0,0.0 -123,0.34224766,0.67407435,0.0 -124,0.32162848,0.7241001,0.0 -125,0.29791638,0.7756419,0.0 -126,0.27317336,0.82415175,0.0 -127,0.25049224,0.8756935,0.0 -128,0.22471827,0.92420334,0.0 -129,0.2010062,0.97877693,0.0 -130,0.18141796,0.9272352,0.0 -131,0.0,0.0,0.0 -132,0.25564706,0.67407435,0.0 -133,0.23605883,0.7241001,0.0 -134,0.21028483,0.77261,0.0 -135,0.18451084,0.82111984,0.0 -136,0.16389164,0.8726616,0.0 -137,0.13708669,0.92420334,0.0 -138,0.112343654,0.9727132,0.0 -139,0.09378638,0.9211715,0.0 -140,0.07316718,0.86962974,0.0 -141,0.056671824,0.818088,0.0 -142,0.038114548,0.76957816,0.0 -143,0.018526316,0.7165205,0.0 -144,0.001,0.6695266,0.0 -145,0.08760062,0.6695266,0.0 -146,0.1061579,0.72106826,0.0 -147,0.12265325,0.77261,0.0 -148,0.14327246,0.818088,0.0 -149,0.0,0.0,0.0 +0,0.001,1.0,0.0 +1,0.12977734,0.97563416,0.0 +2,0.64878905,0.2933902,0.0 +3,0.27611524,0.8538049,0.0 +4,0.37952733,0.6588781,0.0 +5,1.0,0.001,0.0 +6,0.8965879,0.12282927,0.0 +7,0.52391404,0.56141466,0.0 +8,0.77366406,0.24465854,0.0 From 6ebd19aea078066e317c7f15ea858a18ec2617f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Wed, 31 Jan 2018 12:32:27 -0800 Subject: [PATCH 05/11] sending RGB on channels 0-2, using color brightness to populate remaing DMX channels, assuming they represent WHITE. --- LightWork_Mapper/Interface.pde | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/LightWork_Mapper/Interface.pde b/LightWork_Mapper/Interface.pde index 73f4da0..38c30d1 100644 --- a/LightWork_Mapper/Interface.pde +++ b/LightWork_Mapper/Interface.pde @@ -1,4 +1,4 @@ -/* //<>// +/* //<>// //<>// * LED * * This class handles connecting to and switching between PixelPusher, FadeCandy and ArtNet devices. @@ -37,7 +37,7 @@ public class Interface { int numStrips = 1; int numLeds = ledsPerStrip*numStrips; int ledBrightness; - + int numArtnetChannels = 5; // Channels per ArtNet fixture int numArtnetFixtures = 9; // Number of ArtNet DMX fixtures (each one can have multiple channels and LEDs @@ -168,7 +168,7 @@ public class Interface { leds.add(temp); leds.get(i).setAddress(i); } - + numLeds = leds.size(); } @@ -212,18 +212,26 @@ public class Interface { } case ARTNET: - { //<>// + { + // Grab all the colors for (int i = 0; i < colors.length; i++) { + // Extract RGB values + // We assume the first three channels are RGB, and the rest is WHITE. int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) int b = colors[i] & 0xFF; // Faster way of getting blue(argb) + // Write RGB values to the packet int index = i*numArtnetChannels; artnetPacket[index] = byte(r); // Red artnetPacket[index+1] = byte(g); // Green artnetPacket[index+2] = byte(b); // Blue - artnetPacket[index+3] = byte(0); // White - artnetPacket[index+4] = (byte(0)); // Unused channnel + + // Populate remaining channels (presumably W) with color brightness + for (int j = 3; j < numArtnetChannels; j++) { + int br = int(brightness(colors[i])); + artnetPacket[index+j] = byte(br); // White + } } artnet.broadcast(artnetPacket); From 30fbec2a0ed31d8c3af679b25d28454b56df6eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Wed, 31 Jan 2018 13:48:36 -0800 Subject: [PATCH 06/11] added fixtures UI element. showing and hiding dynamically depending on driver selection. --- LightWork_Mapper/Interface.pde | 8 ++++++++ LightWork_Mapper/UI.pde | 24 ++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/LightWork_Mapper/Interface.pde b/LightWork_Mapper/Interface.pde index 38c30d1..8f47cf4 100644 --- a/LightWork_Mapper/Interface.pde +++ b/LightWork_Mapper/Interface.pde @@ -96,6 +96,14 @@ public class Interface { int getNumStrips() { return numStrips; } + + int getNumArtnetFixtures() { + return numArtnetFixtures; + } + + int getNumArtnetChannels() { + return numArtnetChannels; + } void setLedBrightness(int brightness) { //TODO: set overall brightness? ledBrightness = brightness; diff --git a/LightWork_Mapper/UI.pde b/LightWork_Mapper/UI.pde index 927aec7..5306b64 100644 --- a/LightWork_Mapper/UI.pde +++ b/LightWork_Mapper/UI.pde @@ -143,6 +143,19 @@ void buildUI() { .getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE, CENTER).setPadding(5*guiMultiply, 5*guiMultiply) ; + println("adding textfield for number of DMX/ArtNet fixtures"); + cp5.addTextfield("fixtures") + .setPosition(0, buttonHeight*3+uiSpacing*3) + .setSize(buttonWidth, buttonHeight) + .setAutoClear(false) + .setGroup("network") + .setValue(str(network.getNumArtnetFixtures())) + .setVisible(false) + .getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE, CENTER).setPadding(5*guiMultiply, 5*guiMultiply) + ; + + + println("listing drivers"); //draw after text boxes so the dropdown overlaps properly List driver = Arrays.asList("PixelPusher", "Fadecandy", "ArtNet"); //"ArtNet" removed for now - throws errors @@ -400,9 +413,9 @@ void driver(int n) { cp5.get(Textfield.class, "ip").setVisible(false); cp5.get(Textfield.class, "leds_per_strip").setVisible(false); cp5.get(Textfield.class, "strips").setVisible(false); + cp5.get(Textfield.class, "fixtures").setVisible(false); println("network: PixelPusher"); - } - else if (label.equals("FADECANDY")) { + } else if (label.equals("FADECANDY")) { if (network.isConnected) { network.shutdown(); cp5.get("connect").setCaptionLabel("Connect"); @@ -411,10 +424,13 @@ void driver(int n) { cp5.get(Textfield.class, "ip").setVisible(true); cp5.get(Textfield.class, "leds_per_strip").setVisible(true); cp5.get(Textfield.class, "strips").setVisible(true); + cp5.get(Textfield.class, "fixtures").setVisible(false); println("network: Fadecandy"); - } - else if (label.equals("ARTNET")) { + } else if (label.equals("ARTNET")) { network.setMode(device.ARTNET); + cp5.get(Textfield.class, "fixtures").setVisible(true); + cp5.get(Textfield.class, "leds_per_strip").setVisible(false); + cp5.get(Textfield.class, "strips").setVisible(false); println("network: ArtNet"); } } From 52a41dda31f8d9e36b764e6bb0208ac9d602c8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Wed, 31 Jan 2018 13:55:32 -0800 Subject: [PATCH 07/11] UI element for channels per fixture --- LightWork_Mapper/UI.pde | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/LightWork_Mapper/UI.pde b/LightWork_Mapper/UI.pde index 5306b64..ac14f10 100644 --- a/LightWork_Mapper/UI.pde +++ b/LightWork_Mapper/UI.pde @@ -153,6 +153,17 @@ void buildUI() { .setVisible(false) .getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE, CENTER).setPadding(5*guiMultiply, 5*guiMultiply) ; + + println("adding textfield for number of number of channels per DMX/Artnet Fixture"); + cp5.addTextfield("channels") + .setPosition(0, buttonHeight*2+uiSpacing*2) + .setSize(buttonWidth, buttonHeight) + .setAutoClear(false) + .setGroup("network") + .setValue(str(network.getNumArtnetChannels())) + .setVisible(false) + .getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE, CENTER).setPadding(5*guiMultiply, 5*guiMultiply) + ; @@ -414,6 +425,7 @@ void driver(int n) { cp5.get(Textfield.class, "leds_per_strip").setVisible(false); cp5.get(Textfield.class, "strips").setVisible(false); cp5.get(Textfield.class, "fixtures").setVisible(false); + cp5.get(Textfield.class, "channels").setVisible(false); println("network: PixelPusher"); } else if (label.equals("FADECANDY")) { if (network.isConnected) { @@ -425,10 +437,12 @@ void driver(int n) { cp5.get(Textfield.class, "leds_per_strip").setVisible(true); cp5.get(Textfield.class, "strips").setVisible(true); cp5.get(Textfield.class, "fixtures").setVisible(false); + cp5.get(Textfield.class, "channels").setVisible(false); println("network: Fadecandy"); } else if (label.equals("ARTNET")) { network.setMode(device.ARTNET); cp5.get(Textfield.class, "fixtures").setVisible(true); + cp5.get(Textfield.class, "channels").setVisible(true); cp5.get(Textfield.class, "leds_per_strip").setVisible(false); cp5.get(Textfield.class, "strips").setVisible(false); println("network: ArtNet"); From 11c0473d8d20d1d6d90b331013f159888e1e15f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Wed, 31 Jan 2018 15:22:11 -0800 Subject: [PATCH 08/11] Artnet UI elements now functional. clearLeds and populateLeds now have built in conditionals to deal with fixtures vs. leds. --- LightWork_Mapper/Interface.pde | 30 ++++++++++++++++++++++++++++-- LightWork_Mapper/UI.pde | 14 +++++++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/LightWork_Mapper/Interface.pde b/LightWork_Mapper/Interface.pde index 8f47cf4..ebe1071 100644 --- a/LightWork_Mapper/Interface.pde +++ b/LightWork_Mapper/Interface.pde @@ -101,9 +101,19 @@ public class Interface { return numArtnetFixtures; } + void setNumArtnetFixtures(int numFixtures) { + numArtnetFixtures = numFixtures; + populateLeds(); + } + int getNumArtnetChannels() { return numArtnetChannels; } + + void setNumArtnetChannels(int numChannels) { + numArtnetChannels = numChannels; + } + void setLedBrightness(int brightness) { //TODO: set overall brightness? ledBrightness = brightness; @@ -161,6 +171,14 @@ public class Interface { // Reset the LED vector void populateLeds() { + int val = 0; + + if (mode == device.ARTNET) { + val = getNumArtnetFixtures(); + } + else { + val = numLeds; + } // Clear existing LEDs if (leds.size()>0) { println("Clearing LED Array"); @@ -171,7 +189,7 @@ public class Interface { // Create new LEDS println("Creating LED Array"); - for (int i = 0; i < numLeds; i++) { + for (int i = 0; i < val; i++) { LED temp = new LED(); leds.add(temp); leds.get(i).setAddress(i); @@ -252,12 +270,20 @@ public class Interface { } void clearLeds() { - color[] col = new color[numLeds]; + int valCount = 0; + if (mode == device.ARTNET) { + valCount = numArtnetFixtures; + } + else { + valCount = numLeds; + } + color[] col = new color[valCount]; for (color c : col) { c = color(0); } update(col); // Update Physical LEDs with black (off) } + //open connection to controller void connect(PApplet parent) { diff --git a/LightWork_Mapper/UI.pde b/LightWork_Mapper/UI.pde index ac14f10..ff2ff46 100644 --- a/LightWork_Mapper/UI.pde +++ b/LightWork_Mapper/UI.pde @@ -464,6 +464,15 @@ public void strips(String theText) { network.setNumStrips(int(theText)); } +public void fixtures(String numFixtures) { + println("numFixtures: "+numFixtures); + network.setNumArtnetFixtures(int(numFixtures)); +} + +public void channels(String numChannels) { + network.setNumArtnetChannels(int(numChannels)); +} + public void connect() { if (network.getMode()!=device.NULL) { @@ -491,17 +500,12 @@ public void refresh() { cp5.get(ScrollableList.class, "camera").setItems(cameras); } - public void cvThreshold(int value) { cvThreshold = value; - //opencv.threshold(cvThreshold); - //println("set Open CV threshold to "+cvThreshold); } public void cvContrast(float value) { cvContrast =value; - //opencv.contrast(cvContrast); - //println("set Open CV contrast to "+cvContrast); } public void ledBrightness(int value) { From 4c551c42a0ef6e164aad0cf37221e3c7f6addc25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Wed, 31 Jan 2018 16:18:18 -0800 Subject: [PATCH 09/11] scraper supports ArtNet --- LightWork_Scraper/Interface.pde | 34 ++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/LightWork_Scraper/Interface.pde b/LightWork_Scraper/Interface.pde index 6f87c45..e7b73e0 100644 --- a/LightWork_Scraper/Interface.pde +++ b/LightWork_Scraper/Interface.pde @@ -87,6 +87,7 @@ public class Interface { } else if (mode == device.ARTNET) { numArtnetFixtures = numFixtures; numArtnetChannels = numChans; // Number of channels per fixture + } //populateLeds(); @@ -125,7 +126,25 @@ public class Interface { int getNumStrips() { return numStrips; } + + int getNumArtnetFixtures() { + return numArtnetFixtures; + } + + void setNumArtnetFixtures(int numFixtures) { + numArtnetFixtures = numFixtures; + } + + int getNumArtnetChannels() { + return numArtnetChannels; + } + + void setNumArtnetChannels(int numChannels) { + numArtnetChannels = numChannels; + } + + //TODO: rework this to work in mapper and scraper //void setLedBrightness(int brightness) { //TODO: set overall brightness? @@ -241,17 +260,25 @@ public class Interface { case ARTNET: { + // Grab all the colors for (int i = 0; i < colors.length; i++) { + // Extract RGB values + // We assume the first three channels are RGB, and the rest is WHITE. int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) int b = colors[i] & 0xFF; // Faster way of getting blue(argb) - int index = i*numArtnetFixtures; + // Write RGB values to the packet + int index = i*numArtnetChannels; artnetPacket[index] = byte(r); // Red artnetPacket[index+1] = byte(g); // Green artnetPacket[index+2] = byte(b); // Blue - artnetPacket[index+3] = byte(0); // White - artnetPacket[index+4] = (byte(0)); // Unused channnel + + // Populate remaining channels (presumably W) with color brightness + for (int j = 3; j < numArtnetChannels; j++) { + int br = int(brightness(colors[i])); + artnetPacket[index+j] = byte(br); // White + } } artnet.broadcast(artnetPacket); @@ -355,6 +382,7 @@ public class Interface { artnet = new ArtnetP5(); isConnected = true; artnetPacket = new byte[numArtnetFixtures*numArtnetChannels]; // Reusing numLeds to indicate the number of fixtures (even though + update(scrape.getColors()); } From 158979e841cef09cce4515f36c3a8f0068de5d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Wed, 31 Jan 2018 17:01:32 -0800 Subject: [PATCH 10/11] scraper -> getting white value from lowest color channel value --- LightWork_Scraper/Interface.pde | 8 ++++++-- LightWork_Scraper/LightWork_Scraper.pde | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/LightWork_Scraper/Interface.pde b/LightWork_Scraper/Interface.pde index e7b73e0..89b5b91 100644 --- a/LightWork_Scraper/Interface.pde +++ b/LightWork_Scraper/Interface.pde @@ -267,7 +267,7 @@ public class Interface { int r = (colors[i] >> 16) & 0xFF; // Faster way of getting red(argb) int g = (colors[i] >> 8) & 0xFF; // Faster way of getting green(argb) int b = colors[i] & 0xFF; // Faster way of getting blue(argb) - + // Write RGB values to the packet int index = i*numArtnetChannels; artnetPacket[index] = byte(r); // Red @@ -275,8 +275,12 @@ public class Interface { artnetPacket[index+2] = byte(b); // Blue // Populate remaining channels (presumably W) with color brightness + //int br = int(brightness(colors[i])); // Follow the brightness + color c = colors[i]; + + int br = int(min(red(c), green(c), blue(c))); // White tracks the minimum color channel value + println(min(red(c), green(c), blue(c))); for (int j = 3; j < numArtnetChannels; j++) { - int br = int(brightness(colors[i])); artnetPacket[index+j] = byte(br); // White } } diff --git a/LightWork_Scraper/LightWork_Scraper.pde b/LightWork_Scraper/LightWork_Scraper.pde index 5601719..524e9a7 100644 --- a/LightWork_Scraper/LightWork_Scraper.pde +++ b/LightWork_Scraper/LightWork_Scraper.pde @@ -11,7 +11,7 @@ float margin = 50; //prevents scraper from operating outside the canvas PGraphics gradient; void setup() { - size(1280, 960, P3D); + size(640, 480, P3D); gradient = createGraphics(width, height); //initialize scraper @@ -46,7 +46,7 @@ void draw() { //cursor to test accuracy noStroke(); - fill(255, 255, 255); + fill(100, 50, 20); ellipse(mouseX, mouseY, 30, 30); //end animation code From dec90a2184708f20feff1824d3abe947008d5836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3=20Stef=C3=A1nsson?= Date: Fri, 2 Feb 2018 15:56:55 -0800 Subject: [PATCH 11/11] comments and cleanup --- LightWork_Mapper/Animator.pde | 15 +++--- LightWork_Mapper/BinaryPattern.pde | 7 +-- LightWork_Mapper/Blob.pde | 8 +-- LightWork_Mapper/BlobManager.pde | 12 +---- LightWork_Mapper/Interface.pde | 27 +++++----- LightWork_Mapper/KeyPress.pde | 7 +-- LightWork_Mapper/LED.pde | 3 +- LightWork_Mapper/LightWork_Mapper.pde | 72 ++++++++------------------- LightWork_Mapper/UI.pde | 59 ++++++++++------------ 9 files changed, 82 insertions(+), 128 deletions(-) diff --git a/LightWork_Mapper/Animator.pde b/LightWork_Mapper/Animator.pde index aa61b01..f5deeb1 100644 --- a/LightWork_Mapper/Animator.pde +++ b/LightWork_Mapper/Animator.pde @@ -42,7 +42,6 @@ public class Animator { ledIndex = 0; // TODO: resetInternalVariables() method? testIndex = 0; frameCounter = 0; - //resetPixels(); } AnimationMode getMode() { @@ -78,8 +77,8 @@ public class Animator { for (int i = 0; i// //<>// - } + return l; + } //<>// //<>// ////////////////////////////////////////////////////////////// @@ -113,7 +112,7 @@ public class Animator { // Advance the internal counter frameCounter++; - //send pixel data over network + // Send pixel data over network if (mode!=AnimationMode.OFF && network.isConnected) { network.update(this.getPixels()); } @@ -133,13 +132,13 @@ public class Animator { } if (frameCounter == 0) return; // Avoid the first LED going off too quickly //<>// //<>// - if (frameCounter%this.frameSkip==0)ledIndex++; // use frameskip to delay animation updates + if (frameCounter%this.frameSkip==0)ledIndex++; // use frameskip to delay animation updates //<>// //<>// // Stop at end of LEDs if (ledIndex >= leds.size()) { this.setMode(AnimationMode.OFF); - } //<>// //<>// - } + } + } //<>// //<>// // Set all LEDs to the same colour (useful to turn them all on or off). void setAllLEDColours(color col) { @@ -148,7 +147,7 @@ public class Animator { } } - //LED pre-flight test. Cycle: White, Red, Green, Blue. + // LED pre-flight test. Cycle: White, Red, Green, Blue. void test() { testIndex++; diff --git a/LightWork_Mapper/BinaryPattern.pde b/LightWork_Mapper/BinaryPattern.pde index 92e1100..76c9410 100644 --- a/LightWork_Mapper/BinaryPattern.pde +++ b/LightWork_Mapper/BinaryPattern.pde @@ -32,12 +32,13 @@ public class BinaryPattern { BinaryPattern() { numBits = 10; animationPatternLength = 10; - frameNum = 0; // Used for animation - readIndex = 0; // Used by the detector to write bits - writeIndex = 0; + frameNum = 0; // Used for animation + readIndex = 0; // Used by the detector to read bits + writeIndex = 0; // Used by the detector to write bits previousState = 0; detectedState = 0; + // TODO: Review initial capacity decodedString = new StringBuffer(10); // Init with capacity decodedString.append("W123456789"); diff --git a/LightWork_Mapper/Blob.pde b/LightWork_Mapper/Blob.pde index 04986d6..3a5d4b7 100644 --- a/LightWork_Mapper/Blob.pde +++ b/LightWork_Mapper/Blob.pde @@ -7,6 +7,8 @@ * @author: Jordi Tost (@jorditost) * * University of Applied Sciences Potsdam, 2014 + * + * Modified by Leó Stefánsson */ class Blob { @@ -51,16 +53,10 @@ class Blob { //set draw location based on displayed camera position, accounts for moving cam in UI float x = map(r.x, 0, (float)camWidth, (float)camArea.x, camArea.x+camArea.width); float y = map(r.y, 0, (float)camHeight, (float)camArea.y, camArea.y+camArea.height); - //float opacity = map(timer+1, 0, 255, 0, 127); - //fill(0, 255, 0, opacity); noFill(); stroke(255, 0, 0); rect(x, y, r.width, r.height); - //fill(255, 0, 0); - //textSize(12); - //text(id+ ": "+detectedPattern.decodedString.toString(), x+30, y); - //stroke(0, 255, 0); } void update(Contour newContour) { diff --git a/LightWork_Mapper/BlobManager.pde b/LightWork_Mapper/BlobManager.pde index e1d5ef4..74de842 100644 --- a/LightWork_Mapper/BlobManager.pde +++ b/LightWork_Mapper/BlobManager.pde @@ -19,7 +19,6 @@ class BlobManager { float distanceThreshold = 2; int lifetime = 200; - //ArrayList contours; // List of detected contours parsed as blobs (every frame) ArrayList newBlobs; // List of my blob objects (persistent) @@ -36,15 +35,11 @@ class BlobManager { void update(PImage cvOutput) { contourFinder.loadImage(cvOutput); - // Find all contours - //blobCV.loadImage(opencv.getSnapshot()); - //ArrayList contours = opencv.findContours(); - // Filter contours, remove contours that are too big or too small // The filtered results are our 'Blobs' (Should be detected LEDs) ArrayList newBlobs = filterContours(contourFinder.findContours()); // Stores all blobs found in this frame - // Note: newBlobs is actually of the Contours datatype + // Note: newBlobs is of the Contours type // Register all the new blobs if the blobList is empty if (blobList.isEmpty()) { //println("Blob List is Empty, adding " + newBlobs.size() + " new blobs."); @@ -102,7 +97,7 @@ class BlobManager { } // Update the blob age - //for (int i = blobList.size()-1; i > 0; i--) { + // TODO: Reverse iteration for (int i = 0; i < blobList.size(); i++) { Blob b = blobList.get(i); b.countDown(); @@ -113,7 +108,6 @@ class BlobManager { } void display() { - for (Blob b : blobList) { strokeWeight(1); b.display(); @@ -156,6 +150,4 @@ class BlobManager { return blobs; } - - } \ No newline at end of file diff --git a/LightWork_Mapper/Interface.pde b/LightWork_Mapper/Interface.pde index ebe1071..c3b9b41 100644 --- a/LightWork_Mapper/Interface.pde +++ b/LightWork_Mapper/Interface.pde @@ -1,4 +1,4 @@ -/* //<>// //<>// +/* //<>// * LED * * This class handles connecting to and switching between PixelPusher, FadeCandy and ArtNet devices. @@ -55,7 +55,7 @@ public class Interface { boolean isConnected =false; ////////////////////////////////////////////////////////////// - //Constructor + // Constructor ///////////////////////////////////////////////////////////// Interface() { @@ -156,7 +156,7 @@ public class Interface { return isConnected; } - //Set number of strips and pixels based on pusher config - only pulling for one right now. + // Set number of strips and pixels based on pusher config - only pulling for one right now. void fetchPPConfig() { if (mode == device.PIXELPUSHER && isConnected()) { List pps = registry.getPushers(); @@ -173,12 +173,14 @@ public class Interface { void populateLeds() { int val = 0; + // Deal with ArtNet vs. LED structure if (mode == device.ARTNET) { val = getNumArtnetFixtures(); } else { val = numLeds; } + // Clear existing LEDs if (leds.size()>0) { println("Clearing LED Array"); @@ -207,7 +209,7 @@ public class Interface { switch(mode) { case FADECANDY: { - //check if opc object exists and is connected before writing data + // Check if OPC object exists and is connected before writing data if (opc!=null&&opc.isConnected()) { opc.autoWriteData(colors); } @@ -215,11 +217,11 @@ public class Interface { } case PIXELPUSHER: { - //check if network observer exists and has discovered strips before writing data + // Check if network observer exists and has discovered strips before writing data if (testObserver!=null&&testObserver.hasStrips) { registry.startPushing(); - //iterate through PP strip objects to set LED colors + // Iterate through PixelPusher strip objects to set LED colors List strips = registry.getStrips(); if (strips.size() > 0) { int stripNum =0; @@ -271,6 +273,8 @@ public class Interface { void clearLeds() { int valCount = 0; + + // Deal with ArtNet vs. LED addresses if (mode == device.ARTNET) { valCount = numArtnetFixtures; } @@ -285,7 +289,7 @@ public class Interface { } - //open connection to controller + // Open Connection to Controller void connect(PApplet parent) { if (isConnected) { shutdown(); @@ -323,14 +327,13 @@ public class Interface { animator.setAllLEDColours(off); // Update pixels twice (elegant, I know... but it works) update(animator.getPixels()); - //update(animator.getPixels()); println("Connected to Fadecandy OPC server at: "+IP+":"+port); isConnected =true; opc.setPixelCount(numLeds); populateLeds(); } } else if (mode == device.PIXELPUSHER ) { - // does not like being instantiated a second time + // Does not like being instantiated a second time if (registry == null) { registry = new DeviceRegistry(); testObserver = new TestObserver(); @@ -377,12 +380,11 @@ public class Interface { } } - //Close existing connections + // Close existing connections void shutdown() { if (mode == device.FADECANDY && opc!=null) { opc.dispose(); isConnected = false; - //opc = null; } if (mode==device.PIXELPUSHER && registry!=null) { registry.stopPushing() ; //TODO: Need to disconnect devices as well @@ -390,6 +392,7 @@ public class Interface { isConnected = false; } if (mode==device.ARTNET) { + // TODO: deinitialize artnet connection //artnet = null; } if (mode==device.NULL) { @@ -397,7 +400,7 @@ public class Interface { } - //toggle verbose logging for PixelPusher + // Toggle verbose logging for PixelPusher void pusherLogging(boolean b) { registry.setLogging(b); } diff --git a/LightWork_Mapper/KeyPress.pde b/LightWork_Mapper/KeyPress.pde index 9e11ee0..c3b3985 100644 --- a/LightWork_Mapper/KeyPress.pde +++ b/LightWork_Mapper/KeyPress.pde @@ -8,9 +8,10 @@ * @authors Leó Stefánsson and Tim Rolls */ -//ALT-SHIFT-S : Save UI properties to file -//ALT-SHIFT-L : Load UI properties to file -//SHIFT-H : Disable dragging (if accidentally activated with shift) +// Shortcuts: +// ALT-SHIFT-S : Save UI properties to file +// ALT-SHIFT-L : Load UI properties to file +// SHIFT-H : Disable dragging (if accidentally activated with shift) void keyPressed() { //if (key == 's') { diff --git a/LightWork_Mapper/LED.pde b/LightWork_Mapper/LED.pde index 6f45283..586bc49 100644 --- a/LightWork_Mapper/LED.pde +++ b/LightWork_Mapper/LED.pde @@ -1,7 +1,7 @@ /* * LED * - * This class tracks location, pattern and color data per LED + * This class tracks location, pattern and color data for an LED object * * Copyright (C) 2017 PWRFL * @@ -33,7 +33,6 @@ public class LED { void setAddress(int addr) { address = addr; binaryPattern.generatePattern(address+bPatternOffset); - //println("LED Address: "+addr+" pattern: "+binaryPattern.binaryPatternString); } void setCoord(PVector coordinates) { diff --git a/LightWork_Mapper/LightWork_Mapper.pde b/LightWork_Mapper/LightWork_Mapper.pde index 6c1a1d6..cd7ebda 100644 --- a/LightWork_Mapper/LightWork_Mapper.pde +++ b/LightWork_Mapper/LightWork_Mapper.pde @@ -1,4 +1,4 @@ -/* //<>// //<>// +/* //<>// * Lightwork-Mapper * * This sketch uses computer vision to automatically generate mapping for LEDs. @@ -71,7 +71,7 @@ String savePath = "../LightWork_Scraper/data/layout.csv"; PImage videoInput; PImage cvOutput; -// Image sequence stuff +// Image sequence parameters int numFrames = 10; // The number of frames in the animation int currentFrame = 0; ArrayList images; @@ -117,12 +117,12 @@ void setup() animator.setAllLEDColours(off); // Clear the LED strips animator.update(); - //Check for high resolution display + // Check for high resolution display println("setup gui multiply"); if (displayWidth >= 2560) { guiMultiply = 2; } - //set up window for 2d mapping + // Set up window for 2d mapping window2d(); println("calling buildUI on a separate thread"); @@ -256,8 +256,7 @@ void draw() { } showLEDOutput(); - showBlobCount(); //TODO: display during calibration/ after mapping - //processCV(); + showBlobCount(); // ------------------------------------------------------- // MAPPING @@ -278,9 +277,7 @@ void draw() { if (shouldStartPatternMatching) { matchBinaryPatterns(); - }//else { - - //} + } } else if (isMapping && !patternMapping) { blobManager.update(opencv.getOutput()); if (frameCount%frameSkip==0) { @@ -294,7 +291,6 @@ void draw() { // Mapping methods void sequentialMapping() { - //println("sequentialMapping() -> blobList size() = "+blobList.size()); if (blobManager.blobList.size()!=0) { Rectangle rect = blobManager.blobList.get(blobManager.blobList.size()-1).contour.getBoundingBox(); PVector loc = new PVector(); @@ -309,11 +305,9 @@ void sequentialMapping() { void matchBinaryPatterns() { for (int i = 0; i < leds.size(); i++) { if (leds.get(i).foundMatch) { - //println("Already found match for LED: "+leds.get(i).address); continue; } String targetPattern = leds.get(i).binaryPattern.binaryPatternString.toString(); - //println("finding target pattern: "+targetPattern); for (int j = 0; j < blobManager.blobList.size(); j++) { String decodedPattern = blobManager.blobList.get(j).detectedPattern.decodedString.toString(); //println("checking match with decodedPattern: "+decodedPattern); @@ -328,10 +322,7 @@ void matchBinaryPatterns() { } } - - //map(); // Toggle mapping off // Mapping is done, Save CSV for LEFT or RIGHT channels - // TODO: refactor. Maybe this method should return true when done, and then call saveCSV() if (stereoMode ==true && mapRight==true) { rightMap= new PVector[leds.size()]; arrayCopy( getLEDVectors(leds).toArray(), rightMap); @@ -366,9 +357,8 @@ void decode() { } } -//Open CV processing functions +// OpenCV Processing void processCV() { - diff.beginDraw(); diff.background(0); diff.blendMode(NORMAL); @@ -379,14 +369,9 @@ void processCV() { opencv.loadImage(diff); opencv.contrast(cvContrast); opencv.threshold(cvThreshold); - - //opencv.loadImage(videoInput); - //opencv.diff(backgroundImage); - //opencv.contrast(cvContrast); - //opencv.threshold(cvThreshold); } -//Count LEDs that have been matched +// Count LEDs that have been matched int listMatchedLEDs() { int count=0; for (LED led : leds) { @@ -395,23 +380,18 @@ int listMatchedLEDs() { return count; } -//return LED locations as PVectors +// Return LED locations as PVectors ArrayList getLEDVectors(ArrayList l) { ArrayList loc= new ArrayList(); - //println("l size: "+l.size()); - for (int i = 0; i pointsCopy) { //ArrayList pointsCopy = new ArrayList(points); @@ -438,7 +418,6 @@ float[] getMinMaxCoords(ArrayList pointsCopy) { int index =0; for (PVector temp : pointsCopy) { - xArr[index] = temp.x; yArr[index] = temp.y; zArr[index] = temp.z; @@ -457,7 +436,7 @@ float[] getMinMaxCoords(ArrayList pointsCopy) { return out; } -//normalize point coordinates +// Normalize point coordinates ArrayList normCoords(ArrayList in) { float[] norm = new float[6]; @@ -465,17 +444,15 @@ ArrayList normCoords(ArrayList in) ArrayList out = in; int index=0; - //println(loc); - for (LED temp : out) { - //ignore 0,0 points + // Ignore 0,0 coordinates if (temp.coord.x>0 && temp.coord.y>0) { if (temp.coord.z!=0) { - //3d coords + // 3D coords temp.coord.set (map(temp.coord.x, norm[0], norm[3], 0.001, 1), map(temp.coord.y, norm[1], norm[4], 0.001, 1), map(temp.coord.z, norm[2], norm[5], 0.001, 1)); out.set(index, temp); } else { - //2d coords + // 2D coords temp.coord.set (map(temp.coord.x, norm[0], norm[3], 0.001, 1), map(temp.coord.y, norm[1], norm[4], 0.001, 1)); out.set(index, temp); } @@ -492,7 +469,7 @@ ArrayList normCoords(ArrayList in) void saveSVG(ArrayList points) { if (points.size() == 0) { - //User is trying to save without anything to output - bail + // User is trying to save without anything to output - bail println("No point data to save, run mapping first"); return; } else { @@ -514,19 +491,12 @@ void saveCSV(ArrayList ledArray, String path) { for (int i = 0; i < ledArray.size(); i++) { output.println(ledArray.get(i).address+","+ledArray.get(i).coord.x+","+ledArray.get(i).coord.y+","+ledArray.get(i).coord.z); - //println(ledArray.get(i).address+" "+ledArray.get(i).coord.x+" "+ledArray.get(i).coord.y); } output.close(); // Finishes the file - - //wait until finished writing - //File f = new File(path); - //while (!f.exists()) - //{ - //} println("Exported CSV File to "+path); } -//Console warranty and OS info +// Console warranty and OS info void warranty() { println("Lightwork-Mapper"); println("Copyright (C) 2017 Leó Stefánsson and Tim Rolls @PWRFL"); @@ -536,16 +506,16 @@ void warranty() { println("Operating System: "+os); } -//Closes connections (once deployed as applet) +// Close connections (once deployed as applet) void stop() { - cam =null; + cam = null; super.stop(); } -//Closes connections +// Closes connections void exit() { - cam =null; + cam = null; super.exit(); } \ No newline at end of file diff --git a/LightWork_Mapper/UI.pde b/LightWork_Mapper/UI.pde index ff2ff46..a183397 100644 --- a/LightWork_Mapper/UI.pde +++ b/LightWork_Mapper/UI.pde @@ -1,4 +1,4 @@ -/* //<>// //<>// +/* //<>// * UI * * This class builds the UI for the application @@ -41,7 +41,7 @@ void buildUI() { cp5.setVisible(false); cp5.enableShortcuts(); - //check for defaults file + // Check for defaults file File defaults = new File("controlP5.json"); float startTime = millis(); @@ -107,7 +107,7 @@ void buildUI() { .hideBar() ; - //loadWidth = width/12*6; + // loadWidth = width/12*6; println("adding textfield for IP"); cp5.addTextfield("ip") .setCaptionLabel("ip address") @@ -182,7 +182,7 @@ void buildUI() { .bringToFront() .setGroup("network"); ; - //TODO fix style on dropdown + // TODO: fix style on dropdown cp5.getController("driver").getCaptionLabel().align(ControlP5.CENTER, ControlP5.CENTER).setPaddingX(uiSpacing); println("adding connect button"); @@ -239,11 +239,11 @@ void buildUI() { .getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE, CENTER).setPadding(5*guiMultiply, 5*guiMultiply) ; - ////set labels to bottom + //// Set labels to bottom //cp5.getController("ledBrightness").getValueLabel().align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); //cp5.getController("ledBrightness").getCaptionLabel().align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); - //Mapping type toggle + // Mapping type toggle List mapToggle = Arrays.asList("Pattern", "Sequence"); ButtonBar b = cp5.addButtonBar("mappingToggle") .setPosition(0, (buttonHeight+uiSpacing)*3) @@ -383,7 +383,7 @@ void buildUI() { //cp5.getController("camera").getCaptionLabel().align(ControlP5.CENTER, CENTER).setPadding(10*guiMultiply, 5*guiMultiply); - //load defaults + // Load defaults if (defaults.exists()) { cp5.loadProperties("controlP5.json"); cp5.update(); @@ -392,7 +392,7 @@ void buildUI() { addMouseWheelListener(); // Wrap up, report done - //loadWidth = width; + // loadWidth = width; float deltaTime = millis()-startTime; println("Done building GUI, total time: " + deltaTime + " ms"); cp5.setVisible(true); @@ -527,7 +527,6 @@ void controlEvent(ControlEvent theControlEvent) { blobManager.minBlobSize = int(theControlEvent.getController().getArrayValue(0)); blobManager.maxBlobSize = int(theControlEvent.getController().getArrayValue(1)); } - //else if (theControlEvent.isFrom(" } public void calibrate() { @@ -566,17 +565,17 @@ public void calibrate() { public void saveLayout() { if (leds.size() <= 0) { // TODO: review, does this work? - //User is trying to save without anything to output - bail + // User is trying to save without anything to output - bail println("No point data to save, run mapping first"); return; } else if (stereoMode == true && leftMap!=null && rightMap!=null) { - //Save stereo map with Z + // Save stereo map with Z calculateZ(leftMap, rightMap); savePath = "../Lightwork_Scraper_3D/data/stereoLayout.csv"; File sketch = new File(savePath); selectOutput("Select a file to write to:", "fileSelected", sketch); } else { - //Save 2d Map + // Save 2D Map File sketch = new File(savePath); selectOutput("Select a file to write to:", "fileSelected", sketch); } @@ -593,7 +592,7 @@ void fileSelected(File selection) { } } -//TODO: investigate "ignoring" error and why this doesn't work, but keypress do +// TODO: investigate "ignoring" error and why this doesn't work, but keypress do void saveSettings(float v) { cp5.saveProperties("default"); } @@ -637,10 +636,7 @@ public void map() { animator.setMode(AnimationMode.OFF); network.clearLeds(); - - // Clear CV FBO - //cvFBO = createGraphics(camWidth, camHeight, P3D); - + shouldStartPatternMatching = false; shouldStartDecoding = false; images.clear(); @@ -697,9 +693,6 @@ public void map2() { animator.setMode(AnimationMode.OFF); network.clearLeds(); - // Clear CV FBO - //cvFBO = createGraphics(camWidth, camHeight, P3D); - shouldStartPatternMatching = false; images.clear(); currentFrame = 0; @@ -708,7 +701,7 @@ public void map2() { cp5.get("map2").setCaptionLabel("Stop"); } - //Binary pattern mapping + // Binary pattern mapping else if (!isMapping && patternMapping==true) { mapRight = true; println("Binary pattern mapping started"); @@ -735,8 +728,8 @@ public void map2() { videoMode = VideoMode.CAMERA; animator.setMode(AnimationMode.CHASE); backgroundImage = videoInput.copy(); - //animator.resetPixels(); - blobManager.setBlobLifetime(400); // TODO: Replace 10 with binary pattern length + + blobManager.setBlobLifetime(400); // TODO: Review blob lifetime isMapping=true; cp5.get("map2").setColorBackground(#00aaff); cp5.get("map2").setCaptionLabel("Stop"); @@ -747,12 +740,12 @@ public void map2() { // UI Methods ////////////////////////////////////////////////////////////// -//get the list of currently connected cameras +// Get the list of currently connected cameras String[] enumerateCams() { String[] list = Capture.list(); - //catch null cases + // Catch null cases if (list == null) { println("Failed to retrieve the list of available cameras, will try the default..."); //cam = new Capture(this, camWidth, camHeight, FPS); @@ -760,15 +753,15 @@ String[] enumerateCams() { println("There are no cameras available for capture."); } - //parse out camera names from device listing + // Parse out camera names from device listing for (int i=0; i