#!/usr/bin/perl -w # # mapselect CGI for the ZazaMap applet, poslib and the web control # interface. Used to select the map and starting position for the # robot when in Phase III/IV mode. # # Copyright (C) 2003 Brian Rudy (brudyNO@SPAMpraecogito.com) # # This program 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. # # This program is distributed in the hope that it will be useful, # 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. # # # Requires: poslib.pl # CGI::Request # CGI::LogCarp # LWP::Simple; # Image::Magick; # LWP::Simple; # # ## Revision History ## # 0.01 10-10-2003 # First working version. # require "/home/brudy/posServer/poslib.pl"; #use Config::IniFiles; # this is loaded through poslib.pl use CGI::Request; use CGI::LogCarp qw(:STDLOG); use Apache::Constants ':common'; use Image::Magick; use LWP::Simple; # Full Interface: my $req = new CGI::Request; # fetch and parse request my $clientip = $req->cgi->var("REMOTE_ADDR"); my $clientpath = $req->cgi->var("HTTP_REFERER"); my $tlmap_dir = "/home/brudy/posServer/maps"; my $html_dir = "/var/www/html/mapselect"; my $bee_bin_dir = "/home/brudy/bee/bin"; #my $robot_image = "/home/brudy/public_html/zaza/java/images/robot.gif"; #my $robot_image = "/home/brudy/public_html/zaza/java/images/robot3.png"; my $robot_image = "/home/brudy/public_html/zaza/java/images/robot4.png"; print "\n"; if (!poslib::isuberclient($clientip)) { # This IP is not an uberclient, let's see if they have authenticated if (($clientpath =~ m/brudy\/internal\//) || ($clientpath =~ m/cgi-bin\/zaza-control/) || ($clientpath =~ m/cgi-bin\/mapselect/)) { # It's ok, they have authenticated } else { print"
 Sorry " . $clientip . ", you are not allowed to select maps.<\/pre><\/html>\n";
    die "$clientip attempted to use the mapselect CGI!\n";
  }
}

