api_version: cmvr.edge.ai/v1 runtime: # PyAV plus the PPE and phone-use YOLO branches share this bounded pool. thread_workers: 4 shutdown_timeout_s: 8 endpoints: cmvr_es: transport: grpc # cmvr-es gRPC address. Change this value for each deployed robot. target: 192.168.0.119:50052 tls: false timeout_s: 5 options: max_receive_mb: 32 ppe_alert_platform: transport: http # Detection-alert platform HTTP base URL. The alert payload model_id and # rule_id distinguish PPE violations from phone-use violations. base_url: http://192.168.0.222:13080 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. This repository-relative # path requires launching cmvr-edge-ai from the repository root. weights: models/detection/construction-ppe-yolov8/v1/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 # phone_detector: # uses: detection.model@1 # with: # model: people-talking-yolov8x@1 # # The checkpoint also contains a generic class named "label". It is # # retained in model registration for class-ID safety but is not an # # actionable phone-use event, so this branch selects only class 1. # detect_labels: # - talking on phone # confidence: 0.50 # # YOLOv8x is substantially heavier than the PPE model. Start with a # # conservative CPU rate and tune only after measuring target hardware. # max_fps: 5 # inference_log_interval_s: 5 # attach_frame: true # model_options: # weights: models/detection/people-talking-yolov8x/v1/best.pt # device: cpu # imgsz: 640 # iou: 0.70 # half: false # max_det: 100 # phone_repeat_gate: # uses: detection.repeat_gate@1 # with: # time_source: received # alert_image: # enabled: true # jpeg_quality: 85 # rules: # - id: talking-on-phone # labels: [talking on phone] # min_hits: 3 # window_ms: 2000 # cooldown_ms: 30000 # min_confidence: 0.50 # scope: source alert_platform: uses: platform.http_json_sink@1 with: endpoint: ppe_alert_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 # Fan out the already decoded image; do not open a second camera stream # or decode the same H264/H265 packet twice. - from: decoder.frames to: phone_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: phone_detector.detections # to: phone_repeat_gate.detections # qos: # profile: telemetry # # attach_frame carries the decoded image until the rule is evaluated. # capacity: 2 # overflow: drop_oldest - from: repeat_gate.alerts to: alert_platform.input qos: profile: telemetry capacity: 64 overflow: block # - from: phone_repeat_gate.alerts # to: alert_platform.input # qos: # profile: telemetry # capacity: 64 # overflow: block talk: enabled: true nodes: audio_stream_placeholder: # Replace with cmvr.grpc.microphone_audio_stream@1 when its proto lands. uses: core.sequence_source@1 with: items: - simulated-audio-chunk schema_name: AudioChunk schema_version: 1 dialogue_placeholder: # The real chain will be VAD -> ASR -> dialogue -> TTS. uses: core.passthrough@1 output: uses: core.log_sink@1 with: logger: cmvr_edge_ai.talk edges: - from: audio_stream_placeholder.output to: dialogue_placeholder.input qos: profile: audio_contiguous capacity: 16 overflow: block - from: dialogue_placeholder.output to: output.input qos: profile: request capacity: 8 overflow: block