Revision: 6873
          http://playerstage.svn.sourceforge.net/playerstage/?rev=6873&view=rev
Author:   natepak
Date:     2008-07-15 19:48:14 -0700 (Tue, 15 Jul 2008)

Log Message:
-----------
Updates to the 2d map loader

Modified Paths:
--------------
    code/gazebo/trunk/server/physics/Body.cc
    code/gazebo/trunk/server/physics/BoxGeom.cc
    code/gazebo/trunk/server/physics/BoxGeom.hh
    code/gazebo/trunk/server/physics/Geom.cc
    code/gazebo/trunk/server/physics/OccupancyGridGeom.cc
    code/gazebo/trunk/server/physics/OccupancyGridGeom.hh
    code/gazebo/trunk/server/physics/SConscript

Added Paths:
-----------
    code/gazebo/trunk/server/physics/QuadTreeGeom.cc
    code/gazebo/trunk/server/physics/QuadTreeGeom.hh
    code/gazebo/trunk/server/physics/SpaceTree.cc
    code/gazebo/trunk/server/physics/SpaceTree.hh

Modified: code/gazebo/trunk/server/physics/Body.cc
===================================================================
--- code/gazebo/trunk/server/physics/Body.cc    2008-07-16 01:26:03 UTC (rev 
6872)
+++ code/gazebo/trunk/server/physics/Body.cc    2008-07-16 02:48:14 UTC (rev 
6873)
@@ -29,6 +29,7 @@
 #include "GazeboMessage.hh"
 #include "HeightmapGeom.hh"
 #include "OccupancyGridGeom.hh"
+#include "QuadTreeGeom.hh"
 #include "OgreVisual.hh"
 #include "Global.hh"
 #include "Vector2.hh"
@@ -417,6 +418,10 @@
   {
     geom = new OccupancyGridGeom(this);
   }
+  else if (node->GetName() == "quadtree")
+  {
+    geom = new QuadTreeGeom(this);
+  }
   else
   {
     gzthrow("Unknown Geometry 
Type["+node->GetString("name",std::string(),0)+"]");

Modified: code/gazebo/trunk/server/physics/BoxGeom.cc
===================================================================
--- code/gazebo/trunk/server/physics/BoxGeom.cc 2008-07-16 01:26:03 UTC (rev 
6872)
+++ code/gazebo/trunk/server/physics/BoxGeom.cc 2008-07-16 02:48:14 UTC (rev 
6873)
@@ -64,3 +64,14 @@
     this->visualNode->SetMaterial("Gazebo/GreenEmissive");
     */
 }
+
+//////////////////////////////////////////////////////////////////////////////
+// Set the size of the box
+void BoxGeom::SetSize( Vector3 size )
+{
+  // Initialize box mass matrix
+  dMassSetBoxTotal(&this->mass, this->dblMass, size.x, size.y, size.z);
+
+  // Create a box geometry with box mass matrix
+  this->SetGeom(dCreateBox( 0, size.x, size.y, size.z), true );
+}

Modified: code/gazebo/trunk/server/physics/BoxGeom.hh
===================================================================
--- code/gazebo/trunk/server/physics/BoxGeom.hh 2008-07-16 01:26:03 UTC (rev 
6872)
+++ code/gazebo/trunk/server/physics/BoxGeom.hh 2008-07-16 02:48:14 UTC (rev 
6873)
@@ -79,6 +79,10 @@
 
     /// \brief Load the box
     protected: void LoadChild(XMLConfigNode *node);
+
+    /// \brief Set the size of the box
+    public: void SetSize( Vector3 size );
+
   };
 
   /// \}

Modified: code/gazebo/trunk/server/physics/Geom.cc
===================================================================
--- code/gazebo/trunk/server/physics/Geom.cc    2008-07-16 01:26:03 UTC (rev 
6872)
+++ code/gazebo/trunk/server/physics/Geom.cc    2008-07-16 02:48:14 UTC (rev 
6873)
@@ -130,7 +130,7 @@
 
 
   // Create the bounding box
-  if (dGeomGetClass(this->geomId) != dPlaneClass)
+  if (this->geomId && dGeomGetClass(this->geomId) != dPlaneClass)
   {
     dReal aabb[6];
     dGeomGetAABB(this->geomId, aabb);
@@ -142,7 +142,8 @@
     this->bbVisual->AttachBoundingBox(min,max);
   }
 