if ($req->param('set_map') eq '') {
  # create the map selection window

  # dump header info
  print<
  
  mapselect
  


Select Map

HEADER # index directories opendir(DIR, $tlmap_dir) || die "Can't open top level map directory!"; my @directories = grep { !/^\./ && !/params/ && -d "$tlmap_dir/$_" } readdir(DIR); closedir(DIR); # clear out anything left over from the last run system("rm $html_dir/*_map.gif"); my $firsttime = 1; foreach $directory (@directories) { # Open the ini file for this map my $inifile = new Config::IniFiles( -file => "$tlmap_dir/$directory/mapselect.ini"); # Skip any map that isn't enabled if ($inifile->val( 'Map', 'Enabled') =~ m/yes|1/i) { if (!-e "$tlmap_dir/$directory/map_image/map.gif") { # create images if needed create_applet_image("$tlmap_dir/$directory"); } # copy images to web accessable location system("cp $tlmap_dir/$directory/map_image/map.gif $html_dir/$directory" . "_map.gif"); # dump table HTML for this map if (!$firsttime) { print "

\n"; } print "
\"$directory\" <\/a> <\/td> <\/tr>
$directory<\/strong>
<\/td> <\/tr>
Areas: " . $inifile->val( 'Map', 'Areas' ) . "
<\/td> <\/tr>
" . $inifile->val( 'Map', 'Description') . " <\/small> <\/td> <\/tr> <\/tbody> <\/table>

\n"; $firsttime = 0; } } print "<\/body>\n"; } elsif($req->param('set_startpos') eq '') { # create the start position selector my $directory = $req->param('set_map'); # Open the ini file for this map my $inifile = new Config::IniFiles( -file => "$tlmap_dir/$directory/mapselect.ini") or die "Error opening the config file for $directory!"; my @Descriptions = $inifile->val( 'Start_Positions', 'Description'); my @Xs = $inifile->val( 'Start_Positions', 'X'); my @Ys = $inifile->val( 'Start_Positions', 'Y'); my @Thetas = $inifile->val( 'Start_Positions', 'Theta'); # Delete the images from the last run system("rm $html_dir/$directory" . "_startpos*"); # dump header info print< mapselect

Select Start Position

HEADER2 # create thumbnail images of start positions for $index (0 .. $#Descriptions) { create_startpos_thumb($index, $directory, $Xs[$index], $Ys[$index], $Thetas[$index]); # Dump the table HTML print "
\"$Descriptions[$index]\" <\/a> <\/td> <\/tr>
$Descriptions[$index]<\/small><\/td> <\/tr> <\/tbody> <\/table>
\n"; } print "<\/body>\n"; } elsif(($req->param('set_startpos') ne '') && ($req->param('set_map') ne '')) { # load em up my $directory = $req->param('set_map'); # Open the ini file for this map my $inifile = new Config::IniFiles( -file => "$tlmap_dir/$directory/mapselect.ini") or die "Error opening the config file for $directory!"; my @Descriptions = $inifile->val( 'Start_Positions', 'Description'); my @Xs = $inifile->val( 'Start_Positions', 'X'); my @Ys = $inifile->val( 'Start_Positions', 'Y'); my @Thetas = $inifile->val( 'Start_Positions', 'Theta'); my $x = $Xs[$req->param('set_startpos')]; my $y = $Ys[$req->param('set_startpos')]; my $theta = $Thetas[$req->param('set_startpos')]; # begin the startup sequence if (is_error(getprint("http://zaza1/cgi-bin/zaza-control-simple?op_mode=Test"))) { print "
";
     print "Error, could not reach zaza1!\n";
     print "
"; } else { print "
";
     print "Starting zazaconsole processes...\n";

     system("/home/brudy/posServer/speakit2.pl Starting localizer! >/dev/null 2>&1 &") == 0
         or print "speakit2.pl execution failed: $?";   

     # plan -nodisplay
     # SET_ROBOT -pos 2235 3885 153 -sim
     # LOCALIZE tech-ex.ini
     # poslibtcx -gmap /home/brudy/bee/data/localize/tech-ex/map-ex.map
     # obstacleServer /home/brudy/bee/data/localize/tech-ex/map-ex.planmap

     system("/home/brudy/posServer/reaction-up.pl 2>&1 &") == 0
         or print "reaction startup failed: $?";

     system("export TCXHOST=zaza1; cd /home/brudy/bee/bin; ./plan -nodisplay >/var/www/html/logs/plan.log 2>&1 &") == 0
         or print "plan startup failed: $?";

     system("export TCXHOST=zaza1; cd /home/brudy/bee/bin; ./SET_ROBOT -pos $x $y $theta -sim >/var/www/html/logs/SET_ROBOT.log 2>&1 &") == 0
         or print "SET_ROBOT startup failed: $?";
     sleep 1;
     system("export TCXHOST=zaza1; cd $tlmap_dir/$directory; /home/brudy/bee/bin/LOCALIZE localize.ini >/var/www/html/logs/LOCALIZE.log 2>&1 &") == 0
         or print "LOCALIZE startup failed: $?";

     system("export TCXHOST=zaza1; cd /home/brudy/bee/bin; ./poslibtcx -gmap $tlmap_dir/$directory/map.map >/var/www/html/logs/poslibtcx.log 2>&1 &") == 0
         or print "poslibtcx startup failed: $?";

     # Push the goals for this map into shared memory for poslib
     poslib::set_poslib_goals("$tlmap_dir/$directory/goals.ini");
     
     system("export TCXHOST=zaza1; cd /home/brudy/bee/bin; ./obstacleServer $tlmap_dir/$directory/map.planmap >/var/www/html/logs/obstacleServer.log 2>&1 &") == 0
         or print "obstacleServer startup failed: $?";
     sleep 3;

     # Update the shm for poslib so clients will now get the applet window 
     poslib::set_applet_timer(0); # Countdown=0
     poslib::set_applet_enabled(1);

     system("/home/brudy/posServer/speakit2.pl Startup Complete! >/dev/null 2>&1 &") == 0
         or print "speakit2.pl execution failed: $?";   



  # reset the process monitor window
  print<
   onload = function() {
    parent.proc.window.location="/~brudy/internal/proc.html"
    }
   
JSCRIPT1
  }   
} 
else {
  # oops, something isn't right...
}
print "<\/html>\n";



