def quaternion_slerp(q_1, q_2, fraction):
  """ Quaternion slerp between q_1 and q_2 at fraction ([0,1]).

  Spherical linear quaternion interpolation method.
  q_1 and q_2 should be unit quaternions.
  """
  assert fraction >= 0.0 and fraction <= 1.0, "fraction should be in [0,1]."
  assert isinstance(q_1, Quaternion), "q_1 should be of Quaternion type."
  assert isinstance(q_2, Quaternion), "q_2 should be of Quaternion type."
  assert np.isclose(
      q_1.norm(), 1.0, atol=1.e-8), "Slerp should only be used with unit quaternions."
  assert np.isclose(
      q_2.norm(), 1.0, atol=1.e-8), "Slerp should only be used with unit quaternions."

  q1 = q_1.q.copy()
  q2 = q_2.q.copy()
  if fraction == 0.0:
    return Quaternion(q=q1)
  if fraction == 1.0:
    return Quaternion(q=q2)

  dot_product = np.dot(q1, q2)
  if dot_product < 0.0:
    dot_product = -dot_product
    q1 *= -1

  # Stay within the domain of acos().
  dot_product = np.clip(dot_product, -1.0, 1.0)

  # Angle between q_1 and q_2.
  theta_prime = np.arccos(dot_product)
  theta = theta_prime * fraction

  q_3 = Quaternion(q=q2 - q1 * dot_product)
  q_3.normalize()

  return Quaternion(q=q1 * np.cos(theta)) + q_3 * np.sin(theta)
 Quaternion slerp between q_1 and q_2 at fraction ([0,1]).

  Spherical linear quaternion interpolation method.
  q_1 and q_2 should be unit quaternions.
  
hand_eye_calibration/python/hand_eye_calibration/quaternion.py