Example 2: Tier-Scalable Planetary Reconnaissance
Mobile Robot Agent

<?xml version="1.0"?>

<!DOCTYPE myMessage SYSTEM "mobilec.dtd">

<MOBILEC_MESSAGE>
 <MESSAGE message="MOBILE_AGENT">
  <MOBILE_AGENT>
   <AGENT_DATA>
    <NAME>mobagent1</NAME>
    <OWNER>IEL</OWNER>
    <HOME>monkey.engr.ucdavis.edu:5050</HOME>
    <TASKS task="3" num="0">
     <TASK num="0" complete="0" server="mouse2.engr.ucdavis.edu:5050" code_id="1" />
     <TASK num="1" complete="0" server="fish.engr.ucdavis.edu:5050"   code_id="2" />
     <TASK num="2" complete="0" server="monkey.engr.ucdavis.edu:5050" code_id="3" />
     <AGENT_CODE id="1">
      <![CDATA[
#include <cv.h>
#include <highgui.h>

#define IMAGEWIDTH  640
#define IMAGEHEIGHT 480

int nSideContours = 0;
int nTargetContours = 0;
CvRect *targetObjectsROI;
CvRect *sideObjectsROI;

int targetObjectsROI_X[10] = {0};
int targetObjectsROI_Y[10] = {0};
int targetObjectsROI_Width[10] = {0};
int sideObjectsROI_X[10] = {0};
int sideObjectsROI_Y[10] = {0};
int sideObjectsROI_Width[10] = {0};

int
main (void)
{
  CvCapture *capture = NULL;
  IplImage
    *sideImage       = NULL,
    *sideImageGray   = NULL,
    *sideImageRed    = NULL,
    *sideImageBlue   = NULL,
    *sideImageGreen  = NULL,
    *sideImageRBDiff = NULL,
    *sideImageRGDiff = NULL,
    *sideImageSum    = NULL;

  int *sideObjectsIndex;
  CvRect *sideObjectsRotatedROI;

  CvMemStorage* contoursStorage  = NULL;
  CvSeq*        contoursSequence = NULL;

  int i;

  // ------ Load image --------

  // Uncomment the following to caputer from the camera
  /*
    capture   = cvCaptureFromCAM(0);
    sideImage = cvQueryFrame(capture);
  */
    sideImage = cvLoadImage("/tmp/sideview.png", 1);


  // ------ Find Field Objects -------

  // Convert to Gray Scale
  sideImageGray = cvCreateImage (cvGetSize(sideImage), 8, 1);
  cvConvertImage (sideImage, sideImageGray, CV_BGR2GRAY);

  // Smooth and threshold
  cvSmooth(sideImageGray, sideImageGray, CV_GAUSSIAN, 9, 9, 0, 0);
  cvThreshold(sideImageGray, sideImageGray, 220, 255, CV_THRESH_BINARY);
  cvSmooth(sideImageGray, sideImageGray, CV_GAUSSIAN, 5, 5, 0, 0);

  // Find contours and save locations
  contoursStorage = cvCreateMemStorage(0);
  nSideContours = cvFindContours(sideImageGray, contoursStorage,
      &contoursSequence, sizeof(CvContour),
      CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0));

  sideObjectsROI = (CvRect*)malloc(sizeof(CvRect)*nSideContours);

  for(i=0;i<nSideContours;i++)
  {
    sideObjectsROI[i] = cvBoundingRect(contoursSequence, 0);
    contoursSequence = contoursSequence->h_next;
  }
  cvClearMemStorage(contoursStorage);

  // ------ End Find Field Objects -------

  // ------ Find Target Objects -------

  sideImageRed    = cvCreateImage(cvGetSize(sideImage), 8, 1);
  sideImageBlue   = cvCreateImage(cvGetSize(sideImage), 8, 1);
  sideImageGreen  = cvCreateImage(cvGetSize(sideImage), 8, 1);
  sideImageRGDiff = cvCreateImage(cvGetSize(sideImage), 8, 1);
  sideImageRBDiff = cvCreateImage(cvGetSize(sideImage), 8, 1);
  sideImageSum    = cvCreateImage(cvGetSize(sideImage), 8, 1);

  // Split color componenets
  cvSplit(sideImage, sideImageBlue, sideImageGreen, sideImageRed, NULL);
  cvSub(sideImageRed, sideImageGreen, sideImageRGDiff, NULL);
  cvSub(sideImageRed, sideImageBlue,  sideImageRBDiff, NULL);
  cvAdd(sideImageRGDiff, sideImageRBDiff, sideImageSum, NULL);

  // Threshold and smooth
  cvThreshold(sideImageSum, sideImageSum, 250, 255, CV_THRESH_BINARY);
  cvSmooth(sideImageSum, sideImageSum, CV_GAUSSIAN, 5, 5, 0, 0);

  contoursStorage = cvCreateMemStorage(0);
  nTargetContours = cvFindContours(sideImageSum, contoursStorage,
                 &contoursSequence, sizeof(CvContour),
                 CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0));

  targetObjectsROI = (CvRect*)malloc(sizeof(CvRect)*nTargetContours);

  for(i=0;i<nTargetContours;i++)
  {
    targetObjectsROI[i] = cvBoundingRect(contoursSequence, 0);
    contoursSequence = contoursSequence->h_next;
  }
  cvClearMemStorage(contoursStorage);

  // ------ End Find Target Objects -------


  for(i=0;i<nSideContours;i++)
  {
    sideObjectsROI_X[i]     = (int) sideObjectsROI[i].x;
    sideObjectsROI_Y[i]     = (int) sideObjectsROI[i].y;
    sideObjectsROI_Width[i] = (int) sideObjectsROI[i].width;
  }
  for(i=0;i<nTargetContours;i++)
  {
    targetObjectsROI_X[i]     = (int) targetObjectsROI[i].x;
    targetObjectsROI_Y[i]     = (int) targetObjectsROI[i].y;
    targetObjectsROI_Width[i] = (int) targetObjectsROI[i].width;
  }

  mc_AgentVariableSave(mc_current_agent, "nSideContours");
  mc_AgentVariableSave(mc_current_agent, "nTargetContours");
  mc_AgentVariableSave(mc_current_agent, "sideObjectsROI_X");
  mc_AgentVariableSave(mc_current_agent, "sideObjectsROI_Y");
  mc_AgentVariableSave(mc_current_agent, "sideObjectsROI_Width");
  mc_AgentVariableSave(mc_current_agent, "targetObjectsROI_X");
  mc_AgentVariableSave(mc_current_agent, "targetObjectsROI_Y");
  mc_AgentVariableSave(mc_current_agent, "targetObjectsROI_Width");

  cvReleaseImage (&sideImage);
  cvReleaseImage (&sideImageGray);
  cvReleaseImage (&sideImageRed);
  cvReleaseImage (&sideImageBlue);
  cvReleaseImage (&sideImageGreen);
  cvReleaseImage (&sideImageRBDiff);
  cvReleaseImage (&sideImageRGDiff);
  cvReleaseImage (&sideImageSum);

 
  return 0;
}
     ]]>
     </AGENT_CODE>
     <AGENT_CODE id="2">
      <![CDATA[
#include <cv.h>
#include <highgui.h>
#include <gaul.h>

#define ROTATIONANGLE (25.0*3.1415/180.0)
#define IMAGEWIDTH  640
#define IMAGEHEIGHT 480

#define K3RADIUS      25 // In pixels as seen from the aerial camera
#define K3XPOSITION  264 // In pixels as seen from the aerial camera 
#define K3YPOSITION  109 // In pixels as seen from the aerial camera

int topMap[64][48] = {0};
char** robotPath = NULL;
int GAPathPlanning();
int wayPointsX[50];
int wayPointsY[50];
int wayPathSize = 0;

int
main (void)
{
  CvCapture *capture = NULL;
  IplImage
    *topImage        = NULL,
    *topImageGray    = NULL;

  int *nSideContours;
  int *nTargetContours;
  int *sideObjectsROI_X;
  int *sideObjectsROI_Y;
  int *sideObjectsROI_Width;
  int *targetObjectsROI_X;
  int *targetObjectsROI_Y;
  int *targetObjectsROI_Width;

  int *sideObjectsIndex;
  int *targetSideObjectsIndex;

  CvRect *sideObjectsRotatedROI;

  int nTopContours = 0;

  CvMemStorage* contoursStorage  = NULL;
  CvSeq*        contoursSequence = NULL;

  CvRect *topObjectsROI;

  int *targetTopObjectsIndex;

  int i;

  // ------ Load image --------

  // Uncomment the following to caputer from the camera
  /*
    capture   = cvCaptureFromCAM(0);
    topImage = cvQueryFrame(capture);
  */
    topImage = cvLoadImage("/tmp/topview.png", 1);

  // ------ Find Field Objects -------

  // Grab grayscale
  topImageGray  = cvCreateImage (cvGetSize(topImage),  8, 1);
  cvConvertImage (topImage,  topImageGray,  CV_BGR2GRAY);

  // Smooth and threshold
  cvSmooth(topImageGray, topImageGray, CV_GAUSSIAN, 5, 5, 0, 0);
  cvThreshold(topImageGray, topImageGray, 254, 255, CV_THRESH_BINARY);
  cvSmooth(topImageGray, topImageGray, CV_GAUSSIAN, 7, 7, 0, 0);
  // Find contours and save locations
  contoursStorage = cvCreateMemStorage(0);
  nTopContours = cvFindContours(topImageGray, contoursStorage,
      &contoursSequence, sizeof(CvContour),
      CV_RETR_TREE, 5, cvPoint(0,0));

  topObjectsROI = (CvRect*)malloc(sizeof(CvRect)*nTopContours);

  for(i=0;i<nTopContours;i++)
  { 
    topObjectsROI[i] = cvBoundingRect(contoursSequence, 0);
    contoursSequence = contoursSequence->h_next;
  }
  cvClearMemStorage(contoursStorage);

  nSideContours 
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "nSideContours", 0);
  nTargetContours
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "nTargetContours", 0);
  sideObjectsROI_X
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "sideObjectsROI_X", 0);
  sideObjectsROI_Y
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "sideObjectsROI_Y", 0);
  sideObjectsROI_Width
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "sideObjectsROI_Width", 0);
  targetObjectsROI_X
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "targetObjectsROI_X", 0);
  targetObjectsROI_Y
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "targetObjectsROI_Y", 0);
  targetObjectsROI_Width
     = (int*)mc_AgentVariableRetrieve(mc_current_agent, "targetObjectsROI_Width", 0);

  // ------ Correlate Targets with Field Objects -------

  targetSideObjectsIndex = (int*)malloc(sizeof(int)*(*nTargetContours));

  for(i=0; i<(*nTargetContours); i++)
  {
    int j = 0;
    int leftSide = 0;
    int rightSide = 0;
    int objectXCenter;
    int minimumDistance = 9999;

    leftSide = targetObjectsROI_X[i];
    rightSide = targetObjectsROI_X[i]+targetObjectsROI_Width[i];

    for(j=0; j<*nSideContours; j++)
    {
      objectXCenter = sideObjectsROI_X[j] + sideObjectsROI_Width[j]/2;

      if(objectXCenter > leftSide && objectXCenter < rightSide &&
          sideObjectsROI_Y[j] < targetObjectsROI_Y[i])
      {
        if((targetObjectsROI_Y[i] - sideObjectsROI_Y[j]) < minimumDistance)
        {
          minimumDistance = (targetObjectsROI_Y[i] - sideObjectsROI_Y[j]);
          targetSideObjectsIndex[i] = j;
        }
      }
    }
  }

  // ---- End Correlate Targets with Field Objects -----


  // ------ Sort Objects -------
  sideObjectsRotatedROI = (CvRect*)malloc(sizeof(CvRect)*(*nSideContours));
  sideObjectsIndex = (int*)malloc(sizeof(int)*(*nSideContours));

  for(i=0; i<*nSideContours; i++)
  {
    int X, Y;

    X = -(IMAGEWIDTH/2 - sideObjectsROI_X[i]);
    Y = (IMAGEHEIGHT/2 - sideObjectsROI_Y[i]);

    sideObjectsRotatedROI[i] = 
      cvRect(sideObjectsROI_X[i], sideObjectsROI_Y[i],
             sideObjectsROI_Width[i], 0);
    sideObjectsIndex[i] = i;

    sideObjectsRotatedROI[i].x = X * cos(ROTATIONANGLE) - Y * sin(ROTATIONANGLE);
    sideObjectsRotatedROI[i].y = X * sin(ROTATIONANGLE) + Y * cos(ROTATIONANGLE);

    sideObjectsRotatedROI[i].x = (IMAGEWIDTH/2  + sideObjectsRotatedROI[i].x);
    sideObjectsRotatedROI[i].y = (IMAGEHEIGHT/2 - sideObjectsRotatedROI[i].y);
  }

  // we assume nTopContours == nSideContours
  // sort objects
  for(i=0;i<nTopContours-1;i++)
  {
    CvRect tempRect;
    int tempIndex;
    int j;

    // Sort by y
    for(j=i+1;j<nTopContours;j++)
    {
      if(sideObjectsRotatedROI[j].y < sideObjectsRotatedROI[i].y)
      {
        tempRect = sideObjectsRotatedROI[i];
        sideObjectsRotatedROI[i] = sideObjectsRotatedROI[j];
        sideObjectsRotatedROI[j] = tempRect;

        tempIndex = sideObjectsIndex[i];
        sideObjectsIndex[i] = sideObjectsIndex[j];
        sideObjectsIndex[j] = tempIndex;
      }

      if(topObjectsROI[j].y < topObjectsROI[i].y)
      {
        tempRect = topObjectsROI[i];
        topObjectsROI[i] = topObjectsROI[j];
        topObjectsROI[j] = tempRect;
      }
    }
  }

  // Sort by x if needed
  for(i=0;i<(nTopContours-1);i++)
  {
    CvRect tempRect;
    int tempIndex;
    int j;

    if((sideObjectsRotatedROI[i+1].y - sideObjectsRotatedROI[i].y) < 20)
    {
      if(sideObjectsRotatedROI[i+1].x < sideObjectsRotatedROI[i].x)
      {
        tempRect = sideObjectsRotatedROI[i];
        sideObjectsRotatedROI[i] = sideObjectsRotatedROI[i+1];
        sideObjectsRotatedROI[i+1] = tempRect;

        tempIndex = sideObjectsIndex[i];
        sideObjectsIndex[i] = sideObjectsIndex[i+1];
        sideObjectsIndex[i+1] = tempIndex;
      }
    }
    if((topObjectsROI[i+1].y - topObjectsROI[i].y) < 20)
    {
      if(topObjectsROI[i+1].x < topObjectsROI[i].x)
      {
        tempRect = topObjectsROI[i];
        topObjectsROI[i] = topObjectsROI[i+1];
        topObjectsROI[i+1] = tempRect;
      }
    }
  }

  // ------ End Sort Objects -------
  // ------ Correlate Target Objects -------

  targetTopObjectsIndex = (int*)malloc(sizeof(int)*nTopContours);
  memset(targetTopObjectsIndex, 0, nTopContours);

  for(i=0; i<(*nTargetContours); i++)
  {
    int j;

    for(j=0; j<*nSideContours; j++)
    {
      if(sideObjectsIndex[j] == targetSideObjectsIndex[i])
      {
        targetTopObjectsIndex[i] = j;
      }
    }
  }

  // ------ Correlate Target Objects -------

  //  ---- Begin Create Map --------

  // Fill In Objects and Target
  for(i=0; i<nTopContours; i++)
  {
    int xIni = 0, xFin = 0;
    int yIni = 0, yFin = 0;
    int j;

    xIni = (topObjectsROI[i].x - K3RADIUS) / 10;
    yIni = (topObjectsROI[i].y - K3RADIUS) / 10;

    xFin = (topObjectsROI[i].x + topObjectsROI[i].width + K3RADIUS)  / 10;
    yFin = (topObjectsROI[i].y + topObjectsROI[i].height + K3RADIUS) / 10;

    int x, y;
    for(x = xIni; x <= xFin; x++)
    {
      for(y = yIni; y <= yFin; y++)
      {
        // Object
        topMap[x][y] = 1;

        // Target
        for(j=0;j<(*nTargetContours); j++)
          if(targetTopObjectsIndex[j] == i)
            topMap[x][y] = 2;
      }
    }
  }

  //  ---- End Create Map --------

  wayPathSize = GAPathPlanning();

  for(i=0;i<wayPathSize;i++)
  {
    wayPointsX[i] = robotPath[i][0];
    wayPointsY[i] = robotPath[i][1];
  }

  mc_AgentVariableSave(mc_current_agent, "wayPathSize");
  mc_AgentVariableSave(mc_current_agent, "wayPointsX");
  mc_AgentVariableSave(mc_current_agent, "wayPointsY");

  // Memory cleanup
  cvReleaseImage (&topImage);
  cvReleaseImage (&topImageGray);

  free(sideObjectsROI_X);
  free(sideObjectsROI_Y);
  free(sideObjectsROI_Width);
  free(targetObjectsROI_X);
  free(targetObjectsROI_Y);
  free(targetObjectsROI_Width);

  free(topObjectsROI);
  free(sideObjectsRotatedROI);

  free(sideObjectsIndex);
  free(targetSideObjectsIndex);
  free(targetTopObjectsIndex);

  return 0;
}

