Revision: 4479
http://playerstage.svn.sourceforge.net/playerstage/?rev=4479&view=rev
Author: gerkey
Date: 2008-04-04 17:31:33 -0700 (Fri, 04 Apr 2008)
Log Message:
-----------
added heap for priority queue, fixed cost propagation
Modified Paths:
--------------
code/player/trunk/server/drivers/planner/wavefront/Makefile.am
code/player/trunk/server/drivers/planner/wavefront/Makefile.test
code/player/trunk/server/drivers/planner/wavefront/plan.c
code/player/trunk/server/drivers/planner/wavefront/plan.h
code/player/trunk/server/drivers/planner/wavefront/plan_plan.c
code/player/trunk/server/drivers/planner/wavefront/test.c
Added Paths:
-----------
code/player/trunk/server/drivers/planner/wavefront/heap.c
code/player/trunk/server/drivers/planner/wavefront/heap.h
Modified: code/player/trunk/server/drivers/planner/wavefront/Makefile.am
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/Makefile.am
2008-04-04 19:59:14 UTC (rev 4478)
+++ code/player/trunk/server/drivers/planner/wavefront/Makefile.am
2008-04-05 00:31:33 UTC (rev 4479)
@@ -6,5 +6,4 @@
AM_CPPFLAGS = -Wall -g -I$(top_srcdir) `pkg-config --cflags gdk-pixbuf-2.0`
libwavefront_la_SOURCES = plan.c plan_plan.c plan_waypoint.c plan.h \
- wavefront.cc
-#heap.h heap.c
+ wavefront.cc heap.h heap.c
Modified: code/player/trunk/server/drivers/planner/wavefront/Makefile.test
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/Makefile.test
2008-04-04 19:59:14 UTC (rev 4478)
+++ code/player/trunk/server/drivers/planner/wavefront/Makefile.test
2008-04-05 00:31:33 UTC (rev 4479)
@@ -1,9 +1,9 @@
CFLAGS = -I. -I../../../.. -Wall -Werror -O2 -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
+SRCS = test.c plan.c plan_plan.c plan_waypoint.c heap.c
-test: $(SRCS) plan.h
+test: $(SRCS) plan.h heap.h
gcc $(CFLAGS) -o $@ $(SRCS) $(LIBS)
clean:
Added: code/player/trunk/server/drivers/planner/wavefront/heap.c
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/heap.c
(rev 0)
+++ code/player/trunk/server/drivers/planner/wavefront/heap.c 2008-04-05
00:31:33 UTC (rev 4479)
@@ -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]);
+}
Added: code/player/trunk/server/drivers/planner/wavefront/heap.h
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/heap.h
(rev 0)
+++ code/player/trunk/server/drivers/planner/wavefront/heap.h 2008-04-05
00:31:33 UTC (rev 4479)
@@ -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/trunk/server/drivers/planner/wavefront/plan.c
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/plan.c 2008-04-04
19:59:14 UTC (rev 4478)
+++ code/player/trunk/server/drivers/planner/wavefront/plan.c 2008-04-05
00:31:33 UTC (rev 4479)
@@ -63,10 +63,12 @@
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->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->waypoint_size = 100;
@@ -81,7 +83,7 @@
{
if (plan->cells)
free(plan->cells);
- free(plan->queue);
+ heap_free(plan->heap);
free(plan->waypoints);
free(plan);
@@ -218,7 +220,7 @@
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++)
@@ -238,7 +240,7 @@
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;
@@ -248,10 +250,10 @@
}
}
-#if 0
+#if 1
#include <gdk-pixbuf/gdk-pixbuf.h>
-void
+ void
draw_cspace(plan_t* plan, const char* fname)
{
GdkPixbuf* pixbuf;
@@ -297,6 +299,105 @@
plan->size_y,
plan->size_x * 3,
NULL, NULL);
+
+ gdk_pixbuf_save(pixbuf,fname,"png",&error,NULL);
+ gdk_pixbuf_unref(pixbuf);
+ free(pixels);
+}
+
+ 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 ci, cj;
+ plan_cell_t* cell;
+
+ ci = PLAN_GXWX(plan, lx);
+ cj = PLAN_GYWY(plan, ly);
+
+ pixels = (guchar*)malloc(sizeof(guchar)*plan->size_x*plan->size_y*3);
+
+ 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;
+ }
+ */
+ }
+ }
+
+ cell = plan->cells + PLAN_INDEX(plan, ci, cj);
+ while (cell != NULL)
+ {
+ paddr = 3*PLAN_INDEX(plan,cell->ci,plan->size_y - cell->cj - 1);
+ pixels[paddr] = 0;
+ pixels[paddr+1] = 255;
+ pixels[paddr+2] = 0;
+
+ cell = cell->plan_next;
+ }
+
+ for(p=0;p<plan->waypoint_count;p++)
+ {
+ cell = plan->waypoints[p];
+ for(j=-3;j<=3;j++)
+ {
+ cj = cell->cj + j;
+ for(i=-3;i<=3;i++)
+ {
+ 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;
+ }
+ }
+ }
+
+ 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);
Modified: code/player/trunk/server/drivers/planner/wavefront/plan.h
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/plan.h 2008-04-04
19:59:14 UTC (rev 4478)
+++ code/player/trunk/server/drivers/planner/wavefront/plan.h 2008-04-05
00:31:33 UTC (rev 4479)
@@ -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
{
@@ -65,8 +70,9 @@
size_t marks_size;
// Queue of cells to update
- int queue_start, queue_len, queue_size;
- plan_cell_t **queue;
+ //int queue_start, queue_len, queue_size;
+ //plan_cell_t **queue;
+ heap_t* heap;
// Waypoints
int waypoint_count, waypoint_size;
Modified: code/player/trunk/server/drivers/planner/wavefront/plan_plan.c
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/plan_plan.c
2008-04-04 19:59:14 UTC (rev 4478)
+++ code/player/trunk/server/drivers/planner/wavefront/plan_plan.c
2008-04-05 00:31:33 UTC (rev 4479)
@@ -32,14 +32,15 @@
for (ni = 0; ni < plan->size_x; ni++)
{
cell = plan->cells + PLAN_INDEX(plan, ni, nj);
- cell->plan_cost = 1e6;
+ cell->plan_cost = PLAN_MAX_COST;
cell->plan_next = NULL;
}
}
// Reset the queue
- plan->queue_start = 0;
- plan->queue_len = 0;
+ //plan->queue_start = 0;
+ //plan->queue_len = 0;
+ heap_reset(plan->heap);
// Initialize the goal cell
ni = PLAN_GXWX(plan, gx);
@@ -67,8 +68,10 @@
{
for (di = -1; di <= +1; di++)
{
- if (di == 0 && dj == 0)
+ if (!di && !dj)
continue;
+ //if (di && dj)
+ //continue;
ni = oi + di;
nj = oj + dj;
@@ -80,7 +83,10 @@
if (ncell->occ_dist < plan->abs_min_radius)
continue;
- cost = cell->plan_cost + plan->scale;
+ if(di && dj)
+ cost = cell->plan_cost + plan->scale * M_SQRT2;
+ else
+ cost = cell->plan_cost + plan->scale;
if (ncell->occ_dist < plan->max_radius)
cost += plan->dist_penalty * (plan->max_radius - ncell->occ_dist);
@@ -102,6 +108,7 @@
// Push a plan location onto the queue
void plan_push(plan_t *plan, plan_cell_t *cell)
{
+ /*
int i;
// HACK: should resize the queue dynamically (tricky for circular queue)
@@ -110,7 +117,12 @@
i = (plan->queue_start + plan->queue_len) % plan->queue_size;
plan->queue[i] = cell;
plan->queue_len++;
+ */
+ // Substract from max cost because the heap is set up to return the max
+ // element. This could of course be changed.
+ heap_insert(plan->heap, PLAN_MAX_COST - cell->plan_cost, cell);
+
return;
}
@@ -118,6 +130,7 @@
// Pop a plan location from the queue
plan_cell_t *plan_pop(plan_t *plan)
{
+ /*
int i;
plan_cell_t *cell;
@@ -128,6 +141,10 @@
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));
}
Modified: code/player/trunk/server/drivers/planner/wavefront/test.c
===================================================================
--- code/player/trunk/server/drivers/planner/wavefront/test.c 2008-04-04
19:59:14 UTC (rev 4478)
+++ code/player/trunk/server/drivers/planner/wavefront/test.c 2008-04-05
00:31:33 UTC (rev 4479)
@@ -12,6 +12,9 @@
// 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,
@@ -35,7 +38,7 @@
double max_radius=1.0;
double dist_penalty=1.0;;
- double t0, t1, t2, t3;
+ double t_c0, t_c1, t_p0, t_p1, t_w0, t_w1;
if(argc < 7)
{
@@ -86,22 +89,28 @@
free(mapdata);
- t0 = get_time();
+ t_c0 = get_time();
plan_update_cspace(plan,NULL);
- t1 = get_time();
+ t_c1 = get_time();
+ draw_cspace(plan,"cspace.png");
+
// compute costs to the new goal
+ t_p0 = get_time();
plan_update_plan(plan, gx, gy);
- t2 = get_time();
+ t_p1 = get_time();
// compute a path to the goal from the current position
+ t_w0 = get_time();
plan_update_waypoints(plan, lx, ly);
- t3 = get_time();
+ t_w1 = get_time();
- printf("cspace: %.6lf\n", t1-t0);
- printf("update: %.6lf\n", t2-t1);
- printf("waypnt: %.6lf\n", t3-t2);
+ draw_path(plan,lx,ly,"plan.png");
+ printf("cspace: %.6lf\n", t_c1-t_c0);
+ printf("plan : %.6lf\n", t_p1-t_p0);
+ printf("waypnt: %.6lf\n", t_w1-t_w0);
+
if(plan->waypoint_count == 0)
{
puts("no path");
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
Register now and save $200. Hurry, offer ends at 11:59 p.m.,
Monday, April 7! Use priority code J8TLD2.
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