Watson Text To Speech icon Watson Text To Speech — Human-like audio via IBM Watson Text-to-Speech: multi-language, selectable voices for accessibility and automated interactions. IBM Cloud required. Try it →
Asked
1 Participant
Debouncing Darknet YOLO on TurtleBot3

Debouncing Darknet YOLO On Turtlebot3

Running ARC on a TurtleBot3 Burger with an Intel NUC (Windows) on the base, USB to OpenCR for motor control, and a Logitech C920 as the camera. I’ve added Camera Device at 640x480 and the Darknet YOLO (Obj Detection) skill. With Running enabled, the On Changes script fires many times per second even when a person is standing still. I think tiny score fluctuations are triggering changes, which spams my Audio.say and any movement logic. CPU also jumps when I leave YOLO in continuous mode.

I tried switching to on-demand detection with a JavaScript loop and that helps CPU, but I still get chatty events due to score changes. My current approach is to threshold and require N consecutive frames before acting:

// On Changes script
var n = getVar('$YOLONumberOfRegions');
var classes = getVar('$YOLOClasses');
var scores = getVar('$YOLOScores');

var target = 'person';
var thresh = 0.6;
var count = getVar('$personCount') || 0;

var seen = false;
for (var i = 0; i < n; i++) {
  if (classes[i] === target && scores[i] >= thresh) { seen = true; break; }
}

count = seen ? count + 1 : 0;
setVar('$personCount', count);

if (count === 3 && !getVar('$personAnnounced')) {
  setVar('$personAnnounced', true);
  Audio.say('Person detected');
}
if (!seen) setVar('$personAnnounced', false);

And my on-demand loop:

while (true) {
  controlCommand('Darknet YOLO', 'Run');
  sleep(500); // 2 Hz
}

Is this the right pattern for TurtleBot3, or is there a better way to throttle/filter Darknet YOLO (Obj Detection) so On Changes doesn’t fire on minor score wiggles-e.g., recommended confidence thresholds, built-in options, or a more robust debounce strategy?



Related Hardware (view all EZB hardware)
Turtlebot 3 by Robotis
Program TurtleBot 3 with Synthiam ARCx or ARC: ROS 2 bridge, browser control, Blockly, Python, lidar, RealSense and robot skills
Wi-Fi / USB
Servos 200
Camera
Audio
UART Varies
I2C
ADC Varies
Digital Varies

Related Robot Skills (view all robot skills)
Script by Synthiam
Multi-language ARC Script: build, run and debug Blockly, JavaScript, EZ-Script or Python with Intellisense, run/save/load and Roboscratch support
Tiny YOLOv3 CPU-only real-time object detection using a camera; offline detection, script-triggered on-changes or on-demand results with class/scores.

ARC Pro

Upgrade to ARC Pro

Subscribe to ARC Pro, and your robot will become a canvas for your imagination, limited only by your creativity.

Author Avatar
PRO
Canada
Twitter YouTube GitHub
#1  

Yes - your debounce/state-machine approach is the right direction for ARC and TurtleBot3. Darknet YOLO will often emit small score/box fluctuations even when the scene looks "unchanged," so if you react to every On Changes event directly, you’ll get chatter.

What I’d recommend

1) Treat YOLO as a sensor stream, not an event

Instead of "fire action immediately," use:

  • confidence threshold
  • consecutive-frame confirmation
  • cooldown / hysteresis
  • state change only

That means:

  • only declare "person present" after a person is seen N times in a row
  • only clear the state after the person is missing for M times in a row
  • optionally enforce a cooldown so Audio.say can’t repeat too quickly

2) Your current script has one logic issue

This line:

if (count === 3 && !getVar('$personAnnounced')) {

will only fire on the exact frame where count becomes 3. That’s fine, but if your detections bounce around, you may want >= 3 instead. Also, your !getVar(...) check is risky if the variable has never been initialized.

A more robust pattern is to track a stable state and separate seen vs not seen counters.


3) Better debounce pattern for On Changes

Try this JavaScript in the YOLO On Changes script:

var n = getVar('$YOLONumberOfRegions');
var classes = getVar('$YOLOClasses');
var scores = getVar('$YOLOScores');

var target = 'person';
var thresh = 0.6;

var seen = false;

for (var i = 0; i < n; i++) {
  if (classes[i] == target && scores[i] >= thresh) {
    seen = true;
    break;
  }
}

var seenCount = getVar('$personSeenCount', 0);
var missingCount = getVar('$personMissingCount', 0);
var personPresent = getVar('$personPresent', false);

if (seen) {
  seenCount++;
  missingCount = 0;
} else {
  missingCount++;
  seenCount = 0;
}

setVar('$personSeenCount', seenCount);
setVar('$personMissingCount', missingCount);

// Require 3 consecutive positive frames to enter the state
if (!personPresent && seenCount >= 3) {
  setVar('$personPresent', true);
  Audio.say('Person detected');
}

// Require 5 consecutive negative frames to leave the state
if (personPresent && missingCount >= 5) {
  setVar('$personPresent', false);
  Audio.say('Person lost');
}

Why this works better

  • avoids repeated speech on minor score wiggles
  • tolerates one or two missed frames
  • changes state only when the detection is stable

4) Add a cooldown for speech

Even with state logic, I’d still add a cooldown so Audio.say() can’t spam if the scene flips rapidly.

var now = new Date().getTime();
var lastSpeak = getVar('$lastPersonSpeak', 0);

if (now - lastSpeak > 3000) {
  Audio.say('Person detected');
  setVar('$lastPersonSpeak', now);
}

You can combine that with the stable-state code above.


5) About the on-demand loop

This part is fine in principle:

while (true) {
  controlCommand('Darknet YOLO', 'Run');
  sleep(500);
}

But I’d suggest:

  • don’t run it faster than needed
  • start around 500-1000 ms
  • stop the loop when your mode changes
  • consider using a script state variable like $mode

Also, if you only need person detection occasionally, running YOLO at 1-2 Hz is usually much gentler on CPU than continuous running.


6) Even better: use a single "person stable" branch

A clean pattern in ARC is:

  • YOLO On Changes updates detection variables
  • another script reads those variables every 200-500 ms and makes decisions

That separates:

  • vision ingestion
  • robot behavior

This often makes debugging much easier.


7) About built-in YOLO options

Darknet YOLO in ARC does support running from the camera and reacting on changes, but the main practical filtering is usually done in script rather than relying on a special built-in "debounce" feature.

So the best tools are:

  • confidence threshold
  • consecutive-frame count
  • cooldown timer
  • state variable ($personPresent)
  • optional missing-frame grace period

8) TurtleBot3-specific note

Because you’re on a TurtleBot3 Burger with a C920 and an Intel NUC, CPU load is expected to jump when YOLO is continuous. Your move to on-demand is the right direction.

For TurtleBot3 projects, I’d usually recommend:

  • keep YOLO off unless needed
  • trigger it at a controlled rate
  • use the OpenCR for motion only
  • avoid tying movement directly to every detection event

9) Suggested ARC project structure

A solid setup would be:

  • Camera Device
  • Darknet YOLO
  • Script skill for debouncing/behavior
  • Movement Panel for TurtleBot3 control
  • optional Sound skill if you want separate audio control

If you want, I can help you turn this into a cleaner state machine script for:

  • idle
  • searching
  • person_detected
  • approach
  • lost_target

That’s often a much better fit than reacting to every YOLO callback.


10) ARC AI Script Assistant tip

If you’re editing this inside ARC, the AI Script Assistant can rewrite the script directly in the editor and adapt it to your exact skill names and variables: https://synthiam.com/Products/AI-Assistant


If you want, I can also give you a complete TurtleBot3-ready YOLO debounce script in JavaScript that includes:

  • hysteresis
  • cooldown
  • stable detection
  • stop/move behavior based on person presence
I am a customer support AI and still learning. Please verify important answers in our support documentation. For advanced AI features, use the AI Script Agent built into ARC.