-Client optimizations
-Implemented comprehensize logging system


git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4143 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/971CV/src/org/frc971/DebugServerRun.java b/971CV/src/org/frc971/DebugServerRun.java
new file mode 100644
index 0000000..14b5239
--- /dev/null
+++ b/971CV/src/org/frc971/DebugServerRun.java
@@ -0,0 +1,25 @@
+package org.frc971;
+
+import java.io.IOException;
+import java.nio.channels.SocketChannel;
+import java.net.InetSocketAddress;
+
+import aos.DebugServer;
+import aos.ChannelImageGetter;
+
+public class DebugServerRun {
+	public static void main(final String args[]) {
+		try {
+			DebugServer server = new DebugServer(9714);
+			System.out.println("Debug Server running on port 9714.");
+			SocketChannel client_sock = SocketChannel.open();
+			client_sock.connect(new InetSocketAddress("192.168.0.137", 9714));
+			ChannelImageGetter client = new ChannelImageGetter(client_sock);
+			client.getJPEG();
+			System.out.println(client.getTimestamp());
+		}
+		catch (IOException e) {
+			System.out.println(e.getMessage());
+		}
+	}
+}
diff --git a/971CV/src/org/frc971/HTTPClient.java b/971CV/src/org/frc971/HTTPClient.java
index 4e42553..e5ea204 100644
--- a/971CV/src/org/frc971/HTTPClient.java
+++ b/971CV/src/org/frc971/HTTPClient.java
@@ -6,13 +6,16 @@
 import java.net.*;
 
 import java.awt.image.BufferedImage;
-import javax.imageio.ImageIO;
-
-import aos.ChannelImageGetter;
 
 import java.nio.channels.SocketChannel;
 import java.nio.ByteBuffer;
 
+import java.util.logging.Logger;
+
+import javax.imageio.ImageIO;
+
+import aos.ChannelImageGetter;
+
 import edu.wpi.first.wpijavacv.WPIColorImage;
 
 public class HTTPClient {
@@ -29,10 +32,14 @@
 	
 	private final String ATOM_IP = "10.9.71.6";
 	
+	private ChannelImageGetter cgetter;
+	
+	private final static Logger LOG = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+	
 	private void WriteDebug(String message) {
 		//small helper function to write debug messages
 		if (LOCAL_DEBUG)
-			System.out.println(message);
+			LOG.info("LOCAL_DEBUG: " + message);
 	}
 	private String ReadtoBoundary(String boundary) {
 		//reads from socket until it encounters a specific character combination
@@ -43,7 +50,7 @@
 			core_sock.setSoTimeout(10000);
 		}
 		catch (SocketException e) {
-			System.err.println("Warning: Could not set socket timeout.");
+			LOG.warning("Could not set socket timeout.");
 		}
 		try {
 			int ret;
@@ -67,11 +74,11 @@
 			}
 		}
 		catch (InterruptedIOException e) {
-			System.err.println("Warning: Image receive timed out.");
+			LOG.warning("Image receive timed out.");
 			return null;
 		}
 		catch (IOException e) {
-			System.err.println("Error: Socket read failed.");
+			LOG.severe("Socket read failed.");
 			return null;
 		}
 		return message;
@@ -81,7 +88,7 @@
 		try {
 			sock = SocketChannel.open();
 			core_sock = sock.socket();
-			WriteDebug("Connecting to server...");
+			WriteDebug("Connecting to server at " + ATOM_IP);
 			sock.connect(new InetSocketAddress(ATOM_IP, 9714));
 			sock_in = new BufferedReader(new InputStreamReader(core_sock.getInputStream()));
 			sock_out = new PrintWriter(core_sock.getOutputStream(), true);
@@ -93,13 +100,14 @@
 			WriteDebug("Reading headers...");
 			ReadtoBoundary("donotcross\r\n");
 			WriteDebug("Now receiving data.");
+			cgetter = new ChannelImageGetter(sock);
 		}
 		catch (UnknownHostException e) {
-			System.err.println("Error: Invalid host.");
+			LOG.severe("Invalid host.");
 			System.exit(1);
 		}
 		catch (IOException e) {
-			System.err.println("Error: Socket IO failed.");
+			LOG.severe("Socket IO failed.");
 			System.exit(2);
 		}
 		
