-
Notifications
You must be signed in to change notification settings - Fork 192
Buxfix/align runtime calibration change #1782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -353,11 +353,43 @@ void ImageAlign::run() { | |
| auto latestConfig = initialConfig; | ||
|
|
||
| int previousShiftFactor = 0; | ||
| bool refreshAlignToTransform = false; | ||
|
|
||
| ImgTransformation inputAlignToTransform; | ||
| ImgFrame inputAlignToImgFrame; | ||
| uint32_t currentEepromId = getParentPipeline().getEepromId(); | ||
|
|
||
| auto updateAlignToData = [&](const std::shared_ptr<ImgFrame>& inputAlignToImg) { | ||
| inputAlignToImgFrame = *inputAlignToImg; | ||
|
|
||
| auto alignTransform = inputAlignToImg->transformation; | ||
| const auto alignToDistortion = alignTransform.getDistortionCoefficients(); | ||
| const bool hasDistortion = std::any_of(alignToDistortion.begin(), alignToDistortion.end(), [](float value) { return std::abs(value) > 0.0f; }); | ||
| if(hasDistortion) { | ||
| logger->warn( | ||
| "The input connected to inputAlignTo is distorted. The aligned image will still be undistorted, meaning it won't be perfectly " | ||
| "aligned."); | ||
| } | ||
|
|
||
| alignTo = static_cast<CameraBoardSocket>(inputAlignToImg->getInstanceNum()); | ||
| if(alignWidth == 0 || alignHeight == 0) { | ||
| alignWidth = inputAlignToImg->getWidth(); | ||
| alignHeight = inputAlignToImg->getHeight(); | ||
| } | ||
|
|
||
| auto alignTransformForIntrinsics = alignTransform; | ||
| auto [alignTransformWidth, alignTransformHeight] = alignTransformForIntrinsics.getSize(); | ||
| if(static_cast<int>(alignTransformWidth) != alignWidth || static_cast<int>(alignTransformHeight) != alignHeight) { | ||
| float scaleX = static_cast<float>(alignWidth) / static_cast<float>(alignTransformWidth); | ||
| float scaleY = static_cast<float>(alignHeight) / static_cast<float>(alignTransformHeight); | ||
| alignTransformForIntrinsics.addScale(scaleX, scaleY); | ||
| alignTransformForIntrinsics.setSize(alignWidth, alignHeight); | ||
| } | ||
|
|
||
| alignSourceIntrinsics = alignTransformForIntrinsics.getIntrinsicMatrix(); | ||
| inputAlignToTransform = alignTransformForIntrinsics; | ||
| }; | ||
|
|
||
| while(mainLoop()) { | ||
| std::shared_ptr<ImgFrame> inputImg = nullptr; | ||
| std::shared_ptr<ImageAlignConfig> inConfig = nullptr; | ||
|
|
@@ -371,35 +403,7 @@ void ImageAlign::run() { | |
| initialized = true; | ||
|
|
||
| auto inputAlignToImg = inputAlignTo.get<ImgFrame>(); | ||
|
|
||
| inputAlignToImgFrame = *inputAlignToImg; | ||
|
|
||
| inputAlignToTransform = inputAlignToImg->transformation; | ||
| const auto alignToDistortion = inputAlignToTransform.getDistortionCoefficients(); | ||
| const bool hasDistortion = std::any_of(alignToDistortion.begin(), alignToDistortion.end(), [](float value) { return std::abs(value) > 0.0f; }); | ||
| if(hasDistortion) { | ||
| logger->warn( | ||
| "The input connected to inputAlignTo is distorted. The aligned image will still be undistorted, meaning it won't be perfectly " | ||
| "aligned."); | ||
| } | ||
|
|
||
| alignTo = static_cast<CameraBoardSocket>(inputAlignToImg->getInstanceNum()); | ||
| if(alignWidth == 0 || alignHeight == 0) { | ||
| alignWidth = inputAlignToImg->getWidth(); | ||
| alignHeight = inputAlignToImg->getHeight(); | ||
| } | ||
|
|
||
| auto alignTransformForIntrinsics = inputAlignToTransform; | ||
| auto [alignTransformWidth, alignTransformHeight] = alignTransformForIntrinsics.getSize(); | ||
| if(static_cast<int>(alignTransformWidth) != alignWidth || static_cast<int>(alignTransformHeight) != alignHeight) { | ||
| float scaleX = static_cast<float>(alignWidth) / static_cast<float>(alignTransformWidth); | ||
| float scaleY = static_cast<float>(alignHeight) / static_cast<float>(alignTransformHeight); | ||
| alignTransformForIntrinsics.addScale(scaleX, scaleY); | ||
| alignTransformForIntrinsics.setSize(alignWidth, alignHeight); | ||
| } | ||
|
|
||
| alignSourceIntrinsics = alignTransformForIntrinsics.getIntrinsicMatrix(); | ||
| inputAlignToTransform = alignTransformForIntrinsics; | ||
| updateAlignToData(inputAlignToImg); | ||
| } | ||
|
|
||
| if(inputConfig.getWaitForMessage()) { | ||
|
|
@@ -451,10 +455,22 @@ void ImageAlign::run() { | |
| if(latestEepromId > currentEepromId) { | ||
| logger->debug("EEPROM data changed (ID: {} -> {}), reconfiguring ...", currentEepromId, latestEepromId); | ||
| calibrationSet = false; | ||
| previousShiftFactor = 0; | ||
| refreshAlignToTransform = true; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need refreshAlignToTransform? To me it looks like the inverse of calibrationSet and they are inherently linked (when refreshAlignToTransform == True then setCalibration has to be false to properly update the maps). The updateAlignToData lambda has a capture by reference for setCalibration bool and could have the same logic as extractCalibrationData where |
||
| calibHandler = pipeline.getCalibrationData(); | ||
| currentEepromId = latestEepromId; | ||
| } | ||
|
|
||
| if(refreshAlignToTransform) { | ||
| if(auto latestAlignToImg = inputAlignTo.tryGet<ImgFrame>()) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would preffer |
||
| updateAlignToData(latestAlignToImg); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is going to be unpredictable behaviour. Lets say that the eeprom ID got updated but an ImgFrame with the new ImgTransformation hasn`t gotten to the inputAlignTo queue (eg. Camera hasnt generated a new ImgFrame yet), then latestAlignToImg will be a message with the old ImgTransformation. So the update wont actually update the ImgTransformation. I'm guessing this happens more often if you dont have camera node connected directly to the ImageAling node but have some other nodes in between that increase the time between between new inputAlignTo messages. IMO best solution is to store the previous ImgTransformation and only update when that changes. But I have that made in another branch where its also fallsback to previous impl in case no ImgTransformations available. |
||
| refreshAlignToTransform = false; | ||
| } else { | ||
| logger->trace("Waiting for updated inputAlignTo frame after calibration change."); | ||
| continue; | ||
| } | ||
|
Comment on lines
+464
to
+471
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stale The The critical problem is that A targeted fix: after calling 🛡️ Proposed hardening if(refreshAlignToTransform) {
if(auto latestAlignToImg = inputAlignTo.tryGet<ImgFrame>()) {
updateAlignToData(latestAlignToImg);
+ // Guard against stale queued frames: re-read intrinsics from the freshly
+ // updated calibHandler so alignSourceIntrinsics is always consistent with
+ // the new calibration data used in extractCalibrationData.
+ auto freshIntrinsics = calibHandler.getCameraIntrinsics(alignTo, alignWidth, alignHeight);
+ for(size_t i = 0; i < 3; ++i)
+ for(size_t j = 0; j < 3; ++j)
+ alignSourceIntrinsics[i][j] = freshIntrinsics[i][j];
refreshAlignToTransform = false;
} else {🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| try { | ||
| extractCalibrationData(width, height, alignWidth, alignHeight); | ||
| } catch(const std::exception& e) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.