Commit 194773ba authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Add exclusion and camera bound checking.

parent 274cc4bb
......@@ -151,6 +151,12 @@ public class RoboTrack extends JApplet {
map.stop();
}
// Simply for the benefit of running from the shell for testing.
public void init(boolean fromshell) {
shelled = fromshell;
init();
}
/*
* A thing that waits for an image to be loaded.
*/
......@@ -206,12 +212,33 @@ public class RoboTrack extends JApplet {
Vector robotmap = new Vector(10, 10);
int robotcount = 0;
/*
* A container for obstacle information.
*/
private class Obstacle {
int id; // DB identifier; not actually used.
int x1, y1; // Upper left x,y coords in pixels.
int x2, y2; // Lower right x,y coords in pixels.
String description;
}
Vector Obstacles = new Vector(10, 10);
/*
* A container for camera information.
*/
private class Camera {
String name; // DB identifier; not actually used.
int x1, y1; // Upper left x,y coords in pixels.
int x2, y2; // Lower right x,y coords in pixels.
}
Vector Cameras = new Vector(10, 10);
private class Map extends JPanel implements Runnable {
private Thread thread;
private BufferedImage bimg;
private Graphics2D G2 = null;
// The DOT radius.
// The DOT radius. This is radius of the circle of the robot.
int DOT_RAD = 20;
// The length of the orientation stick, from the center of the circle.
int STICK_LEN = 20;
......@@ -220,6 +247,13 @@ public class RoboTrack extends JApplet {
int LABEL_Y = 20;
public Map() {
/*
* Request obstacle list when a real applet.
*/
if (!shelled) {
GetObstacles();
GetCameras();
}
}
/*
......@@ -362,11 +396,11 @@ public class RoboTrack extends JApplet {
while (e.hasMoreElements()) {
Robot robbie = (Robot)e.nextElement();
if ((Math.abs(robbie.y - y) < 10 &&
Math.abs(robbie.x - x) < 10) ||
if ((Math.abs(robbie.y - y) < DOT_RAD/2 &&
Math.abs(robbie.x - x) < DOT_RAD/2) ||
(robbie.dragging &&
Math.abs(robbie.drag_y - y) < 10 &&
Math.abs(robbie.drag_x - x) < 10)) {
Math.abs(robbie.drag_y - y) < DOT_RAD/2 &&
Math.abs(robbie.drag_x - x) < DOT_RAD/2)) {
return robbie.pname;
}
}
......@@ -374,8 +408,114 @@ public class RoboTrack extends JApplet {
}
/*
* Draw some buttons.
* Check for overlap with exclusions zones (obstacles). We check
* all the robots that are dragging, and popup a dialog box if
* we find one. The user then has to fix it.
*
* XXX I am treating the robot as a square! Easier to calculate.
*
* XXX The value below (OBSTACLE_BUFFER) is hardwired in floormap
* code (where the base image is generated).
*/
int OBSTACLE_BUFFER = 23;
public boolean CheckforCollisions() {
Enumeration robot_enum = robots.elements();
while (robot_enum.hasMoreElements()) {
Robot robbie = (Robot)robot_enum.nextElement();
if (!robbie.dragging)
continue;
int rx1 = robbie.drag_x - ((DOT_RAD/2) + OBSTACLE_BUFFER);
int ry1 = robbie.drag_y - ((DOT_RAD/2) + OBSTACLE_BUFFER);
int rx2 = robbie.drag_x + ((DOT_RAD/2) + OBSTACLE_BUFFER);
int ry2 = robbie.drag_y + ((DOT_RAD/2) + OBSTACLE_BUFFER);
//System.out.println("CheckCollision: " + rx1 + "," +
// ry1 + "," + rx2 + "," + ry2);
/*
* Check for overlap of this robot with each obstacle.
*/
for (int index = 0; index < Obstacles.size(); index++) {
Obstacle obstacle = (Obstacle) Obstacles.elementAt(index);
int ox1 = obstacle.x1;
int oy1 = obstacle.y1;
int ox2 = obstacle.x2;
int oy2 = obstacle.y2;
//System.out.println(" " + ox1 + "," +
// oy1 + "," + ox2 + "," + cy2);
if (! (oy2 < ry1 ||
ry2 < oy1 ||
ox2 < rx1 ||
rx2 < ox1)) {
MyDialog("Collision",
robbie.pname + " overlaps with an obstacle");
return true;
}
}
}
return false;
}
/*
* Check for robots wandering out of camera range. We check
* all the robots that are dragging, and popup a dialog box if
* we find one. The user then has to fix it.
*
* XXX I am treating the robot as a square! Easier to calculate.
*/
public boolean CheckOutOfBounds() {
Enumeration robot_enum = robots.elements();
while (robot_enum.hasMoreElements()) {
Robot robbie = (Robot)robot_enum.nextElement();
int index;
if (!robbie.dragging)
continue;
int rx1 = robbie.drag_x - ((DOT_RAD/2));
int ry1 = robbie.drag_y - ((DOT_RAD/2));
int rx2 = robbie.drag_x + ((DOT_RAD/2));
int ry2 = robbie.drag_y + ((DOT_RAD/2));
//System.out.println("CheckOutOfBounds: " + rx1 + "," +
// ry1 + "," + rx2 + "," + ry2);
/*
* Check for full overlap with at least one camera.
*/
for (index = 0; index < Cameras.size(); index++) {
Camera camera = (Camera) Cameras.elementAt(index);
int cx1 = camera.x1;
int cy1 = camera.y1;
int cx2 = camera.x2;
int cy2 = camera.y2;
//System.out.println(" " + cx1 + "," +
// cy1 + "," + cx2 + "," + cy2);
if ((rx1 >= cx1 &&
ry1 >= cy1 &&
rx2 <= cx2 &&
ry2 <= cy2))
break;
}
if (index == Cameras.size()) {
MyDialog("Out of Bounds",
robbie.pname + " is out of camera range");
return true;
}
}
return false;
}
/*
* Draw a robot, which is either the real one, a destination one,
......@@ -1047,13 +1187,157 @@ public class RoboTrack extends JApplet {
maptable.clearSelection();
}
else if (source == SubmitMenuItem) {
SendInDestinations();
/*
* Check for collisions before submitting.
*/
if (! map.CheckforCollisions() &&
! map.CheckOutOfBounds())
SendInDestinations();
}
repaint();
maptable.repaint(10);
}
}
/*
* Get the Obstacle list from the server.
*/
public boolean GetObstacles() {
String urlstring = "obstacles.php3?fromapplet=1"
+ "&nocookieuid="
+ URLEncoder.encode(uid)
+ "&nocookieauth="
+ URLEncoder.encode(auth);
try
{
URL url = new URL(getCodeBase(), urlstring);
URLConnection urlConn;
InputStream is;
String str;
int index = 0;
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setUseCaches(false);
is = urlConn.getInputStream();
BufferedReader input
= new BufferedReader(new InputStreamReader(is));
Obstacles = new Vector(10, 10);
/*
* This should be in XML format.
*/
while ((str = input.readLine()) != null) {
System.out.println(str);
StringTokenizer tokens = new StringTokenizer(str, ",");
String tmp;
Obstacle obstacle = new Obstacle();
/*
* Convert from meters to pixels ...
*/
obstacle.id = Integer.parseInt(tokens.nextToken().trim());
obstacle.x1 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
obstacle.y1 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
obstacle.x2 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
obstacle.y2 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
obstacle.description = tokens.nextToken().trim();
Obstacles.insertElementAt(obstacle, index++);
}
is.close();
}
catch(Throwable th)
{
MyDialog("GetObstacles",
"Failed to get obstacle list from server");
th.printStackTrace();
return false;
}
return true;
}
/*
* Get the Camera list from the server.
*/
public boolean GetCameras() {
String urlstring = "cameras.php3?fromapplet=1"
+ "&nocookieuid="
+ URLEncoder.encode(uid)
+ "&nocookieauth="
+ URLEncoder.encode(auth);
try
{
URL url = new URL(getCodeBase(), urlstring);
URLConnection urlConn;
InputStream is;
String str;
int index = 0;
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setUseCaches(false);
is = urlConn.getInputStream();
BufferedReader input
= new BufferedReader(new InputStreamReader(is));
Cameras = new Vector(10, 10);
/*
* This should be in XML format.
*/
while ((str = input.readLine()) != null) {
System.out.println(str);
StringTokenizer tokens = new StringTokenizer(str, ",");
String tmp;
Camera camera = new Camera();
/*
* Convert from meters to pixels ...
*/
camera.name = tokens.nextToken().trim();
camera.x1 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
camera.y1 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
camera.x2 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
camera.y2 = (int)
(Double.parseDouble(tokens.nextToken().trim())
* pixels_per_meter);
Cameras.insertElementAt(camera, index++);
}
is.close();
}
catch(Throwable th)
{
MyDialog("GetCameras",
"Failed to get camera list from server");
th.printStackTrace();
return false;
}
return true;
}
/*
* Send all destinations into the web server.
*/
......@@ -1062,7 +1346,7 @@ public class RoboTrack extends JApplet {
// Its a POST, so no leading "?" for the URL arguments.
String urlstring = "fromapplet=1"
+ "nocookieuid="
+ "&nocookieuid="
+ URLEncoder.encode(uid)
+ "&nocookieauth="
+ URLEncoder.encode(auth);
......@@ -1126,11 +1410,7 @@ public class RoboTrack extends JApplet {
input.close();
if (str.length() > 0) {
System.out.println(str);
JOptionPane.showMessageDialog(getContentPane(),
str, "Submit Failed",
JOptionPane.ERROR_MESSAGE);
MyDialog("Setdest Submission Failed", str);
}
}
catch(Throwable th)
......@@ -1140,15 +1420,25 @@ public class RoboTrack extends JApplet {
return true;
}
/*
* Utility function to pop up a dialog box.
*/
public void MyDialog(String title, String msg) {
System.out.println(title + " - " + msg);
JOptionPane.showMessageDialog(getContentPane(),
msg, title,
JOptionPane.ERROR_MESSAGE);
}
public static void main(String argv[]) {
final RoboTrack robomap = new RoboTrack();
try
{
URL url = new URL("file://robots-4.jpg");
robomap.init();
robomap.init(true);
robomap.is = System.in;
robomap.floorimage = robomap.getImage(url);
robomap.shelled = true;
robomap.uid = "stoller";
robomap.auth = "xyz";
}
......
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002, 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
chdir("..");
include("defs.php3");
#
# Only known and logged in users can watch LEDs
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
#
# One robot map right now ...
#
$building = "MEB-ROBOTS";
$floor = 4;
# Initial goo.
header("Content-Type: text/plain");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
flush();
#
# Clean up when the remote user disconnects
#
function SPEWCLEANUP()
{
exit(0);
}
register_shutdown_function("SPEWCLEANUP");
# Get the obstacle information.
$query_result =
DBQueryFatal("select * from cameras ".
"where building='$building' and floor='$floor'");
while ($row = mysql_fetch_array($query_result)) {
$name = $row["name"];
$x1 = $row["loc_x"];
$y1 = $row["loc_y"];
$x2 = $x1 + $row["width"];
$y2 = $y1 + $row["height"];
echo "$name, $x1, $y1, $x2, $y2\n";
}
?>
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002, 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
chdir("..");
include("defs.php3");
#
# Only known and logged in users can watch LEDs
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
#
# One robot map right now ...
#
$building = "MEB-ROBOTS";
$floor = 4;
# Initial goo.
header("Content-Type: text/plain");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
flush();
#
# Clean up when the remote user disconnects
#
function SPEWCLEANUP()
{
exit(0);
}
register_shutdown_function("SPEWCLEANUP");
#
# Get the obstacle information. This stuff is in pixels, but we want to
# always send meters to the applet.
#
$query_result =
DBQueryFatal("select o.*,f.pixels_per_meter from obstacles as o ".
"left join floorimages as f on ".
" o.building=f.building and o.floor=f.floor ".
"where o.building='$building' and o.floor='$floor'");
while ($row = mysql_fetch_array($query_result)) {
$id = $row["obstacle_id"];
$x1 = $row["x1"];
$y1 = $row["y1"];
$x2 = $row["x2"];
$y2 = $row["y2"];
$desc = $row["description"];
$ppm = $row["pixels_per_meter"];
if (!isset($desc))
$desc = "";
$meters_x1 = sprintf("%.4f", $x1 / $ppm);
$meters_y1 = sprintf("%.4f", $y1 / $ppm);
$meters_x2 = sprintf("%.4f", $x2 / $ppm);
$meters_y2 = sprintf("%.4f", $y2 / $ppm);
echo "$id, $meters_x1, $meters_y1, $meters_x2, $meters_y2, $desc\n";
}
?>
......@@ -77,7 +77,7 @@ if (!preg_match("/^\/tmp\/([-\w]+)$/", $prefix, $matches)) {
}
$uniqueid = $matches[1];
$perl_args = "-o $prefix -t -z -n -x -y -f $floor $building";
$perl_args = "-o $prefix -t -z -n -x -v -y -f $floor $building";
$retval = SUEXEC($uid, "nobody", "webfloormap $perl_args",
SUEXEC_ACTION_IGNORE);
......@@ -122,7 +122,10 @@ echo "<br>
moves (start the robots on their way), or cancel the moves.
<li> Only one move per robot at a time.
<li> To change just the orientation (no drag), edit the destination
orientation column in the table.
orientation column in the table.
<li> A robot destination must not overlap an obstacle (shaded area,
blue border), and it must be fully within the field of view of at
least one camera (orange boxes).
</ul>
<blockquote><blockquote>\n";
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment