package oculusPrime; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import developer.Navigation; import developer.Ros; import developer.depth.Mapper; import developer.depth.ScanUtils; import oculusPrime.State.values; @SuppressWarnings("serial") @MultipartConfig(fileSizeThreshold=1024*1024*2, // 2MB maxFileSize=1024*1024*10, // 10MB maxRequestSize=1024*1024*50) // 50MB public class FrameGrabHTTP extends HttpServlet { private static BufferedImage radarImage = null; private static Application app = null; private static State state; private static BanList ban; private static int var; public static void setApp(Application a) { if(app != null) return; state = State.getReference(); ban = BanList.getRefrence(); app = a; var = 0; } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doPost(req,res); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if( ! ban.knownAddress(req.getRemoteAddr())){ Util.log("unknown address: danger: "+req.getRemoteAddr(), this); // response.setContentType("text/html"); // PrintWriter out = response.getWriter(); //out.println("unknown address: danger: "+req.getServerName() + " \n " + ban.toString()); //out.close(); return; } if (req.getParameter("mode") != null) { String mode = req.getParameter("mode"); if (mode.equals("radar")) radarGrab(req,res); else if(mode.equals("processedImg")) processedImg(req,res); else if(mode.equals("processedImgJPG")) processedImgJPG(req,res); else if (mode.equals("videoOverlayImg")) videoOverlayImg(req, res); else if (mode.equals("depthFrame") && Application.openNIRead.depthCamGenerating) { Application.processedImage = Application.openNIRead.generateDepthFrameImg(); processedImg(req,res); } else if (mode.equals("floorPlane") && Application.openNIRead.depthCamGenerating) { // short[] depthFrame = Application.openNIRead.readFullFrame(); // Application.processedImage = Application.scanMatch.floorPlaneImg(depthFrame); Application.processedImage = Application.scanUtils.floorPlaneImg(); processedImg(req,res); } else if (mode.equals("floorPlaneTop") && Application.openNIRead.depthCamGenerating) { Application.processedImage = ScanUtils.floorPlaneTopViewImg(); processedImg(req,res); } else if (mode.equals("map")) { Application.processedImage = ScanUtils.cellsToImage(Mapper.map); // if (req.getParameter("scale") != null) { // double scale = Double.parseDouble(req.getParameter("scale")); // Application.processedImage = ScanUtils.byteCellsToImage(Mapper.map, scale); // } processedImg(req,res); } else if (mode.equals("rosmap")) { Application.processedImage = Ros.rosmapImg(); if (!state.exists(State.values.rosmapinfo)) app.driverCallServer(PlayerCommands.messageclients, "map data unavailable, try starting navigation system"); processedImg(req,res); } else if (mode.equals("rosmapinfo")) { // xmlhttp text res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.print(Ros.mapinfo()); out.close(); } else if (mode.equals("routesload")) { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.print(Navigation.routesLoad()); out.close(); } else if (mode.equals("rosmapdownload")) { res.setContentType("image/x-portable-graymap"); res.setHeader("Content-Disposition", "attachment; filename=\"map.pgm\""); FileInputStream a = new FileInputStream(Ros.getMapFilePath()+Ros.mapfilename); while(a.available() > 0) res.getWriter().append((char)a.read()); a.close(); } else if (mode.equals("rosmapupload")) { if (!state.get(State.values.navsystemstatus).equals(Ros.navsystemstate.stopped.toString())) { app.message("unable to modify map while navigation running", null, null); return; } Part part = req.getParts().iterator().next(); if (part == null) { app.message("problem uploading, map not saved", null, null); return; } File save = new File(Ros.getMapFilePath(), Ros.mapfilename ); Ros.backUpMappgm(); part.write(save.getAbsolutePath()); app.message("map saved as: " + save.getAbsolutePath(), null, null); } } else { frameGrab(req, res); } } private void frameGrab(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("image/jpeg"); OutputStream out = res.getOutputStream(); Application.framegrabimg = null; Application.processedImage = null; if (app.frameGrab()) { int n = 0; while (state.getBoolean(State.values.framegrabbusy)) { Util.delay(5); n++; if (n> 2000) { // give up after 10 seconds state.set(State.values.framegrabbusy, false); break; } } if (Application.framegrabimg != null) { // TODO: unused? for (int i=0; i<Application.framegrabimg.length; i++) { out.write(Application.framegrabimg[i]); } } else { if (Application.processedImage != null) { ImageIO.write(Application.processedImage, "JPG", out); } } out.close(); } } private void processedImg(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (Application.processedImage == null) return; // send image res.setContentType("image/gif"); OutputStream out = res.getOutputStream(); ImageIO.write(Application.processedImage, "GIF", out); } private void processedImgJPG(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (Application.processedImage == null) return; // send image res.setContentType("image/jpg"); OutputStream out = res.getOutputStream(); ImageIO.write(Application.processedImage, "JPG", out); } private void videoOverlayImg(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (Application.videoOverlayImage == null) Application.videoOverlayImage= new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB); // send image res.setContentType("image/jpg"); OutputStream out = res.getOutputStream(); ImageIO.write(Application.videoOverlayImage, "JPG", out); } private void radarGrab(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { generateRadarImage(); // send image res.setContentType("image/gif"); OutputStream out = res.getOutputStream(); ImageIO.write(radarImage, "GIF", out); } private void generateRadarImage() { final int w = 240; final int h = 320; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); final int voff = 0; // offset final double angle = 0.392699082; // 22.5 deg in radians from ctr, or half included view angle Graphics2D g2d = image.createGraphics(); //render background g2d.setColor(new Color(10,10,10)); g2d.fill(new Rectangle2D.Double(0, 0, w, h)); // too close out of range background fill // g2d.setColor(new Color(23,25,0)); g2d.setColor(new Color(20,20,20)); int r = 40; g2d.fill(new Ellipse2D.Double( w/2-r, h-1-r*0.95+voff, r*2, r*2*0.95)); // retrieve & render pixel data and shadows int maxDepthInMM = 3500; if (Application.openNIRead.depthCamGenerating == true) { WritableRaster raster = image.getRaster(); int[] xdepth = Application.openNIRead.readHorizDepth(120); /* TODO: need to figure out some way to drop request if taking too long * above line hangs whole servlet? */ int[] dataRGB = {0,255,0}; // sensor data pixel colour g2d.setColor(new Color(0,70,0)); // shadow colour int xdctr = xdepth.length/2; for (int xd=0; xd < xdepth.length; xd++) { // for (int xd=xdepth.length-1; xd>=0; xd--) { int y = (int) ((float)xdepth[xd]/(float)maxDepthInMM*(float)h); // x(opposite) = tan(angle)*y(adjacent) double xdratio = (double)(xd - xdctr)/ (double) xdctr; // Util.log(Double.toString(xdratio),this); int x = (w/2) - ((int) (Math.tan(angle)*(double) y * xdratio)); int xend = (w/2) - ((int) (Math.tan(angle)*(double) (h-1) * xdratio)); // for shadow fill past point if (y<h-voff && y>0+voff && x>=0 && x<w) { y = h-y-1+voff; //flip vertically g2d.drawLine(x, y, xend, 0); //fill area behind with line raster.setPixel(x,y,dataRGB); raster.setPixel(x,y+1,dataRGB); } } } else { // pulsator g2d.setColor(new Color(0,0,155)); var += 11; if (var > h + 50) { var = 0; } g2d.draw(new Ellipse2D.Double( w/2-var, h-1-var*0.95+voff, var*2, var*2*0.95)); } // dist scale arcs g2d.setColor(new Color(100,100,100)); r = 100; g2d.draw(new Ellipse2D.Double( w/2-r, h-1-r*0.95+voff, r*2, r*2*0.95)); r = 200; g2d.draw(new Ellipse2D.Double( w/2-r, h-1-r*0.95+voff, r*2, r*2*0.95)); r = 300; g2d.draw(new Ellipse2D.Double( w/2-r, h-1-r*0.95+voff, r*2, r*2*0.95)); // outside cone colour fill // g2d.setColor(new Color(23,25,0)); // blue opposite comp? g2d.setColor(new Color(20,20,20)); for (int y= 0-voff; y<h+voff; y++) { int x = (int) (Math.tan(angle)*(double)(h-y-1)); if (x>=0) { g2d.drawLine(0, y, (w/2)-x, y); g2d.drawLine(w-1, y, (w/2)+x,y); } } // cone perim lines g2d.setColor(new Color(100,100,100)); int x = (int) (Math.tan(angle)*(double)(319)); g2d.drawLine(w/2, 319, (w/2)-x, 0); g2d.drawLine(w/2, 319, (w/2)+x, 0); // radarImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); radarImage = image; // radarImageGenerating = false; // } }).start(); } /** * @param args download url params, can be null * @return returns download url of saved image */ public static String saveToFile(String args) { String urlString = "http://127.0.0.1:" + state.get(State.values.httpport) + "/oculusPrime/frameGrabHTTP"; if(args != null) if(args.startsWith("?")) urlString += args; final String url = urlString; String datetime = Util.getDateStamp(); // no spaces in filenames if(state.exists(values.roswaypoint) && state.get(State.values.navsystemstatus).equals(Ros.navsystemstate.running.toString()) ) datetime += "_" + state.get(values.roswaypoint).replaceAll(" ", "_"); final String name = datetime + ".jpg"; new Thread(new Runnable() { public void run() { new Downloader().FileDownload(url, name, "webapps/oculusPrime/framegrabs"); } }).start(); return "/oculusPrime/framegrabs/"+name; } /** add extra text into file name after timestamp */ public static String saveToFile(final String args, final String optionalname) { String urlString = "http://127.0.0.1:" + state.get(State.values.httpport) + "/oculusPrime/frameGrabHTTP"; if(args != null) if(args.startsWith("?")) urlString += args; final String url = urlString; String datetime = Util.getDateStamp(); // no spaces in filenames if(state.exists(values.roswaypoint) && state.get(State.values.navsystemstatus).equals(Ros.navsystemstate.running.toString()) ) datetime += "_" + state.get(values.roswaypoint); final String name = (datetime + optionalname + ".jpg").replaceAll(" ", "_"); new Thread(new Runnable() { public void run() { new Downloader().FileDownload(url, name, "webapps/oculusPrime/framegrabs"); } }).start(); return "/oculusPrime/framegrabs/"+name; } }