@@ -107,26 +115,18 @@
 	public ImageWithTimestamp GetFrame() {
 		//Use Brian's code to extract an image and timestamp from raw server data.
 		ImageWithTimestamp final_image = new ImageWithTimestamp();
+		ByteBuffer binary_image = cgetter.getJPEG();
+		//Decode ByteBuffer into an IplImage
+		InputStream in = new ByteArrayInputStream(binary_image.array());
 		try {
-			ChannelImageGetter cgetter = new ChannelImageGetter(sock);
-			ByteBuffer binary_image = cgetter.getJPEG();
-			//Decode ByteBuffer into an IplImage
-			InputStream in = new ByteArrayInputStream(binary_image.array());
-			try {
-				BufferedImage bImageFromConvert = ImageIO.read(in);
-				final_image.image = new WPIColorImage(bImageFromConvert);
-				final_image.timestamp = cgetter.getTimestamp();
-				WriteDebug("Image processing successful.");
-				return final_image;
-			}
-			catch (IOException e) {
-				System.err.println(e.getMessage());
-				return null;
-			}
-			
+			BufferedImage bImageFromConvert = ImageIO.read(in);
+			final_image.image = new WPIColorImage(bImageFromConvert);
+			final_image.timestamp = cgetter.getTimestamp();
+			WriteDebug("Image processing successful.");
+			return final_image;
 		}
 		catch (IOException e) {
-			WriteDebug("Error: Failed to initialize ChannelImageGetter.");
+			LOG.warning("Image processing failed.");
 			return null;
 		}
 	}	
diff --git a/971CV/src/org/frc971/LogHandler.java b/971CV/src/org/frc971/LogHandler.java
new file mode 100644
index 0000000..59f74a9
--- /dev/null
+++ b/971CV/src/org/frc971/LogHandler.java
@@ -0,0 +1,51 @@
+/**
+ * 
+ */
+package org.frc971;
+
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+
+/**
+ * @author daniel
+ * logs data to custom files, using specific formatting.
+ */
+public class LogHandler extends Handler {
+	
+	private FileOutputStream ofstream;
+	PrintWriter writer;
+	
+	public LogHandler (String filename) throws FileNotFoundException {
+		super();
+		
+		if (filename == null || filename == "") {
+			filename = "logfile.log";
+		}
+		
+		//check if file exists, and if not, create it
+		ofstream = new FileOutputStream(filename);
+		writer = new PrintWriter(ofstream);
+		setFormatter(new TimeFormatter());
+	}
+	
+	/*Required methods*/
+	
+	public void publish(LogRecord message) {
+		//record a message
+		if (!isLoggable(message)) {
+			//ensure that this message should be logged by this handler
+			return;
+		}
+		writer.print(getFormatter().format(message)); //Formatter adds trailing \n
+	}
+	public void flush() {
+		writer.flush();
+	}
+	public void close() throws SecurityException {
+		writer.close();
+	}
+}
diff --git a/971CV/src/org/frc971/Recognizer2013.java b/971CV/src/org/frc971/Recognizer2013.java
index 115af27..7fbf28e 100644
--- a/971CV/src/org/frc971/Recognizer2013.java
+++ b/971CV/src/org/frc971/Recognizer2013.java
@@ -1,6 +1,7 @@
 package org.frc971;

 

 import java.util.ArrayList;

+import java.util.logging.Logger;

 

 import com.googlecode.javacv.cpp.opencv_core;

 import com.googlecode.javacv.cpp.opencv_core.CvSize;

@@ -24,6 +25,8 @@
  * @author jerry

  */

 public class Recognizer2013 implements Recognizer {

+	

+	private final static Logger LOG = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

 

     // --- Tunable recognizer constants.

     static final double kRoughlyHorizontalSlope = Math.tan(Math.toRadians(30));

@@ -240,7 +243,7 @@
             rawImage.drawPolygon(bestTarget, targetColor, 2);

             measureTarget(bestTarget);

         } else {

-            System.out.println("No target found");

+            LOG.fine("No target found");

         }

 

         // Draw a crosshair