-  if (dGeomGetClass(this->geomId) != dPlaneClass && 
dGeomGetClass(this->geomId) != dHeightfieldClass)
+  if (this->geomId && dGeomGetClass(this->geomId) != dPlaneClass && 
+      dGeomGetClass(this->geomId) != dHeightfieldClass)
   {
     World::Instance()->RegisterGeom(this);
     this->ShowPhysics(false);

Modified: code/gazebo/trunk/server/physics/OccupancyGridGeom.cc
===================================================================
--- code/gazebo/trunk/server/physics/OccupancyGridGeom.cc       2008-07-16 
01:26:03 UTC (rev 6872)
+++ code/gazebo/trunk/server/physics/OccupancyGridGeom.cc       2008-07-16 
02:48:14 UTC (rev 6873)
@@ -36,6 +36,7 @@
 #include "OgreAdaptor.hh"
 #include "Global.hh"
 #include "Body.hh"
+#include "SpaceTree.hh"
 #include "OccupancyGridGeom.hh"
 
 using namespace gazebo;
@@ -45,6 +46,7 @@
 OccupancyGridGeom::OccupancyGridGeom(Body *body)
     : Geom(body)
 {
+  this->tree = NULL;
 }
 
 
@@ -52,6 +54,8 @@
 // Destructor
 OccupancyGridGeom::~OccupancyGridGeom()
 {
+  if (this->tree)
+    delete this->tree;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -100,16 +104,16 @@
 
   // Create the 2d lines of the map
   this->GenerateLines();
-  std::cout << "OccupancyGrid: found [%d] walls" << this->wallCount;
-      
+  printf("OccupancyGrid: found [%d] walls\n",this->wallCount);
+     
+
   // Create the quad tree
-  /*this->tree = new SpaceTree();
+  this->tree = new SpaceTree();
   tree->BuildTree( this->walls, this->wallCount, 
                    this->mapWidth, this->mapHeight );
 
   // Create the extruded geometry
   this->GenerateGeometry();
-  */
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -120,7 +124,6 @@
   unsigned char v;
   MapPoint **map;
   MapPoint *pt;
-  const unsigned char *imageData;
   Ogre::ColourValue pixColor;
 
   this->mapWidth = this->mapImage.getWidth();
@@ -148,54 +151,53 @@
       if (this->negative)
         v = 255 - v;
  
-      std::cout << "XY[" << x << " " << y << "] Color[" << pixColor[0] << " " 
<< pixColor[1] << " " << pixColor[2] << "]";
-      printf("V[%d]\n",v);
+  //    std::cout << "XY[" << x << " " << y << "] Color[" << pixColor[0] << " 
" << pixColor[1] << " " << pixColor[2] << "]"; printf("V[%d]\n",v);
 
       // If the image data is beyond the threshold, then create a new map
       // point
-  /*    if (v >= this->threshold)
+      if (v >= this->threshold)
       {
         // Create the new point
-        map[r*this->mapWidth+c] = new MapPoint( c, r );
+        map[y*this->mapWidth+x] = new MapPoint( x, y );
 
         // Point to the North
-        if (r>0 && map[(r-1)*this->mapWidth+c] != NULL)
+        if (y>0 && map[(y-1)*this->mapWidth+x] != NULL)
         {
-          map[r*this->mapWidth+c]->arcs[0] = map[(r-1)*this->mapWidth+c];
-          map[r*this->mapWidth+c]->arcCount++;
+          map[y*this->mapWidth+x]->arcs[0] = map[(y-1)*this->mapWidth+x];
+          map[y*this->mapWidth+x]->arcCount++;
 
-          map[(r-1)*this->mapWidth+c]->arcs[4] = map[r*this->mapWidth+c];
-          map[(r-1)*this->mapWidth+c]->arcCount++;
+          map[(y-1)*this->mapWidth+x]->arcs[4] = map[y*this->mapWidth+x];
+          map[(y-1)*this->mapWidth+x]->arcCount++;
         }
 
         // Point the NorthWest
-        if (c>0 && r>0 && map[(r-1)*this->mapWidth+c-1] != NULL)
+        if (x>0 && y>0 && map[(y-1)*this->mapWidth+x-1] != NULL)
         {
-          map[r*this->mapWidth+c]->arcs[7] = map[(r-1)*this->mapWidth+c-1];
-          map[r*this->mapWidth+c]->arcCount++;
+          map[y*this->mapWidth+x]->arcs[7] = map[(y-1)*this->mapWidth+x-1];
+          map[y*this->mapWidth+x]->arcCount++;
 
-          map[(r-1)*this->mapWidth+c-1]->arcs[3] = map[r*this->mapWidth+c];
-          map[(r-1)*this->mapWidth+c-1]->arcCount++;
+          map[(y-1)*this->mapWidth+x-1]->arcs[3] = map[y*this->mapWidth+x];
+          map[(y-1)*this->mapWidth+x-1]->arcCount++;
         }
  
         // Point to the West
-        if (c>0 && map[r*this->mapWidth+c-1] != NULL)
+        if (x>0 && map[y*this->mapWidth+x-1] != NULL)
         {
-          map[r*this->mapWidth+c]->arcs[6] = map[r*this->mapWidth+c-1]; 
-          map[r*this->mapWidth+c]->arcCount++;
+          map[y*this->mapWidth+x]->arcs[6] = map[y*this->mapWidth+x-1]; 
+          map[y*this->mapWidth+x]->arcCount++;
 
-          map[r*this->mapWidth+c-1]->arcs[2] = map[r*this->mapWidth+c];
-          map[r*this->mapWidth+c-1]->arcCount++;
+          map[y*this->mapWidth+x-1]->arcs[2] = map[y*this->mapWidth+x];
+          map[y*this->mapWidth+x-1]->arcCount++;
         }
 
         // Point to the NorthEast
-        if (c+1<this->mapWidth && r>0 && map[(r-1)*this->mapWidth+c+1] != NULL)
+        if (x+1<this->mapWidth && y>0 && map[(y-1)*this->mapWidth+x+1] != NULL)
         {
-          map[r*this->mapWidth+c]->arcs[1] = map[(r-1)*this->mapWidth+c+1]; 
-          map[r*this->mapWidth+c]->arcCount++;
+          map[y*this->mapWidth+x]->arcs[1] = map[(y-1)*this->mapWidth+x+1]; 
+          map[y*this->mapWidth+x]->arcCount++;
 
-          map[(r-1)*this->mapWidth+c+1]->arcs[5] = map[r*this->mapWidth+c];
-          map[(r-1)*this->mapWidth+c+1]->arcCount++;
+          map[(y-1)*this->mapWidth+x+1]->arcs[5] = map[y*this->mapWidth+x];
+          map[(y-1)*this->mapWidth+x+1]->arcCount++;
         }
        
         // Point to the East
@@ -211,20 +213,16 @@
       }
       else
       {
-        map[r*this->mapWidth+c] = NULL;
+        map[y*this->mapWidth+x] = NULL;
       }
-
-      */
     }
   }
