Exemple #1
0
    /// Finds contacts between the ball and a plane
    virtual void find_contacts_ball_parabloid(CollisionGeometryPtr ball_cg, CollisionGeometryPtr parabloid_cg, std::vector<UnilateralConstraint>& contacts)
    {
      const unsigned X = 0, Y = 1, Z = 2;

      // get the pose for the parabloid 
      shared_ptr<const Pose3d> Pparabloid = parabloid_cg->get_pose(); 

      // get the pose for the ball 
      shared_ptr<const Pose3d> Pball = ball_cg->get_pose();

      // get the pose of the center-of-mass of the ball
      Transform3d pTb = Pose3d::calc_relative_pose(Pball, Pparabloid);

      // compute the height of the ball above the parabloid; note: this assumes
      // that the parabloid is relatively flat
      double dist = -sqr(pTb.x[X])/(A*A) + sqr(pTb.x[Y])/(B*B) + (pTb.x[Z] - R); 

      // compute the closest point - we'll go half way between the closest
      // point on the ball and the closest point on the surface 
      double z = sqr(pTb.x[X])/sqr(A) + sqr(pTb.x[Y])/sqr(B);
      Point3d closest_parabloid(pTb.x[X], pTb.x[Y], z, Pparabloid);
      Point3d closest_ball(0.0, 0.0, -R, Pball);
      Point3d point = (Pose3d::transform_point(GLOBAL, closest_ball) +
                       Pose3d::transform_point(GLOBAL, closest_parabloid))*0.5; 

      // compute the normal to the surface
      Vector3d normal(2.0*-pTb.x[X]/(A*A), 2.0*-pTb.x[Y]/(B*B), 1.0, Pparabloid); 
      normal.normalize();
      Vector3d normal_global = Pose3d::transform_vector(GLOBAL, normal);

      contacts.clear();
      contacts.push_back(
        CollisionDetection::create_contact(ball_cg,parabloid_cg,point, normal_global,dist)
              );
    }
Exemple #2
0
    /// Calculates signed distance between a ball and a plane
    double calc_signed_dist_ball_parabloid(CollisionGeometryPtr ball_cg, CollisionGeometryPtr parabloid_cg,Vector3d& pball,Vector3d& pparabloid)
    {
      const unsigned X = 0, Y = 1, Z = 2;

      // setup the minimum dist
      double min_dist = std::numeric_limits<double>::max();

      // get the pose for the parabloid 
      shared_ptr<const Pose3d> Pparabloid = parabloid_cg->get_pose(); 

      // get the pose for the ball 
      shared_ptr<const Pose3d> Pball = ball_cg->get_pose();

      // get the pose of the center-of-mass of the ball
      Transform3d pTb = Pose3d::calc_relative_pose(Pball, Pparabloid);

      // compute the height of the ball above the parabloid; note: this assumes
      // that the parabloid is relatively flat
      double dist = -sqr(pTb.x[X])/(A*A) + sqr(pTb.x[Y])/(B*B) + (pTb.x[Z] - R); 

      // compute the closest point - we'll go half way between the closest
      // point on the ball and the closest point on the surface 
      double z = sqr(pTb.x[X])/sqr(A) + sqr(pTb.x[Y])/sqr(B);
      pparabloid = Point3d(pTb.x[X], pTb.x[Y], z, Pparabloid);
      pball = Point3d(0.0, 0.0, -R, Pball);

      return dist;
    }