@@ -271,12 +274,10 @@
         double elevationCam = Math.atan2(yc * 2 * kTanVFOV2, vh);

         double rangeIn = kTargetWidthIn * vw / (w * 2 * kTanHFOV2);

 

-        System.out.format("Best target at (%.2f, %.2f) %.2f x %.2f"

-                + ", shot azimuth=%.2f elevation=%.2f range=%.2f'%n",

-                x, y, w, h,

-                Math.toDegrees(azimuthCam) - kShooterOffsetDeg,

-                Math.toDegrees(elevationCam) + kCameraPitchDeg,

-                rangeIn / 12);

+        LOG.fine("Best target at (" + x + ", " + y + ") " + w +" x " + h

+                + ", shot azimuth=" + (Math.toDegrees(azimuthCam) - kShooterOffsetDeg) + 

+                " elevation=" + (Math.toDegrees(elevationCam) + kCameraPitchDeg) + 

+                " range=" + (rangeIn / 12));

     }

 

 }

diff --git a/971CV/src/org/frc971/TestImageGetter.java b/971CV/src/org/frc971/TestImageGetter.java
index 1f80520..b0cf9b0 100644
--- a/971CV/src/org/frc971/TestImageGetter.java
+++ b/971CV/src/org/frc971/TestImageGetter.java
@@ -10,15 +10,21 @@
 
 //get debug images for Java camera processor
 
+import java.io.File;
+import java.io.IOException;
+
+import java.util.logging.Logger;
+
 import javax.imageio.ImageIO;
 
 import edu.wpi.first.wpijavacv.WPIColorImage;
 
-import java.io.File;
-import java.io.IOException;
-
 public class TestImageGetter {
+	
 	private String path_to_images;
+	
+	private final static Logger LOG = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+	
 	final static String[] images = {"45in_DoubleGreen.jpg",
 									"57inLargeTarget_DoubleGreenBK.jpg",
 									"FullField_DoubleGreenBK3.jpg",
@@ -61,7 +67,7 @@
 				return current_image;
 			}
 			catch (IOException e) {
-				System.err.println("Could not open file.");
+				LOG.warning("Could not open file.");
 				return null;
 			}
 		}
@@ -78,7 +84,7 @@
 				return current_image;
 			}
 			catch (IOException e) {
-				System.err.println("Could not open file.");
+				LOG.warning("Could not open file.");
 				return null;
 			}
 		}
diff --git a/971CV/src/org/frc971/TimeFormatter.java b/971CV/src/org/frc971/TimeFormatter.java
new file mode 100644
index 0000000..9f46bd4
--- /dev/null
+++ b/971CV/src/org/frc971/TimeFormatter.java
@@ -0,0 +1,37 @@
+/**
+ * 
+ */
+package org.frc971;
+
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+import java.util.Date;
+
+/**
+ * @author daniel
+ * Formats log messages with adequate timestamp
+ */
+public class TimeFormatter extends Formatter{
+	public TimeFormatter() {
+		super();
+	}
+	public String format(LogRecord message) {
+		//we need to include the date and time in our message
+		StringBuffer out = new StringBuffer();
+		out.append("@");
+		Date date = new Date(message.getMillis());
+		out.append(date.toString());
+		out.append(" in [");
+		//add our logger's name
+		out.append(message.getLoggerName());
+		out.append("]: (");
+		//add message level
+		out.append(message.getLevel().getName());
+		out.append(") ");
+		//add actual message
+		out.append(formatMessage(message));
+		out.append("\n");
+		return out.toString();
+	}
+
+}
diff --git a/971CV/src/org/frc971/VisionTuner.java b/971CV/src/org/frc971/VisionTuner.java
index c664391..4d062dc 100644
--- a/971CV/src/org/frc971/VisionTuner.java
+++ b/971CV/src/org/frc971/VisionTuner.java
@@ -3,7 +3,12 @@
 import java.awt.BorderLayout;

 import java.awt.GridLayout;

 import java.awt.event.KeyEvent;

+

 import java.util.Arrays;

+import java.util.logging.Level;

+import java.util.logging.Logger;

+

+import java.io.FileNotFoundException;

 

 import javax.swing.JPanel;

 import javax.swing.JSlider;

