Beispiel #1
0
ODEObjectID WorldSimulation::WorldToODEID(int id) const
{
  int i=world->IsRigidObject(id);
  if(i>=0) return ODEObjectID(2,i);
  i=world->IsTerrain(id);
  if(i>=0) return ODEObjectID(0,i);
  i=world->IsRobot(id);
  if(i>=0) return ODEObjectID(1,i);
  pair<int,int> res=world->IsRobotLink(id);
  if(res.first>=0) return ODEObjectID(1,res.first,res.second);
  FatalError("World ID %d not valid\n",id);
  return ODEObjectID();
}
Beispiel #2
0
void ODESimulator::DetectCollisions()
{
  dJointGroupEmpty(contactGroupID);
  //clear feedback structure
  for(map<pair<ODEObjectID,ODEObjectID>,ODEContactList>::iterator i=contactList.begin();i!=contactList.end();i++) {
    i->second.points.clear();
    i->second.forces.clear();
    i->second.feedbackIndices.clear();
  }
  gContacts.clear();

  pair<ODEObjectID,ODEObjectID> cindex;
  int jcount=0;
  if(settings.rigidObjectCollisions) {
    //call the collision routine between objects and the world
    dSpaceCollide(envSpaceID,(void*)this,collisionCallback);

    for(list<ODEContactResult>::iterator j=gContacts.begin();j!=gContacts.end();j++,jcount++) {
      //// int is not necessarily big enough, use intptr_t
      //int o1 = (int)dGeomGetData(j->o1);
      //int o2 = (int)dGeomGetData(j->o2);
      intptr_t o1 = (intptr_t)dGeomGetData(j->o1);
      intptr_t o2 = (intptr_t)dGeomGetData(j->o2);
      if(o1 < 0) {  //it's an environment
	cindex.first = ODEObjectID(0,(-o1-1));
      }
      else {
	cindex.first = ODEObjectID(2,o1);
      }
      if(o2 < 0) {  //it's an environment
	cindex.second = ODEObjectID(0,(-o2-1));
      }
      else {
	cindex.second = ODEObjectID(2,o2);
      }
      if(o1 < 0 && o2 < 0) {
	fprintf(stderr,"Warning, detecting terrain-terrain collisions?\n");
      }
      else {
	j->feedback.resize(j->contacts.size());
	SetupContactResponse(cindex.first,cindex.second,jcount,*j);
      }
    }
  }

  //do robot-environment collisions
  for(size_t i=0;i<robots.size();i++) {
    cindex.first = ODEObjectID(1,i);

    //call the collision routine between the robot and the world
    list<ODEContactResult>::iterator gContactStart = --gContacts.end();
    dSpaceCollide2((dxGeom *)robots[i]->space(),(dxGeom *)envSpaceID,(void*)this,collisionCallback);
    ++gContactStart;
    ProcessContacts(gContactStart,gContacts.end(),settings);

    //setup the contact "joints" and contactLists
    for(list<ODEContactResult>::iterator j=gContactStart;j!=gContacts.end();j++,jcount++) {
      bool isBodyo1 = false, isBodyo2 = false;
      for(size_t k=0;k<robots[i]->robot.links.size();k++) {
	if(robots[i]->triMesh(k) && j->o1 == robots[i]->geom(k)) isBodyo1=true;
	if(robots[i]->triMesh(k) && j->o2 == robots[i]->geom(k)) isBodyo2=true;
      }
      intptr_t body,obj;
      if(isBodyo2) {
	printf("Warning, ODE collision result lists bodies in reverse order\n");
	Assert(!isBodyo1);
	body = (intptr_t)dGeomGetData(j->o2);
	obj = (intptr_t)dGeomGetData(j->o1);
      }
      else {
	Assert(!isBodyo2);
	Assert(isBodyo1);
	body = (intptr_t)dGeomGetData(j->o1);
	obj = (intptr_t)dGeomGetData(j->o2);
      }
      //printf("Collision between body %d and obj %d\n",body,obj);
      Assert(body >= 0 && body < (int)robots[i]->robot.links.size());
      Assert(obj >= -(int)envs.size() && obj < (int)objects.size());
      if(robots[i]->robot.parents[body] == -1 && obj < 0) { //fixed links
	fprintf(stderr,"Warning, colliding a fixed link and the terrain\n");
	continue;
      }
      cindex.first.bodyIndex = body;
      if(obj < 0) {  //it's an environment
	cindex.second = ODEObjectID(0,(-obj-1));
      }
      else {
	cindex.second = ODEObjectID(2,obj);
      }
      SetupContactResponse(cindex.first,cindex.second,jcount,*j);
    }

    if(settings.robotSelfCollisions) {
      robots[i]->EnableSelfCollisions(true);

      cindex.second = ODEObjectID(1,i);
      list<ODEContactResult>::iterator gContactStart = --gContacts.end();
      //call the self collision routine for the robot
      dSpaceCollide(robots[i]->space(),(void*)robots[i],selfCollisionCallback);
      ++gContactStart;
      
      ProcessContacts(gContactStart,gContacts.end(),settings);

      //setup the contact "joints" and contactLists
      for(list<ODEContactResult>::iterator j=gContactStart;j!=gContacts.end();j++,jcount++) {
	intptr_t body1 = (intptr_t)dGeomGetData(j->o1);
	intptr_t body2 = (intptr_t)dGeomGetData(j->o2);
	//printf("Collision between body %d and body %d\n",body1,body2);
	Assert(body1 >= 0 && body1 < (int)robots[i]->robot.links.size());
	Assert(body2 >= 0 && body2 < (int)robots[i]->robot.links.size());
	cindex.first.bodyIndex = body1;
	cindex.second.bodyIndex = body2;
	SetupContactResponse(cindex.first,cindex.second,jcount,*j);
      }
    }

    if(settings.robotRobotCollisions) {    
      for(size_t k=i+1;k<robots.size();k++) {
	cindex.second = ODEObjectID(1,k);
	list<ODEContactResult>::iterator gContactStart = --gContacts.end();
	dSpaceCollide2((dxGeom *)robots[i]->space(),(dxGeom *)robots[k]->space(),(void*)this,collisionCallback);
	++gContactStart;
	ProcessContacts(gContactStart,gContacts.end(),settings);

	//setup the contact "joints" and contactLists
	for(list<ODEContactResult>::iterator j=gContactStart;j!=gContacts.end();j++,jcount++) {
	  intptr_t body1 = (intptr_t)dGeomGetData(j->o1);
	  intptr_t body2 = (intptr_t)dGeomGetData(j->o2);
	  //printf("Collision between robot %d and robot %d\n",i,k);
	  Assert(body1 >= 0 && body1 < (int)robots[i]->robot.links.size());
	  Assert(body2 >= 0 && body2 < (int)robots[k]->robot.links.size());
	  cindex.first.bodyIndex = body1;
	  cindex.second.bodyIndex = body2;
	  SetupContactResponse(cindex.first,cindex.second,jcount,*j);
	}
      }
    }
  }
}