async def test_correct_hotspots():
    config = robot_configs.build_config([], {})

    tip_length = 47
    switch_clearance = 7.5
    x_switch_offset = 2.0
    y_switch_offset = 5.0
    z_switch_offset = 5.0
    deck_clearance = 5.0
    z_probe_clearance = 5.0
    z_start_clearance = 20.0

    size_x, size_y, size_z = config.tip_probe.dimensions

    rel_x_start = (size_x / 2) + switch_clearance
    rel_y_start = (size_y / 2) + switch_clearance
    center = [293.03, 301.27, 74.3]

    nozzle_safe_z = round((size_z - tip_length) + z_probe_clearance, 3)
    z_start = max(deck_clearance, nozzle_safe_z)
    expected = [robot_configs.HotSpot('x',
                                      -rel_x_start,
                                      x_switch_offset,
                                      z_start,
                                      size_x),
                robot_configs.HotSpot('x',
                                      rel_x_start,
                                      x_switch_offset,
                                      z_start,
                                      -size_x),
                robot_configs.HotSpot('y',
                                      y_switch_offset,
                                      -rel_y_start,
                                      z_start,
                                      size_y),
                robot_configs.HotSpot('y',
                                      y_switch_offset,
                                      rel_y_start,
                                      z_start,
                                      -size_y),
                robot_configs.HotSpot('z',
                                      0,
                                      z_switch_offset,
                                      center[2] + z_start_clearance,
                                      -size_z)]

    actual = robot_configs.calculate_tip_probe_hotspots(
        tip_length,
        config.tip_probe)

    assert expected == actual
示例#2
0
def probe_instrument(instrument, robot, tip_length=None) -> Point:
    robot.home()
    tp = robot.config.tip_probe
    if tip_length is None:
        tip_length = robot.config.tip_length[instrument.model]
    instrument._add_tip(tip_length)

    # probe_center is the point at the center of the switch pcb
    center = Point(*tp.center)

    hot_spots = robot_configs.calculate_tip_probe_hotspots(tip_length, tp)

    # The saved axis positions from limit switch response
    axis_pos = []

    safe_height = _calculate_safeheight(robot, tp.z_clearance.crossover)

    log.info("Moving to safe z: {}".format(safe_height))
    robot.poses = instrument._move(robot.poses, z=safe_height)

    for hs in hot_spots:
        x0 = tp.center[0] + hs.x_start_offs
        y0 = tp.center[1] + hs.y_start_offs
        z0 = hs.z_start_abs

        log.info("Moving to {}".format((x0, y0, z0)))
        robot.poses = instrument._move(robot.poses, x=x0, y=y0)
        robot.poses = instrument._move(robot.poses, z=z0)

        axis_index = 'xyz'.index(hs.axis)
        robot.poses = instrument._probe(robot.poses, hs.axis,
                                        hs.probe_distance)

        # Tip position is stored in accumulator and averaged for each axis
        # to be used for more accurate positioning for the next axis
        value = absolute(robot.poses, instrument)[axis_index]
        axis_pos.append(value)

        # after probing two points along the same axis
        # average them out, update center and clear accumulator
        # except Z, we're only probing that once
        if hs.axis == 'z':
            center = center._replace(**{hs.axis: axis_pos[0]})
            axis_pos.clear()
        elif len(axis_pos) == 2:
            center = center._replace(
                **{hs.axis: (axis_pos[0] + axis_pos[1]) / 2.0})

            axis_pos.clear()

        log.debug("Current axis positions for {}: {}".format(
            hs.axis, axis_pos))

        # Bounce back to release end stop
        sgn = hs.probe_distance / abs(hs.probe_distance)
        bounce = value + (tp.bounce_distance * -sgn)

        robot.poses = instrument._move(robot.poses, **{hs.axis: bounce})
        robot.poses = instrument._move(robot.poses, z=safe_height)

        log.debug("Updated center point tip probe {}".format(center))

    instrument._remove_tip(tip_length)

    return center
示例#3
0
async def test_moves_to_hotspot(hardware_api, monkeypatch, mount,
                                pipette_model):
    move_calls = []
    rel_calls = []
    probe_calls = []

    old_move_to = hardware_api.move_to
    old_move_rel = hardware_api.move_rel
    old_probe = hardware_api._backend.probe

    async def fake_move_to(which_mount, point):
        move_calls.append((which_mount, point))
        return await old_move_to(which_mount, point)

    async def fake_move_rel(which_mount, delta):
        rel_calls.append((which_mount, delta))
        return await old_move_rel(which_mount, delta)

    def fake_probe(ax, dist):
        probe_calls.append((ax, dist))
        return old_probe(ax, dist)

    monkeypatch.setattr(hardware_api, 'move_to', fake_move_to)
    monkeypatch.setattr(hardware_api, 'move_rel', fake_move_rel)
    monkeypatch.setattr(hardware_api._backend, 'probe', fake_probe)

    await hardware_api.cache_instruments(
        {mount: name_for_model(pipette_model)})
    await hardware_api.home()

    center = await hardware_api.locate_tip_probe_center(mount, 30)
    hotspots = robot_configs.calculate_tip_probe_hotspots(
        30, hardware_api._config.tip_probe)
    assert len(move_calls) == len(hotspots) * 4
    assert len(rel_calls) == len(hotspots)
    move_iter = iter(move_calls)
    rel_iter = iter(rel_calls)
    probe_iter = iter(probe_calls)
    bounce_base = hardware_api._config.tip_probe.bounce_distance
    old_center = hardware_api._config.tip_probe.center
    for hs in hotspots:
        x0 = old_center[0] + hs.x_start_offs
        y0 = old_center[1] + hs.y_start_offs
        z0 = hs.z_start_abs
        next(move_iter)
        next(move_iter)
        rel = next(rel_iter)
        if hs.probe_distance < 0:
            bounce = bounce_base
        else:
            bounce = -bounce_base
        assert rel[1] == Point(**{hs.axis: bounce})
        prep_point = next(move_iter)
        assert prep_point[1] == Point(x0, y0, z0)
        probe = next(probe_iter)
        assert probe[0] == hs.axis if hs.axis != 'z' else 'a'
        assert probe[1] == hs.probe_distance
        next(move_iter)

    targ = Point(*hardware_api._config.tip_probe.center)
    # The x and y are the same because the offsets from our naive mock of
    # probe() should cancel out, but the z only has one side so we need
    # to figure out what it will be
    targ = targ._replace(z=hotspots[-1][3] + hotspots[-1][4])
    assert list(center) == pytest.approx(targ)