Esempio n. 1
0
File: Joint.cpp Progetto: hsu/Moby
/**
 * \note also points the outboard link to this joint
 */
void Joint::set_outboard_link(RigidBodyPtr outboard)
{
  _outboard_link = outboard;
  if (!outboard)
    return;

  //update spatial axes if both links are set
  if (!_outboard_link.expired() && !_inboard_link.expired())
    update_spatial_axes();

  // use one articulated body pointer to set the other, if possible
  if (!outboard->get_articulated_body() && !_abody.expired())
    outboard->set_articulated_body(ArticulatedBodyPtr(_abody));
  else if (outboard->get_articulated_body() && _abody.expired())
    set_articulated_body(ArticulatedBodyPtr(outboard->get_articulated_body()));

  // the articulated body pointers must now be equal; it is
  // conceivable that the user is updating the art. body pointers in an
  // unorthodox manner, but we'll look for this anwyway...
  if (!_abody.expired())
  {
    ArticulatedBodyPtr abody1(outboard->get_articulated_body());
    ArticulatedBodyPtr abody2(_abody);
    assert(abody1 == abody2);
  }
}
Esempio n. 2
0
File: Joint.cpp Progetto: hsu/Moby
/// Sets s bar from si
void Joint::calc_s_bar_from_si()
{
  const unsigned SPATIAL_DIM = 6;
  const unsigned NDOF = num_dof();
  SAFESTATIC MatrixN ns;
  SAFESTATIC SMatrix6N sx;

  // transform sx to frame located at joint
  RigidBodyPtr outboard = get_outboard_link();
  if (!outboard)
    return;
  const Matrix4& To = outboard->get_transform();
  Vector3 x = get_position_global();
  SpatialTransform(To, IDENTITY_3x3, x).transform(_si, sx);

  // setup ns - it's the standard (i.e., non-spatial) transpose of sx
  assert(sx.columns() == NDOF);
  ns.resize(NDOF, SPATIAL_DIM);
  for (unsigned i=0; i< NDOF; i++)
    for (unsigned j=0; j< SPATIAL_DIM; j++)
      ns(i,j) = sx(j,i);

  // compute the nullspace
  LinAlg::nullspace(ns, _s_bar);
}
TEFUNC void computeCorrectValuesForOne() {
	simulationTime += interval;

	double scalar = exp(lambda * simulationTime);
	
	correctPosition = scalar * positionInit;
	
	Vec3 axis;
	float angle;
	
	orientationInit.getAxisAngle(axis, angle);
	correctOrientation = Quaternion(scalar * angle, axis);

 	correctAngularVelocity = scalar * angularVelocityInit;
	
	referenceBody->setPosition(correctPosition);
	referenceBody->setVelocity(correctVelocity);
	referenceBody->setOrientation(correctOrientation);
	referenceBody->setAngularVelocity(correctAngularVelocity);

	referenceBody->getOrientation().getAxisAngle(axis, angle);
	correctRotationAxis = axis;
	correctRotationAngle = angle;

	cout << "Correct Values:" << endl
		 << "  Position: " << correctPosition << endl
		 << "  Velocity: " << correctVelocity << endl
		 << "  Orientation: " << correctOrientation << endl
		 << "  AngularVelocity: " << correctAngularVelocity << endl
		 << "  RotationAngle: " << correctRotationAngle << endl
		 << "  RotationAxis: " << correctRotationAxis 
		 << endl << endl;
}
Esempio n. 4
0
/**
 * The primitive is not cloned, nor is it unaltered; <b>this</b> points to
 * the pointer returned by this method (typically <b>primitive</b>).
 * \return primitive <i>unless the geometry of the underlying primitive is 
 * inconsistent, degenerate, or non-convex<i>; in that case,  
 * a corrected primitive will be returned.
 */
