robotmap.php3 10.7 KB
Newer Older
1 2 3
<?php
#
# EMULAB-COPYRIGHT
4
# Copyright (c) 2004-2007 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16
# All rights reserved.
#
include("defs.php3");

#
# Standard Testbed Header
#
PAGEHEADER("Robot Map");

#
# Only logged in people at the moment; might open up at some point.
#
17 18 19
$this_user = CheckLoginOrDie();
$uid       = $this_user->uid();
$isadmin   = ISADMIN();
20

21 22 23 24 25 26 27 28 29 30 31 32
#
# Verify page args
#
$optargs = OptionalPageArguments("experiment",    PAGEARG_EXPERIMENT,
				 "building",      PAGEARG_STRING,
				 "floor",         PAGEARG_STRING,
				 "prefix",        PAGEARG_STRING,
				 "map_x",         PAGEARG_INTEGER,
				 "map_y",         PAGEARG_INTEGER,
				 "show_cameras",  PAGEARG_STRING,
				 "show_exclusion",PAGEARG_STRING);

33 34 35 36
# Careful with this local variable
unset($prefix);

#
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
# Verify page arguments. First allow user to optionally specify building/floor.
#
if (isset($building) && $building != "") {
    # Sanitize for the shell.
    if (!preg_match("/^[-\w]+$/", $building)) {
	PAGEARGERROR("Invalid building argument.");
    }
    # Optional floor argument. Sanitize for the shell.
    if (isset($floor) && !preg_match("/^[-\w]+$/", $floor)) {
	PAGEARGERROR("Invalid floor argument.");
    }
}
else {
    $building = "MEB-ROBOTS";
    $floor    = 4;
}
53 54 55 56 57 58

#
# Optional pid,eid. Without a building/floor, show all the nodes for the
# experiment in all buildings/floors. Without pid,eid show all wireless
# nodes in the specified building/floor.
#
59 60 61 62 63 64
if (isset($experiment)) {
    $pid = $experiment->pid();
    $eid = $experiment->eid();
    if (! $experiment->AccessCheck($this_user, $TB_EXPT_READINFO)) {
	USERERROR("You do not have permission to view robotmaps ".
		  "for experiment $pid/$eid!", 1);
65 66 67 68
    }
}

#
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
# map_x and map_y are the map.x and map.y coordinates from clicking on the map.
#
if (isset($map_x) && $map_x != "") {
    # Sanitize for the shell.
    if (!preg_match("/^[0-9]+$/", $map_x)) {
	PAGEARGERROR("Invalid map_x argument.");
    }
}
else {
    unset($map_x);
}
if (isset($map_y) && $map_y != "") {
    # Sanitize for the shell.
    if (!preg_match("/^[0-9]+$/", $map_y)) {
	PAGEARGERROR("Invalid map_y argument.");
    }
}
else {
    unset($map_y);
}

#
# Assume a single image for the robot map. When user clicks, pixel
# coords correspond to building and floor.
93
#
94 95 96 97 98 99 100
$query_result =
    DBQueryFatal("select * from floorimages where ".
		 "building='$building' and floor='$floor'");
if (mysql_num_rows($query_result)) {
    $row = mysql_fetch_array($query_result);
    $pixels_per_meter = $row["pixels_per_meter"];
}
101

102 103 104 105
#
# Build a table of location info to print in table below image.
#
$locations = array();
106
$vnames = array();
107 108

$query_result =
109
    DBQueryFatal("select loc.*,r.vname,r.pid,r.eid from location_info as loc ".
110
		 "left join reserved as r on r.node_id=loc.node_id ".
111
		 "where loc.floor='$floor' and loc.building='$building'");
112 113 114

while ($row = mysql_fetch_array($query_result)) {
    $node_id   = $row["node_id"];
115 116
    $loc_x     = $row["loc_x"];
    $loc_y     = $row["loc_y"];
117
    $loc_z     = $row["loc_z"];
Leigh Stoller's avatar
Leigh Stoller committed
118
    $orient    = $row["orientation"];
119

120 121 122 123
    if ((isset($experiment) &&
	 $pid == $row["pid"] &&
	 $eid == $row["eid"]) &&
	 isset($row["vname"])) {
124
	$vnames[$node_id] = $row["vname"];
125
    }
126

127
    if (isset($pixels_per_meter) && $pixels_per_meter) {
128 129
	$meters_x = sprintf("%.2f", $loc_x / $pixels_per_meter);
	$meters_y = sprintf("%.2f", $loc_y / $pixels_per_meter);
130

131 132 133 134 135
	$locations[$node_id] = "x=$meters_x, y=$meters_y meters";
    }
    else {
	$locations[$node_id] = "x=$loc_x, y=$loc_y pixels";
    }
136 137 138
    if (isset($loc_z)) {
	$locations[$node_id] .= ", z=" . sprintf("%.2f", $loc_z) . " meters";
    }
Leigh Stoller's avatar
Leigh Stoller committed
139
    if (isset($orient)) {
140
	$locations[$node_id] .= ", o=" . sprintf("%.1f", $orient) . "&#176;";
Leigh Stoller's avatar
Leigh Stoller committed
141
    }
142 143
}