-  /*
-  int i=0;
 
-  for (r=0; r<this->mapHeight; r++)
+  for (y=0; y<this->mapHeight; y++)
   {
-    for (c=0; c<this->mapWidth; c++)
+    for (x=0; x<this->mapWidth; x++)
     {
-      pt = map[r*this->mapWidth+c];
+      pt = map[y*this->mapWidth+x];
 
       // If the map point is valid
       if (pt != NULL && pt->arcCount < 8)
@@ -244,19 +242,15 @@
   // Free the map data
   delete [] map;
 
-  // Free the image
-  delete dataSet;
-
   // If the user has specified an error bound, then reduce the graph. 
   // This will only reduce curved surefaces
-  if (this->errBound > 0)
+  /*if (this->errBound > 0)
   {
     ReduceLines();
-  }
-  */
+  }*/
 
 }
-/*
+
 //////////////////////////////////////////////////////////////////////////////
 // Create a single line starting from point pt in direction dir
 void OccupancyGridGeom::GenerateLine( MapPoint* pt, int dir )
@@ -348,22 +342,23 @@
 
 }
 
+
 //////////////////////////////////////////////////////////////////////////////
 // Create the geometry from a list of 2d lines
 void OccupancyGridGeom::GenerateGeometry()
 {
   // We are a space of fixed objects, and shouldnt collide with ourself
-  dGeomSetCategoryBits( (dGeomID) this->modelSpaceId, GZ_FIXED_COLLIDE );
-  dGeomSetCollideBits( (dGeomID) this->modelSpaceId, ~GZ_FIXED_COLLIDE );
+  //dGeomSetCategoryBits( (dGeomID) this->modelSpaceId, GZ_FIXED_COLLIDE );
+  //dGeomSetCollideBits( (dGeomID) this->modelSpaceId, ~GZ_FIXED_COLLIDE );
   
-  this->tree->GetRoot()->GenerateGeoms( this->modelSpaceId, this->body,
+  this->tree->GetRoot()->GenerateGeoms( this->spaceId, this->body,
       this->wallWidth, this->wallHeight, this->pos,
-      this->scale, this->color, this->shadeModel, this->polygonMode);
+      this->scale, this->color);
 
-  this->AddSpaceGeoms(this->tree->GetRoot());
+  //this->AddSpaceGeoms(this->tree->GetRoot());
 }
 
-void OccupancyGridGeom::AddSpaceGeoms( SpaceNode *node)
+/*void OccupancyGridGeom::AddSpaceGeoms( SpaceNode *node)
 {
   //int i = 0;
   if (node==NULL)
@@ -379,7 +374,7 @@
   //{
   //  this->AddSpaceGeoms(node->children[i]);
   //}
-}
+}*/
 
 
 //////////////////////////////////////////////////////////////////////////////
@@ -515,5 +510,3 @@
     this->mid.y = this->start.y - fabs( this->start.y - this->end.y ) / 2.0; 
   }
 }
-
-*/

Modified: code/gazebo/trunk/server/physics/OccupancyGridGeom.hh
===================================================================
--- code/gazebo/trunk/server/physics/OccupancyGridGeom.hh       2008-07-16 
01:26:03 UTC (rev 6872)
+++ code/gazebo/trunk/server/physics/OccupancyGridGeom.hh       2008-07-16 
02:48:14 UTC (rev 6873)
@@ -63,6 +63,7 @@
   /// \{
 
 
+  class SpaceTree;
   class Line;
   class MapPoint;
 
@@ -84,9 +85,27 @@
     /// \brief Get the 2d lines from an image file
     private: void GenerateLines();
 
+    /// \brief Create a single line starting from point pt in direction dir
+    private: void GenerateLine( MapPoint* pt, int dir );
+
+    /// \brief Reduce the number of lines in the map
+    private: void ReduceLines();
+
+    /// \brief Calculates the shortest distance from a point to a line
+    private: float PointLineDist( const MapPoint &p1, const MapPoint &p2, 
+                                  const MapPoint &p );
+    /// \brief Adds a wall
+    private: void AddWall( Line *line );
+
+    /// \brief Deletes a wall segment
+    private: void EraseWall( int index );
+
+    /// \brief Create the geometry from a list of 2d lines
+    private: void GenerateGeometry();
+
     private: Vector3 mapSize;
 
-    //private: Line **walls;
+    private: Line **walls;
     private: int wallCount;
     private: int wallMaxCount;
 
@@ -112,7 +131,7 @@
     private: float wallHeight;
 
     // The color of the walls
-    //private: Vector3 color;
+    private: Vector3 color;
 
     // The amount of acceptable error in the model
     private: float errBound;
@@ -122,8 +141,10 @@
     private: unsigned int mapHeight;
 
     private: Ogre::Image mapImage;
+
+    private: SpaceTree *tree;
   };
-/*
+
   class MapPoint
   {
     public: MapPoint() : x(0), y(0), arcCount(0) 
@@ -174,7 +195,6 @@
     private: float length;
     private: float angle;
   };
-  */
 
 
   /// \}

