ON THIS PAGE

  • Script
  • How to place it
  • Inputs and Outputs
  • Usage
  • Interfacing with GPIOs
  • Time synchronization
  • Using DepthAI
  • Available modules and libraries
  • Examples of functionality
  • Reference

Script

Script node allows users to run custom Python scripts on the device. Due to the computational resource constraints, script node shouldn't be used for heavy computing (eg. image manipulation/CV), but for managing the flow of the pipeline (business logic). Example use cases would be controlling nodes like ImageManip, ColorCamera, SpatialLocationCalculator, decoding NeuralNetwork results, or interfacing with GPIOs.

How to place it

Python
C++

Python

Python
1pipeline = dai.Pipeline()
2script = pipeline.create(dai.node.Script)

Inputs and Outputs

Users can define as many inputs and outputs as they need. Inputs and outputs can be any components_messages type.

Usage

Python
C++

Python

Python
1script = pipeline.create(dai.node.Script)
2script.setScript("""
3    import time
4    import marshal
5    num = 123
6    node.warn(f"Number {num}") # Print to host
7    x = [1, "Hello", {"Foo": "Bar"}]
8    x_serial = marshal.dumps(x)
9    b = Buffer(len(x_serial))
10    while True:
11        time.sleep(1)
12        b.setData(x_serial)
13        node.io['out'].send(b)
14""")
15script.outputs['out'].link(xout.input)
16
17# ...
18# After initializing the device, enable log levels
19device.setLogLevel(dai.LogLevel.WARN)
20device.setLogOutputLevel(dai.LogLevel.WARN)

Interfacing with GPIOs

In the script node you can interface with GPIOs of the VPU using module GPIO. Currently supported functions are:
Python
1# Module
2import GPIO
3
4# General
5GPIO.setup(gpio, dir, pud, exclusive)
6GPIO.release(gpio)
7GPIO.write(gpio, value)
8GPIO.read(gpio)
9
10# Interrupts
11GPIO.waitInterruptEvent(gpio = -1) # blocks until any interrupt or interrupt by specified gpio is fired. Interrupts with callbacks are ignored here
12GPIO.hasInterruptEvent(gpio = -1) # returns whether interrupt happened on any or specified gpio. Interrupts with callbacks are ignored here
13GPIO.setInterrupt(gpio, edge, priority, callback = None) # adds interrupt to specified pin
14GPIO.clearInterrupt(gpio) # clears interrupt of specified pin
15
16# PWM
17GPIO.setPwm(gpio, highCount, lowCount, repeat=0) # repeat == 0 means indefinite
18GPIO.enablePwm(gpio, enable)
19
20# Enumerations
21GPIO.Direction: GPIO.IN, GPIO.OUT
22GPIO.State: GPIO.LOW, GPIO.HIGH
23GPIO.PullDownUp: GPIO.PULL_NONE, GPIO.PULL_DOWN, GPIO.PULL_UP
24GPIO.Edge: GPIO.RISING, GPIO.FALLING, GPIO.LEVEL_HIGH, GPIO.LEVEL_LOW
Here's an example of toggling GPIO pin 40 inside Script node from the host. On OAK-SoM-Pro, GPIO 40 drives FSYNC signal for both 4-lane cameras, and we have used the code below for this exact reason.
Python
1import GPIO
2MX_PIN = 40
3
4ret = GPIO.setup(MX_PIN, GPIO.OUT, GPIO.PULL_DOWN)
5toggleVal = True
6
7while True:
8  data = node.io['in'].get()  # Wait for a message from the host computer
9
10  node.warn('GPIO toggle: ' + str(toggleVal))
11  toggleVal = not toggleVal
12  ret = GPIO.write(MX_PIN, toggleVal)  # Toggle the GPIO

Time synchronization

Script node has access to both device (internal) clock and also synchronized host clock. Host clock is synchronized with device clock at below 2.5ms precision at 1σ, Host clock syncing.
Python
1import time
2interval = 60
3ctrl = CameraControl()
4ctrl.setCaptureStill(True)
5previous = 0
6while True:
7    time.sleep(0.001)
8
9    tnow_full = Clock.nowHost() # Synced clock with host
10    # Clock.now() -> internal/device clock
11    # Clock.offsetToHost() -> Offset between internal/device clock and host clock
12
13    now = tnow_full.seconds
14    if now % interval == 0 and now != previous:
15        previous = now
16        node.warn(f'{tnow_full}')
17        node.io['out'].send(ctrl)

Using DepthAI Messages

