def compute_hand_eye_calibration_BASELINE(dq_B_H_vec, dq_W_E_vec, config):
  """
  Do the actual hand eye-calibration as described in the referenced paper.

  Outputs a tuple containing:
   - success
   - dq_H_E
   - (best_rmse_position, best_rmse_orientation)
   - best_num_inliers
   - num_poses_after_filtering
   - runtime
   - singular_values
   - bad_singular_values
  """
  assert len(dq_W_E_vec) == len(dq_B_H_vec)
  num_poses = len(dq_W_E_vec)

  start_time = timeit.default_timer()

  # Enforce the same sign of the rotation quaternion.
  for i in range(num_poses):
    dq_B_H = dq_B_H_vec[i]
    dq_W_E = dq_W_E_vec[i]
    if ((dq_W_E.q_rot.w < 0. and dq_B_H.q_rot.w > 0.) or
            (dq_W_E.q_rot.w > 0. and dq_B_H.q_rot.w < 0.)):
      dq_W_E_vec[i].dq = -dq_W_E_vec[i].dq.copy()

  # 0.0 Reject pairs whose motion is not informative,
  # i.e. their screw axis dot product is large
  if config.prefilter_poses_enabled:
    dq_B_H_vec_filtered, dq_W_E_vec_filtered = prefilter_using_screw_axis(
        dq_B_H_vec, dq_W_E_vec, config.prefilter_dot_product_threshold)
  else:
    dq_B_H_vec_filtered = dq_B_H_vec
    dq_W_E_vec_filtered = dq_W_E_vec
  num_poses_after_filtering = len(dq_W_E_vec_filtered)

  best_idx = -1
  best_num_inliers = config.min_num_inliers - 1
  best_dq_W_E_vec_inlier = []
  best_dq_B_H_vec_inlier = []

  if config.enable_exhaustive_search:
    print("Do exhaustive search to find biggest subset of inliers...")
  else:
    print("Search for first set of inliers bigger than {}...".format(
        config.min_num_inliers))

  # 0.1 Reject pairs where scalar parts of dual quaternions do not match.
  # Loop over all the indices to find an index of a pose pair.
  for j in range(num_poses_after_filtering):
    # Re-align all dual quaternion to the j-th dual quaternion.
    dq_W_E_vec_aligned = align_paths_at_index(dq_W_E_vec_filtered, j)
    dq_B_H_vec_aligned = align_paths_at_index(dq_B_H_vec_filtered, j)

    dq_W_E_vec_inlier = []
    dq_B_H_vec_inlier = []

    # Loop over the indices again starting at the first index to find either:
    # - The first set of inliers of at least size min_num_inliers
    #       OR
    # - The largest set of inliers using an exhaustive search
    for i in range(0, num_poses_after_filtering):
      dq_W_E = dq_W_E_vec_aligned[i]
      dq_B_H = dq_B_H_vec_aligned[i]
      scalar_parts_W_E = dq_W_E.scalar()
      scalar_parts_B_H = dq_B_H.scalar()
      # Append the inliers to the filtered dual quaternion vectors.
      if np.allclose(scalar_parts_W_E.dq, scalar_parts_B_H.dq, atol=1e-2):
        dq_W_E_vec_inlier.append(dq_W_E)
        dq_B_H_vec_inlier.append(dq_B_H)

    assert len(dq_W_E_vec_inlier) == len(dq_B_H_vec_inlier)

    if config.enable_exhaustive_search:
      has_the_most_inliers = (len(dq_W_E_vec_inlier) > best_num_inliers)
      if has_the_most_inliers:
        best_num_inliers = len(dq_W_E_vec_inlier)
        best_idx = j
        best_dq_W_E_vec_inlier = copy.deepcopy(dq_W_E_vec_inlier)
        best_dq_B_H_vec_inlier = copy.deepcopy(dq_B_H_vec_inlier)
        print("Found new best start idx: {} number of inliers: {}".format(
            best_idx, best_num_inliers))
    else:
      has_enough_inliers = (len(dq_W_E_vec_inlier) > config.min_num_inliers)
      if has_enough_inliers:
        best_idx = j
        best_num_inliers = len(dq_W_E_vec_inlier)
        break

      assert (j + 1) < num_poses_after_filtering, (
          "Reached over all filtered poses and couldn't find "
          "enough inliers. num_samples: {}, num_inliers: {}".format(
              num_poses_after_filtering, len(dq_W_E_vec_inlier)))

  if config.enable_exhaustive_search:
    assert best_idx != -1, "Not enough inliers found!"
    dq_W_E_vec_inlier = best_dq_W_E_vec_filtered
    dq_B_H_vec_inlier = best_dq_B_H_vec_inlier

  aligned_dq_B_H = align_paths_at_index(dq_B_H_vec_inlier, best_idx)
  aligned_dq_W_E = align_paths_at_index(dq_W_E_vec_inlier, best_idx)

  print("Best start idx: {}".format(best_idx))
  print("Removed {} outliers from the (prefiltered) poses.".format(
      len(dq_B_H_vec_filtered) - len(dq_B_H_vec_inlier)))
  print("Running the hand-eye calibration with the remaining {} pairs of "
        "poses".format(len(dq_B_H_vec_inlier)))

  try:
    # Compute hand-eye calibration on the inliers.
    (dq_H_E_estimated,
     singular_values,
     bad_singular_values) = compute_hand_eye_calibration(
        dq_B_H_vec_inlier, dq_W_E_vec_inlier,
        config.hand_eye_calibration_scalar_part_equality_tolerance)
    dq_H_E_estimated.normalize()
  except:
    print("\n\n Hand-eye calibration FAILED! "
          "algorithm_name: {} exception: \n\n".format(
              config.algorithm_name, sys.exc_info()[0]))
    end_time = timeit.default_timer()
    runtime = end_time - start_time
    return (False, None, (None, None),
            None, num_poses_after_filtering, runtime, None, None)

  # Evaluate hand-eye calibration either on all poses aligned by the
  # sample index or only on the inliers.
  if config.ransac_evaluate_refined_model_on_inliers_only:
    (poses_B_H, poses_W_H) = get_aligned_poses(dq_B_H_vec_inlier,
                                               dq_W_E_vec_inlier,
                                               dq_H_E_estimated)
  else:
    # TODO(mfehr): There is some redundancy here, fix it!
    aligned_dq_B_H = align_paths_at_index(dq_B_H_vec, best_idx)
    aligned_dq_W_E = align_paths_at_index(dq_W_E_vec, best_idx)
    (poses_B_H, poses_W_H) = get_aligned_poses(aligned_dq_B_H,
                                               aligned_dq_W_E,
                                               dq_H_E_estimated)

  (rmse_position,
   rmse_orientation,
   inlier_flags) = evaluate_alignment(poses_B_H, poses_W_H, config, config.visualize)

  end_time = timeit.default_timer()
  runtime = end_time - start_time

  pose_vec = dq_H_E_estimated.to_pose()
  print("Solution found by aligned based on idx: {}\n"
        "\t\tNumber of inliers: {}\n"
        "\t\tRMSE position:     {:10.4f}\n"
        "\t\tRMSE orientation:  {:10.4f}\n"
        "\t\tdq_H_E:    {}\n"
        "\t\tpose_H_E:  {}\n"
        "\t\tTranslation norm:  {:10.4f}".format(
            best_idx, best_num_inliers, rmse_position,
            rmse_orientation, dq_H_E_estimated,
            pose_vec, np.linalg.norm(pose_vec[0:3])))

  return (True, dq_H_E_estimated,
          (rmse_position, rmse_orientation),
          best_num_inliers, num_poses_after_filtering, runtime, singular_values, bad_singular_values)

  Do the actual hand eye-calibration as described in the referenced paper.

  Outputs a tuple containing:
   - success
   - dq_H_E
   - (best_rmse_position, best_rmse_orientation)
   - best_num_inliers
   - num_poses_after_filtering
   - runtime
   - singular_values
   - bad_singular_values
  
hand_eye_calibration/python/hand_eye_calibration/dual_quaternion_hand_eye_calibration.py