32 #include <VirtualRobot/Grasping/GraspSet.h>
38 #include <VirtualRobot/Grasping/Grasp.h>
39 #include <VirtualRobot/Workspace/Manipulability.h>
40 #include <VirtualRobot/ManipulationObject.h>
46 #include <IceUtil/UUID.h>
47 #include <RobotComponents/interface/components/MotionPlanning/MotionPlanningServer.h>
48 #include <VirtualRobot/RobotConfig.h>
49 #include <VisionX/interface/components/VoxelGridProviderInterface.h>
50 #include <VirtualRobot/math/Helpers.h>
52 #include <SimoxUtility/algorithm/string/string_tools.h>
60 static const DrawColor COLOR_ROBOT
62 1.0f, 1.0f, 0.5f, 1.0f
68 defineOptionalProperty<std::string>(
"RobotName",
"Armar3",
"Name of the robot to use");
69 defineOptionalProperty<std::string>(
"RobotFilePath",
"RobotAPI/robots/Armar3/ArmarIII.xml",
"File path of the robot to use");
70 defineOptionalProperty<std::string>(
"CollisionModel",
"PlatformTorsoHeadColModel",
"Collisionmodel of the robot");
71 defineOptionalProperty<std::string>(
"WorkspaceFilePaths",
72 "Armar3/reachability/reachability_right_hand_smoothened.bin;Armar3/reachability/reachability_left_hand_smoothened.bin",
73 "Paths to manipulability and reachability files (';' delimited)");
77 defineOptionalProperty<float>(
"MinimumDistanceToEnvironment",
79 "Minimum distance to the environment for all robot placements. Much faster if set to zero.");
80 defineOptionalProperty<float>(
"VisualizationSlowdownFactor", 1.0f,
"1.0 is a good value for clear visualization, 0 the visualization should not slow down the process",
PropertyDefinitionBase::eModifiable);
83 defineOptionalProperty<float>(
"MinManipulabilityDecreaseFactor", 0.9f,
"Min initial manipulability in relation to max manipulabity value and factor by which this threshold is decreased each trial",
PropertyDefinitionBase::eModifiable);
88 defineOptionalProperty<std::string>(
"EefNamePreferenceFilter",
"R",
"Prefer grasps where eef name contains this name by setting grasp success probability to 1. Set to empty string to disable.");
96 drawRobotId =
"local_robot_";
97 visuLayerName =
"SimpleRobotPlacement";
99 robotName = getProperty<std::string>(
"RobotName").getValue();
100 robotFilePath = getProperty<std::string>(
"RobotFilePath").getValue();
104 ARMARX_ERROR <<
"Could not find robot file: " << robotFilePath;
107 workspaceFilePaths =
armarx::Split(getProperty<std::string>(
"WorkspaceFilePaths").getValue(),
";");
109 for (std::string& path : workspaceFilePaths)
111 std::string packageName = std::filesystem::path {path} .begin()->string();
112 ARMARX_CHECK_EXPRESSION(!packageName.empty()) <<
"Workspace file path '" << path <<
"' could not be parsed correctly, because package name is empty";
114 path =
project.getDataDir() +
"/" + path;
115 if (!std::filesystem::exists(path))
117 throw LocalException(
"File not found at ") << path;
121 colModel = getProperty<std::string>(
"CollisionModel").getValue();
133 srand(IceUtil::Time::now().toSeconds());
138 getProxy(robotStateComponentPrx,
"RobotStateComponent");
140 objectInstances = wm->getObjectInstancesSegment();
141 agentInstances = wm->getAgentInstancesSegment();
142 objectClasses = prior->getObjectClassesSegment();
146 debugDrawerPrx = getTopic<armarx::DebugDrawerInterfacePrx>(
"DebugDrawerUpdates");
147 entityDrawerPrx = getTopic<memoryx::EntityDrawerInterfacePrx>(
"DebugDrawerUpdates");
165 planningTasks.clear();
166 GraspingPlacementList result;
167 AgentInstancePtr agent = AgentInstancePtr::dynamicCast(agentInstances->getAgentInstanceByName(robotName));
168 std::shared_ptr<RemoteRobot> remoteRobot(
new RemoteRobot(robotStateComponentPrx->getSynchronizedRobot()));
169 robot->setGlobalPose(remoteRobot->getGlobalPose());
172 GeneratedGraspList filteredGrasps = filterGrasps(grasps);
173 visualizedGrid.reset();
174 entityDrawerPrx->clearLayer(visuLayerName);
178 if (getProperty<bool>(
"UseVoxelGridCSpace").getValue())
180 cspace =
new VoxelGridCSpace(getProxy<visionx::VoxelGridProviderInterfacePrx>(getProperty<std::string>(
"VoxelGridProviderName").getValue()), prior->getCommonStorage());
184 cspace =
new SimoxCSpace(prior->getCommonStorage(),
false, 30);
186 cspace->addObjectsFromWorkingMemory(wm);
187 AgentPlanningInformation agentData;
188 agentData.agentProjectNames = robotStateComponentPrx->getArmarXPackages();
189 agentData.agentRelativeFilePath = robotStateComponentPrx->getRobotFilename();
191 agentData.kinemaicChainNames = {};
192 agentData.collisionSetNames = {colModel};
193 agentData.initialJointValues = robot->getConfig()->getRobotNodeJointValueMap();
194 cspace->setAgent(agentData);
195 cspace->setStationaryObjectMargin(getProperty<float>(
"MinimumDistanceToEnvironment").getValue());
196 cspace->initCollisionTest();
198 int placementsPerGrasp = getProperty<int>(
"PlacmentsPerGrasp");
199 ARMARX_VERBOSE <<
"Searching " << placementsPerGrasp <<
" poses for " << filteredGrasps.size() <<
" grasps";
200 for (
const auto& g : filteredGrasps)
202 Eigen::Matrix4f graspPose = FramedPosePtr::dynamicCast(g.framedPose)->toGlobalEigen(robot);
208 std::map<float, GraspingPlacement> placementCandidates;
209 for (
int i = 0; i < placementsPerGrasp; ++i)
217 VirtualRobot::WorkspaceGridPtr reachGrid = createWorkspaceGrid(g, graspPose);
220 drawWorkspaceGrid(visualizedGrid);
226 float xGoal, yGoal, platformRotation;
228 getSuitablePosition(g, reachGrid, graspPose, xGoal, yGoal, platformRotation, score);
230 newPose->position->x = xGoal;
231 newPose->position->y = yGoal;
235 float x = newPoseEigen(0, 3);
236 float y = newPoseEigen(1, 3);
237 float z = newPoseEigen(2, 3);
238 newPoseEigen.block<3, 1>(0, 3) = Eigen::Vector3f::Zero();
240 transform = Eigen::Translation<float, 3>(x, y, z) * Eigen::AngleAxisf(platformRotation, Eigen::Vector3f(0, 0, 1));
246 ARMARX_INFO <<
"Inserting robot placement: " << resultPose->output();
247 placementCandidates[score] = GraspingPlacement {g, resultPose, 0};
249 if (!placementCandidates.empty())
255 result.push_back(placementCandidates.rbegin()->second);
259 std::map<std::pair<float, float>, GraspingPlacement> orderedMap;
260 std::string EefNamePreferenceFilter = getProperty<std::string>(
"EefNamePreferenceFilter");
261 for (GraspingPlacement& gp : result)
263 Eigen::Matrix4f mat = inverseRobotPose * FramedPosePtr::dynamicCast(gp.robotPose)->toEigen();
264 Eigen::AngleAxisf aa(mat.block<3, 3>(0, 0));
265 float distanceLhs = mat.block<3, 1>(0, 3).
norm() * aa.angle() * 50;
268 float handPreferenceScore =
Contains(gp.grasp.eefName, EefNamePreferenceFilter,
true) ? 0.f : 1.f;
269 orderedMap [ {handPreferenceScore, distanceLhs}] = gp;
273 entityDrawerPrx->removeLayer(visuLayerName);
274 return getMapValues<>(orderedMap);
281 std::vector<SimpleRobotPlacement::RobotPlacement>
placements;
285 std::sort(placements.begin(), placements.end(), [](
auto &
a,
auto & b)
287 return a.score > b.score;
290 std::pair<float, float> sortingInfo{0, 0};
297 planningTasks.clear();
298 GraspingPlacementList result;
299 AgentInstancePtr agent = AgentInstancePtr::dynamicCast(agentInstances->getAgentInstanceByName(robotName));
301 robot->setGlobalPose(remoteRobot->getGlobalPose());
304 GeneratedGraspList filteredGrasps = filterGrasps(grasps);
305 visualizedGrid.reset();
306 entityDrawerPrx->clearLayer(visuLayerName);
310 if (getProperty<bool>(
"UseVoxelGridCSpace").getValue())
312 cspace =
new VoxelGridCSpace(getProxy<visionx::VoxelGridProviderInterfacePrx>(getProperty<std::string>(
"VoxelGridProviderName").getValue()), prior->getCommonStorage());
316 cspace =
new SimoxCSpace(prior->getCommonStorage(),
false, 30);
318 cspace->addObjectsFromWorkingMemory(wm);
319 AgentPlanningInformation agentData;
320 agentData.agentProjectNames = robotStateComponentPrx->getArmarXPackages();
321 agentData.agentRelativeFilePath = robotStateComponentPrx->getRobotFilename();
323 agentData.kinemaicChainNames = {};
324 agentData.collisionSetNames = {colModel};
325 agentData.initialJointValues = robot->getConfig()->getRobotNodeJointValueMap();
326 cspace->setAgent(agentData);
327 cspace->setStationaryObjectMargin(getProperty<float>(
"MinimumDistanceToEnvironment").getValue());
328 cspace->initCollisionTest();
330 int placementsPerGrasp = getProperty<int>(
"PlacmentsPerGrasp");
331 ARMARX_VERBOSE <<
"Searching " << placementsPerGrasp <<
" poses for " << filteredGrasps.size() <<
" grasps";
333 std::vector<PlacementInfo> pis;
334 for (
const auto& g : filteredGrasps)
338 pi.graspPose = FramedPosePtr::dynamicCast(g.framedPose)->toGlobalEigen(robot);
339 pi.reachGrid = createWorkspaceGrid(g,
pi.graspPose);
340 drawWorkspaceGrid(visualizedGrid);
344 int maxIterations = 1;
345 for (
int n = 0; n < maxIterations; n++)
349 std::vector<SimpleRobotPlacement::RobotPlacement> placements = getSuitablePositions(
pi.grasp,
pi.reachGrid,
pi.graspPose, 0.1, 10, 100);
350 pi.placements.insert(
pi.placements.end(), placements.begin(), placements.end());
355 std::string EefNamePreferenceFilter = getProperty<std::string>(
"EefNamePreferenceFilter");
359 if (
pi.placements.size() == 0)
369 Eigen::Matrix4f robotpose = ::math::Helpers::CreatePose(Eigen::Vector3f(rp.
x, rp.
y, 0), Eigen::AngleAxisf(rp.
z, Eigen::Vector3f::UnitZ()).toRotationMatrix());
371 pi.sortingInfo.first =
Contains(
pi.grasp.eefName, EefNamePreferenceFilter,
true) ? 0.f : 1.f;
372 pi.sortingInfo.second = -rp.
score;
374 entityDrawerPrx->removeLayer(visuLayerName);
375 std::sort(pis.begin(), pis.end(), [](
auto &
a,
auto & b)
377 return a.sortingInfo < b.sortingInfo;
381 if (
pi.placements.size() > 0)
383 GraspingPlacement gp;
385 gp.score =
pi.placements.at(0).score;
386 gp.robotPose =
pi.resultPose;
388 result.push_back(gp);
397 planningTasks.clear();
398 GraspingPlacementList result;
400 if (!hasWorkspace(endEffectorName))
402 ARMARX_ERROR <<
"No pre-loaded workspace found for EEF '" << endEffectorName <<
"'";
407 target_pose->changeToGlobal(robotStateComponentPrx->getSynchronizedRobot());
409 std::shared_ptr<RemoteRobot> remoteRobot(
new RemoteRobot(robotStateComponentPrx->getSynchronizedRobot()));
410 robot->setGlobalPose(remoteRobot->getGlobalPose());
413 AgentPlanningInformation agentData;
414 agentData.agentProjectNames = robotStateComponentPrx->getArmarXPackages();
415 agentData.agentRelativeFilePath = robotStateComponentPrx->getRobotFilename();
416 agentData.kinemaicChainNames = {};
417 agentData.collisionSetNames = {colModel};
418 agentData.initialJointValues = robot->getConfig()->getRobotNodeJointValueMap();
420 visualizedGrid.reset();
421 entityDrawerPrx->clearLayer(visuLayerName);
424 if (getProperty<bool>(
"UseVoxelGridCSpace").getValue())
426 cspace =
new VoxelGridCSpace(getProxy<visionx::VoxelGridProviderInterfacePrx>(getProperty<std::string>(
"VoxelGridProviderName").getValue()), prior->getCommonStorage());
430 cspace =
new SimoxCSpace(prior->getCommonStorage(),
false, 30);
431 cspace->addObjectsFromWorkingMemory(wm);
433 cspace->setAgent(agentData);
434 cspace->setStationaryObjectMargin(getProperty<float>(
"MinimumDistanceToEnvironment").getValue());
437 for (
auto& obstacle : planarObstacles)
439 std::vector<Eigen::Vector3f> plane;
441 for (
auto& p : obstacle)
443 plane.push_back(FramedPositionPtr::dynamicCast(p)->toGlobalEigen(robotStateComponentPrx->getSynchronizedRobot()));
446 cspace->addPlanarObject(plane);
449 cspace->initCollisionTest();
453 g.eefName = endEffectorName;
454 g.framedPose = target_pose;
456 int placmentsPerGrasp = getProperty<int>(
"PlacmentsPerGrasp");
457 ARMARX_INFO <<
"Searching " << placmentsPerGrasp <<
" poses for EEF pose " << target_pose->toEigen();
460 VirtualRobot::MathTools::ConvexHull2DPtr placementArea_ch;
461 if (placementArea.size() > 2)
463 std::vector<Eigen::Vector2f> area;
464 for (
auto& p : placementArea)
466 area.push_back(FramedPositionPtr::dynamicCast(p)->toGlobalEigen(robot).head(2));
468 placementArea_ch = VirtualRobot::MathTools::createConvexHull2D(area);
471 for (
auto& p : placementArea_ch->vertices)
477 for (
int i = 0; i < placmentsPerGrasp; ++i)
480 VirtualRobot::WorkspaceGridPtr grid = createWorkspaceGrid(g, target_pose->toEigen());
481 drawWorkspaceGrid(visualizedGrid);
483 float xGoal, yGoal, platformRotation;
485 getSuitablePosition(g, grid, target_pose->toEigen(), xGoal, yGoal, platformRotation, score, placementArea_ch);
487 if (xGoal == 0 && yGoal == 0 && platformRotation == 0)
494 newPose->position->x = xGoal;
495 newPose->position->y = yGoal;
499 float x = newPoseEigen(0, 3);
500 float y = newPoseEigen(1, 3);
501 float z = newPoseEigen(2, 3);
502 newPoseEigen.block<3, 1>(0, 3) = Eigen::Vector3f::Zero();
504 transform = Eigen::Translation<float, 3>(x, y, z) * Eigen::AngleAxisf(platformRotation, Eigen::Vector3f(0, 0, 1));
508 result.push_back(GraspingPlacement {g, resultPose, score});
511 entityDrawerPrx->removeLayer(visuLayerName);
518 for (VirtualRobot::WorkspaceRepresentationPtr workspace : workspaces)
520 if (workspace->getTCP()->getName() == robot->getEndEffector(g.eefName)->getTcp()->getName())
526 return VirtualRobot::WorkspaceRepresentationPtr();
529 VirtualRobot::WorkspaceGridPtr SimpleRobotPlacement::createWorkspaceGrid(GeneratedGrasp g,
const Eigen::Matrix4f& globalObjectPose)
531 static int counter = 0;
532 std::string graspName =
"some_random_grasp_" +
to_string(counter++);
533 std::string robotType = robotName;
534 std::string eef = g.eefName;
537 VirtualRobot::ManipulationObjectPtr dummyObject(
new ManipulationObject(
"dummyObject"));
538 dummyObject->setGlobalPose(globalObjectPose);
541 Eigen::Matrix4f tcpPoseGlobal = FramedPosePtr::dynamicCast(g.framedPose)->toGlobalEigen(robot);
542 Eigen::Matrix4f tcpPrePoseGlobal = FramedPosePtr::dynamicCast(g.framedPrePose)->toGlobalEigen(robot);
543 Eigen::Matrix4f objectPoseInTcpFrame = tcpPoseGlobal.inverse() * globalObjectPose;
544 VirtualRobot::GraspPtr dummyGrasp(
new Grasp(graspName, robotType, eef, objectPoseInTcpFrame));
545 VirtualRobot::GraspPtr dummyPrepose(
new Grasp(graspName, robotType, eef, tcpPrePoseGlobal.inverse() * globalObjectPose));
547 VirtualRobot::WorkspaceRepresentationPtr ws;
552 Eigen::Vector3f minBB, maxBB;
553 ws->getWorkspaceExtends(minBB, maxBB);
554 VirtualRobot::WorkspaceGridPtr reachGridPrepose;
555 reachGridPrepose.reset(
new WorkspaceGrid(minBB(0), maxBB(0), minBB(1), maxBB(1), ws->getDiscretizeParameterTranslation()));
556 reachGridPrepose->setGridPosition(globalObjectPose(0, 3), globalObjectPose(1, 3));
557 reachGridPrepose->fillGridData(ws, dummyObject, dummyPrepose, robot->getRootNode());
560 VirtualRobot::WorkspaceGridPtr reachGridGrasp;
561 reachGridGrasp.reset(
new WorkspaceGrid(minBB(0), maxBB(0), minBB(1), maxBB(1), ws->getDiscretizeParameterTranslation()));
562 reachGridGrasp->setGridPosition(globalObjectPose(0, 3), globalObjectPose(1, 3));
563 ARMARX_INFO <<
" grasp pose: " << dummyGrasp->getTcpPoseGlobal(globalObjectPose);
564 ARMARX_INFO <<
" prepose pose: " << dummyPrepose->getTcpPoseGlobal(globalObjectPose);
565 reachGridGrasp->fillGridData(ws, dummyObject, dummyGrasp, robot->getRootNode());
574 visualizedGrid = reachGridGrasp;
586 return reachGridGrasp;
590 bool SimpleRobotPlacement::getSuitablePosition(
const GeneratedGrasp& g, VirtualRobot::WorkspaceGridPtr reachGrid,
const Eigen::Matrix4f& globalObjectPose,
float& storeGlobalX,
float& storeGlobalY,
float& storeGlobalYaw,
int& score,
const VirtualRobot::MathTools::ConvexHull2DPtr& placementArea)
598 float minX, maxX, minY, maxY;
599 reachGrid->getExtends(minX, maxX, minY, maxY);
602 reachGrid->getCells(nX, nY);
603 int maxEntry = reachGrid->getMaxEntry();
604 int minRequiredEntry = maxEntry;
606 bool collision =
true;
607 std::vector<GraspPtr> dummyGrasps;
608 float minCollisionDistance = getProperty<float>(
"MinimumDistanceToEnvironment").getValue();
610 auto collisionCheckVisu =
"collisionCheckRobotVisu";
611 if (getProperty<bool>(
"EnableVisualization"))
613 entityDrawerPrx->setRobotVisu(visuLayerName, collisionCheckVisu, robotStateComponentPrx->getRobotFilename(), simox::alg::join(robotStateComponentPrx->getArmarXPackages(),
","), FullModel);
614 auto config = robotStateComponentPrx->getSynchronizedRobot()->getConfig();
616 entityDrawerPrx->updateRobotConfig(visuLayerName, collisionCheckVisu, config);
619 float visuSlowdownFactor = getProperty<float>(
"VisualizationSlowdownFactor");
621 float minManipulabilityDecreaseFactor = getProperty<float>(
"MinManipulabilityDecreaseFactor").getValue();
622 int maxTrials = 1000;
625 const float minDistance2D = getProperty<float>(
"MinPlacementDistance").getValue();
626 const float maxDistance2D = getProperty<float>(
"MaxPlacementDistance").getValue();
631 if (counter >= maxTrials)
633 ARMARX_ERROR <<
"Could not find a collision free robot placement.";
640 minRequiredEntry *= minManipulabilityDecreaseFactor;
641 minRequiredEntry = std::max<int>(minRequiredEntry, maxEntry * 0.1f);
643 if (!reachGrid->getRandomPos(minRequiredEntry, storeGlobalX, storeGlobalY, dummyGrasps, 100, &entries))
647 float distance2D = (Eigen::Vector2f(storeGlobalX, storeGlobalY) - globalObjectPose.block<2, 1>(0, 3)).norm();
648 if (distance2D > maxDistance2D)
651 ARMARX_INFO <<
"Placement too far away: " << distance2D;
654 if (distance2D < minDistance2D)
656 ARMARX_INFO <<
"Placement too close: " << distance2D;
660 if (placementArea !=
nullptr && !VirtualRobot::MathTools::isInside(Eigen::Vector2f(storeGlobalX, storeGlobalY), placementArea))
662 ARMARX_INFO <<
"Generated placement (" << storeGlobalX <<
", " << storeGlobalY <<
") lies outside the permitted area => Retry.";
667 tmpRobotPoseGlobal = originalRobotPoseGlobal;
668 tmpRobotPoseGlobal(0, 3) = storeGlobalX;
669 tmpRobotPoseGlobal(1, 3) = storeGlobalY;
671 storeGlobalYaw = getPlatformRotation(tmpRobotPoseGlobal, globalObjectPose);
672 score = reachGrid->getEntry(storeGlobalX, storeGlobalY);
675 float x = tmpRobotPoseGlobal(0, 3);
676 float y = tmpRobotPoseGlobal(1, 3);
677 float z = tmpRobotPoseGlobal(2, 3);
678 if (std::isnan(x) || std::isnan(y) || std::isnan(z))
683 tmpRobotPoseGlobal.block<3, 1>(0, 3) = Eigen::Vector3f::Zero();
685 transform = Eigen::Translation<float, 3>(x, y, z) * Eigen::AngleAxisf(storeGlobalYaw, Eigen::Vector3f(0, 0, 1));
686 tmpRobotPoseGlobal =
transform * tmpRobotPoseGlobal;
688 robot->setGlobalPose(tmpRobotPoseGlobal);
689 cspace->getAgentSceneObj()->setGlobalPose(tmpRobotPoseGlobal);
690 int max = wsr->getMaxEntry();
691 ARMARX_VERBOSE <<
"Candidate pose: " << 100. * wsr->getEntry(FramedPosePtr::dynamicCast(g.framedPrePose)->toEigen()) /
max <<
"% min. required: " << minRequiredEntry <<
" trial: " << counter * 100 / maxTrials <<
"%";
692 if (!wsr->isCovered(FramedPosePtr::dynamicCast(g.framedPrePose)->toEigen()))
698 collision = cspace->getCD().isInCollision();
699 if (minCollisionDistance > 0)
701 float distance = cspace->getCD().getDistance();
702 if (
distance < minCollisionDistance)
710 if (getProperty<bool>(
"EnableVisualization"))
712 updateRobot(collisionCheckVisu, tmpRobotPoseGlobal,
713 collision ? DrawColor {1.0, 0.0, 0.0, 1} : DrawColor {0.0, 1.0, 0.0, 1});
714 usleep(500000 * visuSlowdownFactor);
750 robot->setGlobalPose(originalRobotPoseGlobal);
754 std::vector<SimpleRobotPlacement::RobotPlacement> SimpleRobotPlacement::getSuitablePositions(
const GeneratedGrasp& g, WorkspaceGridPtr reachGrid,
const Eigen::Matrix4f& globalObjectPose,
float requiredReachabilityFraction,
int requiredCount,
int maxIterations,
const MathTools::ConvexHull2DPtr& placementArea)
757 std::vector<SimpleRobotPlacement::RobotPlacement> placements;
763 float minX, maxX, minY, maxY;
764 reachGrid->getExtends(minX, maxX, minY, maxY);
767 reachGrid->getCells(nX, nY);
768 int maxEntry = reachGrid->getMaxEntry();
769 int minRequiredEntry = maxEntry * requiredReachabilityFraction;
771 bool collision =
true;
772 std::vector<GraspPtr> dummyGrasps;
773 float minCollisionDistance = getProperty<float>(
"MinimumDistanceToEnvironment").getValue();
774 auto collisionCheckVisu =
"collisionCheckRobotVisu";
775 if (getProperty<bool>(
"EnableVisualization"))
777 entityDrawerPrx->setRobotVisu(visuLayerName, collisionCheckVisu, robotStateComponentPrx->getRobotFilename(), simox::alg::join(robotStateComponentPrx->getArmarXPackages(),
","), FullModel);
778 auto config = robotStateComponentPrx->getSynchronizedRobot()->getConfig();
780 entityDrawerPrx->updateRobotConfig(visuLayerName, collisionCheckVisu, config);
783 float visuSlowdownFactor = getProperty<float>(
"VisualizationSlowdownFactor");
786 for (
int n = 0; n < maxIterations; n++)
790 float storeGlobalX, storeGlobalY;
791 if (!reachGrid->getRandomPos(minRequiredEntry, storeGlobalX, storeGlobalY, dummyGrasps, 100, &entries))
795 float distance2D = (Eigen::Vector2f(storeGlobalX, storeGlobalY) - globalObjectPose.block<2, 1>(0, 3)).norm();
796 if (distance2D > 1000)
799 ARMARX_INFO <<
"Placement too far away: " << distance2D;
802 if (distance2D < 400)
804 ARMARX_INFO <<
"Placement too close: " << distance2D;
808 if (placementArea !=
nullptr && !VirtualRobot::MathTools::isInside(Eigen::Vector2f(storeGlobalX, storeGlobalY), placementArea))
810 ARMARX_INFO <<
"Generated placement (" << storeGlobalX <<
", " << storeGlobalY <<
") lies outside the permitted area => Retry.";
815 tmpRobotPoseGlobal = originalRobotPoseGlobal;
816 tmpRobotPoseGlobal(0, 3) = storeGlobalX;
817 tmpRobotPoseGlobal(1, 3) = storeGlobalY;
819 float storeGlobalYaw = getPlatformRotation(tmpRobotPoseGlobal, globalObjectPose);
820 float score = reachGrid->getEntry(storeGlobalX, storeGlobalY);
823 float x = tmpRobotPoseGlobal(0, 3);
824 float y = tmpRobotPoseGlobal(1, 3);
825 float z = tmpRobotPoseGlobal(2, 3);
826 if (std::isnan(x) || std::isnan(y) || std::isnan(z))
831 tmpRobotPoseGlobal.block<3, 1>(0, 3) = Eigen::Vector3f::Zero();
833 transform = Eigen::Translation<float, 3>(x, y, z) * Eigen::AngleAxisf(storeGlobalYaw, Eigen::Vector3f(0, 0, 1));
834 tmpRobotPoseGlobal =
transform * tmpRobotPoseGlobal;
836 robot->setGlobalPose(tmpRobotPoseGlobal);
837 cspace->getAgentSceneObj()->setGlobalPose(tmpRobotPoseGlobal);
838 int max = wsr->getMaxEntry();
839 ARMARX_VERBOSE <<
"Candidate pose: " << 100. * wsr->getEntry(FramedPosePtr::dynamicCast(g.framedPrePose)->toEigen()) /
max <<
"% min. required: " << minRequiredEntry;
840 if (!wsr->isCovered(FramedPosePtr::dynamicCast(g.framedPrePose)->toEigen()))
846 collision = cspace->getCD().isInCollision();
847 if (minCollisionDistance > 0)
849 float distance = cspace->getCD().getDistance();
850 if (
distance < minCollisionDistance)
858 if (getProperty<bool>(
"EnableVisualization"))
860 updateRobot(collisionCheckVisu, tmpRobotPoseGlobal,
861 collision ? DrawColor {1.0, 0.0, 0.0, 1} : DrawColor {0.0, 1.0, 0.0, 1});
862 usleep(500000 * visuSlowdownFactor);
874 pl.z = storeGlobalYaw;
876 placements.push_back(pl);
882 if ((
int)placements.size() > requiredCount)
888 ARMARX_INFO <<
"Found " << placements.size() <<
" collision free placements";
889 robot->setGlobalPose(originalRobotPoseGlobal);
896 float x = localTarget(0, 3);
897 float y = localTarget(1, 3);
899 float alpha = std::atan2(y, x);
904 void SimpleRobotPlacement::loadRobot()
906 robot = VirtualRobot::RobotIO::loadRobot(robotFilePath);
909 ARMARX_ERROR <<
"Failed to load robot: " << robotFilePath;
913 std::shared_ptr<RemoteRobot> remoteRobot(
new RemoteRobot(robotStateComponentPrx->getSynchronizedRobot()));
914 robot->setGlobalPose(remoteRobot->getGlobalPose());
917 void SimpleRobotPlacement::loadWorkspaces()
919 for (std::string wsFile : workspaceFilePaths)
921 VirtualRobot::WorkspaceRepresentationPtr newSpace;
927 newSpace.reset(
new Manipulability(robot));
928 newSpace->load(wsFile);
931 ARMARX_INFO <<
"Map '" << wsFile <<
"' loaded as Manipulability map";
942 newSpace.reset(
new Reachability(robot));
943 newSpace->load(wsFile);
946 ARMARX_INFO <<
"Map '" << wsFile <<
"' loaded as Reachability map";
956 workspaces.push_back(newSpace);
960 ARMARX_ERROR <<
"Failed to load map '" << wsFile <<
"'";
965 bool SimpleRobotPlacement::hasWorkspace(std::string tcp)
967 for (VirtualRobot::WorkspaceRepresentationPtr ws : workspaces)
969 if (ws->getTCP()->getName() == tcp)
977 GeneratedGraspList SimpleRobotPlacement::filterGrasps(
const GeneratedGraspList grasps)
979 GeneratedGraspList filteredGrasps = grasps;
980 GeneratedGraspList::iterator it = filteredGrasps.begin();
981 while (it != filteredGrasps.end())
983 GeneratedGrasp g = (*it);
984 auto tcpName = robot->getEndEffector(g.eefName)->getTcp()->getName();
985 if (!hasWorkspace(tcpName))
987 ARMARX_VERBOSE <<
"Removing grasp because tcp " << tcpName <<
" is not available in workspace";
988 it = filteredGrasps.erase(it);
995 return filteredGrasps;
1000 if (!getProperty<bool>(
"EnableVisualization"))
1004 static int suffix = 0;
1005 std::string
id = drawRobotId +
to_string(suffix++);
1006 entityDrawerPrx->setRobotVisu(visuLayerName,
id, robotStateComponentPrx->getRobotFilename(), simox::alg::join(robotStateComponentPrx->getArmarXPackages(),
","), FullModel);
1008 auto config = robotStateComponentPrx->getSynchronizedRobot()->getConfig();
1010 entityDrawerPrx->updateRobotConfig(visuLayerName,
id, config);
1011 updateRobot(
id, globalPose, COLOR_ROBOT);
1014 void SimpleRobotPlacement::updateRobot(std::string
id,
Eigen::Matrix4f globalPose, DrawColor color)
1016 if (!getProperty<bool>(
"EnableVisualization"))
1020 entityDrawerPrx->updateRobotColor(visuLayerName,
id, color);
1021 entityDrawerPrx->updateRobotPose(visuLayerName,
id,
new Pose(globalPose));
1024 void SimpleRobotPlacement::drawWorkspaceGrid(
const GeneratedGrasp& grasp,
const std::string& objectInstanceEntityId)
1026 if (!getProperty<bool>(
"EnableVisualization"))
1030 ObjectInstancePtr instance = ObjectInstancePtr::dynamicCast(objectInstances->getEntityById(objectInstanceEntityId));
1031 Eigen::Matrix4f objectPose = instance->getPose()->toGlobalEigen(robot);
1033 drawWorkspaceGrid(createWorkspaceGrid(grasp, objectPose));
1036 void SimpleRobotPlacement::drawWorkspaceGrid(VirtualRobot::WorkspaceGridPtr reachGrid)
1038 if (!getProperty<bool>(
"EnableVisualization"))
1044 float minX, maxX, minY, maxY;
1045 reachGrid->getExtends(minX, maxX, minY, maxY);
1051 reachGrid->getCells(nX, nY);
1053 int maxEntry = reachGrid->getMaxEntry();
1055 float sizeX = (maxX - minX) / (
float)nX;
1056 float sizeY = (maxY - minY) / (
float)nY;
1057 auto batch = debugDrawerPrx->ice_batchOneway();
1059 for (
int x = 0; x < nX; x++)
1061 float xPos = minX + (
float)x * sizeX + 0.5f * sizeX;
1063 for (
int y = 0; y < nY; y++)
1065 int cellEntry = reachGrid->getCellEntry(x, y);
1069 float intensity = (
float)cellEntry / (
float)maxEntry;
1071 float yPos = minY + (
float)y * sizeY + 0.5f * sizeY;
1078 VirtualRobot::ColorMap cm = VirtualRobot::ColorMap::eHot;
1081 armarx::DrawColor voxelColor;
1082 voxelColor.r = color.r;
1083 voxelColor.g = color.g;
1084 voxelColor.b = color.b;
1087 batch->setBoxVisu(visuLayerName,
"reachGridVoxel_" +
to_string(counter++),
1088 tmpPose, dimensions, voxelColor);
1092 batch->ice_flushBatchRequests();