LoadObjectsIntoMemoryWidgetController.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 ARCHES::gui-plugins::LoadObjectsIntoMemoryWidgetController
17 * \author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * \date 2018
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23
25
26#include <chrono>
27#include <filesystem>
28#include <string>
29
30#include <VirtualRobot/CollisionDetection/CollisionModel.h>
31#include <VirtualRobot/Visualization/TriMeshUtils.h>
32#include <VirtualRobot/Visualization/VisualizationNode.h>
33
35
38
39using namespace armarx;
40
42{
43 widget.setupUi(getWidget());
44 connect(widget.pushButtonAddObjects, SIGNAL(clicked()), this, SLOT(addObjects()));
45}
46
47void
49{
50 priorPrx =
51 getProxy<memoryx::PriorKnowledgeInterfacePrx>(dialog->getProxyName("PriorKnowledge"));
52 classesSegmentPrx = priorPrx->getObjectClassesSegment();
53
54 databasePrx = priorPrx->getCommonStorage();
55 fileManager.reset(new memoryx::GridFileManager(databasePrx));
56 QMetaObject::invokeMethod(this, "updateDBs", Qt::QueuedConnection);
57}
58
59QPointer<QDialog>
61{
62 if (!dialog)
63 {
64 dialog = new SimpleConfigDialog(parent);
65 dialog->addProxyFinder<memoryx::PriorKnowledgeInterfacePrx>(
66 {"PriorKnowledge", "PriorKnowledge", "PriorKnowledge*"});
67 }
68 return qobject_cast<SimpleConfigDialog*>(dialog);
69}
70
71void
73{
74 const NameList dbNames = databasePrx->getDBNames();
75 widget.comboBoxDBs->clear();
76 for (const auto& db : dbNames)
77 {
78 widget.comboBoxDBs->addItem(QString::fromStdString(db));
79 }
80 ARMARX_INFO << "setting list of DBs to: " << dbNames;
81}
82
83void
85{
86 namespace fs = std::filesystem;
87
88 const std::string dir = widget.lineEditDir->text().toStdString();
89 const std::string collection = widget.lineEditCollection->text().toStdString();
90 const std::string db = widget.comboBoxDBs->currentText().toStdString();
91 const std::string tmpdir =
92 "/tmp/LoadObjectsIntoMemoryWidget/" +
93 std::to_string(std::chrono::high_resolution_clock::now().time_since_epoch().count()) + "/";
94
95 fs::create_directories(tmpdir);
96
97 ARMARX_CHECK_EXPRESSION(!dir.empty());
98 ARMARX_CHECK_EXPRESSION(fs::exists(dir));
99 ARMARX_CHECK_EQUAL(collection.empty(), db.empty());
100
101 //set write collection
102 if (!collection.empty())
103 {
104 const std::string fullCollectionName = db + "." + collection;
105 ARMARX_INFO << "setting write collection to: " << fullCollectionName;
106 memoryx::CollectionInterfacePrx coll = databasePrx->requestCollection(fullCollectionName);
108 classesSegmentPrx->setWriteCollection(coll);
109 ARMARX_INFO << "setting write collection done";
110 }
111
112 for (fs::directory_iterator dit{dir}; dit != fs::directory_iterator{}; ++dit)
113 {
114 const fs::path p = *dit;
115 if (!fs::is_regular_file(p))
116 {
117 ARMARX_INFO << "skipping non file " << p;
118 continue;
119 }
120 const std::string fname = p.filename().string();
121 const std::string fpath = p.string();
122 const auto endswith = [&](const std::string& suff)
123 {
124 const auto pos = fname.rfind(suff);
125 return pos != std::string::npos && pos == (fname.size() - suff.size());
126 };
127 std::string className = fname;
128
129
130 //trim name
131 {
132 if (widget.radioButtonWRL->isChecked())
133 {
134 if (endswith(".wrl"))
135 {
136 className = className.substr(0, className.size() - 4);
137 }
138 else if (endswith(".iv"))
139 {
140 className = className.substr(0, className.size() - 3);
141 }
142 else
143 {
144 ARMARX_INFO << "skipping non wrl/iv file " << p;
145 continue;
146 }
147 }
148 else
149 {
150 if (endswith(".xml"))
151 {
152 className = className.substr(0, className.size() - 4);
153 }
154 else
155 {
156 ARMARX_INFO << "skipping non xml file " << p;
157 continue;
158 }
159 }
160 ARMARX_INFO << "processing file " << p;
161 }
162
163 memoryx::ObjectClassPtr objectClass;
164 const bool isNewClass = !classesSegmentPrx->hasEntityByName(className);
165 {
166 if (!isNewClass)
167 {
168 if (!widget.checkBoxOverride->isChecked())
169 {
170 ARMARX_INFO << "object class " << className << " already exists in memory";
171 continue;
172 }
173 objectClass = memoryx::ObjectClassPtr::dynamicCast(
174 classesSegmentPrx->getEntityByName(className));
175 ARMARX_CHECK_NOT_NULL(objectClass);
176 }
177 else
178 {
179 objectClass = new memoryx::ObjectClass();
180 }
181 }
182
183 //wrappers
184 objectClass->addWrapper(new memoryx::EntityWrappers::SimoxObjectWrapper(fileManager));
185
186 //set attributes
187 {
188 objectClass->setName(className);
189 objectClass->clearParentClasses();
190 {
191 const std::string parentClass = widget.lineEditParentClass->text().toStdString();
192 if (!parentClass.empty())
193 {
194 objectClass->addParentClass(parentClass);
195 }
196 }
197 objectClass->setInstanceable(true);
198 }
199
200 //update simox data
201 {
202 // VirtualRobot::ManipulationObject
203
205 objectClass->getWrapper<memoryx::EntityWrappers::SimoxObjectWrapper>();
206 if (widget.radioButtonWRL->isChecked())
207 {
208 ARMARX_INFO << "setting wrl as model";
209 simoxWrapper->setAndStoreModelIVFiles(fpath, fpath, getFilesDBName());
210 }
211 else
212 {
213 ARMARX_INFO << "reading simox xml";
214 simoxWrapper->setAndStoreManipulationFile(fpath, getFilesDBName());
215 }
216 if (widget.checkBoxScale->isChecked() || widget.checkBoxBBDensity->isChecked())
217 {
218 bool change = false;
219 Eigen::Vector3f bbmin;
220 Eigen::Vector3f bbmax;
221 auto mo = simoxWrapper->getManipulationObject();
222 auto col = mo->getCollisionModel();
223 ARMARX_CHECK_EXPRESSION(col->getTriMeshModel()->getSize(bbmin, bbmax));
224 Eigen::Vector3f bbsz = bbmax - bbmin;
225
226 if (widget.checkBoxBBDensity->isChecked())
227 {
228 const float vol = bbsz(0) * bbsz(1) * bbsz(2);
229 const float mass = vol * widget.doubleSpinBoxBBDensity->value();
230 if (mo->getMass() == mass)
231 {
232 change = true;
233 mo->setMass(mass);
234 }
235 }
236 if (widget.checkBoxScale->isChecked())
237 {
238 const double sidesz = bbsz(widget.spinBoxScaleDim->value());
239 bool doScale = false;
240 float factor = 1;
241 if (sidesz > widget.doubleSpinBoxScaleMax->value())
242 {
243 change = true;
244 doScale = true;
245 factor = widget.doubleSpinBoxScaleMax->value() / sidesz;
246 }
247 else if (sidesz < widget.doubleSpinBoxScaleMin->value())
248 {
249 change = true;
250 doScale = true;
251 factor = widget.doubleSpinBoxScaleMin->value() / sidesz;
252 }
253 if (doScale)
254 {
255 ARMARX_INFO << "scaling mesh with factor " << factor;
256 const Eigen::Vector3f scalev{factor, factor, factor};
257 auto triNew = col->getTriMeshModel()->clone(scalev);
258 auto moNew = VirtualRobot::ManipulationObject::createFromMesh(triNew);
259 moNew->setMass(mo->getMass());
260 moNew->setInertiaMatrix(mo->getInertiaMatrix());
261 moNew->setCoMLocal(mo->getCoMLocal());
262 const std::string meshName = tmpdir + className + ".wrl";
263 moNew->getVisualization()->setFilename(meshName, false);
264 moNew->getCollisionModel()->getVisualization()->setFilename(meshName,
265 false);
266 mo = moNew;
267 }
268 }
269 if (change)
270 {
271 mo->setName(className);
272 mo->saveModelFiles(tmpdir, false);
273 const std::string tmpxml = tmpdir + className + ".xml";
274 std::ofstream{tmpxml} << mo->toXML(tmpdir);
275
276 ARMARX_INFO << "reading generated xml";
277 simoxWrapper->setAndStoreManipulationFile(tmpxml, getFilesDBName());
278 }
279 }
280 }
281
282 //add or update
283 if (!widget.checkBoxDryRun->isChecked())
284 {
285 if (isNewClass)
286 {
287 ARMARX_INFO << "adding " << className;
288 const std::string id = classesSegmentPrx->addEntity(objectClass);
289 ARMARX_IMPORTANT << "added class " << objectClass << " with id " << id;
290 }
291 else
292 {
293 ARMARX_INFO << "updating " << className;
294 const std::string id = objectClass->getId();
295 classesSegmentPrx->updateEntity(id, objectClass);
296 ARMARX_IMPORTANT << "updated class " << objectClass << " with id " << id;
297 }
298 }
299 }
300}
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
virtual QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
A config-dialog containing one (or multiple) proxy finders.
SimoxObjectWrapper offers a simplified access to the Simox ManipulationObject (i.e visualization,...
GridFileManager provides utility functions for working with files in Mongo GridFS and links to them s...
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< SimoxObjectWrapper > SimoxObjectWrapperPtr
IceInternal::Handle< ObjectClass > ObjectClassPtr
Definition ObjectClass.h:35