SemanticRelationAnalyzer.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package VisionX::ArmarXObjects::SemanticRelationAnalyzer
17  * @author Fabian Paus ( fabian dot paus at kit dot edu )
18  * @date 2019
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
25 #include <VirtualRobot/CollisionDetection/CollisionChecker.h>
26 #include <VirtualRobot/CollisionDetection/CollisionCheckerImplementation.h>
27 #include <VirtualRobot/CollisionDetection/CollisionModel.h>
28 #include <VirtualRobot/ManipulationObject.h>
29 #include <VirtualRobot/Visualization/TriMeshModel.h>
30 
32 
37 
38 #include <SemanticObjectRelations/Shapes/json/ShapeSerializers.h>
39 #include <SemanticObjectRelations/SupportAnalysis/json.h>
40 #include <SemanticObjectRelations/Visualization/ContactDetectionVisualizer.h>
41 #include <SemanticObjectRelations/Visualization/SupportAnalysisVisualizer.h>
42 
43 namespace armarx
44 {
46  std::string prefix) :
48  {
49  defineOptionalProperty<std::string>(
50  "WorkingMemoryName", "WorkingMemory", "Name of WorkingMemory component");
51  defineOptionalProperty<std::string>(
52  "PriorKnowledgeName", "PriorKnowledge", "Name of PriorKnowledge component");
53  defineOptionalProperty<std::string>("RobotStateComponentName",
54  "RobotStateComponent",
55  "Name of RobotStateComponent component");
56  defineOptionalProperty<std::string>(
57  "DebugDrawerTopicName", "DebugDrawerUpdates", "The name of the debug drawer topic");
58  defineOptionalProperty<int>("UpdatePeriodInMS", 10, "Update period in ms");
59 
60  defineOptionalProperty<semrel::VisuLevel>(
61  "VisuLevel",
62  semrel::VisuLevel::RESULT,
63  "Visualization level: Determines what is shown in the debug drawer\n"
64  "Possible values: live, verbose, result, user, disabled")
65  .map("live", semrel::VisuLevel::LIVE_VISU)
66  .map("verbose", semrel::VisuLevel::VERBOSE)
67  .map("result", semrel::VisuLevel::RESULT)
68  .map("user", semrel::VisuLevel::USER)
69  .map("disabled", semrel::VisuLevel::DISABLED);
70 
71  defineOptionalProperty<float>(
72  "ContactMarginInMM", 5.0f, "Margin (mm) used during contact detection between objects");
73  }
74 
75  static semrel::ContactPointList
76  calculateContactPoints(semrel::ShapeList const& objects)
77  {
78  semrel::ContactPointList result;
79 
80  VirtualRobot::CollisionCheckerPtr collisionChecker =
81  VirtualRobot::CollisionChecker::getGlobalCollisionChecker();
82  for (std::size_t i = 0; i < objects.size(); ++i)
83  {
85  dynamic_cast<armarx::semantic::SimoxObjectShape const&>(*objects[i]);
86  for (std::size_t j = i + 1; j < objects.size(); ++j)
87  {
89  dynamic_cast<armarx::semantic::SimoxObjectShape const&>(*objects[j]);
90  Eigen::Affine3f poseB(shapeB.object->getGlobalPose());
91 
92  VirtualRobot::CollisionModelPtr collModelA = shapeA.object->getCollisionModel();
93  VirtualRobot::CollisionModelPtr collModelB = shapeB.object->getCollisionModel();
94  VirtualRobot::MultiCollisionResult collisions =
95  collisionChecker->checkMultipleCollisions(collModelA, collModelB);
96 
97  //auto& facesA = collModelA->getTriMeshModel()->faces;
98  auto& facesB = collModelB->getTriMeshModel()->faces;
99  auto& normalsB = collModelB->getTriMeshModel()->normals;
100  for (VirtualRobot::SingleCollisionPair const& collision : collisions.pairs)
101  {
102  //VirtualRobot::MathTools::TriangleFace const& faceOnA = facesA.at(collision.id1);
103  VirtualRobot::MathTools::TriangleFace const& faceOnB = facesB.at(collision.id2);
104 
105  Eigen::Vector3f globalPointOnB = collision.contact2;
106 
107  Eigen::Vector3f localNormalOnB;
108  if (faceOnB.idNormal1 == UINT_MAX)
109  {
110  localNormalOnB = poseB.linear() * faceOnB.normal;
111  }
112  else
113  {
114  Eigen::Vector3f n1B = normalsB[faceOnB.idNormal1];
115  Eigen::Vector3f n2B = normalsB[faceOnB.idNormal2];
116  Eigen::Vector3f n3B = normalsB[faceOnB.idNormal3];
117 
118  localNormalOnB = (n1B + n2B + n3B).normalized();
119  }
120  Eigen::Vector3f globalNormalOnB = poseB.linear() * localNormalOnB;
121 
122  result.emplace_back(&shapeA, &shapeB, globalPointOnB, globalNormalOnB);
123  }
124  }
125  }
126 
127  return result;
128  }
129 
130  static void
131  filterObjectsWithoutCollisionModel(std::vector<memoryx::ObjectInstanceWrapper>& objects)
132  {
133  // Filter out object without collision model
134  auto removeIter = std::remove_if(
135  objects.begin(),
136  objects.end(),
137  [](memoryx::ObjectInstanceWrapper const& object)
138  {
139  // Check whether this thing has a collision model
140  if (object.manipulationObject->getCollisionModel())
141  {
142  if (object.manipulationObject->getCollisionModel()->getTriMeshModel())
143  {
144  return false;
145  }
146  else
147  {
148  ARMARX_WARNING_S << "No tri-mesh model in '"
149  << object.instanceInMemory->getMostProbableClass() << "'";
150  }
151  }
152  else
153  {
154  ARMARX_WARNING_S << "No collision model in '"
155  << object.instanceInMemory->getMostProbableClass() << "'";
156  }
157  return true;
158  });
159  objects.erase(removeIter, objects.end());
160  }
161 
163  SemanticRelationAnalyzer::extractSupportGraphFromWorkingMemory(const Ice::Current&)
164  {
165  std::lock_guard<std::mutex> lock(componentMutex);
166 
167  std::vector<memoryx::ObjectInstanceWrapper> objectInstances =
168  objectInstancesSegment_.queryObjects();
169  filterObjectsWithoutCollisionModel(objectInstances);
170 
171  semrel::ShapeList shapes;
172  std::set<semrel::ShapeID> safeShapes;
173  std::set<std::string> safeObjectClassNames = {"workbench", "booth"};
174 
175  std::vector<std::string> names;
176  int uniqueID = 0;
177  for (auto& object : objectInstances)
178  {
179  std::string objectClass = object.instanceInMemory->getMostProbableClass();
180  // Here we have the manipulation object, i.e. mesh of the object
181  if (safeObjectClassNames.count(objectClass) > 0)
182  {
183  ARMARX_IMPORTANT << "Adding safe object: " << object.instanceInMemory->getName();
184  safeShapes.insert(semrel::ShapeID{uniqueID});
185  }
186  object.manipulationObject->getCollisionModel()->inflateModel(prop_ContactMarginInMM);
187  std::unique_ptr<semantic::SimoxObjectShape> shape =
188  std::make_unique<semantic::SimoxObjectShape>(object.manipulationObject,
189  objectClass);
190  shape->entityId = object.instanceInMemory->getId();
191 
192  shape->setID(semrel::ShapeID{uniqueID});
193  uniqueID += 1;
194  shapes.push_back(std::move(shape));
195  }
196 
197  ARMARX_INFO << deactivateSpam(1) << "Object instances (" << shapes.size() << "): " << names;
198 
199  // Do the contact detection our own way (for now)
200  semrel::ContactPointList contactPoints = calculateContactPoints(shapes);
201  semrel::ContactGraph contactGraph = semrel::buildContactGraph(contactPoints, shapes);
202  //semrel::SupportAnalysisVisualizer& visu = semrel::SupportAnalysisVisualizer::get();
203  semrel::ContactDetectionVisualizer& visu = semrel::ContactDetectionVisualizer::get();
204  visu.drawContactPoints(contactPoints);
205 
206  semrel::SupportGraph supportGraph =
207  supportAnalysis.performSupportAnalysis(shapes, safeShapes, &contactGraph);
208  ARMARX_IMPORTANT << "Supprt graph:\n" << supportGraph;
209 
210  // , semantic::JsonSimoxShapeSerializer()
211  semrel::AttributedGraph attributedGraph = semrel::toAttributedGraph(supportGraph);
212  attributedGraph.serializeObjects(semrel::toShapeMap(shapes));
213  semantic::data::Graph iceGraph = armarx::semantic::toIce(attributedGraph);
214  getGraphStorageTopic()->begin_reportGraph("Support", iceGraph);
215 
216  memoryx::RelationList relations = semantic::toMemory(attributedGraph);
217  relationSegment->replaceRelations(relations);
218 
219  return iceGraph;
220  }
221 
222 #define GET_PROP(name) prop_##name = getProperty<decltype(prop_##name)>(#name).getValue()
223 
224  void
225  SemanticRelationAnalyzer::onInitComponent()
226  {
227  // Register shape serializer for
228 
229  GET_PROP(WorkingMemoryName);
230  GET_PROP(PriorKnowledgeName);
231  GET_PROP(RobotStateComponentName);
232  GET_PROP(DebugDrawerTopicName);
233  GET_PROP(UpdatePeriodInMS);
234  GET_PROP(ContactMarginInMM);
235 
236  offeringTopic(prop_DebugDrawerTopicName);
237 
238  semantic::ArmarXLog::setAsImplementation(getName());
239  }
240 
241  void
242  SemanticRelationAnalyzer::onConnectComponent()
243  {
244  workingMemory = getProxy<memoryx::WorkingMemoryInterfacePrx>(prop_WorkingMemoryName);
245  priorKnowledge = getProxy<memoryx::PriorKnowledgeInterfacePrx>(prop_PriorKnowledgeName);
246  robotStateComponent =
247  getProxy<RobotStateComponentInterfacePrx>(prop_RobotStateComponentName);
248  debugDrawer = getTopic<DebugDrawerInterfacePrx>(prop_DebugDrawerTopicName);
249 
250  semantic::ArmarXVisualizer::setAsImplementation(debugDrawer);
251  semrel::VisuLevel visuLevel = getProperty<semrel::VisuLevel>("VisuLevel").getValue();
252  semrel::VisualizerInterface::get().setMinimumVisuLevel(visuLevel);
253 
254  relationSegment = workingMemory->getRelationsSegment();
255  objectInstancesSegment_.initFromProxies(priorKnowledge, workingMemory, robotStateComponent);
256 
257  jsonSerializer.reset(
258  new semantic::JsonSimoxShapeSerializer(&objectInstancesSegment_.objectClassSegment));
259  semantic::JsonSimoxShapeSerializer::registerSerializer(jsonSerializer, true);
260 
261  // We call the method once for test purposes
262  extractSupportGraphFromWorkingMemory(Ice::Current());
263 
265  this, &SemanticRelationAnalyzer::update, prop_UpdatePeriodInMS);
266  updateTask->start();
267  }
268 
269  void
270  SemanticRelationAnalyzer::onDisconnectComponent()
271  {
272  updateTask->stop();
273  updateTask = nullptr;
274  }
275 
276  void
277  SemanticRelationAnalyzer::onExitComponent()
278  {
279  }
280 
282  SemanticRelationAnalyzer::createPropertyDefinitions()
283  {
285  new SemanticRelationAnalyzerPropertyDefinitions(getConfigIdentifier()));
286  }
287 
288  static std::string const LAYER_NAME = "SemanticRelationAnalyzer";
289 
290  void
292  {
293  // extractSupportGraphFromWorkingMemory(Ice::Current());
294  }
295 
296 } // namespace armarx
hooks.h
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
memory_serialization.h
armarx::SemanticRelationAnalyzerPropertyDefinitions::SemanticRelationAnalyzerPropertyDefinitions
SemanticRelationAnalyzerPropertyDefinitions(std::string prefix)
Definition: SemanticRelationAnalyzer.cpp:45
GetTypeString.h
armarx::SemanticRelationAnalyzerPropertyDefinitions
Definition: SemanticRelationAnalyzer.h:50
armarx::armem::wm::toMemory
void toMemory(Memory &m, const std::vector< CoreSegment > &e)
Definition: memory_conversions.cpp:6
armarx::semantic::toIce
data::Graph toIce(const semrel::AttributedGraph &input)
Definition: graph.cpp:15
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
SemanticRelationAnalyzer.h
armarx::Graph
boost::subgraph< CloudGraph > Graph
Definition: Common.h:58
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:68
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
armarx::viz::data::ElementFlags::names
const simox::meta::IntEnumNames names
Definition: json_elements.cpp:13
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle< class PropertyDefinitionContainer >
memoryx::ObjectInstanceWrapper
Definition: ObjectInstanceSegmentWrapper.h:17
ice_serialization.h
armarx::PeriodicTask
Definition: ArmarXManager.h:70
GET_PROP
#define GET_PROP(name)
Definition: SemanticRelationAnalyzer.cpp:222
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
shapes
MiscLib::Vector< std::pair< MiscLib::RefCountPtr< PrimitiveShape >, size_t > > shapes
Definition: ReadMe.txt:92
armarx::semantic::SimoxObjectShape
Definition: SimoxObjectShape.h:10
SimoxObjectShape.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::semantic::SimoxObjectShape::object
VirtualRobot::ManipulationObjectPtr object
Definition: SimoxObjectShape.h:37