Tool Driver Development

This guide outlines the process of developing and integrating new tool drivers into the Galago platform. Tool drivers are essential components that enable communication between the Galago controller and laboratory instruments.

Table of Contents

  1. Overview
  2. Tool Drivers
  3. Development Process
  4. Creating the Proto Interfaces
  5. Implementing the Driver
  6. Testing the Driver
  7. Integrating with the Controller
  8. Best Practices
  9. Troubleshooting

Overview

Communication Architecture

We use gRPC to communicate between tool servers and the controller. Each tool has its own instance of a gRPC server running on a dedicated port. The controller and Python both reference the <workcell_config>.json file to match a tool ID to the port it runs on.

Tool Drivers

🔍
Manufacturer Instrument Name Category
BioTek Cytation Plate Reader
Opentrons Opentrons2 Liquid Handler
Brooks PF400 Dispenser
Liconic Liconic Incubator
Cognex Dataman70 Barcode Reader
Molecular Devices Spectramax Plate Reader
QInstruments Bioshake Shaker
BioNex HIG Centrifuge Centrifuge
Agilent Bravo Liquid Handler
Agilent VCode Barcode Reader
Agilent Plateloc Plate Sealer
Azenta XPeel Plate Peeler
Thermo Fisher Scientific ALPS3000 Plate Sealer
Custom Toolbox Utility Tool
Hamilton Hamilton Star/Star Plus Liquid Handler

Development Process

1
Define the proto interfaces
2
Implement the driver
3
Test the driver
4
Integrate with the controller

Creating the Proto Interfaces

Protocol Definition

We first need to define the methods and attributes that the top-level driver commands will execute. The data is structured in the form of 'Messages'.

These files are located under interfaces/tools.

Here is an example proto for a basic bioshake driver:

syntax = 'proto3';

package com.science.foundry.tools.grpc_interfaces.bioshake;

message Command {
  oneof command {
    Grip grip = 1;
    Ungrip ungrip = 2;
    Home home = 3;
    StartShake start_shake = 4;
    StopShake stop_shake = 5;
    Reset reset = 6;
    WaitForShakeToFinish wait_for_shake_to_finish = 7;
  }
  message Grip {}
  message Ungrip {}
  message Home {}
  message StartShake {
    int32 speed = 1;
    int32 duration = 2;
  }
  message StopShake {}
  message Reset {}
  message WaitForShakeToFinish {
    int32 timeout = 1;
  }
}
message Config {
  string com_port = 1;
  string tool_id = 2;
}

Implementing the Driver

Driver Structure

After defining the proto interface, you need to implement the actual driver that will communicate with the laboratory instrument. The driver should be implemented in Python and follow the structure below:

from concurrent import futures
import grpc
import time
import logging

from com.science.foundry.tools.grpc_interfaces.bioshake import bioshake_pb2
from com.science.foundry.tools.grpc_interfaces.bioshake import bioshake_pb2_grpc

class BioshakeDriver(bioshake_pb2_grpc.BioshakeServicer):
    def __init__(self, config):
        self.com_port = config.com_port
        self.tool_id = config.tool_id
        # Initialize connection to the device
        
    def Execute(self, request, context):
        command_type = request.WhichOneof("command")
        
        if command_type == "grip":
            # Implement grip functionality
            return bioshake_pb2.CommandResponse()
        elif command_type == "ungrip":
            # Implement ungrip functionality
            return bioshake_pb2.CommandResponse()
        # Implement other commands...
        
        return bioshake_pb2.CommandResponse(error="Unknown command")

Testing the Driver

Test Implementation

Before integrating with the controller, it's important to test your driver to ensure it communicates correctly with the laboratory instrument. Create a test script that:

  • Initializes the driver with a test configuration
  • Executes various commands
  • Verifies the responses
import grpc
import time
from com.science.foundry.tools.grpc_interfaces.bioshake import bioshake_pb2
from com.science.foundry.tools.grpc_interfaces.bioshake import bioshake_pb2_grpc

def run_test():
    # Create a gRPC channel
    channel = grpc.insecure_channel('localhost:50051')
    
    # Create a stub (client)
    stub = bioshake_pb2_grpc.BioshakeStub(channel)
    
    # Test grip command
    grip_request = bioshake_pb2.Command(grip=bioshake_pb2.Command.Grip())
    response = stub.Execute(grip_request)
    print(f"Grip response: {response}")
    
    # Test shake command
    shake_request = bioshake_pb2.Command(
        start_shake=bioshake_pb2.Command.StartShake(speed=500, duration=10)
    )
    response = stub.Execute(shake_request)
    print(f"Shake response: {response}")
    
    # Add more tests as needed

if __name__ == '__main__':
    run_test()

Integrating with the Controller

Configuration Setup

To integrate your driver with the Galago controller, you need to:

  1. Add your driver to the appropriate directory in the codebase
  2. Update the workcell configuration file to include your tool
  3. Register the tool with the controller

Example workcell configuration entry:

{
  "tools": [
    {
      "id": "bioshake_1",
      "type": "bioshake",
      "port": 50051,
      "config": {
        "com_port": "COM3",
        "tool_id": "bioshake_1"
      }
    }
  ]
}

Best Practices

Error Handling

  • Implement comprehensive error handling
  • Return descriptive error messages
  • Log errors for debugging

Resource Management

  • Properly manage connections to devices
  • Release resources when not in use
  • Implement timeouts for operations

Documentation

  • Document all commands and parameters
  • Include example usage
  • Document hardware requirements

Troubleshooting

Common Issues

Issue Possible Cause Solution
Connection failures Incorrect port or address Verify connection settings in the configuration file
Command timeouts Device not responding Check physical connections and device power
Protocol errors Mismatched proto definitions Ensure proto files are up-to-date and properly compiled

Tip: When developing a new driver, start with a simple implementation that supports basic functionality, then gradually add more complex features.

Note: Always test your driver thoroughly with the actual hardware before deploying it in a production environment.