Skip to content

Commit b6b20c9

Browse files
Merge pull request #795 from luxonis/develop
Release v2.21.0.0
2 parents 23aa63f + 1f162f1 commit b6b20c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+407
-120
lines changed

depthai-core

Submodule depthai-core updated 59 files

docs/source/components/nodes/imu.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ Limitations
5050
- For BNO086, gyroscope frequency above 400Hz can produce some jitter from time to time due to sensor HW limitation.
5151
- **Maximum frequencies**: 500 Hz raw accelerometer, 1000 Hz raw gyroscope values individually, and 500Hz combined (synced) output. You can obtain the combined synced 500Hz output with :code:`imu.enableIMUSensor([dai.IMUSensor.ACCELEROMETER_RAW, dai.IMUSensor.GYROSCOPE_RAW], 500)`.
5252

53+
IMU sensor frequencies
54+
######################
55+
56+
Below are the discrete **stable frequencies** available for each (raw) IMU sensor. Some maximum IMU frequencies are higher, eg.
57+
for BNO086, maximum frequency for gyroscope is 1000Hz, but up to 400Hz is stable (due to driver limitation).
58+
59+
**BNO086:**
60+
61+
- Accelerometer: 100Hz, 200Hz, 400Hz
62+
- Gyroscope: 125Hz, 250Hz, 400Hz
63+
- Magnetometer: 100Hz
64+
65+
**BMI270:**
66+
67+
- Accelerometer: 25Hz, 50Hz, 100Hz, 200Hz, 400Hz
68+
- Gyroscope: 25Hz, 50Hz, 100Hz, 200Hz, 400Hz
69+
5370
Usage
5471
#####
5572

examples/CrashReport/crash_report.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python3
2+
3+
import cv2
4+
import depthai as dai
5+
from json import dump
6+
from os.path import exists
7+
8+
# Connect to device and start pipeline
9+
with dai.Device() as device:
10+
11+
if device.hasCrashDump():
12+
crashDump = device.getCrashDump()
13+
commitHash = crashDump.depthaiCommitHash
14+
deviceId = crashDump.deviceId
15+
16+
json = crashDump.serializeToJson()
17+
18+
i = -1
19+
while True:
20+
i += 1
21+
destPath = "crashDump_" + str(i) + "_" + deviceId + "_" + commitHash + ".json"
22+
if exists(destPath):
23+
continue
24+
25+
with open(destPath, 'w', encoding='utf-8') as f:
26+
dump(json, f, ensure_ascii=False, indent=4)
27+
28+
print("Crash dump found on your device!")
29+
print(f"Saved to {destPath}")
30+
print("Please report to developers!")
31+
break
32+
else:
33+
print("There was no crash dump found on your device!")
34+

examples/IMU/imu_firmware_update.py

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,35 @@
55
import time
66
import math
77

8+
device = dai.Device()
9+
10+
imuVersion = device.getConnectedIMU()
11+
imuFirmwareVersion = device.getIMUFirmwareVersion()
12+
embeddedIMUFirmwareVersion = device.getEmbeddedIMUFirmwareVersion()
13+
print(f"IMU type: {imuVersion}, firmware version: {imuFirmwareVersion}, embedded firmware version: {embeddedIMUFirmwareVersion}")
14+
815
print("Warning! Flashing IMU firmware can potentially soft brick your device and should be done with caution.")
916
print("Do not unplug your device while the IMU firmware is flashing.")
1017
print("Type 'y' and press enter to proceed, otherwise exits: ")
1118
if input() != 'y':
1219
print("Prompt declined, exiting...")
1320
exit(-1)
1421

15-
# Create pipeline
16-
pipeline = dai.Pipeline()
17-
18-
# Define sources and outputs
19-
imu = pipeline.create(dai.node.IMU)
20-
xlinkOut = pipeline.create(dai.node.XLinkOut)
21-
22-
xlinkOut.setStreamName("imu")
23-
24-
# enable ACCELEROMETER_RAW at 500 hz rate
25-
imu.enableIMUSensor(dai.IMUSensor.ACCELEROMETER_RAW, 500)
26-
# enable GYROSCOPE_RAW at 400 hz rate
27-
imu.enableIMUSensor(dai.IMUSensor.GYROSCOPE_RAW, 400)
28-
# it's recommended to set both setBatchReportThreshold and setMaxBatchReports to 20 when integrating in a pipeline with a lot of input/output connections
29-
# above this threshold packets will be sent in batch of X, if the host is not blocked and USB bandwidth is available
30-
imu.setBatchReportThreshold(1)
31-
# maximum number of IMU packets in a batch, if it's reached device will block sending until host can receive it
32-
# if lower or equal to batchReportThreshold then the sending is always blocking on device
33-
# useful to reduce device's CPU load and number of lost packets, if CPU load is high on device side due to multiple nodes
34-
imu.setMaxBatchReports(10)
35-
36-
# Link plugins IMU -> XLINK
37-
imu.out.link(xlinkOut.input)
38-
39-
imu.enableFirmwareUpdate(True)
40-
4122
# Pipeline is defined, now we can connect to the device
42-
with dai.Device(pipeline) as device:
23+
with device:
4324

