Example #1
0
void GetNearbyContacts(RobotWithGeometry& robot,int link,RobotWorld& world,Real tol,vector<ContactPoint>& contacts)
{
  contacts.resize(0);
  if(robot.IsGeometryEmpty(link)) {
    return;
  }
  Geometry::AnyCollisionGeometry3D& g1 = *robot.geometry[link];
  Real m1 = 0;
  Real m2 = tol;
  dContactGeom temp[1000];
  int maxContacts = 1000;
  vector<Geometry::AnyCollisionGeometry3D*> geomsToCheck;
  for(size_t i=0;i<world.terrains.size();i++) {
    if(world.terrains[i]->geometry.Empty()) continue;
    geomsToCheck.push_back(&*world.terrains[i]->geometry);
  }
  for(size_t i=0;i<world.rigidObjects.size();i++) {
    if(world.rigidObjects[i]->geometry.Empty()) {
      continue;
    }
    geomsToCheck.push_back(&*world.rigidObjects[i]->geometry);
    world.rigidObjects[i]->UpdateGeometry();
  }
  //now do the tolerance checks and add to the contacts list
  for(size_t i=0;i<geomsToCheck.size();i++) {
    int nc = GeometryGeometryCollide(g1,m1,*geomsToCheck[i],m2,temp,maxContacts);
    if(nc > 0) {
      size_t start = contacts.size();
      contacts.resize(start+nc);
      for(int j=0;j<nc;j++) {
        //contacts[j].x.set(temp[j].pos);
        contacts[j].x.set(temp[j].pos[0], temp[j].pos[1], temp[j].pos[2]);
        contacts[j].n.set(temp[j].normal[0], temp[j].normal[1], temp[j].normal[2]);
        //contacts[j].n.set(temp[j].normal);
        contacts[j].kFriction = 0;

        //convert to local coordinates
        Vector3 localPos,localNormal;
        robot.links[link].T_World.mulInverse(contacts[j].x,localPos);
        robot.links[link].T_World.R.mulTranspose(contacts[j].n,localNormal);
        contacts[j].x = localPos;
        contacts[j].n = localNormal;
      }
    }
  }
}
Example #2
0
//Produces a list of contacts as though the robot were standing on a plane.
//tol is the tolerance with which minimum-distance points are generated.
//All contacts are given zero friction and in the local frame of the robot.
void GetFlatContacts(RobotWithGeometry& robot,Real tol,ContactFormation& contacts)
{
  vector<AABB3D> bbs(robot.geometry.size());
  vector<pair<Real,int> > order;
  robot.UpdateGeometry();
  for(size_t i=0;i<robot.geometry.size();i++)
    if(robot.parents[i] >= 0 && !robot.IsGeometryEmpty(i)) {
      AABB3D aabb = robot.geometry[i]->GetAABB();
      bbs[i] = aabb;
      order.push_back(pair<Real,int>(aabb.bmin.z,(int)i));
    }
  sort(order.begin(),order.end());
  Real best = Inf;
  for(size_t i=0;i<order.size();i++) {
    if(order[i].first > best) break; //done
    int k=order[i].second;
    switch(robot.geometry[k]->type) {
    case AnyGeometry3D::Primitive:
      FatalError("Can't get flat contacts for primitives");
      break;
    case AnyGeometry3D::ImplicitSurface:
      FatalError("Can't get flat contacts for implicit surfaces");
      break;
    case AnyGeometry3D::Group:
      FatalError("Can't get flat contacts for geometry group");
      break;
    case AnyGeometry3D::TriangleMesh:
      {
	const TriMesh& m=robot.geometry[k]->AsTriangleMesh();
	for(size_t v=0;v<m.verts.size();v++) {
	  Vector3 pw = robot.links[k].T_World*m.verts[v];
	  if(pw.z < best)
	    best = pw.z;
	  assert(pw.z >= order[i].first);
	}
      }
      break;
    case AnyGeometry3D::PointCloud:
      {
	const PointCloud3D& pc=robot.geometry[k]->AsPointCloud();
	for(size_t v=0;v<pc.points.size();v++) {
	  Vector3 pw = robot.links[k].T_World*pc.points[v];
	  if(pw.z < best)
	    best = pw.z;
	  assert(pw.z >= order[i].first);
	}
      }
      break;
    }
  }
  
  //got the plane height, now output the vertices
  ContactPoint cp;
  cp.kFriction = 0.0;
  contacts.links.resize(0);
  contacts.contacts.resize(0);
  for(size_t i=0;i<order.size();i++) {
    if(order[i].first > best+tol) break; //done
    int k=order[i].second;
    contacts.links.resize(contacts.links.size()+1);
    contacts.links.back()=k;
    contacts.contacts.resize(contacts.contacts.size()+1);
    vector<Vector3> pts;
    switch(robot.geometry[k]->type) {
    case AnyGeometry3D::TriangleMesh:
      {
	const TriMesh& m=robot.geometry[k]->AsTriangleMesh();
	for(size_t v=0;v<m.verts.size();v++) {
	  Vector3 pw = robot.links[k].T_World*m.verts[v];
	  if(pw.z < best+tol) {
	    pts.push_back(pw);
	  }
	}
      }
      break;
    case AnyGeometry3D::PointCloud:
      {
	const PointCloud3D& pc=robot.geometry[k]->AsPointCloud();
	for(size_t v=0;v<pc.points.size();v++) {
	  Vector3 pw = robot.links[k].T_World*pc.points[v];
	  if(pw.z < best+tol) {
	    pts.push_back(pw);
	  }
	}
      }
      break;
    default:
      break;
    }
    //get the convex hull of those points
    vector<Vector2> pts2(pts.size());
    vector<Vector2> hull(pts.size());
    vector<int> hindex(pts.size());
    for(size_t v=0;v<pts.size();v++)
      pts2[v].set(pts[v].x,pts[v].y);
    int num = ConvexHull2D_Chain_Unsorted( &pts2[0], pts2.size(), &hull[0], &hindex[0]);
    contacts.contacts.back().resize(num);
    for(int v=0;v<num;v++) {
      //local estimate
      robot.links[k].T_World.mulInverse(pts[hindex[v]],cp.x);
      robot.links[k].T_World.R.mulTranspose(Vector3(0,0,1),cp.n);
      contacts.contacts.back()[v] = cp;
    }
    if(contacts.contacts.back().empty()) {
      //bound was below threshold, but no contacts below threshold
      contacts.links.resize(contacts.links.size()-1);
      contacts.contacts.resize(contacts.contacts.size()-1);
    }
  }
}