PrimitivePtr CollisionGeometry::set_geometry(PrimitivePtr primitive)
{
  Quatd EYE;

  if (_single_body.expired())
    throw std::runtime_error("CollisionGeometry::set_geometry() called before single body set!");

  SingleBodyPtr sb(_single_body);
  RigidBodyPtr rb = dynamic_pointer_cast<RigidBody>(sb);
  if (rb && !Quatd::rel_equal(rb->get_pose()->q, EYE))
  {
    std::cerr << "CollisionGeometry::set_primitive() warning - rigid body's orientation is not identity." << std::endl;
    std::cerr << "  At the rigid body's current orientation (" << AAngled(rb->get_pose()->q) << ")" << std::endl;
    std::cerr << "  the primitive will have the orientation (" << AAngled(primitive->get_pose()->q) << ")" << std::endl;
  }

  // save the primitive
  _geometry = primitive;

  // add this to the primitive
  CollisionGeometryPtr cg = dynamic_pointer_cast<CollisionGeometry>(shared_from_this());
  primitive->add_collision_geometry(cg);

  return primitive;
}
Esempio n. 5
0
/// Updates the spatial axis for this joint
void ScrewJoint::update_spatial_axes()
{
  const unsigned X = 0, Y = 1, Z = 2;

  // call parent method
  Joint::update_spatial_axes();

  // make sure the outboard link exists
  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();
  if (!inboard || !outboard)
    return;

  try
  {
    // get the joint to com vector in outer link coordinates
    const Vector3d& di = outboard->get_inner_joint_data(inboard).joint_to_com_vec_of;

    // get the joint axis in outer link coordinates
    Vector3d u0 = inboard->get_transform().mult_vector(_u);
    Vector3d ui = outboard->get_transform().transpose_mult_vector(u0);

    // update the spatial axis in link coordinates
    Vector3d x = Vector3d::cross(ui, di);
    _s[0].set_angular(ui);
    _s[0].set_lower(ui*_pitch + x);

    // setup s_bar
    calc_s_bar_from_s();
  }
  catch (std::runtime_error e)
  {
    // do nothing -- joint data has not yet been set in the link
  }
}
Esempio n. 6
0
/// (Relatively slow) method for determining the joint velocity from current link velocities
void Joint::determine_q_dot()
{
  MatrixNd m, U, V;
  VectorNd S;

  // get the spatial axes
  const vector<SVelocityd>& s = get_spatial_axes();

  // convert to a matrix
  to_matrix(s, m);

  // compute the SVD
  _LA.svd(m, U, S, V);

  // get the velocities in computation frames
  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();
  const SVelocityd& vi = inboard->get_velocity();
  const SVelocityd& vo = outboard->get_velocity();

  // get velocities in s's frame
  shared_ptr<const Pose3d> spose = get_pose();
  SVelocityd svi = Pose3d::transform(spose, vi);
  SVelocityd svo = Pose3d::transform(spose, vo);

  // compute the change in velocity
  m.mult(svo - svi, this->qd);
}
Esempio n. 7
0
/// Determines (and sets) the value of Q from the axes and the inboard link and outboard link transforms
void UniversalJoint::determine_q(VectorNd& q)
{
  const unsigned X = 0, Y = 1, Z = 2;

  // get the outboard link
  RigidBodyPtr outboard = get_outboard_link();

  // verify that the outboard link is set
  if (!outboard)
    throw std::runtime_error("determine_q() called on NULL outboard link!");

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

  // get the poses of the joint and outboard link
  shared_ptr<const Pose3d> Fj = get_pose();
  shared_ptr<const Pose3d> Fo = outboard->get_pose();

  // compute transforms
  Transform3d wTo = Pose3d::calc_relative_pose(Fo, GLOBAL); 
  Transform3d jTw = Pose3d::calc_relative_pose(GLOBAL, Fj);
  Transform3d jTo = jTw * wTo;

  // determine the joint transformation
  Matrix3d R = jTo.q;

  // determine q1 and q2 -- they are uniquely determined by examining the rotation matrix
  // (see get_rotation())
  q.resize(num_dof());
  q[DOF_1] = std::atan2(R(Z,Y), R(Y,Y));
  q[DOF_2] = std::atan2(R(X,Z), R(X,X));   
}
Esempio n. 8
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;
}
TEFUNC void computeCorrectValuesForThree() {
	simulationTime += interval;

	double scalar = exp(lambda * simulationTime);
	
	Vec3 correctRotation(orientationInit.getEulerRotation() + 
						 lambda * simulationTime * 
						 scalar * angularVelocityInit);
	
	correctPosition = positionInit + 
		lambda * simulationTime * 
		scalar * velocityInit;

	correctOrientation = Quaternion(correctRotation[0],
 									correctRotation[1], 
 									correctRotation[2]);
	
	Vec3 axis;
	float angle;
	referenceBody->getOrientation().getAxisAngle(axis, angle);
	correctRotationAxis = axis;
	correctRotationAngle = angle;

	referenceBody->setPosition(correctPosition);
	referenceBody->setVelocity(correctVelocity);
	referenceBody->setOrientation(correctOrientation);
	referenceBody->setAngularVelocity(correctAngularVelocity);

	cout << "Correct Values:" << endl
		 << "  Position: " << correctPosition << endl
		 << "  Orientation: " << correctOrientation << endl
		 << "  RotationAngle: " << correctRotationAngle << endl
		 << "  RotationAxis: " << correctRotationAxis 
		 << endl << endl;
}
//! Do update for the RB by useing the second test case
TEFUNC void updateRigidBodyForThree(RigidBodyPtr body) {

	body->setAcceleration(lambda * body->getVelocity());

	body->setAngularAcceleration(lambda * body->getAngularVelocity());

	cout << "Accel: " <<  body->getAcceleration() << endl;
}
//! Do update for the RB by useing the second test case
TEFUNC void updateRigidBodyForTwo(RigidBodyPtr body) {

	body->setVelocity(lambda * body->getPosition());	

	body->setAngularVelocity(lambda * body->getOrientation().getEulerRotation());

	body->setAngularAcceleration(Vec3(0,0,0));
}
Esempio n. 12
0
/**
 * \note these spatial axes are not constant, unlike many joints.
 */
const SMatrix6N& SphericalJoint::get_spatial_axes(ReferenceFrameType rftype)
{
  const unsigned X = 0, Y = 1, Z = 2;

  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();
  if (!inboard)
    throw std::runtime_error("SphericalJoint::get_spatial_axes() called with NULL inboard link");
  if (!outboard)
    throw std::runtime_error("SphericalJoint::get_spatial_axes() called with NULL outboard link");

  // get current values of q
  const VectorN& q = this->q;
  const VectorN& q_tare = this->_q_tare;

  // get the outboard link's joint to com vector in outer link coordinates
  const Vector3& p = outboard->get_inner_joint_data(inboard).joint_to_com_vec_of;

  // get the set of spatial axes
  Real c1 = std::cos(q[DOF_1]+q_tare[DOF_1]);
  Real c2 = std::cos(q[DOF_2]+q_tare[DOF_2]);
  Real s1 = std::sin(q[DOF_1]+q_tare[DOF_1]);
  Real s2 = std::sin(q[DOF_2]+q_tare[DOF_2]);

  // form untransformed spatial axes -- this are the vectors describing each axis, after
  // rotation by preceding axis/axes; note that first axis always points toward 1,0,0
  Vector3 uu2(0, c1, s1);
  Vector3 uu3(s2, -c2*s1, c1*c2);

  // transform the spatial axes into the outer link frame
  Vector3 u1;
  _R.get_column(X, u1.begin());
  Vector3 u2 = _R * uu2;
  Vector3 u3 = _R * uu3;

  // update the spatial axis in link coordinates
  SVector6 si1, si2, si3;
  si1.set_upper(u1);
  si2.set_upper(u2);
  si3.set_upper(u3);
  si1.set_lower(Vector3::cross(u1, p));
  si2.set_lower(Vector3::cross(u2, p));
  si3.set_lower(Vector3::cross(u3, p));
  _si.set_column(eAxis1, si1);
  _si.set_column(eAxis2, si2);
  _si.set_column(eAxis3, si3);

  // setup the complement of the spatial axes in link coordinates
  calc_s_bar_from_si();

  // use the Joint function to do the rest
  return Joint::get_spatial_axes(rftype);
}
Esempio n. 13
0
/**
 * \note these spatial axes are not constant, unlike many joints.
 */
const SMatrix6N& SphericalJoint::get_spatial_axes_dot(ReferenceFrameType rftype)
{
  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();
  if (!inboard)
    throw std::runtime_error("SphericalJoint::get_spatial_axes_dot() called with NULL inboard link");
  if (!outboard)
    throw std::runtime_error("SphericalJoint::get_spatial_axes_dot() called with NULL outboard link");

  // get q, _q_tare, and qd
  const VectorN& q = this->q;
  const VectorN& q_tare = this->_q_tare;
  const VectorN& qd = this->qd;

  // get the two transformed axes
  Real c1 = std::cos(q[DOF_1]+q_tare[DOF_1]);
  Real c2 = std::cos(q[DOF_2]+q_tare[DOF_2]);
  Real s1 = std::sin(q[DOF_1]+q_tare[DOF_1]);
  Real s2 = std::sin(q[DOF_2]+q_tare[DOF_2]);
  Real qd1 = qd[DOF_1];
  Real qd2 = qd[DOF_2];

  // form the time derivatives of the non-constant spatial axes (untransformed) 
  Vector3 uu2(0, -s1*qd1, c1*qd1);
  Vector3 uu3(c2*qd2, -c2*c1*qd1 + s2*s1*qd2, -c1*s2*qd2 - s1*c2*qd1);

  // transform the axes into outer link coordinates
  Vector3 u2 = _R * uu2; 
  Vector3 u3 = _R * uu3; 

  // get the outboard link's joint to com vector in outer link coordinates
  const Vector3& p = outboard->get_inner_joint_data(inboard).joint_to_com_vec_of;

  // update the spatial axis in link coordinates; note that third column of spatial axis
  // derivative set to zero in constructor and is never modified
  SVector6 si2, si3;
  si2.set_upper(u2);
  si3.set_upper(u3);
  si2.set_lower(Vector3::cross(u2, p));
  si3.set_lower(Vector3::cross(u3, p));
  _si_dot.set_column(eAxis2, si2);
  _si_dot.set_column(eAxis3, si3);

  // transform to global coordinates
  SpatialTransform X_0_i = outboard->get_spatial_transform_link_to_global();
  X_0_i.transform(_si_dot, _s0_dot);

  return (rftype == eLink) ? _si_dot : _s0_dot;
}
Esempio n. 14
0
File: Joint.cpp Progetto: hsu/Moby
/// Gets the spatial constraints for this joint
SMatrix6N& Joint::get_spatial_constraints(ReferenceFrameType rftype, SMatrix6N& s)
{
  const unsigned X = 0, Y = 1, Z = 2;
  Real Cq[7];

  // get the outboard link and its orientation quaternion
  RigidBodyPtr outboard = get_outboard_link();
  assert(outboard);
  const Quat& q = outboard->get_orientation();

  // resize the spatial constraint matrix
  s.resize(6, num_constraint_eqns());

  // calculate the constraint Jacobian in relation to the outboard link
  for (unsigned i=0; i< num_constraint_eqns(); i++)
  {
    // calculate the constraint Jacobian
    calc_constraint_jacobian_rodrigues(outboard, i, Cq);

    // convert the differential quaternion constraints to an angular velocity
    // representation
    Vector3 omega = q.G_mult(Cq[3], Cq[4], Cq[5], Cq[6]) * (Real) 0.5;

    // setup the column of the constraint Jacobian
    s(0,i) = omega[X];
    s(1,i) = omega[Y];
    s(2,i) = omega[Z];
    s(3,i) = Cq[X];
    s(4,i) = Cq[Y];
    s(5,i) = Cq[Z];
  }

  // TODO: this should be in link-global frame -- fix this!
  assert(false);

  // convert to link frame if necessary (constraints computed in global frame)
  if (rftype == eLink)
  {
    SpatialTransform Xi0 = outboard->get_spatial_transform_global_to_link();
    for (unsigned i=0; i< num_constraint_eqns(); i++)
    {
      SVector6 scol = s.get_column(i);
      scol = Xi0.transform(scol);
      s.set_column(i, scol);
    }
  }

  return s;
}
Esempio n. 15
0
/// Sets the location of this joint with specified inboard and outboard links
void Joint::set_location(const Point3d& point, RigidBodyPtr inboard, RigidBodyPtr outboard) 
{
  assert(inboard && outboard);

  // convert p to the inboard and outboard links' frames
  Point3d pi = Pose3d::transform_point(inboard->get_pose(), point);
  Point3d po = Pose3d::transform_point(outboard->get_pose(), point);

  // set _F's and Fb's origins
  _F->x = Origin3d(pi);
  _Fb->x = Origin3d(po);

  // invalidate all outboard pose vectors
  outboard->invalidate_pose_vectors();

  // set inboard and outboard links
  set_inboard_link(inboard, false);
  set_outboard_link(outboard, false);
}
//! Do update for the RB by useing the first test case
TEFUNC void updateRigidBodyForOne(RigidBodyPtr body) {

	body->setVelocity(lambda * body->getPosition());	
	body->setAcceleration(lambda * body->getVelocity());

	Vec3 axis;
	float angle;
	body->getOrientation().getAxisAngle(axis, angle);
	Quaternion tmp(lambda * angle, axis);
	body->setAngularVelocity(tmp.getEulerRotation());
	body->setAngularAcceleration(lambda * body->getAngularVelocity());
}
/**
 * \brief Start-Funktion der Testumgebung
 *
 * Diese Funktion wird direkt von display() aufgerufen. Hier
 * sollte alles reingeschrieben werden, was für die einzelnen
 * Tests nötig ist.
 */
