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

Log Message:
-----------
Merging changes 6320:6327 from trunk

Modified Paths:
--------------
    code/player/branches/cmake/server/drivers/localization/fakelocalize.cc
    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_control.c
    code/player/branches/cmake/server/drivers/planner/wavefront/plan_plan.c
    code/player/branches/cmake/server/drivers/planner/wavefront/test.c
    code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc

Property Changed:
----------------
    code/player/branches/cmake/server/drivers/health/statgrab/


Property changes on: code/player/branches/cmake/server/drivers/health/statgrab
___________________________________________________________________
Name: svn:ignore
   - Makefile
Makefile.in
.deps
*.la

   + Makefile
Makefile.in
.deps
*.la
.libs


Modified: code/player/branches/cmake/server/drivers/localization/fakelocalize.cc
===================================================================
--- code/player/branches/cmake/server/drivers/localization/fakelocalize.cc      
2008-04-18 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/localization/fakelocalize.cc      
2008-04-18 08:35:32 UTC (rev 6364)
@@ -48,6 +48,7 @@
 @par Provides
 
 - @ref interface_localize
+- @ref interface_position2d (optionally)
 
 @par Requires
 
@@ -88,23 +89,27 @@
 */
 /** @} */
 
-
-#include <sys/types.h>
-#include <netinet/in.h>
 #include <unistd.h>
+#include <cstddef>
+#include <cstdlib>
+#include <ctime>
+#include <cassert>
+#include <cstring>
 
 #include <libplayercore/playercore.h>
 
-#define SLEEPTIME_US 100000
+#define SLEEPTIME_NS 100000000
 
-#define min(x,y) (x < y ? x : y)
+#define min(x,y) ((x) < (y) ? (x) : (y))
 
+using namespace std;
+
 // Driver for computing the free c-space from a laser scan.
 class FakeLocalize : public Driver
 {
   // Constructor
   public: FakeLocalize( ConfigFile* cf, int section);
-  ~FakeLocalize();
+  public: virtual ~FakeLocalize();
 
   // Setup/shutdown/run routines.
   public: virtual int Setup();
@@ -114,30 +119,27 @@
                                      player_msghdr * hdr,
                                      void * data);
 
-
   // Simulation stuff.
   private: int UpdateData();
   private: Device *sim;
   private: player_devaddr_t sim_id;
   private: player_devaddr_t localize_addr;
+  private: player_devaddr_t position2d_addr;
   private: char* model;
 };
 
-
 // Initialization function
 Driver* FakeLocalize_Init( ConfigFile* cf, int section)
 {
   return ((Driver*) (new FakeLocalize( cf, section)));
 }
 
-
 // a driver registration function
 void fakelocalize_Register(DriverTable* table)
 {
   table->AddDriver("fakelocalize", FakeLocalize_Init);
 }
 
-
 
////////////////////////////////////////////////////////////////////////////////
 // Constructor
 FakeLocalize::FakeLocalize( ConfigFile* cf, int section)
@@ -151,8 +153,8 @@
     return;
   }
   this->sim = NULL;
-
-  memset(&this->localize_addr, 0, sizeof(player_devaddr_t));
+  memset(&(this->localize_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->position2d_addr), 0, sizeof(player_devaddr_t));
   // Do we create a localize interface?
   if(cf->ReadDeviceAddr(&(this->localize_addr), section, "provides",
                         PLAYER_LOCALIZE_CODE, -1, NULL) == 0)
@@ -163,7 +165,22 @@
       return;
     }
   }
+  // Do we create a position2d interface?
+  if(cf->ReadDeviceAddr(&(this->position2d_addr), section, "provides",
+                        PLAYER_POSITION2D_CODE, -1, NULL) == 0)
+  {
+    if(this->AddInterface(this->position2d_addr))
+    {
+      this->SetError(-1);
+      return;
+    }
+  }
 
+  if (!((this->localize_addr.interf) || (this->position2d_addr.interf)))
+  {
+    this->SetError(-1);
+    return;
+  }
 
   if(!(this->model = strdup(cf->ReadString(section, "model", NULL))))
   {
@@ -177,7 +194,7 @@
 
 FakeLocalize::~FakeLocalize()
 {
-  free (this->model);
+  free(this->model);
 }
 
 
////////////////////////////////////////////////////////////////////////////////
@@ -188,19 +205,18 @@
   if(!(this->sim = deviceTable->GetDevice(this->sim_id)))
   {
     PLAYER_ERROR("unable to locate suitable simulation device");
-    return(-1);
+    return -1;
   }
   if(this->sim->Subscribe(this->InQueue) != 0)
   {
     PLAYER_ERROR("unable to subscribe to simulation device");
-    return(-1);
+    return -1;
   }
 
   this->StartThread();
   return 0;
 }
 
-
 
////////////////////////////////////////////////////////////////////////////////
 // Shutdown the device (called by server thread).
 int FakeLocalize::Shutdown()
@@ -217,53 +233,70 @@
 FakeLocalize::UpdateData()
 {
   player_localize_data_t loc_data;
+  player_position2d_data_t pos_data;
   player_simulation_pose2d_req_t cfg;
 
   // Request pose
+  memset(&cfg, 0, sizeof cfg);
   cfg.name = this->model;
-  cfg.name_count = strlen(cfg.name);
+  cfg.name_count = strlen(cfg.name) + 1;
 
   Message * Reply = sim->Request(InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_SIMULATION_REQ_GET_POSE2D,
-               (void *) &cfg, sizeof(cfg), NULL);
+               reinterpret_cast<void *>(&cfg), sizeof cfg, NULL);
 
-  if (Reply && Reply->GetHeader()->type == PLAYER_MSGTYPE_RESP_ACK)
+  if (!Reply) return -1;
+  if (Reply->GetHeader()->type == PLAYER_MSGTYPE_RESP_ACK)
   {
-       // we got a good reply so update our data
-       assert(Reply->GetDataSize() > 0);
-       player_simulation_pose2d_req_t * resp = 
reinterpret_cast<player_simulation_pose2d_req_t *> (Reply->GetPayload());
+    // we got a good reply so update our data
+    assert(Reply->GetDataSize() > 0);
+    player_simulation_pose2d_req_t * resp = 
reinterpret_cast<player_simulation_pose2d_req_t *>(Reply->GetPayload());
+    assert(resp);
+    if (this->localize_addr.interf)
+    {
+      // Fill in loc_data
+      memset(&loc_data, 0, sizeof loc_data);
+      loc_data.pending_count = 0;
+      loc_data.pending_time = Reply->GetHeader()->timestamp;
+      loc_data.hypoths_count = 1;
+      loc_data.hypoths = new player_localize_hypoth_t[1];
 
-    // Fill in loc_data, byteswapping as we go.
-    loc_data.pending_count = 0;
-    loc_data.pending_time = Reply->GetHeader()->timestamp;
-    loc_data.hypoths_count = 1;
-    loc_data.hypoths = new player_localize_hypoth_t[1];
+      loc_data.hypoths[0].mean = resp->pose;
 
-    loc_data.hypoths[0].mean = resp->pose;
+      // zero covariance and max weight
+      memset(loc_data.hypoths[0].cov, 0, sizeof loc_data.hypoths[0].cov);
+      loc_data.hypoths[0].alpha = 1e6;
 
-    // zero covariance and max weight
-    memset(loc_data.hypoths[0].cov,0,sizeof(loc_data.hypoths[0].cov));
-    loc_data.hypoths[0].alpha = 1e6;
-
-    Publish(device_addr, PLAYER_MSGTYPE_DATA, 
PLAYER_LOCALIZE_DATA_HYPOTHS,&loc_data);
-    delete [] loc_data.hypoths;
+      Publish(this->localize_addr, PLAYER_MSGTYPE_DATA, 
PLAYER_LOCALIZE_DATA_HYPOTHS, reinterpret_cast<void *>(&loc_data));
+      delete []loc_data.hypoths;
+    }
+    if (this->position2d_addr.interf)
+    {
+      // Fill in pos_data
+      memset(&pos_data, 0, sizeof pos_data);
+      pos_data.pos.px = resp->pose.px;
+      pos_data.pos.py = resp->pose.py;
+      pos_data.pos.pa = resp->pose.pa;
+      this->Publish(this->position2d_addr, PLAYER_MSGTYPE_DATA, 
PLAYER_POSITION2D_DATA_STATE,
+                                          reinterpret_cast<void *>(&pos_data), 
sizeof pos_data, NULL);
+    }
     delete Reply;
     Reply = NULL;
   }
   else
   {
-       // we got an error, thats bad
+       // we got an error, that's bad
        delete Reply;
        return -1;
   }
 
-
-  return(0);
+  return 0;
 }
 
-
 void
 FakeLocalize::Main()
 {
+  struct timespec ts;
+
   for(;;)
   {
     if(this->UpdateData() < 0)
@@ -272,8 +305,9 @@
       pthread_exit(NULL);
     }
     this->ProcessMessages();
-
-    usleep(SLEEPTIME_US);
+    ts.tv_sec = 0;
+    ts.tv_nsec = SLEEPTIME_NS;
+    nanosleep(&ts, NULL);
   }
 }
 
@@ -281,36 +315,37 @@
                                 player_msghdr * hdr,
                                 void * data)
 {
-  player_localize_set_pose_t* setposereq;
-
   // Is it a request to set the filter's pose?
   if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
                            PLAYER_LOCALIZE_REQ_SET_POSE,
                            this->localize_addr))
     {
-      setposereq = (player_localize_set_pose_t*)data;
       player_simulation_pose2d_req_t req;
-
+      player_localize_set_pose_t * setposereq = 
(player_localize_set_pose_t*)data;
+      assert(setposereq);
       req.pose.px = setposereq->mean.px;
       req.pose.py = setposereq->mean.py;
       req.pose.pa = setposereq->mean.pa;
 
-      strcpy(req.name, this->model);
+      req.name = this->model;
+      req.name_count = strlen(req.name) + 1;
+
       // look up the named model
       Message * Reply = sim->Request(InQueue, PLAYER_MSGTYPE_REQ,
                                     PLAYER_SIMULATION_REQ_SET_POSE2D,
-                                    (void *) &req, sizeof(req), NULL);
-      if (Reply && Reply->GetHeader()->type == PLAYER_MSGTYPE_RESP_ACK)
+                                    reinterpret_cast<void *>(&req), sizeof 
req, NULL);
+      if (!Reply) return -1;
+      if (Reply->GetHeader()->type == PLAYER_MSGTYPE_RESP_ACK)
        {
          // Send an ACK
          this->Publish(this->localize_addr, resp_queue,
                        PLAYER_MSGTYPE_RESP_ACK,
                        PLAYER_LOCALIZE_REQ_SET_POSE);
-         return(0);
+         return 0;
        }
       else
        {
-         delete (Reply);
+         delete Reply;
          return -1;
        }
     }
@@ -323,16 +358,16 @@
 
       // Request pose
       cfg.name = this->model;
-      cfg.name_count = strlen(cfg.name);
+      cfg.name_count = strlen(cfg.name) + 1;
 
       Message * Reply = sim->Request(InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_SIMULATION_REQ_GET_POSE2D,
-                                    (void *) &cfg, sizeof(cfg), NULL);
-
-      if (Reply && Reply->GetHeader()->type == PLAYER_MSGTYPE_RESP_ACK)
+                                    reinterpret_cast<void *>(&cfg), sizeof 
cfg, NULL);
+      if (!Reply) return -1;
+      if (Reply->GetHeader()->type == PLAYER_MSGTYPE_RESP_ACK)
        {
-         assert(Reply->GetDataSize() == sizeof(cfg));
+         assert(Reply->GetDataSize() == sizeof cfg);
          player_simulation_pose2d_req_t * ans = 
reinterpret_cast<player_simulation_pose2d_req_t *> (Reply->GetPayload());
-
+         assert(ans);
          player_localize_get_particles_t resp;
          resp.mean.px = ans->pose.px;
          resp.mean.py = ans->pose.py;
@@ -355,7 +390,7 @@
          delete Reply;
          Reply = NULL;
 
-         return(0);
+         return 0;
        }
       else
        {
@@ -363,6 +398,5 @@
          return -1;
        }
     }
-  return(-1);
+  return -1;
 }
-

Modified: code/player/branches/cmake/server/drivers/planner/wavefront/plan.c
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/plan.c  
2008-04-18 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan.c  
2008-04-18 08:35:32 UTC (rev 6364)
@@ -34,13 +34,17 @@
 #define HASH_LEN (MD5_DIGEST_LENGTH / sizeof(unsigned int))
 #endif
 
+#include <sys/time.h>
+static double get_time(void);
+
 #if 0
 void draw_cspace(plan_t* plan, const char* fname);
 #endif
 
 // Create a planner
 plan_t *plan_alloc(double abs_min_radius, double des_min_radius,
-                   double max_radius, double dist_penalty)
+                   double max_radius, double dist_penalty,
+                   double hysteresis_factor)
 {
   plan_t *plan;
 
@@ -51,6 +55,7 @@
 
   plan->max_radius = max_radius;
   plan->dist_penalty = dist_penalty;
+  plan->hysteresis_factor = hysteresis_factor;
   
   plan->heap = heap_alloc(PLAN_DEFAULT_HEAP_SIZE, (heap_free_elt_fn_t)NULL);
   assert(plan->heap);
@@ -71,42 +76,40 @@
 plan_set_obstacles(plan_t* plan, double* obs, size_t num)
 {
   size_t i;
+  int j;
   int di,dj;
   float* p;
   plan_cell_t* cell, *ncell;
+  double t0,t1;
 
-  // Remove any previous obstacles
-  for(i=0;i<plan->obs_pts_num;i++)
+  t0 = get_time();
+
+  // Start with static obstacle data
+  cell = plan->cells;
+  for(j=0;j<plan->size_y*plan->size_x;j++,cell++)
   {
-    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;
+    cell->mark = 0;
   }
 
-  // Do we need more room?
-  if(num > plan->obs_pts_size)
+  // Expand around the dynamic obstacle pts
+  for(i=0;i<num;i++)
   {
-    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;
 
+    if(!PLAN_VALID(plan,gx,gy))
+      continue;
+
     cell = plan->cells + PLAN_INDEX(plan,gx,gy);
 
+    if(cell->mark)
+      continue;
+
+    cell->mark = 1;
     cell->occ_state_dyn = 1;
     cell->occ_dist_dyn = 0.0;
 
@@ -128,6 +131,9 @@
       }
     }
   }
+
+  t1 = get_time();
+  printf("plan_set_obstacles: %.6lf\n", t1-t0);
 }
 
 void
@@ -373,10 +379,9 @@
   }
 }
 
