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