-
Notifications
You must be signed in to change notification settings - Fork 30
CI: testing frame order and fps #331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b8a7a7d
b7c7239
933728e
cd30c11
8b79c77
d9e3acd
c8dcd4b
f8af750
c6c1177
193b8cb
0c78331
5d81889
84c4c6f
c5c5215
5421f88
f993ef1
30bb9c3
0d66c52
7dc7fd3
f3101ae
8461377
d483738
6f2d76c
f434346
f9ee1cf
94edb77
552da1a
b98d04f
40ae5c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException | ||
|
|
||
| pipeline { | ||
| agent { label 'rs-orin-01.realsenseai.com' } | ||
|
|
||
| options { | ||
| timestamps() | ||
| timeout(time: 30, unit: 'MINUTES') | ||
| } | ||
|
|
||
| parameters { | ||
| booleanParam( | ||
| name: 'REBOOT', | ||
| description: 'When set the artifacts will be installed to target agent and the agent rebooted', | ||
| defaultValue: false, | ||
| ) | ||
| string( | ||
| name: 'ARTIFACTS', | ||
| description: 'Jenkins job for artifacts to be installed on target agent', | ||
| defaultValue: "D4xx_Kernel_Module_Jetson_JP6" | ||
| ) | ||
| string( | ||
| name: 'BUILD', | ||
| description: 'Build number for artifacts. Leave empty for last successful' | ||
| ) | ||
| } | ||
|
|
||
| stages { | ||
| stage('Get artifacts') { | ||
| when { | ||
| expression { params.REBOOT == true } | ||
| } | ||
| steps { | ||
| script { | ||
| def buildSelector | ||
| if (params.BUILD?.trim()) { | ||
| buildSelector = specific(params.BUILD) | ||
| } else { | ||
| buildSelector = lastSuccessful() | ||
| } | ||
|
|
||
| copyArtifacts filter: '**/*.tar.bz2', | ||
| projectName: params.ARTIFACTS, | ||
| flatten: true, | ||
| selector: buildSelector, | ||
| target: 'artifacts/' | ||
| } | ||
| } | ||
| } | ||
| stage('Install artifacts') { | ||
| when { | ||
| expression { params.REBOOT == true } | ||
| } | ||
| steps { | ||
| sh """#!/bin/sh | ||
| rm -rf lib/modules | ||
| tar -xf artifacts/rootfs.tar.bz2 | ||
| # external script on agent to install artifacts | ||
| sudo install.tegra.artifacts.sh | ||
| """ | ||
| } | ||
| post { | ||
| success { | ||
| sh 'nohup sudo reboot &' | ||
| } | ||
| } | ||
| } | ||
| stage('Pytest') { | ||
| steps { | ||
| sh """#!/bin/sh | ||
| pytest --tb=no -s test | ||
| """ | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #!/bin/bash | ||
| set -e | ||
|
|
||
| # add jenkins user to sudo group | ||
| # add the following line to /etc/sudoers for jenkins user, here nvidia | ||
| # nvidia ALL=(root) NOPASSWD: /sbin/reboot, /sbin/install.tegra.artifacts.sh | ||
|
|
||
| RELEASE=$(ls lib/modules) | ||
| cp -R lib/modules/* /lib/modules | ||
| [[ -f /boot/Image ]] && rm /boot/Image | ||
| [[ -f /boot/initrd.img ]] && rm /boot/initrd.img | ||
| cp boot/Image /boot/Image-$RELEASE | ||
| ln -s /boot/Image-$RELEASE /boot/Image | ||
| update-initramfs -uk $RELEASE | ||
| ln -s /boot/initrd.img-$RELEASE /boot/initrd.img | ||
| cp boot/*.dtbo /boot/ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [pytest] | ||
| markers = | ||
| d457: realsense D457 camera | ||
|
|
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -46,7 +46,7 @@ def run_test(cmd): | |||||
| timeout=200, | ||||||
| check=True ) | ||||||
| except Exception as e: | ||||||
| print( "Exception occurred.") | ||||||
| print("Exception occurred: {}".format( e )) | ||||||
|
||||||
| print("Exception occurred: {}".format( e )) | |
| print("Exception occurred: {}".format(e)) |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent spacing in sys.exit() call - there are extra spaces before and after the parentheses. Should be sys.exit(1) to match Python conventions and the existing sys.exit(0) pattern in the usage() function
| sys.exit ( 1 ) | |
| sys.exit(1) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import subprocess | ||
| import pytest | ||
| import re | ||
|
|
||
| @pytest.mark.d457 | ||
| @pytest.mark.parametrize("frames", {150}) | ||
| @pytest.mark.parametrize("device", {'0', '2'}) | ||
| def test_fps(device, frames): | ||
| try: | ||
| print(f"\nDevice: {device}") | ||
| formats = get_formats(device) | ||
| for w, h in formats: | ||
| print(f"Format: {w}x{h}") | ||
| for FPS in formats[(w, h)]: | ||
| cmd = [ "v4l2-ctl", | ||
| f"-d{device}", | ||
| f"--set-fmt-video=width={w},height={h}", | ||
| ] | ||
| subprocess.check_call(cmd) | ||
| print(f"FPS/{FPS}:", end=' ') | ||
| cmd = [ "v4l2-ctl", | ||
| f"-d{device}", | ||
| "-p", | ||
| f"{FPS}", | ||
| ] | ||
| subprocess.check_call(cmd, stdout=subprocess.DEVNULL) | ||
| cmd = [ "v4l2-ctl", | ||
| f"-d{device}", | ||
| "--stream-mmap", | ||
| "--stream-count", | ||
| f"{frames}", | ||
| "--verbose", | ||
| ] | ||
| timeout = 4.0 * frames / FPS | ||
| output = subprocess.run(cmd, | ||
| check=True, | ||
| text=True, | ||
| capture_output=True, | ||
| timeout=timeout).stderr.splitlines() | ||
| last = None | ||
| skip = True # skip first FPS measurement | ||
| kpi = 5 # [%] | ||
| count = 0 | ||
| for line in output: | ||
| m = re.search(r"cap dqbuf:.*seq:\s*(\d*) bytesused:", line) | ||
| if m: | ||
| count += 1 | ||
| frame = int(m.group(1)) | ||
| # print(f"{frame}", end='') | ||
| if last: | ||
| assert frame > last, f"Repeated frame: {frame}" | ||
| assert (frame - last) < 3, f"Frames dropped between: {last} and {frame}" | ||
| m = re.search(r"delta:\s*(\d+\.\d+) ms", line) | ||
| if m: | ||
| fps = 1000 / float(m.group(1)) | ||
| # print(f"/{fps:.2f}", end='') | ||
| if not skip: | ||
| assert fps > FPS * (1 - kpi/100), f"FPS too low: {fps:.2f}/{FPS}" | ||
| assert fps < FPS * (1 + kpi/100), f"FPS too high: {fps:.2f}/{FPS}" | ||
| else: | ||
| # print('?', end='') | ||
| skip = False | ||
| # print(end=',') | ||
| last = frame | ||
| print() | ||
| assert last, "No frames arrived" | ||
| assert count == frames, f"Missing frames: {count} < {frames}" | ||
| except subprocess.TimeoutExpired: | ||
| assert False, "No frames arrived" | ||
|
|
||
| def get_formats(device): | ||
| cmd = [ "v4l2-ctl", | ||
| "-d" + device, | ||
| "--list-formats-ext", | ||
| ] | ||
| output = subprocess.run(cmd, | ||
| check=True, | ||
| text=True, | ||
| capture_output=True | ||
| ).stdout.splitlines() | ||
| formats = {} | ||
| last = None | ||
| for line in output: | ||
| m = re.search(r"\s*Size: Discrete\s*(\d+)x(\d+)", line) | ||
| if m: | ||
| w = int(m.group(1)) | ||
| h = int(m.group(2)) | ||
| last = (w, h) | ||
| if not last in formats: | ||
| formats[last] = set() | ||
| continue | ||
| m = re.search(r"\s*Interval: Discrete.*\((\d+\.\d+)\s+fps\)", line) | ||
| if m: | ||
| fps = float(m.group(1)) | ||
| if last: | ||
| formats[last].add(fps) | ||
| return formats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest renaming the file as libci is not related