-#if 0
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
-        void
+void
 draw_cspace(plan_t* plan, const char* fname)
 {
   GdkPixbuf* pixbuf;
@@ -394,7 +399,8 @@
     for(i=0;i<plan->size_x;i++,p++)
     {
       paddr = p * 3;
-      if(plan->cells[PLAN_INDEX(plan,i,j)].occ_state == 1)
+      //if(plan->cells[PLAN_INDEX(plan,i,j)].occ_state == 1)
+      if(plan->cells[PLAN_INDEX(plan,i,j)].occ_dist < plan->abs_min_radius)
       {
         pixels[paddr] = 255;
         pixels[paddr+1] = 0;
@@ -533,7 +539,6 @@
   gdk_pixbuf_unref(pixbuf);
   free(pixels);
 }
-#endif
 
 // Construct the configuration space from the occupancy grid.
 // This treats both occupied and unknown cells as bad.
@@ -709,3 +714,11 @@
   MD5_Final((unsigned char*)digest,&c);
 }
 #endif // HAVE_OPENSSL_MD5_H && HAVE_LIBCRYPTO
+
+double 
+static 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/plan.h
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/plan.h  
2008-04-18 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan.h  
2008-04-18 08:35:32 UTC (rev 6364)
@@ -37,6 +37,8 @@
 
   // Mark used in dynamic programming
   char mark;
+  // Mark used in path hysterisis
+  char lpathmark;
 
   // The next cell in the plan
   struct _plan_cell_t *plan_next;
@@ -68,15 +70,13 @@
 
   // Penalty factor for cells inside the max radius
   double dist_penalty;
+  
+  // Cost multiplier for cells on the previous local path
+  double hysteresis_factor;
 
   // The grid data
   plan_cell_t *cells;
 
-  // 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;
@@ -100,8 +100,11 @@
 
 
 // Create a planner
-plan_t *plan_alloc(double abs_min_radius, double des_min_radius,
-                   double max_radius, double dist_penalty);
+plan_t *plan_alloc(double abs_min_radius, 
+                   double des_min_radius,
+                   double max_radius, 
+                   double dist_penalty, 
+                   double hysteresis_factor);
 
 void plan_compute_dist_kernel(plan_t* plan);
 
@@ -148,6 +151,8 @@
                        double lx, double ly, 
                        double maxdist, double distweight);
 
+void plan_set_obstacles(plan_t* plan, double* obs, size_t num);
+
 #if HAVE_OPENSSL_MD5_H && HAVE_LIBCRYPTO
 // Write the cspace occupancy distance values to a file, one per line.
 // Read them back in with plan_read_cspace().

Modified: 
code/player/branches/cmake/server/drivers/planner/wavefront/plan_control.c
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/plan_control.c  
2008-04-18 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan_control.c  
2008-04-18 08:35:32 UTC (rev 6364)
@@ -1,4 +1,5 @@
 #include <stdlib.h>
+#include <assert.h>
 
 #include "plan.h"
 
@@ -12,12 +13,21 @@
   int li, lj;
   double dist, d;
   double cost, bestcost;
+  char old_occ_state;
+  float old_occ_dist;
 
   li = PLAN_GXWX(plan, lx);
   lj = PLAN_GYWY(plan, ly);
 
   cell = plan->cells + PLAN_INDEX(plan,li,lj);
 
+  // Latch and clear the obstacle state for the cell I'm in
+  cell = plan->cells + PLAN_INDEX(plan, li, lj);
+  old_occ_state = cell->occ_state_dyn;
+  old_occ_dist = cell->occ_dist_dyn;
+  cell->occ_state_dyn = -1;
+  cell->occ_dist_dyn = plan->max_radius;
+
   // Step back from maxdist, looking for the best carrot
   bestcost = -1.0;
   for(dist = maxdist; dist >= plan->scale; dist -= plan->scale)
@@ -30,7 +40,11 @@
 
     // Check whether the straight-line path is clear
     if((cost = _plan_check_path(plan, cell, ncell)) < 0.0)
+    {
+      printf("no path from (%d,%d) to (%d,%d)\n",
+             cell->ci, cell->cj, ncell->ci, ncell->cj);
       continue;
+    }
 
     // Weight distance
     cost += distweight * (1.0/(dist*dist));
@@ -41,6 +55,11 @@
       *py = PLAN_WYGY(plan,ncell->cj);
     }
   }
+ 
+  // Restore the obstacle state for the cell I'm in
+  cell = plan->cells + PLAN_INDEX(plan, li, lj);
+  cell->occ_state_dyn = old_occ_state;
+  cell->occ_dist_dyn = old_occ_dist;
 
   return(bestcost);
 }

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 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/plan_plan.c     
2008-04-18 08:35:32 UTC (rev 6364)
@@ -80,14 +80,15 @@
   int xmin,ymin,xmax,ymax;
   plan_cell_t* cell;
   double t0,t1;
+  int i;
 
   t0 = get_time();
 
   // Set bounds as directed
   xmin = PLAN_GXWX(plan, lx - plan_halfwidth);
-  ymin = PLAN_GXWX(plan, ly - plan_halfwidth);
+  ymin = PLAN_GYWY(plan, ly - plan_halfwidth);
   xmax = PLAN_GXWX(plan, lx + plan_halfwidth);
-  ymax = PLAN_GXWX(plan, ly + plan_halfwidth);
+  ymax = PLAN_GYWY(plan, ly + plan_halfwidth);
   plan_set_bounds(plan, xmin, ymin, xmax, ymax);
 
   // Reset plan costs (within the local patch)
@@ -112,6 +113,11 @@
   li = PLAN_GXWX(plan, lx);
   lj = PLAN_GYWY(plan, ly);
 