/// Determines whether a pair of geometries is checked for collision detection
bool CollisionDetection::is_checked(CollisionGeometryPtr cg1, CollisionGeometryPtr cg2) const
{
  // if both geometries belong to one rigid body, don't check
  RigidBodyPtr rb1 = dynamic_pointer_cast<RigidBody>(cg1->get_single_body());
  RigidBodyPtr rb2 = dynamic_pointer_cast<RigidBody>(cg2->get_single_body());
  if (rb1 && rb2 && rb1 == rb2)
    return false;

  // check the geometries
  return (is_enabled(cg1) && is_enabled(cg2) && is_enabled(cg1, cg2));
}
/// Calculates the signed distances between two geometries and returns closest points if geometries are not interpenetrating
double CollisionGeometry::calc_signed_dist(CollisionGeometryPtr gA, CollisionGeometryPtr gB, Point3d& pA, Point3d& pB) 
{
  // get the two primitives
  PrimitivePtr primA = gA->get_geometry();
  PrimitivePtr primB = gB->get_geometry();

  // setup poses for the points
  pA.pose = primA->get_pose(gA);
  pB.pose = primB->get_pose(gB);

  FILE_LOG(LOG_COLDET) << "CollisionGeometry::calc_signed_dist() - computing signed distance between " << gA->get_single_body()->id << " and " << gB->get_single_body()->id << std::endl;

  // now compute the signed distance
  return primA->calc_signed_dist(primB, pA, pB);
}
/// Calculates the velocity expanded bounding volume for the bounding sphere (calculates an OBB)
BVPtr BoundingSphere::calc_swept_BV(CollisionGeometryPtr g, const SVelocityd& v) const
{
  // get the corresponding body
  SingleBodyPtr b = g->get_single_body();

  // if the body does not move, just return the bounding sphere 
  if (!b->is_enabled())
  {
    FILE_LOG(LOG_BV) << "BoundingSphere::calc_swept_BV() entered" << endl;
    FILE_LOG(LOG_BV) << "  -- using original bounding sphere" << endl;
    FILE_LOG(LOG_BV) << "BoundingSphere::calc_swept_BV() exited" << endl;

    return const_pointer_cast<BoundingSphere>(get_this());
  }

  // get the velocity in the proper frame
  SVelocityd vx = Pose3d::transform(get_relative_pose(), v); 

  // otherwise, create a SSL 
  shared_ptr<SSL> ssl(new SSL);
  ssl->p1 = this->center;
  ssl->p2 = this->center + vx.get_linear();
  ssl->radius = this->radius;
  return ssl;
}
Exemple #6
0
void ColdetPlugin::add_collision_geometry(CollisionGeometryPtr cg)
{
  RigidBodyPtr rb = dynamic_pointer_cast<RigidBody>(cg->get_single_body());
  if (rb->id.find("box") != std::string::npos)
  {
    // add the box
    _boxes.push_back(cg);

    // sort all collision geometries
    std::map<std::string, CollisionGeometryPtr> geoms;
    for (unsigned i=0; i< _boxes.size(); i++)
      geoms[_boxes[i]->get_single_body()->id] = _boxes[i];

    // clear the boxes
    _boxes.clear();
    for (std::map<std::string, CollisionGeometryPtr>::const_iterator i = geoms.begin(); i != geoms.end(); i++)
      _boxes.push_back(i->second);
  }
  else
  {
    assert(rb->id == "ground");
    _ground = cg;
  }
}
Exemple #7
0
/**
 * This method looks for contact data not only between the pair of geometries, but also
 * the rigid bodies that the geometries belong to, and any articulated bodies as well.
 * The search proceeds in the following manner: <br />
 * <ol>
 *  <li>two collision geometries</li>
 *  <li>one collision geometry, one rigid body</li>
 *  <li>two rigid bodies</li>
 *  <li>one collision geometry, one articulated body</li>
 *  <li>one rigid body, one articulated body</li>
 *  <li>two articulated bodies</li>
 * </ol>
 * The search order allows for multiple granularities; for example, a collision can easily
 * be specified between two geometries of two of a robot's links (i.e., representing different
 * surfaces on the links), between two links, or between two robots.
 * \param g1 the first collision geometry
 * \param g2 the second collision geometry
 * \return a pointer to the contact data, if any, found
 */
shared_ptr<ContactParameters> EventDrivenSimulator::get_contact_parameters(CollisionGeometryPtr geom1, CollisionGeometryPtr geom2) const
{
  map<sorted_pair<BasePtr>, shared_ptr<ContactParameters> >::const_iterator iter;

  // search for the two contact geometries first
  if ((iter = contact_params.find(make_sorted_pair(geom1, geom2))) != contact_params.end())
    return iter->second;

  // get the geometries as base pointers
  BasePtr g1(geom1);
  BasePtr g2(geom2);
  
  // get the two single bodies
  assert(geom1->get_single_body());
  assert(geom2->get_single_body());
  SingleBodyPtr singlebody1 = geom1->get_single_body();
  SingleBodyPtr singlebody2 = geom2->get_single_body();
  BasePtr sb1 = singlebody1;
  BasePtr sb2 = singlebody2;

  // search for contact geometry 1 and rigid body 2
  if ((iter = contact_params.find(make_sorted_pair(g1, sb2))) != contact_params.end())
    return iter->second;

  // search for contact geometry 2 and rigid body 1
  if ((iter = contact_params.find(make_sorted_pair(g2, sb1))) != contact_params.end())
    return iter->second;

  // search for both rigid bodies
  if ((iter = contact_params.find(make_sorted_pair(sb1, sb2))) != contact_params.end())
    return iter->second;

  // get the articulated bodies, if any
  RigidBodyPtr rb1 = dynamic_pointer_cast<RigidBody>(singlebody1);
  RigidBodyPtr rb2 = dynamic_pointer_cast<RigidBody>(singlebody2);
  BasePtr ab1, ab2;
  if (rb1)
    ab1 = rb1->get_articulated_body();
  if (rb2)
    ab2 = rb2->get_articulated_body();

  // check collision geometry 2 and rigid body 2 against articulated body 1
  if (ab1)
  {
    if ((iter = contact_params.find(make_sorted_pair(g2, ab1))) != contact_params.end())
      return iter->second;
    if ((iter = contact_params.find(make_sorted_pair(sb2, ab1))) != contact_params.end())
      return iter->second;
  }

  // check collision geometry 1 and rigid body 1 against articulated body 2
  if (ab2)
  {
    if ((iter = contact_params.find(make_sorted_pair(g1, ab2))) != contact_params.end())
      return iter->second;
    if ((iter = contact_params.find(make_sorted_pair(sb1, ab2))) != contact_params.end())
      return iter->second;
  }

  // check the two articulated bodies against articulated body 2
  if (ab1 && ab2)
    if ((iter = contact_params.find(make_sorted_pair(ab1, ab2))) != contact_params.end())
      return iter->second;
  
  // still here?  no contact data found
  return shared_ptr<ContactParameters>();
}