Skip to content

ITEP-90209: tracked object contains re-id state and object id chain#1302

Open
saratpoluri wants to merge 4 commits intomainfrom
feature/object-reided
Open

ITEP-90209: tracked object contains re-id state and object id chain#1302
saratpoluri wants to merge 4 commits intomainfrom
feature/object-reided

Conversation

@saratpoluri
Copy link
Copy Markdown
Contributor

📝 Description

Provide a clear summary of the changes and the context behind them. Describe what was changed, why it was needed, and how the changes address the issue or add value.

✨ Type of Change

Select the type of change your PR introduces:

  • 🐞 Bug fix – Non-breaking change which fixes an issue
  • 🚀 New feature – Non-breaking change which adds functionality
  • 🔨 Refactor – Non-breaking change which refactors the code base
  • 💥 Breaking change – Changes that break existing functionality
  • 📚 Documentation update
  • 🔒 Security update
  • 🧪 Tests
  • 🚂 CI

🧪 Testing Scenarios

Describe how the changes were tested and how reviewers can test them too:

  • ✅ Tested manually
  • 🤖 Ran automated end-to-end tests

✅ Checklist

Before submitting the PR, ensure the following:

  • 🔍 PR title is clear and descriptive
  • 📝 For internal contributors: If applicable, include the JIRA ticket number (e.g., ITEP-123456) in the PR title. Do not include full URLs
  • 💬 I have commented my code, especially in hard-to-understand areas
  • 📄 I have made corresponding changes to the documentation
  • ✅ I have added tests that prove my fix is effective or my feature works

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 extends the Scene Controller’s tracked-object output to carry explicit ReID status and an object-ID history chain (for post-mortem stitching/analysis), and updates multiple service “Agents” guides plus repository Copilot instructions to reflect current build/test workflows.

Changes:

  • Add ReidState + previous_ids_chain tracking on MovingObject, and serialize these fields in detection outputs.
  • Update UUID assignment / similarity-query flow to set ReID state and record ID-chain transitions.
  • Refresh build/test instructions across service Agents.md docs and .github/copilot-instructions.md.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
controller/src/controller/moving_object.py Introduces ReidState, ID-chain recording helpers, and new per-object fields.
controller/src/controller/uuid_manager.py Updates similarity-query / ID assignment to set ReID state and record ID changes.
controller/src/controller/detections_builder.py Serializes reid_state and previous_ids_chain into object dictionaries.
controller/Agents.md Updates controller build/test instructions (currently has Markdown fence issues).
mapping/Agents.md Updates mapping build/test instructions (wording vs actual Make targets mismatch).
manager/Agents.md Updates manager build/test instructions (wording vs actual Make targets mismatch).
autocalibration/Agents.md Updates autocalibration build/test instructions (wording vs actual Make targets mismatch).
cluster_analytics/Agents.md Updates cluster_analytics build/test instructions (wording vs actual Make targets mismatch).
.github/copilot-instructions.md Updates repo-wide guidance for build/test prerequisites and test targets.

Comment on lines 422 to +424
# MATCH FOUND - YES + DB ID ALREADY IN DICT - NO
if database_id and self.isNewID(database_id):
self.active_ids[sscape_object.rv_id] = [database_id, similarity]
# Query succeeded and found a match -> update state to MATCHED
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

updateActiveDict() uses if database_id and self.isNewID(database_id) to detect whether a matched DB ID is already assigned to another active track. When isNewID(database_id) is false (ID collision), the current logic falls into the else path and ends up reusing that database_id anyway, which can produce duplicate gid values across simultaneous tracks. Handle the collision separately (e.g., treat as no-match and generate/keep a unique gid) instead of reusing the already-active ID.

Copilot uses AI. Check for mistakes.
Comment on lines +496 to 502
# If reid is disabled, mark object state immediately (no query will be made)
if not self.reid_enabled:
sscape_object.reid_state = ReidState.REID_DISABLED

# Continue gathering features until we have enough or query is already submitted
if sscape_object.rv_id not in self.active_query and self.reid_enabled:
self.gatherQualityVisualFeatures(sscape_object)
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

assignID() sets sscape_object.reid_state = REID_DISABLED whenever self.reid_enabled is false. Since assignID() runs every frame, this will overwrite per-object terminal states like MATCHED/QUERY_NO_MATCH after they were set, and it can also mask an in-flight/completed query. Only set REID_DISABLED for objects that have not already been queried/matched (e.g., when reid_state is still PENDING_COLLECTION and no query has been submitted for that track).

Copilot uses AI. Check for mistakes.
Comment on lines 128 to +132
self.reid = {} # Initialize reid as empty dict
self.metadata = {} # Initialize metadata as empty dict
self.reid_state = ReidState.PENDING_COLLECTION # Track reID state
self.similarity = None # Similarity score from last reID match
self.previous_ids_chain = [] # Track object ID history: [{'id': gid, 'timestamp': ts, 'similarity_score': score}, ...]
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

reid_state, similarity, and previous_ids_chain are initialized on each new MovingObject instance. In the tracking flow, objects are re-created each frame and setPrevious() copies persistent fields (gid, first_seen, chain_data, etc.) from the prior instance, but it does not copy these newly added fields. As a result, downstream outputs will often see reid_state reset to PENDING_COLLECTION and lose previous_ids_chain across frames. Persist these fields across frames (e.g., copy them in setPrevious() or store them inside chain_data).

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +143
make -C controller # Rebuild controller
make -C controller test-build # Build controller + test image

