示例#1
0
class Batch:
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol_printer = Printer(prefix=(batch.RESPONSE_PREFIX +
                                                'Echo: '))
        self.command_printer = MessagePrinter(prefix='  Sending: ')
        self.protocol = Protocol(response_receivers=[self.protocol_printer],
                                 command_receivers=[self.command_printer])
        self.response_printer = MessagePrinter(prefix=batch.RESPONSE_PREFIX)
        self.messaging_stack.register_response_receivers(self.response_printer)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        print('Running test routine...')
        await asyncio.sleep(1.0)

        for i in range(10):
            await self.protocol.request(i)
        await asyncio.sleep(1.0)

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
class Batch:
    """Actor-based batch execution."""

    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol_printer = Printer(prefix=batch.RESPONSE_PREFIX)
        self.command_printer = MessagePrinter(prefix='  Sending: ')
        self.protocol = Protocol(
            response_receivers=[self.protocol_printer],
            command_receivers=[self.command_printer]
        )
        self.response_printer = MessagePrinter(prefix=batch.RESPONSE_PREFIX)
        self.messaging_stack.register_response_receivers(self.response_printer)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter, self.messaging_stack.command_sender,
            self.test_routine, header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.wait_connected
        )
        self.messaging_stack.register_execution_manager(self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        print('Running test routine...')
        await asyncio.sleep(1.0)

        print('RPC-style with empty payloads:')
        await self.protocol.request()
        await self.protocol.blink.request()
        await self.protocol.blink.high_interval.request()
        await self.protocol.blink.low_interval.request()
        await self.protocol.blink.periods.request()
        await self.protocol.blink.notify.request()

        print('RPC with complete wait for finite-periods blink:')
        await self.protocol.blink.notify.request(1)
        await self.protocol.blink.low_interval.request(500)
        await self.protocol.blink.high_interval.request(500)
        await self.protocol.blink.request_complete(5)
        await asyncio.sleep(1.0)

        print('RPC-style manual blink:')
        for i in range(10):
            await self.protocol.request(1)
            await asyncio.sleep(0.25)
            await self.protocol.request(0)
            await asyncio.sleep(0.25)

        print('RPC-style without waiting for blink completion:')
        await self.protocol.blink.notify.request(0)
        await self.protocol.blink.low_interval.request(100)
        await self.protocol.blink.high_interval.request(100)
        await self.protocol.blink.request(1)
        await asyncio.sleep(5.0)

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
示例#3
0
class Batch:
    """Actor-based batch execution."""

    def __init__(self, transport_loop, axis):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol = Protocol('{}-Axis'.format(axis.upper()), axis)
        self.protocol_plotter = Plotter(self.protocol)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter, self.messaging_stack.command_sender,
            self.test_routine, header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.wait_connected
        )
        self.messaging_stack.register_execution_manager(self.batch_execution_manager)
        print('Showing plot...')
        self.protocol_plotter.show()

    async def test_routine(self):
        """Run the batch execution test routine."""
        print('Running test routine...')
        await self.protocol.initialized.wait()
        self.colors = {
            0: 'gray',  # braking
            -1: 'orange',  # stalled
            -2: 'green',  # converged
            -3: 'red',  # timer
        }

        print('Motor position feedback control with position and motor duty notification')
        await self.protocol.position.notify.change_only.request(0)
        await self.protocol.position.notify.interval.request(20)
        await self.protocol.motor.notify.change_only.request(0)
        await self.protocol.motor.notify.interval.request(20)
        await self.protocol.position.notify.request(2)
        await self.protocol.motor.notify.request(2)
        for i in range(10):
            await self.go_to_position(100)
            await asyncio.sleep(0.5)
            await self.go_to_position(700)
            await asyncio.sleep(0.5)
        await self.protocol.position.notify.request(0)
        await self.protocol.motor.notify.request(0)

        print(batch.OUTPUT_FOOTER)
        print('Idling...')
        self.protocol_plotter.server.run_until_shutdown()

    async def go_to_position(self, position):
        """Send the actuator to the specified position."""
        self.protocol_plotter.position_plotter.add_arrow(position, slope=2)
        self.protocol_plotter.duty_plotter.start_state_region()
        await self.protocol.feedback_controller.request_complete(position)
        self.protocol_plotter.duty_plotter.add_state_region(
            self.colors[self.protocol.last_response_payload]
        )
class Batch():
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.axis = Axis()
        self.messaging_stack.register_response_receivers(self.axis.protocol)
        self.messaging_stack.register_command_senders(self.axis.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        self.prompt = Prompt(end='', flush=True)

        print('Running test routine...')
        await self.axis.wait_until_initialized()
        await self.axis.synchronize_values()
        self.axis.load_calibration_json()
        self.axis.load_discrete_json()
        print('Physical calibration:',
              self.axis.calibration_data['parameters'])

        print('Testing discrete position targeting...')
        relative_heights = ['above', 'top', 'high', 'mid', 'low', 'bottom']

        await self.axis.go_to_high_end_position()
        await self.prompt('Testing cuvette positioning: ')
        for height in relative_heights:
            print('Moving to {}...'.format(height))
            await self.axis.go_to_cuvette(height)
            await self.prompt('Press enter to continue: ')
            await self.axis.go_to_cuvette('far above')
        await self.axis.go_to_high_end_position()
        await self.prompt('Testing 96-well plate positioning: ')
        for height in relative_heights:
            print('Moving to {}...'.format(height))
            await self.axis.go_to_96_well_plate(height)
            await self.prompt('Press enter to continue: ')
            await self.axis.go_to_96_well_plate('far above')

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
class Batch:
    """Actor-based batch execution."""

    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol_printer = Printer(prefix=(batch.RESPONSE_PREFIX))
        self.command_printer = MessagePrinter(prefix='  Sending: ')
        self.protocol = Protocol(
            self.messaging_stack.connection_synchronizer,
            response_receivers=[self.protocol_printer],
            command_receivers=[self.command_printer]
        )
        self.response_printer = MessagePrinter(prefix=batch.RESPONSE_PREFIX)
        self.messaging_stack.register_response_receivers(self.response_printer)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)

        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter, self.messaging_stack.command_sender,
            self.test_routine, header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.wait_connected
        )
        self.messaging_stack.register_execution_manager(self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        print('Running test routine...')
        await asyncio.sleep(1.0)

        print('RPC-style with completion wait:')
        await self.protocol.request_complete()
        await asyncio.sleep(2.0)
        print(batch.RESPONSE_PREFIX + 'Reset completed!')

        print('RPC-style with acknowledgement response wait:')
        await self.protocol.request()
        print(batch.RESPONSE_PREFIX + 'Reset command acknowledged!')
        await self.messaging_stack.connection_synchronizer.disconnected.wait()
        print(batch.RESPONSE_PREFIX + 'Connection lost!')
        await self.messaging_stack.connection_synchronizer.connected.wait()
        print(batch.RESPONSE_PREFIX + 'Reset completed!')
        await asyncio.sleep(2.0)

        await asyncio.sleep(2.0)
        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
示例#6
0
class Batch:
    """Actor-based batch execution."""

    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol_printer = Printer(prefix=batch.RESPONSE_PREFIX)
        self.command_printer = MessagePrinter(prefix='  Sending: ')
        self.protocol = Protocol(
            response_receivers=[self.protocol_printer],
            command_receivers=[self.command_printer]
        )
        self.response_printer = MessagePrinter(prefix=batch.RESPONSE_PREFIX)
        self.messaging_stack.register_response_receivers(self.response_printer)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter, self.messaging_stack.command_sender,
            self.test_routine, header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.wait_connected
        )
        self.messaging_stack.register_execution_manager(self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        prompt = Prompt()

        print('Running test routine...')
        await asyncio.sleep(1.0)

        await prompt('Press enter to start blinking:')

        print('Blinking 5 times:')
        await self.protocol.blink.notify.request(1)
        await self.protocol.blink.low_interval.request(250)
        await self.protocol.blink.high_interval.request(250)
        await self.protocol.blink.request_complete(5)

        while True:
            blinks = await prompt('Enter the number of times to blink:')
            try:
                blinks = int(blinks)
                if blinks <= 0:
                    raise ValueError
                break
            except ValueError:
                print('Invalid input!')

        print('Blinking {} times:'.format(blinks))
        await self.protocol.blink.notify.request(1)
        await self.protocol.blink.request_complete(blinks)

        await self.protocol.blink.notify.request(0)
        asyncio.ensure_future(self.protocol.blink.request(1))
        await prompt(
            'Blinking indefinitely. Press enter to stop blinking, '
            'turn the LED on, and exit:'
        )
        await self.protocol.request(1)

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
class Batch:
    """Actor-based batch execution."""

    def __init__(self, transport_loop, axis):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol = Protocol('{}-Axis'.format(axis.upper()), axis)
        self.dashboard = LinearActuatorControlModel(self.protocol)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter, self.messaging_stack.command_sender,
            self.test_routine,
            ready_waiter=self.messaging_stack.connection_synchronizer.wait_connected
        )
        self.messaging_stack.register_execution_manager(self.batch_execution_manager)
        print('Showing dashboard...')
        self.dashboard.show()

    async def test_routine(self):
        """Run the batch execution test routine."""
        self.prompt = Prompt(end='', flush=True)

        print('Waiting for {} to initialize...'.format(self.protocol.channel_path))
        await self.protocol.initialized.wait()
        self.colors = {
            0: 'gray',  # braking
            -1: 'orange',  # stalled
            -2: 'green',  # converged
            -3: 'red',  # timer
        }

        print('Requesting all motor parameter values...')
        await self.protocol.motor.request_all()

        print('Requesting all feedback controller parameter values...')
        await self.protocol.feedback_controller.request_all()

        self.num_cycles = 5
        self.low_position = 100
        self.high_position = 700
        await self.set_test_parameters()
        await self.prompt('Press enter to begin: ')
        await self.dashboard.plotter.toggler.start_plotting()
        try:
            while True:
                for i in range(self.num_cycles):
                    await self.go_to_position(self.low_position)
                    await asyncio.sleep(0.5)
                    await self.go_to_position(self.high_position)
                    await asyncio.sleep(0.5)
                print('Finished test cycles!')
                self.dashboard.plotter.position_plotter.stop_plotting()
                self.dashboard.plotter.duty_plotter.stop_plotting()
                await self.set_test_parameters()
                await self.prompt('Press enter to restart: ')
                self.dashboard.plotter.position_plotter.clear()
                self.dashboard.plotter.duty_plotter.clear()
                if self.dashboard.plotter.toggler.plotting:
                    self.dashboard.plotter.position_plotter.start_plotting()
                    self.dashboard.plotter.duty_plotter.start_plotting()
        except KeyboardInterrupt:
            await self.dashboard.plotter.toggler.stop_plotting()

        print('Idling...')
        self.dashboard.plotter.server.run_until_shutdown()

    async def set_test_parameters(self):
        """Set the test motion parameters."""
        self.num_cycles = await self.prompt.number(
            'How many test cycles to run?', self.num_cycles
        )
        self.low_position = await self.prompt.number(
            'Low target position?', self.low_position
        )
        self.high_position = await self.prompt.number(
            'High target position?', self.high_position
        )

    async def go_to_position(self, position):
        """Send the actuator to the specified position."""
        self.dashboard.plotter.position_plotter.add_arrow(position, slope=2)
        self.dashboard.plotter.duty_plotter.start_state_region()
        await self.protocol.feedback_controller.request_complete(position)
        self.dashboard.plotter.duty_plotter.add_state_region(
            self.colors[self.protocol.last_response_payload]
        )
        self.dashboard.feedback_controller.errors_plotter.add_error(
            position, self.protocol.position.last_response_payload
        )