44-
def timeDeltaToMilliS(delta) -> float:
45-
return delta.total_seconds()*1000
25+
started = device.startIMUFirmwareUpdate()
26+
if not started:
27+
print("Couldn't start IMU firmware update")
28+
exit(1)
4629

47-
# Output queue for imu bulk packets
48-
imuQueue = device.getOutputQueue(name="imu", maxSize=50, blocking=False)
49-
baseTs = None
5030
while True:
51-
imuData = imuQueue.get() # blocking call, will wait until a new data has arrived
52-
53-
imuPackets = imuData.packets
54-
for imuPacket in imuPackets:
55-
acceleroValues = imuPacket.acceleroMeter
56-
gyroValues = imuPacket.gyroscope
57-
58-
acceleroTs = acceleroValues.getTimestampDevice()
59-
gyroTs = gyroValues.getTimestampDevice()
60-
if baseTs is None:
61-
baseTs = acceleroTs if acceleroTs < gyroTs else gyroTs
62-
acceleroTs = timeDeltaToMilliS(acceleroTs - baseTs)
63-
gyroTs = timeDeltaToMilliS(gyroTs - baseTs)
64-
65-
imuF = "{:.06f}"
66-
tsF = "{:.03f}"
67-
68-
print(f"Accelerometer timestamp: {tsF.format(acceleroTs)} ms")
69-
print(f"Accelerometer [m/s^2]: x: {imuF.format(acceleroValues.x)} y: {imuF.format(acceleroValues.y)} z: {imuF.format(acceleroValues.z)}")
70-
print(f"Gyroscope timestamp: {tsF.format(gyroTs)} ms")
71-
print(f"Gyroscope [rad/s]: x: {imuF.format(gyroValues.x)} y: {imuF.format(gyroValues.y)} z: {imuF.format(gyroValues.z)} ")
72-
73-
if cv2.waitKey(1) == ord('q'):
31+
fwUpdateFinished, percentage = device.getIMUFirmwareUpdateStatus()
32+
print(f"IMU FW update status: {percentage:.1f}%")
33+
if fwUpdateFinished:
34+
if percentage == 100:
35+
print("Firmware update successful!")
36+
else:
37+
print("Firmware update failed!")
7438
break
39+
time.sleep(1)

examples/IMU/imu_rotation_vector.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55
import time
66
import math
77

8+
device = dai.Device()
9+
10+
imuType = device.getConnectedIMU()
11+
imuFirmwareVersion = device.getIMUFirmwareVersion()
12+
print(f"IMU type: {imuType}, firmware version: {imuFirmwareVersion}")
13+
14+
if imuType != "BNO086":
15+
print("Rotation vector output is supported only by BNO086!")
16+
exit(1)
17+
818
# Create pipeline
919
pipeline = dai.Pipeline()
1020

@@ -28,7 +38,8 @@
2838
imu.out.link(xlinkOut.input)
2939

3040
# Pipeline is defined, now we can connect to the device
31-
with dai.Device(pipeline) as device:
41+
with device:
42+
device.startPipeline(pipeline)
3243

3344
def timeDeltaToMilliS(delta) -> float:
3445
return delta.total_seconds()*1000

examples/IMU/imu_version.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env python3
2+
3+
import depthai as dai
4+
5+
device = dai.Device()
6+
7+
imuType = device.getConnectedIMU()
8+
imuFirmwareVersion = device.getIMUFirmwareVersion()
9+
print(f"IMU type: {imuType}, firmware version: {imuFirmwareVersion}")

examples/ImageManip/image_manip_warp_mesh.py

100644100755
File mode changed.

examples/MonoCamera/mono_preview_alternate_pro.py

100644100755
File mode changed.

examples/NeuralNetwork/concat_multi_input.py

100644100755
File mode changed.

examples/NeuralNetwork/detection_parser.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@
4242
nn.setNumInferenceThreads(2)
4343
nn.input.setBlocking(False)
4444