Added: code/gazebo/trunk/server/physics/QuadTreeGeom.cc
===================================================================
--- code/gazebo/trunk/server/physics/QuadTreeGeom.cc                            
(rev 0)
+++ code/gazebo/trunk/server/physics/QuadTreeGeom.cc    2008-07-16 02:48:14 UTC 
(rev 6873)
@@ -0,0 +1,302 @@
+/*
+ *  Gazebo - Outdoor Multi-Robot Simulator
+ *  Copyright (C) 2003
+ *     Nate Koenig & Andrew Howard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+/* Desc: QuadTree geometry
+ * Author: Nate Koenig
+ * Date: 14 July 2008
+ * CVS: $Id:$
+ */
+
+#include <ode/ode.h>
+#include <Ogre.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+
+#include "GazeboError.hh"
+#include "OgreAdaptor.hh"
+#include "Simulator.hh"
+#include "OgreAdaptor.hh"
+#include "Global.hh"
+#include "Body.hh"
+#include "SpaceTree.hh"
+#include "QuadTreeGeom.hh"
+
+using namespace gazebo;
+
+//////////////////////////////////////////////////////////////////////////////
+// Constructor
+QuadTreeGeom::QuadTreeGeom(Body *body)
+    : Geom(body)
+{
+  this->root = new QuadNode(NULL);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Destructor
+QuadTreeGeom::~QuadTreeGeom()
+{
+  if (this->root)
+    delete this->root;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+/// Update function.
+void QuadTreeGeom::UpdateChild()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Load the heightmap
+void QuadTreeGeom::LoadChild(XMLConfigNode *node)
+{
+  OgreAdaptor *ogreAdaptor;
+
+  ogreAdaptor = Simulator::Instance()->GetRenderEngine();
+
+  std::string imageFilename = node->GetString("image","",1);
+  this->mapSize = node->GetVector3("size",Vector3(10,10,10));
+
+  this->negative = node->GetBool("negative", 0);
+  this->threshold = node->GetDouble( "threshold", 200.0);
+
+  this->wallHeight = node->GetDouble( "height", 1.0, 0 );
+
+  //this->color = node->GetColor( "color", GzColor(1.0, 1.0, 1.0) );
+
+  // Make sure they are ok
+  if (this->scale <= 0) this->scale = 0.1;
+  if (this->threshold <=0) this->threshold = 200;
+  if (this->wallHeight <= 0) this->wallHeight = 1.0;
+  if (this->errBound <= 0) this->errBound = 0.0;
+
+  // Load the image 
+  this->mapImage.load(imageFilename,
+                Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+  this->root->x = 0;
+  this->root->y = 0;
+  this->root->width = this->mapImage.getWidth();
+  this->root->height = this->mapImage.getHeight();
+
+  this->BuildTree(this->root);
+  this->root->Print(" ");
+
+  printf("\n\n");
+
+  this->merged = true;
+  while (this->merged)
+  {
+    printf("---------------------------\n");
+    this->merged =false;
+    this->ReduceTree(this->root);
+  }
+
+  this->root->Print(" ");
+
+}
+
+void QuadTreeGeom::ReduceTree(QuadNode *node)
+{
+  std::vector<QuadNode*>::iterator iter;
+
+  if (!node->valid)
+    return;
+
+  if (!node->leaf)
+  {
+    for (iter = node->children.begin(); iter != node->children.end(); iter++)
+    {
+      if ((*iter)->valid)
+        this->ReduceTree((*iter));
+    }
+  }
+  else
+  {
+    this->Merge(node, this->root);
+
+/*    for (unsigned int i=0; i<4; i++)
+    {
+      QuadNode *sibling = node->parent->children[i];
+      this->Merge(node, sibling);
+
+      if ( sibling->x == node->x+node->width && 
+           sibling->y == node->y && 
+           sibling->occupied == node->occupied)
+      {
+        node->width += sibling->width;
+        sibling->valid = false;
+        node->valid = true;
+
+        printf("Combine XY[%d %d][%d] XY[%d %d][%d]\n",node->x, node->y, 
node->occupied, sibling->x, sibling->y, sibling->occupied);
+      }
+    }*/
+  }
+}
+
+void QuadTreeGeom::Merge(QuadNode *nodeA, QuadNode *nodeB)
+{
+  std::vector<QuadNode*>::iterator iter;
+
+  if (!nodeB)
+    return;
+
+  if (nodeB->leaf)
+  {
+    if ( nodeB->x == nodeA->x + nodeA->width && 
+         nodeB->y == nodeA->y && 
+         nodeB->occupied == nodeA->occupied )
+    {
+      nodeA->width += nodeB->width;
+      nodeB->valid = false;
+      nodeA->valid = true;
+
+      this->merged = true;
+
+      printf("Combine XY[%d %d][%d] XY[%d %d][%d]\n",nodeA->x, nodeA->y, 
nodeA->occupied, nodeB->x, nodeB->y, nodeB->occupied);
+    }
+
+    /*if (nodeB->x == nodeA->x && nodeB->width == nodeA->width &&
+        nodeB->y == nodeA->y + nodeA->height &&
+        nodeB->occupied == nodeA->occupied)
+    {
+      nodeA->height += nodeA->height;
+      nodeB->valid = false;
+      nodeA->valid = true;
+
+      this->merged = true;
+
+      printf("Combine XY[%d %d][%d] XY[%d %d][%d]\n",nodeA->x, nodeA->y, 
nodeA->occupied, nodeB->x, nodeB->y, nodeB->occupied);
+
+    }*/
+  }
+  else
+  {
+
+    for (iter = nodeB->children.begin(); iter != nodeB->children.end(); iter++)
+    {
+      if ((*iter)->valid)
+        this->Merge(nodeA, (*iter));
+    }
+  }
+}
+
+
+void QuadTreeGeom::BuildTree(QuadNode *node)
+{
+  QuadNode *newNode = NULL;
+  unsigned int freePixels, occPixels;
+
+  this->GetPixelCount(node->x, node->y, node->width, node->height, 
+                      freePixels, occPixels);
+
+  if (freePixels > 0 && occPixels > 0)
+  {
+    float newX, newY;
+    float newW, newH;
+   
+    newY = node->y;
+    newW = node->width / 2.0;
+    newH = node->height / 2.0;
+
+    // Create the children for the node
+    for (int i=0; i<2; i++)
+    {
+      newX = node->x;
+
+      for (int j=0; j<2; j++)
+      {
+        newNode = new QuadNode(node);
+        newNode->x = (unsigned int)newX;
+        newNode->y = (unsigned int)newY;
+
+        if (j == 0)
+          newNode->width = (unsigned int)floor(newW);
+        else
+          newNode->width = (unsigned int)ceil(newW);
+
+        if (i==0)
+          newNode->height = (unsigned int)floor(newH);
+        else
+          newNode->height = (unsigned int)ceil(newH);
+
+        node->children.push_back(newNode);
+
+        this->BuildTree(newNode);
+
+        newX += newNode->width;
+
+        if (newNode->width == 0 || newNode->height ==0)
+          newNode->valid = false;
+      }
+
+      if (i==0)
+        newY += floor(newH);
+      else
+        newY += ceil(newH);
+    }
+
+    node->occupied = true;
+    node->leaf = false;
+  }
+  else if (occPixels == 0)
+  {
+    node->occupied = false;
+    node->leaf = true;
+    node->parent->leaves++;
+  }
+  else
+  {
+    node->occupied = true;
+    node->leaf = true;
+    node->parent->leaves++;
+  }
+
+}
+
+void QuadTreeGeom::GetPixelCount(unsigned int xStart, unsigned int yStart, 
+                                 unsigned int width, unsigned int height, 
+                                 unsigned int &freePixels, 
+                                 unsigned int &occPixels )
+{
+  Ogre::ColourValue pixColor;
+  unsigned char v;
+  unsigned int x,y;
+
+  freePixels = occPixels = 0;
+
+  for (y = yStart; y < yStart + height; y++)
+  {
+    for (x = xStart; x < xStart + width; x++)
+    {
+      pixColor = this->mapImage.getColourAt(x, y, 0);
+      v = (unsigned char)(255 * ((pixColor[0] + pixColor[1] + pixColor[2]) / 
3.0));
+      if (this->negative)
+        v = 255 - v;
+
+      if (v < this->threshold)
+        freePixels++;
+      else
+        occPixels++;
+    }
+  }
+}
+

Added: code/gazebo/trunk/server/physics/QuadTreeGeom.hh
===================================================================
--- code/gazebo/trunk/server/physics/QuadTreeGeom.hh                            
(rev 0)
+++ code/gazebo/trunk/server/physics/QuadTreeGeom.hh    2008-07-16 02:48:14 UTC 
(rev 6873)
@@ -0,0 +1,178 @@
+/*
+ *  Gazebo - Outdoor Multi-Robot Simulator
+ *  Copyright (C) 2003  
+ *     Nate Koenig & Andrew Howard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+/* Desc: Occupancy grid geom
+ * Author: Nate Koenig
+ * Date: 14 Jly 2008
+ * CVS: $Id:$
+ */
+
+#ifndef QUADTREEGEOM_HH
+#define QUADTREEGEOM_HH
+
+#include <Ogre.h>
+#include <vector>
+
+#include "Vector2.hh"
+#include "Geom.hh"
+
+namespace gazebo
+{
+  /// \addtogroup gazebo_physics_geom
+  /// \{
+  /** \defgroup gazebo_occupancy_geom Occupancy grid geom
+      \brief Occupancy grid geom
+
+    \par Attributes
+    The following attributes are supported.
+
+    - image (string)
+      - Binary image that defines an occupancy grid
+      - Default: (empty)
+
+    - size (float tuple)
+      - Size of the height map
+      - Default: 0 0 0
+
+    \par Example
+    \verbatim
+      <geom:occupancygrid name="occ_geom">
+        <image>map.png</image>
+        <size>100 100 1.0</size>
+      </geom:occupancygrid>
+    \endverbatim
+    */
+  /// \}
+  /// \addtogroup gazebo_occupancy_geom 
+  /// \{
+
+
+  class SpaceTree;
+  class QuadNode;
+
+  /// \brief Occupancy grid geom
+  class QuadTreeGeom : public Geom
+  {
+    /// \brief Constructor
+    public: QuadTreeGeom(Body *body);
+
+    /// \brief Destructor
+    public: virtual ~QuadTreeGeom();
+
+    /// \brief Update function 
+    public: void UpdateChild();
+
+    /// \brief Load the heightmap
+    protected: virtual void LoadChild(XMLConfigNode *node);
+
+    private: void BuildTree(QuadNode *node);
+
+    private: void GetPixelCount(unsigned int xStart, unsigned int yStart, 
+                                unsigned int width, unsigned int height, 
+                                unsigned int &freePixels, 
+                                unsigned int &occPixels  );
+
+    private: void ReduceTree(QuadNode *node);
+
+    private: void Merge(QuadNode *nodeA, QuadNode *nodeB);
+
+    private: Vector3 mapSize;
+
+    // The scale factor to apply to the geoms
+    private: float scale;
+
+    // Alignment
+    private: std::string halign, valign;
+
+    // The position of the map
+    private: Vector3 pos;
+
+    // Negative image?
+    private: int negative;
+
+    // Image color threshold used for extrusion
+    private: float threshold;
+
+    // The color of the walls
+    private: Vector3 color;
+
+    // The amount of acceptable error in the model
+    private: float errBound;
+
+    private: float wallHeight;
+
+    // The map dimensions
+    private: unsigned int mapWidth;
+    private: unsigned int mapHeight;
+
+    private: Ogre::Image mapImage;
+
+    private: QuadNode *root;
+    private: bool merged;
+  };
+
+
+  class QuadNode
+  {
+    public: QuadNode( QuadNode *_parent ) 
+            {
+              parent = _parent;
+              occupied = false;
+              leaf = true;
+              leaves = 0;
+              valid = true;
+            }
+
+    public: ~QuadNode() 
+            { 
+              std::vector<QuadNode*>::iterator iter;
+              for (iter = children.begin(); iter != children.end(); iter++) 
+                  delete (*iter); 
+            }
+
+    public: void Print(std::string space)
+            {
+              std::vector<QuadNode*>::iterator iter;
+
+              printf("%sXY[%d %d] WH[%d %d] O[%d] L[%d] 
V[%d]\n",space.c_str(),x,y,width, height, occupied, leaf, valid);
+              space += "  ";
+              for (iter = children.begin(); iter != children.end(); iter++) 
+                if ((*iter)->valid)
+                  (*iter)->Print(space);
+            }
+
+    public: unsigned int x, y;
+    public: unsigned int width, height;
+
+    public: std::vector<Geom*> geoms;
+
+    public: QuadNode *parent;
+    public: std::vector<QuadNode*> children;
+    public: bool occupied;
+    public: bool leaf;
+    public: int leaves;
+
+    public: bool valid;
+  };
+
+  /// \}
+}
+
+#endif

Modified: code/gazebo/trunk/server/physics/SConscript
===================================================================
--- code/gazebo/trunk/server/physics/SConscript 2008-07-16 01:26:03 UTC (rev 
6872)
+++ code/gazebo/trunk/server/physics/SConscript 2008-07-16 02:48:14 UTC (rev 
6873)
@@ -24,6 +24,8 @@
            'TrimeshGeom.cc',
            'HeightmapGeom.cc',
            'OccupancyGridGeom.cc',
+           'SpaceTree.cc',
+           'QuadTreeGeom.cc'
            ]
 
 headers.append( 
@@ -43,8 +45,9 @@
            'server/physics/SliderJoint.hh',
            'server/physics/SphereGeom.hh',
            'server/physics/TrimeshGeom.hh',
-           'server/physics/UniversalJoint.hh'
-           'server/physics/OccupancyGridGeom.hh'
+           'server/physics/UniversalJoint.hh',
+           'server/physics/OccupancyGridGeom.hh',
+           'server/physics/SpaceTree.hh'
            ] )
 
 staticObjs.append( env.StaticObject(sources) )

Added: code/gazebo/trunk/server/physics/SpaceTree.cc
===================================================================
--- code/gazebo/trunk/server/physics/SpaceTree.cc                               
(rev 0)
+++ code/gazebo/trunk/server/physics/SpaceTree.cc       2008-07-16 02:48:14 UTC 
(rev 6873)
@@ -0,0 +1,316 @@
+/*
+ *  Gazebo - Outdoor Multi-Robot Simulator
+ *  Copyright (C) 2003  
+ *     Nate Koenig & Andrew Howard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+/* Desc: A QuadTree to logically segment the geometries in a map
+ * Author: Nate Koenig
+ * Date: 28 July 2003
+ * CVS: $Id: SpaceTree.cc,v 1.14 2004/08/16 18:34:24 natepak Exp $
+ */
+
+#include <GL/gl.h>
+#include <assert.h>
+
+#include "Body.hh"
+#include "SpaceTree.hh"
+#include "BoxGeom.hh"
+
+using namespace gazebo;
+
+//////////////////////////////////////////////////////////////////////////////
+// Constructor
+SpaceNode::SpaceNode( SpaceNode *parent, float x, float y, float hl, float hh )
+  : parent( parent ), isLeaf( false ), cx( x ), cy( y ), 
+    halfWidth( hl ), halfHeight( hh ), 
+    walls(NULL), wallCount(0), wallMaxCount(0),
+    geoms(NULL), geomCount(0), geomMaxCount(0)
+{
+  for (int i=0; i<4; i++)
+    this->children[i] = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Destructor
+SpaceNode::~SpaceNode()
+{
+  int i=0;
+
+  this->parent = NULL;
+
+  for (int i=0; i<this->geomCount; i++)
+  {
+    delete this->geoms[i];
+  }
+
+  free(geoms);
+
+  // Delete all children
+  if (this->isLeaf)
+  {
+    dSpaceDestroy( this->spaceId );
+  }
+  else
+  {
+    // Delete all children
+    for (i=0; i<4; i++)
+    {
+      delete this->children[i];
+      this->children[i] = NULL;
+    }
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Add a wall to this space
+void SpaceNode::AddWall( Line *line )
+{
+  if (this->wallCount >= this->wallMaxCount)
+  {
+    this->wallMaxCount += 10;
+    this->walls = (Line**) realloc(this->walls, this->wallMaxCount *
+        sizeof(this->walls[0]));
+
+    assert(this->walls);
+  }
+
+  this->walls[this->wallCount++] = line;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Add a geom to this space
+void SpaceNode::AddGeom( Geom *geom )
+{
+  if (this->geomCount >= this->geomMaxCount)
+  {
+    this->geomMaxCount += 10;
+    this->geoms = (Geom**) realloc(this->geoms, this->geomMaxCount *
+        sizeof(this->geoms[0]));
+
+    assert(this->geoms);
+  }
+
+  this->geoms[this->geomCount++] = geom;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Create the ODE geometries
+void SpaceNode::GenerateGeoms( dSpaceID parentSpace, Body *body, 
+                               float wallWidth, float wallHeight, 
+                               Vector3 &pos, float scale, 
+                               Vector3 color)
+{
+
+  // Generate recursive spaces (maximizes collision detection performance)
+  this->spaceId = dSimpleSpaceCreate( parentSpace );
+
+  // We are a space of fixed objects, and shouldnt collide with ourself
+  dGeomSetCategoryBits( (dGeomID) this->spaceId, GZ_FIXED_COLLIDE );
+  dGeomSetCollideBits( (dGeomID) this->spaceId, ~GZ_FIXED_COLLIDE );
+
+  if (this->isLeaf)
+  {
+
+    for (int i=0; i<this->wallCount; i++)
+    {
+      std::ostringstream stream;
+
+      // Align the walls with the ground properly
+      float z = wallHeight/2.0;
+
+      // Create the box geometry
+      BoxGeom* newBox = new BoxGeom( body );
+
+      XMLConfig *boxConfig = new XMLConfig();
+      Quatern rot;
+      Vector3 rpy;
+      rot.SetFromAxis( 0, 0, 1, this->walls[i]->Angle() );
+      rpy = rot.GetAsEuler();
+
+      stream << "<gazebo:world 
xmlns:gazebo=\"http://playerstage.sourceforge.net/gazebo/xmlschema/#gz\"; 
xmlns:geom=\"http://playerstage.sourceforge.net/gazebo/xmlschema/#geom\";>"; 
+
+      stream << "<geom:box name='occ_geom'>";
+      stream << "  <mass>0.0</mass>";
+      stream << "  <xyz>" << this->walls[i]->Mid().x * scale + pos.x << " " <<
+                   this->walls[i]->Mid().y * scale + pos.y << " " << z + pos.z 
<< "</xyz>";
+      stream << "  <rpy>" << RTOD(rpy.x) << " " << RTOD(rpy.y) << " " << 
RTOD(rpy.z) << "</rpy>";
+      stream << "  <size>" << this->walls[i]->Length() * scale + wallWidth * 
scale << " " << wallWidth * scale << " " << wallHeight << "</size>";
+      stream << "  <visual>";
+      stream << "    <mesh>unit_box</mesh>";
+      stream << "    <material>Gazebo/Rocky</material>";
+      stream << "    <size>" << this->walls[i]->Length() * scale + wallWidth * 
scale << " " << wallWidth * scale << " " << wallHeight << "</size>";
+      stream << "  </visual>";
+      stream << "</geom:box>";
+      stream << "</gazebo:world>";
+
+      boxConfig->LoadString( stream.str() );
+
+      newBox->Load( boxConfig->GetRootNode()->GetChild() );
+      delete boxConfig;
+    }
+  }
+  else if (children[0])
+  {
+    for (int i=0; i<4; i++)
+      this->children[i]->GenerateGeoms( this->spaceId, body, wallWidth, 
+          wallHeight, pos, scale,color);
+  }
+
+  /* TESTING
+  // Display the actual bounding box of the space
+  if (dSpaceGetNumGeoms(this->spaceId) > 0)
+  {
+    dReal box[6];
+    dGeomGetAABB((dGeomID) this->spaceId, box);
+
+    BoxGeom *bBox = new BoxGeom( 0,
+                                 box[1] - box[0],
+                                 box[3] - box[2],
+                                 box[5] - box[4]);
+    bBox->SetPosition((box[1] + box[0]) / 2,
+                      (box[3] + box[2]) / 2,
+                      (box[5] + box[4]) / 2);
+
+    bBox->SetColor( 1, 0, 0);
+
+    bBox->SetCategoryBits( 0 );
+    bBox->SetCollideBits( 0 );
+
+    this->geoms.PushBack( bBox );
+  }
+  */
+
+  // Destroy the newly created space if it has nothing in it.  This is
+  // particularly important for getting the recursive spaces right.
+  if (dSpaceGetNumGeoms(this->spaceId) == 0)
+  {
+    dSpaceDestroy(this->spaceId);
+    this->spaceId = 0;
+  }
+
+  return;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Constructor
+SpaceTree::SpaceTree()
+  : root( NULL ), linesPerNode( 10 )
+{
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Destructor
+SpaceTree::~SpaceTree()
+{
+  // Delete the entire tree
+  if (this->root)
+    delete this->root;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Return the root node
+SpaceNode *SpaceTree::GetRoot() const
+{
+  return this->root;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Build the tree from a list of line segements. 
+void SpaceTree::BuildTree( Line **lines, unsigned int lineCount,
+                                float width, float height )
+{
+
+  if (lineCount <= this->linesPerNode)
+  {
+    // Create the root node, and make it a leaf
+    this->root = new SpaceNode( NULL, width/2.0, height/2.0, 
+                                width/2.0, height/2.0);
+    this->root->isLeaf = true;
+
+    // Add all the lines to the root node
+    for (unsigned int i=0; i<lineCount; i++)
+      this->root->AddWall( lines[i] );
+  }
+  else
+  {
+
+    // Recursibely create the tree
+    this->root = this->Construct( NULL, width/2.0, height/2.0, width/2.0, 
+                                  height/2.0, lines, lineCount );
+  }
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Called from BuildTree to recursively build the tree
+SpaceNode *SpaceTree::Construct( SpaceNode *parent, float cx, float cy, 
+                                 float hw, float hh,  
+                                 Line** lines, unsigned int lineCount )
+{
+
+  SpaceNode *node = new SpaceNode( parent, cx, cy, hw, hh );
+
+  // If the count is within range, then create a leaf node
+  if (lineCount < this->linesPerNode)
+  {
+    node->isLeaf = true;
+
+    for (unsigned int i=0; i<lineCount; i++)
+      node->AddWall( lines[i] );
+
+  } 
+
+  // Otherwise create a new node and its children 
+  else if (lineCount > 0) 
+  {
+    delete node->walls;
+    unsigned int i=0;
+
+    // Grab the lines contained within this node
+    while (i != lineCount)
+    {
+      if (lines[i]->Mid().x < cx+hw && lines[i]->Mid().x >= cx-hw &&
+          lines[i]->Mid().y < cy+hh && lines[i]->Mid().y >= cy-hh )
+      {
+        node->AddWall( lines[i] );
+        //iter = lines.Erase( iter );
+      }
+      i++;
+    }
+
+    // Create the node's children
+    node->children[0] = this->Construct( node, cx+hw/2.0, cy+hh/2.0, hw/2.0, 
+                                         hh/2.0, node->walls, node->wallCount 
);
+    node->children[1] = this->Construct( node, cx-hw/2.0, cy+hh/2.0, hw/2.0, 
+                                         hh/2.0, node->walls, node->wallCount 
);
+    node->children[2] = this->Construct( node, cx-hw/2.0, cy-hh/2.0, hw/2.0, 
+                                         hh/2.0, node->walls, node->wallCount);
+    node->children[3] = this->Construct( node, cx+hw/2.0, cy-hh/2.0, hw/2.0, 
+                                         hh/2.0, node->walls, node->wallCount 
);
+  }
+
+  return node;
+}
+

Added: code/gazebo/trunk/server/physics/SpaceTree.hh
===================================================================
--- code/gazebo/trunk/server/physics/SpaceTree.hh                               
(rev 0)
+++ code/gazebo/trunk/server/physics/SpaceTree.hh       2008-07-16 02:48:14 UTC 
(rev 6873)
@@ -0,0 +1,120 @@
+/*
+ *  Gazebo - Outdoor Multi-Robot Simulator
+ *  Copyright (C) 2003  
+ *     Nate Koenig & Andrew Howard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+/* Desc: A QuadTree to logically segment the geometries in a map
+ * Author: Nate Koenig
+ * Date: 28 July 2003
+ * CVS: $Id: SpaceTree.hh,v 1.11 2004/10/10 17:57:29 inspectorg Exp $
+ */
+
+#ifndef SPACETREE_HH
+#define SPACETREE_HH
+
+#include "OccupancyGridGeom.hh"
+#include "Global.hh"
+
+namespace gazebo
+{
+  
+  // Forward declarations
+  class Body;
+  
+  class SpaceNode
+  {
+    // Constructor
+    public: SpaceNode( SpaceNode *parent, float x, float y, float hw, float hh 
);
+  
+    // Destructor
+    public: virtual ~SpaceNode();
+  
+    // Add a wall to the space
+    public: void AddWall( Line *line );
+  
+    // Add a geom to the space
+    public: void AddGeom( Geom *geom );
+  
+    // Create the ODE geometries
+    public: void GenerateGeoms(dSpaceID spaceId, Body *body, float wallWidth, 
+                float wallHeight, Vector3 &pos, float scale, 
+                Vector3 color);
+
+     // The parent of this node
+    public: SpaceNode *parent;
+ 
+    // Is this node a leaf??
+    public: bool isLeaf;
+  
+    // Each node has 4 children since this is a quad tree
+    public: SpaceNode *children[4];
+  
+    // The center location of this node
+    public: float cx, cy;
+  
+    // The half length of the rectangle (in x direction)
+    public: float halfWidth;
+  
+    // The half height of the rectangle (in y direction)
+    public: float halfHeight;
+  
+    // The lines representing walls contained in this space
+    public: Line** walls;
+    public: int wallCount;
+    public: int wallMaxCount;
+  
+    public: Geom** geoms;
+    public: int geomCount;
+    public: int geomMaxCount;
+  
+    // The spaceId for this node
+    private: dSpaceID spaceId;
+  };
+  
+  
+  class SpaceTree
+  {
+    // Constructor
+    public: SpaceTree();
+  
+    // Destructor
+    public: virtual ~SpaceTree();
+  
+     // Return the root node of the tree
+    public: SpaceNode *GetRoot() const;
+  
+    // Build the tree from a list of line segments
+    public: void BuildTree(  Line** lines, unsigned int numLines, 
+                                  float width, float height );
+  
+    // Called from BuildTree to recursively build the tree
+    private: SpaceNode *Construct( SpaceNode *parent, float cx, float cy, 
+                                   float hw, float hh, 
+                                  Line** lines, unsigned int lineCount );
+  
+    // The root node
+    private: SpaceNode *root;
+  
+    // Then maxmimum number of lines per node
+    private: unsigned int linesPerNode;
+  
+  };
+  
+}
+
+#endif


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 Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Playerstage-commit mailing list
Playerstage-commit@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to