+  // Reset path marks (TODO: find a smarter place to do this)
+  cell = plan->cells;
+  for(i=0;i<plan->size_x*plan->size_y;i++,cell++)
+    cell->lpathmark = 0;
+
   // Cache the path
   for(cell = plan->cells + PLAN_INDEX(plan,li,lj);
       cell;
@@ -125,6 +131,7 @@
       assert(plan->lpath);
     }
     plan->lpath[plan->lpath_count++] = cell;
+    cell->lpathmark = 1;
   }
 
   t1 = get_time();
@@ -142,6 +149,8 @@
   int gi, gj, li,lj;
   float cost;
   plan_cell_t *cell, *ncell;
+  char old_occ_state;
+  float old_occ_dist;
 
   // Reset the queue
   heap_reset(plan->heap);
@@ -153,7 +162,7 @@
   // 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))
@@ -168,6 +177,13 @@
     return(-1);
   }
 
+  // Latch and clear the obstacle state for the cell I'm in
+  cell = plan->cells + PLAN_INDEX(plan, li, lj);
+  old_occ_state = cell->occ_state_dyn;
+  old_occ_dist = cell->occ_dist_dyn;
+  cell->occ_state_dyn = -1;
+  cell->occ_dist_dyn = plan->max_radius;
+
   cell = plan->cells + PLAN_INDEX(plan, gi, gj);
   cell->plan_cost = 0;
   plan_push(plan, cell);
@@ -206,7 +222,11 @@
         if (ncell->occ_dist_dyn < plan->abs_min_radius)
           continue;
 
-        cost = cell->plan_cost + *p;
+        cost = cell->plan_cost;
+        if(ncell->lpathmark)
+          cost += (*p) * plan->hysteresis_factor;
+        else
+          cost += *p;
 
         if(ncell->occ_dist_dyn < plan->max_radius)
           cost += plan->dist_penalty * (plan->max_radius - 
ncell->occ_dist_dyn);
@@ -222,7 +242,11 @@
     }
   }
 
+  // Restore the obstacle state for the cell I'm in
   cell = plan->cells + PLAN_INDEX(plan, li, lj);
+  cell->occ_state_dyn = old_occ_state;
+  cell->occ_dist_dyn = old_occ_dist;
+
   if(!cell->plan_next)
   {
     puts("never found start");
@@ -253,6 +277,8 @@
   li = PLAN_GXWX(plan, lx);
   lj = PLAN_GYWY(plan, ly);
 
+  assert(PLAN_VALID_BOUNDS(plan,li,lj));
+
   // Find the closest place to jump on the global path
   squared_d_min = DBL_MAX;
   c_min = -1;

Modified: code/player/branches/cmake/server/drivers/planner/wavefront/test.c
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/test.c  
2008-04-18 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/test.c  
2008-04-18 08:35:32 UTC (rev 6364)
@@ -33,9 +33,9 @@
   int i, j;
 
   plan_t* plan;
-  double robot_radius=0.25;
-  double safety_dist=0.2;
-  double max_radius=1.0;
+  double robot_radius=0.16;
+  double safety_dist=0.05;
+  double max_radius=0.25;
   double dist_penalty=1.0;;
   double plan_halfwidth = 5.0;
 
@@ -76,9 +76,15 @@
     }
   }
   free(mapdata);
+
+  plan->scale = res;
+  plan->size_x = sx;
+  plan->size_y = sy;
+  plan->origin_x = 0.0;
+  plan->origin_y = 0.0;
   
   // Do initialization
-  plan_init(plan, res, sx, sy, 0.0, 0.0);
+  plan_init(plan);
 
   t_c0 = get_time();
   plan_compute_cspace(plan);

Modified: 
code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc
===================================================================
--- code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc    
2008-04-18 08:29:18 UTC (rev 6363)
+++ code/player/branches/cmake/server/drivers/planner/wavefront/wavefront.cc    
2008-04-18 08:35:32 UTC (rev 6364)
@@ -219,9 +219,14 @@
 #include <assert.h>
 #include <math.h>
 
+
 #include <libplayercore/playercore.h>
 #include "plan.h"
 
+#include <sys/time.h>
+static double get_time(void);
+extern "C" { void draw_cspace(plan_t* plan, const char* fname); }
+
 // TODO: monitor localize timestamps, and slow or stop robot accordingly
 
 // time to sleep between loops (us)
@@ -237,6 +242,8 @@
     player_devaddr_t position_id;
     player_devaddr_t localize_id;
     player_devaddr_t map_id;
+    player_devaddr_t laser_id;
+    player_devaddr_t graphics2d_id;
     double map_res;
     double robot_radius;
     double safety_dist;
@@ -253,6 +260,8 @@
     Device* position;
     Device* localize;
     Device* mapdevice;
+    Device* laser;
+    Device* graphics2d;
 
     // are we disabled?
     bool enable;
@@ -299,19 +308,35 @@
     int force_map_refresh;
     // Should we do velocity control, or position control?
     bool velocity_control;
+    // How many laser scans should we buffer?
+    int scans_size;
+    // How far out do we insert obstacles?
+    double scan_maxrange;
+    // The scan buffer
+    player_laser_data_scanpose_t* scans;
+    int scans_count;
+    int scans_idx;
+    double* scan_points;
+    int scan_points_size;
+    int scan_points_count;
 
     // methods for internal use
     int SetupLocalize();