// ------------------- GA PATH PLANNING ----------------------

char 
  dir[2][9] =
     {{1, 1, 0, -1, -1, -1,  0,  1},
      {0, 1, 1,  1,  0, -1, -1, -1}},
  beg_pt[2] = {K3XPOSITION/10,K3YPOSITION/10};


boolean path_fitness(population *pop, entity *entity)
{
  int i;
  char cur_pt[2] = {beg_pt[0],beg_pt[1]}; // Start at beg_pt
  char value = 0;
  double fitness = 0;
  double d = 0;
  double w = 0;
  char target = 0;


  for(i=0;i<pop->len_chromosomes;i++)
  {
    if(target) 
    {
      ((char *)entity->chromosome[0])[i] = -99;
      continue;
    }

    // reset w to 0
    w = 0;
    value = ((char *)entity->chromosome[0])[i];

    if(value < -8) continue;

    if(value < 0) {
      value += 8;
      ((char *)entity->chromosome[0])[i] = value;
    }

    d = ( (value & 1) ? 1.4142 : 1);

    cur_pt[0] += dir[0][value];
    cur_pt[1] += dir[1][value];

    if(cur_pt[0] < 1 || cur_pt[0] > 63) 
      w = 300.0;
    else if(cur_pt[1] < 1 || cur_pt[1] > 47) 
      w = 300.0;
    else if(topMap[cur_pt[0]][cur_pt[1]] == 1) 
      w = 300.0;
    else if(topMap[cur_pt[0]][cur_pt[1]] == 2)
    {
      w = -100;
      target = 1;
    }

    // take into account total length?
    fitness += d*(1+w);
  }

  entity->fitness = -fitness;

  return TRUE;
}