# OR from controller/ directory
cd controller && make # Rebuild controller
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

The build commands shown here use make -C <service> / cd <service> && make, but those targets default to build-image (cached build) via common.mk, not a no-cache rebuild. Either change the wording from "Rebuild" to "Build", or update the commands to explicitly run make ... rebuild if you intend a rebuild.

Suggested change
make -C controller # Rebuild controller
make -C controller test-build # Build controller + test image
# OR from controller/ directory
cd controller && make # Rebuild controller
make -C controller # Build controller
make -C controller test-build # Build controller + test image
# OR from controller/ directory
cd controller && make # Build controller

Copilot uses AI. Check for mistakes.
Comment on lines 164 to +168
# Specific test module

pytest tests/sscape_tests/controller/test_tracking.py -v
```

````
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

Markdown code fences are broken here: the controller build/test code block is closed at line 162, but a new fence is started with four backticks (````) at line 168, and the "Running Locally" block is also closed with four backticks. This renders incorrectly in GitHub. Use triple backticks consistently (```), and wrap the pytest ... command in an appropriate fenced block if desired.

Copilot uses AI. Check for mistakes.
Comment on lines 97 to +103
```bash
# From root directory
make manager # Build image
make rebuild-manager # Clean + rebuild
# From repo root
make -C manager # Rebuild manager

# Build with dependencies
make build-core # Includes manager
# OR from manager/ directory
cd manager && make # Rebuild manager

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

make -C manager / cd manager && make runs the default build-image target (cached build), not a rebuild. Consider changing the wording from "Rebuild" to "Build", or update the command to make ... rebuild if a rebuild is intended.

Copilot uses AI. Check for mistakes.
Comment on lines +78 to +82
make -C autocalibration # Rebuild autocalibration
make -C autocalibration test-build # Build autocalibration + test image

# OR from autocalibration/ directory
cd autocalibration && make # Rebuild autocalibration
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

make -C autocalibration / cd autocalibration && make invokes the default build-image target; it does not do a no-cache rebuild. Please align the wording ("Build" vs "Rebuild") or use make ... rebuild if you intend rebuild semantics.

Suggested change
make -C autocalibration # Rebuild autocalibration
make -C autocalibration test-build # Build autocalibration + test image
# OR from autocalibration/ directory
cd autocalibration && make # Rebuild autocalibration
make -C autocalibration # Build autocalibration
make -C autocalibration test-build # Build autocalibration + test image
# OR from autocalibration/ directory
cd autocalibration && make # Build autocalibration

Copilot uses AI. Check for mistakes.
Comment on lines 134 to +141
```bash
# From root directory
make cluster_analytics # Build image
make rebuild-cluster_analytics # Clean + rebuild
# From repo root
make -C cluster_analytics # Rebuild cluster_analytics
make -C cluster_analytics test-build # Build cluster_analytics + test image

# OR from cluster_analytics/ directory
cd cluster_analytics && make # Rebuild cluster_analytics
cd cluster_analytics && make test-build # Build cluster_analytics + test image
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

make -C cluster_analytics / cd cluster_analytics && make runs the default cached build target, not a rebuild. Adjust the wording from "Rebuild" to "Build" or use make ... rebuild if a rebuild is intended.

Copilot uses AI. Check for mistakes.
Comment on lines 423 to +433
if database_id and self.isNewID(database_id):
self.active_ids[sscape_object.rv_id] = [database_id, similarity]
# Query succeeded and found a match -> update state to MATCHED
sscape_object.reid_state = ReidState.MATCHED
sscape_object.gid = database_id
sscape_object.similarity = similarity
# Record the matched ID in chain with similarity score
sscape_object.record_id_change(database_id, similarity_score=similarity, timestamp=query_timestamp)

log.debug(
f"updateActiveDict: Match found for {sscape_object.rv_id}: {database_id},{similarity}")
# MATCH FOUND - NO / DB ID ALREADY IN DICT - YES
f"updateActiveDict: Match found for {sscape_object.rv_id}: {database_id}, similarity={similarity}, state={ReidState.MATCHED.value}")
self.active_ids[sscape_object.rv_id] = [database_id, similarity]
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

New behavior in updateActiveDict() mutates per-object state (reid_state, similarity) and appends to previous_ids_chain via record_id_change(), but the existing tests/sscape_tests/uuid_manager/test_uuid_manager.py suite does not currently cover updateActiveDict() or these new state transitions. Adding unit tests for (a) match found, (b) no match/new gid assignment, and (c) ID-collision handling would help prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +134
# Add reid state for downstream business logic to distinguish "never queried" from "query made"
if hasattr(aobj, 'reid_state'):
obj_dict['reid_state'] = aobj.reid_state.value # Convert enum to string

# Add previous IDs chain for post-mortem object stitching analysis
if hasattr(aobj, 'previous_ids_chain') and aobj.previous_ids_chain:
obj_dict['previous_ids_chain'] = aobj.previous_ids_chain

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

prepareObjDict() now conditionally emits reid_state and previous_ids_chain, but tests/sscape_tests/scenescape/test_detections_builder.py does not assert these fields are serialized correctly. Adding a couple of unit tests (e.g., enum -> string conversion and chain presence/absence) would lock in the API contract for downstream consumers.

Copilot uses AI. Check for mistakes.
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.

2 participants