# Create the thumbnails for the start position selector
sub create_startpos_thumb {
  my ($index,$mapname,$x,$y,$theta) = @_;

  my $zoom = 5;
  # Open robot image
  my $robotimage = Image::Magick->new;
  
  #open(IMAGE, $robot_image);
  #$robotimage->Read(file=>\*IMAGE);
  #close(IMAGE);
  $robotimage->Read($robot_image);

  $robotimage->Set(antialias=>'True');
  #$robotimage->Set(antialias=>'False');
  $robotimage->Transparent(color=>'white');
  #$robotimage->Set(quality=>'100');

  # scale the image to roughly 2xRadius (2x26.7/15)
  #$robotimage->Scale(width=>(5*$zoom), height=>(5*$zoom));
  $robotimage->Sample(width=>(5*$zoom), height=>(5*$zoom));
  my $robotwidth=$robotimage->Get('width');
  my $robotheight=$robotimage->Get('height');

  # Open map image
  my $mapimage = Image::Magick->new;
  #open(IMAGE, "$tlmap_dir/$mapname/map_image/map.gif");
  #$mapimage->Read(file=>\*IMAGE);
  #close(IMAGE);
  $mapimage->Read("$tlmap_dir/$mapname/map_image/map.gif");

  # Convert the X and Y to image format
  my $Y = ($mapimage->Get('height') - ($y/15))*$zoom;
  my $X = ($x/15)*$zoom;
  my $Theta = 360-$theta;

  my $mapwidth = $mapimage->Get('width');
  my $mapheight =  $mapimage->Get('height');
  #$mapimage->Scale(width=>($mapwidth*$zoom), height=>($mapheight*$zoom));
  $mapimage->Sample(width=>($mapwidth*$zoom), height=>($mapheight*$zoom));

  # rotate robot image n degrees
  $robotimage->Rotate(degrees=>$Theta, color=>'white');
  #$robotimage->Trim;
  #$robotimage->Enhance;
  #$robotimage->Quantize(colors=>'3', treedepth=>'3');
  #$robotimage->Despeckle;
  
  $mapimage->Transparent(color=>'white');
  $mapimage->Set(antialias=>'True');
  # composite rotated robot image at x,y on map image
  my $xpos = $X - ($robotwidth/2);
  my $ypos = $Y - ($robotheight/2);
  $mapimage->Composite(image=>$robotimage, x=>$xpos, y=>$ypos, compose=>'Over');
  #$mapimage->Composite(image=>$robotimage, x=>$xpos, y=>$ypos, compose=>'Over', rotate=>$Theta);
  
  #Alternate method of drawing the robot
  #my $Xrad=$X+1;
  #my $Yrad=$Y+1;
  #$mapimage->Draw(primitive=>'circle', stroke=>'red', strokewidth=>1, fill=>'red', antialias=>'true', points=>"$X,$Y,$Xrad,$Yrad");

  # crop map image by 400x400
  my $windowsize = 400;
  my $cropxstart;
  my $cropystart;
  if (($X - ($windowsize/2)) < 0) {
    $cropxstart = 0;
  }
  else {
    $cropxstart = $X - ($windowsize/2);
  }

  if (($Y - ($windowsize/2)) < 0) {
    $cropystart = 0;
  }
  else {
    $cropystart = $Y - ($windowsize/2);
  }
  $mapimage->Crop(x=>$cropxstart, y=>$cropystart, width=>$windowsize, height=>$windowsize);
  $mapimage->Magnify();

  # write output to file
  my $outfile = "$html_dir/$mapname" . "_startpos_" . "$index.png";
  $mapimage->Write($outfile);
  # The rotated robot image for testing purposes
  #$robotimage->Write("/usr/tmp/robot_rotated.png");
  undef $mapimage;
  undef $robotimage;
}

# Create the map image used in the applet 
sub create_applet_image {
  my ($location) = @_;  # The subdirectory of the specified map
  system("$bee_bin_dir/MAP2GIF $location/map.map -clip $location/map_image/map.gif" );
  # Should we draw the goals on the map too?
}