api_version: cmvr.edge.ai/v1 runtime: thread_workers: 3 shutdown_timeout_s: 8 endpoints: cmvr_es: transport: grpc # cmvr-es gRPC address. Change this value for each deployed robot. target: 192.168.0.102:50052 tls: false timeout_s: 5 options: max_receive_mb: 32 platform: transport: http # Violation-alert platform HTTP base URL. base_url: http://127.0.0.1:8081 timeout_s: 3 pipelines: detection: enabled: true nodes: camera: uses: cmvr.grpc.camera_rgb_stream@1 with: endpoint: cmvr_es device_id: wrist_cam pixel_format: BGR8 reconnect: true reconnect_initial_s: 0.5 reconnect_max_s: 10 # Log stream state immediately on first frame and emit a periodic # progress/stall heartbeat without printing every encoded frame. stream_log_interval_s: 5 decoder: uses: media.video_decoder.pyav@1 detector: uses: detection.model@1 with: model: construction-ppe-yolov8@1 # Omitting detect_labels means all registered labels. This example # asks the backend to return only PPE violations used by the rules. detect_labels: - No-Boots - No-Ear-Protection - No-Glass - No-Glove - No-Helmet - No-Mask - No-Vest confidence: 0.50 max_fps: 10 # Log the first completed inference immediately, then aggregate one # heartbeat every 5 seconds so model activity is visible without # printing every frame. Set to 1 for one-second debugging, or omit to disable. inference_log_interval_s: 5 # Keep the decoded threshold frame available to repeat_gate so an # annotated alert image can be rendered only when a rule triggers. attach_frame: true model_options: # Model artifact and inference device are deployment configuration, # not process environment requirements. weights: /home/xtkuang/Projects/cmvr/changan_robot/construction-ppe-yolov8/best.pt device: cpu imgsz: 640 iou: 0.70 half: false max_det: 100 repeat_gate: uses: detection.repeat_gate@1 with: # cmvr-es currently omits capture timestamps on successful stream # frames, so received time is the deterministic deployment default. time_source: received alert_image: enabled: true jpeg_quality: 85 rules: - id: no-boots labels: [No-Boots] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source - id: no-ear-protection labels: [No-Ear-Protection] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source - id: no-glass labels: [No-Glass] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source - id: no-glove labels: [No-Glove] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source - id: no-helmet labels: [No-Helmet] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source - id: no-mask labels: [No-Mask] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source - id: no-vest labels: [No-Vest] min_hits: 3 window_ms: 2000 cooldown_ms: 30000 min_confidence: 0.50 scope: source platform: uses: platform.http_json_sink@1 with: endpoint: platform path: /v1/detection-alerts # Platform outages must not stop camera capture or inference. After # bounded retries, log a WARNING and drop only this report. failure_mode: log_and_drop max_attempts: 3 retry_initial_s: 0.25 retry_max_s: 2 edges: # Encoded H264/H265 packets must remain contiguous before decode. - from: camera.frames to: decoder.frames qos: profile: video_contiguous capacity: 8 overflow: block # Once frames are decoded, keeping only the newest frame bounds latency. - from: decoder.frames to: detector.frames qos: profile: realtime_latest capacity: 1 overflow: drop_oldest - from: detector.detections to: repeat_gate.detections qos: profile: telemetry # DetectionResult carries a decoded frame when attach_frame is enabled; # keep this queue short so raw image buffers cannot accumulate. Under # sustained overload drop_oldest also means dropped results do not count. capacity: 2 overflow: drop_oldest - from: repeat_gate.alerts to: platform.input qos: profile: telemetry capacity: 64 overflow: block