/**
*
* @author greg (at) myrobotlab.org
*
* This file is part of MyRobotLab (http://myrobotlab.org).
*
* MyRobotLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version (subject to the "Classpath" exception
* as provided in the LICENSE.txt file that accompanied this code).
*
* MyRobotLab is distributed in the hope that it will be useful or fun,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* All libraries in thirdParty bundle are subject to their own license
* requirements - please refer to http://myrobotlab.org/libraries for
* details.
*
* Enjoy !
*
* */
package org.myrobotlab.control;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JList;
import javax.swing.JTabbedPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.myrobotlab.image.SerializableImage;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.service.GUIService;
import org.myrobotlab.service.Wii.IRData;
import org.myrobotlab.service.WiiDar;
import org.myrobotlab.service.WiiDar.Point;
import org.myrobotlab.service.interfaces.VideoGUISource;
import org.slf4j.Logger;
public class WiiDARGUI extends ServiceGUI implements ListSelectionListener, VideoGUISource {
static final long serialVersionUID = 1L;
public final static Logger log = LoggerFactory.getLogger(WiiDARGUI.class.toString());
VideoWidget screen = null;
Graphics cam = null;
Graphics graph = null;
transient BufferedImage camImage = null;
transient BufferedImage graphImage = null;
int width = 1024;
int height = 768;
int xyScale = 2;
ArrayList<ArrayList<Point>> left = new ArrayList<ArrayList<Point>>();
ArrayList<ArrayList<Point>> right = new ArrayList<ArrayList<Point>>();
ArrayList<ArrayList<Point>> history = new ArrayList<ArrayList<Point>>();
public Random rand = new Random();
public IRData lastIRData = null;
final String leftstr = "left";
final String rightstr = "right";
boolean calibrating = true;
int servoRightMax = 0;
IRData irRightMax = null;
int servoLeftMax = 0;
IRData irLeftMax = null;
int vheight = height / xyScale;
int vwidth = width / xyScale;
ArrayList<Point> hist = new ArrayList<Point>();
boolean staticInfo = false;
DecimalFormat df = new DecimalFormat("#.##");
int cnt = 0;
public WiiDARGUI(final String boundServiceName, final GUIService myService, final JTabbedPane tabs) {
super(boundServiceName, myService, tabs);
}
@Override
public void attachGUI() {
// subscribe("publishIR", "publishIR",
// IRData.class.getCanonicalName());
subscribe("publishSweepData", "publishSweepData", ArrayList.class);
subscribe("setServoLeftMax", "setServoLeftMax", Integer.class);
subscribe("setServoRightMax", "setServoRightMax", Integer.class);
subscribe("setIRLeftMax", "setIRLeftMax", Integer.class);
subscribe("setIRRightMax", "setIRRightMax", Integer.class);
subscribe("setCalibrating", "setCalibrating", Boolean.class);
}
protected ImageIcon createImageIcon(String path, String description) {
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
@Override
public void detachGUI() {
// unsubscribe("publishIR", "publishIR",
// IRData.class);
unsubscribe("publishSweepData", "publishSweepData", ArrayList.class);
unsubscribe("setServoLeftMax", "setServoLeftMax", Integer.class);
unsubscribe("setServoRightMax", "setServoRightMax", Integer.class);
unsubscribe("setIRLeftMax", "setIRLeftMax", Integer.class);
unsubscribe("setIRRightMax", "setIRRightMax", Integer.class);
unsubscribe("setCalibrating", "setCalibrating", Boolean.class);
}
public void displayFrame(SerializableImage camImage) {
screen.displayFrame(camImage);
}
// TODO - check for copy/ref of parameter moved locally
// TODO remove IREven
// find angle
public void displaySweepData(ArrayList<Point> points) {
int x;
int y;
int zScale = 8; // 11
int xOffset = vwidth / 2; // set origin of polar in middle
if (points != null) {
// blank screen
graph.setColor(Color.black);
graph.fillRect(0, 0, vwidth, vheight);
// draw static parts
graph.setColor(Color.gray);
int midh = (vheight) / 2;
int midw = (vwidth) / 2;
graph.drawLine(midw - 20, midh, midw + 20, midh);
graph.drawLine(midw, midh - 20, midw, midh + 20);
for (int i = 0; i < vheight; i += 60) {
graph.drawLine(0, vheight - i, vwidth, vheight - i);
}
// get the first and last point
Point first = points.get(0);
String dir = (first.direction == WiiDar.LEFT) ? "left" : "right";
// set appropriate color
Color color = (dir.compareTo(leftstr) == 0) ? Color.green : Color.red;
graph.setColor(color);
// draw first last info
/*
* int vpos =10; graph.drawString("smin " + servoRightMax + " smax " +
* servoLeftMax, 10, vpos); graph.drawString("pts " + points.size() +
* " midloc " + points.get(20).getX() + "," + points.get(20).getY(), 10,
* vpos+=10); graph.drawString("fs " + first.servoPos + " ls " +
* last.servoPos , 10, vpos+=10); graph.drawString("dir " + dir, 10,
* vpos+=10);
*/
Point p = null;
graph.setColor(Color.green);
for (int i = 0; i < points.size(); ++i) {
p = points.get(i);
// polar coordinates !
x = vwidth - ((int) (p.z * Math.cos(Math.toRadians(p.servoPos)) * zScale) + xOffset);
y = vheight - ((int) (p.z * Math.sin(Math.toRadians(p.servoPos)) * zScale));
graph.drawLine(x, y, x, y);
}
// draw history TODO - draw history first
/*
* history = (dir.compareTo(leftstr)==0)?left:right;
*/
int v = 180;
for (int i = 0; i < history.size(); ++i) {
ArrayList<Point> sweep = history.get(i);
graph.setColor(new Color(v, v, v));
for (int j = 0; j < sweep.size(); ++j) {
p = sweep.get(j);
x = vwidth - ((int) (p.z * Math.cos(Math.toRadians(p.servoPos)) * zScale) + xOffset);
y = vheight - ((int) (p.z * Math.sin(Math.toRadians(p.servoPos)) * zScale));
graph.drawLine(x, y, x, y);
}
v -= 30;
}
int maxHistory = 3;
history.add(WiiDar.copy(points));
p = history.get(0).get(0);
if (history.size() > maxHistory) {
history.remove(0);
}
screen.displayFrame(new SerializableImage(graphImage, boundServiceName));
} else {
log.error("points null");
}
}
public void drawStaticInfo() {
graph.setColor(Color.gray);
int inches = 0;
// 10 inches per 140 inches
int r = 160;
for (r = 160; r < vheight * 2; r += 160) {
inches += 10;
graph.drawArc(vwidth / 2 - r / 2, vheight - r / 2, r, r, 0, 180);
// graph.drawLine(0, vheight - i, vwidth, vheight - i);
// graph.drawArc(vwidth - 40, vheight, vheight - i - 5, vheight - i
// - 5, 0, 360);
// graph.drawArc(vwidth - 40, vheight, 30, 30, 0, 360);
// graph.drawArc(vwidth/2 - 100, vheight - 100, 200, 200, 0, 180);
graph.drawString("" + inches, vwidth / 2 + r / 2, vheight - 10);
}
staticInfo = true;
}
@Override
public VideoWidget getLocalDisplay() {
return screen;
}
@Override
public void init() {
screen = new VideoWidget(boundServiceName, myService, tabs);
screen.init();
camImage = new BufferedImage(width / xyScale, height / xyScale, BufferedImage.TYPE_INT_RGB);
graphImage = new BufferedImage(width / xyScale, height / xyScale, BufferedImage.TYPE_INT_RGB);
cam = camImage.getGraphics();
graph = graphImage.getGraphics();
graph.setColor(Color.green);
screen.displayFrame(new SerializableImage(graphImage, boundServiceName));
gc.gridx = 0;
gc.gridy = 0;
gc.gridheight = 4;
gc.gridwidth = 2;
display.add(screen.display, gc);
gc.gridx = 2;
gc.gridx = 0;
gc.gridheight = 1;
gc.gridwidth = 1;
gc.gridy = 5;
setCurrentFilterMouseListener();
}
public Point publishSinglePoint(Point p) {
int x;
int y;
int x0;
int y0;
int zScale = 8; // 11
int xOffset = vwidth / 2; // set origin of polar in middle
++cnt;
if (cnt % 180 == 0) {
// graph.setColor(Color.black);
// graph.fillRect(0, 0, vwidth, vheight);
drawStaticInfo();
}
// TODO add offset of wii to axis for polar (camera is not center of
// axis)
// calculate xy for p
x = ((int) (p.z * Math.cos(Math.toRadians(p.servoPos)) * zScale) + xOffset);
y = vheight - ((int) (p.z * Math.sin(Math.toRadians(p.servoPos)) * zScale));
// take care of history
if (hist.size() > 0) {
// get historical coordinates
Point h = hist.get(hist.size() - 1);
x0 = ((int) (h.z * Math.cos(Math.toRadians(h.servoPos)) * zScale) + xOffset);
y0 = vheight - ((int) (h.z * Math.sin(Math.toRadians(h.servoPos)) * zScale));
double distance = Math.sqrt((x0 - x) * (x0 - x) + (y0 - y) * (y0 - y));
// black out previous info
graph.setColor(Color.black);
graph.drawString(h.servoPos + " " + df.format(h.z), x0, y0 - 40);
graph.drawLine(x0, y0, x0, y0 - 40);
// gray out previous point
// graph.setColor(new Color(0,128,0));
// graph.drawLine(x0, y0, x0, y0);
graph.setColor(Color.green);
// draw line if under min distance from previous point
if (distance < 40) {
graph.drawLine(x, y, x0, y0);
}
// black historical lidar vector
graph.setColor(Color.black);
x0 = ((int) (5 * Math.cos(Math.toRadians(h.servoPos)) * zScale) + xOffset);
y0 = vheight - ((int) (5 * Math.sin(Math.toRadians(h.servoPos)) * zScale));
graph.drawLine(vwidth / 2, vheight, x0, y0);
}
int maxHistory = 180;
if (hist.size() > maxHistory) {
// aggressive removal - doesnt check on distance
graph.setColor(Color.black);
Point h = hist.remove(0);
x0 = ((int) (h.z * Math.cos(Math.toRadians(h.servoPos)) * zScale) + xOffset);
y0 = vheight - ((int) (h.z * Math.sin(Math.toRadians(h.servoPos)) * zScale));
Point h1 = hist.get(0);
int x1 = ((int) (h1.z * Math.cos(Math.toRadians(h1.servoPos)) * zScale) + xOffset);
int y1 = vheight - ((int) (h1.z * Math.sin(Math.toRadians(h1.servoPos)) * zScale));
graph.drawLine(x1, y1, x0, y0);
// remove line segment
}
// draw the point & info
if (p.z > 0) {
// draw point
graph.setColor(Color.green);
// x = vwidth - ((int)(p.z * Math.cos(Math.toRadians(p.servoPos)) *
// zScale) + xOffset);
// y = vheight - ((int) (p.z * Math.sin(Math.toRadians(p.servoPos))
// * zScale));
graph.drawLine(x, y, x, y);
graph.drawLine(x, y, x, y - 40);
graph.drawString(p.servoPos + " " + df.format(p.z), x, y - 40);
} else {
// out of range - dump the point
// return p; - need point to refresh lidar vector
}
// draw lidar vector
x = ((int) (5 * Math.cos(Math.toRadians(p.servoPos)) * zScale) + xOffset);
y = vheight - ((int) (5 * Math.sin(Math.toRadians(p.servoPos)) * zScale));
graph.setColor(Color.gray);
graph.drawLine(vwidth / 2, vheight, x, y);
hist.add(p);
// screen image
screen.displayFrame(new SerializableImage(graphImage, boundServiceName));
/*
* // send it to OpenCV if (cnt%20 == 0) { myService.invoke("processImage",
* Utils.copyImage(graphImage)); }
*/
return p;
}
public ArrayList<Point> publishSweepData(ArrayList<Point> d) {
displaySweepData(d);
return d;
}
public Boolean setCalibrating(Boolean t) {
calibrating = t;
return t;
}
// TODO - encapsulate this
// MouseListener mouseListener = new MouseAdapter() {
public void setCurrentFilterMouseListener() {
MouseListener mouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {
JList theList = (JList) mouseEvent.getSource();
if (mouseEvent.getClickCount() == 2) {
int index = theList.locationToIndex(mouseEvent.getPoint());
if (index >= 0) {
Object o = theList.getModel().getElementAt(index);
System.out.println("Double-clicked on: " + o.toString());
}
}
}
};
}
public IRData setIRLeftMax(IRData max) {
irLeftMax = max;
return max;
}
public IRData setIRRightMax(IRData max) {
irRightMax = max;
return max;
}
// inbound from publish points
public Integer setServoLeftMax(Integer max) {
servoLeftMax = max;
return max;
}
public Integer setServoRightMax(Integer max) {
servoRightMax = max;
return max;
}
@Override
public void valueChanged(ListSelectionEvent arg0) {
}
}