# Buggy code
def locate(
    visible_markers,
    camera_model,
    registered_markers_undist,
    registered_markers_dist,
):
    """Computes a Surface_Location based on a list of visible markers."""

    visible_registered_marker_ids = set(visible_markers.keys()) & set(
        registered_markers_undist.keys()
    )

    # If the surface is defined by 2+ markers, we require 2+ markers to be detected.
    # If the surface is defined by 1 marker, we require 1 marker to be detected.
    if not visible_registered_marker_ids or len(visible_registered_marker_ids) < min(
        2, len(registered_markers_undist)
    ):
        return Surface_Location(detected=False)

    visible_verts_dist = np.array(
        [visible_markers[id].verts_px for id in visible_registered_marker_ids]
    )
    registered_verts_undist = np.array(
        [
            registered_markers_undist[uid].verts_uv
            for uid in visible_registered_marker_ids
        ]
    )
    registered_verts_dist = np.array(
        [registered_markers_dist[uid].verts_uv for uid in visible_registered_marker_ids]
    )

    visible_verts_dist.shape = (-1, 2)
    registered_verts_undist.shape = (-1, 2)
    registered_verts_dist.shape = (-1, 2)

    dist_img_to_surf_trans, surf_to_dist_img_trans = Surface._find_homographies(
        registered_verts_dist, visible_verts_dist
    )

    visible_verts_undist = camera_model.undistort_points_on_image_plane(
        visible_verts_dist
    )
    img_to_surf_trans, surf_to_img_trans = Surface._find_homographies(
        registered_verts_undist, visible_verts_undist
    )

    return Surface_Location(
        True,
        dist_img_to_surf_trans,
        surf_to_dist_img_trans,
        img_to_surf_trans,
        surf_to_img_trans,
        len(visible_registered_marker_ids),
    )


# Traceback (TypeError)
2020-05-13 15:27:43,610 - player - [DEBUG] root: Recalculate Surface Cache!
2020-05-13 15:27:43,656 - Background Data Processor - [DEBUG] background_helper: Entering _wrapper
2020-05-13 15:27:43,661 - Background Data Processor - [DEBUG] surface_tracker.surface: Failed to calculate inverse homography with np.inv()! Trying with np.pinv() instead.
2020-05-13 15:27:43,663 - Background Data Processor - [INFO] background_helper: AttributeError: 'NoneType' object has no attribute 'conjugate'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "shared_modules\background_helper.py", line 73, in _wrapper
File "shared_modules\surface_tracker\background_tasks.py", line 189, in data_processing_generator
File "shared_modules\surface_tracker\background_tasks.py", line 176, in handle_sample
File "shared_modules\surface_tracker\offline_utils.py", line 35, in __call__
File "shared_modules\surface_tracker\surface.py", line 323, in locate
File "shared_modules\surface_tracker\surface.py", line 363, in _find_homographies
File "<__array_function__ internals>", line 6, in pinv
File "site-packages\numpy\linalg\linalg.py", line 1969, in pinv
TypeError: loop of ufunc does not support argument 0 of type NoneType which has no callable conjugate method

# Fixed code
def locate(
    visible_markers,
    camera_model,
    registered_markers_undist,
    registered_markers_dist,
):
    """Computes a Surface_Location based on a list of visible markers."""

    visible_registered_marker_ids = set(visible_markers.keys()) & set(
        registered_markers_undist.keys()
    )

    # If the surface is defined by 2+ markers, we require 2+ markers to be detected.
    # If the surface is defined by 1 marker, we require 1 marker to be detected.
    if not visible_registered_marker_ids or len(visible_registered_marker_ids) < min(
        2, len(registered_markers_undist)
    ):
        return Surface_Location(detected=False)

    visible_verts_dist = np.array(
        [visible_markers[id].verts_px for id in visible_registered_marker_ids]
    )
    registered_verts_undist = np.array(
        [
            registered_markers_undist[uid].verts_uv
            for uid in visible_registered_marker_ids
        ]
    )
    registered_verts_dist = np.array(
        [registered_markers_dist[uid].verts_uv for uid in visible_registered_marker_ids]
    )

    visible_verts_dist.shape = (-1, 2)
    registered_verts_undist.shape = (-1, 2)
    registered_verts_dist.shape = (-1, 2)

    dist_img_to_surf_trans, surf_to_dist_img_trans = Surface._find_homographies(
        registered_verts_dist, visible_verts_dist
    )

    if None in (dist_img_to_surf_trans, surf_to_dist_img_trans):
        return Surface_Location(detected=False)

    visible_verts_undist = camera_model.undistort_points_on_image_plane(
        visible_verts_dist
    )
    img_to_surf_trans, surf_to_img_trans = Surface._find_homographies(
        registered_verts_undist, visible_verts_undist
    )

    if None in (img_to_surf_trans, surf_to_img_trans):
        return Surface_Location(detected=False)

    return Surface_Location(
        True,
        dist_img_to_surf_trans,
        surf_to_dist_img_trans,
        img_to_surf_trans,
        surf_to_img_trans,
        len(visible_registered_marker_ids),
    )