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