Пример #1
0
/// Determines (and sets) the value of Q from the axis and the inboard link and outboard link transforms
void ScrewJoint::determine_q(VectorN& q)
{
  // get the inboard and outboard link pointers
  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();
  
  // verify that the inboard and outboard links are set
  if (!inboard || !outboard)
  {
    std::cerr << "ScrewJoint::determine_Q() called on NULL inboard and/or outboard links!" << std::endl;
    assert(false);
    return;
  }

  // if axis is not defined, can't use this method
  if (std::fabs(_u.norm() - 1.0) > NEAR_ZERO)
  {
    std::cerr << "ScrewJoint::determine_Q() warning: some axes undefined; aborting..." << std::endl;
    return;
  }

  // get the attachment points on the link (global coords)
  Vector3d p1 = get_position_global(false);
  Vector3d p2 = get_position_global(true);

  // get the joint axis in the global frame
  Vector3d ug = inboard->get_transform().mult_vector(_u);

  // now, we'll project p2 onto the axis ug; points will be setup so that
  // ug passes through origin on inboard
  q.resize(num_dof());
  q[DOF_1] = ug.dot(p2-p1)/_pitch;
}
Пример #2
0
bool PathLCPSolver::solve_lcp(const MatrixN& MM, const VectorN& q, VectorN& z, double tol)
{
  const Real INF = std::numeric_limits<Real>::max();
  int i, j, k;
  int variables;
  shared_array<int> m_i, m_j;
  shared_array<double> dq, lb, ub, m_ij, x_end;
  MCP_Termination termination;
   
  Output_Printf(Output_Log | Output_Status | Output_Listing, "%s: Standalone-C Link\n", Path_Version());

  // We need a sparse representation of the matrix
  assert(q.size() == MM.rows());
  assert(q.size() == z.size());

  // Copy q to dq
  variables = q.size();
  dq = shared_array<double>(new double[variables+1]);
  for (i = 0;i < variables; i++)
    dq[i] = q[i];

  // Copy q to dq
  variables = q.size();
  dq = shared_array<double>(new double[variables+1]);
  for (i = 0;i < variables; i++)
    dq[i] = q[i];

  int num_non_zeroes = 0;
  for (i = 0;i < variables; i++)
    for (j = 0;j < variables; j++)
      if (std::fabs(MM(i,j)) > NEAR_ZERO)
        num_non_zeroes++;

  m_i = shared_array<int>(new int[num_non_zeroes + 1]);
  m_j = shared_array<int>(new int[num_non_zeroes + 1]);
  m_ij = shared_array<double>(new double[num_non_zeroes + 1]);

  k = 0;
  for (i = 0;i < variables; i++)
  {
    for (j = 0;j < variables; j++)
    {
      if (std::fabs(MM(i,j)) > NEAR_ZERO)
      {
        m_i[k] = i+1;
        m_j[k] = j+1;
        m_ij[k] = MM(i,j);
        k++;
      }
    }
  }
    
  lb = shared_array<double>(new double[variables+1]);
  ub = shared_array<double>(new double[variables+1]);
  for (i = 0;i < variables; i++)
  {
    lb[i] = 0.0;
    ub[i] = INF;
  }

  x_end = shared_array<double>(new double[variables+1]);

  SimpleLCP(variables, num_non_zeroes, m_i.get(), m_j.get(), m_ij.get(), dq.get(), lb.get(), ub.get(), &termination, x_end.get(), tol);

  // We now copy x_end into z
  z.resize(variables); 
  for (i = 0;i < variables; i++)
    z[i] = x_end[i];

  return (termination == MCP_Solved);
}
Пример #3
0
/// Determines (and sets) the value of Q from the axes and the inboard link and outboard link transforms
void SphericalJoint::determine_q(VectorN& q)
{
  const unsigned X = 0, Y = 1, Z = 2;

  // get the inboard and outboard links
  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();

  // verify that the inboard and outboard links are set
  if (!inboard || !outboard)
    throw NullPointerException("SphericalJoint::determine_q() called on NULL inboard and/or outboard links!");

  // if any of the axes are not defined, can't use this method
  if (std::fabs(_u[0].norm_sq() - 1.0) > NEAR_ZERO ||
      std::fabs(_u[1].norm_sq() - 1.0) > NEAR_ZERO ||
      std::fabs(_u[2].norm_sq() - 1.0) > NEAR_ZERO)
    return;

  // set proper size for q
  q.resize(num_dof());

  // get the link transforms
  Matrix3 R_inboard, R_outboard;
  inboard->get_transform().get_rotation(&R_inboard);
  outboard->get_transform().get_rotation(&R_outboard);

  // determine the joint transformation
  Matrix3 R_local = R_inboard.transpose_mult(R_outboard);

  // back out the transformation to z-axis
  Matrix3 RU = _R.transpose_mult(R_local * _R);

  // determine cos and sin values for q1, q2,  and q3
  Real s2 = RU(X,Z);
  Real c2 = std::cos(std::asin(s2));
  Real s1, c1, s3, c3;
  if (std::fabs(c2) > NEAR_ZERO)
  {
    s1 = -RU(Y,Z)/c2;
    c1 = RU(Z,Z)/c2;
    s3 = -RU(X,Y)/c2;
    c3 = RU(X,X)/c2;
    assert(!std::isnan(s1));
    assert(!std::isnan(c1));
    assert(!std::isnan(s3));
    assert(!std::isnan(c3));
  }
  else
  {
    // singular, we can pick any value for s1, c1, s3, c3 as long as the
    // following conditions are satisfied
    // c1*s3 + s1*c3*s2 = RU(Y,X)
    // c1*c3 - s1*s3*s2 = RU(Y,Y)
    // s1*s3 - c1*c3*s2 = RU(Z,X)
    // s1*c3 + c1*s3*s2 = RU(Z,Y)
    // so, we'll set q1 to zero (arbitrarily) and obtain
    s1 = 0;
    c1 = 1;
    s3 = RU(Y,X);
    c3 = RU(Y,Y);
  }

  // now determine q; only q2 can be determined without ambiguity
  if (std::fabs(s1) < NEAR_ZERO)
    q[DOF_2] = std::atan2(RU(X,Z), RU(Z,Z)/c1);
  else
    q[DOF_2] = std::atan2(RU(X,Z), -RU(Y,Z)/s1);
  assert(!std::isnan(q[DOF_2]));

  // if cos(q2) is not singular, proceed easily from here..
  if (std::fabs(c2) > NEAR_ZERO)
  {
    q[DOF_1] = std::atan2(-RU(Y,Z)/c2, RU(Z,Z)/c2);
    q[DOF_3] = std::atan2(-RU(X,Y)/c2, RU(X,X)/c2);
    assert(!std::isnan(q[DOF_1]));
    assert(!std::isnan(q[DOF_3]));
  }
  else
  {
    if (std::fabs(c1) > NEAR_ZERO)
      q[DOF_3] = std::atan2((RU(Y,X) - s1*s2*c3)/c1, (RU(Y,Y) + s1*s2*s3)/c1);
    else
      q[DOF_3] = std::atan2((RU(Z,X) + c1*s2*c3)/s1, (RU(Z,Y) - c1*s2*s3)/s1);
    if (std::fabs(c3) > NEAR_ZERO)
      q[DOF_1] = std::atan2((RU(Y,X) - c1*s3)/(s2*c3), (-RU(Y,X) + s1*s3)/(s2*c3));
    else
      q[DOF_1] = std::atan2((-RU(Y,Y) + c1*c3)/(s2*s3), (RU(Z,Y) - s1*c3)/(s2*s3));
    assert(!std::isnan(q[DOF_1]));
    assert(!std::isnan(q[DOF_3]));
  }
}