TEFUNC void displayLoop() {
	if (loop) {
		//! gravitation aufrechnen
		bodySystem.addGravity();
	
		geometrySystem.resolveCollisions(10);
	
		constraintSystem.step();
		if (postStabilization)
			constraintSystem.computePostStabilization ();
		
		//! Integriere so weit, wie der letzte simulations Schritt brauchte
		//bodySystem.integrateRungeKutta(getLastTime());
		//bodySystem.integrateEuler(getLastTime());
		
		bodySystem.integrateEulerVelocities(10);
		geometrySystem.resolveContacts(10);
		bodySystem.integrateEulerPositions(10);
					
		// für schweben : -1.170
		sph1acc->addForce(-1.10 * SimonState::exemplar()->getGravityVector()* sph1acc->getMass());
		
		if (move) {
			sph6acc->addForce(Vec3(5.0,5.0,0.0));
			sph7acc->addForce(Vec3(-5.0,5.0,0.0));
			sph8acc->addForce(Vec3(0.0,5.0,5.0));
			sph9acc->addForce(Vec3(0.0,5.0,-5.0));
		}
		//sph->addForce(50 * Vec3(1.0,0.0,0.0));
	
		
	}
	geometrySystem.drawGeometries();
	//cout << getLastTime() << endl;
}
Esempio n. 18
0
/// Sets the pointer to the inboard link for this joint (and updates the spatial axes, if the outboard link has been set)
void Joint::set_inboard_link(RigidBodyPtr inboard, bool update_pose)
{
  _inboard_link = inboard;
  if (!inboard)
    return;

  // add this joint to the outer joints
  inboard->_outer_joints.insert(get_this());

  // setup F's pose relative to the inboard
  set_inboard_pose(inboard->get_pose(), update_pose);

  // update articulated body pointers, if possible
  if (!inboard->get_articulated_body() && !_abody.expired())
    inboard->set_articulated_body(ArticulatedBodyPtr(_abody));
  else if (inboard->get_articulated_body() && _abody.expired())
    set_articulated_body(ArticulatedBodyPtr(inboard->get_articulated_body()));

  // the articulated body pointers must now be equal; it is
  // conceivable that the user is updating the art. body pointers in an
  // unorthodox manner, but we'll look for this anwyway...
  if (!_abody.expired())
  {
    ArticulatedBodyPtr abody1(inboard->get_articulated_body());
    ArticulatedBodyPtr abody2(_abody);
    assert(abody1 == abody2);
  }
}
Esempio n. 19
0
File: Joint.cpp Progetto: hsu/Moby
/// Evaluates the time derivative of the constraint
void Joint::evaluate_constraints_dot(Real C[6])
{
  Real Cx[6];

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

  // get the linear angular velocities
  const Vector3& lvi = in->get_lvel();
  const Vector3& lvo = out->get_lvel();
  const Vector3& avi = in->get_avel();
  const Vector3& avo = out->get_avel();

  // compute
  const unsigned NEQ = num_constraint_eqns();
  for (unsigned i=0; i< NEQ; i++)
  {
    calc_constraint_jacobian(DynamicBody::eAxisAngle, in, i, Cx);
    Vector3 lv(Cx[0], Cx[1], Cx[2]);
    Vector3 av(Cx[3], Cx[4], Cx[5]);
    C[i] = lv.dot(lvi) + av.dot(avi);
    calc_constraint_jacobian(DynamicBody::eAxisAngle, out, i, Cx);
    lv = Vector3(Cx[0], Cx[1], Cx[2]);
    av = Vector3(Cx[3], Cx[4], Cx[5]);
    C[i] += -lv.dot(lvo) - av.dot(avo);
  }
}
Esempio n. 20
0
/// Gets the farthest point from this geometry
double CollisionGeometry::get_farthest_point_distance() const
{
  // get the primitive from this
  PrimitivePtr primitive = get_geometry();

  // get the vertices
  vector<Point3d> verts;
  get_vertices(verts);
  if (verts.empty())
    return 0.0;

  // get the rigid body pose in P's frame
  RigidBodyPtr rb = dynamic_pointer_cast<RigidBody>(get_single_body());
  Point3d rbX = Pose3d::transform_point(verts.front().pose, Point3d(0,0,0,rb->get_pose()));
 
  // find which point is closest
  double max_dist = 0.0;
  for (unsigned i=0; i< verts.size(); i++)
    max_dist = std::max(max_dist, (verts[i] - rbX).norm()); 

  return max_dist; 
}
Esempio n. 21
0
/// The main control loop
void controller(DynamicBodyPtr robot, Real time, void* data)
{
  // determine coordinates of ball in gripper coordinate frames
  if (first)
  {
    _ball_grip_left = Matrix4::inverse_transform(left_gripper->get_transform()) .mult_point(ball->get_position());  
    _ball_grip_right = Matrix4::inverse_transform(right_gripper->get_transform()).mult_point(ball->get_position());  
    first = false;
  }
  else
  {
    // output the combined error from the starting position w.r.t. both grippers
    std::ofstream out("error.ball", std::ios::app);
    Vector3 ball_grip_left = Matrix4::inverse_transform(left_gripper->get_transform()).mult_point(ball->get_position());  
    Vector3 ball_grip_right = Matrix4::inverse_transform(right_gripper->get_transform()).mult_point(ball->get_position());  
    Real err = std::sqrt((ball_grip_left - _ball_grip_left).norm_sq() + (ball_grip_right - _ball_grip_right).norm_sq());
    out << time << " " << err << std::endl;
    out.close();
  }

  control_PID(dynamic_pointer_cast<RCArticulatedBody>(robot), time);
}
	void SetIgnoreCollisionCheck(RigidBodyPtr rigidBody, bool ignore){
		auto colObj = dynamic_cast<btCollisionObject*>(rigidBody.get());
		assert(colObj);
		if (ignore){
			int i = mSelf->m_objectsWithoutCollisionCheck.findLinearSearch(colObj);
			if (i == mSelf->m_objectsWithoutCollisionCheck.size()){
				mSelf->setIgnoreCollisionCheck(colObj, ignore);
			}
		}
		else{
			mSelf->setIgnoreCollisionCheck(colObj, ignore);
		}
	}
Esempio n. 23
0
File: Joint.cpp Progetto: hsu/Moby
/// (Relatively slow) method for determining the joint velocity from current link velocities
void Joint::determine_q_dot()
{
  // get the pseudo-inverse of the spatial axes
  MatrixN s;
  s.copy_from(get_spatial_axes(eGlobal));
  try
  {
    LinAlg::pseudo_inverse(s, LinAlg::svd1); 
  }
  catch (NumericalException e)
  {
    s.copy_from(get_spatial_axes(eGlobal));
    LinAlg::pseudo_inverse(s, LinAlg::svd2); 
  }

  // get the change in velocity
  RigidBodyPtr inboard = get_inboard_link();
  RigidBodyPtr outboard = get_outboard_link();
  SVector6 vi = inboard->get_spatial_velocity(eGlobal);
  SVector6 vo = outboard->get_spatial_velocity(eGlobal);
  s.mult(vo - vi, this->qd);
}
Esempio n. 24
0
/**
 * \note also points the outboard link to this joint
 */
void Joint::set_outboard_link(RigidBodyPtr outboard, bool update_pose)
{
  _outboard_link = outboard;
  if (!outboard)
    return;

  // add this joint to the outer joints
  outboard->_inner_joints.insert(get_this());

  // get the outboard pose
  if (outboard->_F->rpose)
    throw std::runtime_error("Joint::set_inboard_link() - relative pose on inboard link already set");

  // setup Fb's pose relative to the outboard 
  set_outboard_pose(outboard->_F, update_pose);

  // setup the frame
  outboard->_xdj.pose = get_pose();
  outboard->_xddj.pose = get_pose();
  outboard->_Jj.pose = get_pose();
  outboard->_forcej.pose = get_pose();

  // use one articulated body pointer to set the other, if possible
  if (!outboard->get_articulated_body() && !_abody.expired())
    outboard->set_articulated_body(ArticulatedBodyPtr(_abody));
  else if (outboard->get_articulated_body() && _abody.expired())
    set_articulated_body(ArticulatedBodyPtr(outboard->get_articulated_body()));

  // the articulated body pointers must now be equal; it is
  // conceivable that the user is updating the art. body pointers in an
  // unorthodox manner, but we'll look for this anwyway...
  if (!_abody.expired())
  {
    ArticulatedBodyPtr abody1(outboard->get_articulated_body());
    ArticulatedBodyPtr abody2(_abody);
    assert(abody1 == abody2);
  }
}
TEFUNC void printRigidBody(RigidBodyPtr body) {
	Vec3 axis;
	float angle;
	body->getOrientation().getAxisAngle(axis, angle);

	cout << "Differences from " << body->getId() << " to reference:" <<  endl
		 << "  Position: " << body->getPosition() - correctPosition << endl
		 << "  Velocity: " << body->getVelocity() - correctVelocity << endl
		//! \todo komponentenweise subtraktion für quaternionen
		 << "  Orientation: " << body->getOrientation() + (-1 * correctOrientation) << endl
		 << "  AngularVelocity: " << body->getAngularVelocity() - correctAngularVelocity << endl
		 << "  RotationAngle: " << angle - correctRotationAngle << endl
		 << "  RotationAxis: " << axis - correctRotationAxis 
		 << endl << endl;
}
Esempio n. 26
0
/**
 * \pre Uses joint accelerations computed by forward dynamics, so the 
 *      appropriate forward dynamics function must be run first.
 */
void RNEAlgorithm::calc_constraint_forces(RCArticulatedBodyPtr body)
{
  queue<RigidBodyPtr> link_queue;
  SMatrix6N s;
  vector<SpatialRBInertia> Iiso;

  FILE_LOG(LOG_DYNAMICS) << "RNEAlgorithm::calc_constraint_forces() entered" << endl;

  // get the reference frame for computation
  ReferenceFrameType rftype = body->computation_frame_type;

  // ** STEP 0: compute isolated inertias 

  // get the set of links
  const vector<RigidBodyPtr>& links = body->get_links();

  // get the isolated inertiae
  Iiso.resize(links.size());
  for (unsigned i=1; i< links.size(); i++)
  {
    unsigned idx = links[i]->get_index();
    Iiso[idx] = links[i]->get_spatial_iso_inertia(rftype); 
  }

   // ** STEP 1: compute velocities and accelerations

  // get the base link
  RigidBodyPtr base = links.front();

  // setup the vector of link accelerations
  vector<SVector6> accels(links.size(), ZEROS_6);
  
  // add all child links of the base to the processing queue
  list<RigidBodyPtr> child_links;
  base->get_child_links(std::back_inserter(child_links)); 
  BOOST_FOREACH(RigidBodyPtr rb, child_links)
    link_queue.push(rb);

  // ** STEP 1: compute link forces -- backward recursion
  vector<bool> processed(links.size(), false);
  vector<SVector6> forces(links.size(), ZEROS_6);

  // add all leaf links to the queue
  for (unsigned i=1; i< links.size(); i++)
    if (links[i]->num_child_links() == 0)
      link_queue.push(links[i]);
      
  // process all links up to, but not including, the base
  while (!link_queue.empty())
  {
    // get the link off of the front of the queue and push all children of the link onto the queue
    RigidBodyPtr link = link_queue.front();
    link_queue.pop();    
    unsigned idx = link->get_index();

    // if this link has already been processed, do not process it again
    if (processed[idx])
      continue;

    // if the link is the base, continue the loop
    if (link->is_base())
      continue;
    
    // link is not the base; add the parent to the queue for processing
    RigidBodyPtr parent(link->get_parent_link());
    link_queue.push(parent);
    unsigned pidx = parent->get_index();

    // get the forces for this link and this link's parent
    SVector6& fi = forces[idx];
    SVector6& fim1 = forces[pidx];

    // get this link's acceleration
    SVector6 a = link->get_spatial_accel(rftype);
    
    FILE_LOG(LOG_DYNAMICS) << " computing necessary force; processing link " << link->id << endl;
    FILE_LOG(LOG_DYNAMICS) << "  currently determined link force: " << fi << endl;    
    FILE_LOG(LOG_DYNAMICS) << "  I * a = " << (Iiso[idx] * a) << endl;

    // get the spatial velocity for this link
    const SVector6& v = link->get_spatial_velocity(rftype);

    // add I*a to the link force
    fi += Iiso[idx] * a;

    // update the determined force to this link w/Coriolis + centrifugal terms
    fi += SVector6::spatial_cross(v, Iiso[idx] * v);

    FILE_LOG(LOG_DYNAMICS) << "  force (+ I*a): " << fi << endl;    

    // determine external forces in link frame
    const Vector3& fext = link->sum_forces();  
    const Vector3& text = link->sum_torques();  
    const Matrix4& T = link->get_transform();
    SVector6 fx(T.transpose_mult_vector(fext), T.transpose_mult_vector(text));

    // subtract external forces in the appropriate frame
    if (rftype == eGlobal)
    {
      SpatialTransform X_0_i = link->get_spatial_transform_link_to_global();
      fi -= X_0_i.transform(fx);
    }
    else
      fi -= fx;

    FILE_LOG(LOG_DYNAMICS) << "  force on link after subtracting external force: " << fi << endl;

    // indicate that this link has been processed
    processed[idx] = true;

    // update the parent force, if the parent is not the base
    if (parent->is_base())
      continue;
    else
    { 
      if (rftype == eGlobal)
        fim1 += fi;
      else
        fim1 += link->get_spatial_transform_backward().transform(fi);
    }
  }
  
  // ** STEP 2: compute constraint forces

  // compute actuator forces
  for (unsigned i=1; i< links.size(); i++)
  {
    RigidBodyPtr link = links[i];
    JointPtr joint(link->get_inner_joint_implicit());
    joint->get_spatial_constraints(rftype, s);
    s.transpose_mult(forces[link->get_index()], joint->lambda);
  
    FILE_LOG(LOG_DYNAMICS) << "joint " << joint->id << " constraint force: " << joint->lambda << endl;
  }

  FILE_LOG(LOG_DYNAMICS) << "RNEAlgorithm::calc_constraint_forces() exited" << endl;
}
Esempio n. 27
0
/**
 * Computed joint actuator forces are stored in inv_dyn_data.
 */
map<JointPtr, VectorN> RNEAlgorithm::calc_inv_dyn_fixed_base(RCArticulatedBodyPtr body, const map<RigidBodyPtr, RCArticulatedBodyInvDynData>& inv_dyn_data) const
{
  queue<RigidBodyPtr> link_queue;
  map<RigidBodyPtr, RCArticulatedBodyInvDynData>::const_iterator idd_iter;
  vector<SpatialRBInertia> Iiso;

  FILE_LOG(LOG_DYNAMICS) << "RNEAlgorithm::calc_inv_dyn_fixed_base() entered" << endl;

  // get the reference frame for computation
  ReferenceFrameType rftype = body->computation_frame_type;

  // ** STEP 0: compute isolated inertias 

  // get the set of links
  const vector<RigidBodyPtr>& links = body->get_links();

  // get the isolated inertiae
  Iiso.resize(links.size());
  for (unsigned i=1; i< links.size(); i++)
  {
    unsigned idx = links[i]->get_index();
    Iiso[idx] = links[i]->get_spatial_iso_inertia(rftype); 
  }

  // ** STEP 1: compute velocities and accelerations

  // get the base link
  RigidBodyPtr base = links.front();

  // setup the vector of link accelerations
  vector<SVector6> accels(links.size(), ZEROS_6);
  
  // add all child links of the base to the processing queue
  list<RigidBodyPtr> child_links;
  base->get_child_links(std::back_inserter(child_links)); 
  BOOST_FOREACH(RigidBodyPtr rb, child_links)
    link_queue.push(rb);
  
  // process all links
  while (!link_queue.empty())
  {
    // get the link off of the front of the queue 
    RigidBodyPtr link = link_queue.front();
    link_queue.pop();    
    unsigned idx = link->get_index();

    // push all children of the link onto the queue
    child_links.clear();
    link->get_child_links(std::back_inserter(child_links)); 
    BOOST_FOREACH(RigidBodyPtr rb, child_links)
      link_queue.push(rb);

    // get the link's parent
    RigidBodyPtr parent(link->get_parent_link());
    unsigned pidx = parent->get_index();

    // get the joint for this link
    JointPtr joint(link->get_inner_joint_implicit());

    // get the spatial link velocity
    const SVector6& v = link->get_spatial_velocity(rftype); 

    // get the reference to the spatial link acceleration
    SVector6& a = accels[idx];
 
    // get spatial axes for this link's inner joint
    const SMatrix6N& s = joint->get_spatial_axes(rftype);

    // get derivative of the spatial axes for this link's inner joint
    const SMatrix6N& s_dot = joint->get_spatial_axes_dot(rftype);

    // get the current joint velocity
    const VectorN& qd = joint->qd;

    // **** compute acceleration

    // get the desired joint acceleration
    idd_iter = inv_dyn_data.find(link);
    assert(idd_iter != inv_dyn_data.end());
    const VectorN& qdd_des = idd_iter->second.qdd;  

    // add this link's contribution
    a += SVector6::spatial_cross(v, s.mult(qd)) + s.mult(qdd_des) + s_dot.mult(qd);

    // now add parent's contribution
    if (rftype == eGlobal)
      a += accels[pidx];
    else
    {
      SpatialTransform X_i_im1 = link->get_spatial_transform_forward();
      a += X_i_im1.transform(accels[pidx]);
    }

    FILE_LOG(LOG_DYNAMICS) << " computing link velocity / acceleration; processing link " << link->id << endl;
    FILE_LOG(LOG_DYNAMICS) << "  spatial axis: " << s << endl;
    FILE_LOG(LOG_DYNAMICS) << "  spatial joint velocity: " << s.mult(qd) << endl;
    FILE_LOG(LOG_DYNAMICS) << "  link velocity: " << v << endl;
    FILE_LOG(LOG_DYNAMICS) << "  link accel: " << a << endl;
  }
  
  // ** STEP 2: compute link forces -- backward recursion
  vector<bool> processed(links.size(), false);
  vector<SVector6> forces(links.size(), SVector6(0,0,0,0,0,0));

  // add all leaf links to the queue
  for (unsigned i=1; i< links.size(); i++)
    if (links[i]->num_child_links() == 0)
      link_queue.push(links[i]);
      
  // process all links up to, but not including, the base
  while (!link_queue.empty())
  {
    // get the link off of the front of the queue
    RigidBodyPtr link = link_queue.front();
    link_queue.pop();    
    unsigned idx = link->get_index();

    // if this link has already been processed, do not process it again
    if (processed[idx])
      continue;

    // if the link is the base, continue the loop
    if (link->is_base())
      continue;
    
    // link is not the base; add the parent to the queue for processing
    RigidBodyPtr parent(link->get_parent_link());
    link_queue.push(parent);
    unsigned pidx = parent->get_index();

    // get the forces for this link and this link's parent
    SVector6& fi = forces[idx];
    SVector6& fim1 = forces[pidx];
    
    FILE_LOG(LOG_DYNAMICS) << " computing necessary force; processing link " << link->id << endl;
    FILE_LOG(LOG_DYNAMICS) << "  currently determined link force: " << fi << endl;    
    FILE_LOG(LOG_DYNAMICS) << "  I * a = " << (Iiso[idx] * accels[idx]) << endl;

    // get the spatial velocity for this link
    const SVector6& v = link->get_spatial_velocity(rftype);

    // add I*a to the link force
    fi += Iiso[idx] * accels[idx];

    // update the determined force to this link w/Coriolis + centrifugal terms
    fi += SVector6::spatial_cross(v, Iiso[idx] * v);

    FILE_LOG(LOG_DYNAMICS) << "  force (+ I*a): " << fi << endl;    

    // determine external forces in link frame
    idd_iter = inv_dyn_data.find(link);
    assert(idd_iter != inv_dyn_data.end());
    const Vector3& fext = idd_iter->second.fext;  
    const Vector3& text = idd_iter->second.text;  
    const Matrix4& T = link->get_transform();
    SVector6 fx(T.transpose_mult_vector(fext), T.transpose_mult_vector(text));

    // subtract external forces in the appropriate frame
    if (rftype == eGlobal)
    {
      SpatialTransform X_0_i = link->get_spatial_transform_link_to_global();
      fi -= X_0_i.transform(fx);
    }
    else
      fi -= fx;

    FILE_LOG(LOG_DYNAMICS) << "  force on link after subtracting external force: " << fi << endl;

    // indicate that this link has been processed
    processed[idx] = true;

    // update the parent force, if the parent is not the base
    if (parent->is_base())
      continue;
    else 
      if (rftype == eGlobal)
        fim1 += fi;
      else
        fim1 += link->get_spatial_transform_backward().transform(fi);
  }
  
  // ** STEP 3: compute joint forces

  // setup a map from joints to actuator forces
  map<JointPtr, VectorN> actuator_forces;

  // compute actuator forces
  for (unsigned i=1; i< links.size(); i++)
  {
    RigidBodyPtr link = links[i];
    JointPtr joint(link->get_inner_joint_implicit());
    const SMatrix6N& s = joint->get_spatial_axes(rftype);
    VectorN& Q = actuator_forces[joint];  
    s.transpose_mult(forces[link->get_index()], Q);
  
    FILE_LOG(LOG_DYNAMICS) << "joint " << joint->id << " inner joint force: " << actuator_forces[joint] << endl;
  }

  FILE_LOG(LOG_DYNAMICS) << "RNEAlgorithm::calc_inv_dyn_fixed_base() exited" << endl;

  return actuator_forces;
}
Esempio n. 28
0
/**
 * \param inv_dyn_data a mapping from links to the external forces (and
 *        torques) applied to them and to the desired inner joint
 *        accelerations; note that all links in the robot should be included
 *        in this map (even the base link, although inner joint acceleration
 *        is not applicable in that case and will be ignored for it)
 * \return a mapping from joints to actuator forces
 */
map<JointPtr, VectorN> RNEAlgorithm::calc_inv_dyn_floating_base(RCArticulatedBodyPtr body, const map<RigidBodyPtr, RCArticulatedBodyInvDynData>& inv_dyn_data) const
{
  queue<RigidBodyPtr> link_queue;
  map<RigidBodyPtr, RCArticulatedBodyInvDynData>::const_iterator idd_iter;
  vector<SpatialRBInertia> Iiso, I;
  vector<SVector6> Z, v, a;

  FILE_LOG(LOG_DYNAMICS) << "RNEAlgorithm::calc_inv_dyn_floating_base() entered" << endl;

  // get the reference frame type
  ReferenceFrameType rftype = body->computation_frame_type;

  // get the set of links
  const vector<RigidBodyPtr>& links = body->get_links();

  // ** STEP 0: compute isolated inertias 

  // get the isolated inertiae
  Iiso.resize(links.size());
  for (unsigned i=0; i< links.size(); i++)
  {
    unsigned idx = links[i]->get_index();
    Iiso[idx] = links[i]->get_spatial_iso_inertia(rftype); 
  }

  // ** STEP 1: compute velocities and relative accelerations

  // set all desired velocities and accelerations (latter relative to the base)
  // to zero initially
  v.resize(links.size());
  a.resize(links.size());
  for (unsigned i=0; i< links.size(); i++)
    v[i] = a[i] = ZEROS_6;
  
  // get the base link
  RigidBodyPtr base = links.front();
  
  // set velocity for the base
  v.front() = base->get_spatial_velocity(rftype);

  // add all child links of the base to the processing queue
  list<RigidBodyPtr> child_links;
  base->get_child_links(std::back_inserter(child_links)); 
  BOOST_FOREACH(RigidBodyPtr rb, child_links)
    link_queue.push(rb);
    
  // process all links
  while (!link_queue.empty())
  {
    // get the link off of the front of the queue
    RigidBodyPtr link = link_queue.front();
    link_queue.pop();
    
    // add all child links of the link to the processing queue
    child_links.clear();
    link->get_child_links(std::back_inserter(child_links)); 
    BOOST_FOREACH(RigidBodyPtr rb, child_links)
      link_queue.push(rb);
    
    // get the parent link
    RigidBodyPtr parent(link->get_parent_link());
    
    // get the index of this link and its parent
    unsigned i = link->get_index();
    unsigned im1 = parent->get_index();

    // get the spatial axes (and derivative) of this link's inner joint
    JointPtr joint(link->get_inner_joint_implicit());
    const SMatrix6N& s = joint->get_spatial_axes(rftype);
    const SMatrix6N& s_dot = joint->get_spatial_axes_dot(rftype);

    // compute s * qdot
    SVector6 sqd = s.mult(joint->qd);
    
    // get the desired acceleration for the current link
    idd_iter = inv_dyn_data.find(link);
    assert(idd_iter != inv_dyn_data.end());
    const VectorN& qdd_des = idd_iter->second.qdd;

    // compute velocity and relative acceleration
    v[i] = v[im1] + sqd;
    a[i] = a[im1] + s.mult(qdd_des) + s_dot.mult(joint->qd) + SVector6::spatial_cross(v[i], sqd);

    FILE_LOG(LOG_DYNAMICS) << "  s: " << s << endl;
    FILE_LOG(LOG_DYNAMICS) << "  velocity for link " << links[i]->id << ": " << v[i] << endl;
    FILE_LOG(LOG_DYNAMICS) << "  s * qdd: " << s.mult(qdd_des) << endl;
    FILE_LOG(LOG_DYNAMICS) << "  v x s * qd: " << SVector6::spatial_cross(v[i], sqd) << endl;
    FILE_LOG(LOG_DYNAMICS) << "  relative accel for link " << links[i]->id << ": " << a[i] << endl;
  }
  
  // ** STEP 2: compute composite inertias and Z.A. forces

  // resize vectors of spatial inertias and Z.A. vectors
  I.resize(links.size());
  Z.resize(links.size());

  // zero out I and Z
  for (unsigned i=0; i< links.size(); i++)
  {
    I[i].set_zero();
    Z[i] = ZEROS_6;
  }

  // set all spatial isolated inertias and Z.A. forces
  for (unsigned i=0; i< links.size(); i++)
  {
    // get the i'th link
    RigidBodyPtr link = links[i];
    unsigned idx = link->get_index();

    // add the spatial isolated inertia for this link to the composite inertia
    I[idx] += Iiso[idx];

    // setup forces due to (relative) acceleration on link
    Z[idx] = Iiso[idx] * a[idx];

    // add coriolis and centrifugal forces on link
    Z[idx] += SVector6::spatial_cross(v[i], Iiso[idx] * v[idx]);

    // determine external forces on the link in link frame
    idd_iter = inv_dyn_data.find(link);
    assert(idd_iter != inv_dyn_data.end());
    const Vector3& fext = idd_iter->second.fext;  
    const Vector3& text = idd_iter->second.text;  
    const Matrix4& T = link->get_transform();
    SVector6 fx(T.transpose_mult_vector(fext), T.transpose_mult_vector(text));

    // transform external forces and subtract from Z.A. vector
    SpatialTransform X_0_i = link->get_spatial_transform_link_to_global();
    Z[idx] -= X_0_i.transform(fx);

    FILE_LOG(LOG_DYNAMICS) << " -- processing link " << link->id << endl;
    FILE_LOG(LOG_DYNAMICS) << "   external force / torque: " << fext << " / " << text << endl;
    FILE_LOG(LOG_DYNAMICS) << "   ZA vector: " << Z[idx] << endl;
    FILE_LOG(LOG_DYNAMICS) << "   isolated spatial-inertia: " << endl << Iiso[idx];
  }
  
  // *** compute composite inertias and zero acceleration vectors

  // setup vector that indicates when links have been processed
  vector<bool> processed(links.size(), false);

  // put all leaf links into the queue
  for (unsigned i=0; i< links.size(); i++)
    if (links[i]->num_child_links() == 0)
      link_queue.push(links[i]);

  // process all links
  while (!link_queue.empty())
  {
    // get the link off of the front of the queue
    RigidBodyPtr link = link_queue.front();
    link_queue.pop();

    // get the index for this link
    unsigned i = link->get_index();
    
    // see whether this link has already been processed
    if (processed[i])
      continue;
    
    // process the parent link, if possible
    RigidBodyPtr parent(link->get_parent_link());
    if (parent)
    {
      // put the parent on the queue
      link_queue.push(parent);
    
      // get the parent index
      unsigned im1 = parent->get_index();
    
      // add this inertia and Z.A. force to its parent
      I[im1] += I[i];
      Z[im1] += Z[i];

      // indicate that the link has been processed
      processed[i] = true;
    }
  }

  // ** STEP 3: compute base acceleration
  a.front() = I.front().inverse_mult(-Z.front());
  
  SpatialTransform X_i_0 = base->get_spatial_transform_global_to_link(); 
  FILE_LOG(LOG_DYNAMICS) << "  Composite inertia for the base: " << endl << I.front();
  FILE_LOG(LOG_DYNAMICS) << "  ZA vector for the base (link frame): " << X_i_0.transform(Z.front()) << endl;
  FILE_LOG(LOG_DYNAMICS) << "  Determined base acceleration (link frame): " << X_i_0.transform(a.front()) << endl;

  // ** STEP 4: compute joint forces
  
  // setup the map of actuator forces
  map<JointPtr, VectorN> actuator_forces;

  // compute the forces
  for (unsigned i=1; i< links.size(); i++)
  {
    unsigned idx = links[i]->get_index();
    JointPtr joint(links[i]->get_inner_joint_implicit());
    const SMatrix6N& s = joint->get_spatial_axes(rftype);
    VectorN& Q = actuator_forces[joint];
    s.transpose_mult((I[idx] * a.front()) + Z[idx], Q);

    FILE_LOG(LOG_DYNAMICS) << "  processing link: " << links[i]->id << endl;
    FILE_LOG(LOG_DYNAMICS) << "    spatial axis: " << endl << s;
    FILE_LOG(LOG_DYNAMICS) << "    I: " << endl << I[idx];
    FILE_LOG(LOG_DYNAMICS) << "    Z: " << endl << Z[idx];
    FILE_LOG(LOG_DYNAMICS) << "    actuator force: " << actuator_forces[joint] << endl;
  }

  FILE_LOG(LOG_DYNAMICS) << "RNEAlgorithm::calc_inv_dyn_floating_base() exited" << endl;

  return actuator_forces;
}
Esempio n. 29
0
/// Computes the time derivative of the constraint jacobian with respect to a body
void SphericalJoint::calc_constraint_jacobian_dot_rodrigues(RigidBodyPtr body, unsigned index, Real Cq[7])
{
  const unsigned X = 0, Y = 1, Z = 2, SPATIAL_DIM = 7;

  // get the two links
  RigidBodyPtr inner = get_inboard_link();
  RigidBodyPtr outer = get_outboard_link();

  // mke sure that body is one of the links
  if (inner != body && outer != body)
  {
    for (unsigned i=0; i< SPATIAL_DIM; i++)
      Cq[i] = (Real) 0.0;
    return;
  }

  // setup the constraint equations (from Shabana, p. 432)
  if (body == inner)
  {
    // get the information necessary to compute the constraint equations
    const Quat& q = inner->get_orientation();
    const Vector3& p = inner->get_outer_joint_data(outer).com_to_joint_vec;
    const Real px = p[X];
    const Real py = p[Y];
    const Real pz = p[Z];
    Quat qd = Quat::deriv(q, inner->get_avel());
    const Real dqw = qd.w;
    const Real dqx = qd.x;
    const Real dqy = qd.y;
    const Real dqz = qd.z;

    switch (index)
    {
      case 0:
        Cq[0] = 0.0;    
        Cq[1] = 0.0;    
        Cq[2] = 0.0;    
        Cq[3] = 4*px*dqw + 2*pz*dqy - 2*py*dqz;
        Cq[4] = 4*dqx*px + 2*dqy*py + 2*dqz*pz;
        Cq[5] = 2*pz*dqw + 2*py*dqx;
        Cq[6] = 2*pz*dqx - 2*py*dqw;
        break;

      case 1:
        Cq[0] = 0.0;    
        Cq[1] = 0.0;    
        Cq[2] = 0.0;    
        Cq[3] = 4*py*dqw - 2*pz*dqx + 2*px*dqz;
        Cq[4] = 2*dqy*px - 2*dqw*pz;
        Cq[5] = 2*px*dqx + 4*py*dqy + 2*pz*dqz;
        Cq[6] = 2*px*dqw + 2*pz*dqy;
        break;

      case 2:
        Cq[0] = 0.0;
        Cq[1] = 0.0;
        Cq[2] = 0.0;
        Cq[3] = 4*pz*dqw + 2*py*dqx - 2*px*dqy;
        Cq[4] = 2*dqz*px + 2*dqw*py;
        Cq[5] = 2*py*dqz - 2*px*dqw;
        Cq[6] = 4*pz*dqz + 2*py*dqy + 2*px*dqx;
        break;

      default:
        throw std::runtime_error("Invalid joint constraint index!");
    }
  }
  else
  {
    // get the information necessary to compute the constraint equations
    const Quat& q = outer->get_orientation();
    const Vector3& p = body->get_inner_joint_data(inner).joint_to_com_vec_of;
    const Real px = -p[X];
    const Real py = -p[Y];
    const Real pz = -p[Z];
    Quat qd = Quat::deriv(q, outer->get_avel());
    const Real dqw = qd.w;
    const Real dqx = qd.x;
    const Real dqy = qd.y;
    const Real dqz = qd.z;

    switch (index)
    {
      case 0:
        Cq[0] = 0.0;     
        Cq[1] = 0.0;      
        Cq[2] = 0.0;      
        Cq[3] = -(4*px*dqw + 2*pz*dqy - 2*py*dqz);
        Cq[4] = -(4*dqx*px + 2*dqy*py + 2*dqz*pz);
        Cq[5] = -(2*pz*dqw + 2*py*dqx);
        Cq[6] = -(2*pz*dqx - 2*py*dqw);
        break;

      case 1:
        Cq[0] = 0.0;      
        Cq[1] = 0.0;     
        Cq[2] = 0.0;      
        Cq[3] = -(4*py*dqw - 2*pz*dqx + 2*px*dqz);
        Cq[4] = -(2*dqy*px - 2*dqw*pz);
        Cq[5] = -(2*px*dqx + 4*py*dqy + 2*pz*dqz);
        Cq[6] = -(2*px*dqw + 2*pz*dqy);
        break;

      case 2:
        Cq[0] = 0.0;
        Cq[1] = 0.0;
        Cq[2] = 0.0;
        Cq[3] = -(4*pz*dqw + 2*py*dqx - 2*px*dqy);
        Cq[4] = -(2*dqz*px + 2*dqw*py);
        Cq[5] = -(2*py*dqz - 2*px*dqw);
        Cq[6] = -(4*pz*dqz + 2*py*dqy + 2*px*dqx);
        break;

      default:
        throw std::runtime_error("Invalid joint constraint index!");
    }
  }
}
Esempio n. 30
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]));
  }
}