45-
blob = dai.OpenVINO.Blob(args.nnPath);
46-
nn.setBlob(blob);
47-
det.setBlob(blob);
48-
det.setNNFamily(dai.DetectionNetworkType.MOBILENET);
49-
det.setConfidenceThreshold(0.5);
45+
blob = dai.OpenVINO.Blob(args.nnPath)
46+
nn.setBlob(blob)
47+
det.setBlob(blob)
48+
det.setNNFamily(dai.DetectionNetworkType.MOBILENET)
49+
det.setConfidenceThreshold(0.5)
5050

5151
# Linking
5252
if args.sync:

examples/Script/script_change_pipeline_flow.py

100644100755
File mode changed.

examples/Script/script_forward_frames.py

100644100755
File mode changed.

examples/SpatialDetection/spatial_location_calculator.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
config = dai.SpatialLocationCalculatorConfigData()
4545
config.depthThresholds.lowerThreshold = 100
4646
config.depthThresholds.upperThreshold = 10000
47+
calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MEDIAN
4748
config.roi = dai.Rect(topLeft, bottomRight)
4849

4950
spatialLocationCalculator.inputConfig.setWaitForMessage(False)
@@ -123,10 +124,30 @@
123124
topLeft.x += stepSize
124125
bottomRight.x += stepSize
125126
newConfig = True
127+
elif key == ord('1'):
128+
calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MEAN
129+
print('Switching calculation algorithm to MEAN!')
130+
newConfig = True
131+
elif key == ord('2'):
132+
calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MIN
133+
print('Switching calculation algorithm to MIN!')
134+
newConfig = True
135+
elif key == ord('3'):
136+
calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MAX
137+
print('Switching calculation algorithm to MAX!')
138+
newConfig = True
139+
elif key == ord('4'):
140+
calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MODE
141+
print('Switching calculation algorithm to MODE!')
142+
newConfig = True
143+
elif key == ord('5'):
144+
calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MEDIAN
145+
print('Switching calculation algorithm to MEDIAN!')
146+
newConfig = True
126147

127148
if newConfig:
128149
config.roi = dai.Rect(topLeft, bottomRight)
129-
config.calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.AVERAGE
150+
config.calculationAlgorithm = calculationAlgorithm
130151
cfg = dai.SpatialLocationCalculatorConfig()
131152
cfg.addROI(config)
132153
spatialCalcConfigInQueue.send(cfg)

examples/StereoDepth/depth_preview_lr.py

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,99 @@
1111
# Better handling for occlusions:
1212
lr_check = True
1313

14+
enableRectified = False
15+
1416
# Create pipeline
1517
pipeline = dai.Pipeline()
1618

1719
# Define sources and outputs
1820
left = pipeline.create(dai.node.ColorCamera)
21+
center = pipeline.create(dai.node.ColorCamera)
1922
right = pipeline.create(dai.node.ColorCamera)
20-
depth = pipeline.create(dai.node.StereoDepth)
21-
xout = pipeline.create(dai.node.XLinkOut)
22-
xoutl = pipeline.create(dai.node.XLinkOut)
23-
xoutr = pipeline.create(dai.node.XLinkOut)
23+
LC_depth = pipeline.create(dai.node.StereoDepth)
24+
LR_depth = pipeline.create(dai.node.StereoDepth)
25+
CR_depth = pipeline.create(dai.node.StereoDepth)
26+
27+
xout_LC = pipeline.create(dai.node.XLinkOut)
28+
xout_LR = pipeline.create(dai.node.XLinkOut)
29+
xout_CR = pipeline.create(dai.node.XLinkOut)
30+
31+
xout_LC.setStreamName("disparity_LC")
32+
if enableRectified:
33+
xoutl_LC = pipeline.create(dai.node.XLinkOut)
34+
xoutr_LC = pipeline.create(dai.node.XLinkOut)
35+
xoutl_LC.setStreamName("rectifiedLeft_LC")
36+
xoutr_LC.setStreamName("rectifiedRight_LC")
2437

25-
xout.setStreamName("disparity")
26-
xoutl.setStreamName("rectifiedLeft")
27-
xoutr.setStreamName("rectifiedRight")
38+
xout_LR.setStreamName("disparity_LR")
39+
if enableRectified:
40+
xoutl_LR = pipeline.create(dai.node.XLinkOut)
41+
xoutr_LR = pipeline.create(dai.node.XLinkOut)
42+
xoutl_LR.setStreamName("rectifiedLeft_LR")
43+
xoutr_LR.setStreamName("rectifiedRight_LR")
44+
45+
xout_CR.setStreamName("disparity_CR")
46+
if enableRectified:
47+
xoutl_CR = pipeline.create(dai.node.XLinkOut)
48+
xoutr_CR = pipeline.create(dai.node.XLinkOut)
49+
xoutl_CR.setStreamName("rectifiedLeft_CR")
50+
xoutr_CR.setStreamName("rectifiedRight_CR")
2851

