Skip to content

[issue/1002] Fix and enhance singleton sensor tagging with cache persistence#1029

Merged
saratpoluri merged 49 commits intomainfrom
fix/singleton-sensor-tagging
Apr 3, 2026
Merged

[issue/1002] Fix and enhance singleton sensor tagging with cache persistence#1029
saratpoluri merged 49 commits intomainfrom
fix/singleton-sensor-tagging

Conversation

@rawatts10
Copy link
Copy Markdown
Contributor

@rawatts10 rawatts10 commented Feb 18, 2026

📝 Description

This PR restores and enhances singleton sensor tagging for tracked objects, addressing multiple issues that broke the feature. Enables two types of sensors:

Environmental Sensors: Scene-wide sensors (temperature, noise, air quality) that track timestamped readings. Objects maintain a history of sensor values with timestamps while in the sensor region.

Attribute Sensors: Event-based sensors (card readers, barcode, weight, license plate) that tag objects with timestamped attribute values when MQTT messages arrive.

Key Features

  • Sensor data automatically attached to tracked objects in entry/exit events
  • Timestamped value tracking for environmental sensors (e.g., [["2026-02-18T22:06:47.652Z", 20.5]])
  • Cross-detection-type support (sensor can tag person, vehicle, etc.)
  • Sensor cache resilient across geometry changes and scene reloads
  • Sensor data only published on events, regulated, and external topics for performance
  • Value-change detection: updates timestamp instead of appending when value unchanged

Major Fixes

  • Fixed scene-wide sensors: Tag all objects in scene when "scene" is selected as measurement area
  • Fixed circular regions: Resolved geometry issue preventing circular sensor regions from tagging objects
  • Fixed singleton_type connection: Restored database-to-runtime linkage for sensor type classification
  • Fixed cross-detection-type tagging: Sensors now correctly tag all object types (person, vehicle, etc.)
  • Fixed region cleanup: Properly clean up sensor state when objects exit regions

Additional Bug Fixes

  • Fixed crash in _buildEnteredObjsList when sensor objects not in detections_dict
  • Fixed empty entered/exited arrays in region events by properly clearing stale events after publishing
  • Fixed sensor cache being lost during geometry changes (circle ↔ polygon)
  • Removed redundant sensor "value" events (data now only in object events)
  • Fixed type consistency in environmental/attribute sensor value comparisons
  • Fixed analytics-only mode crash (added tracker null check)
  • Improved circle region validation with clearer error messages
  • Protected dictionaries used across threads to prevent race conditions

Architecture Simplification

  • Removed exposure calculation: Simplified sensor model to only track timestamped readings
  • Environmental sensors now store readings as simple [(timestamp, value), ...] arrays
  • Removed unused scene.when attribute and related tracking code
  • Sensor output contains only values array without complexity of exposure tracking

Known Limitations

  • Unbounded cache growth: Sensor readings are stored in unbounded lists (env_sensor_state[sensor_id]['readings'] and attr_sensor_events[sensor_id]). For long-running objects that remain in sensor regions with frequent updates, these lists can grow indefinitely. For example, an object in a sensor for 24 hours with readings every second would accumulate 86,400 entries. The timestamp update optimization helps when values don't change, but frequent value changes can still cause memory exhaustion. Future work should implement bounded cache with FIFO eviction, time-based cleanup, or periodic consolidation. TODO comments added in code.

Fixes #1002

✨ Type of Change

  • 🚀 New feature – Non-breaking change which adds functionality
  • 🐞 Bug fix – Non-breaking change which fixes an issue

🧪 Testing Scenarios

  • ✅ Tested manually
    • Created environmental sensor (temp) and attribute sensor (badge) with various region types (polygon, circle, scene-wide)
    • Published MQTT sensor readings, verified objects entering region receive cached values
    • Verified timestamped readings accumulate correctly in sensor data arrays
    • Tested geometry changes (polygon → circle → scene → polygon) - sensor cache preserved
    • Verified entered/exited arrays populate correctly in region events with sensor values
    • Tested cross-detection-type tagging (sensor tags person, chair, table, couch, etc.)
    • Verified scene-wide sensors tag all tracked objects regardless of location
    • Confirmed sensor data only appears on events/regulated/external topics for performance
    • Tested type consistency fixes for environmental and attribute sensors
    • Verified value-change detection prevents duplicate entries with same value

