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
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit