Vector4d rigidBodyDynamics::quaternionDivision(Vector4d& q1, Vector4d& q2) const {
	Vector4d q2inv;

	q2inv << -q2(0) , -q2(1) , -q2(2) , q2(3);

	Vector4d result = quaternionMultiplication(q1,q2inv);
	return result;
}
예제 #2
0
void ComplementaryFilter::updateImpl(
		double gx, double gy, double gz,
		double ax, double ay, double az,
	    double dt)
{
  if (!initialized_)
  {
    // First time - ignore prediction:
    getMeasurement(ax, ay, az,
                   q0_, q1_, q2_, q3_);
    initialized_ = true;
    return;
  }

  if(dt <= 0.0)
  {
    UERROR("dt=%f <=0.0, orientation will not be updated!", dt);
    return;
  }

  // Bias estimation.
  if (do_bias_estimation_)
    updateBiases(ax, ay, az, gx, gy, gz);

  // Prediction.
  double q0_pred, q1_pred, q2_pred, q3_pred;
  getPrediction(gx, gy, gz, dt,
                q0_pred, q1_pred, q2_pred, q3_pred);

  // Correction (from acc):
  // q_ = q_pred * [(1-gain) * qI + gain * dq_acc]
  // where qI = identity quaternion
  double dq0_acc, dq1_acc, dq2_acc, dq3_acc;
  getAccCorrection(ax, ay, az,
                   q0_pred, q1_pred, q2_pred, q3_pred,
                   dq0_acc, dq1_acc, dq2_acc, dq3_acc);

  double gain;
  if (do_adaptive_gain_)
  {
    gain = getAdaptiveGain(gain_acc_, ax, ay, az);

  }
  else
  {
    gain = gain_acc_;

  }

  scaleQuaternion(gain, dq0_acc, dq1_acc, dq2_acc, dq3_acc);

  quaternionMultiplication(q0_pred, q1_pred, q2_pred, q3_pred,
                           dq0_acc, dq1_acc, dq2_acc, dq3_acc,
                           q0_, q1_, q2_, q3_);

  normalizeQuaternion(q0_, q1_, q2_, q3_);
}
예제 #3
0
void ComplementaryFilter::getMeasurement(
    double ax, double ay, double az,
    double mx, double my, double mz,
    double& q0_meas, double& q1_meas, double& q2_meas, double& q3_meas)
{
  // q_acc is the quaternion obtained from the acceleration vector representing
  // the orientation of the Global frame wrt the Local frame with arbitrary yaw
  // (intermediary frame). q3_acc is defined as 0.
  double q0_acc, q1_acc, q2_acc, q3_acc;

  // Normalize acceleration vector.
  normalizeVector(ax, ay, az);
  if (az >=0)
    {
      q0_acc =  sqrt((az + 1) * 0.5);
      q1_acc = -ay/(2.0 * q0_acc);
      q2_acc =  ax/(2.0 * q0_acc);
      q3_acc = 0;
    }
    else
    {
      double X = sqrt((1 - az) * 0.5);
      q0_acc = -ay/(2.0 * X);
      q1_acc = X;
      q2_acc = 0;
      q3_acc = ax/(2.0 * X);
    }

  // [lx, ly, lz] is the magnetic field reading, rotated into the intermediary
  // frame by the inverse of q_acc.
  // l = R(q_acc)^-1 m
  double lx = (q0_acc*q0_acc + q1_acc*q1_acc - q2_acc*q2_acc)*mx +
      2.0 * (q1_acc*q2_acc)*my - 2.0 * (q0_acc*q2_acc)*mz;
  double ly = 2.0 * (q1_acc*q2_acc)*mx + (q0_acc*q0_acc - q1_acc*q1_acc +
      q2_acc*q2_acc)*my + 2.0 * (q0_acc*q1_acc)*mz;

  // q_mag is the quaternion that rotates the Global frame (North West Up) into
  // the intermediary frame. q1_mag and q2_mag are defined as 0.
	double gamma = lx*lx + ly*ly;
	double beta = sqrt(gamma + lx*sqrt(gamma));
  double q0_mag = beta / (sqrt(2.0 * gamma));
  double q3_mag = ly / (sqrt(2.0) * beta);

  // The quaternion multiplication between q_acc and q_mag represents the
  // quaternion, orientation of the Global frame wrt the local frame.
  // q = q_acc times q_mag
  quaternionMultiplication(q0_acc, q1_acc, q2_acc, q3_acc,
                           q0_mag, 0, 0, q3_mag,
                           q0_meas, q1_meas, q2_meas, q3_meas );
  //q0_meas = q0_acc*q0_mag;
  //q1_meas = q1_acc*q0_mag + q2_acc*q3_mag;
  //q2_meas = q2_acc*q0_mag - q1_acc*q3_mag;
  //q3_meas = q0_acc*q3_mag;
}
Vector4d rigidBodyDynamics::addQuaternionError(Vector3d& mrp, Vector4d& qref) const{
	Vector4d qnew, dq;
	dq = mrp2quaternion(mrp);

	Vector4d qnew1 = quaternionMultiplication(dq, qref);

	if (qnew1.dot(qref) >= 0) {
		return qnew1;
	} else {
		Vector4d qnew2 = -1 * qnew1;
		return qnew2;
	}

}