The depthai module is implicitly imported to the script node. You can create new depthai messages and assign data to it, for example:
Python
1buf = Buffer(100) # Assign 100 bytes to the Buffer message
2
3# Create CameraControl message, set manual focus
4control = CameraControl()
5control.setManualFocus(100)
6
7imgFrame = ImgFrame(300*300*3) # Buffer with 300x300x3 bytes

Available modules and libraries

Available modules
Text
1"posix", "errno", "pwd", "_sre", "_codecs", "_weakref", "_functools", "_operator",
2"_collections", "_abc", "itertools", "atexit", "_stat", "time", "_datetime", "math",
3"_thread", "_io", "_symtable", "marshal", "_ast", "gc", "_warnings", "_string", "_struct"
Available Modules for LEON_CSS:
Text
1"binascii", "_random", "_socket", "_md5", "_sha1", "_sha256", "_sha512", "select",
2"array", "unicodedata"
Libraries
Text
1"__main__", "_collections_abc", "_frozen_importlib", "_frozen_importlib_external",
2"_sitebuiltins", "abc", "codecs", "datetime", "encodings", "encodings.aliases",
3"encodings.ascii", "encodings.latin_1", "encodings.mbcs", "encodings.utf_8", "genericpath",
4"io", "os", "posixpath", "site", "stat", "threading", "types", "struct", "copyreg",
5"reprlib", "operator", "keyword", "heapq", "collections", "functools", "sre_constants",
6"sre_parse", "sre_compile", "enum", "re", "json", "json.decoder", "json.encoder",
7"json.scanner", "textwrap"
Libraries for LEON_CSS:
Text
1"http", "http.client", "http.server", "html", "mimetypes", "copy", "shutil", "fnmatch",
2"socketserver", "contextlib", "email", "email._encoded_words", "email._header_value_parser",
3"email._parseaddr", "email._policybase", "email.base64mime", "email.charset",
4"email.contentmanager",  "email.encoders", "email.errors", "email.feedparser",
5"email.generator", "email.header", "email.headerregistry", "email.iterators", "email.message",
6"email.parser", "email.policy", "email.quoprimime", "email.utils", "string", "base64",
7"quopri", "random", "warnings", "bisect", "hashlib", "logging", "traceback", "linecache",
8"socket", "token", "tokenize", "weakref", "_weakrefset", "collections.abc", "selectors",
9"urllib", "urllib.parse", "calendar", "locale", "uu", "encodings.idna", "stringprep"
The difference between module and library is that module is a precompiled C source with Python bindings, whereas library is Python source code packed into a library and precompiled into Python bytecode (before loaded into our Firmware).Networking/protocol modules/libraries that are available on the LEON_CSS can only be used on OAK POE device. You can specify on which processor the script will run, eg. for LEON_CSS:
Python
1script = pipeline.create(dai.node.Script)
2script.setProcessor(dai.ProcessorType.LEON_CSS)

Examples of functionality

Reference

class

dai::node::Script

variable
InputMap inputs
Inputs to Script node. Can be accessed using subscript operator (Eg: inputs['in1']) By default inputs are set to blocking with queue size 8
variable
OutputMap outputs
Outputs from Script node. Can be accessed subscript operator (Eg: outputs['out1'])
function
void setScriptPath(const dai::Path & path, const std::string & name)
Specify local filesystem path to load the script
Parameters
  • path: Filesystem path to load the script
  • name: Optionally set a name of this script, otherwise the name defaults to the path
function
void setScript(const std::string & script, const std::string & name)
Sets script data to be interpreted
Parameters
  • script: Script string to be interpreted
  • name: Optionally set a name of this script
function
void setScript(const std::vector< std::uint8_t > & data, const std::string & name)
Sets script data to be interpreted
Parameters
  • data: Binary data that represents the script to be interpreted
  • name: Optionally set a name of this script
function
dai::Path getScriptPath()
function
std::string getScriptName()
function
void setProcessor(ProcessorType type)
Set on which processor the script should run
Parameters
  • type: Processor type - Leon CSS or Leon MSS
function
ProcessorType getProcessor()
Get on which processor the script should run
Returns
Processor type - Leon CSS or Leon MSS
function
void buildInternal()
inline function
DeviceNodeCRTP()
inline function
DeviceNodeCRTP(const std::shared_ptr< Device > & device)
inline function
DeviceNodeCRTP(std::unique_ptr< Properties > props)
inline function
DeviceNodeCRTP(std::unique_ptr< Properties > props, bool confMode)
inline function
DeviceNodeCRTP(const std::shared_ptr< Device > & device, std::unique_ptr< Properties > props, bool confMode)

Need assistance?

Head over to Discussion Forum for technical support or any other questions you might have.