✅ Checklist

  • 🔍 PR title is clear and descriptive
  • 💬 I have commented my code, especially in hard-to-understand areas
  • 📄 I have made corresponding changes to the documentation (the feature now works as documented)
  • ✅ I have added tests that prove my fix is effective or my feature works (⚠️ Manual testing only - automated tests recommended for future work)

- Environmental sensors: ambient readings with exposure tracking
- Attribute sensors: persistent object-specific events
- Fixed singleton_type database-to-runtime connection
- Fixed scene-wide and circle region geometry
- Fixed region cleanup outside debounce
- Value-change optimization for memory efficiency
This commit addresses multiple issues discovered during testing of the
singleton sensor implementation on Feb 17, 2026:

Event Publishing Fixes:
- Fix KeyError crash in _buildEnteredObjsList when sensor objects not in
  detections_dict (occurs during sensor MQTT value events)
- Fix empty entered/exited arrays by clearing stale events after publishing
  while preserving sensor 'value' events
- Remove redundant sensor "value" event publishing (sensor data already
  included in object entry/exit events via sensors field)

Exposure Calculation Fixes:
- Set scene.when timestamp in all message handlers (handleSensorMessage,
  handleMovingObjectMessage, handleSceneDataMessage) to enable exposure
  calculation in detections_builder
- Use epoch time directly instead of string conversion when initializing
  sensor state to avoid precision loss in exposure calculations
- Exposure now correctly calculates as: value × (exit_time - entry_time)

Sensor Cache Resilience:
- Preserve sensor cache (value, lastValue, lastWhen) during region geometry
  updates in scene._updateRegions()
- Preserve sensor cache across scene invalidation/recreation in
  cache_manager by storing old cache during invalidate() and restoring
  sensor values when scene is deserialized
- Preserve region state (entered, exited, objects, when) during updates

Testing verified:
- Objects entering/exiting sensor regions receive correct sensor data
- Exposure accumulation is precise (matches manual calculation)
- Sensor cache persists through all geometry changes (circle ↔ polygon)
- No crashes during sensor MQTT message handling
- Event data includes correct entered/exited object lists

Files modified:
- controller/src/controller/scene.py
- controller/src/controller/scene_controller.py
- controller/src/controller/cache_manager.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR restores and enhances singleton sensor tagging for tracked objects in the SceneScape controller. It addresses issue #1002 where sensors were not properly tagging objects with data. The implementation adds support for two sensor types: environmental sensors (scene-wide ambient conditions like temperature, with cumulative exposure tracking via trapezoid integration) and attribute sensors (event-based data like card readers, with persistent event history).

Changes:

  • Restored database-to-runtime linkage for singleton_type field enabling sensor type classification
  • Implemented cross-detection-type tagging so sensors work with all object types (person, vehicle, etc.)
  • Added sensor cache persistence across geometry changes and scene reloads
  • Fixed circular region geometry handling and scene-wide sensor support

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
scene_common/src/scene_common/geometry.py Fixes circle region handling by checking explicit area type before inferring from hasPointsArray
manager/src/django/models.py Passes singleton_type from database to runtime Region objects
controller/src/controller/scene_controller.py Adds include_sensors parameter to control sensor data publishing on different topics (full-rate vs regulated/external)
controller/src/controller/scene.py Core sensor processing logic with exposure calculation, cross-detection-type support, and sensor state initialization
controller/src/controller/moving_object.py Refactors ChainData to use separate dicts for environmental and attribute sensors instead of flat sensors dict
controller/src/controller/detections_builder.py Builds structured sensor output with values and exposure for environmental sensors, values only for attribute sensors
controller/src/controller/cache_manager.py Preserves sensor cache values (value, lastValue, lastWhen) across scene refreshes

Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/detections_builder.py Outdated
Comment thread scene_common/src/scene_common/geometry.py Outdated
Comment thread controller/src/controller/scene.py
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene_controller.py Outdated
Comment thread controller/src/controller/scene_controller.py
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene.py
Comment thread controller/src/controller/cache_manager.py Outdated
Convert cur_value to float once at the beginning to ensure consistent
type comparison when checking if sensor values have changed. This prevents
false positives/negatives in value comparison that could occur when mixing
string and numeric types in the readings array.
Address code quality and robustness concerns identified in PR review:

- Type consistency: Convert sensor values to appropriate types (float for
  environmental, string for attribute) once and use consistently throughout
- Negative exposure prevention: Add dt > 0 checks in all exposure calculations
  to guard against out-of-order messages or clock skew
- Analytics-only mode: Add tracker null check to prevent crashes when tracker
  is not initialized
- Circle region validation: Improve error messages to distinguish missing vs
  invalid center values
