rayproximity.cc

来自「机器人人3D仿真工具,可以加入到Simbad仿真环境下应用。」· CC 代码 · 共 280 行

CC
280
字号
/* *  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: Ray proximity sensor * Author: Carle Cote (Laborius - Universite de Sherbrooke - Sherbrooke, Quebec, Canada) * Date: 23 february 2004 * CVS: $Id: RayProximity.cc,v 1.15 2005/11/22 16:44:51 natepak Exp $ * * Modification description : * * Author: Carle Cote  *           (Laborius - Universite de Sherbrooke - Sherbrooke, Quebec, Canada) * Date: 26 may 2004  * Desc: Fix model with refactored core *          - Change collision detection mechanism *          - Change rays to have their own spaceID  */#include <assert.h>#include <float.h>#include "RayGeom.hh"#include "World.hh"#include "WorldFile.hh"#include "RayProximity.hh"#include "Vector.hh"#include "Error.hh"//////////////////////////////////////////////////////////////////////////////// ConstructorRayProximity::RayProximity( World *world, Body *body, int rayCount)    : Sensor( world ){  int i;    this->world = world;  this->body = body;    // Create a space to contain the ray space  this->superSpaceId = dSimpleSpaceCreate( 0 );      // Create a space to contain all the rays  this->raySpaceId = dSimpleSpaceCreate( this->superSpaceId );    // Set collision bits  dGeomSetCategoryBits((dGeomID) this->raySpaceId, GZ_LASER_COLLIDE);  dGeomSetCollideBits((dGeomID) this->raySpaceId, ~GZ_LASER_COLLIDE);  // Create and array of ray geoms  this->rayCount = rayCount;  this->rays = new RayGeom*[this->rayCount];  for (i = 0; i < this->rayCount; i++)    this->rays[i] = new RayGeom(this->body, this->raySpaceId);  return;}//////////////////////////////////////////////////////////////////////////////// DestructorRayProximity::~RayProximity(){}//////////////////////////////////////////////////////////////////////////////// Set ray endpointsvoid RayProximity::SetRay(int index, GzVector a, GzVector b){  RayGeom *ray;  assert(index >= 0 && index < this->rayCount);  ray = this->rays[index];    ray->SetColor( GzColor(0, 0, 1) );  ray->SetCategoryBits( GZ_LASER_COLLIDE );  ray->SetCollideBits( ~GZ_LASER_COLLIDE );  ray->SetLength(GzVectorMag(GzVectorSub(b, a)));  ray->pos_a = a;  ray->pos_b = b;  return;}//////////////////////////////////////////////////////////////////////////////// Return a pointer to the ray geomvoid RayProximity::GetRay(int index, GzVector *pos, GzVector *dir){  RayGeom *ray;  assert(index >= 0 && index < this->rayCount);  ray = this->rays[index];  ray->Get(pos, dir);}//////////////////////////////////////////////////////////////////////////////// Get detected range for a raydouble RayProximity::GetRange(int index){  RayGeom *ray;  assert(index >= 0 && index < this->rayCount);  ray = this->rays[index];  return ray->contactDepth;}//////////////////////////////////////////////////////////////////////////////// Get detected retro (intensity) value for a ray.double RayProximity::GetRetro(int index){  RayGeom *ray;  assert(index >= 0 && index < this->rayCount);  ray = this->rays[index];  return ray->contactRetro;}//////////////////////////////////////////////////////////////////////////////// Get detected fiducial value for a ray.int RayProximity::GetFiducial(int index){  RayGeom *ray;  assert(index >= 0 && index < this->rayCount);  ray = this->rays[index];  return ray->contactFiducial;}//////////////////////////////////////////////////////////////////////////////// Update the sensor informationvoid RayProximity::Update(){  int i;  GzPose pose;  RayGeom *ray;  GzVector a, b;  // Get the pose of the sensor body (global cs)  pose = this->body->GetPose();    // Reset the ray lengths and mark the geoms as dirty (so they get  // redrawn)  for (i = 0; i < this->rayCount; i++)  {    ray = this->rays[i];    ray->dirty = true;    ray->contactDepth = DBL_MAX;    ray->contactRetro = 0.0;    ray->contactFiducial = -1;    // Update the ray endpoints (global cs)    a = GzCoordPositionAdd(ray->pos_a, pose.pos, pose.rot);    b = GzCoordPositionAdd(ray->pos_b, pose.pos, pose.rot);        ray->Set(a, GzVectorUnit(GzVectorSub(b, a)));  }  // Do collision detection  dSpaceCollide2( ( dGeomID ) ( this->superSpaceId ),                  ( dGeomID ) ( this->world->GetSpaceId() ),                  this, &UpdateCallback );    return;}/////////////////////////////////////////////////////////////////////////////// Callback for ray intersection testvoid RayProximity::UpdateCallback( void *data, dGeomID o1, dGeomID o2 ){  int n;  dContactGeom contact;  dxGeom *geom1, *geom2;  RayGeom *rayGeom;  Geom *hitGeom;  RayProximity *self;  self = (RayProximity*) data;   // Check space  if ( dGeomIsSpace( o1 ) || dGeomIsSpace( o2 ) )  {    if (dGeomGetSpace(o1) == self->superSpaceId || dGeomGetSpace(o2) == self->superSpaceId)    {      dSpaceCollide2( o1, o2, self, &UpdateCallback );    }    if (dGeomGetSpace(o1) == self->raySpaceId || dGeomGetSpace(o2) == self->raySpaceId)    {      dSpaceCollide2( o1, o2, self, &UpdateCallback );    }  }  else  {    geom1 = NULL;    geom2 = NULL;        // Get pointers to the underlying geoms    if (dGeomGetClass(o1) == dGeomTransformClass)      geom1 = (dxGeom*) dGeomGetData(dGeomTransformGetGeom(o1));    else      geom1 = (dxGeom*) dGeomGetData(o1);        if (dGeomGetClass(o2) == dGeomTransformClass)      geom2 = (dxGeom*) dGeomGetData(dGeomTransformGetGeom(o2));    else      geom2 = (dxGeom*) dGeomGetData(o2);    assert(geom1 && geom2);    rayGeom = NULL;    hitGeom = NULL;    // Figure out which one is a ray; note that this assumes    // that the ODE dRayClass is used *soley* by the RayGeom.        if (dGeomGetClass(o1) == dRayClass)    {      rayGeom = (RayGeom*) geom1;      hitGeom = (Geom*) geom2;      dGeomRaySetParams(o1, 0, 0);      dGeomRaySetClosestHit(o1, 1);    }        if (dGeomGetClass(o2) == dRayClass)    {      assert(rayGeom == NULL);      rayGeom = (RayGeom*) geom2;      hitGeom = (Geom* )geom1;      dGeomRaySetParams(o2, 0, 0);      dGeomRaySetClosestHit(o2, 1);    }            // Check for ray/geom intersections    if ( rayGeom && hitGeom )    {      n = dCollide(o1, o2, 1, &contact, sizeof(contact));             if ( n > 0 )      {               if (contact.depth < rayGeom->contactDepth)        {          GzVector start;          GzVector dir;          rayGeom->Get(&start, &dir);          rayGeom->contactDepth = contact.depth;          rayGeom->contactRetro = hitGeom->GetRetro();          rayGeom->contactFiducial = hitGeom->GetFiducial();        }      }    }  }  return;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?