예제 #1
0
void check_self_consistency(SkeletonPtr skeleton)
{
  for(size_t i=0; i<skeleton->getNumBodyNodes(); ++i)
  {
    BodyNode* bn = skeleton->getBodyNode(i);
    EXPECT_TRUE(bn->getIndexInSkeleton() == i);
    EXPECT_TRUE(skeleton->getBodyNode(bn->getName()) == bn);

    Joint* joint = bn->getParentJoint();
    EXPECT_TRUE(skeleton->getJoint(joint->getName()) == joint);

    for(size_t j=0; j<joint->getNumDofs(); ++j)
    {
      DegreeOfFreedom* dof = joint->getDof(j);
      EXPECT_TRUE(dof->getIndexInJoint() == j);
      EXPECT_TRUE(skeleton->getDof(dof->getName()) == dof);
    }
  }

  for(size_t i=0; i<skeleton->getNumDofs(); ++i)
  {
    DegreeOfFreedom* dof = skeleton->getDof(i);
    EXPECT_TRUE(dof->getIndexInSkeleton() == i);
    EXPECT_TRUE(skeleton->getDof(dof->getName()) == dof);
  }
}
예제 #2
0
// Solve for a balanced pose using IK (Lesson 7 Answer)
Eigen::VectorXd solveIK(SkeletonPtr biped)
{
  // Modify the intial pose to one-foot stance before IK 
  biped->setPosition(biped->getDof("j_shin_right")->
                     getIndexInSkeleton(), -1.4);
  biped->setPosition(biped->getDof("j_bicep_left_x")->
                     getIndexInSkeleton(), 0.8);
  biped->setPosition(biped->getDof("j_bicep_right_x")->
                     getIndexInSkeleton(), -0.8);

  Eigen::VectorXd newPose = biped->getPositions();
  BodyNodePtr leftHeel = biped->getBodyNode("h_heel_left");
  BodyNodePtr leftToe = biped->getBodyNode("h_toe_left");
  double initialHeight = -0.8;

  for(std::size_t i = 0; i < default_ik_iterations; ++i)
  {
    Eigen::Vector3d deviation = biped->getCOM() - leftHeel->getCOM();
    Eigen::Vector3d localCOM = leftHeel->getCOM(leftHeel);
    LinearJacobian jacobian = biped->getCOMLinearJacobian() -
        biped->getLinearJacobian(leftHeel, localCOM);
    
    // Sagittal deviation
    double error = deviation[0];
    Eigen::VectorXd gradient = jacobian.row(0);
    Eigen::VectorXd newDirection = -0.2 * error * gradient;
    
    // Lateral deviation
    error = deviation[2];
    gradient = jacobian.row(2);
    newDirection += -0.2 * error * gradient;
    
    // Position constraint on four (approximated) corners of the left foot
    Eigen::Vector3d offset(0.0, -0.04, -0.03);
    error = (leftHeel->getTransform() * offset)[1] - initialHeight;
    gradient = biped->getLinearJacobian(leftHeel, offset).row(1);
    newDirection += -0.2 * error * gradient;
    
    offset[2] = 0.03;
    error = (leftHeel->getTransform() * offset)[1] - initialHeight;
    gradient = biped->getLinearJacobian(leftHeel, offset).row(1);
    newDirection += -0.2 * error * gradient;
    
    offset[0] = 0.04;
    error = (leftToe->getTransform() * offset)[1] - initialHeight;
    gradient = biped->getLinearJacobian(leftToe, offset).row(1);
    newDirection += -0.2 * error * gradient;
    
    offset[2] = -0.03;
    error = (leftToe->getTransform() * offset)[1] - initialHeight;
    gradient = biped->getLinearJacobian(leftToe, offset).row(1);
    newDirection += -0.2 * error * gradient;
    
    newPose += newDirection;
    biped->setPositions(newPose);
    biped->computeForwardKinematics(true, false, false);
  }
  return newPose;
}
예제 #3
0
void setAllColors(const SkeletonPtr& object, const Eigen::Vector3d& color)
{
  // Set the color of all the shapes in the object
  for(size_t i=0; i < object->getNumBodyNodes(); ++i)
  {
    BodyNode* bn = object->getBodyNode(i);
    for(size_t j=0; j < bn->getNumVisualizationShapes(); ++j)
      bn->getVisualizationShape(j)->setColor(color);
  }
}
예제 #4
0
SkeletonPtr createGround()
{
  // Create a Skeleton to represent the ground
  SkeletonPtr ground = Skeleton::create("ground");
  Eigen::Isometry3d tf(Eigen::Isometry3d::Identity());
  double thickness = 0.01;
  tf.translation() = Eigen::Vector3d(0,0,-thickness/2.0);
  WeldJoint::Properties joint;
  joint.mT_ParentBodyToJoint = tf;
  ground->createJointAndBodyNodePair<WeldJoint>(nullptr, joint);
  ShapePtr groundShape =
      std::make_shared<BoxShape>(Eigen::Vector3d(10,10,thickness));
  groundShape->setColor(dart::Color::Blue(0.2));

  ground->getBodyNode(0)->addVisualizationShape(groundShape);
  ground->getBodyNode(0)->addCollisionShape(groundShape);

  return ground;
}
예제 #5
0
SkeletonPtr createHubo()
{
  dart::utils::DartLoader loader;
  loader.addPackageDirectory("drchubo", DART_DATA_PATH"/urdf/drchubo");
  SkeletonPtr hubo =
      loader.parseSkeleton(DART_DATA_PATH"/urdf/drchubo/drchubo.urdf");

  for(size_t i = 0; i < hubo->getNumBodyNodes(); ++i)
  {
    BodyNode* bn = hubo->getBodyNode(i);
    if(bn->getName().substr(0, 7) == "Body_LF"
       || bn->getName().substr(0, 7) == "Body_RF"
       || bn->getName().substr(0, 7) == "Body_NK")
    {
      bn->remove();
      --i;
    }
  }

  hubo->setPosition(5, 0.97);

  for(size_t i=1; i < hubo->getNumJoints(); ++i)
  {
    hubo->getJoint(i)->setActuatorType(Joint::VELOCITY);
  }

  for(size_t i=0; i < hubo->getNumBodyNodes(); ++i)
  {
    BodyNode* bn = hubo->getBodyNode(i);
    for(size_t j=0; j < bn->getNumVisualizationShapes(); ++j)
    {
      const ShapePtr& shape = bn->getVisualizationShape(j);
      shape->setColor(Eigen::Vector3d(0.2, 0.2, 0.2));

      if(MeshShapePtr mesh = std::dynamic_pointer_cast<MeshShape>(shape))
        mesh->setColorMode(MeshShape::SHAPE_COLOR);
    }
  }

  hubo->setName("drchubo");
  return hubo;
}
예제 #6
0
void setAllColors(const SkeletonPtr& object, const Eigen::Vector3d& color)
{
  // Set the color of all the shapes in the object
  for(size_t i=0; i < object->getNumBodyNodes(); ++i)
  {
    BodyNode* bn = object->getBodyNode(i);
    auto visualShapeNodes = bn->getShapeNodesWith<VisualAddon>();
    for(auto visualShapeNode : visualShapeNodes)
      visualShapeNode->getVisualAddon()->setColor(color);
  }
}
예제 #7
0
// Load a skateboard model and connect it to the biped model via an Euler joint
// (Lesson 5 Answer)
void modifyBipedWithSkateboard(SkeletonPtr biped)
{
  // Load the Skeleton from a file
  WorldPtr world = SkelParser::readWorld("dart://sample/skel/skateboard.skel");

  SkeletonPtr skateboard = world->getSkeleton(0);
  
  EulerJoint::Properties properties = EulerJoint::Properties();
  properties.mT_ChildBodyToJoint.translation() = Eigen::Vector3d(0, 0.1, 0);
  
  skateboard->getRootBodyNode()->moveTo<EulerJoint>
      (biped->getBodyNode("h_heel_left"), properties);
}
예제 #8
0
TEST(Skeleton, ZeroDofJointInReferential)
{
  // This is a regression test which makes sure that the BodyNodes of
  // ZeroDofJoints will be correctly included in linkages.
  SkeletonPtr skel = Skeleton::create();

  BodyNode* bn = skel->createJointAndBodyNodePair<RevoluteJoint>().second;
  BodyNode* zeroDof1 = skel->createJointAndBodyNodePair<WeldJoint>(bn).second;
  bn = skel->createJointAndBodyNodePair<PrismaticJoint>(zeroDof1).second;
  BodyNode* zeroDof2 = skel->createJointAndBodyNodePair<WeldJoint>(bn).second;

  BranchPtr branch = Branch::create(skel->getBodyNode(0));
  EXPECT_EQ(branch->getNumBodyNodes(), skel->getNumBodyNodes());
  EXPECT_FALSE(branch->getIndexOf(zeroDof1) == INVALID_INDEX);
  EXPECT_FALSE(branch->getIndexOf(zeroDof2) == INVALID_INDEX);
}
예제 #9
0
void enableDragAndDrops(osgDart::Viewer& viewer, const SkeletonPtr& atlas)
{
  // Turn on drag-and-drop for the whole Skeleton
  for(size_t i=0; i < atlas->getNumBodyNodes(); ++i)
    viewer.enableDragAndDrop(atlas->getBodyNode(i), false, false);

  for(size_t i=0; i < atlas->getNumEndEffectors(); ++i)
  {
    EndEffector* ee = atlas->getEndEffector(i);
    if(!ee->getIK())
      continue;

    // Check whether the target is an interactive frame, and add it if it is
    if(const auto& frame = std::dynamic_pointer_cast<osgDart::InteractiveFrame>(
         ee->getIK()->getTarget()))
      viewer.enableDragAndDrop(frame.get());
  }
}
예제 #10
0
void checkForBodyNodes(
    size_t& count,
    const ReferentialSkeletonPtr& refSkel,
    const SkeletonPtr& skel,
    const std::string& name,
    Args ... args)
{
  bool contains = refSkel->getIndexOf(skel->getBodyNode(name)) != INVALID_INDEX;
  EXPECT_TRUE(contains);
  if(!contains)
  {
    dtmsg << "The ReferentialSkeleton [" << refSkel->getName() << "] does NOT "
          << "contain the BodyNode [" << name << "] of the Skeleton ["
          << skel->getName() << "]\n";
  }

  ++count;
  checkForBodyNodes(count, refSkel, skel, args...);
}
예제 #11
0
SkeletonPtr createAtlas()
{
  // Parse in the atlas model
  DartLoader urdf;
  SkeletonPtr atlas =
      urdf.parseSkeleton(DART_DATA_PATH"sdf/atlas/atlas_v3_no_head.urdf");

  // Add a box to the root node to make it easier to click and drag
  double scale = 0.25;
  ShapePtr boxShape =
      std::make_shared<BoxShape>(scale*Eigen::Vector3d(1.0, 1.0, 0.5));
  boxShape->setColor(dart::Color::Black());

  Eigen::Isometry3d tf(Eigen::Isometry3d::Identity());
  tf.translation() = Eigen::Vector3d(0.1*Eigen::Vector3d(0.0, 0.0, 1.0));
  boxShape->setLocalTransform(tf);

  atlas->getBodyNode(0)->addVisualizationShape(boxShape);

  return atlas;
}
예제 #12
0
//==============================================================================
TEST(FORWARD_KINEMATICS, YAW_ROLL)
{
  // Checks forward kinematics for two DoF arm manipulators.
  // NOTE: The following is the reference frame description of the world
  //       frame. The x-axis is into the page, z-axis is to the top of the
  //       page and the y-axis is to the left. At the zero angle, the links
  //       are parallel to the z-axis and face the +x-axis.

  // Create the world
  const double l1 = 1.5, l2 = 1.0;
  SkeletonPtr robot = createTwoLinkRobot(Vector3d(0.3, 0.3, l1), DOF_YAW,
                                         Vector3d(0.3, 0.3, l2), DOF_ROLL);

  // Set the test cases with the joint values and the expected end-effector
  // positions
  const std::size_t numTests = 2;
  double temp = sqrt(0.5*l2*l2);
  Vector2d joints [numTests] = { Vector2d( constantsd::pi()/4.0,  constantsd::pi()/2.0),
                                 Vector2d(-constantsd::pi()/4.0, -constantsd::pi()/4.0) };
  Vector3d expectedPos [numTests] = { Vector3d(temp, -temp, l1),
                                      Vector3d(temp / sqrt(2.0),
                                      temp / sqrt(2.0), l1+temp) };

  // Check each case by setting the joint values and obtaining the end-effector
  // position
  for (std::size_t i = 0; i < numTests; i++)
  {
    robot->setPositions(Eigen::VectorXd(joints[i]));
    BodyNode* bn = robot->getBodyNode("ee");
    Vector3d actual = bn->getTransform().translation();
    bool equality = equals(actual, expectedPos[i], 1e-3);
    EXPECT_TRUE(equality);
    if(!equality)
    {
      std::cout << "Joint values: " << joints[i].transpose() << std::endl;
      std::cout << "Actual pos: " << actual.transpose() << std::endl;
      std::cout << "Expected pos: " <<  expectedPos[i].transpose() << std::endl;
    }
  }
}
예제 #13
0
//==============================================================================
TEST(SdfParser, SDFSingleBodyWithoutJoint)
{
  // Regression test for #444
  WorldPtr world
      = SdfParser::readSdfFile(
            DART_DATA_PATH"/sdf/test/single_bodynode_skeleton.world");
  EXPECT_TRUE(world != nullptr);

  SkeletonPtr skel = world->getSkeleton(0);
  EXPECT_TRUE(skel != nullptr);
  EXPECT_EQ(skel->getNumBodyNodes(), 1u);
  EXPECT_EQ(skel->getNumJoints(), 1u);

  BodyNodePtr bodyNode = skel->getBodyNode(0);
  EXPECT_TRUE(bodyNode != nullptr);
  EXPECT_EQ(bodyNode->getNumVisualizationShapes(), 1u);
  EXPECT_EQ(bodyNode->getNumCollisionShapes(), 1u);

  JointPtr joint = skel->getJoint(0);
  EXPECT_TRUE(joint != nullptr);
  EXPECT_EQ(joint->getType(), FreeJoint::getStaticType());
}
예제 #14
0
TEST(Skeleton, NodePersistence)
{
  SkeletonPtr skel = Skeleton::create();
  skel->createJointAndBodyNodePair<FreeJoint>(nullptr);

  {
    EndEffector* manip =
        skel->getBodyNode(0)->createEndEffector(Entity::Properties("manip"));

    EXPECT_TRUE(skel->getEndEffector("manip") == manip);
    EXPECT_TRUE(skel->getEndEffector(0) == manip);
    EXPECT_TRUE(skel->getBodyNode(0)->getEndEffector(0) == manip);

    WeakEndEffectorPtr weakManip = manip;

    EXPECT_FALSE(weakManip.lock() == nullptr);

    manip->remove();

    // The Node has been removed, and no strong reference to it exists, so it
    // should be gone from the Skeleton
    EXPECT_TRUE(skel->getEndEffector("manip") == nullptr);
    EXPECT_TRUE(skel->getNumEndEffectors() == 0);
    EXPECT_TRUE(skel->getBodyNode(0)->getNumEndEffectors() == 0);

    EXPECT_TRUE(weakManip.lock() == nullptr);
  }

  {
    EndEffector* manip =
        skel->getBodyNode(0)->createEndEffector(Entity::Properties("manip"));

    EXPECT_TRUE(skel->getEndEffector("manip") == manip);
    EXPECT_TRUE(skel->getEndEffector(0) == manip);
    EXPECT_TRUE(skel->getBodyNode(0)->getEndEffector(0) == manip);

    EndEffectorPtr strongManip = manip;
    WeakEndEffectorPtr weakManip = strongManip;

    EXPECT_FALSE(weakManip.lock() == nullptr);

    manip->remove();

    // The Node has been removed, but a strong reference to it still exists, so
    // it will remain in the Skeleton for now
    EXPECT_TRUE(skel->getEndEffector("manip") == manip);
    EXPECT_TRUE(skel->getEndEffector(0) == manip);
    EXPECT_TRUE(skel->getBodyNode(0)->getEndEffector(0) == manip);

    EXPECT_FALSE(weakManip.lock() == nullptr);

    strongManip = nullptr;

    // The Node has been removed, and no strong reference to it exists any
    // longer, so it should be gone from the Skeleton
    EXPECT_TRUE(skel->getEndEffector("manip") == nullptr);
    EXPECT_TRUE(skel->getNumEndEffectors() == 0);
    EXPECT_TRUE(skel->getBodyNode(0)->getNumEndEffectors() == 0);

    EXPECT_TRUE(weakManip.lock() == nullptr);
  }
}
예제 #15
0
//==============================================================================
void ConstraintTest::SingleContactTest(const std::string& /*_fileName*/)
{
  using namespace std;
  using namespace Eigen;
  using namespace dart::math;
  using namespace dart::collision;
  using namespace dart::constraint;
  using namespace dart::dynamics;
  using namespace dart::simulation;
  using namespace dart::io;

  //----------------------------------------------------------------------------
  // Settings
  //----------------------------------------------------------------------------
  // Number of random state tests for each skeletons
#ifndef NDEBUG  // Debug mode
  // std::size_t testCount = 1;
#else
  // std::size_t testCount = 1;
#endif

  WorldPtr world = World::create();
  EXPECT_TRUE(world != nullptr);
  world->setGravity(Vector3d(0.0, -10.00, 0.0));
  world->setTimeStep(0.001);
  world->getConstraintSolver()->setCollisionDetector(
        DARTCollisionDetector::create());

  SkeletonPtr sphereSkel = createSphere(0.05, Vector3d(0.0, 1.0, 0.0));
  BodyNode* sphere = sphereSkel->getBodyNode(0);
  Joint* sphereJoint = sphere->getParentJoint();
  sphereJoint->setVelocity(3, Random::uniform(-2.0, 2.0));  // x-axis
  sphereJoint->setVelocity(5, Random::uniform(-2.0, 2.0));  // z-axis
  world->addSkeleton(sphereSkel);
  EXPECT_EQ(sphereSkel->getGravity(), world->getGravity());
  assert(sphere);

  SkeletonPtr boxSkel = createBox(Vector3d(1.0, 1.0, 1.0),
                                  Vector3d(0.0, 1.0, 0.0));
  BodyNode* box = boxSkel->getBodyNode(0);
  Joint* boxJoint = box->getParentJoint();
  boxJoint->setVelocity(3, Random::uniform(-2.0, 2.0));  // x-axis
  boxJoint->setVelocity(5, Random::uniform(-2.0, 2.0));  // z-axis
//  world->addSkeleton(boxSkel);
//  EXPECT_EQ(boxSkel->getGravity(), world->getGravity());
//  assert(box);

  SkeletonPtr groundSkel = createGround(Vector3d(10000.0, 0.1, 10000.0),
                                      Vector3d(0.0, -0.05, 0.0));
  groundSkel->setMobile(false);
  // BodyNode* ground = groundSkel->getBodyNode(0);
  world->addSkeleton(groundSkel);
  EXPECT_EQ(groundSkel->getGravity(), world->getGravity());
  // assert(ground);

  EXPECT_EQ((int)world->getNumSkeletons(), 2);

  // Lower and upper bound of configuration for system
  // double lb = -1.5 * constantsd::pi();
  // double ub =  1.5 * constantsd::pi();

  int maxSteps = 500;
  for (int i = 0; i < maxSteps; ++i)
  {
//    Vector3d pos1 = sphere->getWorldTransform().translation();
//    Vector3d vel1 = sphere->getWorldLinearVelocity(pos1);

//    std::cout << "pos1:" << pos1.transpose() << std::endl;
//    std::cout << "vel1:" << vel1.transpose() << std::endl;

    if (!world->checkCollision())
    {
      world->step();
      continue;
    }

    // for (std::size_t j = 0; j < cd->getNumContacts(); ++j)
    // {
      // Contact contact = cd->getContact(j);
      // Vector3d pos1 = sphere->getTransform().inverse() * contact.point;
      // Vector3d vel1 = sphere->getWorldLinearVelocity(pos1);

      // std::cout << "pos1:" << pos1.transpose() << std::endl;
      // std::cout << "vel1:" << vel1.transpose() << std::endl;
    // }

    world->step();

    const auto& result = world->getConstraintSolver()->getLastCollisionResult();

    for (const auto& contact : result.getContacts())
    {
      Vector3d pos1 = sphere->getTransform().inverse() * contact.point;
      Vector3d vel1 = sphere->getLinearVelocity(pos1);

//      std::cout << "pos1:" << pos1.transpose() << std::endl;

//      std::cout << "pos1[1]: " << pos1[1] << std::endl;

//      std::cout << "pos1:" << pos1.transpose() << std::endl;
      std::cout << "vel1:" << vel1.transpose() << ", pos1[1]: " << pos1[1] << std::endl;

//      EXPECT_NEAR(pos1[0], 0.0, 1e-9);
//      EXPECT_NEAR(pos1[1], -0.05, 1e-2);
//      EXPECT_NEAR(pos1[2], 0.0, 1e-9);

//      EXPECT_NEAR(vel1[0], 0.0, 1e-9);
//      EXPECT_NEAR(vel1[1], 0.0, 1e-9);
//      EXPECT_NEAR(vel1[2], 0.0, 1e-9);

//      if (!equals(vel1, Vector3d(0.0, 0.0, 0.0)))
//        std::cout << "vel1:" << vel1.transpose() << std::endl;

//      EXPECT_EQ(vel1, Vector3d::Zero());
    }

//    std::cout << std::endl;

    break;
  }
}
예제 #16
0
void setupEndEffectors(const SkeletonPtr& atlas)
{
  // Apply very small weights to the gradient of the root joint in order to
  // encourage the arms to use arm joints instead of only moving around the root
  // joint
  Eigen::VectorXd rootjoint_weights = Eigen::VectorXd::Ones(6);
  rootjoint_weights = 0.01*rootjoint_weights;

  // Setting the bounds to be infinite allows the end effector to be implicitly
  // unconstrained
  Eigen::Vector3d linearBounds =
      Eigen::Vector3d::Constant(std::numeric_limits<double>::infinity());

  Eigen::Vector3d angularBounds =
      Eigen::Vector3d::Constant(std::numeric_limits<double>::infinity());

  // -- Set up the left hand --

  // Create a relative transform for the EndEffector frame. This is the
  // transform that the left hand will have relative to the BodyNode that it is
  // attached to
  Eigen::Isometry3d tf_hand(Eigen::Isometry3d::Identity());
  tf_hand.translation() = Eigen::Vector3d(0.0009, 0.1254, 0.012);
  tf_hand.rotate(Eigen::AngleAxisd(90.0*M_PI/180.0, Eigen::Vector3d::UnitZ()));

  // Create the left hand's end effector and set its relative transform
  EndEffector* l_hand = atlas->getBodyNode("l_hand")->createEndEffector("l_hand");
  l_hand->setDefaultRelativeTransform(tf_hand, true);

  // Create an interactive frame to use as the target for the left hand
  osgDart::InteractiveFramePtr lh_target(new osgDart::InteractiveFrame(
                                           Frame::World(), "lh_target"));

  // Set the target of the left hand to the interactive frame. We pass true into
  // the function to tell it that it should create the IK module if it does not
  // already exist. If we don't do that, then calling getIK() could return a
  // nullptr if the IK module was never created.
  l_hand->getIK(true)->setTarget(lh_target);

  // Tell the left hand to use the whole body for its IK
  l_hand->getIK()->useWholeBody();

  // Set the weights for the gradient
  l_hand->getIK()->getGradientMethod().setComponentWeights(rootjoint_weights);

  // Set the bounds for the IK to be infinite so that the hands start out
  // unconstrained
  l_hand->getIK()->getErrorMethod().setLinearBounds(
        -linearBounds, linearBounds);

  l_hand->getIK()->getErrorMethod().setAngularBounds(
        -angularBounds, angularBounds);

  // -- Set up the right hand --

  // The orientation of the right hand frame is different than the left, so we
  // need to adjust the signs of the relative transform
  tf_hand.translation()[0] = -tf_hand.translation()[0];
  tf_hand.translation()[1] = -tf_hand.translation()[1];
  tf_hand.linear() = tf_hand.linear().inverse();

  // Create the right hand's end effector and set its relative transform
  EndEffector* r_hand = atlas->getBodyNode("r_hand")->createEndEffector("r_hand");
  r_hand->setDefaultRelativeTransform(tf_hand, true);

  // Create an interactive frame to use as the target for the right hand
  osgDart::InteractiveFramePtr rh_target(new osgDart::InteractiveFrame(
                                           Frame::World(), "rh_target"));

  // Create the right hand's IK and set its target
  r_hand->getIK(true)->setTarget(rh_target);

  // Tell the right hand to use the whole body for its IK
  r_hand->getIK()->useWholeBody();

  // Set the weights for the gradient
  r_hand->getIK()->getGradientMethod().setComponentWeights(rootjoint_weights);

  // Set the bounds for the IK to be infinite so that the hands start out
  // unconstrained
  r_hand->getIK()->getErrorMethod().setLinearBounds(
        -linearBounds, linearBounds);

  r_hand->getIK()->getErrorMethod().setAngularBounds(
        -angularBounds, angularBounds);


  // Define the support geometry for the feet. These points will be used to
  // compute the convex hull of the robot's support polygon
  dart::math::SupportGeometry support;
  const double sup_pos_x =  0.10-0.186;
  const double sup_neg_x = -0.03-0.186;
  const double sup_pos_y =  0.03;
  const double sup_neg_y = -0.03;
  support.push_back(Eigen::Vector3d(sup_neg_x, sup_neg_y, 0.0));
  support.push_back(Eigen::Vector3d(sup_pos_x, sup_neg_y, 0.0));
  support.push_back(Eigen::Vector3d(sup_pos_x, sup_pos_y, 0.0));
  support.push_back(Eigen::Vector3d(sup_neg_x, sup_pos_y, 0.0));

  // Create a relative transform that goes from the center of the feet to the
  // bottom of the feet
  Eigen::Isometry3d tf_foot(Eigen::Isometry3d::Identity());
  tf_foot.translation() = Eigen::Vector3d(0.186, 0.0, -0.08);

  // Constrain the feet to snap to the ground
  linearBounds[2] = 1e-8;

  // Constrain the feet to lie flat on the ground
  angularBounds[0] = 1e-8;
  angularBounds[1] = 1e-8;

  // Create an end effector for the left foot and set its relative transform
  EndEffector* l_foot = atlas->getBodyNode("l_foot")->createEndEffector("l_foot");
  l_foot->setRelativeTransform(tf_foot);

  // Create an interactive frame to use as the target for the left foot
  osgDart::InteractiveFramePtr lf_target(new osgDart::InteractiveFrame(
                                           Frame::World(), "lf_target"));

  // Create the left foot's IK and set its target
  l_foot->getIK(true)->setTarget(lf_target);

  // Set the left foot's IK hierarchy level to 1. This will project its IK goals
  // through the null space of any IK modules that are on level 0. This means
  // that it will try to accomplish its goals while also accommodating the goals
  // of other modules.
  l_foot->getIK()->setHierarchyLevel(1);

  // Use the bounds defined above
  l_foot->getIK()->getErrorMethod().setLinearBounds(
        -linearBounds, linearBounds);
  l_foot->getIK()->getErrorMethod().setAngularBounds(
        -angularBounds, angularBounds);

  // Create Support for the foot and give it geometry
  l_foot->getSupport(true)->setGeometry(support);

  // Turn on support mode so that it can be used as a foot
  l_foot->getSupport()->setActive();

  // Create an end effector for the right foot and set its relative transform
  EndEffector* r_foot = atlas->getBodyNode("r_foot")->createEndEffector("r_foot");
  r_foot->setRelativeTransform(tf_foot);

  // Create an interactive frame to use as the target for the right foot
  osgDart::InteractiveFramePtr rf_target(new osgDart::InteractiveFrame(
                                           Frame::World(), "rf_target"));

  // Create the right foot's IK module and set its target
  r_foot->getIK(true)->setTarget(rf_target);

  // Set the right foot's IK hierarchy level to 1
  r_foot->getIK()->setHierarchyLevel(1);

  // Use the bounds defined above
  r_foot->getIK()->getErrorMethod().setLinearBounds(
        -linearBounds, linearBounds);
  r_foot->getIK()->getErrorMethod().setAngularBounds(
        -angularBounds, angularBounds);

  // Create Support for the foot and give it geometry
  r_foot->getSupport(true)->setGeometry(support);

  // Turn on support mode so that it can be used as a foot
  r_foot->getSupport()->setActive();

  // Move atlas to the ground so that it starts out squatting with its feet on
  // the ground
  double heightChange = -r_foot->getWorldTransform().translation()[2];
  atlas->getDof(5)->setPosition(heightChange);

  // Now that the feet are on the ground, we should set their target transforms
  l_foot->getIK()->getTarget()->setTransform(l_foot->getTransform());
  r_foot->getIK()->getTarget()->setTransform(r_foot->getTransform());
}
예제 #17
0
//==============================================================================
TEST(NameManagement, Skeleton)
{
  SkeletonPtr skel = Skeleton::create();

  std::pair<Joint*, BodyNode*> pair;
  pair = skel->createJointAndBodyNodePair<RevoluteJoint>(
        nullptr, SingleDofJoint::Properties(std::string("joint")));
  Joint* joint1 = pair.first;
  BodyNode* body1 = pair.second;

  pair = skel->createJointAndBodyNodePair<TranslationalJoint>(
        body1, MultiDofJoint<3>::Properties(std::string("joint")));
  Joint* joint2 = pair.first;
  BodyNode* body2 = pair.second;

  pair = skel->createJointAndBodyNodePair<FreeJoint>(
        body2, MultiDofJoint<6>::Properties(std::string("joint")));
  Joint* joint3 = pair.first;
  BodyNode* body3 = pair.second;

  // Testing whether the repeated names of BodyNodes and Joints get resolved
  // correctly as BodyNodes get added to the Skeleton
  EXPECT_FALSE(body1->getName() == body2->getName());
  EXPECT_FALSE(body2->getName() == body3->getName());
  EXPECT_FALSE(body3->getName() == body1->getName());

  EXPECT_FALSE(joint1->getName() == joint2->getName());
  EXPECT_FALSE(joint2->getName() == joint3->getName());
  EXPECT_FALSE(joint3->getName() == joint1->getName());

  EXPECT_TRUE(joint1->getDof(0)->getName() == "joint");

  EXPECT_TRUE(joint2->getDof(0)->getName() == "joint(1)_x");
  EXPECT_TRUE(joint2->getDof(1)->getName() == "joint(1)_y");
  EXPECT_TRUE(joint2->getDof(2)->getName() == "joint(1)_z");

  EXPECT_TRUE(joint3->getDof(0)->getName() == "joint(2)_rot_x");
  EXPECT_TRUE(joint3->getDof(1)->getName() == "joint(2)_rot_y");
  EXPECT_TRUE(joint3->getDof(2)->getName() == "joint(2)_rot_z");
  EXPECT_TRUE(joint3->getDof(3)->getName() == "joint(2)_pos_x");
  EXPECT_TRUE(joint3->getDof(4)->getName() == "joint(2)_pos_y");
  EXPECT_TRUE(joint3->getDof(5)->getName() == "joint(2)_pos_z");

  // Testing whether the repeated names of BodyNodes get resolved correctly
  // as they are changed with BodyNode::setName(~)
  std::string newname1 = body1->setName("same_name");
  std::string newname2 = body2->setName("same_name");
  std::string newname3 = body3->setName("same_name");

  EXPECT_FALSE(body1->getName() == body2->getName());
  EXPECT_FALSE(body2->getName() == body3->getName());
  EXPECT_FALSE(body3->getName() == body1->getName());

  EXPECT_TRUE(body1->getName() == newname1);
  EXPECT_TRUE(body2->getName() == newname2);
  EXPECT_TRUE(body3->getName() == newname3);

  EXPECT_TRUE(skel->getBodyNode(newname1) == body1);
  EXPECT_TRUE(skel->getBodyNode(newname2) == body2);
  EXPECT_TRUE(skel->getBodyNode(newname3) == body3);

  // Testing whether the repeated names of Joints get resolved correctly
  // as they are changed with Joint::setName(~)
  newname1 = joint1->setName("another_name");
  newname2 = joint2->setName("another_name");
  newname3 = joint3->setName("another_name");

  EXPECT_FALSE(joint1->getName() == joint2->getName());
  EXPECT_FALSE(joint2->getName() == joint3->getName());
  EXPECT_FALSE(joint3->getName() == joint1->getName());

  EXPECT_TRUE(joint1->getName() == newname1);
  EXPECT_TRUE(joint2->getName() == newname2);
  EXPECT_TRUE(joint3->getName() == newname3);

  EXPECT_TRUE(skel->getJoint(newname1) == joint1);
  EXPECT_TRUE(skel->getJoint(newname2) == joint2);
  EXPECT_TRUE(skel->getJoint(newname3) == joint3);

  // Testing whether unique names get accidentally changed by the NameManager
  std::string unique_name = body2->setName("a_unique_name");
  EXPECT_TRUE(body2->getName() == unique_name);
  EXPECT_TRUE(body2->getName() == "a_unique_name");
  EXPECT_TRUE(skel->getBodyNode("a_unique_name") == body2);

  EXPECT_FALSE(body1->getName() == body2->getName());
  EXPECT_FALSE(body2->getName() == body3->getName());
  EXPECT_FALSE(body3->getName() == body1->getName());

  unique_name = joint3->setName("a_unique_name");
  EXPECT_TRUE(joint3->getName() == unique_name);
  EXPECT_TRUE(joint3->getName() == "a_unique_name");
  EXPECT_TRUE(skel->getJoint("a_unique_name") == joint3);

  // Testing whether the DegreeOfFreedom names get updated correctly upon their
  // joint's name change
  EXPECT_TRUE(joint3->getDof(0)->getName() == "a_unique_name_rot_x");
  EXPECT_TRUE(joint3->getDof(1)->getName() == "a_unique_name_rot_y");
  EXPECT_TRUE(joint3->getDof(2)->getName() == "a_unique_name_rot_z");
  EXPECT_TRUE(joint3->getDof(3)->getName() == "a_unique_name_pos_x");
  EXPECT_TRUE(joint3->getDof(4)->getName() == "a_unique_name_pos_y");
  EXPECT_TRUE(joint3->getDof(5)->getName() == "a_unique_name_pos_z");

  EXPECT_TRUE(joint3->getDof(0) == skel->getDof("a_unique_name_rot_x"));
  EXPECT_TRUE(joint3->getDof(3) == skel->getDof("a_unique_name_pos_x"));

  // Note: The following assumes the joint order in the Skeleton is:
  // RevoluteJoint -> TranslationalJoint -> FreeJoint
  EXPECT_TRUE(joint1->getDof(0) == skel->getDof(0));

  EXPECT_TRUE(joint2->getDof(0) == skel->getDof(1));
  EXPECT_TRUE(joint2->getDof(1) == skel->getDof(2));
  EXPECT_TRUE(joint2->getDof(2) == skel->getDof(3));

  EXPECT_TRUE(joint3->getDof(0) == skel->getDof(4));
  EXPECT_TRUE(joint3->getDof(1) == skel->getDof(5));
  EXPECT_TRUE(joint3->getDof(2) == skel->getDof(6));
  EXPECT_TRUE(joint3->getDof(3) == skel->getDof(7));
  EXPECT_TRUE(joint3->getDof(4) == skel->getDof(8));
  EXPECT_TRUE(joint3->getDof(5) == skel->getDof(9));

  // Test whether the return of getIndexInSkeleton() and the index of the
  // corresponding DegreeOfFreedom in the Skeleton are same
  for (size_t i = 0; i < skel->getNumDofs(); ++i)
    EXPECT_TRUE(skel->getDof(i)->getIndexInSkeleton() == i);

  // Test whether all the joint names are still unique
  EXPECT_FALSE(joint1->getName() == joint2->getName());
  EXPECT_FALSE(joint2->getName() == joint3->getName());
  EXPECT_FALSE(joint3->getName() == joint1->getName());

  // Make sure that the Skeleton gives back nullptr for non existent names
  EXPECT_TRUE(skel->getBodyNode("nonexistent_name") == nullptr);
  EXPECT_TRUE(skel->getJoint("nonexistent_name") == nullptr);
  EXPECT_TRUE(skel->getSoftBodyNode("nonexistent_name") == nullptr);
}
예제 #18
0
TEST(Skeleton, Restructuring)
{
  std::vector<SkeletonPtr> skeletons = getSkeletons();

#ifndef NDEBUG
  size_t numIterations = 10;
#else
  size_t numIterations = 2*skeletons.size();
#endif

  // Test moves within the current Skeleton
  for(size_t i=0; i<numIterations; ++i)
  {
    size_t index = floor(math::random(0, skeletons.size()));
    index = std::min(index, skeletons.size()-1);
    SkeletonPtr skeleton = skeletons[index];
    SkeletonPtr original = skeleton->clone();

    size_t maxNode = skeleton->getNumBodyNodes()-1;
    BodyNode* bn1 = skeleton->getBodyNode(floor(math::random(0, maxNode)));
    BodyNode* bn2 = skeleton->getBodyNode(ceil(math::random(0, maxNode)));

    if(bn1 == bn2)
    {
      --i;
      continue;
    }

    BodyNode* child = bn1->descendsFrom(bn2)? bn1 : bn2;
    BodyNode* parent = child == bn1? bn2 : bn1;

    child->moveTo(parent);

    EXPECT_TRUE(skeleton->getNumBodyNodes() == original->getNumBodyNodes());
    if(skeleton->getNumBodyNodes() == original->getNumBodyNodes())
    {
      for(size_t j=0; j<skeleton->getNumBodyNodes(); ++j)
      {
        // Make sure no BodyNodes have been lost or gained in translation
        std::string name = original->getBodyNode(j)->getName();
        BodyNode* bn = skeleton->getBodyNode(name);
        EXPECT_FALSE(bn == nullptr);
        if(bn)
          EXPECT_TRUE(bn->getName() == name);

        name = skeleton->getBodyNode(j)->getName();
        bn = original->getBodyNode(name);
        EXPECT_FALSE(bn == nullptr);
        if(bn)
          EXPECT_TRUE(bn->getName() == name);


        // Make sure no Joints have been lost or gained in translation
        name = original->getJoint(j)->getName();
        Joint* joint = skeleton->getJoint(name);
        EXPECT_FALSE(joint == nullptr);
        if(joint)
          EXPECT_TRUE(joint->getName() == name);

        name = skeleton->getJoint(j)->getName();
        joint = original->getJoint(name);
        EXPECT_FALSE(joint == nullptr);
        if(joint)
          EXPECT_TRUE(joint->getName() == name);
      }
    }

    EXPECT_TRUE(skeleton->getNumDofs() == original->getNumDofs());
    for(size_t j=0; j<skeleton->getNumDofs(); ++j)
    {
      std::string name = original->getDof(j)->getName();
      DegreeOfFreedom* dof = skeleton->getDof(name);
      EXPECT_FALSE(dof == nullptr);
      if(dof)
        EXPECT_TRUE(dof->getName() == name);

      name = skeleton->getDof(j)->getName();
      dof = original->getDof(name);
      EXPECT_FALSE(dof == nullptr);
      if(dof)
        EXPECT_TRUE(dof->getName() == name);
    }
  }

  // Test moves between Skeletons
  for(size_t i=0; i<numIterations; ++i)
  {
    size_t fromIndex = floor(math::random(0, skeletons.size()));
    fromIndex = std::min(fromIndex, skeletons.size()-1);
    SkeletonPtr fromSkel = skeletons[fromIndex];

    if(fromSkel->getNumBodyNodes() == 0)
    {
      --i;
      continue;
    }

    size_t toIndex = floor(math::random(0, skeletons.size()));
    toIndex = std::min(toIndex, skeletons.size()-1);
    SkeletonPtr toSkel = skeletons[toIndex];

    if(toSkel->getNumBodyNodes() == 0)
    {
      --i;
      continue;
    }

    BodyNode* childBn = fromSkel->getBodyNode(
          floor(math::random(0, fromSkel->getNumBodyNodes()-1)));
    BodyNode* parentBn = toSkel->getBodyNode(
          floor(math::random(0, toSkel->getNumBodyNodes()-1)));

    if(fromSkel == toSkel)
    {
      if(childBn == parentBn)
      {
        --i;
        continue;
      }

      if(parentBn->descendsFrom(childBn))
      {
        BodyNode* tempBn = childBn;
        childBn = parentBn;
        parentBn = tempBn;

        SkeletonPtr tempSkel = fromSkel;
        fromSkel = toSkel;
        toSkel = tempSkel;
      }
    }

    BodyNode* originalParent = childBn->getParentBodyNode();
    std::vector<BodyNode*> subtree;
    constructSubtree(subtree, childBn);

    // Move to a new Skeleton
    childBn->moveTo(parentBn);

    // Make sure all the objects have moved
    for(size_t j=0; j<subtree.size(); ++j)
    {
      BodyNode* bn = subtree[j];
      EXPECT_TRUE(bn->getSkeleton() == toSkel);
    }

    // Move to the Skeleton's root while producing a new Joint type
    sub_ptr<Joint> originalJoint = childBn->getParentJoint();
    childBn->moveTo<FreeJoint>(nullptr);

    // The original parent joint should be deleted now
    EXPECT_TRUE(originalJoint == nullptr);

    // The BodyNode should now be a root node
    EXPECT_TRUE(childBn->getParentBodyNode() == nullptr);

    // The subtree should still be in the same Skeleton
    for(size_t j=0; j<subtree.size(); ++j)
    {
      BodyNode* bn = subtree[j];
      EXPECT_TRUE(bn->getSkeleton() == toSkel);
    }

    // Create some new Skeletons and mangle them all up

    childBn->copyTo<RevoluteJoint>(fromSkel, originalParent);

    SkeletonPtr temporary = childBn->split("temporary");
    SkeletonPtr other_temporary =
        childBn->split<PrismaticJoint>("other temporary");
    SkeletonPtr another_temporary = childBn->copyAs("another temporary");
    SkeletonPtr last_temporary = childBn->copyAs<ScrewJoint>("last temporary");

    childBn->copyTo(another_temporary->getBodyNode(
                      another_temporary->getNumBodyNodes()-1));
    childBn->copyTo<PlanarJoint>(another_temporary->getBodyNode(0));
    childBn->copyTo<TranslationalJoint>(temporary, nullptr);
    childBn->moveTo(last_temporary,
        last_temporary->getBodyNode(last_temporary->getNumBodyNodes()-1));
    childBn->moveTo<BallJoint>(last_temporary, nullptr);
    childBn->moveTo<EulerJoint>(last_temporary,
                                last_temporary->getBodyNode(0));
    childBn->changeParentJointType<FreeJoint>();

    // Test the non-recursive copying
    if(toSkel->getNumBodyNodes() > 1)
    {
      SkeletonPtr singleBodyNode =
          toSkel->getBodyNode(0)->copyAs("single", false);
      EXPECT_TRUE(singleBodyNode->getNumBodyNodes() == 1);

      std::pair<Joint*, BodyNode*> singlePair =
          toSkel->getBodyNode(0)->copyTo(nullptr, false);
      EXPECT_TRUE(singlePair.second->getNumChildBodyNodes() == 0);
    }

    // Check that the mangled Skeletons are all self-consistent
    check_self_consistency(fromSkel);
    check_self_consistency(toSkel);
    check_self_consistency(temporary);
    check_self_consistency(other_temporary);
    check_self_consistency(another_temporary);
    check_self_consistency(last_temporary);
  }
}
예제 #19
0
TEST(Skeleton, Group)
{
  SkeletonPtr skel = constructLinkageTestSkeleton();

  // Make twice as many BodyNodes in the Skeleton
  SkeletonPtr skel2 = constructLinkageTestSkeleton();
  skel2->getRootBodyNode()->moveTo(skel, nullptr);

  // Test nullptr construction
  GroupPtr nullGroup = Group::create("null_group", nullptr);
  EXPECT_EQ(nullGroup->getNumBodyNodes(), 0u);
  EXPECT_EQ(nullGroup->getNumJoints(), 0u);
  EXPECT_EQ(nullGroup->getNumDofs(), 0u);

  // Test conversion from Skeleton
  GroupPtr skel1Group = Group::create("skel1_group", skel);
  EXPECT_EQ(skel1Group->getNumBodyNodes(), skel->getNumBodyNodes());
  EXPECT_EQ(skel1Group->getNumJoints(), skel->getNumJoints());
  EXPECT_EQ(skel1Group->getNumDofs(), skel->getNumDofs());

  for(size_t i=0; i < skel1Group->getNumBodyNodes(); ++i)
    EXPECT_EQ(skel1Group->getBodyNode(i), skel->getBodyNode(i));

  for(size_t i=0; i < skel1Group->getNumJoints(); ++i)
    EXPECT_EQ(skel1Group->getJoint(i), skel->getJoint(i));

  for(size_t i=0; i < skel1Group->getNumDofs(); ++i)
    EXPECT_EQ(skel1Group->getDof(i), skel->getDof(i));

  // Test arbitrary Groups by plucking random BodyNodes, Joints, and
  // DegreesOfFreedom from a Skeleton.
  GroupPtr group = Group::create();
  std::vector<BodyNode*> bodyNodes;
  std::vector<Joint*> joints;
  std::vector<DegreeOfFreedom*> dofs;
  for(size_t i=0; i < 2*skel->getNumBodyNodes(); ++i)
  {
    size_t randomIndex = floor(random(0, skel->getNumBodyNodes()));
    BodyNode* bn = skel->getBodyNode(randomIndex);
    if(group->addBodyNode(bn, false))
      bodyNodes.push_back(bn);

    randomIndex = floor(random(0, skel->getNumJoints()));
    Joint* joint = skel->getJoint(randomIndex);
    if(group->addJoint(joint, false, false))
      joints.push_back(joint);

    randomIndex = floor(random(0, skel->getNumDofs()));
    DegreeOfFreedom* dof = skel->getDof(randomIndex);
    if(group->addDof(dof, false, false))
      dofs.push_back(dof);
  }

  EXPECT_EQ(group->getNumBodyNodes(), bodyNodes.size());
  EXPECT_EQ(group->getNumJoints(), joints.size());
  EXPECT_EQ(group->getNumDofs(), dofs.size());

  for(size_t i=0; i < group->getNumBodyNodes(); ++i)
    EXPECT_EQ(group->getBodyNode(i), bodyNodes[i]);

  for(size_t i=0; i < group->getNumJoints(); ++i)
    EXPECT_EQ(group->getJoint(i), joints[i]);

  for(size_t i=0; i < group->getNumDofs(); ++i)
    EXPECT_EQ(group->getDof(i), dofs[i]);
}
예제 #20
0
TEST(Skeleton, Linkage)
{
  // Test a variety of uses of Linkage::Criteria
  SkeletonPtr skel = constructLinkageTestSkeleton();

  BranchPtr subtree = Branch::create(skel->getBodyNode("c3b3"), "subtree");
  checkForBodyNodes(subtree, skel, true,
                    "c3b3", "c3b4", "c4b1", "c4b2", "c4b3");

  ChainPtr midchain = Chain::create(skel->getBodyNode("c1b3"),
                 skel->getBodyNode("c3b4"), "midchain");
  checkForBodyNodes(midchain, skel, true, "c3b1", "c3b2", "c3b3");
  checkLinkageJointConsistency(midchain);

  Linkage::Criteria criteria;
  criteria.mStart = skel->getBodyNode("c5b2");
  criteria.mTargets.push_back(
        Linkage::Criteria::Target(skel->getBodyNode("c4b3")));
  LinkagePtr path = Linkage::create(criteria, "path");
  checkForBodyNodes(path, skel, true, "c5b2", "c5b1", "c1b3", "c3b1", "c3b2",
                                      "c3b3", "c4b1", "c4b2", "c4b3");
  checkLinkageJointConsistency(path);

  skel->getBodyNode(0)->copyTo(nullptr);
  criteria.mTargets.clear();
  criteria.mStart = skel->getBodyNode("c3b1");
  criteria.mStart.mPolicy = Linkage::Criteria::UPSTREAM;
  criteria.mTargets.push_back(
        Linkage::Criteria::Target(skel->getBodyNode("c3b1(1)"),
                                  Linkage::Criteria::UPSTREAM));

  LinkagePtr combinedTreeBases = Linkage::create(criteria, "combinedTreeBases");
  checkForBodyNodes(combinedTreeBases, skel, true,
                    "c3b1",    "c1b3",    "c2b1",    "c2b2",    "c2b3",
                    "c3b1(1)", "c1b3(1)", "c2b1(1)", "c2b2(1)", "c2b3(1)",
                    "c5b1",    "c5b2",    "c1b2",    "c1b1",
                    "c5b1(1)", "c5b2(1)", "c1b2(1)", "c1b1(1)");
  checkLinkageJointConsistency(combinedTreeBases);

  SkeletonPtr skel2 = skel->getBodyNode(0)->copyAs("skel2");
  criteria.mTargets.clear();
  criteria.mTargets.push_back(
        Linkage::Criteria::Target(skel2->getBodyNode("c3b1"),
                                  Linkage::Criteria::UPSTREAM));
  LinkagePtr combinedSkelBases = Linkage::create(criteria, "combinedSkelBases");
  size_t count = 0;
  count += checkForBodyNodes(combinedSkelBases, skel, false,
                             "c3b1", "c1b3", "c2b1", "c2b2", "c2b3",
                             "c5b1", "c5b2", "c1b2", "c1b1");
  count += checkForBodyNodes(combinedSkelBases, skel2, false,
                             "c3b1", "c1b3", "c2b1", "c2b2", "c2b3",
                             "c5b1", "c5b2", "c1b2", "c1b1");
  EXPECT_TRUE( count == combinedSkelBases->getNumBodyNodes() );

  ChainPtr downstreamFreeJoint = Chain::create(skel->getBodyNode("c1b1"),
      skel->getBodyNode("c1b3"), Chain::IncludeBoth, "downstreamFreeJoint");
  checkForBodyNodes(downstreamFreeJoint, skel, true, "c1b1");
  checkLinkageJointConsistency(downstreamFreeJoint);

  ChainPtr emptyChain = Chain::create(skel->getBodyNode("c1b1"),
      skel->getBodyNode("c1b3"), "emptyChain");
  checkForBodyNodes(emptyChain, skel, true);
  checkLinkageJointConsistency(emptyChain);

  ChainPtr chainFromNull = Chain::create(nullptr, skel->getBodyNode("c1b2"),
                                         "chainFromNull");
  checkForBodyNodes(chainFromNull, skel, true, "c1b1");
  checkLinkageJointConsistency(chainFromNull);

  ChainPtr upstreamFreeJoint = Chain::create(skel->getBodyNode("c1b3"),
                          skel->getBodyNode("c1b1"), "upstreamFreeJoint");
  checkForBodyNodes(upstreamFreeJoint, skel, true, "c1b3", "c1b2");
  checkLinkageJointConsistency(upstreamFreeJoint);

  // Using nullptr as the target should bring us towards the root of the tree
  ChainPtr upTowardsRoot =
      Chain::create(skel->getBodyNode("c1b3"), nullptr, "upTowardsRoot");
  checkForBodyNodes(upTowardsRoot, skel, true, "c1b3", "c1b2");
  checkLinkageJointConsistency(upTowardsRoot);

  criteria.mTargets.clear();
  criteria.mTargets.push_back(skel->getBodyNode("c4b3"));
  criteria.mStart = skel->getBodyNode("c1b3");
  criteria.mTerminals.push_back(skel->getBodyNode("c3b2"));
  LinkagePtr terminatedLinkage = Linkage::create(criteria, "terminatedLinkage");
  checkForBodyNodes(terminatedLinkage, skel, true,
                    "c1b3", "c3b1", "c3b2");
  checkLinkageJointConsistency(terminatedLinkage);

  criteria.mStart = skel->getBodyNode("c1b1");
  criteria.mStart.mPolicy = Linkage::Criteria::DOWNSTREAM;
  criteria.mTargets.clear();
  criteria.mTerminals.clear();
  criteria.mTerminals.push_back(
        Linkage::Criteria::Terminal(skel->getBodyNode("c2b1"), false));
  criteria.mTerminals.push_back(skel->getBodyNode("c3b3"));
  LinkagePtr terminatedSubtree = Linkage::create(criteria, "terminatedSubtree");
  checkForBodyNodes(terminatedSubtree, skel, true,
                    "c1b1", "c1b2", "c1b3", "c5b1",
                    "c5b2", "c3b1", "c3b2", "c3b3");
  checkLinkageJointConsistency(terminatedSubtree);

  criteria.mStart.mPolicy = Linkage::Criteria::UPSTREAM;
  criteria.mStart.mNode = skel->getBodyNode("c3b1");
  LinkagePtr terminatedUpstream = Linkage::create(criteria, "terminatedUpstream");
  checkForBodyNodes(terminatedUpstream, skel, true,
                    "c3b1", "c1b3", "c5b1", "c5b2", "c1b2", "c1b1");
  checkLinkageJointConsistency(terminatedUpstream);
}
예제 #21
0
TEST(Skeleton, Persistence)
{
  WeakBodyNodePtr weakBnPtr;
  SoftBodyNodePtr softBnPtr;
  WeakSoftBodyNodePtr weakSoftBnPtr;
  WeakSkeletonPtr weakSkelPtr;
  {
    BodyNodePtr strongPtr;
    {
      {
        SkeletonPtr skeleton = createThreeLinkRobot(
              Eigen::Vector3d(1.0, 1.0, 1.0), DOF_X,
              Eigen::Vector3d(1.0, 1.0, 1.0), DOF_Y,
              Eigen::Vector3d(1.0, 1.0, 1.0), DOF_Z);
        weakSkelPtr = skeleton;

        // Test usability of the BodyNodePtr
        strongPtr = skeleton->getBodyNode(0);
        weakBnPtr = strongPtr;
        ConstBodyNodePtr constPtr = strongPtr;

        EXPECT_FALSE( strongPtr == nullptr );
        EXPECT_FALSE( nullptr == strongPtr );

        EXPECT_TRUE( strongPtr == skeleton->getBodyNode(0) );
        EXPECT_TRUE( skeleton->getBodyNode(0) == strongPtr );
        EXPECT_TRUE( constPtr == strongPtr );
        EXPECT_TRUE( weakBnPtr.lock() == strongPtr );

        EXPECT_FALSE( strongPtr < constPtr );
        EXPECT_FALSE( strongPtr < skeleton->getBodyNode(0) );
        EXPECT_FALSE( strongPtr < weakBnPtr.lock() );
        EXPECT_FALSE( skeleton->getBodyNode(0) < strongPtr );
        EXPECT_FALSE( weakBnPtr.lock() < strongPtr);

        EXPECT_FALSE( strongPtr > constPtr );
        EXPECT_FALSE( strongPtr > skeleton->getBodyNode(0) );
        EXPECT_FALSE( strongPtr > weakBnPtr.lock() );
        EXPECT_FALSE( skeleton->getBodyNode(0) > strongPtr );
        EXPECT_FALSE( weakBnPtr.lock() > strongPtr );

        BodyNodePtr tail = skeleton->getBodyNode(skeleton->getNumBodyNodes()-1);
        std::pair<Joint*, SoftBodyNode*> pair =
            skeleton->createJointAndBodyNodePair<RevoluteJoint, SoftBodyNode>(
              tail);

        softBnPtr = pair.second;
        weakSoftBnPtr = softBnPtr;
        WeakBodyNodePtr otherWeakPtr = weakSoftBnPtr; // Test convertability

        // Test usability of the DegreeOfFreedomPtr
        DegreeOfFreedomPtr dof = skeleton->getDof(1);
        WeakDegreeOfFreedomPtr weakdof = dof;
        ConstDegreeOfFreedomPtr const_dof = dof;
        WeakConstDegreeOfFreedomPtr const_weakdof = weakdof;
        const_weakdof = const_dof;

        EXPECT_TRUE( dof == skeleton->getDof(1) );
        EXPECT_TRUE( dof == const_dof );
        EXPECT_TRUE( weakdof.lock() == const_weakdof.lock() );
        EXPECT_TRUE( const_weakdof.lock() == skeleton->getDof(1) );
        EXPECT_TRUE( skeleton->getDof(1) == const_weakdof.lock() );

        EXPECT_FALSE( dof < const_dof );
        EXPECT_FALSE( dof < skeleton->getDof(1) );
        EXPECT_FALSE( dof < weakdof.lock() );
        EXPECT_FALSE( skeleton->getDof(1) < dof );
        EXPECT_FALSE( weakdof.lock() < dof );

        EXPECT_FALSE( dof > const_dof );
        EXPECT_FALSE( dof > skeleton->getDof(1) );
        EXPECT_FALSE( dof > weakdof.lock() );
        EXPECT_FALSE( skeleton->getDof(1) > dof );
        EXPECT_FALSE( weakdof.lock() > dof );

        dof = nullptr;
        weakdof = nullptr;
        const_dof = nullptr;
        const_weakdof = nullptr;

        EXPECT_TRUE( dof == nullptr );
        EXPECT_TRUE( nullptr == dof );
        EXPECT_TRUE( weakdof.lock() == nullptr );
        EXPECT_TRUE( nullptr == weakdof.lock() );
        EXPECT_TRUE( const_dof == nullptr );
        EXPECT_TRUE( const_weakdof.lock() == nullptr );

        EXPECT_FALSE( dof < const_dof );

        // Test usability of the JointPtr
        JointPtr joint = skeleton->getJoint(1);
        WeakJointPtr weakjoint = joint;
        ConstJointPtr const_joint = joint;
        WeakConstJointPtr const_weakjoint = const_joint;

        EXPECT_TRUE( joint == skeleton->getJoint(1) );
        EXPECT_TRUE( joint == const_joint );
        EXPECT_TRUE( weakjoint.lock() == const_weakjoint.lock() );
        EXPECT_TRUE( const_weakjoint.lock() == skeleton->getJoint(1) );

        EXPECT_FALSE( joint < const_joint );
        EXPECT_FALSE( joint < skeleton->getJoint(1) );
        EXPECT_FALSE( joint < weakjoint.lock() );
        EXPECT_FALSE( skeleton->getJoint(1) < joint );
        EXPECT_FALSE( weakjoint.lock() < joint );

        EXPECT_FALSE( joint > const_joint );
        EXPECT_FALSE( joint > skeleton->getJoint(1) );
        EXPECT_FALSE( joint > weakjoint.lock() );
        EXPECT_FALSE( skeleton->getJoint(1) > joint );
        EXPECT_FALSE( weakjoint.lock() > joint );

        joint = nullptr;
        weakjoint = nullptr;
        const_joint = nullptr;
        const_weakjoint = nullptr;

        EXPECT_TRUE( joint == nullptr );
        EXPECT_TRUE( weakjoint.lock() == nullptr );
        EXPECT_TRUE( const_joint == nullptr );
        EXPECT_TRUE( const_weakjoint.lock() == nullptr );
      }

      // The BodyNode should still be alive, because a BodyNodePtr still
      // references it
      EXPECT_FALSE(weakBnPtr.expired());

      // The Skeleton should still be alive, because a BodyNodePtr still
      // references one of its BodyNodes
      EXPECT_FALSE(weakSkelPtr.lock() == nullptr);

      // Take the BodyNode out of its Skeleton and put it into a temporary one
      strongPtr->remove();

      // The BodyNode should still be alive, because a BodyNodePtr still
      // references it
      EXPECT_FALSE(weakBnPtr.expired());

      // The Skeleton should be destroyed, because it lost the only BodyNode
      // that still had a reference
      EXPECT_TRUE(weakSkelPtr.lock() == nullptr);

      // Update the weakSkelPtr so it references the Skeleton that still exists
      weakSkelPtr = strongPtr->getSkeleton();
      EXPECT_FALSE(weakSkelPtr.lock() == nullptr);

      // Change the BodyNode that this BodyNodePtr is referencing
      strongPtr = strongPtr->getChildBodyNode(0);

      // Make sure the Skeleton is still alive. If the SkeletonPtr being used
      // by the BodyNodePtr is not swapped atomically, then this will fail,
      // which means we cannot rely on BodyNodePtr to keep BodyNodes alive.
      EXPECT_FALSE(weakSkelPtr.lock() == nullptr);
    }

    SkeletonPtr other_skeleton = createThreeLinkRobot(
          Eigen::Vector3d(1.0, 1.0, 1.0), DOF_X,
          Eigen::Vector3d(1.0, 1.0, 1.0), DOF_Y,
          Eigen::Vector3d(1.0, 1.0, 1.0), DOF_Z);
    BodyNode* tail = other_skeleton->getBodyNode(
          other_skeleton->getNumBodyNodes()-1);

    WeakConstBodyNodePtr weakParentPtr;
    {
      ConstBodyNodePtr parent = strongPtr;
      parent = parent->getParentBodyNode();
      weakParentPtr = parent;
      strongPtr->moveTo(tail);

      // The Skeleton should still be alive because 'parent' exists
      EXPECT_FALSE(weakSkelPtr.lock() == nullptr);
    }

    // Now that 'parent' is out of scope, the Skeleton should be gone
    EXPECT_TRUE(weakSkelPtr.lock() == nullptr);
    EXPECT_TRUE(weakParentPtr.lock() == nullptr);

    weakBnPtr = strongPtr;
    weakSkelPtr = strongPtr->getSkeleton();
    EXPECT_FALSE(weakBnPtr.expired());
    EXPECT_FALSE(weakSkelPtr.expired());
  }

  // softBnPtr still exists, so it should be keeping the Skeleton active
  EXPECT_FALSE(weakBnPtr.expired());

  std::weak_ptr<Skeleton> weakSkel = softBnPtr->remove();

  // Now that the SoftBodyNode which is holding the reference has been moved to
  // another Skeleton, the weakBnPtr and weakSkelPtr should disappear
  EXPECT_TRUE(weakBnPtr.expired());
  EXPECT_TRUE(weakSkelPtr.expired());

  // The WeakSoftBodyNodePtr should not have expired yet, because a strong
  // reference to its SoftBodyNode still exists
  EXPECT_FALSE(weakSoftBnPtr.expired());

  // Test the user-defined copy constructor
  SoftBodyNodePtr otherSoftBnPtr = softBnPtr;

  softBnPtr = nullptr;

  EXPECT_FALSE(weakSkel.lock() == nullptr);
  EXPECT_FALSE(weakSoftBnPtr.lock() == nullptr);

  BodyNodePtr strongPtr = otherSoftBnPtr;

  otherSoftBnPtr = nullptr;

  BodyNodePtr otherStrongPtr = strongPtr;

  strongPtr = nullptr;

  EXPECT_FALSE(weakSkel.lock() == nullptr);
  EXPECT_FALSE(weakSoftBnPtr.lock() == nullptr);

  otherStrongPtr = nullptr;

  // Now that all the strong BodyNodePtrs have been cleared, the
  // WeakSoftBodyNodePtr should also be cleared
  EXPECT_TRUE(weakSoftBnPtr.lock() == nullptr);
  EXPECT_TRUE(weakSkel.lock() == nullptr);
}