- Docstring accuracy: Update _clearSensorValuesOnExit to reflect actual behavior
- Cache restoration: Use sentinel value to properly handle None as valid cached
  value vs attribute not existing
- Performance optimization: Skip redundant isPointWithin checks for scene-wide
  sensors, remove unused objects_by_type tracking
- Scene.when initialization: Add explicit None initialization in __init__
- Observability: Add debug logging for sensor cache restoration
- TODO comments: Document unbounded cache growth and performance optimization
  opportunities for future work
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 18 comments.

Comment thread controller/src/controller/detections_builder.py Outdated
Comment thread controller/src/controller/scene.py Outdated
Comment thread manager/src/django/models.py
Comment thread controller/src/controller/moving_object.py
Comment thread scene_common/src/scene_common/geometry.py Outdated
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/cache_manager.py Outdated
Comment thread controller/src/controller/moving_object.py
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene.py
saratpoluri and others added 2 commits February 18, 2026 10:44
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@saratpoluri saratpoluri force-pushed the fix/singleton-sensor-tagging branch from a9e45bb to d012fd1 Compare February 18, 2026 18:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene_controller.py
Comment thread controller/src/controller/detections_builder.py Outdated
rawatts10 and others added 3 commits February 18, 2026 14:08
- Remove all exposure tracking and calculation code
- Environmental sensors now only store timestamped readings
- Simplify sensor state structure (remove exposure fields)
- Remove unused scene.when attribute
- Update comments to reflect simplified sensor data model
- Sensor output now contains only 'values' array without 'exposure' field
- Creates tc_singleton_sensor_tagging.py with 5 test scenarios:
  1. Environmental sensor entry with cached reading
  2. Environmental sensor exit with reading removal
  3. Environmental sensor re-entry with cache
  4. Attribute sensor entry/exit with persistence
  5. Attribute sensor re-entry without cache (event-based only)
- Adds make target 'singleton-sensor-tagging' to Makefile.functional
- Test validates simplified sensor model (timestamped readings only)
- Auto-cleanup of existing sensors before test and after completion
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/detections_builder.py Outdated
Comment thread controller/src/controller/scene_controller.py
Comment thread controller/src/controller/scene_controller.py Outdated
Comment thread controller/src/controller/scene_controller.py
dependabot Bot and others added 6 commits April 2, 2026 13:52
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: scenescapecicd <sys_scenescape_ci@intel.com>
Co-authored-by: Dmytro Yermolenko <dmytro.yermolenko@intel.com>
@saratpoluri saratpoluri force-pushed the fix/singleton-sensor-tagging branch from 9227ba4 to e746441 Compare April 2, 2026 20:52
@saratpoluri saratpoluri force-pushed the fix/singleton-sensor-tagging branch 2 times, most recently from eea8bda to 4419915 Compare April 2, 2026 23:19
@saratpoluri saratpoluri force-pushed the fix/singleton-sensor-tagging branch from 4419915 to 623725a Compare April 2, 2026 23:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.

Comment thread controller/src/controller/scene_controller.py
Comment thread controller/src/controller/scene.py
Comment thread controller/src/controller/scene.py Outdated
Comment thread controller/src/controller/detections_builder.py
Comment thread controller/src/controller/scene.py Outdated
Comment thread tests/sscape_tests/scenescape/test_scene_controller.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.

Comment on lines +96 to +104
# Copy sensor data while holding lock, then release
with chain_data._lock:
env_state_copy = dict(chain_data.env_sensor_state)
attr_events_copy = dict(chain_data.attr_sensor_events)

# Environmental sensors: timestamped readings
for sensor_id, state in env_state_copy.items():
values = state['readings'] if 'readings' in state and state['readings'] else []

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

prepareObjDict() releases chain_data._lock after a shallow dict(...) copy of env_sensor_state / attr_sensor_events, but the copied dict values still reference the same underlying readings / events lists. Another thread can mutate those lists while serialization is iterating them (via orjson), leading to inconsistent output or hard-to-reproduce runtime errors. Copy the nested lists (and/or state dicts) while holding the lock (e.g., clone state['readings'] and events), or keep the lock held until the sensor payload is fully assembled.

Copilot uses AI. Check for mistakes.
@saratpoluri saratpoluri merged commit 18e715f into main Apr 3, 2026
33 checks passed
@saratpoluri saratpoluri deleted the fix/singleton-sensor-tagging branch April 3, 2026 17:55
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.

[Bug] Sensor data not tagged on tracks as expected

7 participants