I have a setup with more than 10 camera's so i want to use the script node to reduce network bandwidth. I build my code based on two examples:

#!/usr/bin/env python3

import depthai as dai

import cv2

import time

# Create pipeline

pipeline = dai.Pipeline()

# Mono cameras setup

monoLeft = pipeline.create(dai.node.MonoCamera)

monoLeft.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P)

monoLeft.setBoardSocket(dai.CameraBoardSocket.LEFT)

monoLeft.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)

monoLeft.initialControl.setExternalTrigger(4, 3)

xoutLeft = pipeline.create(dai.node.XLinkOut)

xoutLeft.setStreamName("left")

monoLeft.out.link(xoutLeft.input)

monoRight = pipeline.createMonoCamera()

monoRight.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P)

monoRight.setBoardSocket(dai.CameraBoardSocket.RIGHT)

monoRight.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)

monoRight.initialControl.setExternalTrigger(4, 3)

xoutRight = pipeline.create(dai.node.XLinkOut)

xoutRight.setStreamName("right")

monoRight.out.link(xoutRight.input)

# RGB camera setup

rgbCam = pipeline.create(dai.node.ColorCamera)

rgbCam.setResolution(dai.ColorCameraProperties.SensorResolution.THE_4_K)

# rgbCam.setInterleaved(False)

rgbCam.setBoardSocket(dai.CameraBoardSocket.RGB)

# rgbCam.initialControl.setExternalTrigger(4, 3)

rgbCam.initialControl.setCaptureStill(True)

rgbCam.setFps(15)

# Trigger script setup

xin = pipeline.create(dai.node.XLinkIn)

xin.setStreamName('in')

script = pipeline.create(dai.node.Script)

xin.out.link(script.inputs['in'])

# script.inputs["in"].setBlocking(False)

# script.inputs["in"].setQueueSize(1)

script.setScript("""

import GPIO

import time

GPIO_PIN = 41 # Trigger

GPIO.setup(GPIO_PIN, GPIO.OUT, GPIO.PULL_DOWN)

ctrl = CameraControl()

ctrl.setCaptureStill(True)

def capture():

GPIO.write(GPIO_PIN, True)

time.sleep(0.001) # 1ms pulse is enough

GPIO.write(GPIO_PIN, False)

node.io['out'].send(ctrl)

# jpegImage = node.io['jpeg'].get()

# frame = node.io['rgb'].get()

# node.io['rgb_out'].send(frame)

while True:

wait_for_trigger = node.io['in'].get()

capture()

node.warn('Trigger successful')

""")

xout = pipeline.create(dai.node.XLinkOut)

xout.setStreamName('rgb')

script.outputs['out'].link(rgbCam.inputControl)

rgbCam.still.link(xout.input)

device_info = dai.DeviceInfo("169.254.1.101")

with dai.Device(pipeline, device_info, maxUsbSpeed=dai.UsbSpeed.SUPER_PLUS) as device:

inQ = device.getInputQueue("in")

arr = ['left', 'right', 'rgb'] #, 'rgb_out']

# arr = ['rgb']

queues = {}

frames = {}

for name in arr:

queues[name] = device.getOutputQueue(name)

def trigger():

buffer = dai.Buffer()

buffer.setData([1])

inQ.send(buffer)

time.sleep(1)

trigger() # Initial trigger

t_trigger = time.monotonic()

while True:

for name in arr:

if queues[name].has():

temp = queues[name].get()

t_stamp = temp.getTimestamp().total_seconds()

diff = t_stamp - t_trigger

print(f"{name} time [s]: {t_stamp:0.3f}, diff {diff:0.3f}")

frames[name] = temp.getCvFrame()

for name, frame in frames.items():

cv2.imshow(name, frame)

key = cv2.waitKey(0)

if key == ord('q'):

break

elif key == ord('c'):

t_trigger = time.monotonic()

trigger()

# time.sleep(0.1)


ir: example of @jakaskerl

https://discuss.luxonis.com/d/2447-taking-still-images-in-the-dark-using-ir-flood-and-monocamera/7

rgb: <https://docs.luxonis.com/software/depthai/examples/script_camera_control/ >

I slightly changed the visualisation Instead of a cv2.waitKey(1), I replaced it with cv2.waitKey(0). Because after a trigger I only should get 1 frame. However, apparently, with cv2.waitKey set to 0. I always get an old frame. Further debugging showed that actually with one trigger it can get multiple frames see screenshot below (tested with cv2.waitKey(1) to go through the loop multiple times).

    bartvm
    Try setting the external trigger to only capture one frame.

    setExternalTrigger(self: depthai.CameraControl, numFramesBurst: int, numFramesDiscard: int) -> depthai.CameraControl
    
    Set a command to enable external trigger snapshot mode
    
    A rising edge on the sensor FSIN pin will make it capture a sequence of numFramesBurst frames. First numFramesDiscard will be skipped as configured (can be set to 0 as well), as they may have degraded quality

    Thanks,
    Jaka

    Dear @jakaskerl thank you for the fast response.

    I changed it to (1,0). To force only 1 frame per trigger. There are two interesting observations:

    1. Frame is still old (time between frame timestamp and trigger is negative). Despite having a queue size of 1 and trigger only once.

    2. Inconsistent brightness; see second frame:

    What should I do?, I did tested a "ugly" while loop to only return the frames if timestamp difference >0. However, this is quite slow as it take ±.6seconds to get a frame with positive diff.

      bartvm
      Then do (4, 4) or (3, 3).

      Thanks,
      Jaka

      Thanks for the suggestion but still with (4,4) or (3,3) or (1,1) still old frames <-0.1 (even with delay of 0.25) after my trigger:

        Hi bartvm
        Well the time between trigger and image will always be what it is since the trigger is done using SW.
        The message is sent via xlink, then script reads the message, turns on the trigger, image capture is done, milliseconds pass, image is sent, ... There's your time diff.

        Thanks,
        Jaka

        6 days later

        Dear @jakaskerl unfortunately it is not milliseconds. I have a while loop that returns the image after the diff is positive and this loop takes 0.4 seconds. I know that SW triggering is not perfect and some delay can be expected but 0.4 is much more than I expected, certainly not milliseconds. Preferably I would have used the HW trigger, I tried that but there is I think still an unsolved bug: https://discuss.luxonis.com/d/5323-hardware-trigger-synchronization-including-rgb-image-oakd-s2/20