2952
# Properties
3053
left.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1200_P)
3154
left.setBoardSocket(dai.CameraBoardSocket.LEFT)
55+
left.setIspScale(2, 3)
56+
57+
center.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1200_P)
58+
center.setBoardSocket(dai.CameraBoardSocket.CENTER)
59+
center.setIspScale(2, 3)
60+
3261
right.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1200_P)
3362
right.setBoardSocket(dai.CameraBoardSocket.RIGHT)
3463
right.setIspScale(2, 3)
35-
left.setIspScale(2, 3)
3664

65+
LC_depth.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
66+
LC_depth.initialConfig.setMedianFilter(dai.MedianFilter.MEDIAN_OFF)
67+
LC_depth.setLeftRightCheck(lr_check)
68+
LC_depth.setExtendedDisparity(extended_disparity)
69+
LC_depth.setSubpixel(subpixel)
3770

38-
# Create a node that will produce the depth map (using disparity output as it's easier to visualize depth this way)
39-
depth.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
40-
# Options: MEDIAN_OFF, KERNEL_3x3, KERNEL_5x5, KERNEL_7x7 (default)
41-
depth.initialConfig.setMedianFilter(dai.MedianFilter.KERNEL_7x7)
42-
depth.setInputResolution(1280, 800)
43-
depth.setLeftRightCheck(lr_check)
44-
depth.setExtendedDisparity(extended_disparity)
45-
depth.setSubpixel(subpixel)
46-
depth.setInputResolution(1280, 800)
71+
LR_depth.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
72+
LR_depth.initialConfig.setMedianFilter(dai.MedianFilter.MEDIAN_OFF)
73+
LR_depth.setLeftRightCheck(lr_check)
74+
LR_depth.setExtendedDisparity(extended_disparity)
75+
LR_depth.setSubpixel(subpixel)
76+
77+
CR_depth.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
78+
CR_depth.initialConfig.setMedianFilter(dai.MedianFilter.MEDIAN_OFF)
79+
CR_depth.setLeftRightCheck(lr_check)
80+
CR_depth.setExtendedDisparity(extended_disparity)
81+
CR_depth.setSubpixel(subpixel)
4782

4883
# Linking
49-
left.isp.link(depth.left)
50-
right.isp.link(depth.right)
51-
depth.disparity.link(xout.input)
52-
depth.rectifiedLeft.link(xoutl.input)
53-
depth.rectifiedRight.link(xoutr.input)
84+
# LC
85+
left.isp.link(LC_depth.left)
86+
center.isp.link(LC_depth.right)
87+
LC_depth.disparity.link(xout_LC.input)
88+
if enableRectified:
89+
LC_depth.rectifiedLeft.link(xoutl_LC.input)
90+
LC_depth.rectifiedRight.link(xoutr_LC.input)
91+
# LR
92+
left.isp.link(LR_depth.left)
93+
right.isp.link(LR_depth.right)
94+
LR_depth.disparity.link(xout_LR.input)
95+
if enableRectified:
96+
LR_depth.rectifiedLeft.link(xoutl_LR.input)
97+
LR_depth.rectifiedRight.link(xoutr_LR.input)
98+
# CR
99+
center.isp.link(CR_depth.left)
100+
right.isp.link(CR_depth.right)
101+
CR_depth.disparity.link(xout_CR.input)
102+
if enableRectified:
103+
CR_depth.rectifiedLeft.link(xoutl_CR.input)
104+
CR_depth.rectifiedRight.link(xoutr_CR.input)
105+
106+
maxDisp = LC_depth.initialConfig.getMaxDisparity()
54107

55108
# Connect to device and start pipeline
56109
with dai.Device(pipeline) as device:
@@ -62,7 +115,6 @@
62115
if type(message) == dai.ImgFrame:
63116
frame = message.getCvFrame()
64117
if 'disparity' in q:
65-
maxDisp = depth.initialConfig.getMaxDisparity()
66118
disp = (frame * (255.0 / maxDisp)).astype(np.uint8)
67119
disp = cv2.applyColorMap(disp, cv2.COLORMAP_JET)
68120
cv2.imshow(q, disp)

0 commit comments

Comments
 (0)