+    int SetupLaser();
     int SetupPosition();
     int SetupMap();
+    int SetupGraphics2d();
     int GetMap(bool threaded);
     int GetMapInfo(bool threaded);
     int ShutdownPosition();
     int ShutdownLocalize();
+    int ShutdownLaser();
     int ShutdownMap();
+    int ShutdownGraphics2d();
     double angle_diff(double a, double b);
 
     void ProcessCommand(player_planner_cmd_t* cmd);
+    void ProcessLaserScan(player_laser_data_scanpose_t* data);
     void ProcessLocalizeData(player_position2d_data_t* data);
     void ProcessPositionData(player_position2d_data_t* data);
     void ProcessMapInfo(player_map_info_t* info);
@@ -378,6 +403,17 @@
     this->SetError(-1);
     return;
   }
+  
+  // Can use a laser device
+  memset(&this->laser_id,0,sizeof(player_devaddr_t));
+  cf->ReadDeviceAddr(&this->laser_id, section, "requires",
+                     PLAYER_LASER_CODE, -1, NULL);
+
+  // Can use a graphics2d device
+  memset(&this->graphics2d_id,0,sizeof(player_devaddr_t));
+  cf->ReadDeviceAddr(&this->graphics2d_id, section, "requires",
+                     PLAYER_GRAPHICS2D_CODE, -1, NULL);
+
   this->safety_dist = cf->ReadLength(section,"safety_dist", 0.25);
   this->max_radius = cf->ReadLength(section,"max_radius",1.0);
   this->dist_penalty = cf->ReadFloat(section,"dist_penalty",1.0);
@@ -391,6 +427,18 @@
           cf->ReadInt(section, "add_rotational_waypoints", 1);
   this->force_map_refresh = cf->ReadInt(section, "force_map_refresh", 0);
   this->velocity_control = cf->ReadInt(section, "velocity_control", 0);
+  if(this->laser_id.interf)
+  {
+    this->scans_size = cf->ReadInt(section, "laser_buffer_size", 10);
+    if(this->scans_size < 1)
+    {
+      PLAYER_WARN("must buffer at least one laser scan");
+      this->scans_size = 1;
+    }
+    this->scan_maxrange = cf->ReadLength(section, "laser_maxrange", 6.0);
+  }
+  else
+    this->scans_size = 0;
 }
 
 
@@ -425,7 +473,8 @@
   if(!(this->plan = plan_alloc(this->robot_radius+this->safety_dist,
                                this->robot_radius+this->safety_dist,
                                this->max_radius,
-                               this->dist_penalty)))
+                               this->dist_penalty,
+                               0.5)))
   {
     PLAYER_ERROR("failed to allocate plan");
     return(-1);
@@ -436,6 +485,28 @@
   if(SetupLocalize() < 0)
     return(-1);
 
+  if(this->laser_id.interf)
+  {
+    if(SetupLaser() < 0)
+      return(-1);
+
+    this->scans = 
+            (player_laser_data_scanpose_t*)malloc(this->scans_size *
+                                                  
sizeof(player_laser_data_scanpose_t));
+    assert(this->scans);
+    this->scans_idx = 0;
+    this->scans_count = 0;
+    this->scan_points = NULL;
+    this->scan_points_size = 0;
+    this->scan_points_count = 0;
+  }
+
+  if(this->graphics2d_id.interf)
+  {
+    if(SetupGraphics2d() < 0)
+      return(-1);
+  }
+
   // Start the driver thread.
   this->StartThread();
   return 0;
@@ -458,6 +529,10 @@
   ShutdownPosition();
   ShutdownLocalize();
   ShutdownMap();
+  if(this->laser_id.interf)
+    ShutdownLaser();
+  if(this->graphics2d_id.interf)
+    ShutdownGraphics2d();
 
   return 0;
 }
@@ -489,6 +564,120 @@
 #endif
 }
 
