38 #include <Calibration/Calibration.h>
39 #include <Image/ImageProcessor.h>
40 #include <Color/ColorParameterSet.h>
44 #include <Locators/VisualTargetLocator.h>
58 usingProxy(getProperty<std::string>(
"RobotStateComponentName").getValue());
59 tcpNameLeft = getProperty<std::string>(
"TCPNameLeft").getValue();
60 tcpNameRight = getProperty<std::string>(
"TCPNameRight").getValue();
61 markerNameLeft = getProperty<std::string>(
"MarkerNameLeft").getValue();
62 markerNameRight = getProperty<std::string>(
"MarkerNameRight").getValue();
63 useVision = getProperty<bool>(
"UseVision").getValue();
69 robotStateComponent = getProxy<armarx::RobotStateComponentInterfacePrx>(getProperty<std::string>(
"RobotStateComponentName").getValue());
80 std::string colorParameterFilename = getProperty<std::string>(
"ColorParameterFile").getValue();
84 ARMARX_ERROR <<
"Could not find color parameter file in ArmarXDataPath: " << colorParameterFilename;
88 ARMARX_VERBOSE <<
"Color parameter file name: " << colorParameterFilename;
90 visualTargetLocator =
new CVisualTargetLocator();
97 colorParameterSet =
new CColorParameterSet();
98 colorParameterSet->LoadFromFile(colorParameterFilename.c_str());
101 showSegmentedResultImages = getProperty<bool>(
"ShowSegmentedResultImages").getValue();
103 if (!showSegmentedResultImages)
115 ARMARX_VERBOSE <<
"Adding object class " << objectClassEntity->getName();
118 markerColors[objectClassEntity->getName()] = recognitionWrapper->getObjectColor();
129 const float recognitionCertainty = 0.8f;
130 const float uncertaintyWhenReturningKinematicPosition = 10000;
131 const float maxDistToFwdKinPose = getProperty<float>(
"MaximalAcceptedDistanceFromForwardKinematics").getValue();
136 const auto agentName = localRobot->getName();
137 std::string firstObjectName = objectClassNames.at(0);
138 bool firstEntryIsLeft = firstObjectName.find(
"left") != std::string::npos || firstObjectName.find(
"Left") != std::string::npos;
140 Eigen::Matrix4f leftHandPose = localRobot->getRobotNode(tcpNameLeft)->getPoseInRootFrame();
141 Eigen::Matrix4f rightHandPose = localRobot->getRobotNode(tcpNameRight)->getPoseInRootFrame();
142 Eigen::Matrix4f leftMarkerPose = localRobot->getRobotNode(markerNameLeft)->getPoseInRootFrame();
143 Eigen::Matrix4f rightMarkerPose = localRobot->getRobotNode(markerNameRight)->getPoseInRootFrame();
153 leftHandPose = cameraPoseInv * leftHandPose;
154 rightHandPose = cameraPoseInv * rightHandPose;
155 leftMarkerPose = cameraPoseInv * leftMarkerPose;
156 rightMarkerPose = cameraPoseInv * rightMarkerPose;
158 Eigen::Vector3f markerOffsetToTCPLeft = leftHandPose.block<3, 1>(0, 3) - leftMarkerPose.block<3, 1>(0, 3);
159 Eigen::Vector3f markerOffsetToTCPRight = rightHandPose.block<3, 1>(0, 3) - rightMarkerPose.block<3, 1>(0, 3);
162 memoryx::ObjectLocalizationResultList resultList;
167 Vec3d handMarkerPositionLeft, handMarkerPositionRight;
168 int numFoundMarkers = 0;
178 numFoundMarkers = visualTargetLocator->LocateOneOrTwoTargets(
cameraImages, NULL, handMarkerPositionLeft, handMarkerPositionRight, -1,
getImagesAreUndistorted(), markerColors[firstObjectName]);
181 ARMARX_VERBOSE <<
"Found " << numFoundMarkers <<
" hand markers.";
183 if (numFoundMarkers == 0)
185 ARMARX_INFO <<
"Marker not found, color: " << markerColors[firstObjectName];
189 if (numFoundMarkers > 0)
192 memoryx::ObjectLocalizationResult result;
193 result.recognitionCertainty = recognitionCertainty;
195 Eigen::Vector3f position;
197 if (numFoundMarkers == 1)
199 if (objectClassNames.size() == 1)
201 result.objectClassName = objectClassNames.at(0);
202 position << handMarkerPositionLeft.x, handMarkerPositionLeft.y, handMarkerPositionLeft.z;
204 float distToFwdKinPos;
205 if (firstEntryIsLeft)
207 distToFwdKinPos = (leftMarkerPose.block<3, 1>(0, 3) - position).norm();
208 position = position + markerOffsetToTCPLeft;
209 result.orientation = orientationLeftHand;
213 distToFwdKinPos = (rightMarkerPose.block<3, 1>(0, 3) - position).norm();
214 position = position + markerOffsetToTCPRight;
215 result.orientation = orientationRightHand;
222 if (firstEntryIsLeft)
224 ARMARX_VERBOSE <<
"Position of left hand: " << pos->toRootFrame(localRobot)->output();
228 ARMARX_VERBOSE <<
"Position of right hand: " << pos->toRootFrame(localRobot)->output();
230 ARMARX_DEBUG <<
"Distance to position from forward kinematics: " << distToFwdKinPos <<
"(max: " << maxDistToFwdKinPose <<
")";
232 if (distToFwdKinPos < maxDistToFwdKinPose)
234 resultList.push_back(result);
245 ARMARX_VERBOSE <<
"Refusing found marker because it is too far from the position from the kinematic model (" << distToFwdKinPos <<
", max: " << maxDistToFwdKinPose <<
")";
248 else if (objectClassNames.size() == 2)
250 ARMARX_IMPORTANT <<
"Found only 1 hand marker, but 2 were searched for. Returning the localized marker position as a localization result for the closer hand from forward kinematics." ;
252 position << handMarkerPositionLeft.x, handMarkerPositionLeft.y, handMarkerPositionLeft.z;
253 float distToFwdKinPosLeft = (leftMarkerPose.block<3, 1>(0, 3) - position).norm();
254 float distToFwdKinPosRight = (rightMarkerPose.block<3, 1>(0, 3) - position).norm();
256 std::string nameLeft, nameRight;
258 if (firstEntryIsLeft)
260 nameLeft = objectClassNames.at(0);
261 nameRight = objectClassNames.at(1);
265 nameLeft = objectClassNames.at(1);
266 nameRight = objectClassNames.at(0);
269 ARMARX_VERBOSE <<
"Distance to position from forward kinematics for " << nameLeft <<
": " << distToFwdKinPosLeft <<
"(max: " << maxDistToFwdKinPose <<
")";
270 ARMARX_VERBOSE <<
"Distance to position from forward kinematics for " << nameRight <<
": " << distToFwdKinPosRight <<
"(max: " << maxDistToFwdKinPose <<
")";
273 if (distToFwdKinPosLeft < maxDistToFwdKinPose && distToFwdKinPosLeft < distToFwdKinPosRight)
275 result.objectClassName = nameLeft;
276 position = position + markerOffsetToTCPLeft;
279 result.orientation = orientationLeftHand;
280 resultList.push_back(result);
283 if (distToFwdKinPosRight < maxDistToFwdKinPose && distToFwdKinPosRight < distToFwdKinPosLeft)
285 result.objectClassName = nameRight;
286 position = position + markerOffsetToTCPRight;
289 result.orientation = orientationRightHand;
290 resultList.push_back(result);
294 else if (numFoundMarkers == 2)
296 if (objectClassNames.size() == 1)
300 result.objectClassName = objectClassNames.at(0);
302 position << handMarkerPositionLeft.x, handMarkerPositionLeft.y, handMarkerPositionLeft.z;
304 float distToFwdKinPosLeft = (leftMarkerPose.block<3, 1>(0, 3) - position).norm();
305 float distToFwdKinPosRight = (rightMarkerPose.block<3, 1>(0, 3) - position).norm();
307 if (firstEntryIsLeft)
309 ARMARX_VERBOSE <<
"Distance to position from forward kinematics: " << distToFwdKinPosLeft <<
"(max: " << maxDistToFwdKinPose <<
")";
311 position = position + markerOffsetToTCPLeft;
314 result.orientation = orientationLeftHand;
316 if (distToFwdKinPosLeft < maxDistToFwdKinPose && distToFwdKinPosLeft < distToFwdKinPosRight)
318 resultList.push_back(result);
323 ARMARX_VERBOSE <<
"Distance to position from forward kinematics: " << distToFwdKinPosRight <<
"(max: " << maxDistToFwdKinPose <<
")";
325 position = position + markerOffsetToTCPRight;
328 result.orientation = orientationRightHand;
330 if (distToFwdKinPosRight < maxDistToFwdKinPose && distToFwdKinPosRight < distToFwdKinPosLeft)
332 resultList.push_back(result);
338 position << handMarkerPositionRight.x, handMarkerPositionRight.y, handMarkerPositionRight.z;
340 distToFwdKinPosLeft = (leftMarkerPose.block<3, 1>(0, 3) - position).norm();
341 distToFwdKinPosRight = (rightMarkerPose.block<3, 1>(0, 3) - position).norm();
343 if (firstEntryIsLeft)
345 ARMARX_VERBOSE <<
"Distance to position from forward kinematics: " << distToFwdKinPosLeft <<
"(max: " << maxDistToFwdKinPose <<
")";
347 position = position + markerOffsetToTCPLeft;
350 result.orientation = orientationLeftHand;
352 if (distToFwdKinPosLeft < maxDistToFwdKinPose && distToFwdKinPosLeft < distToFwdKinPosRight)
354 resultList.push_back(result);
359 ARMARX_VERBOSE <<
"Distance to position from forward kinematics: " << distToFwdKinPosRight <<
"(max: " << maxDistToFwdKinPose <<
")";
361 position = position + markerOffsetToTCPRight;
364 result.orientation = orientationRightHand;
366 if (distToFwdKinPosRight < maxDistToFwdKinPose && distToFwdKinPosRight < distToFwdKinPosLeft)
368 resultList.push_back(result);
372 else if (objectClassNames.size() == 2)
374 std::string nameLeft, nameRight;
376 if (firstEntryIsLeft)
378 nameLeft = objectClassNames.at(0);
379 nameRight = objectClassNames.at(1);
383 nameLeft = objectClassNames.at(1);
384 nameRight = objectClassNames.at(0);
387 result.objectClassName = nameLeft;
388 position << handMarkerPositionLeft.x, handMarkerPositionLeft.y, handMarkerPositionLeft.z;
389 position = position + markerOffsetToTCPLeft;
390 float distToFwdKinPosLeft = (leftMarkerPose.block<3, 1>(0, 3) - position).norm();
391 float distToFwdKinPosRight = (rightMarkerPose.block<3, 1>(0, 3) - position).norm();
393 result.orientation = orientationLeftHand;
395 ARMARX_VERBOSE <<
"Distance to position from forward kinematics (left): " << distToFwdKinPosLeft <<
"(max: " << maxDistToFwdKinPose <<
")";
397 if (distToFwdKinPosLeft < maxDistToFwdKinPose && distToFwdKinPosLeft < distToFwdKinPosRight)
399 resultList.push_back(result);
402 result.objectClassName = nameRight;
403 position << handMarkerPositionRight.x, handMarkerPositionRight.y, handMarkerPositionRight.z;
404 position = position + markerOffsetToTCPRight;
405 distToFwdKinPosLeft = (leftMarkerPose.block<3, 1>(0, 3) - position).norm();
406 distToFwdKinPosRight = (rightMarkerPose.block<3, 1>(0, 3) - position).norm();
408 result.orientation = orientationRightHand;
410 ARMARX_VERBOSE <<
"Distance to position from forward kinematics (right): " << distToFwdKinPosRight <<
"(max: " << maxDistToFwdKinPose <<
")";
412 if (distToFwdKinPosRight < maxDistToFwdKinPose && distToFwdKinPosRight < distToFwdKinPosLeft)
414 resultList.push_back(result);
421 if (showSegmentedResultImages)
423 CByteImage* pSegmentedImage =
new CByteImage(
cameraImages[0]->width,
cameraImages[0]->height, CByteImage::eGrayScale);
424 ::ImageProcessor::FilterColor(
cameraImages[0], pSegmentedImage, markerColors[firstObjectName], colorParameterSet,
false);
425 ::ImageProcessor::ConvertImage(pSegmentedImage,
resultImages[2]);
426 delete pSegmentedImage;
431 if (resultList.size() < objectClassNames.size())
434 memoryx::ObjectLocalizationResult result;
435 result.recognitionCertainty = recognitionCertainty;
440 float var = uncertaintyWhenReturningKinematicPosition * uncertaintyWhenReturningKinematicPosition;
441 variances << var, 0, 0,
445 if (objectClassNames.size() == 1)
447 ARMARX_INFO <<
"Returning hand pose from forward kinematics for one hand: " << objectClassNames.at(0);
449 result.objectClassName = objectClassNames.at(0);
451 if (firstEntryIsLeft)
453 ARMARX_INFO <<
"left hand position: " << positionLeftHand->output();
454 result.position = positionLeftHand;
455 result.orientation = orientationLeftHand;
456 Eigen::Vector3f
mean = positionLeftHand->toEigen();
461 ARMARX_INFO <<
"right hand position: " << positionRightHand->output();
462 result.position = positionRightHand;
463 result.orientation = orientationRightHand;
464 Eigen::Vector3f
mean = positionRightHand->toEigen();
468 resultList.push_back(result);
470 else if (objectClassNames.size() == 2)
472 std::string leftName = firstEntryIsLeft ? objectClassNames.at(0) : objectClassNames.at(1);
473 std::string rightName = firstEntryIsLeft ? objectClassNames.at(1) : objectClassNames.at(0);
475 if (resultList.size() == 0)
477 ARMARX_INFO <<
"Returning hand pose from forward kinematics for two hands: " << objectClassNames.at(0) <<
", " << objectClassNames.at(1);
479 result.objectClassName = leftName;
480 result.position = positionLeftHand;
481 result.orientation = orientationLeftHand;
482 Eigen::Vector3f
mean = positionLeftHand->toEigen();
484 resultList.push_back(result);
486 result.objectClassName = rightName;
487 result.position = positionRightHand;
488 result.orientation = orientationRightHand;
489 mean = positionRightHand->toEigen();
491 resultList.push_back(result);
495 if (resultList.at(0).objectClassName == leftName)
497 ARMARX_INFO <<
"Returning hand pose from recognition for " << leftName <<
" and from forward kinematics for " << rightName;
498 result.objectClassName = rightName;
499 result.position = positionRightHand;
500 result.orientation = orientationRightHand;
501 Eigen::Vector3f
mean = positionRightHand->toEigen();
503 resultList.push_back(result);
507 ARMARX_INFO <<
"Returning hand pose from recognition for " << rightName <<
" and from forward kinematics for " << leftName;
508 result.objectClassName = leftName;
509 result.position = positionLeftHand;
510 result.orientation = orientationLeftHand;
511 Eigen::Vector3f
mean = positionLeftHand->toEigen();
513 resultList.push_back(result);
519 ARMARX_WARNING <<
"More than 2 hands requested - this case is not handled here";
522 for (
auto& result : resultList)
534 void HandMarkerLocalization::drawCrossInImage(CByteImage* image, Eigen::Vector3f point,
bool leftCamera)
536 Vec3d positionIVT = {point(0), point(1), point(2)};
537 Vec2d projectedPoint;
550 if (size < projectedPoint.x && size < projectedPoint.y && projectedPoint.x < image->width - size - 1 && projectedPoint.y < image->height - size - 3)
552 for (
int i = -size; i <= size; i++)
554 int indexHorizontalLine = 3 * ((int)projectedPoint.y * image->width + (
int)projectedPoint.x + i);
555 int indexVerticalLine = 3 * (((int)projectedPoint.y + i) * image->width + (int)projectedPoint.x);
556 image->pixels[indexHorizontalLine] = 255;
557 image->pixels[indexHorizontalLine + 1] = 255;
558 image->pixels[indexHorizontalLine + 2] = 255;
559 image->pixels[indexVerticalLine] = 255;
560 image->pixels[indexVerticalLine + 1] = 255;
561 image->pixels[indexVerticalLine + 2] = 255;