Skip to content

fix(checks): hoist camera threshold validations to fail early on came… - #459

Merged
kstonekuan merged 1 commit into
Hebbian-Robotics:mainfrom
Chama2001:fix-issue-447
Sep 15, 2026
Merged

kstonekuan merged 1 commit into
Hebbian-Robotics:mainfrom
Chama2001:fix-issue-447

Conversation

@Chama2001

Copy link
Copy Markdown
Contributor

Closes #447

Summary

Moved threshold guards before the camera loop in camera_frame_stats and camera_signal_quality.

Why

As discussed in #447, previously these guards were inside the for topic in selected_cameras: loop, meaning they were skipped entirely on camera-less episodes. This change hoists them to the top of the functions so they fail early and correctly.

Validation

Applied the exact pattern requested in the issue description.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

👋 Hi @Chama2001 — thank you so much for your first contribution to HFlow!

A maintainer will review your pull request as soon as possible. In the meantime:

💡 Tip: one open pull request per contributor at a time. Issues with an assignee are taken; everything else is fair game.

We are excited to have you here and appreciate your help making the project better! 🙌

@kstonekuan kstonekuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Four things.

Nothing tests any of it. None of the five messages appears anywhere in the repo, so removing any line you added leaves the suite green. #447 asks for every case in its table, at least one on a camera-less episode.

Three of the five parameters still accept True. freeze_min_duration_s, freeze_noise_db and bright_luma_threshold pass as 1.

type(x) is bool and TypeError: everywhere else here is isinstance and ValueError. See _field_guards.require_int and #441/#446.

import math inside two function bodies: use the np.isfinite already imported.

Also: #447 asked you to rule on camera_fps_conformance either way. Say which.

@kstonekuan kstonekuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting close. camera_signal_quality is done; camera_frame_stats still has no tests.

Pushed the three mechanical items rather than sending you back: the missing bool clauses, TypeError to ValueError, isinstance, and np.isfinite. All eight parameters now refuse True.

Also rewrote your test. It used an episode with cameras and a bare pytest.raises(ValueError), which a camera-processing failure also satisfies, so it passed whether or not the guard was there. That is the bug #447 is about, inside its own test.

What is left: the same treatment for camera_frame_stats, ten rows.

On camera_fps_conformance: leave it out, I will file it.

Hebbian-Robotics#447. Both functions validated their thresholds inside the loop over
selected_cameras, so on a camera-less episode nothing ran and a bad value
was accepted silently. The guards move above the loop and compose from
_field_guards, which also takes checks.py's share of Hebbian-Robotics#498.

bright_luma_threshold is a float, so it composes rather than mapping onto
require_int_in_range: the helper owns finiteness and the bound stays local.

Tests run on a camera-less episode with anchored patterns. On an episode
with cameras a camera-processing failure also raises ValueError, so an
unanchored assertion passes whether or not the guard is there.

@kstonekuan kstonekuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking this over after five days, so the #447 gap closes and your slot frees.

Your diagnosis was right and it is what the fix does: the guards were inside the loop over selected_cameras, so a camera-less episode ran none of them.

Force-pushed onto current main, because the branch no longer rebased: _field_guards and _resolve_selected_cameras both landed underneath it. The guards now compose from the helpers rather than hand-rolling, which also takes checks.py's share of #498.

bright_luma_threshold is a float, so it does not map onto require_int_in_range; the helper owns finiteness and the bound stays local.

Tests are camera-less with anchored patterns, which matters here: on an episode with cameras a camera-processing failure also raises ValueError, so an unanchored assertion passes whether or not the guard exists.

Mutations: removing either function's guards fails 8 and 6 cases; moving one below the loop fails 2.

@kstonekuan
kstonekuan merged commit 9bcb7d4 into Hebbian-Robotics:main Sep 15, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

camera_frame_stats and camera_signal_quality skip their threshold guards on a camera-less episode, and name internal fields when they do fire

2 participants