[{"data":1,"prerenderedAt":3205},["ShallowReactive",2],{"navigation":3,"\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002Fmove-a-plate":951,"\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002Fmove-a-plate-surround":3200},[4,59,188,271,449,613,802,833],{"title":5,"type":6,"device":6,"path":7,"stem":8,"children":9,"page":41},"Get Started",null,"\u002Fget-started\u002F","01.get-started",[10,15,42,47,51,55],{"title":11,"path":12,"stem":13,"type":14,"device":6},"Welcome to UniteLabs","\u002Fget-started\u002Fwelcome\u002F","01.get-started\u002F00.welcome","landing",{"title":16,"type":6,"device":6,"path":17,"stem":18,"children":19,"page":41},"Setup","\u002Fget-started\u002Fsetup\u002F","01.get-started\u002F01.setup",[20,25,29,33,37],{"title":21,"path":22,"stem":23,"type":24,"device":6},"Get access","\u002Fget-started\u002Fsetup\u002Fget-access\u002F","01.get-started\u002F01.setup\u002F00.get-access","howto",{"title":26,"path":27,"stem":28,"type":24,"device":6},"GroundControl","\u002Fget-started\u002Fsetup\u002Fgroundcontrol\u002F","01.get-started\u002F01.setup\u002F10.groundcontrol",{"title":30,"path":31,"stem":32,"type":24,"device":6},"Connect to Platform","\u002Fget-started\u002Fsetup\u002Fconnect-to-platform\u002F","01.get-started\u002F01.setup\u002F20.connect-to-platform",{"title":34,"path":35,"stem":36,"type":24,"device":6},"Set up your development machine","\u002Fget-started\u002Fsetup\u002Fdeveloper-machine\u002F","01.get-started\u002F01.setup\u002F30.developer-machine",{"title":38,"path":39,"stem":40,"type":24,"device":6},"SDK installation","\u002Fget-started\u002Fsetup\u002Fsdk-installation\u002F","01.get-started\u002F01.setup\u002F40.sdk-installation",false,{"title":43,"path":44,"stem":45,"type":46,"device":6},"Control a device","\u002Fget-started\u002Fcontrol-a-device\u002F","01.get-started\u002F02.control-a-device","tutorial",{"title":48,"path":49,"stem":50,"type":46,"device":6},"Liquid handling as code","\u002Fget-started\u002Fliquid-handling-as-code\u002F","01.get-started\u002F03.liquid-handling-as-code",{"title":52,"path":53,"stem":54,"type":46,"device":6},"Automate your workflows","\u002Fget-started\u002Fautomate-your-workflows\u002F","01.get-started\u002F04.automate-your-workflows",{"title":56,"path":57,"stem":58,"type":6,"device":6},"Self-Paced Setup Guide","\u002Fget-started\u002Fself-onboarding\u002F","01.get-started\u002F90.self-onboarding",{"title":60,"type":6,"device":6,"path":61,"stem":62,"children":63,"page":41},"How-to","\u002Fhow-to\u002F","02.how-to",[64,118,163,180],{"title":65,"type":6,"device":6,"path":66,"stem":67,"children":68,"page":41},"Connectors and devices","\u002Fhow-to\u002Fintegrate\u002F","02.how-to\u002F02.integrate",[69,102],{"title":70,"type":6,"device":6,"path":71,"stem":72,"children":73,"page":41},"Connect a device","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device",[74,78,82,86,90,94,98],{"title":75,"path":76,"stem":77,"type":24,"device":6},"Connector Configuration","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Fconnector-configuration\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F10.connector-configuration",{"title":79,"path":80,"stem":81,"type":24,"device":6},"With an executable","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Fwith-an-executable\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F20.with-an-executable",{"title":83,"path":84,"stem":85,"type":24,"device":6},"From source","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Ffrom-source\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F30.from-source",{"title":87,"path":88,"stem":89,"type":24,"device":6},"Build your own","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Fbuild-yourself\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F40.build-yourself",{"title":91,"path":92,"stem":93,"type":24,"device":6},"Headless install","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Fheadless-install\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F50.headless-install",{"title":95,"path":96,"stem":97,"type":24,"device":6},"Raspberry Pi","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Fraspberry-pi\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F55.raspberry-pi",{"title":99,"path":100,"stem":101,"type":24,"device":6},"Multi-device Networking","\u002Fhow-to\u002Fintegrate\u002Fconnect-a-device\u002Fmultiple-devices\u002F","02.how-to\u002F02.integrate\u002F20.connect-a-device\u002F60.multiple-devices",{"title":103,"type":6,"device":6,"path":104,"stem":105,"children":106,"page":41},"Use a device","\u002Fhow-to\u002Fintegrate\u002Fuse-a-device\u002F","02.how-to\u002F02.integrate\u002F30.use-a-device",[107,110,114],{"title":26,"path":108,"stem":109,"type":24,"device":6},"\u002Fhow-to\u002Fintegrate\u002Fuse-a-device\u002Fgroundcontrol\u002F","02.how-to\u002F02.integrate\u002F30.use-a-device\u002F10.groundcontrol",{"title":111,"path":112,"stem":113,"type":24,"device":6},"Platform","\u002Fhow-to\u002Fintegrate\u002Fuse-a-device\u002Fplatform\u002F","02.how-to\u002F02.integrate\u002F30.use-a-device\u002F20.platform",{"title":115,"path":116,"stem":117,"type":24,"device":6},"UniteLabs SDK & REST API","\u002Fhow-to\u002Fintegrate\u002Fuse-a-device\u002Fpython\u002F","02.how-to\u002F02.integrate\u002F30.use-a-device\u002F30.python",{"title":119,"type":6,"device":6,"path":120,"stem":121,"children":122,"page":41},"Workflows","\u002Fhow-to\u002Fautomate\u002F","02.how-to\u002F07.automate",[123,127,131,135,139,143,147,151,155,159],{"title":124,"path":125,"stem":126,"type":24,"device":6},"Deploy a workflow","\u002Fhow-to\u002Fautomate\u002Fdeploy-a-workflow\u002F","02.how-to\u002F07.automate\u002F30.deploy-a-workflow",{"title":128,"path":129,"stem":130,"type":24,"device":6},"Run a workflow","\u002Fhow-to\u002Fautomate\u002Frun-a-workflow\u002F","02.how-to\u002F07.automate\u002F35.run-a-workflow",{"title":132,"path":133,"stem":134,"type":24,"device":6},"CI\u002FCD for workflows","\u002Fhow-to\u002Fautomate\u002Fcicd-for-workflows\u002F","02.how-to\u002F07.automate\u002F40.cicd-for-workflows",{"title":136,"path":137,"stem":138,"type":24,"device":6},"HITL basics","\u002Fhow-to\u002Fautomate\u002Fbasic-hitl\u002F","02.how-to\u002F07.automate\u002F50.basic-hitl",{"title":140,"path":141,"stem":142,"type":24,"device":6},"Slack notifications and operator confirmation","\u002Fhow-to\u002Fautomate\u002Fslack-notifications\u002F","02.how-to\u002F07.automate\u002F52.slack-notifications",{"title":144,"path":145,"stem":146,"type":24,"device":6},"Typed operator inputs","\u002Fhow-to\u002Fautomate\u002Ftyped-operator-inputs\u002F","02.how-to\u002F07.automate\u002F55.typed-operator-inputs",{"title":148,"path":149,"stem":150,"type":24,"device":6},"Pause and resume a run","\u002Fhow-to\u002Fautomate\u002Fpause-and-resume\u002F","02.how-to\u002F07.automate\u002F57.pause-and-resume",{"title":152,"path":153,"stem":154,"type":24,"device":6},"Error recovery","\u002Fhow-to\u002Fautomate\u002Fbasic-error-handling\u002F","02.how-to\u002F07.automate\u002F60.basic-error-handling",{"title":156,"path":157,"stem":158,"type":24,"device":6},"Advanced error handling","\u002Fhow-to\u002Fautomate\u002Fadvanced-error-handling\u002F","02.how-to\u002F07.automate\u002F70.advanced-error-handling",{"title":160,"path":161,"stem":162,"type":24,"device":6},"Emit lineage events","\u002Fhow-to\u002Fautomate\u002Femitting-lineage-events\u002F","02.how-to\u002F07.automate\u002F90.emitting-lineage-events",{"title":164,"type":6,"device":6,"path":165,"stem":166,"children":167,"page":41},"Data","\u002Fhow-to\u002Fobserve\u002F","02.how-to\u002F08.observe",[168,172,176],{"title":169,"path":170,"stem":171,"type":24,"device":6},"File System Connector","\u002Fhow-to\u002Fobserve\u002Ffilesystem-connector\u002F","02.how-to\u002F08.observe\u002F10.filesystem-connector",{"title":173,"path":174,"stem":175,"type":24,"device":6},"Building an ETL","\u002Fhow-to\u002Fobserve\u002Fbuilding-an-etl\u002F","02.how-to\u002F08.observe\u002F20.building-an-etl",{"title":177,"path":178,"stem":179,"type":24,"device":6},"Read lineage events","\u002Fhow-to\u002Fobserve\u002Freading-lineage-events\u002F","02.how-to\u002F08.observe\u002F30.reading-lineage-events",{"title":111,"type":6,"device":6,"path":181,"stem":182,"children":183,"page":41},"\u002Fhow-to\u002Fplatform\u002F","02.how-to\u002F09.platform",[184],{"title":185,"path":186,"stem":187,"type":24,"device":6},"UniteLabs Desktop","\u002Fhow-to\u002Fplatform\u002Funitelabs-desktop\u002F","02.how-to\u002F09.platform\u002F10.unitelabs-desktop",{"title":189,"type":6,"device":6,"path":190,"stem":191,"children":192},"Technical Reference","\u002Ftechnical-reference\u002F","03.technical-reference",[193,196,201,213,226,235,244,253,262],{"title":194,"path":190,"stem":195,"type":14,"device":6},"Overview","03.technical-reference\u002Findex",{"title":197,"path":198,"stem":199,"type":200,"device":6},"REST API","\u002Ftechnical-reference\u002Frest-api\u002F","03.technical-reference\u002F01.rest-api","reference",{"title":119,"type":6,"device":6,"path":202,"stem":203,"children":204,"page":41},"\u002Ftechnical-reference\u002Fautomate\u002F","03.technical-reference\u002F07.automate",[205,209],{"title":206,"path":207,"stem":208,"type":200,"device":6},"Workflow template","\u002Ftechnical-reference\u002Fautomate\u002Fworkflow-template\u002F","03.technical-reference\u002F07.automate\u002F05.workflow-template",{"title":210,"path":211,"stem":212,"type":200,"device":6},"Workflows REST API","\u002Ftechnical-reference\u002Fautomate\u002Fworkflows-api\u002F","03.technical-reference\u002F07.automate\u002F80.workflows-api",{"title":26,"type":6,"device":6,"path":214,"stem":215,"children":216},"\u002Ftechnical-reference\u002Fgroundcontrol\u002F","03.technical-reference\u002F10.groundcontrol\u002Findex",[217,218,222],{"title":194,"path":214,"stem":215,"type":14,"device":6},{"title":219,"path":220,"stem":221,"type":200,"device":6},"Network requirements","\u002Ftechnical-reference\u002Fgroundcontrol\u002Fnetwork-requirements\u002F","03.technical-reference\u002F10.groundcontrol\u002F10.network-requirements",{"title":223,"path":224,"stem":225,"type":200,"device":6},"Changelog","\u002Ftechnical-reference\u002Fgroundcontrol\u002Fchangelog\u002F","03.technical-reference\u002F10.groundcontrol\u002F20.changelog",{"title":227,"type":6,"device":6,"path":228,"stem":229,"children":230},"UniteLabs SDK","\u002Ftechnical-reference\u002Fpython-sdk\u002F","03.technical-reference\u002F20.python-sdk\u002Findex",[231,232],{"title":194,"path":228,"stem":229,"type":14,"device":6},{"title":223,"path":233,"stem":234,"type":200,"device":6},"\u002Ftechnical-reference\u002Fpython-sdk\u002Fchangelog\u002F","03.technical-reference\u002F20.python-sdk\u002F20.changelog",{"title":236,"type":6,"device":6,"path":237,"stem":238,"children":239},"Liquid Handling SDK","\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002F","03.technical-reference\u002F30.python-liquid-handling-sdk\u002Findex",[240,241],{"title":194,"path":237,"stem":238,"type":14,"device":6},{"title":223,"path":242,"stem":243,"type":200,"device":6},"\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002Fchangelog\u002F","03.technical-reference\u002F30.python-liquid-handling-sdk\u002F20.changelog",{"title":245,"type":6,"device":6,"path":246,"stem":247,"children":248},"Labware","\u002Ftechnical-reference\u002Flabware\u002F","03.technical-reference\u002F40.labware\u002Findex",[249,250],{"title":194,"path":246,"stem":247,"type":14,"device":6},{"title":223,"path":251,"stem":252,"type":200,"device":6},"\u002Ftechnical-reference\u002Flabware\u002Fchangelog\u002F","03.technical-reference\u002F40.labware\u002F20.changelog",{"title":254,"type":6,"device":6,"path":255,"stem":256,"children":257},"Python Omnibus","\u002Ftechnical-reference\u002Fpython-omnibus\u002F","03.technical-reference\u002F50.python-omnibus\u002Findex",[258,259],{"title":194,"path":255,"stem":256,"type":14,"device":6},{"title":223,"path":260,"stem":261,"type":200,"device":6},"\u002Ftechnical-reference\u002Fpython-omnibus\u002Fchangelog\u002F","03.technical-reference\u002F50.python-omnibus\u002F20.changelog",{"title":263,"type":6,"device":6,"path":264,"stem":265,"children":266},"Python CDK","\u002Ftechnical-reference\u002Fpython-cdk\u002F","03.technical-reference\u002F60.python-cdk\u002Findex",[267,268],{"title":194,"path":264,"stem":265,"type":14,"device":6},{"title":223,"path":269,"stem":270,"type":200,"device":6},"\u002Ftechnical-reference\u002Fpython-cdk\u002Fchangelog\u002F","03.technical-reference\u002F60.python-cdk\u002F20.changelog",{"title":272,"type":6,"device":6,"path":273,"stem":274,"children":275,"page":41},"Concepts","\u002Fconcepts\u002F","04.concepts",[276,315,339,387,426],{"title":277,"type":6,"device":6,"path":278,"stem":279,"children":280,"page":41},"Labs as code","\u002Fconcepts\u002Flabs-as-code\u002F","04.concepts\u002F01.labs-as-code",[281,286,290],{"title":282,"path":283,"stem":284,"type":285,"device":6},"Lab as Code","\u002Fconcepts\u002Flabs-as-code\u002Fwhy-code\u002F","04.concepts\u002F01.labs-as-code\u002F00.why-code","explanation",{"title":287,"path":288,"stem":289,"type":285,"device":6},"How it works","\u002Fconcepts\u002Flabs-as-code\u002Fhow-it-works\u002F","04.concepts\u002F01.labs-as-code\u002F01.how-it-works",{"title":291,"type":6,"device":6,"path":292,"stem":293,"children":294,"page":41},"Use Cases","\u002Fconcepts\u002Flabs-as-code\u002Fuse-cases\u002F","04.concepts\u002F01.labs-as-code\u002F02.use-cases",[295,299,303,307,311],{"title":296,"path":297,"stem":298,"type":285,"device":6},"Instrument Control","\u002Fconcepts\u002Flabs-as-code\u002Fuse-cases\u002Flow-level-instrument-control\u002F","04.concepts\u002F01.labs-as-code\u002F02.use-cases\u002F10.low-level-instrument-control",{"title":300,"path":301,"stem":302,"type":285,"device":6},"Multi-device Control","\u002Fconcepts\u002Flabs-as-code\u002Fuse-cases\u002Fmulti-device-control\u002F","04.concepts\u002F01.labs-as-code\u002F02.use-cases\u002F20.multi-device-control",{"title":304,"path":305,"stem":306,"type":285,"device":6},"Workflow Orchestration","\u002Fconcepts\u002Flabs-as-code\u002Fuse-cases\u002Fworkflow-orchestration\u002F","04.concepts\u002F01.labs-as-code\u002F02.use-cases\u002F30.workflow-orchestration",{"title":308,"path":309,"stem":310,"type":285,"device":6},"Custom Apps and LIMS Integration","\u002Fconcepts\u002Flabs-as-code\u002Fuse-cases\u002Fcustom-apps-lims\u002F","04.concepts\u002F01.labs-as-code\u002F02.use-cases\u002F40.custom-apps-lims",{"title":312,"path":313,"stem":314,"type":285,"device":6},"Scale and Fleet Management","\u002Fconcepts\u002Flabs-as-code\u002Fuse-cases\u002Fscale-and-fleet\u002F","04.concepts\u002F01.labs-as-code\u002F02.use-cases\u002F50.scale-and-fleet",{"title":65,"type":6,"device":6,"path":316,"stem":317,"children":318,"page":41},"\u002Fconcepts\u002Fintegrate\u002F","04.concepts\u002F02.integrate",[319,323,327,331,335],{"title":320,"path":321,"stem":322,"type":285,"device":6},"Device","\u002Fconcepts\u002Fintegrate\u002Fdevice\u002F","04.concepts\u002F02.integrate\u002F05.device",{"title":324,"path":325,"stem":326,"type":285,"device":6},"Connector","\u002Fconcepts\u002Fintegrate\u002Fconnector\u002F","04.concepts\u002F02.integrate\u002F10.connector",{"title":328,"path":329,"stem":330,"type":285,"device":6},"Module","\u002Fconcepts\u002Fintegrate\u002Fmodule\u002F","04.concepts\u002F02.integrate\u002F20.module",{"title":332,"path":333,"stem":334,"type":285,"device":6},"Action","\u002Fconcepts\u002Fintegrate\u002Faction\u002F","04.concepts\u002F02.integrate\u002F30.action",{"title":336,"path":337,"stem":338,"type":285,"device":6},"Subscription","\u002Fconcepts\u002Fintegrate\u002Fsubscription\u002F","04.concepts\u002F02.integrate\u002F40.subscription",{"title":340,"type":6,"device":6,"path":341,"stem":342,"children":343,"page":41},"Liquid handling and robots","\u002Fconcepts\u002Foperate\u002F","04.concepts\u002F03.operate",[344,348,352,356,359,363,367,371,375,379,383],{"title":345,"path":346,"stem":347,"type":285,"device":6},"Liquid Handling","\u002Fconcepts\u002Foperate\u002Fliquid-handling\u002F","04.concepts\u002F03.operate\u002F10.liquid-handling",{"title":349,"path":350,"stem":351,"type":285,"device":6},"Modules","\u002Fconcepts\u002Foperate\u002Fmodules\u002F","04.concepts\u002F03.operate\u002F20.modules",{"title":353,"path":354,"stem":355,"type":285,"device":6},"Deck","\u002Fconcepts\u002Foperate\u002Fdeck\u002F","04.concepts\u002F03.operate\u002F30.deck",{"title":245,"path":357,"stem":358,"type":285,"device":6},"\u002Fconcepts\u002Foperate\u002Flabware\u002F","04.concepts\u002F03.operate\u002F40.labware",{"title":360,"path":361,"stem":362,"type":285,"device":6},"Liquids","\u002Fconcepts\u002Foperate\u002Fliquids\u002F","04.concepts\u002F03.operate\u002F50.liquids",{"title":364,"path":365,"stem":366,"type":285,"device":6},"Liquid Classes","\u002Fconcepts\u002Foperate\u002Fliquid-classes\u002F","04.concepts\u002F03.operate\u002F60.liquid-classes",{"title":368,"path":369,"stem":370,"type":285,"device":6},"Parameter Sets","\u002Fconcepts\u002Foperate\u002Fparameter-sets\u002F","04.concepts\u002F03.operate\u002F65.parameter-sets",{"title":372,"path":373,"stem":374,"type":285,"device":6},"Tips and Tip Tracking","\u002Fconcepts\u002Foperate\u002Ftips\u002F","04.concepts\u002F03.operate\u002F70.tips",{"title":376,"path":377,"stem":378,"type":285,"device":6},"Simulation","\u002Fconcepts\u002Foperate\u002Fsimulation\u002F","04.concepts\u002F03.operate\u002F80.simulation",{"title":380,"path":381,"stem":382,"type":285,"device":6},"Error Handling","\u002Fconcepts\u002Foperate\u002Ferror-handling\u002F","04.concepts\u002F03.operate\u002F90.error-handling",{"title":384,"path":385,"stem":386,"type":285,"device":6},"Robot Arms","\u002Fconcepts\u002Foperate\u002Frobot-arms\u002F","04.concepts\u002F03.operate\u002F95.robot-arms",{"title":119,"type":6,"device":6,"path":388,"stem":389,"children":390,"page":41},"\u002Fconcepts\u002Fautomate\u002F","04.concepts\u002F07.automate",[391,395,399,403,407,411,415,419,423],{"title":392,"path":393,"stem":394,"type":285,"device":6},"Workflow","\u002Fconcepts\u002Fautomate\u002Fworkflow\u002F","04.concepts\u002F07.automate\u002F10.workflow",{"title":396,"path":397,"stem":398,"type":285,"device":6},"Phase","\u002Fconcepts\u002Fautomate\u002Fphase\u002F","04.concepts\u002F07.automate\u002F20.phase",{"title":400,"path":401,"stem":402,"type":285,"device":6},"Step","\u002Fconcepts\u002Fautomate\u002Fstep\u002F","04.concepts\u002F07.automate\u002F30.step",{"title":404,"path":405,"stem":406,"type":285,"device":6},"Runs","\u002Fconcepts\u002Fautomate\u002Fruns\u002F","04.concepts\u002F07.automate\u002F40.runs",{"title":408,"path":409,"stem":410,"type":285,"device":6},"Input","\u002Fconcepts\u002Fautomate\u002Finput\u002F","04.concepts\u002F07.automate\u002F50.input",{"title":412,"path":413,"stem":414,"type":285,"device":6},"Artifacts","\u002Fconcepts\u002Fautomate\u002Fartifacts\u002F","04.concepts\u002F07.automate\u002F60.artifacts",{"title":416,"path":417,"stem":418,"type":285,"device":6},"Logs","\u002Fconcepts\u002Fautomate\u002Flogs\u002F","04.concepts\u002F07.automate\u002F70.logs",{"title":420,"path":421,"stem":422,"type":285,"device":6},"Human in the Loop","\u002Fconcepts\u002Fautomate\u002Fhuman-in-the-loop\u002F","04.concepts\u002F07.automate\u002F80.human-in-the-loop",{"title":380,"path":424,"stem":425,"type":285,"device":6},"\u002Fconcepts\u002Fautomate\u002Ferror-handling\u002F","04.concepts\u002F07.automate\u002F90.error-handling",{"title":164,"type":6,"device":6,"path":427,"stem":428,"children":429,"page":41},"\u002Fconcepts\u002Fobserve\u002F","04.concepts\u002F08.observe",[430,433,437,441,445],{"title":194,"path":431,"stem":432,"type":14,"device":6},"\u002Fconcepts\u002Fobserve\u002Foverview\u002F","04.concepts\u002F08.observe\u002F10.overview",{"title":434,"path":435,"stem":436,"type":285,"device":6},"Object Storage","\u002Fconcepts\u002Fobserve\u002Fstorage\u002F","04.concepts\u002F08.observe\u002F10.storage",{"title":438,"path":439,"stem":440,"type":285,"device":6},"Secrets","\u002Fconcepts\u002Fobserve\u002Fsecrets\u002F","04.concepts\u002F08.observe\u002F20.secrets",{"title":442,"path":443,"stem":444,"type":285,"device":6},"Data sources","\u002Fconcepts\u002Fobserve\u002Fdata-sources\u002F","04.concepts\u002F08.observe\u002F30.data-sources",{"title":446,"path":447,"stem":448,"type":285,"device":6},"Data lineage","\u002Fconcepts\u002Fobserve\u002Fdata-lineage\u002F","04.concepts\u002F08.observe\u002F40.data-lineage",{"title":450,"type":6,"device":6,"path":451,"stem":452,"children":453,"page":41},"Devices","\u002Fdevices\u002F","05.devices",[454,457,505,518,534,571,595],{"title":194,"path":455,"stem":456,"type":14,"device":6},"\u002Fdevices\u002Foverview\u002F","05.devices\u002F00.overview",{"title":458,"path":459,"page":41,"children":460},"Heater-shakers","\u002Fdevices\u002Fheater-shakers\u002F",[461,482,492],{"title":462,"path":463,"stem":464,"type":200,"device":465},"QInstruments BioShake","\u002Fdevices\u002Fqinstruments-bioshake\u002F","05.devices\u002F10.qinstruments-bioshake",{"slug":466,"vendor":467,"category":468,"connector":466,"package":469,"models":470,"communication":477,"vendor_software":6,"os":478},"qinstruments-bioshake","QInstruments","Plate Shakers & Temperature Control","unitelabs-qinstruments-bioshake",[471,472,473,474,475,476],"BioShake 3000 \u002F 3000 elm \u002F 3000 elm DWP","BioShake 3000-T \u002F 3000-T elm","BioShake 5000 elm","BioShake D30 \u002F D30 elm \u002F D30-T \u002F D30-T elm","BioShake Q1 \u002F Q1 (1.2 mm) \u002F Q1 (3.0 mm) \u002F Q2","HeatPlate","serial (RS-232 over USB)",[479,480,481],"windows","linux","macos",{"title":483,"path":484,"stem":485,"type":200,"device":486},"QInstruments ColdPlate","\u002Fdevices\u002Fqinstruments-coldplate\u002F","05.devices\u002F20.qinstruments-coldplate",{"slug":487,"vendor":467,"category":468,"connector":466,"package":469,"models":488,"communication":477,"vendor_software":6,"os":491},"qinstruments-coldplate",[489,490],"ColdPlate","ColdPlate slim",[479,480,481],{"title":493,"path":494,"stem":495,"type":200,"device":496},"Inheco Thermoshake","\u002Fdevices\u002Finheco-thermoshake\u002F","05.devices\u002F30.inheco-thermoshake",{"slug":497,"vendor":498,"category":468,"connector":499,"models":500},"inheco-thermoshake","Inheco","inheco-tec-controller",[501,502,503,504],"Thermoshake AC","Thermoshake AC LC","Thermoshake Classic","Thermoshake RM",{"title":506,"path":507,"page":41,"children":508},"Incubation","\u002Fdevices\u002Fincubation\u002F",[509],{"title":510,"path":511,"stem":512,"type":200,"device":513},"Inheco SCILA","\u002Fdevices\u002Finheco-scila\u002F","05.devices\u002F40.inheco-scila",{"slug":514,"vendor":498,"category":506,"connector":514,"models":515},"inheco-scila",[516,517],"SCILA","SCILA MIX 2-gas mixing device",{"title":519,"path":520,"page":41,"children":521},"Thermal cyclers","\u002Fdevices\u002Fthermal-cyclers\u002F",[522],{"title":523,"path":524,"stem":525,"type":200,"device":526},"Inheco ODTC","\u002Fdevices\u002Finheco-odtc\u002F","05.devices\u002F50.inheco-odtc",{"slug":527,"vendor":498,"category":528,"connector":527,"models":529},"inheco-odtc","Thermal Cycler",[530,531,532,533],"ODTC 96","ODTC 96XL","ODTC 384","ODTC 384XL",{"title":535,"path":536,"page":41,"children":537},"Readers","\u002Fdevices\u002Freaders\u002F",[538,547,556],{"title":539,"path":540,"stem":541,"type":200,"device":542},"Agilent Biotek Gen5","\u002Fdevices\u002Fbiotek-gen5\u002F","05.devices\u002F60.biotek-gen5",{"slug":543,"vendor":544,"category":545,"connector":546},"biotek-gen5","Agilent","Readers & Imagers","gen5",{"title":548,"path":549,"stem":550,"type":200,"device":551},"Biotek Synergy H1","\u002Fdevices\u002Fbiotek-synergy-h1\u002F","05.devices\u002F70.biotek-synergy-h1",{"slug":552,"vendor":544,"category":545,"connector":553,"models":554},"biotek-synergy-h1","agilent-synergy-h1",[555],"BioTek Synergy H1",{"title":557,"path":558,"stem":559,"type":200,"device":560},"Tecan Infinite 200","\u002Fdevices\u002Ftecan-infinite-200\u002F","05.devices\u002F75.tecan-infinite-200",{"slug":561,"vendor":562,"category":545,"connector":561,"package":563,"models":564,"communication":568,"vendor_software":569,"os":570},"tecan-infinite-200","Tecan","unitelabs-tecan-infinite-200",[565,566,567],"Infinite F200","Infinite M200","Infinite M200 Pro","USB","i-control on Windows only, for its USB driver",[479,480,481],{"title":572,"path":573,"page":41,"children":574},"Tilt & turn","\u002Fdevices\u002Ftilt-and-turn\u002F",[575,585],{"title":576,"path":577,"stem":578,"type":200,"device":579},"QInstruments TiltStation","\u002Fdevices\u002Fqinstruments-tiltstation\u002F","05.devices\u002F80.qinstruments-tiltstation",{"slug":580,"vendor":467,"category":581,"connector":466,"package":469,"models":582,"communication":477,"vendor_software":6,"os":584},"qinstruments-tiltstation","Plate Tilting",[583],"TiltStation",[479,480,481],{"title":586,"path":587,"stem":588,"type":200,"device":589},"QInstruments TurnStation","\u002Fdevices\u002Fqinstruments-turnstation\u002F","05.devices\u002F90.qinstruments-turnstation",{"slug":590,"vendor":467,"category":591,"connector":466,"package":469,"models":592,"communication":477,"vendor_software":6,"os":594},"qinstruments-turnstation","Plate Rotating",[593],"TurnStation",[479,480,481],{"title":596,"path":597,"page":41,"children":598},"Robots","\u002Fdevices\u002Frobots\u002F",[599],{"title":600,"path":601,"stem":602,"type":200,"device":603},"Brooks PreciseFlex 400","\u002Fdevices\u002Fbrooks-preciseflex-400\u002F","05.devices\u002F95.brooks-preciseflex-400",{"slug":604,"vendor":605,"category":596,"connector":604,"package":606,"models":607,"communication":611,"vendor_software":6,"os":612},"brooks-preciseflex-400","Brooks Automation","unitelabs-brooks-preciseflex-400",[608,609,610],"PreciseFlex 400, standard reach, 400 \u002F 750 \u002F 1160 mm Z","PreciseFlex 400, extended reach (XR), 400 \u002F 750 \u002F 1160 mm Z","Either on a PreciseFlex linear rail (1.0, 1.5 or 2.0 m)","Ethernet (TCP)",[479,480,481],{"title":614,"type":6,"device":6,"path":615,"stem":616,"children":617,"page":41},"Liquid Handling and Robots","\u002Fliquid-handling-and-robots\u002F","06.liquid-handling-and-robots",[618,621,633,657,660,705,730,747,764,786],{"title":194,"path":619,"stem":620,"type":14,"device":6},"\u002Fliquid-handling-and-robots\u002Foverview\u002F","06.liquid-handling-and-robots\u002F00.overview",{"title":353,"type":6,"device":6,"path":622,"stem":623,"children":624,"page":41},"\u002Fliquid-handling-and-robots\u002Fdeck\u002F","06.liquid-handling-and-robots\u002F10.deck",[625,629],{"title":626,"path":627,"stem":628,"type":24,"device":6},"Building a Deck","\u002Fliquid-handling-and-robots\u002Fdeck\u002Fbuilding-a-deck\u002F","06.liquid-handling-and-robots\u002F10.deck\u002F10.building-a-deck",{"title":630,"path":631,"stem":632,"type":24,"device":6},"Save\u002FLoad a Deck","\u002Fliquid-handling-and-robots\u002Fdeck\u002Fsave-load-deck\u002F","06.liquid-handling-and-robots\u002F10.deck\u002F20.save-load-deck",{"title":634,"type":6,"device":6,"path":635,"stem":636,"children":637,"page":41},"Pipetting","\u002Fliquid-handling-and-robots\u002Fpipetting\u002F","06.liquid-handling-and-robots\u002F20.pipetting",[638,642,646,650,653],{"title":639,"path":640,"stem":641,"type":24,"device":6},"Basic Pipetting","\u002Fliquid-handling-and-robots\u002Fpipetting\u002Fbasic-pipetting\u002F","06.liquid-handling-and-robots\u002F20.pipetting\u002F10.basic-pipetting",{"title":643,"path":644,"stem":645,"type":24,"device":6},"Advanced Pipetting","\u002Fliquid-handling-and-robots\u002Fpipetting\u002Fadvanced-pipetting\u002F","06.liquid-handling-and-robots\u002F20.pipetting\u002F20.advanced-pipetting",{"title":647,"path":648,"stem":649,"type":24,"device":6},"Tip Handling","\u002Fliquid-handling-and-robots\u002Fpipetting\u002Ftip-handling\u002F","06.liquid-handling-and-robots\u002F20.pipetting\u002F30.tip-handling",{"title":364,"path":651,"stem":652,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Fpipetting\u002Fliquid-classes\u002F","06.liquid-handling-and-robots\u002F20.pipetting\u002F40.liquid-classes",{"title":654,"path":655,"stem":656,"type":24,"device":6},"Labware Transport","\u002Fliquid-handling-and-robots\u002Fpipetting\u002Flabware-transport\u002F","06.liquid-handling-and-robots\u002F20.pipetting\u002F50.labware-transport",{"title":376,"path":658,"stem":659,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Fsimulation\u002F","06.liquid-handling-and-robots\u002F30.simulation",{"title":661,"type":6,"device":6,"path":662,"stem":663,"children":664,"page":41},"Hamilton STAR","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star",[665,669,673,677,681,685,689,693,697,701],{"title":666,"path":667,"stem":668,"type":24,"device":6},"Positioning & Movement","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fpositioning\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F10.positioning",{"title":670,"path":671,"stem":672,"type":24,"device":6},"Gripper Module","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fcore-gripper\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F20.core-gripper",{"title":674,"path":675,"stem":676,"type":24,"device":6},"iSWAP Module","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fiswap\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F30.iswap",{"title":678,"path":679,"stem":680,"type":24,"device":6},"Using TADM","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Ftadm\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F40.tadm",{"title":682,"path":683,"stem":684,"type":24,"device":6},"Autoload Module","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fautoload\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F50.autoload",{"title":686,"path":687,"stem":688,"type":24,"device":6},"Waste Block","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fwaste-block\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F60.waste-block",{"title":690,"path":691,"stem":692,"type":24,"device":6},"Complex Mixing","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fcomplex-mixing\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F66.complex-mixing",{"title":694,"path":695,"stem":696,"type":24,"device":6},"Teaching Gripper Paddle Positions","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fgripper-positions\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F70.gripper-positions",{"title":698,"path":699,"stem":700,"type":24,"device":6},"Training a Custom Deck Position With the iSWAP","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fcustom-deck-position\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F75.custom-deck-position",{"title":702,"path":703,"stem":704,"type":200,"device":6},"Observable Commands","\u002Fliquid-handling-and-robots\u002Fhamilton-star\u002Fobservable-commands\u002F","06.liquid-handling-and-robots\u002F41.hamilton-star\u002F80.observable-commands",{"title":706,"type":6,"device":6,"path":707,"stem":708,"children":709,"page":41},"Hamilton Vantage","\u002Fliquid-handling-and-robots\u002Fhamilton-vantage\u002F","06.liquid-handling-and-robots\u002F42.hamilton-vantage",[710,714,718,722,726],{"title":711,"path":712,"stem":713,"type":24,"device":6},"Waste Configuration","\u002Fliquid-handling-and-robots\u002Fhamilton-vantage\u002Fwaste-configuration\u002F","06.liquid-handling-and-robots\u002F42.hamilton-vantage\u002F05.waste-configuration",{"title":715,"path":716,"stem":717,"type":24,"device":6},"Covers and Lights","\u002Fliquid-handling-and-robots\u002Fhamilton-vantage\u002Fcovers-and-lights\u002F","06.liquid-handling-and-robots\u002F42.hamilton-vantage\u002F10.covers-and-lights",{"title":719,"path":720,"stem":721,"type":24,"device":6},"IDL Module","\u002Fliquid-handling-and-robots\u002Fhamilton-vantage\u002Fidl\u002F","06.liquid-handling-and-robots\u002F42.hamilton-vantage\u002F20.idl",{"title":723,"path":724,"stem":725,"type":24,"device":6},"IPG Module","\u002Fliquid-handling-and-robots\u002Fhamilton-vantage\u002Fipg\u002F","06.liquid-handling-and-robots\u002F42.hamilton-vantage\u002F30.ipg",{"title":727,"path":728,"stem":729,"type":24,"device":6},"XL Pipettes","\u002Fliquid-handling-and-robots\u002Fhamilton-vantage\u002Fxl-channels\u002F","06.liquid-handling-and-robots\u002F42.hamilton-vantage\u002F40.xl-channels",{"title":731,"type":6,"device":6,"path":732,"stem":733,"children":734,"page":41},"Agilent Bravo","\u002Fliquid-handling-and-robots\u002Fagilent-bravo\u002F","06.liquid-handling-and-robots\u002F43.agilent-bravo",[735,738,741,744],{"title":647,"path":736,"stem":737,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Fagilent-bravo\u002Ftip-handling\u002F","06.liquid-handling-and-robots\u002F43.agilent-bravo\u002F10.tip-handling",{"title":639,"path":739,"stem":740,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Fagilent-bravo\u002Fbasic-pipetting\u002F","06.liquid-handling-and-robots\u002F43.agilent-bravo\u002F20.basic-pipetting",{"title":364,"path":742,"stem":743,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Fagilent-bravo\u002Fliquid-classes\u002F","06.liquid-handling-and-robots\u002F43.agilent-bravo\u002F25.liquid-classes",{"title":670,"path":745,"stem":746,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Fagilent-bravo\u002Fusing-the-gripper\u002F","06.liquid-handling-and-robots\u002F43.agilent-bravo\u002F30.using-the-gripper",{"title":748,"type":6,"device":6,"path":749,"stem":750,"children":751,"page":41},"Tecan FluentControl","\u002Fliquid-handling-and-robots\u002Ftecan-fluentcontrol\u002F","06.liquid-handling-and-robots\u002F44.tecan-fluentcontrol",[752,756,760],{"title":753,"path":754,"stem":755,"type":24,"device":6},"Connect & Run a Method","\u002Fliquid-handling-and-robots\u002Ftecan-fluentcontrol\u002Fconnect-and-run\u002F","06.liquid-handling-and-robots\u002F44.tecan-fluentcontrol\u002F10.connect-and-run",{"title":757,"path":758,"stem":759,"type":24,"device":6},"Sending XML Commands","\u002Fliquid-handling-and-robots\u002Ftecan-fluentcontrol\u002Fsending-xml-commands\u002F","06.liquid-handling-and-robots\u002F44.tecan-fluentcontrol\u002F20.sending-xml-commands",{"title":761,"path":762,"stem":763,"type":24,"device":6},"Full Workflow Example","\u002Fliquid-handling-and-robots\u002Ftecan-fluentcontrol\u002Ffull-workflow-example\u002F","06.liquid-handling-and-robots\u002F44.tecan-fluentcontrol\u002F30.full-workflow-example",{"title":765,"type":6,"device":6,"path":766,"stem":767,"children":768,"page":41},"Tecan Freedom EVO","\u002Fliquid-handling-and-robots\u002Ftecan-freedom-evo\u002F","06.liquid-handling-and-robots\u002F45.tecan-freedom-evo",[769,773,776,779,783],{"title":770,"path":771,"stem":772,"type":24,"device":6},"Deck & Carriers","\u002Fliquid-handling-and-robots\u002Ftecan-freedom-evo\u002Fdeck-and-carriers\u002F","06.liquid-handling-and-robots\u002F45.tecan-freedom-evo\u002F10.deck-and-carriers",{"title":647,"path":774,"stem":775,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Ftecan-freedom-evo\u002Ftip-handling\u002F","06.liquid-handling-and-robots\u002F45.tecan-freedom-evo\u002F20.tip-handling",{"title":639,"path":777,"stem":778,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Ftecan-freedom-evo\u002Fbasic-pipetting\u002F","06.liquid-handling-and-robots\u002F45.tecan-freedom-evo\u002F30.basic-pipetting",{"title":780,"path":781,"stem":782,"type":24,"device":6},"Using the Gripper (RoMa)","\u002Fliquid-handling-and-robots\u002Ftecan-freedom-evo\u002Fusing-the-gripper\u002F","06.liquid-handling-and-robots\u002F45.tecan-freedom-evo\u002F40.using-the-gripper",{"title":364,"path":784,"stem":785,"type":24,"device":6},"\u002Fliquid-handling-and-robots\u002Ftecan-freedom-evo\u002Fliquid-classes\u002F","06.liquid-handling-and-robots\u002F45.tecan-freedom-evo\u002F50.liquid-classes",{"title":600,"type":6,"device":6,"path":787,"stem":788,"children":789,"page":41},"\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002F","06.liquid-handling-and-robots\u002F46.brooks-preciseflex-400",[790,794,798],{"title":791,"path":792,"stem":793,"type":24,"device":6},"Teach Positions","\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002Fteach-positions\u002F","06.liquid-handling-and-robots\u002F46.brooks-preciseflex-400\u002F10.teach-positions",{"title":795,"path":796,"stem":797,"type":24,"device":6},"Move a Plate","\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002Fmove-a-plate\u002F","06.liquid-handling-and-robots\u002F46.brooks-preciseflex-400\u002F20.move-a-plate",{"title":799,"path":800,"stem":801,"type":24,"device":6},"Recover from a Stop","\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002Frecover-from-a-stop\u002F","06.liquid-handling-and-robots\u002F46.brooks-preciseflex-400\u002F30.recover-from-a-stop",{"title":245,"type":6,"device":6,"path":803,"stem":804,"children":805,"page":41},"\u002Flabware\u002F","07.labware",[806,809,813,817,821,825,829],{"title":194,"path":807,"stem":808,"type":14,"device":6},"\u002Flabware\u002Foverview\u002F","07.labware\u002F00.overview",{"title":810,"path":811,"stem":812,"type":200,"device":6},"Standard Labware","\u002Flabware\u002Fstandard-labware\u002F","07.labware\u002F10.standard-labware",{"title":814,"path":815,"stem":816,"type":200,"device":6},"Plates","\u002Flabware\u002Fplates\u002F","07.labware\u002F20.plates",{"title":818,"path":819,"stem":820,"type":200,"device":6},"Tips and Tip Racks","\u002Flabware\u002Ftips-and-racks\u002F","07.labware\u002F30.tips-and-racks",{"title":822,"path":823,"stem":824,"type":200,"device":6},"Tubes and Tube Racks","\u002Flabware\u002Ftubes-and-tube-racks\u002F","07.labware\u002F40.tubes-and-tube-racks",{"title":826,"path":827,"stem":828,"type":200,"device":6},"Troughs","\u002Flabware\u002Ftroughs\u002F","07.labware\u002F50.troughs",{"title":830,"path":831,"stem":832,"type":200,"device":6},"Carriers and Adapters","\u002Flabware\u002Fcarriers-and-adapters\u002F","07.labware\u002F60.carriers-and-adapters",{"title":834,"type":6,"device":6,"path":835,"stem":836,"children":837},"Connector Development (CDK)","\u002Fconnector-development\u002F","20.connector-development",[838,840,864,897,905,945],{"title":194,"path":835,"stem":839,"type":14,"device":6},"20.connector-development\u002Findex",{"title":841,"path":842,"stem":843,"children":844,"page":41},"Getting Started","\u002Fconnector-development\u002Fgetting-started\u002F","20.connector-development\u002F10.getting-started",[845,848,852,856,860],{"title":194,"path":846,"stem":847,"type":285,"device":6},"\u002Fconnector-development\u002Fgetting-started\u002Foverview\u002F","20.connector-development\u002F10.getting-started\u002F10.overview",{"title":849,"path":850,"stem":851,"type":24,"device":6},"What's new","\u002Fconnector-development\u002Fgetting-started\u002Fwhats-new\u002F","20.connector-development\u002F10.getting-started\u002F20.whats-new",{"title":853,"path":854,"stem":855,"type":24,"device":6},"Installation","\u002Fconnector-development\u002Fgetting-started\u002Finstallation\u002F","20.connector-development\u002F10.getting-started\u002F30.installation",{"title":857,"path":858,"stem":859,"type":24,"device":6},"Python Environment and Project Management","\u002Fconnector-development\u002Fgetting-started\u002Fpython-environments\u002F","20.connector-development\u002F10.getting-started\u002F35.python-environments",{"title":861,"path":862,"stem":863,"type":24,"device":6},"Contributing","\u002Fconnector-development\u002Fgetting-started\u002Fcontributing\u002F","20.connector-development\u002F10.getting-started\u002F40.contributing",{"title":865,"path":866,"stem":867,"children":868,"page":41},"Tutorial","\u002Fconnector-development\u002Ftutorial\u002F","20.connector-development\u002F20.tutorial",[869,873,877,881,885,889,893],{"title":870,"path":871,"stem":872,"type":46,"device":6},"Walkthrough","\u002Fconnector-development\u002Ftutorial\u002Fwalkthrough\u002F","20.connector-development\u002F20.tutorial\u002F00.walkthrough",{"title":874,"path":875,"stem":876,"type":46,"device":6},"SiLA Endpoints","\u002Fconnector-development\u002Ftutorial\u002Fsila-endpoints\u002F","20.connector-development\u002F20.tutorial\u002F10.sila-endpoints",{"title":878,"path":879,"stem":880,"type":46,"device":6},"Data Endpoints","\u002Fconnector-development\u002Ftutorial\u002Fdata-endpoints\u002F","20.connector-development\u002F20.tutorial\u002F20.data-endpoints",{"title":882,"path":883,"stem":884,"type":46,"device":6},"Controls","\u002Fconnector-development\u002Ftutorial\u002Fcontrols\u002F","20.connector-development\u002F20.tutorial\u002F30.controls",{"title":886,"path":887,"stem":888,"type":46,"device":6},"SiLA Data Types","\u002Fconnector-development\u002Ftutorial\u002Fdata-types\u002F","20.connector-development\u002F20.tutorial\u002F40.data-types",{"title":890,"path":891,"stem":892,"type":46,"device":6},"Feature","\u002Fconnector-development\u002Ftutorial\u002Fconnector-structure\u002F","20.connector-development\u002F20.tutorial\u002F70.connector-structure",{"title":894,"path":895,"stem":896,"type":46,"device":6},"Hardware Communication","\u002Fconnector-development\u002Ftutorial\u002Fhardware-communication\u002F","20.connector-development\u002F20.tutorial\u002F90.hardware-communication",{"title":272,"type":6,"device":6,"path":898,"stem":899,"children":900,"page":41},"\u002Fconnector-development\u002Fconcepts\u002F","20.connector-development\u002F30.concepts",[901],{"title":902,"path":903,"stem":904,"type":285,"device":6},"SiLA","\u002Fconnector-development\u002Fconcepts\u002Fsila\u002F","20.connector-development\u002F30.concepts\u002Fsila",{"title":906,"path":907,"stem":908,"children":909,"page":41},"Guides","\u002Fconnector-development\u002Fguides\u002F","20.connector-development\u002F40.guides",[910,914,918,922,926,930,934,937,941],{"title":911,"path":912,"stem":913,"type":24,"device":6},"Configuration","\u002Fconnector-development\u002Fguides\u002Fconfiguration\u002F","20.connector-development\u002F40.guides\u002F20.configuration",{"title":915,"path":916,"stem":917,"type":24,"device":6},"Logging","\u002Fconnector-development\u002Fguides\u002Flogging\u002F","20.connector-development\u002F40.guides\u002F21.logging",{"title":919,"path":920,"stem":921,"type":24,"device":6},"Deployment","\u002Fconnector-development\u002Fguides\u002Fdeployment\u002F","20.connector-development\u002F40.guides\u002F30.deployment",{"title":923,"path":924,"stem":925,"type":24,"device":6},"Security","\u002Fconnector-development\u002Fguides\u002Fsecurity\u002F","20.connector-development\u002F40.guides\u002F40.security",{"title":927,"path":928,"stem":929,"type":24,"device":6},"Subscriptions","\u002Fconnector-development\u002Fguides\u002Fsubscriptions\u002F","20.connector-development\u002F40.guides\u002F45.subscriptions",{"title":931,"path":932,"stem":933,"type":24,"device":6},"Execution Modes","\u002Fconnector-development\u002Fguides\u002Fexecution-modes\u002F","20.connector-development\u002F40.guides\u002F46.execution-modes",{"title":380,"path":935,"stem":936,"type":24,"device":6},"\u002Fconnector-development\u002Fguides\u002Ferror-handling\u002F","20.connector-development\u002F40.guides\u002F50.error-handling",{"title":938,"path":939,"stem":940,"type":24,"device":6},"Serial Troubleshooting","\u002Fconnector-development\u002Fguides\u002Fserial-troubleshooting\u002F","20.connector-development\u002F40.guides\u002F70.serial-troubleshooting",{"title":942,"path":943,"stem":944,"type":24,"device":6},"Testing","\u002Fconnector-development\u002Fguides\u002Ftesting\u002F","20.connector-development\u002F40.guides\u002F80.testing",{"title":946,"path":947,"stem":948,"children":949,"type":6,"device":6},"References","\u002Fconnector-development\u002Freference\u002F","20.connector-development\u002F50.reference\u002Findex",[950],{"title":946,"path":947,"stem":948,"type":200,"device":6},{"id":952,"title":795,"body":953,"description":3194,"device":6,"extension":3195,"links":6,"meta":3196,"navigation":1027,"path":3197,"seo":3198,"stem":797,"type":24,"__hash__":3199},"docs\u002F06.liquid-handling-and-robots\u002F46.brooks-preciseflex-400\u002F20.move-a-plate.md",{"type":954,"value":955,"toc":3190},"minimark",[956,969,985,2974,2984,2988,3001,3018,3043,3059,3082,3133,3148,3161,3169,3173,3186],[957,958,959,960,964,965,968],"p",{},"The script below picks a plate up at station ",[961,962,963],"code",{},"A1"," and puts it down at station ",[961,966,967],{},"B1",". Each move is one\ncall: the arm travels in through the station's safe point and approach, grabs or releases at the\nnest, and backs out the same way.",[957,970,971,972,976,977,980,981,984],{},"You need the ",[973,974,975],"a",{"href":39},"SDK installed",", the ",[973,978,979],{"href":601},"PF400 connector running",",\nand both stations taught in the Teach view\n(",[973,982,983],{"href":792},"Teach positions","). The script\nreads the teachpoints from the platform, so a point you re-teach is picked up on the next run. No arm\non the bench? Switch the connector to simulation mode and the script runs the same.",[986,987,993],"pre",{"className":988,"code":989,"filename":990,"language":991,"meta":992,"style":992},"language-python shiki shiki-themes github-light-high-contrast github-light-high-contrast github-dark-default","import asyncio\nfrom dataclasses import dataclass\n\nfrom unitelabs.sdk import AsyncApiClient\n\nDEVICE = \"PF400\"  # the arm's name on the Devices page\n\n# Motion profiles: fixed slots built into the connector (0.4.0 and later)\nSETTLE = 0  # 10% of rated speed, stops exactly on each point\nBLEND = -4  # 25% of rated speed, flows through points without stopping\n\n# The plate, as the jaw holds it\nPLATE_WIDTH = 127.76  # mm between the jaws: an SBS plate, landscape\nGRIP_SPEED = 20.0  # % of the jaw's top speed\nGRIP_FORCE = 5.0  # N, the most the jaw squeezes\n\n\nasync def main():\n    client = AsyncApiClient()\n\n    # 1. Find the arm, and load what was taught in the Teach view\n    device_id, arm = await find_arm(client, DEVICE)\n    teaching = await load_teaching(client, device_id)\n\n    # 2. Plan both moves first. A wrong station name fails here,\n    #    while the arm is still at rest\n    pick = plan(teaching, \"A1\")\n    place = plan(teaching, \"B1\", coming_from=\"A1\")\n\n    # 3. The arm only moves once it is homed\n    state = await read_state(arm)\n    if not state[\"Homed\"]:\n        await arm.movement_controller.home()\n\n    # 4. Pick the plate up at A1 and put it down at B1\n    pick_up, put_down = await transport_actions(arm)\n    grip = dict(width=PLATE_WIDTH, grip_speed=GRIP_SPEED)\n    await pick_up(**pick, **grip, force=GRIP_FORCE)\n    await put_down(**place, **grip)\n    print(\"Plate moved from A1 to B1\")\n\n\n@dataclass\nclass Teaching:\n    points: dict  # point name -> joint values\n    stations: dict  # station -> point names, nest first, safe point last\n    spine: list  # safe point names, in the order the arm passes them\n\n\ndef plan(teaching, station, coming_from=None):\n    \"\"\"The path in to a station's nest and back out again.\"\"\"\n    path = teaching.stations[station]\n    nest = path[0]\n    approach = path[1]\n    way_out = path[2:]  # any transitions, then the safe point\n    way_in = list(reversed(way_out))\n\n    # Coming from another station, travel along the safe spine first\n    if coming_from:\n        start = teaching.stations[coming_from][-1]  # its safe point\n        way_in = spine_between(teaching.spine, start, way_out[-1]) + way_in\n\n    joints = teaching.points\n    return dict(\n        approach_path=[joints[name] for name in way_in],\n        approach_path_profile=BLEND,\n        approach=joints[approach],\n        approach_profile=SETTLE,\n        target=joints[nest],\n        target_profile=SETTLE,\n        retract=joints[approach],\n        retract_profile=SETTLE,\n        retract_path=[joints[name] for name in way_out],\n        retract_path_profile=BLEND,\n    )\n\n\ndef spine_between(spine, start, end):\n    \"\"\"The safe points between two safe points, in travel order.\"\"\"\n    i, j = spine.index(start), spine.index(end)\n    if i \u003C j:\n        return spine[i + 1 : j]\n    return list(reversed(spine[j + 1 : i]))\n\n\nasync def load_teaching(client, device_id):\n    \"\"\"Every teachpoint of the arm, grouped into stations and the spine.\"\"\"\n    points, names = {}, {}\n    url = f\"\u002Fdevices\u002F{device_id}\u002Fteach-points\"\n    for point in await get_all(client, url):\n        # The platform says \"column\": 0, the connector wants \"Column\": 0.0\n        joints = {}\n        for axis, value in point[\"joints\"].items():\n            joints[axis.capitalize()] = float(value)\n        points[point[\"name\"]] = joints\n        names[point[\"id\"]] = point[\"name\"]\n\n    # A group lists its points in path order. A station is a group\n    # named after its nest; the spine is the group of kind SAFE\n    stations, spine = {}, []\n    url = f\"\u002Fdevices\u002F{device_id}\u002Fteach-groups\"\n    for group in await get_all(client, url):\n        members = sorted(group[\"members\"], key=lambda m: m[\"position\"])\n        path = [names[m[\"teachPointId\"]] for m in members]\n        if group[\"kind\"] == \"NEST\":\n            stations[group[\"name\"].removeprefix(\"NEST_\")] = path\n        elif group[\"kind\"] == \"SAFE\":\n            spine = path\n\n    # On an arm with a rail, the spine runs along the rail\n    if spine and all(\"Rail\" in points[name] for name in spine):\n        spine.sort(key=lambda name: points[name][\"Rail\"])\n    return Teaching(points, stations, spine)\n\n\nasync def find_arm(client, name):\n    \"\"\"The device with this name, and the connector that drives it.\"\"\"\n    found = await client.get(\"\u002Fdevices\", params={\"name\": name})\n    if not found[\"data\"]:\n        raise RuntimeError(f\"No device named {name!r}\")\n    device_id = found[\"data\"][0][\"id\"]\n    services = await client.get(f\"\u002Fdevices\u002F{device_id}\u002Fservices\")\n    if not services:\n        raise RuntimeError(f\"{name!r} has no connector\")\n    return device_id, await client.get_service(services[0][\"id\"])\n\n\nasync def transport_actions(arm):\n    \"\"\"Pick-up and put-down. On a rail arm they end in \"_with_rail\".\"\"\"\n    rail = await arm.information_provider.get_rail_installed()\n    suffix = \"_with_rail\" if rail else \"\"\n    actions = arm.transport_controller.actions\n    pick_up = actions[\"pick_up_joints\" + suffix]\n    put_down = actions[\"put_down_joints\" + suffix]\n    return pick_up, put_down\n\n\nasync def read_state(arm):\n    \"\"\"Powered, homed and idle? The first event of the stream is empty.\"\"\"\n    states = await arm.information_provider.subscribe_state()\n    async with states:\n        async for state in states:\n            if \"Homed\" in state:\n                return state\n    raise RuntimeError(\"The state stream closed without a state\")\n\n\nasync def get_all(client, url):\n    \"\"\"One page of up to 100 entries; refuse to drop any silently.\"\"\"\n    page = await client.get(url, params={\"_take\": 100})\n    if page[\"pagination\"][\"hasMore\"]:\n        raise RuntimeError(f\"More than 100 entries at {url}\")\n    return page[\"data\"]\n\n\nasyncio.run(main())\n","move_a_plate.py","python","",[961,994,995,1008,1022,1029,1042,1047,1065,1070,1076,1090,1107,1112,1118,1132,1146,1160,1165,1170,1186,1198,1203,1209,1228,1241,1246,1252,1258,1274,1300,1305,1311,1324,1342,1351,1356,1362,1375,1407,1436,1454,1467,1472,1477,1483,1495,1507,1518,1530,1535,1540,1560,1566,1577,1594,1609,1628,1647,1652,1658,1666,1688,1712,1717,1728,1739,1762,1775,1786,1798,1809,1821,1831,1843,1862,1874,1880,1885,1890,1901,1907,1918,1932,1949,1970,1975,1980,1993,1999,2010,2036,2052,2058,2069,2089,2103,2120,2139,2144,2150,2156,2167,2187,2201,2236,2262,2285,2307,2326,2336,2341,2347,2381,2398,2406,2411,2416,2429,2435,2465,2480,2510,2533,2560,2570,2594,2616,2621,2626,2639,2645,2658,2681,2692,2712,2729,2737,2742,2747,2759,2765,2778,2790,2806,2820,2829,2844,2849,2854,2867,2873,2904,2922,2947,2958,2963,2968],{"__ignoreMap":992},[996,997,1000,1004],"span",{"class":998,"line":999},"line",1,[996,1001,1003],{"class":1002},"sxkbv","import",[996,1005,1007],{"class":1006},"sc-9e"," asyncio\n",[996,1009,1011,1014,1017,1019],{"class":998,"line":1010},2,[996,1012,1013],{"class":1002},"from",[996,1015,1016],{"class":1006}," dataclasses ",[996,1018,1003],{"class":1002},[996,1020,1021],{"class":1006}," dataclass\n",[996,1023,1025],{"class":998,"line":1024},3,[996,1026,1028],{"emptyLinePlaceholder":1027},true,"\n",[996,1030,1032,1034,1037,1039],{"class":998,"line":1031},4,[996,1033,1013],{"class":1002},[996,1035,1036],{"class":1006}," unitelabs.sdk ",[996,1038,1003],{"class":1002},[996,1040,1041],{"class":1006}," AsyncApiClient\n",[996,1043,1045],{"class":998,"line":1044},5,[996,1046,1028],{"emptyLinePlaceholder":1027},[996,1048,1050,1054,1057,1061],{"class":998,"line":1049},6,[996,1051,1053],{"class":1052},"sOiAX","DEVICE",[996,1055,1056],{"class":1002}," =",[996,1058,1060],{"class":1059},"sCx38"," \"PF400\"",[996,1062,1064],{"class":1063},"sIsDC","  # the arm's name on the Devices page\n",[996,1066,1068],{"class":998,"line":1067},7,[996,1069,1028],{"emptyLinePlaceholder":1027},[996,1071,1073],{"class":998,"line":1072},8,[996,1074,1075],{"class":1063},"# Motion profiles: fixed slots built into the connector (0.4.0 and later)\n",[996,1077,1079,1082,1084,1087],{"class":998,"line":1078},9,[996,1080,1081],{"class":1052},"SETTLE",[996,1083,1056],{"class":1002},[996,1085,1086],{"class":1052}," 0",[996,1088,1089],{"class":1063},"  # 10% of rated speed, stops exactly on each point\n",[996,1091,1093,1096,1098,1101,1104],{"class":998,"line":1092},10,[996,1094,1095],{"class":1052},"BLEND",[996,1097,1056],{"class":1002},[996,1099,1100],{"class":1002}," -",[996,1102,1103],{"class":1052},"4",[996,1105,1106],{"class":1063},"  # 25% of rated speed, flows through points without stopping\n",[996,1108,1110],{"class":998,"line":1109},11,[996,1111,1028],{"emptyLinePlaceholder":1027},[996,1113,1115],{"class":998,"line":1114},12,[996,1116,1117],{"class":1063},"# The plate, as the jaw holds it\n",[996,1119,1121,1124,1126,1129],{"class":998,"line":1120},13,[996,1122,1123],{"class":1052},"PLATE_WIDTH",[996,1125,1056],{"class":1002},[996,1127,1128],{"class":1052}," 127.76",[996,1130,1131],{"class":1063},"  # mm between the jaws: an SBS plate, landscape\n",[996,1133,1135,1138,1140,1143],{"class":998,"line":1134},14,[996,1136,1137],{"class":1052},"GRIP_SPEED",[996,1139,1056],{"class":1002},[996,1141,1142],{"class":1052}," 20.0",[996,1144,1145],{"class":1063},"  # % of the jaw's top speed\n",[996,1147,1149,1152,1154,1157],{"class":998,"line":1148},15,[996,1150,1151],{"class":1052},"GRIP_FORCE",[996,1153,1056],{"class":1002},[996,1155,1156],{"class":1052}," 5.0",[996,1158,1159],{"class":1063},"  # N, the most the jaw squeezes\n",[996,1161,1163],{"class":998,"line":1162},16,[996,1164,1028],{"emptyLinePlaceholder":1027},[996,1166,1168],{"class":998,"line":1167},17,[996,1169,1028],{"emptyLinePlaceholder":1027},[996,1171,1173,1176,1179,1183],{"class":998,"line":1172},18,[996,1174,1175],{"class":1002},"async",[996,1177,1178],{"class":1002}," def",[996,1180,1182],{"class":1181},"s4qFZ"," main",[996,1184,1185],{"class":1006},"():\n",[996,1187,1189,1192,1195],{"class":998,"line":1188},19,[996,1190,1191],{"class":1006},"    client ",[996,1193,1194],{"class":1002},"=",[996,1196,1197],{"class":1006}," AsyncApiClient()\n",[996,1199,1201],{"class":998,"line":1200},20,[996,1202,1028],{"emptyLinePlaceholder":1027},[996,1204,1206],{"class":998,"line":1205},21,[996,1207,1208],{"class":1063},"    # 1. Find the arm, and load what was taught in the Teach view\n",[996,1210,1212,1215,1217,1220,1223,1225],{"class":998,"line":1211},22,[996,1213,1214],{"class":1006},"    device_id, arm ",[996,1216,1194],{"class":1002},[996,1218,1219],{"class":1002}," await",[996,1221,1222],{"class":1006}," find_arm(client, ",[996,1224,1053],{"class":1052},[996,1226,1227],{"class":1006},")\n",[996,1229,1231,1234,1236,1238],{"class":998,"line":1230},23,[996,1232,1233],{"class":1006},"    teaching ",[996,1235,1194],{"class":1002},[996,1237,1219],{"class":1002},[996,1239,1240],{"class":1006}," load_teaching(client, device_id)\n",[996,1242,1244],{"class":998,"line":1243},24,[996,1245,1028],{"emptyLinePlaceholder":1027},[996,1247,1249],{"class":998,"line":1248},25,[996,1250,1251],{"class":1063},"    # 2. Plan both moves first. A wrong station name fails here,\n",[996,1253,1255],{"class":998,"line":1254},26,[996,1256,1257],{"class":1063},"    #    while the arm is still at rest\n",[996,1259,1261,1264,1266,1269,1272],{"class":998,"line":1260},27,[996,1262,1263],{"class":1006},"    pick ",[996,1265,1194],{"class":1002},[996,1267,1268],{"class":1006}," plan(teaching, ",[996,1270,1271],{"class":1059},"\"A1\"",[996,1273,1227],{"class":1006},[996,1275,1277,1280,1282,1284,1287,1290,1294,1296,1298],{"class":998,"line":1276},28,[996,1278,1279],{"class":1006},"    place ",[996,1281,1194],{"class":1002},[996,1283,1268],{"class":1006},[996,1285,1286],{"class":1059},"\"B1\"",[996,1288,1289],{"class":1006},", ",[996,1291,1293],{"class":1292},"sNqAu","coming_from",[996,1295,1194],{"class":1002},[996,1297,1271],{"class":1059},[996,1299,1227],{"class":1006},[996,1301,1303],{"class":998,"line":1302},29,[996,1304,1028],{"emptyLinePlaceholder":1027},[996,1306,1308],{"class":998,"line":1307},30,[996,1309,1310],{"class":1063},"    # 3. The arm only moves once it is homed\n",[996,1312,1314,1317,1319,1321],{"class":998,"line":1313},31,[996,1315,1316],{"class":1006},"    state ",[996,1318,1194],{"class":1002},[996,1320,1219],{"class":1002},[996,1322,1323],{"class":1006}," read_state(arm)\n",[996,1325,1327,1330,1333,1336,1339],{"class":998,"line":1326},32,[996,1328,1329],{"class":1002},"    if",[996,1331,1332],{"class":1002}," not",[996,1334,1335],{"class":1006}," state[",[996,1337,1338],{"class":1059},"\"Homed\"",[996,1340,1341],{"class":1006},"]:\n",[996,1343,1345,1348],{"class":998,"line":1344},33,[996,1346,1347],{"class":1002},"        await",[996,1349,1350],{"class":1006}," arm.movement_controller.home()\n",[996,1352,1354],{"class":998,"line":1353},34,[996,1355,1028],{"emptyLinePlaceholder":1027},[996,1357,1359],{"class":998,"line":1358},35,[996,1360,1361],{"class":1063},"    # 4. Pick the plate up at A1 and put it down at B1\n",[996,1363,1365,1368,1370,1372],{"class":998,"line":1364},36,[996,1366,1367],{"class":1006},"    pick_up, put_down ",[996,1369,1194],{"class":1002},[996,1371,1219],{"class":1002},[996,1373,1374],{"class":1006}," transport_actions(arm)\n",[996,1376,1378,1381,1383,1386,1389,1392,1394,1396,1398,1401,1403,1405],{"class":998,"line":1377},37,[996,1379,1380],{"class":1006},"    grip ",[996,1382,1194],{"class":1002},[996,1384,1385],{"class":1052}," dict",[996,1387,1388],{"class":1006},"(",[996,1390,1391],{"class":1292},"width",[996,1393,1194],{"class":1002},[996,1395,1123],{"class":1052},[996,1397,1289],{"class":1006},[996,1399,1400],{"class":1292},"grip_speed",[996,1402,1194],{"class":1002},[996,1404,1137],{"class":1052},[996,1406,1227],{"class":1006},[996,1408,1410,1413,1416,1419,1422,1424,1427,1430,1432,1434],{"class":998,"line":1409},38,[996,1411,1412],{"class":1002},"    await",[996,1414,1415],{"class":1006}," pick_up(",[996,1417,1418],{"class":1002},"**",[996,1420,1421],{"class":1006},"pick, ",[996,1423,1418],{"class":1002},[996,1425,1426],{"class":1006},"grip, ",[996,1428,1429],{"class":1292},"force",[996,1431,1194],{"class":1002},[996,1433,1151],{"class":1052},[996,1435,1227],{"class":1006},[996,1437,1439,1441,1444,1446,1449,1451],{"class":998,"line":1438},39,[996,1440,1412],{"class":1002},[996,1442,1443],{"class":1006}," put_down(",[996,1445,1418],{"class":1002},[996,1447,1448],{"class":1006},"place, ",[996,1450,1418],{"class":1002},[996,1452,1453],{"class":1006},"grip)\n",[996,1455,1457,1460,1462,1465],{"class":998,"line":1456},40,[996,1458,1459],{"class":1052},"    print",[996,1461,1388],{"class":1006},[996,1463,1464],{"class":1059},"\"Plate moved from A1 to B1\"",[996,1466,1227],{"class":1006},[996,1468,1470],{"class":998,"line":1469},41,[996,1471,1028],{"emptyLinePlaceholder":1027},[996,1473,1475],{"class":998,"line":1474},42,[996,1476,1028],{"emptyLinePlaceholder":1027},[996,1478,1480],{"class":998,"line":1479},43,[996,1481,1482],{"class":1181},"@dataclass\n",[996,1484,1486,1489,1492],{"class":998,"line":1485},44,[996,1487,1488],{"class":1002},"class",[996,1490,1491],{"class":1292}," Teaching",[996,1493,1494],{"class":1006},":\n",[996,1496,1498,1501,1504],{"class":998,"line":1497},45,[996,1499,1500],{"class":1006},"    points: ",[996,1502,1503],{"class":1052},"dict",[996,1505,1506],{"class":1063},"  # point name -> joint values\n",[996,1508,1510,1513,1515],{"class":998,"line":1509},46,[996,1511,1512],{"class":1006},"    stations: ",[996,1514,1503],{"class":1052},[996,1516,1517],{"class":1063},"  # station -> point names, nest first, safe point last\n",[996,1519,1521,1524,1527],{"class":998,"line":1520},47,[996,1522,1523],{"class":1006},"    spine: ",[996,1525,1526],{"class":1052},"list",[996,1528,1529],{"class":1063},"  # safe point names, in the order the arm passes them\n",[996,1531,1533],{"class":998,"line":1532},48,[996,1534,1028],{"emptyLinePlaceholder":1027},[996,1536,1538],{"class":998,"line":1537},49,[996,1539,1028],{"emptyLinePlaceholder":1027},[996,1541,1543,1546,1549,1552,1554,1557],{"class":998,"line":1542},50,[996,1544,1545],{"class":1002},"def",[996,1547,1548],{"class":1181}," plan",[996,1550,1551],{"class":1006},"(teaching, station, coming_from",[996,1553,1194],{"class":1002},[996,1555,1556],{"class":1052},"None",[996,1558,1559],{"class":1006},"):\n",[996,1561,1563],{"class":998,"line":1562},51,[996,1564,1565],{"class":1059},"    \"\"\"The path in to a station's nest and back out again.\"\"\"\n",[996,1567,1569,1572,1574],{"class":998,"line":1568},52,[996,1570,1571],{"class":1006},"    path ",[996,1573,1194],{"class":1002},[996,1575,1576],{"class":1006}," teaching.stations[station]\n",[996,1578,1580,1583,1585,1588,1591],{"class":998,"line":1579},53,[996,1581,1582],{"class":1006},"    nest ",[996,1584,1194],{"class":1002},[996,1586,1587],{"class":1006}," path[",[996,1589,1590],{"class":1052},"0",[996,1592,1593],{"class":1006},"]\n",[996,1595,1597,1600,1602,1604,1607],{"class":998,"line":1596},54,[996,1598,1599],{"class":1006},"    approach ",[996,1601,1194],{"class":1002},[996,1603,1587],{"class":1006},[996,1605,1606],{"class":1052},"1",[996,1608,1593],{"class":1006},[996,1610,1612,1615,1617,1619,1622,1625],{"class":998,"line":1611},55,[996,1613,1614],{"class":1006},"    way_out ",[996,1616,1194],{"class":1002},[996,1618,1587],{"class":1006},[996,1620,1621],{"class":1052},"2",[996,1623,1624],{"class":1006},":]  ",[996,1626,1627],{"class":1063},"# any transitions, then the safe point\n",[996,1629,1631,1634,1636,1639,1641,1644],{"class":998,"line":1630},56,[996,1632,1633],{"class":1006},"    way_in ",[996,1635,1194],{"class":1002},[996,1637,1638],{"class":1052}," list",[996,1640,1388],{"class":1006},[996,1642,1643],{"class":1052},"reversed",[996,1645,1646],{"class":1006},"(way_out))\n",[996,1648,1650],{"class":998,"line":1649},57,[996,1651,1028],{"emptyLinePlaceholder":1027},[996,1653,1655],{"class":998,"line":1654},58,[996,1656,1657],{"class":1063},"    # Coming from another station, travel along the safe spine first\n",[996,1659,1661,1663],{"class":998,"line":1660},59,[996,1662,1329],{"class":1002},[996,1664,1665],{"class":1006}," coming_from:\n",[996,1667,1669,1672,1674,1677,1680,1682,1685],{"class":998,"line":1668},60,[996,1670,1671],{"class":1006},"        start ",[996,1673,1194],{"class":1002},[996,1675,1676],{"class":1006}," teaching.stations[coming_from][",[996,1678,1679],{"class":1002},"-",[996,1681,1606],{"class":1052},[996,1683,1684],{"class":1006},"]  ",[996,1686,1687],{"class":1063},"# its safe point\n",[996,1689,1691,1694,1696,1699,1701,1703,1706,1709],{"class":998,"line":1690},61,[996,1692,1693],{"class":1006},"        way_in ",[996,1695,1194],{"class":1002},[996,1697,1698],{"class":1006}," spine_between(teaching.spine, start, way_out[",[996,1700,1679],{"class":1002},[996,1702,1606],{"class":1052},[996,1704,1705],{"class":1006},"]) ",[996,1707,1708],{"class":1002},"+",[996,1710,1711],{"class":1006}," way_in\n",[996,1713,1715],{"class":998,"line":1714},62,[996,1716,1028],{"emptyLinePlaceholder":1027},[996,1718,1720,1723,1725],{"class":998,"line":1719},63,[996,1721,1722],{"class":1006},"    joints ",[996,1724,1194],{"class":1002},[996,1726,1727],{"class":1006}," teaching.points\n",[996,1729,1731,1734,1736],{"class":998,"line":1730},64,[996,1732,1733],{"class":1002},"    return",[996,1735,1385],{"class":1052},[996,1737,1738],{"class":1006},"(\n",[996,1740,1742,1745,1747,1750,1753,1756,1759],{"class":998,"line":1741},65,[996,1743,1744],{"class":1292},"        approach_path",[996,1746,1194],{"class":1002},[996,1748,1749],{"class":1006},"[joints[name] ",[996,1751,1752],{"class":1002},"for",[996,1754,1755],{"class":1006}," name ",[996,1757,1758],{"class":1002},"in",[996,1760,1761],{"class":1006}," way_in],\n",[996,1763,1765,1768,1770,1772],{"class":998,"line":1764},66,[996,1766,1767],{"class":1292},"        approach_path_profile",[996,1769,1194],{"class":1002},[996,1771,1095],{"class":1052},[996,1773,1774],{"class":1006},",\n",[996,1776,1778,1781,1783],{"class":998,"line":1777},67,[996,1779,1780],{"class":1292},"        approach",[996,1782,1194],{"class":1002},[996,1784,1785],{"class":1006},"joints[approach],\n",[996,1787,1789,1792,1794,1796],{"class":998,"line":1788},68,[996,1790,1791],{"class":1292},"        approach_profile",[996,1793,1194],{"class":1002},[996,1795,1081],{"class":1052},[996,1797,1774],{"class":1006},[996,1799,1801,1804,1806],{"class":998,"line":1800},69,[996,1802,1803],{"class":1292},"        target",[996,1805,1194],{"class":1002},[996,1807,1808],{"class":1006},"joints[nest],\n",[996,1810,1812,1815,1817,1819],{"class":998,"line":1811},70,[996,1813,1814],{"class":1292},"        target_profile",[996,1816,1194],{"class":1002},[996,1818,1081],{"class":1052},[996,1820,1774],{"class":1006},[996,1822,1824,1827,1829],{"class":998,"line":1823},71,[996,1825,1826],{"class":1292},"        retract",[996,1828,1194],{"class":1002},[996,1830,1785],{"class":1006},[996,1832,1834,1837,1839,1841],{"class":998,"line":1833},72,[996,1835,1836],{"class":1292},"        retract_profile",[996,1838,1194],{"class":1002},[996,1840,1081],{"class":1052},[996,1842,1774],{"class":1006},[996,1844,1846,1849,1851,1853,1855,1857,1859],{"class":998,"line":1845},73,[996,1847,1848],{"class":1292},"        retract_path",[996,1850,1194],{"class":1002},[996,1852,1749],{"class":1006},[996,1854,1752],{"class":1002},[996,1856,1755],{"class":1006},[996,1858,1758],{"class":1002},[996,1860,1861],{"class":1006}," way_out],\n",[996,1863,1865,1868,1870,1872],{"class":998,"line":1864},74,[996,1866,1867],{"class":1292},"        retract_path_profile",[996,1869,1194],{"class":1002},[996,1871,1095],{"class":1052},[996,1873,1774],{"class":1006},[996,1875,1877],{"class":998,"line":1876},75,[996,1878,1879],{"class":1006},"    )\n",[996,1881,1883],{"class":998,"line":1882},76,[996,1884,1028],{"emptyLinePlaceholder":1027},[996,1886,1888],{"class":998,"line":1887},77,[996,1889,1028],{"emptyLinePlaceholder":1027},[996,1891,1893,1895,1898],{"class":998,"line":1892},78,[996,1894,1545],{"class":1002},[996,1896,1897],{"class":1181}," spine_between",[996,1899,1900],{"class":1006},"(spine, start, end):\n",[996,1902,1904],{"class":998,"line":1903},79,[996,1905,1906],{"class":1059},"    \"\"\"The safe points between two safe points, in travel order.\"\"\"\n",[996,1908,1910,1913,1915],{"class":998,"line":1909},80,[996,1911,1912],{"class":1006},"    i, j ",[996,1914,1194],{"class":1002},[996,1916,1917],{"class":1006}," spine.index(start), spine.index(end)\n",[996,1919,1921,1923,1926,1929],{"class":998,"line":1920},81,[996,1922,1329],{"class":1002},[996,1924,1925],{"class":1006}," i ",[996,1927,1928],{"class":1002},"\u003C",[996,1930,1931],{"class":1006}," j:\n",[996,1933,1935,1938,1941,1943,1946],{"class":998,"line":1934},82,[996,1936,1937],{"class":1002},"        return",[996,1939,1940],{"class":1006}," spine[i ",[996,1942,1708],{"class":1002},[996,1944,1945],{"class":1052}," 1",[996,1947,1948],{"class":1006}," : j]\n",[996,1950,1952,1954,1956,1958,1960,1963,1965,1967],{"class":998,"line":1951},83,[996,1953,1733],{"class":1002},[996,1955,1638],{"class":1052},[996,1957,1388],{"class":1006},[996,1959,1643],{"class":1052},[996,1961,1962],{"class":1006},"(spine[j ",[996,1964,1708],{"class":1002},[996,1966,1945],{"class":1052},[996,1968,1969],{"class":1006}," : i]))\n",[996,1971,1973],{"class":998,"line":1972},84,[996,1974,1028],{"emptyLinePlaceholder":1027},[996,1976,1978],{"class":998,"line":1977},85,[996,1979,1028],{"emptyLinePlaceholder":1027},[996,1981,1983,1985,1987,1990],{"class":998,"line":1982},86,[996,1984,1175],{"class":1002},[996,1986,1178],{"class":1002},[996,1988,1989],{"class":1181}," load_teaching",[996,1991,1992],{"class":1006},"(client, device_id):\n",[996,1994,1996],{"class":998,"line":1995},87,[996,1997,1998],{"class":1059},"    \"\"\"Every teachpoint of the arm, grouped into stations and the spine.\"\"\"\n",[996,2000,2002,2005,2007],{"class":998,"line":2001},88,[996,2003,2004],{"class":1006},"    points, names ",[996,2006,1194],{"class":1002},[996,2008,2009],{"class":1006}," {}, {}\n",[996,2011,2013,2016,2018,2021,2024,2027,2030,2033],{"class":998,"line":2012},89,[996,2014,2015],{"class":1006},"    url ",[996,2017,1194],{"class":1002},[996,2019,2020],{"class":1002}," f",[996,2022,2023],{"class":1059},"\"\u002Fdevices\u002F",[996,2025,2026],{"class":1002},"{",[996,2028,2029],{"class":1006},"device_id",[996,2031,2032],{"class":1002},"}",[996,2034,2035],{"class":1059},"\u002Fteach-points\"\n",[996,2037,2039,2042,2045,2047,2049],{"class":998,"line":2038},90,[996,2040,2041],{"class":1002},"    for",[996,2043,2044],{"class":1006}," point ",[996,2046,1758],{"class":1002},[996,2048,1219],{"class":1002},[996,2050,2051],{"class":1006}," get_all(client, url):\n",[996,2053,2055],{"class":998,"line":2054},91,[996,2056,2057],{"class":1063},"        # The platform says \"column\": 0, the connector wants \"Column\": 0.0\n",[996,2059,2061,2064,2066],{"class":998,"line":2060},92,[996,2062,2063],{"class":1006},"        joints ",[996,2065,1194],{"class":1002},[996,2067,2068],{"class":1006}," {}\n",[996,2070,2072,2075,2078,2080,2083,2086],{"class":998,"line":2071},93,[996,2073,2074],{"class":1002},"        for",[996,2076,2077],{"class":1006}," axis, value ",[996,2079,1758],{"class":1002},[996,2081,2082],{"class":1006}," point[",[996,2084,2085],{"class":1059},"\"joints\"",[996,2087,2088],{"class":1006},"].items():\n",[996,2090,2092,2095,2097,2100],{"class":998,"line":2091},94,[996,2093,2094],{"class":1006},"            joints[axis.capitalize()] ",[996,2096,1194],{"class":1002},[996,2098,2099],{"class":1052}," float",[996,2101,2102],{"class":1006},"(value)\n",[996,2104,2106,2109,2112,2115,2117],{"class":998,"line":2105},95,[996,2107,2108],{"class":1006},"        points[point[",[996,2110,2111],{"class":1059},"\"name\"",[996,2113,2114],{"class":1006},"]] ",[996,2116,1194],{"class":1002},[996,2118,2119],{"class":1006}," joints\n",[996,2121,2123,2126,2129,2131,2133,2135,2137],{"class":998,"line":2122},96,[996,2124,2125],{"class":1006},"        names[point[",[996,2127,2128],{"class":1059},"\"id\"",[996,2130,2114],{"class":1006},[996,2132,1194],{"class":1002},[996,2134,2082],{"class":1006},[996,2136,2111],{"class":1059},[996,2138,1593],{"class":1006},[996,2140,2142],{"class":998,"line":2141},97,[996,2143,1028],{"emptyLinePlaceholder":1027},[996,2145,2147],{"class":998,"line":2146},98,[996,2148,2149],{"class":1063},"    # A group lists its points in path order. A station is a group\n",[996,2151,2153],{"class":998,"line":2152},99,[996,2154,2155],{"class":1063},"    # named after its nest; the spine is the group of kind SAFE\n",[996,2157,2159,2162,2164],{"class":998,"line":2158},100,[996,2160,2161],{"class":1006},"    stations, spine ",[996,2163,1194],{"class":1002},[996,2165,2166],{"class":1006}," {}, []\n",[996,2168,2170,2172,2174,2176,2178,2180,2182,2184],{"class":998,"line":2169},101,[996,2171,2015],{"class":1006},[996,2173,1194],{"class":1002},[996,2175,2020],{"class":1002},[996,2177,2023],{"class":1059},[996,2179,2026],{"class":1002},[996,2181,2029],{"class":1006},[996,2183,2032],{"class":1002},[996,2185,2186],{"class":1059},"\u002Fteach-groups\"\n",[996,2188,2190,2192,2195,2197,2199],{"class":998,"line":2189},102,[996,2191,2041],{"class":1002},[996,2193,2194],{"class":1006}," group ",[996,2196,1758],{"class":1002},[996,2198,1219],{"class":1002},[996,2200,2051],{"class":1006},[996,2202,2204,2207,2209,2212,2215,2218,2221,2224,2227,2230,2233],{"class":998,"line":2203},103,[996,2205,2206],{"class":1006},"        members ",[996,2208,1194],{"class":1002},[996,2210,2211],{"class":1052}," sorted",[996,2213,2214],{"class":1006},"(group[",[996,2216,2217],{"class":1059},"\"members\"",[996,2219,2220],{"class":1006},"], ",[996,2222,2223],{"class":1292},"key",[996,2225,2226],{"class":1002},"=lambda",[996,2228,2229],{"class":1006}," m: m[",[996,2231,2232],{"class":1059},"\"position\"",[996,2234,2235],{"class":1006},"])\n",[996,2237,2239,2242,2244,2247,2250,2252,2254,2257,2259],{"class":998,"line":2238},104,[996,2240,2241],{"class":1006},"        path ",[996,2243,1194],{"class":1002},[996,2245,2246],{"class":1006}," [names[m[",[996,2248,2249],{"class":1059},"\"teachPointId\"",[996,2251,2114],{"class":1006},[996,2253,1752],{"class":1002},[996,2255,2256],{"class":1006}," m ",[996,2258,1758],{"class":1002},[996,2260,2261],{"class":1006}," members]\n",[996,2263,2265,2268,2271,2274,2277,2280,2283],{"class":998,"line":2264},105,[996,2266,2267],{"class":1002},"        if",[996,2269,2270],{"class":1006}," group[",[996,2272,2273],{"class":1059},"\"kind\"",[996,2275,2276],{"class":1006},"] ",[996,2278,2279],{"class":1002},"==",[996,2281,2282],{"class":1059}," \"NEST\"",[996,2284,1494],{"class":1006},[996,2286,2288,2291,2293,2296,2299,2302,2304],{"class":998,"line":2287},106,[996,2289,2290],{"class":1006},"            stations[group[",[996,2292,2111],{"class":1059},[996,2294,2295],{"class":1006},"].removeprefix(",[996,2297,2298],{"class":1059},"\"NEST_\"",[996,2300,2301],{"class":1006},")] ",[996,2303,1194],{"class":1002},[996,2305,2306],{"class":1006}," path\n",[996,2308,2310,2313,2315,2317,2319,2321,2324],{"class":998,"line":2309},107,[996,2311,2312],{"class":1002},"        elif",[996,2314,2270],{"class":1006},[996,2316,2273],{"class":1059},[996,2318,2276],{"class":1006},[996,2320,2279],{"class":1002},[996,2322,2323],{"class":1059}," \"SAFE\"",[996,2325,1494],{"class":1006},[996,2327,2329,2332,2334],{"class":998,"line":2328},108,[996,2330,2331],{"class":1006},"            spine ",[996,2333,1194],{"class":1002},[996,2335,2306],{"class":1006},[996,2337,2339],{"class":998,"line":2338},109,[996,2340,1028],{"emptyLinePlaceholder":1027},[996,2342,2344],{"class":998,"line":2343},110,[996,2345,2346],{"class":1063},"    # On an arm with a rail, the spine runs along the rail\n",[996,2348,2350,2352,2355,2358,2361,2363,2366,2369,2372,2374,2376,2378],{"class":998,"line":2349},111,[996,2351,1329],{"class":1002},[996,2353,2354],{"class":1006}," spine ",[996,2356,2357],{"class":1002},"and",[996,2359,2360],{"class":1052}," all",[996,2362,1388],{"class":1006},[996,2364,2365],{"class":1059},"\"Rail\"",[996,2367,2368],{"class":1002}," in",[996,2370,2371],{"class":1006}," points[name] ",[996,2373,1752],{"class":1002},[996,2375,1755],{"class":1006},[996,2377,1758],{"class":1002},[996,2379,2380],{"class":1006}," spine):\n",[996,2382,2384,2387,2389,2391,2394,2396],{"class":998,"line":2383},112,[996,2385,2386],{"class":1006},"        spine.sort(",[996,2388,2223],{"class":1292},[996,2390,2226],{"class":1002},[996,2392,2393],{"class":1006}," name: points[name][",[996,2395,2365],{"class":1059},[996,2397,2235],{"class":1006},[996,2399,2401,2403],{"class":998,"line":2400},113,[996,2402,1733],{"class":1002},[996,2404,2405],{"class":1006}," Teaching(points, stations, spine)\n",[996,2407,2409],{"class":998,"line":2408},114,[996,2410,1028],{"emptyLinePlaceholder":1027},[996,2412,2414],{"class":998,"line":2413},115,[996,2415,1028],{"emptyLinePlaceholder":1027},[996,2417,2419,2421,2423,2426],{"class":998,"line":2418},116,[996,2420,1175],{"class":1002},[996,2422,1178],{"class":1002},[996,2424,2425],{"class":1181}," find_arm",[996,2427,2428],{"class":1006},"(client, name):\n",[996,2430,2432],{"class":998,"line":2431},117,[996,2433,2434],{"class":1059},"    \"\"\"The device with this name, and the connector that drives it.\"\"\"\n",[996,2436,2438,2441,2443,2445,2448,2451,2453,2456,2458,2460,2462],{"class":998,"line":2437},118,[996,2439,2440],{"class":1006},"    found ",[996,2442,1194],{"class":1002},[996,2444,1219],{"class":1002},[996,2446,2447],{"class":1006}," client.get(",[996,2449,2450],{"class":1059},"\"\u002Fdevices\"",[996,2452,1289],{"class":1006},[996,2454,2455],{"class":1292},"params",[996,2457,1194],{"class":1002},[996,2459,2026],{"class":1006},[996,2461,2111],{"class":1059},[996,2463,2464],{"class":1006},": name})\n",[996,2466,2468,2470,2472,2475,2478],{"class":998,"line":2467},119,[996,2469,1329],{"class":1002},[996,2471,1332],{"class":1002},[996,2473,2474],{"class":1006}," found[",[996,2476,2477],{"class":1059},"\"data\"",[996,2479,1341],{"class":1006},[996,2481,2483,2486,2489,2491,2494,2497,2499,2502,2505,2508],{"class":998,"line":2482},120,[996,2484,2485],{"class":1002},"        raise",[996,2487,2488],{"class":1052}," RuntimeError",[996,2490,1388],{"class":1006},[996,2492,2493],{"class":1002},"f",[996,2495,2496],{"class":1059},"\"No device named ",[996,2498,2026],{"class":1002},[996,2500,2501],{"class":1006},"name",[996,2503,2504],{"class":1002},"!r}",[996,2506,2507],{"class":1059},"\"",[996,2509,1227],{"class":1006},[996,2511,2513,2516,2518,2520,2522,2525,2527,2529,2531],{"class":998,"line":2512},121,[996,2514,2515],{"class":1006},"    device_id ",[996,2517,1194],{"class":1002},[996,2519,2474],{"class":1006},[996,2521,2477],{"class":1059},[996,2523,2524],{"class":1006},"][",[996,2526,1590],{"class":1052},[996,2528,2524],{"class":1006},[996,2530,2128],{"class":1059},[996,2532,1593],{"class":1006},[996,2534,2536,2539,2541,2543,2545,2547,2549,2551,2553,2555,2558],{"class":998,"line":2535},122,[996,2537,2538],{"class":1006},"    services ",[996,2540,1194],{"class":1002},[996,2542,1219],{"class":1002},[996,2544,2447],{"class":1006},[996,2546,2493],{"class":1002},[996,2548,2023],{"class":1059},[996,2550,2026],{"class":1002},[996,2552,2029],{"class":1006},[996,2554,2032],{"class":1002},[996,2556,2557],{"class":1059},"\u002Fservices\"",[996,2559,1227],{"class":1006},[996,2561,2563,2565,2567],{"class":998,"line":2562},123,[996,2564,1329],{"class":1002},[996,2566,1332],{"class":1002},[996,2568,2569],{"class":1006}," services:\n",[996,2571,2573,2575,2577,2579,2581,2583,2585,2587,2589,2592],{"class":998,"line":2572},124,[996,2574,2485],{"class":1002},[996,2576,2488],{"class":1052},[996,2578,1388],{"class":1006},[996,2580,2493],{"class":1002},[996,2582,2507],{"class":1059},[996,2584,2026],{"class":1002},[996,2586,2501],{"class":1006},[996,2588,2504],{"class":1002},[996,2590,2591],{"class":1059}," has no connector\"",[996,2593,1227],{"class":1006},[996,2595,2597,2599,2602,2605,2608,2610,2612,2614],{"class":998,"line":2596},125,[996,2598,1733],{"class":1002},[996,2600,2601],{"class":1006}," device_id, ",[996,2603,2604],{"class":1002},"await",[996,2606,2607],{"class":1006}," client.get_service(services[",[996,2609,1590],{"class":1052},[996,2611,2524],{"class":1006},[996,2613,2128],{"class":1059},[996,2615,2235],{"class":1006},[996,2617,2619],{"class":998,"line":2618},126,[996,2620,1028],{"emptyLinePlaceholder":1027},[996,2622,2624],{"class":998,"line":2623},127,[996,2625,1028],{"emptyLinePlaceholder":1027},[996,2627,2629,2631,2633,2636],{"class":998,"line":2628},128,[996,2630,1175],{"class":1002},[996,2632,1178],{"class":1002},[996,2634,2635],{"class":1181}," transport_actions",[996,2637,2638],{"class":1006},"(arm):\n",[996,2640,2642],{"class":998,"line":2641},129,[996,2643,2644],{"class":1059},"    \"\"\"Pick-up and put-down. On a rail arm they end in \"_with_rail\".\"\"\"\n",[996,2646,2648,2651,2653,2655],{"class":998,"line":2647},130,[996,2649,2650],{"class":1006},"    rail ",[996,2652,1194],{"class":1002},[996,2654,1219],{"class":1002},[996,2656,2657],{"class":1006}," arm.information_provider.get_rail_installed()\n",[996,2659,2661,2664,2666,2669,2672,2675,2678],{"class":998,"line":2660},131,[996,2662,2663],{"class":1006},"    suffix ",[996,2665,1194],{"class":1002},[996,2667,2668],{"class":1059}," \"_with_rail\"",[996,2670,2671],{"class":1002}," if",[996,2673,2674],{"class":1006}," rail ",[996,2676,2677],{"class":1002},"else",[996,2679,2680],{"class":1059}," \"\"\n",[996,2682,2684,2687,2689],{"class":998,"line":2683},132,[996,2685,2686],{"class":1006},"    actions ",[996,2688,1194],{"class":1002},[996,2690,2691],{"class":1006}," arm.transport_controller.actions\n",[996,2693,2695,2698,2700,2703,2706,2709],{"class":998,"line":2694},133,[996,2696,2697],{"class":1006},"    pick_up ",[996,2699,1194],{"class":1002},[996,2701,2702],{"class":1006}," actions[",[996,2704,2705],{"class":1059},"\"pick_up_joints\"",[996,2707,2708],{"class":1002}," +",[996,2710,2711],{"class":1006}," suffix]\n",[996,2713,2715,2718,2720,2722,2725,2727],{"class":998,"line":2714},134,[996,2716,2717],{"class":1006},"    put_down ",[996,2719,1194],{"class":1002},[996,2721,2702],{"class":1006},[996,2723,2724],{"class":1059},"\"put_down_joints\"",[996,2726,2708],{"class":1002},[996,2728,2711],{"class":1006},[996,2730,2732,2734],{"class":998,"line":2731},135,[996,2733,1733],{"class":1002},[996,2735,2736],{"class":1006}," pick_up, put_down\n",[996,2738,2740],{"class":998,"line":2739},136,[996,2741,1028],{"emptyLinePlaceholder":1027},[996,2743,2745],{"class":998,"line":2744},137,[996,2746,1028],{"emptyLinePlaceholder":1027},[996,2748,2750,2752,2754,2757],{"class":998,"line":2749},138,[996,2751,1175],{"class":1002},[996,2753,1178],{"class":1002},[996,2755,2756],{"class":1181}," read_state",[996,2758,2638],{"class":1006},[996,2760,2762],{"class":998,"line":2761},139,[996,2763,2764],{"class":1059},"    \"\"\"Powered, homed and idle? The first event of the stream is empty.\"\"\"\n",[996,2766,2768,2771,2773,2775],{"class":998,"line":2767},140,[996,2769,2770],{"class":1006},"    states ",[996,2772,1194],{"class":1002},[996,2774,1219],{"class":1002},[996,2776,2777],{"class":1006}," arm.information_provider.subscribe_state()\n",[996,2779,2781,2784,2787],{"class":998,"line":2780},141,[996,2782,2783],{"class":1002},"    async",[996,2785,2786],{"class":1002}," with",[996,2788,2789],{"class":1006}," states:\n",[996,2791,2793,2796,2799,2802,2804],{"class":998,"line":2792},142,[996,2794,2795],{"class":1002},"        async",[996,2797,2798],{"class":1002}," for",[996,2800,2801],{"class":1006}," state ",[996,2803,1758],{"class":1002},[996,2805,2789],{"class":1006},[996,2807,2809,2812,2815,2817],{"class":998,"line":2808},143,[996,2810,2811],{"class":1002},"            if",[996,2813,2814],{"class":1059}," \"Homed\"",[996,2816,2368],{"class":1002},[996,2818,2819],{"class":1006}," state:\n",[996,2821,2823,2826],{"class":998,"line":2822},144,[996,2824,2825],{"class":1002},"                return",[996,2827,2828],{"class":1006}," state\n",[996,2830,2832,2835,2837,2839,2842],{"class":998,"line":2831},145,[996,2833,2834],{"class":1002},"    raise",[996,2836,2488],{"class":1052},[996,2838,1388],{"class":1006},[996,2840,2841],{"class":1059},"\"The state stream closed without a state\"",[996,2843,1227],{"class":1006},[996,2845,2847],{"class":998,"line":2846},146,[996,2848,1028],{"emptyLinePlaceholder":1027},[996,2850,2852],{"class":998,"line":2851},147,[996,2853,1028],{"emptyLinePlaceholder":1027},[996,2855,2857,2859,2861,2864],{"class":998,"line":2856},148,[996,2858,1175],{"class":1002},[996,2860,1178],{"class":1002},[996,2862,2863],{"class":1181}," get_all",[996,2865,2866],{"class":1006},"(client, url):\n",[996,2868,2870],{"class":998,"line":2869},149,[996,2871,2872],{"class":1059},"    \"\"\"One page of up to 100 entries; refuse to drop any silently.\"\"\"\n",[996,2874,2876,2879,2881,2883,2886,2888,2890,2892,2895,2898,2901],{"class":998,"line":2875},150,[996,2877,2878],{"class":1006},"    page ",[996,2880,1194],{"class":1002},[996,2882,1219],{"class":1002},[996,2884,2885],{"class":1006}," client.get(url, ",[996,2887,2455],{"class":1292},[996,2889,1194],{"class":1002},[996,2891,2026],{"class":1006},[996,2893,2894],{"class":1059},"\"_take\"",[996,2896,2897],{"class":1006},": ",[996,2899,2900],{"class":1052},"100",[996,2902,2903],{"class":1006},"})\n",[996,2905,2907,2909,2912,2915,2917,2920],{"class":998,"line":2906},151,[996,2908,1329],{"class":1002},[996,2910,2911],{"class":1006}," page[",[996,2913,2914],{"class":1059},"\"pagination\"",[996,2916,2524],{"class":1006},[996,2918,2919],{"class":1059},"\"hasMore\"",[996,2921,1341],{"class":1006},[996,2923,2925,2927,2929,2931,2933,2936,2938,2941,2943,2945],{"class":998,"line":2924},152,[996,2926,2485],{"class":1002},[996,2928,2488],{"class":1052},[996,2930,1388],{"class":1006},[996,2932,2493],{"class":1002},[996,2934,2935],{"class":1059},"\"More than 100 entries at ",[996,2937,2026],{"class":1002},[996,2939,2940],{"class":1006},"url",[996,2942,2032],{"class":1002},[996,2944,2507],{"class":1059},[996,2946,1227],{"class":1006},[996,2948,2950,2952,2954,2956],{"class":998,"line":2949},153,[996,2951,1733],{"class":1002},[996,2953,2911],{"class":1006},[996,2955,2477],{"class":1059},[996,2957,1593],{"class":1006},[996,2959,2961],{"class":998,"line":2960},154,[996,2962,1028],{"emptyLinePlaceholder":1027},[996,2964,2966],{"class":998,"line":2965},155,[996,2967,1028],{"emptyLinePlaceholder":1027},[996,2969,2971],{"class":998,"line":2970},156,[996,2972,2973],{"class":1006},"asyncio.run(main())\n",[957,2975,2976,2977,2980,2981,2983],{},"Run it with ",[961,2978,2979],{},"uv run move_a_plate.py",". Set ",[961,2982,1053],{}," to the arm's name exactly as the Devices page\nshows it.",[2985,2986,287],"h2",{"id":2987},"how-it-works",[957,2989,2990,2997,2998,3000],{},[2991,2992,2993,2996],"strong",{},[961,2994,2995],{},"main()"," is the whole story."," The functions below it each do one step, so read ",[961,2999,2995],{}," first and\nlook up a helper only when you want the detail.",[957,3002,3003,3009,3010,3013,3014,3017],{},[2991,3004,3005,3008],{},[961,3006,3007],{},"load_teaching()"," turns the Teach view into three lookups."," The REST API returns every teachpoint\n(",[961,3011,3012],{},"\u002Fv1\u002Fdevices\u002F{deviceId}\u002Fteach-points",") and every group (",[961,3015,3016],{},"\u002Fteach-groups","). The loader keeps:",[3019,3020,3021,3028,3037],"ul",{},[3022,3023,3024,3027],"li",{},[961,3025,3026],{},"points",": each point's joint values, by name;",[3022,3029,3030,3033,3034,3036],{},[961,3031,3032],{},"stations",": each station's point names in path order, nest first and safe point last, keyed by the\nname the Teach view shows (",[961,3035,963],{},");",[3022,3038,3039,3042],{},[961,3040,3041],{},"spine",": the shared safe points, in the order the arm passes them. On an arm with a rail that is\nthe order along the rail.",[957,3044,3045,3051,3052,3055,3056],{},[2991,3046,3047,3050],{},[961,3048,3049],{},"plan()"," turns a station into the arguments of one pick-up or put-down."," The way out of a station\nis its path after the nest and the approach; the way in is the same list backwards. When the arm\ncomes from another station, ",[961,3053,3054],{},"spine_between()"," adds the safe points it passes on the way. The spine\nis a single line of safe points, so the order matters: on an arm with a rail it comes from the rail,\nand on an arm without one it is the order the safe points were captured. ",[2991,3057,3058],{},"Without a rail, teach the\nsafe points in the order they sit on the bench.",[957,3060,3061,3064,3065,1774,3068,3071,3072,3074,3075,3077,3078,3081],{},[2991,3062,3063],{},"Two profiles, for two kinds of leg."," The legs into the nest and back out (",[961,3066,3067],{},"target_profile",[961,3069,3070],{},"retract_profile",") must stop exactly on their point, because the jaw needs the arm still. They use\n",[961,3073,1081],{},". The legs between safe points and transitions only have to get there, so they use ",[961,3076,1095],{},"\nand carry their speed through each point instead of stopping. Stopping is a property of the\nprofile (a non-negative ",[961,3079,3080],{},"InRange","), separate from its speed.",[3019,3083,3084,3113,3126],{},[3022,3085,3086,3087,3089,3090,3093,3094,1289,3096,3099,3100,3103,3104,1289,3107,3099,3110,3112],{},"Slots ",[961,3088,1590],{}," to ",[961,3091,3092],{},"-5"," are the fixed jog profiles: ",[961,3095,1590],{},[961,3097,3098],{},"-1"," and ",[961,3101,3102],{},"-2"," run at 10, 25 and 50% of rated\nspeed and stop at each point; ",[961,3105,3106],{},"-3",[961,3108,3109],{},"-4",[961,3111,3092],{}," are the same speeds but blend. The Teach view's\njog keys use them, and nobody can overwrite them, so their speed is known.",[3022,3114,3115,3116,3089,3118,3121,3122,3125],{},"They exist from connector 0.4.0. Older connectors take only slots ",[961,3117,1606],{},[961,3119,3120],{},"20",", which you set up\nyourself. Check one with ",[961,3123,3124],{},"movement_controller.read_profile"," before you use it.",[3022,3127,3128,3129,3132],{},"Blending needs the controller's status port (",[961,3130,3131],{},"10000","). Without it, the legs run one at a time.",[957,3134,3135,3138,3139,3141,3142,3144,3145,3147],{},[2991,3136,3137],{},"The grip."," ",[961,3140,1391],{}," is the plate's size between the jaws, ",[961,3143,1429],{}," caps how hard the jaw squeezes\nin newtons, and ",[961,3146,1400],{}," is a percentage of the jaw's top speed.",[957,3149,3150,3151,3099,3154,3157,3158,3160],{},"To pin a workflow to one set of points instead of reading them live, export them from the\nTeachpoints tab and keep the file under version control. Its ",[961,3152,3153],{},"teachPoints",[961,3155,3156],{},"teachGroups"," lists\nhave the same entries as the API, so ",[961,3159,3007],{}," only needs to read them from the file.",[3162,3163,3166],"callout",{"color":3164,"icon":3165},"error","i-heroicons-shield-exclamation",[957,3167,3168],{},"The connector does not check for collisions. It drives the path you give it, and a blended leg cuts the corner at each point it passes, more so at speed. Leave clearance for the rounded path, and run a new route in simulation, or on the Validation tab, before you run it on the arm.",[2985,3170,3172],{"id":3171},"next-steps","Next steps",[3019,3174,3175,3181],{},[3022,3176,3177,3180],{},[973,3178,3179],{"href":800},"Recover from a stop",":\nwhat to do when a transfer is interrupted.",[3022,3182,3183,3185],{},[973,3184,384],{"href":385},": teachpoints, joint moves and the safe spine.",[3187,3188,3189],"style",{},"html pre.shiki code .sxkbv, html code.shiki .sxkbv{--shiki-light:#A0111F;--shiki-default:#A0111F;--shiki-dark:#FF7B72}html pre.shiki code .sc-9e, html code.shiki .sc-9e{--shiki-light:#0E1116;--shiki-default:#0E1116;--shiki-dark:#E6EDF3}html pre.shiki code .sOiAX, html code.shiki .sOiAX{--shiki-light:#023B95;--shiki-default:#023B95;--shiki-dark:#79C0FF}html pre.shiki code .sCx38, html code.shiki .sCx38{--shiki-light:#032563;--shiki-default:#032563;--shiki-dark:#A5D6FF}html pre.shiki code .sIsDC, html code.shiki .sIsDC{--shiki-light:#66707B;--shiki-default:#66707B;--shiki-dark:#8B949E}html pre.shiki code .s4qFZ, html code.shiki .s4qFZ{--shiki-light:#622CBC;--shiki-default:#622CBC;--shiki-dark:#D2A8FF}html pre.shiki code .sNqAu, html code.shiki .sNqAu{--shiki-light:#702C00;--shiki-default:#702C00;--shiki-dark:#FFA657}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":992,"searchDepth":999,"depth":1010,"links":3191},[3192,3193],{"id":2987,"depth":1010,"text":287},{"id":3171,"depth":1010,"text":3172},"One script that reads the PF400's teachpoints from the platform and moves a plate from one nest to another.","md",{},"\u002Fliquid-handling-and-robots\u002Fbrooks-preciseflex-400\u002Fmove-a-plate",{"title":795,"description":3194},"kuyB8lZFBJosgcrmhMYPPcNYKzEfu4Zd5McxHF1Ns2U",[3201,3203],{"title":791,"description":3202,"path":792},"Capture a nest, its approach and its safe point in the platform's Teach view, ready for a script to use.",{"title":799,"description":3204,"path":800},"Stop the PF400 mid-move, then bring it back to a known state before it moves again.",1791466883821]