-
Valenza Florian authored
[CMake][Python] Exposed GeometryModel and GeometryData in python. Little reworked of the headers_variables in the cmakelists
Valenza Florian authored[CMake][Python] Exposed GeometryModel and GeometryData in python. Little reworked of the headers_variables in the cmakelists
geometry.hpp 12.04 KiB
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_geom_hpp__
#define __se3_geom_hpp__
#include "pinocchio/spatial/fwd.hpp"
#include "pinocchio/spatial/se3.hpp"
#include "pinocchio/spatial/force.hpp"
#include "pinocchio/spatial/motion.hpp"
#include "pinocchio/spatial/inertia.hpp"
#include "pinocchio/spatial/fcl-pinocchio-conversions.hpp"
#include "pinocchio/multibody/model.hpp"
#include "pinocchio/multibody/joint/joint-variant.hpp"
#include <iostream>
#include <hpp/fcl/collision_object.h>
#include <hpp/fcl/collision.h>
#include <hpp/fcl/distance.h>
#include <map>
#include <list>
#include <utility>
namespace se3
{
class IsSameCollisionPair
{
typedef Model::Index Index;
typedef std::pair < Index, Index > CollisionPair_t;
public:
IsSameCollisionPair( CollisionPair_t pair): _pair(pair) {}
bool operator()(CollisionPair_t pair) const
{
return (pair == _pair);
}
private:
CollisionPair_t _pair;
};
// Result of distance computation between two CollisionObject.
struct DistanceResult
{
typedef Model::Index Index;
DistanceResult(fcl::DistanceResult dist_fcl, Index o1, Index o2)
: fcl_distance_result(dist_fcl), object1(o1), object2(o2)
{}
// Get distance between objects
double distance () const { return fcl_distance_result.min_distance; }
// Get closest point on inner object in global frame,
Eigen::Vector3d closestPointInner () const { return toVector3d(fcl_distance_result.nearest_points [0]); }
// Get closest point on outer object in global frame,
Eigen::Vector3d closestPointOuter () const { return toVector3d(fcl_distance_result.nearest_points [1]); }
bool operator == (const DistanceResult & other) const
{
return (distance() == other.distance()
&& closestPointInner() == other.closestPointInner()
&& closestPointOuter() == other.closestPointOuter()
&& object1 == other.object1
&& object2 == other.object2);
}
fcl::DistanceResult fcl_distance_result;
std::size_t object1;
std::size_t object2;
}; // struct DistanceResult
class GeometryModel
{
public:
typedef Model::Index Index;
Index ngeom;
std::vector<fcl::CollisionObject> collision_objects;
std::vector<std::string> geom_names;
std::vector<Index> geom_parents; // Joint parent of body <i>, denoted <li> (li==parents[i])
std::vector<SE3> geometryPlacement; // Position of geometry object in parent joint's frame
std::map < Index, std::list<Index> > innerObjects; // Associate a list of CollisionObjects to a given joint Id
std::map < Index, std::list<Index> > outerObjects; // Associate a list of CollisionObjects to a given joint Id
GeometryModel()
: ngeom(0)
, collision_objects()
, geom_names(0)
, geom_parents(0)
, geometryPlacement(0)
, innerObjects()
, outerObjects()
{
}
~GeometryModel() {};
Index addGeomObject( Index parent,const fcl::CollisionObject & co, const SE3 & placement, const std::string & geoName = "");
Index getGeomId( const std::string & name ) const;
bool existGeomName( const std::string & name ) const;
const std::string& getGeomName( Index index ) const;
void addInnerObject(Index joint, Index inner_object);
void addOutterObject(Index joint, Index outer_object);
friend std::ostream& operator<<(std::ostream& os, const GeometryModel& model_geom);
private:
};
class GeometryData
{
public:
typedef Model::Index Index;
typedef std::pair < Index, Index > CollisionPair_t;
Data& data_ref;
GeometryModel& model_geom;
std::vector<se3::SE3> oMg;
std::vector<fcl::Transform3f> oMg_fcl;
std::vector < CollisionPair_t > collision_pairs;
std::size_t nCollisionPairs;
std::vector < DistanceResult > distances;
GeometryData(Data& data, GeometryModel& model_geom)
: data_ref(data)
, model_geom(model_geom)
, oMg(model_geom.ngeom)
, oMg_fcl(model_geom.ngeom)
, collision_pairs()
, nCollisionPairs(0)
, distances()
{
initializeListOfCollisionPairs();
distances.resize(nCollisionPairs, DistanceResult( fcl::DistanceResult(), 0, 0) );
}
~GeometryData() {};
void addCollisionPair (Index co1, Index co2);
void addCollisionPair (const CollisionPair_t& pair);
void removeCollisionPair (Index co1, Index co2);
void removeCollisionPair (const CollisionPair_t& pair);
bool isCollisionPair (Index co1, Index co2) const ;
bool isCollisionPair (const CollisionPair_t& pair) const;
void fillAllPairsAsCollisions();
void desactivateCollisionPairs();
void initializeListOfCollisionPairs();
bool collide(Index co1, Index co2) const;
bool isColliding() const;
fcl::DistanceResult computeDistance(Index co1, Index co2) const;
void resetDistances();
void computeDistances ();
std::vector < DistanceResult > distanceResults(); //TODO : to keep or not depending of public or not for distances
void displayCollisionPairs() const
{
for (std::vector<CollisionPair_t>::const_iterator it = collision_pairs.begin(); it != collision_pairs.end(); ++it)
{
std::cout << it-> first << "\t" << it->second << std::endl;
}
}
friend std::ostream& operator<<(std::ostream& os, const GeometryData& data_geom);
private:
};
inline GeometryModel::Index GeometryModel::addGeomObject( Index parent,const fcl::CollisionObject & co, const SE3 & placement, const std::string & geoName )
{
Index idx = (Index) (ngeom ++);
collision_objects .push_back(co);
geom_parents .push_back(parent);
geometryPlacement .push_back(placement);
geom_names .push_back( (geoName!="")?geoName:random(8));
return idx;
}
inline GeometryModel::Index GeometryModel::getGeomId( const std::string & name ) const
{
std::vector<std::string>::iterator::difference_type
res = std::find(geom_names.begin(),geom_names.end(),name) - geom_names.begin();
assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
assert( (res>=0)&&(res<(long)collision_objects.size())&&"The joint name you asked do not exist" );
return Index(res);
}
inline bool GeometryModel::existGeomName( const std::string & name ) const
{
return (geom_names.end() != std::find(geom_names.begin(),geom_names.end(),name));
}
inline const std::string& GeometryModel::getGeomName( Index index ) const
{
assert( index < (Index)collision_objects.size() );
return geom_names[index];
}
inline void GeometryModel::addInnerObject(Index joint, Index inner_object)
{
innerObjects[joint].push_back(inner_object);
}
inline void GeometryModel::addOutterObject(Index joint, Index outer_object)
{
outerObjects[joint].push_back(outer_object);
}
inline std::ostream& operator<<(std::ostream& os, const GeometryModel& model_geom)
{
os << "Nb collision objects = " << model_geom.ngeom << std::endl;
for(GeometryModel::Index i=0;i<(GeometryModel::Index)(model_geom.ngeom);++i)
{
os << "Object n " << i << " : " << model_geom.geom_names[i] << ": attached to joint = " << model_geom.geom_parents[i]
<< "\nwith offset \n" << model_geom.geometryPlacement[i] <<std::endl;
}
return os;
}
inline std::ostream& operator<<(std::ostream& os, const GeometryData& data_geom)
{
for(GeometryData::Index i=0;i<(GeometryData::Index)(data_geom.model_geom.ngeom);++i)
{
os << "collision object oMi " << data_geom.oMg[i] << std::endl;
}
return os;
}
inline void GeometryData::addCollisionPair (Index co1, Index co2)
{
assert ( co1 < co2);
assert ( co2 < model_geom.ngeom);
CollisionPair_t pair(co1, co2);
addCollisionPair(pair);
}
inline void GeometryData::addCollisionPair (const CollisionPair_t& pair)
{
assert(pair.first < pair.second);
assert(pair.second < model_geom.ngeom);
collision_pairs.push_back(pair);
nCollisionPairs++;
}
inline void GeometryData::removeCollisionPair (Index co1, Index co2)
{
assert(co1 < co2);
assert(co2 < model_geom.ngeom);
assert(isCollisionPair(co1,co2));
removeCollisionPair (CollisionPair_t(co1,co2));
}
inline void GeometryData::removeCollisionPair (const CollisionPair_t& pair)
{
assert(pair.first < pair.second);
assert(pair.second < model_geom.ngeom);
assert(isCollisionPair(pair));
collision_pairs.erase(std::remove(collision_pairs.begin(), collision_pairs.end(), pair), collision_pairs.end());
nCollisionPairs--;
}
inline bool GeometryData::isCollisionPair (Index co1, Index co2) const
{
return isCollisionPair(CollisionPair_t(co1,co2));
}
inline bool GeometryData::isCollisionPair (const CollisionPair_t& pair) const
{
return (std::find_if ( collision_pairs.begin(), collision_pairs.end(),
IsSameCollisionPair(pair)) != collision_pairs.end());
}
inline void GeometryData::fillAllPairsAsCollisions()
{
for (Index i = 0; i < model_geom.ngeom; ++i)
{
for (Index j = i+1; j < model_geom.ngeom; ++j)
{
addCollisionPair(i,j);
}
}
}
// TODO : give a srdf file as argument, read it, and remove corresponding
// pairs from list collision_pairs
inline void GeometryData::desactivateCollisionPairs()
{
}
inline void GeometryData::initializeListOfCollisionPairs()
{
fillAllPairsAsCollisions();
desactivateCollisionPairs();
assert(nCollisionPairs == collision_pairs.size());
}
inline bool GeometryData::collide(Index co1, Index co2) const
{
fcl::CollisionRequest collisionRequest (1, false, false, 1, false, true, fcl::GST_INDEP);
fcl::CollisionResult collisionResult;
if (fcl::collide (model_geom.collision_objects[co1].collisionGeometry().get(), oMg_fcl[co1],
model_geom.collision_objects[co2].collisionGeometry().get(), oMg_fcl[co2],
collisionRequest, collisionResult) != 0)
{
std::cout << "Collision between " << model_geom.getGeomName(co1) << " and " << model_geom.getGeomName(co2) << std::endl;;
return true;
}
return false;
}
inline bool GeometryData::isColliding() const
{
for (std::vector<CollisionPair_t>::const_iterator it = collision_pairs.begin(); it != collision_pairs.end(); ++it)
{
if (collide(it->first, it->second))
{
return true;
}
}
return false;
}
inline fcl::DistanceResult GeometryData::computeDistance(Index co1, Index co2) const
{
fcl::DistanceRequest distanceRequest (true, 0, 0, fcl::GST_INDEP);
fcl::DistanceResult result;
fcl::distance ( model_geom.collision_objects[co1].collisionGeometry().get(), oMg_fcl[co1],
model_geom.collision_objects[co2].collisionGeometry().get(), oMg_fcl[co2],
distanceRequest, result);
return result;
}
inline void GeometryData::resetDistances()
{
std::fill(distances.begin(), distances.end(), DistanceResult( fcl::DistanceResult(), 0, 0) );
}
inline void GeometryData::computeDistances ()
{
std::size_t cpt = 0;
for (std::vector<CollisionPair_t>::iterator it = collision_pairs.begin(); it != collision_pairs.end(); ++it)
{
distances[cpt] = DistanceResult(computeDistance(it->first, it->second), it->first, it->second);
cpt++;
}
}
} // namespace se3
#endif // ifndef __se3_geom_hpp__