Revision: 6360
          http://playerstage.svn.sourceforge.net/playerstage/?rev=6360&view=rev
Author:   gbiggs
Date:     2008-04-18 01:07:57 -0700 (Fri, 18 Apr 2008)

Log Message:
-----------
Merging changes 4470:6287 from trunk

Modified Paths:
--------------
    code/player/branches/cmake/CMake_Todo.txt
    code/player/branches/cmake/server/drivers/planner/wavefront/CMakeLists.txt
    code/player/branches/cmake/server/drivers/planner/wavefront/plan.c
    code/player/branches/cmake/server/drivers/planner/wavefront/plan.h
    code/player/branches/cmake/server/drivers/planner/wavefront/plan_plan.c
    code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc

Added Paths:
-----------
    code/player/branches/cmake/server/drivers/planner/wavefront/Makefile.test
    code/player/branches/cmake/server/drivers/planner/wavefront/heap.c
    code/player/branches/cmake/server/drivers/planner/wavefront/heap.h
    code/player/branches/cmake/server/drivers/planner/wavefront/test.c

Modified: code/player/branches/cmake/CMake_Todo.txt
===================================================================
--- code/player/branches/cmake/CMake_Todo.txt   2008-04-18 07:54:24 UTC (rev 
6359)
+++ code/player/branches/cmake/CMake_Todo.txt   2008-04-18 08:07:57 UTC (rev 
6360)
@@ -10,4 +10,5 @@
 - Some installable cmake modules with macros for making plugin drivers, etc
 - Clean out/replace any stragglers from autotools (including README and co)
 - Drivers being disabled by a check used to correctly force their option to 
off. Figure out why this broke. Fix it.
-- Figure out why C++ tests and C++ examples don't link properly when building 
as static libs, even though the server and utils do.
\ No newline at end of file
+- Figure out why C++ tests and C++ examples don't link properly when building 
as static libs, even though the server and utils do.
+- Add CMakeLists equivalent of the wavefront driver's Makefile.test (and get 
rid of Makefile.test)
\ No newline at end of file

Modified: 
code/player/branches/cmake/server/drivers/planner/wavefront/CMakeLists.txt
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/CMakeLists.txt  
2008-04-18 07:54:24 UTC (rev 6359)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/CMakeLists.txt  
2008-04-18 08:07:57 UTC (rev 6360)
@@ -3,4 +3,4 @@
     wavefront_includeDir wavefront_libDir wavefront_linkFlags wavefront_cFlags)
 PLAYERDRIVER_ADD_DRIVER (wavefront build_wavefront
     "${wavefront_includeDir}" "${wavefront_libDir}" "${wavefront_linkFlags}" 
"${wavefront_cFlags}"
-    plan.c plan_plan.c plan_waypoint.c wavefront.cc)
\ No newline at end of file
+    plan.c plan_plan.c plan_waypoint.c wavefront.cc heap.c)
\ No newline at end of file

Copied: 
code/player/branches/cmake/server/drivers/planner/wavefront/Makefile.test (from 
rev 6287, code/player/trunk/server/drivers/planner/wavefront/Makefile.test)
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/Makefile.test   
                        (rev 0)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/Makefile.test   
2008-04-18 08:07:57 UTC (rev 6360)
@@ -0,0 +1,11 @@
+#CFLAGS = -I. -I../../../.. -Wall -Werror -O3  `pkg-config --cflags 
gdk-pixbuf-2.0`
+CFLAGS = -I. -I../../../.. -Wall -Werror -g  `pkg-config --cflags 
gdk-pixbuf-2.0`
+LIBS = -L../../../../libplayercore/.libs -lplayererror `pkg-config --libs 
gdk-pixbuf-2.0`
+
+SRCS = test.c plan.c plan_plan.c plan_waypoint.c heap.c
+
+test: $(SRCS) plan.h heap.h
+       gcc $(CFLAGS) -o $@ $(SRCS) $(LIBS)
+
+clean:
+       rm -f test

Copied: code/player/branches/cmake/server/drivers/planner/wavefront/heap.c 
(from rev 6287, code/player/trunk/server/drivers/planner/wavefront/heap.c)
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/heap.c          
                (rev 0)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/heap.c  
2008-04-18 08:07:57 UTC (rev 6360)
@@ -0,0 +1,166 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2008-
+ *     Brian Gerkey [EMAIL PROTECTED]
+ *                      
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * An implementation of a heap, as seen in "Introduction to Algorithms," by
+ * Cormen, Leiserson, and Rivest, pages 140-152.
+ */
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "heap.h"
+
+heap_t*
+heap_alloc(int size, heap_free_elt_fn_t free_fn)
+{
+  heap_t* h;
+
+  h = calloc(1,sizeof(heap_t));
+  assert(h);
+  h->size = size;
+  h->free_fn = free_fn;
+  h->A = calloc(h->size,sizeof(double));
+  assert(h->A);
+  h->data = calloc(h->size,sizeof(void*));
+  assert(h->data);
+  h->len = 0;
+
+  return(h);
+}
+
+void
+heap_free(heap_t* h)
+{
+  if(h->free_fn)
+  {
+    while(!heap_empty(h))
+      (*h->free_fn)(heap_extract_max(h));
+  }
+  free(h->data);
+  free(h->A);
+  free(h);
+}
+
+void
+heap_heapify(heap_t* h, int i)
+{
+  int l, r;
+  int largest;
+  double tmp;
+  void* tmp_data;
+
+  l = HEAP_LEFT(i);
+  r = HEAP_RIGHT(i);
+
+  if((l < h->len) && (h->A[l] > h->A[i]))
+    largest = l;
+  else
+    largest = i;
+
+  if((r < h->len) && (h->A[r] > h->A[largest]))
+    largest = r;
+
+  if(largest != i)
+  {
+    tmp = h->A[i];
+    tmp_data = h->data[i];
+    h->A[i] = h->A[largest];
+    h->data[i] = h->data[largest];
+    h->A[largest] = tmp;
+    h->data[largest] = tmp_data;
+    heap_heapify(h,largest);
+  }
+}
+
+int
+heap_empty(heap_t* h)
+{
+  return(h->len == 0);
+}
+
+void*
+heap_extract_max(heap_t* h)
+{
+  void* max;
+
+  assert(h->len > 0);
+
+  max = h->data[0];
+  h->A[0] = h->A[h->len - 1];
+  h->data[0] = h->data[h->len - 1];
+  h->len--;
+  heap_heapify(h,0);
+  return(max);
+}
+
+void
+heap_insert(heap_t* h, double key, void* data)
+{
+  int i;
+
+  if(h->len == h->size)
+  {
+    h->size *= 2;
+    h->A = realloc(h->A, h->size * sizeof(double));
+    assert(h->A);
+    h->data = realloc(h->data, h->size * sizeof(void*));
+    assert(h->data);
+  }
+
+  h->len++;
+  i = h->len - 1;
+
+  while((i > 0) && (h->A[HEAP_PARENT(i)] < key))
+  {
+    h->A[i] = h->A[HEAP_PARENT(i)];
+    h->data[i] = h->data[HEAP_PARENT(i)];
+    i = HEAP_PARENT(i);
+  }
+  h->A[i] = key;
+  h->data[i] = data;
+}
+
+int
+heap_valid(heap_t* h)
+{
+  int i;
+  for(i=1;i<h->len;i++)
+  {
+    if(h->A[HEAP_PARENT(i)] < h->A[i])
+      return(0);
+  }
+  return(1);
+}
+
+void
+heap_reset(heap_t* h)
+{
+  h->len = 0;
+}
+
+void
+heap_dump(heap_t* h)
+{
+  int i;
+  for(i=0;i<h->len;i++)
+    printf("%d: %f\n", i, h->A[i]);
+}

Copied: code/player/branches/cmake/server/drivers/planner/wavefront/heap.h 
(from rev 6287, code/player/trunk/server/drivers/planner/wavefront/heap.h)
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/heap.h          
                (rev 0)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/heap.h  
2008-04-18 08:07:57 UTC (rev 6360)
@@ -0,0 +1,65 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2008-
+ *     Brian Gerkey [EMAIL PROTECTED]
+ *                      
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * An implementation of a heap, as seen in "Introduction to Algorithms," by
+ * Cormen, Leiserson, and Rivest, pages 140-152.
+ */
+
+#ifndef _HEAP_H_
+#define _HEAP_H_
+
+#define HEAP_PARENT(i) ((i)/2)
+#define HEAP_LEFT(i) (2*(i))
+#define HEAP_RIGHT(i) (2*(i)+1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct heap;
+
+typedef void (*heap_free_elt_fn_t) (void* elt);
+
+typedef struct heap
+{
+  int len;
+  int size;
+  heap_free_elt_fn_t free_fn;
+  double* A;
+  void** data;
+} heap_t;
+
+heap_t* heap_alloc(int size, heap_free_elt_fn_t free_fn);
+void heap_free(heap_t* h);
+void heap_heapify(heap_t* h, int i);
+void* heap_extract_max(heap_t* h);
+void heap_insert(heap_t* h, double key, void* data);
+void heap_dump(heap_t* h);
+int heap_valid(heap_t* h);
+int heap_empty(heap_t* h);
+void heap_reset(heap_t* h);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Modified: code/player/branches/cmake/server/drivers/planner/wavefront/plan.c
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/plan.c  
2008-04-18 07:54:24 UTC (rev 6359)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan.c  
2008-04-18 08:07:57 UTC (rev 6360)
@@ -46,77 +46,207 @@
 
   plan = calloc(1, sizeof(plan_t));
 
-  plan->size_x = 0;
-  plan->size_y = 0;
-  plan->scale = 0.0;
-
-  plan->min_x = 0;
-  plan->min_y = 0;
-  plan->max_x = 0;
-  plan->max_y = 0;
-
   plan->abs_min_radius = abs_min_radius;
   plan->des_min_radius = des_min_radius;
 
   plan->max_radius = max_radius;
   plan->dist_penalty = dist_penalty;
   
-  plan->queue_start = 0;
-  plan->queue_len = 0;
-  plan->queue_size = 400000; // HACK: FIX
-  plan->queue = calloc(plan->queue_size, sizeof(plan->queue[0]));
+  plan->heap = heap_alloc(PLAN_DEFAULT_HEAP_SIZE, (heap_free_elt_fn_t)NULL);
+  assert(plan->heap);
 
-  plan->waypoint_count = 0;
+  plan->path_size = 1000;
+  plan->path = calloc(plan->path_size, sizeof(plan->path[0]));
+
+  plan->lpath_size = 100;
+  plan->lpath = calloc(plan->lpath_size, sizeof(plan->lpath[0]));
+
   plan->waypoint_size = 100;
   plan->waypoints = calloc(plan->waypoint_size, sizeof(plan->waypoints[0]));
   
   return plan;
 }
 
+void
+plan_set_obstacles(plan_t* plan, double* obs, size_t num)
+{
+  size_t i;
+  int di,dj;
+  float* p;
+  plan_cell_t* cell, *ncell;
 
+  // Remove any previous obstacles
+  for(i=0;i<plan->obs_pts_num;i++)
+  {
+    cell = plan->cells + 
+            PLAN_INDEX(plan,plan->obs_pts[2*i],plan->obs_pts[2*i+1]);
+    cell->occ_state_dyn = cell->occ_state;
+    cell->occ_dist_dyn = cell->occ_dist;
+  }
+
+  // Do we need more room?
+  if(num > plan->obs_pts_size)
+  {
+    plan->obs_pts_size = num;
+    plan->obs_pts = (unsigned short*)realloc(plan->obs_pts, 
+                                             sizeof(unsigned short) * 2 *
+                                             plan->obs_pts_size);
+    assert(plan->obs_pts);
+  }
+
+  // Copy and expand costs around them
+  plan->obs_pts_num = num;
+  for(i=0;i<plan->obs_pts_num;i++)
+  {
+    // Convert to grid coords
+    int gx,gy;
+    gx = PLAN_GXWX(plan, obs[2*i]);
+    gy = PLAN_GYWY(plan, obs[2*i+1]);
+    plan->obs_pts[2*i] = gx;
+    plan->obs_pts[2*i+1] = gy;
+
+    cell = plan->cells + PLAN_INDEX(plan,gx,gy);
+
+    cell->occ_state_dyn = 1;
+    cell->occ_dist_dyn = 0.0;
+
+    p = plan->dist_kernel;
+    for (dj = -plan->dist_kernel_width/2; 
+         dj <= plan->dist_kernel_width/2; 
+         dj++)
+    {
+      ncell = cell + -plan->dist_kernel_width/2 + dj*plan->size_x;
+      for (di = -plan->dist_kernel_width/2;
+           di <= plan->dist_kernel_width/2; 
+           di++, p++, ncell++)
+      {
+        if(!PLAN_VALID_BOUNDS(plan,cell->ci+di,cell->cj+dj))            
+          continue;
+
+        if(*p < ncell->occ_dist_dyn)
+          ncell->occ_dist_dyn = *p;
+      }
+    }
+  }
+}
+
+void
+plan_compute_dist_kernel(plan_t* plan)
+{
+  int i,j;
+  float* p;
+
+  // Compute variable sized kernel, for use in propagating distance from
+  // obstacles
+  plan->dist_kernel_width = 1 + 2 * (int)ceil(plan->max_radius / plan->scale);
+  plan->dist_kernel = (float*)realloc(plan->dist_kernel,
+                                      sizeof(float) * 
+                                      plan->dist_kernel_width *
+                                      plan->dist_kernel_width);
+  assert(plan->dist_kernel);
+
+  p = plan->dist_kernel;
+  for(j=-plan->dist_kernel_width/2;j<=plan->dist_kernel_width/2;j++)
+  {
+    for(i=-plan->dist_kernel_width/2;i<=plan->dist_kernel_width/2;i++,p++)
+    {
+      *p = sqrt(i*i+j*j) * plan->scale;
+    }
+  }
+  // also compute a 3x3 kernel, used when propagating distance from goal
+  p = plan->dist_kernel_3x3;
+  for(j=-1;j<=1;j++)
+  {
+    for(i=-1;i<=1;i++,p++)
+    {
+      *p = sqrt(i*i+j*j) * plan->scale;
+    }
+  }
+}
+
+
 // Destroy a planner
 void plan_free(plan_t *plan)
 {
   if (plan->cells)
     free(plan->cells);
-  free(plan->queue);
+  heap_free(plan->heap);
   free(plan->waypoints);
+  if(plan->dist_kernel)
+    free(plan->dist_kernel);
   free(plan);
 
   return;
 }
 
-
-// Reset the plan
-void plan_reset(plan_t *plan)
+// Initialize the plan
+void plan_init(plan_t *plan, 
+               double res, double sx, double sy, double ox, double oy)
 {
   int i, j;
   plan_cell_t *cell;
 
+  plan->scale = res;
+  plan->size_x = sx;
+  plan->size_y = sy;
+  plan->origin_x = ox;
+  plan->origin_y = oy;
+
+  cell = plan->cells;
   for (j = 0; j < plan->size_y; j++)
   {
-    for (i = 0; i < plan->size_x; i++)
+    for (i = 0; i < plan->size_x; i++, cell++)
     {
-      cell = plan->cells + PLAN_INDEX(plan, i, j);
       cell->ci = i;
       cell->cj = j;
-      cell->occ_state = 0;
-      cell->occ_dist = plan->max_radius;
-      cell->plan_cost = 1e12;
+      cell->occ_state_dyn = cell->occ_state;
+      if(cell->occ_state >= 0)
+        cell->occ_dist_dyn = cell->occ_dist = 0.0;
+      else
+        cell->occ_dist_dyn = cell->occ_dist = plan->max_radius;
+      cell->plan_cost = PLAN_MAX_COST;
       cell->plan_next = NULL;
     }
   }
   plan->waypoint_count = 0;
-  return;
+
+  plan_compute_dist_kernel(plan);
+
+  plan_set_bounds(plan, 0, 0, plan->size_x - 1, plan->size_y - 1);
 }
 
+
+// Reset the plan
+void plan_reset(plan_t *plan)
+{
+  int i, j;
+  plan_cell_t *cell;
+
+  for (j = plan->min_y; j <= plan->max_y; j++)
+  {
+    cell = plan->cells + PLAN_INDEX(plan,plan->min_x,j);
+    for (i = plan->min_x; i <= plan->max_x; i++, cell++)
+    {
+      cell->plan_cost = PLAN_MAX_COST;
+      cell->plan_next = NULL;
+      cell->mark = 0;
+    }
+  }
+  plan->waypoint_count = 0;
+}
+
 void
 plan_set_bounds(plan_t* plan, int min_x, int min_y, int max_x, int max_y)
 {
-  assert(min_x < plan->size_x);
-  assert(min_y < plan->size_y);
-  assert(max_x < plan->size_x);
-  assert(max_y < plan->size_y);
+  min_x = MAX(0,min_x);
+  min_x = MIN(plan->size_x-1, min_x);
+  min_y = MAX(0,min_y);
+  min_y = MIN(plan->size_y-1, min_y);
+  max_x = MAX(0,max_x);
+  max_x = MIN(plan->size_x-1, max_x);
+  max_y = MAX(0,max_y);
+  max_y = MIN(plan->size_y-1, max_y);
+
   assert(min_x <= max_x);
   assert(min_y <= max_y);
 
@@ -124,6 +254,10 @@
   plan->min_y = min_y;
   plan->max_x = max_x;
   plan->max_y = max_y;
+
+  //printf("new bounds: (%d,%d) -> (%d,%d)\n",
+         //plan->min_x, plan->min_y,
+         //plan->max_x, plan->max_y);
 }
 
 int
@@ -208,48 +342,48 @@
 }
 
 void
-plan_update_cspace_naive(plan_t* plan)
+plan_compute_cspace(plan_t* plan)
 {
   int i, j;
-  int di, dj, dn;
-  double r;
+  int di, dj;
+  float* p;
   plan_cell_t *cell, *ncell;
 
   PLAYER_MSG0(2,"Generating C-space....");
-          
-  dn = (int) ceil(plan->max_radius / plan->scale);
 
   for (j = plan->min_y; j <= plan->max_y; j++)
   {
-    for (i = plan->min_x; i <= plan->max_x; i++)
+    cell = plan->cells + PLAN_INDEX(plan, 0, j);
+    for (i = plan->min_x; i <= plan->max_x; i++, cell++)
     {
-      cell = plan->cells + PLAN_INDEX(plan, i, j);
       if (cell->occ_state < 0)
         continue;
 
-      cell->occ_dist = FLT_MAX;
-
-      for (dj = -dn; dj <= +dn; dj++)
+      p = plan->dist_kernel;
+      for (dj = -plan->dist_kernel_width/2; 
+           dj <= plan->dist_kernel_width/2; 
+           dj++)
       {
-        for (di = -dn; di <= +dn; di++)
+        ncell = cell + -plan->dist_kernel_width/2 + dj*plan->size_x;
+        for (di = -plan->dist_kernel_width/2;
+             di <= plan->dist_kernel_width/2; 
+             di++, p++, ncell++)
         {
-          if (!PLAN_VALID_BOUNDS(plan, i + di, j + dj))            
+          if(!PLAN_VALID_BOUNDS(plan,i+di,j+dj))            
             continue;
-          ncell = plan->cells + PLAN_INDEX(plan, i + di, j + dj);
-          
-          r = plan->scale * sqrt(di * di + dj * dj);
-          if (r < ncell->occ_dist)
-            ncell->occ_dist = r;
+
+          if(*p < ncell->occ_dist)
+            ncell->occ_dist_dyn = ncell->occ_dist = *p;
         }
       }
     }
   }
 }
 
-#if 0
+#if 1
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
-void
+        void
 draw_cspace(plan_t* plan, const char* fname)
 {
   GdkPixbuf* pixbuf;
@@ -295,123 +429,116 @@
                                     plan->size_y,
                                     plan->size_x * 3,
                                     NULL, NULL);
-  
+
   gdk_pixbuf_save(pixbuf,fname,"png",&error,NULL);
   gdk_pixbuf_unref(pixbuf);
   free(pixels);
 }
-#endif
 
-#if 0
-void
-plan_update_cspace_dp(plan_t* plan)
+        void
+draw_path(plan_t* plan, double lx, double ly, const char* fname)
 {
+  GdkPixbuf* pixbuf;
+  GError* error = NULL;
+  guchar* pixels;
+  int p;
+  int paddr;
   int i, j;
-  int di, dj, dn;
-  double r;
-  plan_cell_t *cell, *ncell;
-  //heap_t* Q;
-  plan_cell_t** Q;
-  int qhead, qtail;
+  plan_cell_t* cell;
 
-  PLAYER_MSG0(2,"Generating C-space....");
+  pixels = (guchar*)malloc(sizeof(guchar)*plan->size_x*plan->size_y*3);
 
-  // We'll look this far away from obstacles when updating cell costs
-  dn = (int) ceil(plan->max_radius / plan->scale);
+  p=0;
+  for(j=plan->size_y-1;j>=0;j--)
+  {
+    for(i=0;i<plan->size_x;i++,p++)
+    {
+      paddr = p * 3;
+      if(plan->cells[PLAN_INDEX(plan,i,j)].occ_state == 1)
+      {
+        pixels[paddr] = 255;
+        pixels[paddr+1] = 0;
+        pixels[paddr+2] = 0;
+      }
+      else if(plan->cells[PLAN_INDEX(plan,i,j)].occ_dist < plan->max_radius)
+      {
+        pixels[paddr] = 0;
+        pixels[paddr+1] = 0;
+        pixels[paddr+2] = 255;
+      }
+      else
+      {
+        pixels[paddr] = 255;
+        pixels[paddr+1] = 255;
+        pixels[paddr+2] = 255;
+      }
+      /*
+         if((7*plan->cells[PLAN_INDEX(plan,i,j)].plan_cost) > 255)
+         {
+         pixels[paddr] = 0;
+         pixels[paddr+1] = 0;
+         pixels[paddr+2] = 255;
+         }
+         else
+         {
+         pixels[paddr] = 255 - 7*plan->cells[PLAN_INDEX(plan,i,j)].plan_cost;
+         pixels[paddr+1] = 0;
+         pixels[paddr+2] = 0;
+         }
+       */
+    }
+  }
 
-  // We'll need space for, at most, dn^2 cells in our queue (which is a
-  // binary heap).
-  //Q = heap_alloc(dn*dn, NULL);
-  Q = (plan_cell_t**)malloc(sizeof(plan_cell_t*)*dn*dn);
-  assert(Q);
+  for(i=0;i<plan->path_count;i++)
+  {
+    cell = plan->path[i];
+    
+    paddr = 3*PLAN_INDEX(plan,cell->ci,plan->size_y - cell->cj - 1);
+    pixels[paddr] = 0;
+    pixels[paddr+1] = 255;
+    pixels[paddr+2] = 0;
+  }
 
-  // Make space for the marks that we'll use.
-  if(plan->marks_size != plan->size_x*plan->size_y)
+  for(i=0;i<plan->lpath_count;i++)
   {
-    plan->marks_size = plan->size_x*plan->size_y;
-    plan->marks = (unsigned char*)realloc(plan->marks,
-                                          sizeof(unsigned char*) * 
-                                          plan->marks_size);
+    cell = plan->lpath[i];
+    
+    paddr = 3*PLAN_INDEX(plan,cell->ci,plan->size_y - cell->cj - 1);
+    pixels[paddr] = 255;
+    pixels[paddr+1] = 0;
+    pixels[paddr+2] = 255;
   }
-  assert(plan->marks);
-  
-  // For each obstacle (or unknown cell), spread a wave out in all
-  // directions, updating occupancy distances (inverse costs) on the way.  
-  // Don't ever raise the occupancy distance of a cell.
-  for (j = 0; j < plan->size_y; j++)
+
+  /*
+  for(p=0;p<plan->waypoint_count;p++)
   {
-    for (i = 0; i < plan->size_x; i++)
+    cell = plan->waypoints[p];
+    for(j=-3;j<=3;j++)
     {
-      cell = plan->cells + PLAN_INDEX(plan, i, j);
-      if (cell->occ_state < 0)
-        continue;
-
-      //cell->occ_dist = plan->max_radius;
-      cell->occ_dist = 0.0;
-
-      // clear the marks
-      memset(plan->marks,0,sizeof(unsigned char)*plan->size_x*plan->size_y);
-
-      // Start with the current cell
-      //heap_reset(Q);
-      //heap_insert(Q, cell->occ_dist, cell);
-      qhead = 0;
-      Q[qhead] = cell;
-      qtail = 1;
-
-      //while(!heap_empty(Q))
-      while(qtail != qhead)
+      cj = cell->cj + j;
+      for(i=-3;i<=3;i++)
       {
-        //ncell = heap_extract_max(Q);
-        ncell = Q[qhead++];
-
-        // Mark it, so we don't come back
-        plan->marks[PLAN_INDEX(plan, ncell->ci, ncell->cj)] = 1;
-
-        // Is this cell an obstacle or unknown cell (and not the initial
-        // cell?  If so, don't bother updating its cost here.
-        if((ncell != cell) && (ncell->occ_state >= 0))
-          continue;
-        
-        // How far are we from the obstacle cell we started with?
-        r = plan->scale * hypot(ncell->ci - cell->ci,
-                                ncell->cj - cell->cj);
-
-        // Are we past the distance at which we care?
-        if(r > plan->max_radius)
-          continue;
-
-        // Update the occupancy distance if we're closer
-        if(r < ncell->occ_dist)
-        {
-          ncell->occ_dist = r;
-          // Also put its neighbors on the queue for processing
-          for(dj = -1; dj <= 1; dj+= 2)
-          {
-            for(di = -1; di <= 1; di+= 2)
-            {
-              if (!PLAN_VALID(plan, ncell->ci + di, ncell->cj + dj))           
 
-                continue;
-              // Have we already seen this cell?
-              if(plan->marks[PLAN_INDEX(plan, ncell->ci + di, ncell->cj + dj)])
-                continue;
-              // Add it to the queue
-              /*
-              heap_insert(Q, ncell->occ_dist,
-                          plan->cells + PLAN_INDEX(plan,
-                                                   ncell->ci+di,
-                                                   ncell->cj+dj));
-                                                   */
-              Q[qtail++] = plan->cells + PLAN_INDEX(plan,
-                                                    ncell->ci+di,
-                                                    ncell->cj+dj);
-            }
-          }
-        }
+        ci = cell->ci + i;
+        paddr = 3*PLAN_INDEX(plan,ci,plan->size_y - cj - 1);
+        pixels[paddr] = 255;
+        pixels[paddr+1] = 0;
+        pixels[paddr+2] = 255;
       }
     }
   }
-  //heap_free(Q);
+  */
+
+  pixbuf = gdk_pixbuf_new_from_data(pixels, 
+                                    GDK_COLORSPACE_RGB,
+                                    0,8,
+                                    plan->size_x,
+                                    plan->size_y,
+                                    plan->size_x * 3,
+                                    NULL, NULL);
+  
+  gdk_pixbuf_save(pixbuf,fname,"png",&error,NULL);
+  gdk_pixbuf_unref(pixbuf);
+  free(pixels);
 }
 #endif
 
@@ -421,6 +548,7 @@
 // If cachefile is non-NULL, then we try to read the c-space from that
 // file.  If that fails, then we construct the c-space as per normal and
 // then write it out to cachefile.
+#if 0
 void 
 plan_update_cspace(plan_t *plan, const char* cachefile)
 {
@@ -457,6 +585,7 @@
   draw_cspace(plan,"plan_cspace.png");
 #endif
 }
+#endif
 
 #if HAVE_OPENSSL_MD5_H && HAVE_LIBCRYPTO
 // Write the cspace occupancy distance values to a file, one per line.

Modified: code/player/branches/cmake/server/drivers/planner/wavefront/plan.h
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/plan.h  
2008-04-18 07:54:24 UTC (rev 6359)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan.h  
2008-04-18 08:07:57 UTC (rev 6360)
@@ -9,10 +9,15 @@
 #ifndef PLAN_H
 #define PLAN_H
 
+#include "heap.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#define PLAN_DEFAULT_HEAP_SIZE 1000
+#define PLAN_MAX_COST 1e9
+
 // Description for a grid single cell
 typedef struct _plan_cell_t
 {
@@ -21,13 +26,18 @@
   
   // Occupancy state (-1 = free, 0 = unknown, +1 = occ)
   char occ_state;
+  char occ_state_dyn;
 
   // Distance to the nearest occupied cell
   float occ_dist;
+  float occ_dist_dyn;
 
   // Distance (cost) to the goal
   float plan_cost;
 
+  // Mark used in dynamic programming
+  char mark;
+
   // The next cell in the plan
   struct _plan_cell_t *plan_next;
   
@@ -61,14 +71,29 @@
 
   // The grid data
   plan_cell_t *cells;
-  unsigned char* marks;
-  size_t marks_size;
+
+  // Dynamic obstacle hitpoints
+  unsigned short* obs_pts;
+  size_t obs_pts_size;
+  size_t obs_pts_num;
+
+  // Distance penalty kernel, pre-computed in plan_compute_dist_kernel();
+  float* dist_kernel;
+  int dist_kernel_width;
+  float dist_kernel_3x3[9];
   
-  // Queue of cells to update
-  int queue_start, queue_len, queue_size;
-  plan_cell_t **queue;
+  // Priority queue of cells to update
+  heap_t* heap;
 
-  // Waypoints
+  // The global path
+  int path_count, path_size;
+  plan_cell_t **path;
+  
+  // The local path (mainly for debugging)
+  int lpath_count, lpath_size;
+  plan_cell_t **lpath;
+
+  // Waypoints extracted from global path
   int waypoint_count, waypoint_size;
   plan_cell_t **waypoints;
 } plan_t;
@@ -78,9 +103,15 @@
 plan_t *plan_alloc(double abs_min_radius, double des_min_radius,
                    double max_radius, double dist_penalty);
 
+void plan_compute_dist_kernel(plan_t* plan);
+
 // Destroy a planner
 void plan_free(plan_t *plan);
 
+// Initialize the plan
+void plan_init(plan_t *plan, 
+               double res, double sx, double sy, double ox, double oy);
+
 // Reset the plan
 void plan_reset(plan_t *plan);
 
@@ -97,11 +128,13 @@
 int plan_check_inbounds(plan_t* plan, double x, double y);
 
 // Construct the configuration space from the occupancy grid.
-void plan_update_cspace(plan_t *plan, const char* cachefile);
+//void plan_update_cspace(plan_t *plan, const char* cachefile);
+void plan_compute_cspace(plan_t *plan);
 
-// Generate the plan
-void plan_update_plan(plan_t *plan, double gx, double gy);
+int plan_do_global(plan_t *plan, double lx, double ly, double gx, double gy);
 
+int plan_do_local(plan_t *plan, double lx, double ly, double plan_halfwidth);
+
 // Generate a path to the goal
 void plan_update_waypoints(plan_t *plan, double px, double py);
 

Modified: 
code/player/branches/cmake/server/drivers/planner/wavefront/plan_plan.c
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/plan_plan.c     
2008-04-18 07:54:24 UTC (rev 6359)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan_plan.c     
2008-04-18 08:07:57 UTC (rev 6360)
@@ -11,44 +11,147 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <limits.h>
+#include <float.h>
 
 #include "plan.h"
 
 // Plan queue stuff
 void plan_push(plan_t *plan, plan_cell_t *cell);
 plan_cell_t *plan_pop(plan_t *plan);
+int _plan_update_plan(plan_t *plan, double lx, double ly, double gx, double 
gy);
+int _plan_find_local_goal(plan_t *plan, double* gx, double* gy, double lx, 
double ly);
 
 
+int
+plan_do_global(plan_t *plan, double lx, double ly, double gx, double gy)
+{
+  plan_cell_t* cell;
+  int li, lj;
+
+  // Set bounds to look over the entire grid
+  plan_set_bounds(plan, 0, 0, plan->size_x - 1, plan->size_y - 1);
+
+  // Reset plan costs
+  plan_reset(plan);
+
+  plan->path_count = 0;
+  if(_plan_update_plan(plan, lx, ly, gx, gy) != 0)
+  {
+    // no path
+    return(-1);
+  }
+
+  li = PLAN_GXWX(plan, lx);
+  lj = PLAN_GYWY(plan, ly);
+
+  // Cache the path
+  for(cell = plan->cells + PLAN_INDEX(plan,li,lj);
+      cell;
+      cell = cell->plan_next)
+  {
+    if(plan->path_count >= plan->path_size)
+    {
+      plan->path_size *= 2;
+      plan->path = (plan_cell_t**)realloc(plan->path,
+                                          plan->path_size * 
sizeof(plan_cell_t*));
+      assert(plan->path);
+    }
+    plan->path[plan->path_count++] = cell;
+  }
+
+  return(0);
+}
+
+int
+plan_do_local(plan_t *plan, double lx, double ly, double plan_halfwidth)
+{
+  double gx, gy;
+  int li, lj;
+  int xmin,ymin,xmax,ymax;
+  plan_cell_t* cell;
+
+  // Set bounds as directed
+  xmin = PLAN_GXWX(plan, lx - plan_halfwidth);
+  ymin = PLAN_GXWX(plan, ly - plan_halfwidth);
+  xmax = PLAN_GXWX(plan, lx + plan_halfwidth);
+  ymax = PLAN_GXWX(plan, ly + plan_halfwidth);
+  plan_set_bounds(plan, xmin, ymin, xmax, ymax);
+
+  // Reset plan costs (within the local patch)
+  plan_reset(plan);
+
+  // Find a local goal to pursue
+  if(_plan_find_local_goal(plan, &gx, &gy, lx, ly) != 0)
+  {
+    puts("no local goal");
+    return(-1);
+  }
+
+  printf("local goal: %.3lf, %.3lf\n", gx, gy);
+
+  if(_plan_update_plan(plan, lx, ly, gx, gy) != 0)
+  {
+    puts("local plan update failed");
+    return(-1);
+  }
+
+  li = PLAN_GXWX(plan, lx);
+  lj = PLAN_GYWY(plan, ly);
+
+  // Cache the path
+  for(cell = plan->cells + PLAN_INDEX(plan,li,lj);
+      cell;
+      cell = cell->plan_next)
+  {
+    if(plan->lpath_count >= plan->lpath_size)
+    {
+      plan->lpath_size *= 2;
+      plan->lpath = (plan_cell_t**)realloc(plan->lpath,
+                                           plan->lpath_size * 
sizeof(plan_cell_t*));
+      assert(plan->lpath);
+    }
+    plan->lpath[plan->lpath_count++] = cell;
+  }
+  return(0);
+}
+
+
 // Generate the plan
-void plan_update_plan(plan_t *plan, double gx, double gy)
+int 
+_plan_update_plan(plan_t *plan, double lx, double ly, double gx, double gy)
 {
   int oi, oj, di, dj, ni, nj;
+  int gi, gj, li,lj;
   float cost;
   plan_cell_t *cell, *ncell;
+  int reached_start=0;
 
-  // Reset the grid
-  for (nj = 0; nj < plan->size_y; nj++)
-  {
-    for (ni = 0; ni < plan->size_x; ni++)
-    {
-      cell = plan->cells + PLAN_INDEX(plan, ni, nj);
-      cell->plan_cost = 1e6;
-      cell->plan_next = NULL;
-    }
-  }
-  
   // Reset the queue
-  plan->queue_start = 0;
-  plan->queue_len = 0;
+  heap_reset(plan->heap);
 
   // Initialize the goal cell
-  ni = PLAN_GXWX(plan, gx);
-  nj = PLAN_GYWY(plan, gy);
+  gi = PLAN_GXWX(plan, gx);
+  gj = PLAN_GYWY(plan, gy);
+
+  // Initialize the start cell
+  li = PLAN_GXWX(plan, lx);
+  lj = PLAN_GYWY(plan, ly);
+
+  printf("planning from %d,%d to %d,%d\n", li,lj,gi,gj);
+
+  if(!PLAN_VALID_BOUNDS(plan, gi, gj))
+  {
+    puts("goal out of bounds");
+    return(-1);
+  }
   
-  if (!PLAN_VALID_BOUNDS(plan, ni, nj))
-    return;
+  if(!PLAN_VALID_BOUNDS(plan, li, lj))
+  {
+    puts("start out of bounds");
+    return(-1);
+  }
 
-  cell = plan->cells + PLAN_INDEX(plan, ni, nj);
+  cell = plan->cells + PLAN_INDEX(plan, gi, gj);
   cell->plan_cost = 0;
   plan_push(plan, cell);
 
@@ -63,54 +166,141 @@
 
     //printf("pop %d %d %f\n", cell->ci, cell->cj, cell->plan_cost);
 
+    float* p = plan->dist_kernel_3x3;
     for (dj = -1; dj <= +1; dj++)
     {
-      for (di = -1; di <= +1; di++)
+      ncell = plan->cells + PLAN_INDEX(plan,oi-1,oj+dj);
+      for (di = -1; di <= +1; di++, p++, ncell++)
       {
-        if (di == 0 && dj == 0)
+        if (!di && !dj)
           continue;
+        //if (di && dj)
+          //continue;
         
         ni = oi + di;
         nj = oj + dj;
 
         if (!PLAN_VALID_BOUNDS(plan, ni, nj))
           continue;
-        ncell = plan->cells + PLAN_INDEX(plan, ni, nj);
 
-        if (ncell->occ_dist < plan->abs_min_radius)
+        if(ncell->mark)
           continue;
 
-        cost = cell->plan_cost + plan->scale;
+        if (ncell->occ_dist_dyn < plan->abs_min_radius)
+          continue;
 
-        if (ncell->occ_dist < plan->max_radius)
-          cost += plan->dist_penalty * (plan->max_radius - ncell->occ_dist);
+        cost = cell->plan_cost + *p;
 
-        if (cost < ncell->plan_cost)
+        if(ncell->occ_dist_dyn < plan->max_radius)
+          cost += plan->dist_penalty * (plan->max_radius - 
ncell->occ_dist_dyn);
+
+        if(cost < ncell->plan_cost)
         {
           ncell->plan_cost = cost;
           ncell->plan_next = cell;
+
+          // Are we done?
+          if((ncell->ci == li) && (ncell->cj == lj))
+            reached_start=1;
+
           plan_push(plan, ncell);
         }
       }
     }
   }
 
-  return;
+  /*
+  if(!reached_start)
+  {
+    puts("never found start");
+    return(-1);
+  }
+  else
+  */
+    return(0);
 }
 
+int 
+_plan_find_local_goal(plan_t *plan, double* gx, double* gy, 
+                      double lx, double ly)
+{
+  int c;
+  int c_min;
+  double squared_d;
+  double squared_d_min;
+  int li,lj;
+  plan_cell_t* cell;
 
+  // Must already have computed a global goal
+  if(plan->path_count == 0)
+  {
+    puts("no global path");
+    return(-1);
+  }
+
+  li = PLAN_GXWX(plan, lx);
+  lj = PLAN_GYWY(plan, ly);
+
+  // Find the closest place to jump on the global path
+  squared_d_min = DBL_MAX;
+  c_min = -1;
+  for(c=0;c<plan->path_count;c++)
+  {
+    cell = plan->path[c];
+    squared_d = ((cell->ci - li) * (cell->ci - li) + 
+                 (cell->cj - lj) * (cell->cj - lj));
+    if(squared_d < squared_d_min)
+    {
+      squared_d_min = squared_d;
+      c_min = c;
+    }
+  }
+  assert(c_min > -1);
+
+  // Follow the path to find the last cell that's inside the local planning
+  // area
+  for(c=c_min; c<plan->path_count; c++)
+  {
+    cell = plan->path[c];
+    
+    //printf("step %d: (%d,%d)\n", c, cell->ci, cell->cj);
+
+    if((cell->ci < plan->min_x) || (cell->ci > plan->max_x) ||
+       (cell->cj < plan->min_y) || (cell->cj > plan->max_y))
+    {
+      // Did we move at least one cell along the path?
+      if(c == c_min)
+      {
+        // nope; the entire global path is outside the local region; can't
+        // fix that here
+        puts("global path not in local region");
+        return(-1);
+      }
+      else
+        break;
+    }
+  }
+
+  assert(c > c_min);
+
+  cell = plan->path[c-1];
+
+  //printf("ci: %d cj: %d\n", cell->ci, cell->cj);
+  *gx = PLAN_WXGX(plan, cell->ci);
+  *gy = PLAN_WYGY(plan, cell->cj);
+  
+  return(0);
+}
+
 // Push a plan location onto the queue
 void plan_push(plan_t *plan, plan_cell_t *cell)
 {
-  int i;
+  // Substract from max cost because the heap is set up to return the max
+  // element.  This could of course be changed.
+  assert(PLAN_MAX_COST-cell->plan_cost > 0);
+  cell->mark = 1;
+  heap_insert(plan->heap, PLAN_MAX_COST - cell->plan_cost, cell);
 
-  // HACK: should resize the queue dynamically (tricky for circular queue)
-  assert(plan->queue_len < plan->queue_size);
-
-  i = (plan->queue_start + plan->queue_len) % plan->queue_size;
-  plan->queue[i] = cell;
-  plan->queue_len++;
-
   return;
 }
 
@@ -118,16 +308,9 @@
 // Pop a plan location from the queue
 plan_cell_t *plan_pop(plan_t *plan)
 {
-  int i;
-  plan_cell_t *cell;
-  
-  if (plan->queue_len == 0)
-    return NULL;
 
-  i = plan->queue_start % plan->queue_size;
-  cell = plan->queue[i];
-  plan->queue_start++;
-  plan->queue_len--;
-
-  return cell;
+  if(heap_empty(plan->heap))
+    return(NULL);
+  else
+    return(heap_extract_max(plan->heap));
 }

Copied: code/player/branches/cmake/server/drivers/planner/wavefront/test.c 
(from rev 6287, code/player/trunk/server/drivers/planner/wavefront/test.c)
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/test.c          
                (rev 0)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/test.c  
2008-04-18 08:07:57 UTC (rev 6360)
@@ -0,0 +1,225 @@
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "plan.h"
+
+#define USAGE "USAGE: test <map.png> <res> <lx> <ly> <gx> <gy>"
+
+// compute linear index for given map coords
+#define MAP_IDX(sx, i, j) ((sx) * (j) + (i))
+
+void draw_cspace(plan_t* plan, const char* fname);
+void draw_path(plan_t* plan, double lx, double ly, const char* fname);
+
+double get_time(void);
+
+int read_map_from_image(int* size_x, int* size_y, char** mapdata, 
+                               const char* fname, int negate);
+
+int
+main(int argc, char** argv)
+{
+  char* fname;
+  double res;
+  double lx,ly,gx,gy;
+
+
+  char* mapdata;
+  int sx, sy;
+  int i, j;
+
+  plan_t* plan;
+  double robot_radius=0.25;
+  double safety_dist=0.2;
+  double max_radius=1.0;
+  double dist_penalty=1.0;;
+  double plan_halfwidth = 5.0;
+
+  double t_c0, t_c1, t_p0, t_p1, t_w0, t_w1;
+
+  if(argc < 7)
+  {
+    puts(USAGE);
+    exit(-1);
+  }
+
+  fname = argv[1];
+  res = atof(argv[2]);
+  lx = atof(argv[3]);
+  ly = atof(argv[4]);
+  gx = atof(argv[5]);
+  gy = atof(argv[6]);
+
+  assert(read_map_from_image(&sx, &sy, &mapdata, fname, 0) == 0);
+
+  assert((plan = plan_alloc(robot_radius+safety_dist,
+                           robot_radius+safety_dist,
+                           max_radius,
+                           dist_penalty)));
+
+  // allocate space for map cells
+  assert(plan->cells == NULL);
+  assert((plan->cells = 
+         (plan_cell_t*)realloc(plan->cells,
+                               (sx * sy * sizeof(plan_cell_t)))));
+  
+  // Copy over obstacle information from the image data that we read
+  for(j=0;j<sy;j++)
+  {
+    for(i=0;i<sx;i++)
+    {
+      plan->cells[i+j*sx].occ_state = mapdata[MAP_IDX(sx,i,j)];
+    }
+  }
+  free(mapdata);
+  
+  // Do initialization
+  plan_init(plan, res, sx, sy, 0.0, 0.0);
+
+  t_c0 = get_time();
+  plan_compute_cspace(plan);
+  t_c1 = get_time();
+
+  draw_cspace(plan,"cspace.png");
+
+  printf("cspace: %.6lf\n", t_c1-t_c0);
+  
+  // compute costs to the new goal
+  t_p0 = get_time();
+  if(plan_do_global(plan, lx, ly, gx, gy) < 0)
+    puts("no global path");
+  t_p1 = get_time();
+
+  plan_update_waypoints(plan, lx, ly);
+
+  printf("gplan : %.6lf\n", t_p1-t_p0);
+  for(i=0;i<plan->waypoint_count;i++)
+  {
+    double wx, wy;
+    plan_convert_waypoint(plan, plan->waypoints[i], &wx, &wy);
+    printf("%d: (%d,%d) : (%.3lf,%.3lf)\n",
+           i, plan->waypoints[i]->ci, plan->waypoints[i]->cj, wx, wy);
+  }
+
+  for(i=0;i<1;i++)
+  {
+    // compute costs to the new goal
+    t_p0 = get_time();
+    if(plan_do_local(plan, lx, ly, plan_halfwidth) < 0)
+       puts("no local path");
+    t_p1 = get_time();
+
+    printf("lplan : %.6lf\n", t_p1-t_p0);
+
+    // compute a path to the goal from the current position
+    t_w0 = get_time();
+    plan_update_waypoints(plan, lx, ly);
+    t_w1 = get_time();
+
+    draw_path(plan,lx,ly,"plan.png");
+
+    printf("waypnt: %.6lf\n", t_w1-t_w0);
+    puts("");
+  }
+
+  if(plan->waypoint_count == 0)
+  {
+    puts("no waypoints");
+  }
+  else
+  {
+    for(i=0;i<plan->waypoint_count;i++)
+    {
+      double wx, wy;
+      plan_convert_waypoint(plan, plan->waypoints[i], &wx, &wy);
+      printf("%d: (%d,%d) : (%.3lf,%.3lf)\n",
+             i, plan->waypoints[i]->ci, plan->waypoints[i]->cj, wx, wy);
+    }
+  }
+
+  plan_free(plan);
+
+  return(0);
+}
+
+int
+read_map_from_image(int* size_x, int* size_y, char** mapdata, 
+                    const char* fname, int negate)
+{
+  GdkPixbuf* pixbuf;
+  guchar* pixels;
+  guchar* p;
+  int rowstride, n_channels, bps;
+  GError* error = NULL;
+  int i,j,k;
+  double occ;
+  int color_sum;
+  double color_avg;
+
+  // Initialize glib
+  g_type_init();
+
+  printf("MapFile loading image file: %s...", fname);
+  fflush(stdout);
+
+  // Read the image
+  if(!(pixbuf = gdk_pixbuf_new_from_file(fname, &error)))
+  {
+    printf("failed to open image file %s", fname);
+    return(-1);
+  }
+
+  *size_x = gdk_pixbuf_get_width(pixbuf);
+  *size_y = gdk_pixbuf_get_height(pixbuf);
+
+  assert(*mapdata = (char*)malloc(sizeof(char) * (*size_x) * (*size_y)));
+
+  rowstride = gdk_pixbuf_get_rowstride(pixbuf);
+  bps = gdk_pixbuf_get_bits_per_sample(pixbuf)/8;
+  n_channels = gdk_pixbuf_get_n_channels(pixbuf);
+  if(gdk_pixbuf_get_has_alpha(pixbuf))
+    n_channels++;
+
+  // Read data
+  pixels = gdk_pixbuf_get_pixels(pixbuf);
+  for(j = 0; j < *size_y; j++)
+  {
+    for (i = 0; i < *size_x; i++)
+    {
+      p = pixels + j*rowstride + i*n_channels*bps;
+      color_sum = 0;
+      for(k=0;k<n_channels;k++)
+        color_sum += *(p + (k * bps));
+      color_avg = color_sum / (double)n_channels;
+
+      if(negate)
+        occ = color_avg / 255.0;
+      else
+        occ = (255 - color_avg) / 255.0;
+      if(occ > 0.95)
+        (*mapdata)[MAP_IDX(*size_x,i,*size_y - j - 1)] = +1;
+      else if(occ < 0.1)
+        (*mapdata)[MAP_IDX(*size_x,i,*size_y - j - 1)] = -1;
+      else
+        (*mapdata)[MAP_IDX(*size_x,i,*size_y - j - 1)] = 0;
+    }
+  }
+
+  gdk_pixbuf_unref(pixbuf);
+
+  puts("Done.");
+  printf("MapFile read a %d X %d map\n", *size_x, *size_y);
+  return(0);
+}
+
+double 
+get_time(void)
+{
+  struct timeval curr;
+  gettimeofday(&curr,NULL);
+  return(curr.tv_sec + curr.tv_usec / 1e6);
+}

Modified: 
code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc    
2008-04-18 07:54:24 UTC (rev 6359)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc    
2008-04-18 08:07:57 UTC (rev 6360)
@@ -507,6 +507,7 @@
   // Got new map info pushed to us.  We'll save this info and get the new
   // map.
   this->plan->scale = info->scale;
+  plan_compute_dist_kernel(this->plan);
   this->plan->size_x = info->width;
   this->plan->size_y = info->height;
   this->plan->origin_x = info->origin.px;
@@ -766,10 +767,17 @@
       }
 #endif
 
-      // compute costs to the new goal
-      plan_update_plan(this->plan, this->target_x, this->target_y);
+      // compute costs to the new goal.  Try local plan first
+      if(plan_do_local(this->plan, this->localize_x, this->localize_y, 5.0) < 
0)
+      {
+        puts("Wavefront: local plan failed");
 
-      // compute a path to the goal from the current position
+        if(plan_do_global(this->plan, this->localize_x, this->localize_x, 
+                          this->target_x, this->target_y) < 0)
+          puts("Wavefront: global plan failed");
+      }
+                       
+      // extract waypoints along the path to the goal from the current position
       plan_update_waypoints(this->plan, this->localize_x, this->localize_y);
 
 #if 0
@@ -1124,6 +1132,7 @@
   {
     PLAYER_WARN("failed to get map info");
     this->plan->scale = 0.1;
+    plan_compute_dist_kernel(this->plan);
     this->plan->size_x = 0;
     this->plan->size_y = 0;
     this->plan->origin_x = 0.0;
@@ -1135,6 +1144,7 @@
 
   // copy in the map info
   this->plan->scale = info->scale;
+  plan_compute_dist_kernel(this->plan);
   this->plan->size_x = info->width;
   this->plan->size_y = info->height;
   this->plan->origin_x = info->origin.px;
@@ -1180,7 +1190,8 @@
   if(this->GetMap(false) < 0)
     return(-1);
 
-  plan_update_cspace(this->plan,this->cspace_fname);
+  //plan_update_cspace(this->plan,this->cspace_fname);
+  plan_compute_cspace(this->plan);
 
   this->have_map = true;
   this->new_map = true;
@@ -1260,7 +1271,8 @@
       // Now get the map data, possibly in separate tiles.
       if(this->GetMap(true) < 0) return -1;
 
-      plan_update_cspace(this->plan,this->cspace_fname);
+      //plan_update_cspace(this->plan,this->cspace_fname);
+      plan_compute_cspace(this->plan);
 
       this->have_map = true;
       this->new_map = true;


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to