+void 
+Wavefront::ProcessLaserScan(player_laser_data_scanpose_t* data)
+{
+  double t0,t1;
+
+  t0 = get_time();
+
+  // free up the old scan, if we're replacing one
+  if(this->scans_idx < this->scans_count)
+    playerxdr_cleanup_message(this->scans+this->scans_idx,
+                              PLAYER_LASER_CODE, PLAYER_MSGTYPE_DATA,
+                              PLAYER_LASER_DATA_SCANPOSE);
+  // copy in the new scan
+  playerxdr_deepcopy_message(data, this->scans+this->scans_idx,
+                             PLAYER_LASER_CODE, PLAYER_MSGTYPE_DATA,
+                             PLAYER_LASER_DATA_SCANPOSE);
+  //memcpy(this->scans+this->scans_idx, data,
+         //sizeof(player_laser_data_scanpose_t));
+
+  // update counters
+  this->scans_count++;
+  this->scans_count = MIN(this->scans_count,this->scans_size);
+  this->scans_idx = (this->scans_idx + 1) % this->scans_size;
+
+  printf("%d scans\n", this->scans_count);
+
+  // run through the scans to see how much room we need to store all the
+  // hitpoints
+  int hitpt_cnt=0;
+  player_laser_data_scanpose_t* scan = this->scans;
+  for(int i=0;i<this->scans_count;i++,scan++)
+    hitpt_cnt += scan->scan.ranges_count*2;
+
+  // allocate more space as necessary
+  if(this->scan_points_size < hitpt_cnt)
+  {
+    this->scan_points_size = hitpt_cnt;
+    this->scan_points = (double*)realloc(this->scan_points,
+                                         
this->scan_points_size*sizeof(double));
+    assert(this->scan_points);
+  }
+
+  // project hit points from each scan
+  scan = this->scans;
+  double* pts = this->scan_points;
+  this->scan_points_count = 0;
+  for(int i=0;i<this->scans_count;i++,scan++)
+  {
+    float b=scan->scan.min_angle;
+    float* r=scan->scan.ranges;
+    for(unsigned int j=0;
+        j<scan->scan.ranges_count;
+        j++,r++,b+=scan->scan.resolution)
+    {
+      if(((*r) >= this->scan_maxrange) || ((*r) >= scan->scan.max_range))
+        continue;
+      //double rx, ry;
+      //rx = (*r)*cos(b);
+      //ry = (*r)*sin(b);
+
+      double cs,sn;
+      cs = cos(scan->pose.pa+b);
+      sn = sin(scan->pose.pa+b);
+
+      double lx,ly;
+      lx = scan->pose.px + (*r)*cs;
+      ly = scan->pose.py + (*r)*sn;
+
+      assert(this->scan_points_count*2 < this->scan_points_size);
+      *(pts++) = lx;
+      *(pts++) = ly;
+      this->scan_points_count++;
+    }
+  }
+
+  printf("setting %d hit points\n", this->scan_points_count);
+  plan_set_obstacles(plan, this->scan_points, this->scan_points_count);
+
+  t1 = get_time();
+  printf("ProcessLaserScan: %.6lf\n", t1-t0);
+
+#if 0
+  if(this->graphics2d_id.interf)
+  {
+    // Clear the canvas
+    this->graphics2d->PutMsg(this->InQueue,
+                             PLAYER_MSGTYPE_CMD,
+                             PLAYER_GRAPHICS2D_CMD_CLEAR,
+                             NULL,0,NULL);
+    
+    // Draw the points
+    player_graphics2d_cmd_points pts;
+    assert(pts.points = (player_point_2d_t*)malloc(sizeof(player_point_2d_t)*
+                                                   hitpt_cnt/2));
+    pts.points_count = hitpt_cnt/2;
+    pts.color.alpha = 0;
+    pts.color.red = 255;
+    pts.color.blue = 0;
+    pts.color.green = 0;
+    for(int i=0;i<hitpt_cnt/2;i++)
+    {
+      pts.points[i].px = this->scan_points[2*i];
+      pts.points[i].py = this->scan_points[2*i+1];
+    }
+
+    this->graphics2d->PutMsg(this->InQueue,
+                             PLAYER_MSGTYPE_CMD,
+                             PLAYER_GRAPHICS2D_CMD_POINTS,
+                             (void*)&pts,0,NULL);
+    free(pts.points);
+  }
+#endif
+}
+
 void
 Wavefront::ProcessLocalizeData(player_position2d_data_t* data)
 {
@@ -704,6 +893,13 @@
       this->PutPlannerData();
     }
 
+    if(!this->enable)
+    {
+      this->StopPosition();
+      usleep(CYCLE_TIME_US);
+      continue;
+    }
+
     // Is it time to replan?
     replan_timediff = t - last_replan_time;
     replan_dist = sqrt(((this->localize_x - last_replan_lx) *
@@ -766,12 +962,15 @@
         this->new_map = false;
       }
 #endif
+      double t0,t1;
 
+      t0 = get_time();
+
       // compute costs to the new goal.  Try local plan first
       if(new_goal ||
          (this->plan->path_count == 0) ||
          (plan_do_local(this->plan, this->localize_x, 
-                         this->localize_y, 5.0) < 0))
+                         this->localize_y, this->scan_maxrange) < 0))
       {
         if(!new_goal && (this->plan->path_count != 0))
            puts("Wavefront: local plan failed");
@@ -784,6 +983,35 @@
           this->new_goal = false;
       }
 
+      if(this->graphics2d_id.interf && this->plan->lpath_count)
+      {
+        this->graphics2d->PutMsg(this->InQueue,
+                                 PLAYER_MSGTYPE_CMD,
+                                 PLAYER_GRAPHICS2D_CMD_CLEAR,
+                                 NULL,0,NULL);
+
+        player_graphics2d_cmd_polyline_t line;
+        line.points_count = this->plan->lpath_count;
+        line.points = 
(player_point_2d_t*)malloc(sizeof(player_point_2d_t)*line.points_count);
+        line.color.alpha = 0;
+        line.color.red = 0;
+        line.color.green = 255;
+        line.color.blue = 0;
+        for(int i=0;i<this->plan->lpath_count;i++)
+        {
+          line.points[i].px = PLAN_WXGX(this->plan,this->plan->lpath[i]->ci);
+          line.points[i].py = PLAN_WYGY(this->plan,this->plan->lpath[i]->cj);
+        }
+        this->graphics2d->PutMsg(this->InQueue,
+                                 PLAYER_MSGTYPE_CMD,
+                                 PLAYER_GRAPHICS2D_CMD_POLYLINE,
+                                 (void*)&line,0,NULL);
+        free(line.points);
+      }
+
+      t1 = get_time();
+      printf("planning: %.6lf\n", t1-t0);
+
       if(!this->velocity_control)
       {
         // extract waypoints along the path to the goal from the current 
position
@@ -842,16 +1070,11 @@
       }
     }
 