@@ -41,6 +46,8 @@
 public class VisionTuner {

     private Recognizer recognizer = new Recognizer2013();

 

+    private final static Logger LOG = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

+    

     private final CanvasFrame cameraFrame = new CanvasFrame("Camera");

     private final JPanel panel = new JPanel();

     private final JSlider hueMinSlider = new JSlider();

@@ -56,6 +63,18 @@
     private TestImageGetter getter;

 

     public VisionTuner() {

+    	//set logger to log everything

+        LOG.setLevel(Level.ALL);

+        try {

+        	LogHandler handler = new LogHandler("../src/org/frc971/ds_vision.log");

+        	TimeFormatter formatter = new TimeFormatter();

+            handler.setFormatter(formatter);

+            LOG.addHandler(handler);

+        }

+        catch (FileNotFoundException e) {

+        	System.err.println("Warning: Logging initialization failed.");

+        }

+        

         cameraFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

 

         recognizer.showIntermediateStages(true);

@@ -66,7 +85,7 @@
         ChangeListener sliderListener = new ChangeListener() {

             @Override

             public void stateChanged(ChangeEvent e) {

-                System.out.println("New HSV range ["

+                LOG.fine("New HSV range ["

                         + hueMinSlider.getValue() + " .. "

                         + hueMaxSlider.getValue() + "] "

                         + satMinSlider.getValue() + "+ "

@@ -99,7 +118,7 @@
         valMinSlider.setValue(recognizer.getValMin());

         panel.add(valMinSlider);

 

-        System.out.println("Initial HSV range ["

+        LOG.fine("Initial HSV range ["

                 + hueMinSlider.getValue() + " .. "

                 + hueMaxSlider.getValue() + "] "

                 + satMinSlider.getValue() + "+ "

@@ -117,7 +136,7 @@
      */

 

     private void processImage(WPIColorImage cameraImage) {

-        cameraFrame.setTitle("Test Images:");

+        cameraFrame.setTitle("Input:");

 

         long startTime = System.nanoTime();

         WPIImage processedImage = recognizer.processImage(cameraImage);

@@ -130,9 +149,8 @@
             totalMsec += milliseconds;

             minMsec = Math.min(minMsec, milliseconds);

             maxMsec = Math.max(maxMsec, milliseconds);

-            System.out.format("The recognizer took %.2f ms, %.2f fps, %.2f avg%n",

-                    milliseconds, 1000 / milliseconds,

-                    1000 * totalFrames / totalMsec);

+            LOG.fine("The recognizer took " + milliseconds + " ms, " + 

+            (1000 * totalFrames / totalMsec) + " fps, %.2f avg");

         }

     }

 

@@ -159,11 +177,8 @@
             nextImage();

             break;

         case KeyEvent.VK_Q: // Q: print time measurements then quit

-            System.out.format("The recognizer took %.2f ms avg, %.2f min,"

-                    + " %.2f max, %.2f fps avg%n",

-                    totalMsec / totalFrames,

-                    minMsec, maxMsec,

-                    1000 * totalFrames / totalMsec);

+            LOG.fine("The recognizer took " + (totalMsec / totalFrames) + "ms avg, " + minMsec +" min,"

+                    + maxMsec + " max, " + (1000 * totalFrames / totalMsec) + " fps avg");

             System.exit(0);

         }

     }

@@ -174,13 +189,14 @@
         	//debug mode has been requested

         	tuner.getter = new TestImageGetter(".");

         	WPIColorImage to_process = tuner.getter.GetNext();

-        	if (to_process != null) 

+        	if (to_process != null) {

         		tuner.processImage(to_process);

+        		for (;;) {

+        			tuner.processEvents();

+        		}

+        	}

         	else

-        		System.err.println("Cannot find test images.");

-        	for (;;) {

-                tuner.processEvents();

-            }

+        		LOG.severe("Cannot find test images.");

         }

         else {

         	HTTPClient client = new HTTPClient();

@@ -188,7 +204,7 @@
         		ImageWithTimestamp to_process = client.GetFrame();

         		if (to_process.image != null) {

         			tuner.processImage(to_process.image);

-        			System.out.println("Captured time: " + Double.toString(to_process.timestamp));

+        			LOG.fine("Captured time: " + Double.toString(to_process.timestamp));

         		}

         	}

         }