boolean path_seed(population *pop, entity *adam)
{
  int i;
  static int count = 0;

  /* Checks. */
  if (!pop)  die("Null pointer to population structure passed.");
  if (!adam) die("Null pointer to entity structure passed.");

  for(i=0;i<pop->len_chromosomes;i++)
    ((char*)adam->chromosome[0])[i] = (char)random_int_range(0, 7);

  return TRUE;
}


int GAPathPlanning()
{
  int i;
  int j;
  int size;
  int value;
  char cur_pt[2] = {beg_pt[0], beg_pt[1]};

  population		*pop;			/* Population of solutions. */

  //random_seed(0);
  random_init();

  pop = ga_genesis_char(
      2000,   /* const int              population_size */
      1,    /* const int              num_chromo */
      224,   /* const int              len_chromo */
      NULL, /* GAgeneration_hook      generation_hook */
      NULL, /* GAiteration_hook       iteration_hook */
      NULL, /* GAdata_destructor      data_destructor */
      NULL, /* GAdata_ref_incrementor data_ref_incrementor */
      path_fitness, /* GAevaluate             evaluate */
      path_seed,    /* GAseed                 seed */
      NULL,			    /* GAadapt                adapt */
      ga_select_one_bestof2, /* GAselect_one           select_one */
      ga_select_two_bestof2, /* GAselect_two           select_two */
      ga_mutate_char_multipoint, 	     /* GAmutate               mutate */
      ga_crossover_char_allele_mixing, /* GAcrossover            crossover */
      NULL, /* GAreplace   replace */
      NULL /* vpointer	   User data */
      );

  ga_population_set_parameters(
      pop,  /* population      *pop */
      GA_SCHEME_DARWIN,           /* const ga_scheme_type     scheme */
      GA_ELITISM_PARENTS_SURVIVE,	/* const ga_elitism_type   elitism */
      0.9,  /* double  crossover */
      0.02, /* double  mutation */
      0.0   /* double  migration */
      );

  ga_evolution(
      pop,  /* population	*pop */
      100	  /* const int	max_generations */
      );


  if(ga_get_entity_from_rank(pop,0))
  {
    for(i=0; i<pop->len_chromosomes; i++)
    {
      value = ((char *)ga_get_entity_from_rank(pop,0)->chromosome[0])[i];
      if(value == -99) break;
    }
    size = i;

    robotPath = (char **)malloc(sizeof(char*)*size);
    for(i=0;i<size;i++)
      robotPath[i] = (char *)malloc(sizeof(char)*2);

    robotPath[0][0] = cur_pt[0];
    robotPath[0][1] = cur_pt[1];

    for(i=1; i<size; i++)
    {
      value = ((char *)ga_get_entity_from_rank(pop,0)->chromosome[0])[i-1];

      cur_pt[0] += dir[0][value];
      cur_pt[1] += dir[1][value];

      robotPath[i][0] = cur_pt[0];
      robotPath[i][1] = cur_pt[1];
    }
  }

  ga_extinction(pop);

  return size;
}

     ]]>
    </AGENT_CODE>
    <AGENT_CODE id="3">
      <![CDATA[
#include <stdio.h>

int
main (void)
{
  int* wayPathSize;
  int* wayPointsX;
  int* wayPointsY;
  int i;

  wayPathSize = (int*)mc_AgentVariableRetrieve(mc_current_agent, "wayPathSize", 1);
  wayPointsX  = (int*)mc_AgentVariableRetrieve(mc_current_agent, "wayPointsX",  1);
  wayPointsY  = (int*)mc_AgentVariableRetrieve(mc_current_agent, "wayPointsY",  1);

  printf("Robot Way Points\n");
  printf("----------------\n");
  for(i=0;i<*wayPathSize;i++)
    printf("%3d (%3d,%3d)\n", i, wayPointsX[i], wayPointsY[i]);
 
  return 0;
}
     ]]>
    </AGENT_CODE>
    </TASKS>
   </AGENT_DATA>
  </MOBILE_AGENT>
 </MESSAGE>
</MOBILEC_MESSAGE>