144
$event_time_start = array();
145
if (isset($experiment)) {
146 147 148 149 150 151 152 153 154 155 156
    $query_result =
	DBQueryFatal("SELECT parent,arguments FROM eventlist WHERE " .
		     "pid='$pid' and eid='$eid' and objecttype=3 and ".
		     "eventtype=1 ORDER BY parent");
    if (mysql_num_rows($query_result)) {
	while ($row = mysql_fetch_array($query_result)) {
	    $event_time_start[$row["parent"]] = $row["arguments"];
	}
    }
}

157
#
158 159 160
# Run the Perl script. It will produce three output files; image, areamap,
# and state. We want to embed all of these images into the page we
# send back. This is painful!  
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
#
# Need cleanup "handler" to make sure temp files get deleted! 
#
function CLEANUP()
{
    global $prefix;
    
    if (isset($prefix) && (connection_aborted())) {
	unlink("${prefix}.jpg");
	unlink("${prefix}.map");
	unlink("${prefix}.state");
	unlink($prefix);
    }
    exit();
}
register_shutdown_function("CLEANUP");

#
# Create a tempfile to use as a unique prefix; it is not actually used but
# serves the same purpose (The script uses ${prefix}.jpg and ${prefix}.map .)
# 
$prefix = tempnam("/tmp", "floormap");

#
# Get the unique part to send back.
#
if (!preg_match("/^\/tmp\/([-\w]+)$/", $prefix, $matches)) {
    TBERROR("Bad tempnam: $prefix", 1);
}
$uniqueid = $matches[1];

192 193
$perl_args = ("-o $prefix -t -z -n " .
	      # From clicking on a map image.
194 195 196 197
	      ((isset($show_cameras) &&
		strcmp($show_cameras, "Yep") == 0) ? "-v " : "") .
	      ((isset($show_exclusion) &&
		strcmp($show_exclusion, "Yep") == 0) ? "-x " : "") .
198 199
	      (isset($map_x) ? "-c $map_x,$map_y " : "") .
	      (isset($floor) ? "-f $floor " : "") .
200
	      (isset($experiment) ? "-e $pid,$eid " : "") .
201
	      (isset($building) ? "$building" : ""));  # Building arg must be last!
202 203 204 205

if (0) {    ### Put the Perl script args into the page when debugging.
    echo "\$btfv/floormap -d $perl_args\n";
}
206 207
$retval = SUEXEC($uid, "nobody", "webfloormap $perl_args",
		 SUEXEC_ACTION_IGNORE);
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222

if ($retval) {
    SUEXECERROR(SUEXEC_ACTION_USERERROR);
    # Never returns.
    die("");
}

#
# Spit the areamap contained in the file out; it is fully formatted and
# called "floormap".
#
if (! readfile("${prefix}.map")) {
    TBERROR("Could not read ${prefix}.map", 1);
}

223
if (isset($experiment)) {
224 225 226 227 228 229
    echo "<font size=+2>Robots in experiment <b>".
         "<a href='showproject.php3?pid=$pid'>$pid</a>/".
         "<a href='showexp.php3?pid=$pid&eid=$eid'>$eid</a></b> </font>\n";
    echo "<br /><br />\n";
}

230 231
echo "<center>\n";

232
# Wrap the image and zoom controls together in an input form.
233 234 235
echo "<form method=post action='robotmap.php3" .
       ((isset($building) && isset($floor)) ?
	"?building=${building}&floor=${floor}" : "") . "'>";
236

237
echo "Click on the image to get its X,Y coordinates<br>\n";
238
# The image may be clicked to get node info or set a new center-point.
239
if ($isadmin || $this_user->WebCamAllowed()) {
Leigh Stoller's avatar
Leigh Stoller committed
240
    echo "  <a href=webcam.php3>Webcam View</a> (Updated in real time)";
241 242
    echo "  <br>\n";
}
243 244
echo "  <a href=robotrack/robotrack.php3?building=${building}&floor=${floor}>".
        "Track robots in real time</a>";
245 246
echo "  <a href=robotrack/robotrack.php3?building=${building}&floor=${floor}&withwebcams=1>".
        " (with webcams)</a>";
Leigh Stoller's avatar
Leigh Stoller committed
247
echo "  <br>\n";
248 249 250 251 252 253

if (isset($map_x) && isset($map_y)) {
    if (isset($pixels_per_meter) && $pixels_per_meter) {
	$meters_x = sprintf("%.3f", $map_x / $pixels_per_meter);
	$meters_y = sprintf("%.3f", $map_y / $pixels_per_meter);
    
254
	echo "Last click location was x=<b>$meters_x</b>, y=<b>$meters_y</b> meters.\n";
255 256 257 258 259 260
    }
    else {
	echo "Last click location was x=$map_x, y=$map_y pixels\n";
    }
    echo "<br>\n";
}
261