-    if(!this->enable)
-    {
-      this->StopPosition();
-      usleep(CYCLE_TIME_US);
-      continue;
-    }
 
-
     if(this->velocity_control)
     {
+      double t0, t1;
+      t0 = get_time();
       if(this->plan->path_count && !this->atgoal)
       {
         // Check doneness
@@ -874,12 +1097,16 @@
           double maxd=2.0;
           double distweight=10.0;
 
+          printf("pose: (%.3lf,%.3lf,%.3lf)\n",
+                 this->localize_x, this->localize_y, RTOD(this->localize_a));
           if(plan_get_carrot(this->plan, &wx, &wy,
                              this->localize_x, this->localize_y,
                              maxd, distweight) < 0)
           {
             puts("Failed to find a carrot");
+            draw_cspace(this->plan, "debug.png");
             this->StopPosition();
+            exit(-1);
           }
           else
           {
@@ -942,6 +1169,9 @@
       }
       else
         this->StopPosition();
+
+      t1 = get_time();
+      printf("control: %.6lf\n", t1-t0);
     }
     else // !velocity_control
     {
@@ -1090,15 +1320,56 @@
 
   // take the bigger of the two dimensions, convert to meters, and halve
   // to get a radius
-  this->robot_radius = MAX(geom->size.sl, geom->size.sw);
+  //this->robot_radius = MAX(geom->size.sl, geom->size.sw);
+  this->robot_radius = geom->size.sw;
   this->robot_radius /= 2.0;
 
+  printf("robot radius: %.3lf\n", this->robot_radius);
+
   delete msg;
 
   return 0;
 }
 
 
////////////////////////////////////////////////////////////////////////////////
+// Set up the underlying laser device.
+int
+Wavefront::SetupLaser()
+{
+  // Subscribe to the laser device.
+  if(!(this->laser = deviceTable->GetDevice(this->laser_id)))
+  {
+    PLAYER_ERROR("unable to locate suitable laser device");
+    return(-1);
+  }
+  if(this->laser->Subscribe(this->InQueue) != 0)
+  {
+    PLAYER_ERROR("unable to subscribe to laser device");
+    return(-1);
+  }
+
+  return(0);
+}
+
+int
+Wavefront::SetupGraphics2d()
+{
+  // Subscribe to the graphics2d device.
+  if(!(this->graphics2d = deviceTable->GetDevice(this->graphics2d_id)))
+  {
+    PLAYER_ERROR("unable to locate suitable graphics2d device");
+    return(-1);
+  }
+  if(this->graphics2d->Subscribe(this->InQueue) != 0)
+  {
+    PLAYER_ERROR("unable to subscribe to graphics2d device");
+    return(-1);
+  }
+
+  return(0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Set up the underlying localize device.
 int
 Wavefront::SetupLocalize()
@@ -1194,6 +1465,7 @@
 
   plan_init(this->plan);
   plan_compute_cspace(this->plan);
+  draw_cspace(this->plan,"cspace.png");
 
   return(0);
 }
@@ -1283,6 +1555,18 @@
 }
 
 int
+Wavefront::ShutdownLaser()
+{
+  return(this->laser->Unsubscribe(this->InQueue));
+}
+
+int
+Wavefront::ShutdownGraphics2d()
+{
+  return(this->graphics2d->Unsubscribe(this->InQueue));
+}
+
+int
 Wavefront::ShutdownMap()
 {
   return(this->mapdevice->Unsubscribe(this->InQueue));
@@ -1330,7 +1614,8 @@
       this->plan = plan_alloc(this->robot_radius+this->safety_dist,
                               this->robot_radius+this->safety_dist,
                               this->max_radius,
-                              this->dist_penalty);
+                              this->dist_penalty,
+                              0.5);
       assert(this->plan);
 
       // Fill in the map structure
@@ -1412,6 +1697,15 @@
     this->new_map_available = true;
     return(0);
   }
+  // Is it a pose-stamped laser scan?
+  else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
+                                PLAYER_LASER_DATA_SCANPOSE,
+                                this->laser_id))
+  {
+    player_laser_data_scanpose_t* pdata = (player_laser_data_scanpose_t*)data;
+    this->ProcessLaserScan(pdata);
+    return(0);
+  }
   else
     return(-1);
 }
@@ -1432,3 +1726,11 @@
   else
     return(d2);
 }
+
+double 
+static get_time(void)
+{
+  struct timeval curr;
+  gettimeofday(&curr,NULL);
+  return(curr.tv_sec + curr.tv_usec / 1e6);
+}


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