diff --git a/metro-ai-suite/metro-vision-ai-app-recipe/compose-scenescape.yml b/metro-ai-suite/metro-vision-ai-app-recipe/compose-scenescape.yml index 6ce624cdd..4025c8a0f 100644 --- a/metro-ai-suite/metro-vision-ai-app-recipe/compose-scenescape.yml +++ b/metro-ai-suite/metro-vision-ai-app-recipe/compose-scenescape.yml @@ -164,8 +164,16 @@ services: - scenescape privileged: true entrypoint: ["./run.sh"] + group_add: + - "109" + - "110" + - "992" + device_cgroup_rules: + - 'c 189:* rmw' + - 'c 209:* rmw' + - 'a 189:* rwm' devices: - - "/dev/dri:/dev/dri" + - "/dev:/dev" depends_on: - broker - ntpserver diff --git a/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_start.sh b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_start.sh index a9bf588e2..ae8efacb5 100755 --- a/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_start.sh +++ b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_start.sh @@ -1 +1,147 @@ #!/bin/bash + +DLSPS_NODE_IP="localhost" + +function run_sample() { + device=$1 + + if [ $device == "GPU" ]; then + pipeline_suffix="_gpu" + else + pipeline_suffix="" + fi + + pipeline_list=() + echo + echo -n ">>>>>Initialization..." + + # Define camera names for RTSP paths + camera_names=("camera1" "camera2" "camera3" "camera4") + camera_ids=("camera1" "camera2" "camera3" "camera4") + + # Start all 4 intersection camera pipelines + for cam_num in 1 2 3 4; do + pipeline_name="intersection-cam${cam_num}${pipeline_suffix}" + camera_path="${camera_names[$((cam_num-1))]}" + camera_id="${camera_ids[$((cam_num-1))]}" + + payload=$(cat <>>>>Stopping all running pipelines." + status=$(curl -k -s -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" -H "accept: application/json") + if [ $? -ne 0 ]; then + echo -e "\nError: curl command failed. Check the deployment status." + return 1 + fi + pipelines=$(echo $status | grep -o '"id": "[^"]*"' | awk ' { print $2 } ' | tr -d \" | paste -sd ',' - ) + IFS=',' + for pipeline in $pipelines; do + response=$(curl -k -s --location -X DELETE "https://$DLSPS_NODE_IP/api/pipelines/${pipeline}") + sleep 2 + done + unset IFS + running=true + while [ "$running" == true ]; do + echo -n "." + status=$(curl -k -s --location -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" | grep state | awk ' { print $2 } ' | tr -d \") + if [[ "$status" == *"RUNNING"* ]]; then + running=true + sleep 2 + else + running=false + fi + done + echo -n " done." + echo + return 0 +} + + +forcedCPU=true +forcedGPU=false + +for arg in "$@"; do + if [ "$arg" == "cpu" ]; then + forcedCPU=true + forcedGPU=false + elif [ "$arg" == "gpu" ]; then + forcedGPU=true + forcedCPU=false + fi +done + + +stop_all_pipelines + +if [ $? -ne 0 ]; then + exit 1 +fi + + +# Check if any render device exists +if $forcedGPU; then + if ls /dev/dri/renderD* 1> /dev/null 2>&1; then + echo -e "\n>>>>>GPU device selected." + run_sample GPU + if [ $? -ne 0 ]; then + exit 1 + fi + else + echo -e "\n>>>>>No GPU device found. Please check your GPU driver installation or use CPU." + exit 0 + fi +elif $forcedCPU; then + echo -e "\n>>>>>CPU device selected." + run_sample CPU + if [ $? -ne 0 ]; then + exit 1 + fi +fi + +echo -e "\n>>>>>Results are visualized in UI at 'https://localhost' " +echo -e "\n>>>>>Pipelines status can be checked with 'curl -k --location -X GET https://localhost/api/pipelines/status' or using script 'sample_status.sh'. \n" diff --git a/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_status.sh b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_status.sh new file mode 100755 index 000000000..3786ed5f2 --- /dev/null +++ b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_status.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +DLSPS_NODE_IP="localhost" + +function get_status() { + + interval=10 + start_time=$(date +%s) + + status=$(curl -k -s --location -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" | grep state | awk ' { print $2 } ' | tr -d \") + if [[ "$status" != *"RUNNING"* ]]; then + running=false + echo -e "\nNo running pipelines" + exit 0 + else + running=true + echo -e "\n>>>>>Pipeline status reported every $interval seconds." + echo -e "\n>>>>>Press Ctrl+C to exit..." + + while [ "$running" == true ]; do + status=$(curl -k -s --location -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" | grep state | awk ' { print $2 } ' | tr -d \") + if [[ "$status" != *"RUNNING"* ]]; then + running=false + else + results_pipeline=() + elapsed_time=$(($(date +%s) - $start_time)) + echo -e "\n>>>>>>>>>>>>>>> $elapsed_time seconds." + results=$(curl -k -s --location -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" | grep -A 2 -B 5 RUNNING | grep fps | awk -F': ' '{print $2}' | awk -F',' '{printf" %.2f ", $1}') + results_pipeline+=("$results") + echo -e "pipelines fps: (${results_pipeline[@]})" + sleep $interval + + fi + done + fi + +} +# Function to handle exit +cleanup() { + echo -e "\n>>>>>Ctrl+C pressed, terminating the script..." + exit 0 +} + +# Set trap to catch SIGINT (Ctrl+C) and call cleanup +trap cleanup SIGINT + +get_status diff --git a/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_stop.sh b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_stop.sh new file mode 100755 index 000000000..973f1e53f --- /dev/null +++ b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/sample_stop.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +DLSPS_NODE_IP="localhost" + +function stop_all_pipelines() { + echo + echo -n ">>>>>Stopping all running pipelines." + pipelines=$(curl -k -s -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" -H "accept: application/json" | grep id | awk ' { print $2 } ' | tr -d \" | tr -d '\n') + if [ $? -ne 0 ]; then + echo -e "\nError: curl command failed." + return 1 + fi + IFS=',' + for pipeline in $pipelines; do + response=$(curl -k -s --location -X DELETE "https://$DLSPS_NODE_IP/api/pipelines/${pipeline}") + sleep 2 + done + unset IFS + running=true + while [ "$running" == true ]; do + echo -n "." + status=$(curl -k -s --location -X GET "https://$DLSPS_NODE_IP/api/pipelines/status" | grep state | awk ' { print $2 } ' | tr -d \") + if [[ "$status" == *"RUNNING"* ]]; then + running=true + sleep 2 + else + running=false + fi + done + echo -n " done." + echo + return 0 +} + + + +stop_all_pipelines + +if [ $? -ne 0 ]; then + exit 1 + echo "Error: Check pipelines manually" +else + echo ">>>>>All running pipelines stopped." +fi diff --git a/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/src/dlstreamer-pipeline-server/config.json b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/src/dlstreamer-pipeline-server/config.json index 07afad106..d0de343fc 100644 --- a/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/src/dlstreamer-pipeline-server/config.json +++ b/metro-ai-suite/metro-vision-ai-app-recipe/smart-intersection/src/dlstreamer-pipeline-server/config.json @@ -5,7 +5,7 @@ "name": "intersection-cam1", "source": "gstreamer", "queue_maxsize": 50, - "auto_start": true, + "auto_start": false, "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122north.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", "parameters": { "type": "object", @@ -75,7 +75,7 @@ "name": "intersection-cam2", "source": "gstreamer", "queue_maxsize": 50, - "auto_start": true, + "auto_start": false, "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122east.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", "parameters": { "type": "object", @@ -145,7 +145,7 @@ "name": "intersection-cam3", "source": "gstreamer", "queue_maxsize": 50, - "auto_start": true, + "auto_start": false, "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122south.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", "parameters": { "type": "object", @@ -215,7 +215,7 @@ "name": "intersection-cam4", "source": "gstreamer", "queue_maxsize": 50, - "auto_start": true, + "auto_start": false, "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122west.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", "parameters": { "type": "object", @@ -280,6 +280,286 @@ } } } + }, + { + "name": "intersection-cam1_gpu", + "source": "gstreamer", + "queue_maxsize": 50, + "auto_start": false, + "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122north.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 device=GPU inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", + "parameters": { + "type": "object", + "properties": { + "ntp_config": { + "element": { + "name": "timesync", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "ntpServer": { + "type": "string" + } + } + }, + "camera_config": { + "element": { + "name": "datapublisher", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "intrinsics": { + "type": "array", + "items": { + "type": "number", + "description": "Camera intrinsics as [diagonal_fov] or [horizontal_fov, vertical_fov] or [fx,fy,cx,cy] " + } + }, + "cameraid": { + "type": "string" + }, + "metadatagenpolicy" : { + "type": "string", + "description" : "Meta data generation policy, one of detectionPolicy(default),reidPolicy,classificationPolicy" + }, + "publish_frame": { + "type": "boolean", + "description": "Publish frame to mqtt" + } + } + } + } + }, + "payload": { + "destination":{ + "frame": { + "type": "rtsp", + "path": "camera1" + } + }, + "parameters": { + "ntp_config": { + "ntpServer": "ntpserv" + }, + "camera_config": { + "cameraid": "camera1", + "metadatagenpolicy": "detectionPolicy" + } + } + } + }, + { + "name": "intersection-cam2_gpu", + "source": "gstreamer", + "queue_maxsize": 50, + "auto_start": false, + "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122east.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 device=GPU inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", + "parameters": { + "type": "object", + "properties": { + "ntp_config": { + "element": { + "name": "timesync", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "ntpServer": { + "type": "string" + } + } + }, + "camera_config": { + "element": { + "name": "datapublisher", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "intrinsics": { + "type": "array", + "items": { + "type": "number", + "description": "Camera intrinsics as [diagonal_fov] or [horizontal_fov, vertical_fov] or [fx,fy,cx,cy] " + } + }, + "cameraid": { + "type": "string" + }, + "metadatagenpolicy" : { + "type": "string", + "description" : "Meta data generation policy, one of detectionPolicy(default),reidPolicy,classificationPolicy" + }, + "publish_frame": { + "type": "boolean", + "description": "Publish frame to mqtt" + } + } + } + } + }, + "payload": { + "destination":{ + "frame": { + "type": "rtsp", + "path": "camera2" + } + }, + "parameters": { + "ntp_config": { + "ntpServer": "ntpserv" + }, + "camera_config": { + "cameraid": "camera2", + "metadatagenpolicy": "detectionPolicy" + } + } + } + }, + { + "name": "intersection-cam3_gpu", + "source": "gstreamer", + "queue_maxsize": 50, + "auto_start": false, + "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122south.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 device=GPU inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", + "parameters": { + "type": "object", + "properties": { + "ntp_config": { + "element": { + "name": "timesync", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "ntpServer": { + "type": "string" + } + } + }, + "camera_config": { + "element": { + "name": "datapublisher", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "intrinsics": { + "type": "array", + "items": { + "type": "number", + "description": "Camera intrinsics as [diagonal_fov] or [horizontal_fov, vertical_fov] or [fx,fy,cx,cy] " + } + }, + "cameraid": { + "type": "string" + }, + "metadatagenpolicy" : { + "type": "string", + "description" : "Meta data generation policy, one of detectionPolicy(default),reidPolicy,classificationPolicy" + }, + "publish_frame": { + "type": "boolean", + "description": "Publish frame to mqtt" + } + } + } + } + }, + "payload": { + "destination":{ + "frame": { + "type": "rtsp", + "path": "camera3" + } + }, + "parameters": { + "ntp_config": { + "ntpServer": "ntpserv" + }, + "camera_config": { + "cameraid": "camera3", + "metadatagenpolicy": "detectionPolicy" + } + } + } + }, + { + "name": "intersection-cam4_gpu", + "source": "gstreamer", + "queue_maxsize": 50, + "auto_start": false, + "pipeline": "multifilesrc loop=true location=/home/pipeline-server/videos/1122west.ts name=source ! decodebin ! videorate ! videoconvert ! video/x-raw,format=BGR,framerate=15/1 ! gvapython class=PostDecodeTimestampCapture function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=timesync ! gvadetect model-instance-id=detect1 device=GPU inference-interval=1 model=/home/pipeline-server/models/object_detection/intersection/openvino.xml ! queue ! gvametaconvert add-tensor-data=true name=metaconvert ! gvapython class=PostInferenceDataPublish function=processFrame module=/home/pipeline-server/user_scripts/gvapython/sscape/sscape_adapter.py name=datapublisher ! gvametapublish name=destination ! appsink sync=true", + "parameters": { + "type": "object", + "properties": { + "ntp_config": { + "element": { + "name": "timesync", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "ntpServer": { + "type": "string" + } + } + }, + "camera_config": { + "element": { + "name": "datapublisher", + "property": "kwarg", + "format": "json" + }, + "type": "object", + "properties": { + "intrinsics": { + "type": "array", + "items": { + "type": "number", + "description": "Camera intrinsics as [diagonal_fov] or [horizontal_fov, vertical_fov] or [fx,fy,cx,cy] " + } + }, + "cameraid": { + "type": "string" + }, + "metadatagenpolicy" : { + "type": "string", + "description" : "Meta data generation policy, one of detectionPolicy(default),reidPolicy,classificationPolicy" + }, + "publish_frame": { + "type": "boolean", + "description": "Publish frame to mqtt" + } + } + } + } + }, + "payload": { + "destination":{ + "frame": { + "type": "rtsp", + "path": "camera4" + } + }, + "parameters": { + "ntp_config": { + "ntpServer": "ntpserv" + }, + "camera_config": { + "cameraid": "camera4", + "metadatagenpolicy": "detectionPolicy" + } + } + } } ] }