262
if (isset($experiment)) {
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
    $current_time = time();
    foreach ($event_time_start as $key => $value) {
	$event_time_elapsed = $current_time - $value;
	if ($key == "") {
	    echo "Elapsed event time: ";
	}
	else {
	    echo "Elapsed time for timeline '$key': ";
	}
	$minutes = floor($event_time_elapsed / 60);
	$seconds = $event_time_elapsed % 60;
	echo "<b>" . $minutes . "m " . $seconds . "s </b>(<b>" .
		sprintf("%.1f", $event_time_elapsed) . "s</b>)<br>";
    }
    if (empty($event_time_start)) {
	echo "<i><b>Elapsed event time: Not started yet</b></i>";
    }
}

282 283 284 285 286 287
echo "  <input name=map type=image style=\"border: 2px solid\" ";
echo          "src=\"floormap_aux.php3?prefix=$uniqueid\" ".
              "usemap=\"#floormap\">\n";

echo "  <br>\n";

288 289
# Hidden items are all returned as page arguments when any input control
# is clicked.
290 291
echo "  <input type=\"hidden\" name=\"prefix\" value=\"$uniqueid\">\n";

292 293 294 295 296
if (isset($pid)) {
    echo "  <input type=\"hidden\" name=\"pid\" value=\"$pid\">\n";
    echo "  <input type=\"hidden\" name=\"eid\" value=\"$eid\">\n";
}

297 298 299 300 301
# The last_* items come from a .state file with the map, from the Perl script.
if (! readfile("${prefix}.state")) {
    TBERROR("Could not read ${prefix}.state", 1);
}

302 303 304 305 306 307 308 309 310 311
echo "<br>
      <table cellspacing=5 cellpadding=5 border=0 class=\"stealth\"
             bgcolor=\"#ffffff\">
      <tr>";

echo "<td align=\"left\" valign=\"top\" class=\"stealth\">
      <table>
      <tr><th colspan=2>Legend</th></tr>
      <tr>
          <td><img src=\"floormap/map_legend_node.gif\"></td>
312 313
          <td>Robot Actual Position<br>
              <font size=\"-1\">(Click dots for more information)</font></td>
314 315 316 317 318 319 320
      </tr>
      <tr>
          <td><img src=\"floormap/map_legend_node_dst.gif\"></td>
          <td>Robot Destination Position</td>
      </tr>
      </table>
      </td>";
321 322

if (count($locations)) {
323
    echo "<td align=\"left\" valign=\"top\" class=\"stealth\">";
324 325 326 327
    echo "<table align=center border=2 cellpadding=0 cellspacing=2>
 	  <tr><th>Node</th><th>Location</th></tr>\n";
    
    while (list($node_id, $location) = each($locations)) {
328 329 330 331 332 333 334 335 336
	if ((!isset($pid) && !isset($eid)) || isset($vnames[$node_id])) {
	    if (isset($vnames[$node_id]))
		$name = $vnames[$node_id];
	    else
		$name = $node_id;
	    echo "<tr>
              <td><a href=\"shownode.php3?node_id=$node_id\">$name</a></td>
              <td>$location</td> </tr>\n";
	}
337
    }
338 339 340
    echo "</table></td>\n";
}

341 342
if (isset($show_cameras) &&
    strcmp($show_cameras, "Yep") == 0) {
343
	$cam_checked = "checked";
344
}
345 346 347 348
else {
	$cam_checked = "";
}

349 350
if (isset($show_exclusion) &&
    strcmp($show_exclusion, "Yep") == 0) {
351 352 353 354 355 356 357 358 359 360 361
	$excl_checked = "checked";
}
else {
	$excl_checked = "";
}

echo "<td align=\"left\" valign=\"top\" class=\"stealth\">
      <table>
      <tr><th>Display Options</th></tr>
      <tr>
          <td><input type=checkbox
362
                     name=show_cameras
363
                     value=Yep
364 365 366
                     $cam_checked>Show <a
 href=\"doc/docwrapper.php3?docname=mobilewireless.html#VISION\">Tracking
 Camera</a> Bounds</input></td>
367 368 369
      </tr>
      <tr>
          <td><input type=checkbox
370
                     name=show_exclusion
371
                     value=Yep
372 373 374
                     $excl_checked>Show <a
 href=\"doc/docwrapper.php3?docname=mobilewireless.html#VISION\">Exclusion
 Zones</a></input></td>
375 376 377 378 379 380 381 382
      </tr>
      <tr><td colspan=2 align=center><input type=submit value=Update></td></tr>
      </table>
      </td>";

echo "</tr></table>\n";

echo "</form>\n";
383

384 385 386 387 388 389 390
echo "</center>\n";

#
# Standard Testbed Footer
# 
PAGEFOOTER();
?>