class Batch():
    """Actor-based batch execution."""
    def __init__(self, transport_loop, axis):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        if axis == 'p':
            from lhrhost.robot.p_axis import Axis
        elif axis == 'z':
            from lhrhost.robot.z_axis import Axis
        elif axis == 'y':
            from lhrhost.robot.y_axis import Axis
        else:
            from lhrhost.robot.x_axis import Axis
        self.axis = Axis()
        if axis == 'p':
            self.axis.load_pid_json()
        self.messaging_stack.register_response_receivers(self.axis.protocol)
        self.messaging_stack.register_command_senders(self.axis.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        self.prompt = Prompt(end='', flush=True)

        print('Waiting for axis initialization...')
        await self.axis.wait_until_initialized()
        print('Synchronizing axis values...')
        await self.axis.synchronize_values()

        calibration_samples = []
        print('Collecting calibration samples...')
        while True:
            sensor_position = await self.prompt.number(
                'Move to sensor position:',
                random.randint(*self.axis.last_position_limits))
            await self.axis.go_to_sensor_position(sensor_position)
            await asyncio.sleep(0.5)
            sensor_position = await self.axis.sensor_position
            print('Moved to sensor position {}.'.format(sensor_position))
            physical_position = await self.prompt.number(
                'What is the corresponding physical position? (None to finish)',
                None, float)
            if physical_position is None:
                break
            calibration_samples.append((sensor_position, physical_position))

        print('Performing linear regression with {} samples...'.format(
            len(calibration_samples)))
        for calibration_sample in calibration_samples:
            self.axis.add_calibration_sample(*calibration_sample)
        linear_regression = self.axis.fit_calibration_linear()
        print(
            'Linreg slope: {:.4f}; intercept: {:.4f}; R-value: {:.4f}; stderr: {:.4f}'
            .format(*linear_regression))

        output_path = await self.prompt.string(
            'Save calibration data to path:',
            'calibrations/{}_physical.json'.format(self.axis.name))
        self.axis.save_calibration_json(output_path)

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
示例#9
0
class Batch:
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.axis = Axis()
        self.messaging_stack.register_response_receivers(self.axis.protocol)
        self.messaging_stack.register_command_senders(self.axis.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        self.prompt = Prompt(end='', flush=True)

        print('Running test routine...')
        await self.axis.wait_until_initialized()
        await self.axis.synchronize_values()
        self.axis.load_calibration_json()
        self.axis.load_discrete_json()
        self.axis.load_pid_json()
        print('Physical calibration:',
              self.axis.calibration_data['parameters'])

        print('Testing physical position targeting...')
        positions = list(range(0, 910, 50))
        random.shuffle(positions)
        for position in positions:
            print('Moving to the {} mL mark...'.format(position / 1000))
            try:
                await self.axis.go_to_physical_position(position / 1000)
            except Exception as e:
                print(e)
            await asyncio.sleep(0.5)
            converged_position = await self.axis.physical_position
            print(
                'Converged at the {:.3f} mL mark!'.format(converged_position))
            await self.prompt('Press enter to continue: ')

        print('Testing physical position displacements...')
        await self.axis.go_to_low_end_position()
        await asyncio.sleep(0.5)
        for i in range(0, 18):
            print('Moving up by a 0.05 mL marking...')
            actual_displacement = await self.axis.move_by_physical_delta(0.05)
            print(
                'Moved up by {:.3f} mL markings!'.format(actual_displacement))
            await self.prompt('Press enter to continue: ')

        print('Testing precise volume intake/dispense...')
        await self.axis.go_to_low_end_position()
        await asyncio.sleep(0.5)
        for volume in [0.02, 0.03, 0.04, 0.05, 0.1]:
            print('Preparing for intake...')
            await self.axis.go_to_pre_intake(volume)
            await asyncio.sleep(1.0)
            print('Executing intake of {} mL...'.format(volume))
            actual_intake = await self.axis.intake(volume)
            print('Completed intake of {:.3f} mL!'.format(actual_intake))
            await asyncio.sleep(1.0)
            print('Executing dispense...')
            await self.axis.dispense()
            await self.prompt('Press enter to continue: ')

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
示例#10
0
class Batch:
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.p_printer = Printer('P-Axis', prefix=batch.RESPONSE_PREFIX)
        self.p = Protocol('PAxis', 'p', response_receivers=[self.p_printer])
        self.z = Protocol('ZAxis', 'z')
        self.y = Protocol('YAxis', 'y')
        self.messaging_stack.register_response_receivers(self.p)
        self.messaging_stack.register_response_receivers(self.z)
        self.messaging_stack.register_response_receivers(self.y)
        self.messaging_stack.register_command_senders(self.p)
        self.messaging_stack.register_command_senders(self.z)
        self.messaging_stack.register_command_senders(self.y)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        self.prompt = Prompt(end='', flush=True)
        fluid_amount = 20

        print('Running test routine...')
        await asyncio.gather(self.p.initialized.wait(),
                             self.z.initialized.wait(),
                             self.y.initialized.wait())
        await self.p.motor.request_complete(-255)

        print('Moving to cuvette...')
        await self.y.feedback_controller.request_complete(720 - 30)
        print('  Y-Axis now at {}'.format(
            self.y.position.last_response_payload))

        while True:
            fluid_amount = await self.prompt.number(
                'Move sample platform to cuvette row. Amount to intake/dispense?',
                fluid_amount)
            print('Preparing pipettor for intake...')
            await self.p.feedback_controller.pid.kd.request(int(0.4 * 100))
            await self.p.feedback_controller.request_complete(
                1023 - int(650 + fluid_amount / 2))
            await asyncio.sleep(0.5)
            print('Performing intake...')
            await self.z.feedback_controller.request_complete(400)
            await asyncio.sleep(0.5)
            await self.intake(fluid_amount)
            await asyncio.sleep(0.5)
            await self.p.position.request()
            print('  Pre-dispense position: {}'.format(
                self.p.position.last_response_payload))
            await asyncio.sleep(0.5)
            await self.z.feedback_controller.request_complete(970)
            await self.prompt('Move sample platform to the weigh boat...')
            await self.z.feedback_controller.request_complete(200)
            await asyncio.sleep(0.5)
            await self.p.motor.request_complete(-255)
            await asyncio.sleep(0.5)
            await self.z.feedback_controller.request_complete(970)

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')

    async def intake(self, fluid_amount):
        """Intake a fluid amount specified by position delta."""
        derivative_gains = {100: 0.4, 50: 0.5, 40: 0.9, 30: 0.9, 20: 1}
        k_d = derivative_gains[fluid_amount]
        await self.p.feedback_controller.pid.kd.request(int(k_d * 100))
        await self.p.position.request()
        print('  Pre-intake position: {}'.format(
            self.p.position.last_response_payload))
        await self.p.feedback_controller.request_complete(
            (self.p.position.last_response_payload + fluid_amount))
示例#11
0
class Batch():
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.axis = Axis()
        self.messaging_stack.register_response_receivers(self.axis.protocol)
        self.messaging_stack.register_command_senders(self.axis.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        self.prompt = Prompt(end='', flush=True)

        print('Running test routine...')
        await self.axis.wait_until_initialized()
        await self.axis.synchronize_values()
        self.axis.load_calibration_json()
        self.axis.load_discrete_json()
        print('Physical calibration:',
              self.axis.calibration_data['parameters'])

        print('Moving to alignment hole...')
        await self.axis.go_to_physical_position(0)
        await self.prompt('Press enter to continue: ')

        print('Testing physical position targeting...')
        positions = list(range(0, 100, 10))
        random.shuffle(positions)
        for position in positions:
            print('Moving to {} cm from the alignment hole...'.format(
                position / 10))
            try:
                await self.axis.go_to_physical_position(position / 10)
            except Exception as e:
                print(e)
            await asyncio.sleep(0.5)
            converged_position = await self.axis.physical_position
            print('Converged at {:.3f} cm!'.format(converged_position))
            await self.prompt('Press enter to continue: ')

        print('Testing physical position displacements...')
        await self.axis.go_to_low_end_position()
        await asyncio.sleep(0.5)
        for i in range(0, 10):
            print('Moving away from the alignment hole by 1 cm...')
            actual_displacement = await self.axis.move_by_physical_delta(1)
            print('Moved away {:.3f} cm!'.format(actual_displacement))
            await self.prompt('Press enter to continue: ')

        print('Testing discrete position targeting...')
        await self.axis.go_to_low_end_position()
        await self.prompt('Testing cuvette positioning: ')
        for cuvette_row in ['a', 'b', 'c', 'd', 'e', 'f', 'g']:
            await self.axis.go_to_cuvette(cuvette_row)
            await self.prompt('Press enter to continue: ')
        await self.prompt('Testing 96-well plate positioning: ')
        for plate_row in ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']:
            await self.axis.go_to_96_well_plate(plate_row)
            await self.prompt('Press enter to continue: ')

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
class Batch:
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.protocol_printer = Printer('Z-Axis', prefix=batch.RESPONSE_PREFIX)
        self.command_printer = MessagePrinter(prefix='  Sending: ')
        self.protocol = Protocol('ZAxis',
                                 'z',
                                 response_receivers=[self.protocol_printer],
                                 command_receivers=[self.command_printer])
        self.response_printer = MessagePrinter(prefix=batch.RESPONSE_PREFIX)
        self.messaging_stack.register_response_receivers(self.response_printer)
        self.messaging_stack.register_response_receivers(self.protocol)
        self.messaging_stack.register_command_senders(self.protocol)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        print('Running test routine...')
        await self.protocol.initialized.wait()

        print('RPC-style with empty payloads:')
        await self.protocol.request()
        await self.protocol.position.request()
        await self.protocol.smoothed_position.request()
        await self.protocol.motor.request()

        print('Recursive request through handler tree with empty payloads:')
        await self.protocol.request_all()

        print('Motor direct duty control')
        # Test basic motor direct duty control
        await self.protocol.motor.request_complete(-255)
        await self.protocol.motor.request_complete(255)
        await self.protocol.motor.request_complete(-100)
        # Test motor polarity setting
        await self.protocol.motor.motor_polarity.request(-1)
        await self.protocol.motor.request_complete(-150)
        await self.protocol.motor.motor_polarity.request(1)
        await self.protocol.motor.request_complete(-100)
        # Test timer timeout
        await self.protocol.motor.timer_timeout.request(200)
        for i in range(10):
            await self.protocol.motor.request_complete(150)
            await asyncio.sleep(0.4)
        await self.protocol.motor.timer_timeout.request(10000)

        print('Motor direct duty control with position notification')
        await self.protocol.position.notify.change_only.request(0)
        task = self.protocol.position.notify.request_complete_time_interval(
            20, 100)
        await asyncio.sleep(1.0)
        await self.protocol.motor.request(-80)
        await task

        print(
            'Motor position feedback control with position and motor duty notification'
        )
        await self.protocol.position.notify.change_only.request(1)
        await self.protocol.position.notify.interval.request(100)
        await self.protocol.motor.notify.change_only.request(1)
        await self.protocol.motor.notify.interval.request(100)
        await self.protocol.position.notify.request(2)
        await self.protocol.motor.notify.request(2)
        await self.protocol.feedback_controller.request_complete(1000)
        await self.protocol.feedback_controller.request_complete(0)
        await self.protocol.position.notify.request(0)
        await self.protocol.motor.notify.request(0)

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')
class Batch:
    """Actor-based batch execution."""
    def __init__(self, transport_loop):
        """Initialize member variables."""
        self.messaging_stack = MessagingStack(transport_loop)
        self.z_printer = Printer('Z-Axis', prefix=batch.RESPONSE_PREFIX)
        self.y_printer = Printer('Y-Axis', prefix=batch.RESPONSE_PREFIX)
        self.command_printer = MessagePrinter(prefix='  Sending: ')
        self.z = Protocol('ZAxis',
                          'z',
                          response_receivers=[self.z_printer],
                          command_receivers=[self.command_printer])
        self.y = Protocol('YAxis',
                          'y',
                          response_receivers=[self.y_printer],
                          command_receivers=[self.command_printer])
        self.response_printer = MessagePrinter(prefix=batch.RESPONSE_PREFIX)
        self.messaging_stack.register_response_receivers(self.response_printer)
        self.messaging_stack.register_response_receivers(self.z)
        self.messaging_stack.register_response_receivers(self.y)
        self.messaging_stack.register_command_senders(self.z)
        self.messaging_stack.register_command_senders(self.y)
        self.batch_execution_manager = BatchExecutionManager(
            self.messaging_stack.arbiter,
            self.messaging_stack.command_sender,
            self.test_routine,
            header=batch.OUTPUT_HEADER,
            ready_waiter=self.messaging_stack.connection_synchronizer.
            wait_connected)
        self.messaging_stack.register_execution_manager(
            self.batch_execution_manager)

    async def test_routine(self):
        """Run the batch execution test routine."""
        print('Running test routine...')
        await asyncio.gather(self.z.initialized.wait(),
                             self.y.initialized.wait())

        print('Sequential positioning')
        await self.y.feedback_controller.request_complete(720)
        print('  Y-Axis now at {}'.format(
            self.y.position.last_response_payload))
        await self.z.feedback_controller.request_complete(0)
        print('  Z-Axis now at {}'.format(
            self.z.position.last_response_payload))
        await self.z.feedback_controller.request_complete(1000)
        print('  Z-Axis now at {}'.format(
            self.z.position.last_response_payload))
        await self.y.feedback_controller.request_complete(0)
        print('  Y-Axis now at {}'.format(
            self.y.position.last_response_payload))

        print('Concurrent positioning')
        z_task = self.z.feedback_controller.request_complete(0)
        y_task = self.y.feedback_controller.request_complete(720)
        await asyncio.gather(z_task, y_task)
        print('  Z-Axis now at {}'.format(
            self.z.position.last_response_payload))
        print('  Y-Axis now at {}'.format(
            self.y.position.last_response_payload))
        z_task = self.z.feedback_controller.request_complete(1000)
        y_task = self.y.feedback_controller.request_complete(0)
        await asyncio.gather(z_task, y_task)
        print('  Z-Axis now at {}'.format(
            self.z.position.last_response_payload))
        print('  Y-Axis now at {}'.format(
            self.y.position.last_response_payload))

        print('Concurrent sequential positioning')

        async def z_sequence():
            for i in range(4):
                await self.z.feedback_controller.request_complete(0)
                print('  Z-Axis now at {}'.format(
                    self.z.position.last_response_payload))
                await self.z.feedback_controller.request_complete(1000)
                print('  Z-Axis now at {}'.format(
                    self.z.position.last_response_payload))

        async def y_sequence():
            for i in range(4):
                await self.y.feedback_controller.request_complete(0)
                print('  Y-Axis now at {}'.format(
                    self.y.position.last_response_payload))
                await self.y.feedback_controller.request_complete(720)
                print('  Y-Axis now at {}'.format(
                    self.y.position.last_response_payload))

        await asyncio.gather(z_sequence(), y_sequence())

        print(batch.OUTPUT_FOOTER)
        print('Quitting...')