예제 #1
0
void scaleQuaternion(
  double gain,
  double& dq0, double& dq1, double& dq2, double& dq3)
{
	if (dq0 < 0.0)//0.9
  {
    // Slerp (Spherical linear interpolation):
    double angle = acos(dq0);
    double A = sin(angle*(1.0 - gain))/sin(angle);
    double B = sin(angle * gain)/sin(angle);
    dq0 = A + B * dq0;
    dq1 = B * dq1;
    dq2 = B * dq2;
    dq3 = B * dq3;
  }
  else
  {
    // Lerp (Linear interpolation):
    dq0 = (1.0 - gain) + gain * dq0;
    dq1 = gain * dq1;
    dq2 = gain * dq2;
    dq3 = gain * dq3;
  }

  normalizeQuaternion(dq0, dq1, dq2, dq3);
}
예제 #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
__inline void cleanQuaternion(double *quaternion) {
  if ((quaternion[0] * quaternion[0] + quaternion[3] * quaternion[3]) < NUM_TOL_SQ) {
    quaternion[0] = 1e-5;
    quaternion[3] = -1e-5;
  }
  if ((quaternion[1] * quaternion[1] + quaternion[2] * quaternion[2]) < NUM_TOL_SQ) {
    quaternion[1] = 1e-5;
    quaternion[2] = -1e-5;
  }
  /* normalize */
  normalizeQuaternion(quaternion);
}
void TaitBryanToQuaternion(float v[3], float q[4]){
	float cosX2 = cosf(v[VEC3_X] / 2.0f);
	float sinX2 = sinf(v[VEC3_X] / 2.0f);
	float cosY2 = cosf(v[VEC3_Y] / 2.0f);
	float sinY2 = sinf(v[VEC3_Y] / 2.0f);
	float cosZ2 = cosf(v[VEC3_Z] / 2.0f);
	float sinZ2 = sinf(v[VEC3_Z] / 2.0f);

	q[QUAT_W] = cosX2 * cosY2 * cosZ2 + sinX2 * sinY2 * sinZ2;
	q[QUAT_X] = sinX2 * cosY2 * cosZ2 - cosX2 * sinY2 * sinZ2;
	q[QUAT_Y] = cosX2 * sinY2 * cosZ2 + sinX2 * cosY2 * sinZ2;
	q[QUAT_Z] = cosX2 * cosY2 * sinZ2 - sinX2 * sinY2 * cosZ2;

	normalizeQuaternion(q);
}
예제 #5
0
void ComplementaryFilter::getPrediction(
    double wx, double wy, double wz, double dt,
    double& q0_pred, double& q1_pred, double& q2_pred, double& q3_pred) const
{
  double wx_unb = wx - wx_bias_;
  double wy_unb = wy - wy_bias_;
  double wz_unb = wz - wz_bias_;

  q0_pred = q0_ + 0.5*dt*( wx_unb*q1_ + wy_unb*q2_ + wz_unb*q3_);
  q1_pred = q1_ + 0.5*dt*(-wx_unb*q0_ - wy_unb*q3_ + wz_unb*q2_);
  q2_pred = q2_ + 0.5*dt*( wx_unb*q3_ - wy_unb*q0_ - wz_unb*q1_);
  q3_pred = q3_ + 0.5*dt*(-wx_unb*q2_ + wy_unb*q1_ - wz_unb*q0_);

  normalizeQuaternion(q0_pred, q1_pred, q2_pred, q3_pred);
}
예제 #6
0
void gradientDescent(double *wPrimeWPrimeTranspose, int iFrame, int jFrame, double * wPairwiseProd, double *errArray, double *quaternionArray, char *isDone, int nFrame, int nPoint, double *RTransposeR, double *dRTransposeR, double *quaternionTmp, double *gradient) {
  int i, ii, j, k;
  double errMin, errTmp, errMinOld;
  double *quaternionMin;
  int nItr;
  double lambda;
  double normGradSq;
  int nItrLine;
  
  /* update the wPrimeWPrimeTranspose matrix */
  updateW(wPairwiseProd, iFrame, jFrame, nFrame, wPrimeWPrimeTranspose);
  
  /* Figure out the best guess to start from */
  quaternionMin = quaternionArray + 4 * (iFrame * nFrame + jFrame);
  
  /* Go over all the neighbors around the current location to find the best one */
  if (isDone[jFrame * nFrame + iFrame])
    errMin = errArray[jFrame * nFrame + iFrame];
  else
    errMin = -1;
  for (i = iFrame - 1; i <= iFrame + 1; ++i)
    for (j = jFrame - 1; j <= jFrame + 1; ++j)
      if ((i >= 0) && (i < nFrame) && (j >= 0) && (j < nFrame)
      && isDone[j * nFrame + i]) {
    /* and check which one already gives the smallest value */
    copyQuaternion(quaternionArray + 4 * (i * nFrame + j), quaternionTmp, 1);
    
    errTmp = reconstrPairVal(quaternionTmp, wPrimeWPrimeTranspose, RTransposeR);
    
    /* Keep the best pick */
    if ((errTmp < errMin) || (errMin < 0)) {
      errMin = errTmp;
      copyQuaternion(quaternionTmp, quaternionMin, 0);
    }
      }
  
  /* Start from that optimal value and perform gradient descent */
  lambda=1.0;
  
  /* fprintf(stderr,"Start error %f\n", errMin); */
  for (nItr = 0; nItr < 40; ++nItr) {
    errMin = reconstrPairValGrad(quaternionMin, wPrimeWPrimeTranspose, gradient, RTransposeR, dRTransposeR);
    
    /* stop if the gradient is too small or the error too */
    normGradSq = normSq(4, gradient);
    
    if ((normGradSq < NUM_TOL_SQ) || (errMin < NUM_TOL ))
      break;
    
    /* Perform line search */
    errMinOld=errMin;
    for (nItrLine = 0; nItrLine < 20; ++nItrLine) {
      /* get the value for the current quaternion */
      for (k = 0; k < 4; ++k)
        quaternionTmp[k] = quaternionMin[k] - lambda * gradient[k];
      
      cleanQuaternion(quaternionTmp);
      
      errTmp = reconstrPairVal(quaternionTmp, wPrimeWPrimeTranspose, RTransposeR);
      
      /* check if the error is better than what we had before */
      if (errTmp < errMin) {
        errMin = errTmp;
        copyQuaternion(quaternionTmp, quaternionMin, 0);
        
        break;
      } else
        lambda /= 2;
    }
    
    /* stop if the error does not change much, < 0.1 percent */
    if ((errMinOld-errMin)<0.001*errMinOld)
      break;
  }
  
  /* fprintf(stderr,"%i ", nItr);
   *update if nothing before or if the current result is better than before
   */
  if ((!isDone[iFrame * nFrame + jFrame]) || ((isDone[iFrame * nFrame + jFrame]) && (errMin <errArray[iFrame * nFrame + jFrame]))) {
    errArray[iFrame * nFrame + jFrame] = errMin;
    errArray[jFrame * nFrame + iFrame] = errMin;
    normalizeQuaternion(quaternionMin);
    copyQuaternion(quaternionMin, quaternionArray + 4 * (jFrame * nFrame + iFrame), 0);
    isDone[iFrame * nFrame + jFrame] = 1;
    isDone[jFrame * nFrame + iFrame] = 1;
  }
}