コード例 #1
0
ファイル: rigidkinematics.cpp プロジェクト: barbagroup/PetIBM
// advance the solution by one time step
PetscErrorCode RigidKinematicsSolver::advance()
{
    PetscErrorCode ierr;

    PetscFunctionBeginUser;

    // note: use of `t + dt` because `t` is update in the Navier-Stokes method
    ierr = moveBodies(t + dt); CHKERRQ(ierr);

    ierr = DecoupledIBPMSolver::advance(); CHKERRQ(ierr);

    PetscFunctionReturn(0);
}  // advance
コード例 #2
0
ファイル: graspitDynamics.cpp プロジェクト: iretiayo/graspit
/*! One of the two main functions of the dynamics time step. This function is
called to move the bodies according to the velocities and accelerations found
in the previous step. The move is attempted for the duration of the time step
given in \a timeStep.

After all the bodies are moved, then collisions are checked. If any collisions
are found, the move is traced back and the value of the times step is
interpolated until the exact moment of contact is found. The actual value
of the time step until contact is made is returned. If interpolation fails,
a negative actual time step is returned. All the resulting contacts are added
to the bodies that are in contact to be used for subsequent computations.

The same procedure is carried out if, by executing a full time step, a joint
ends up outside of its legal range.
*/
double GraspitDynamics::moveDynamicBodies(double timeStep) {
  int i, numDynBodies, numCols, moveErrCode;
  std::vector<DynamicBody *> dynBodies;
  static CollisionReport colReport;
  bool jointLimitHit;
  double contactTime, delta, tmpDist, minDist, dofLimitDist;

  int numBodies = mWorld->getNumBodies();
  int numRobots = mWorld->getNumRobots();

  // save the initial position
  for (i = 0; i < numBodies; i++) {
    if (mWorld->getBody(i)->isDynamic()) {
      dynBodies.push_back((DynamicBody *)mWorld->getBody(i));
      ((DynamicBody *)mWorld->getBody(i))->markState();
    }
  }
  numDynBodies = dynBodies.size();

  // call to the dynamics engine to perform the move by the full time step
  DBGP("moving bodies with timestep: " << timeStep);
  moveErrCode = moveBodies(numDynBodies, dynBodies, timeStep);
  if (moveErrCode == 1) {  // object out of bounds
    mWorld->popDynamicState();
    turnOffDynamics();
    return -1.0;
  }

  // this sets the joints internal values according to how bodies have moved
  for (i = 0; i < numRobots; i++) {
    mWorld->getRobot(i)->updateJointValuesFromDynamics();
  }

  // check if we have collisions
  if (numDynBodies > 0) { numCols = mWorld->getCollisionReport(&colReport); }
  else { numCols = 0; }

  // check if we have joint limits exceeded
  jointLimitHit = false;
  for (i = 0; i < numRobots; i++) {
    if (mWorld->getRobot(i)->jointLimitDist() < 0.0) { jointLimitHit = true; }
  }

  // if so, we must interpolate until the exact moment of contact or limit hit
  if (numCols || jointLimitHit) {
    // return to initial position
    for (i = 0; i < numDynBodies; i++) {
      dynBodies[i]->returnToMarkedState();
    }
    minDist = 1.0e+255;
    dofLimitDist = 1.0e+255;

#ifdef GRASPITDBG
    if (numCols) {
      std::cout << "COLLIDE!" << std::endl;
      for (i = 0; i < numCols; i++) {
        std::cout << colReport[i].first->getName().toStdString().c_str() << " collided with " <<
                  colReport[i].second->getName().toStdString().c_str() << std::endl;
      }

      for (i = 0; i < numCols; i++) {
        tmpDist = mWorld->getDist(colReport[i].first, colReport[i].second);
        if (tmpDist < minDist) { minDist = tmpDist; }
        std::cout << "minDist: " << tmpDist << " between " << std::endl;
        std::cout << colReport[i].first->getName().toStdString().c_str() << " and " <<
                  colReport[i].second->getName().toStdString().c_str() << std::endl;
      }
    }
#endif

    // this section refines the timestep until the objects are separated
    // by a distance less than CONTACT_THRESHOLD
    bool done = false;
    contactTime = timeStep;
    delta = contactTime / 2;
    contactTime -= delta;

    while (!done) {
      delta /= 2.0;
      for (i = 0; i < numDynBodies; i++) {
        dynBodies[i]->returnToMarkedState();
      }
      DBGP("moving bodies with timestep: " << contactTime);
      moveErrCode = moveBodies(numDynBodies, dynBodies, contactTime);

      if (moveErrCode == 1) {  // object out of bounds
        mWorld->popDynamicState();
        turnOffDynamics();
        return -1.0;
      }

      const char *min_body_1, *min_body_2;

      // this computes joints values according to how dynamic bodies have moved
      for (i = 0; i < numRobots; i++) {
        mWorld->getRobot(i)->updateJointValuesFromDynamics();
      }

      if (numCols) {
        minDist = 1.0e+255;
        for (i = 0; i < numCols; i++) {
          tmpDist = mWorld->getDist(colReport[i].first, colReport[i].second);
          if (tmpDist < minDist) {
            minDist = tmpDist;
            min_body_1 = colReport[i].first->getName().toStdString().c_str();
            min_body_2 = colReport[i].second->getName().toStdString().c_str();
            DBGP("minDist: " << minDist << " between " << colReport[i].first->getName().toStdString().c_str() <<
                 " and " << colReport[i].second->getName().toStdString().c_str());
          }
        }
      }


      if (jointLimitHit) {
        dofLimitDist = 1.0e10;
        for (i = 0; i < numRobots; i++) {
          dofLimitDist = MIN(dofLimitDist, mWorld->getRobot(i)->jointLimitDist());
        }
      }

      if (minDist <= 0.0 || dofLimitDist < -resabs) {
        contactTime -= delta;
      }
      else if (minDist > Contact::THRESHOLD * 0.5 && dofLimitDist > 0.01) { // why is this not resabs
        contactTime += delta;
      }
      else { break; }

      if (fabs(delta) < 1.0E-15 || contactTime < 1.0e-7) {
        if (minDist <= 0) {
          fprintf(stderr, "Delta failsafe due to collision: %s and %s\n", min_body_1, min_body_2);
        } else {
          fprintf(stderr, "Delta failsafe due to joint\n");
        }
        done = true;  // failsafe
      }
    }

    // COULD NOT FIND COLLISION TIME
    if (done && contactTime < 1.0E-7) {
      DBGP("!! could not find contact time !!");
      for (i = 0; i < numDynBodies; i++) {
        dynBodies[i]->returnToMarkedState();
      }
    }
    mWorld->getWorldTimeRef() += contactTime;
  } else {  // if no collision
    mWorld->getWorldTimeRef() += timeStep;
    contactTime = timeStep;
  }

#ifdef GRASPITDBG
  std::cout << "CHECKING COLLISIONS AT MIDDLE OF STEP: ";
  numCols = mWorld->getCollisionReport(&colReport);

  if (!numCols) {
    std::cout << "None." << std::endl;
  } else {
    std::cout << numCols << " found!!!" << std::endl;
    for (i = 0; i < numCols; i++) {
      std::cout << colReport[i].first->getName().toStdString().c_str() << " collided with " <<
                colReport[i].second->getName().toStdString().c_str() << std::endl;
    }
  }
#endif

  if (numDynBodies > 0) {
    mWorld->findAllContacts();
  }

  for (i = 0; i < numRobots; i++) {
    if (mWorld->getRobot(i)->inherits("HumanHand")) { ((HumanHand *)mWorld->getRobot(i))->updateTendonGeometry(); }
    mWorld->getRobot(i)->emitConfigChange();
  }
  mWorld->tendonChange();

  if (contactTime < 1.0E-7) { return -1.0; }
  return contactTime;
}