ClutteredSceneGeneratorWidgetController.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 ArmarXSimulation::gui-plugins::ClutteredSceneGeneratorWidgetController
17 * \author Patrick Hegemann ( patrick dot hegemann at kit dot edu )
18 * \date 2021
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <algorithm>
26#include <filesystem>
27#include <iterator>
28#include <optional>
29
30#include <glob.h>
31
32#include <boost/algorithm/string/predicate.hpp>
33
34#include <QFlags>
35#include <QListWidget>
36#include <qnamespace.h>
37
40
43
44namespace armarx
45{
47 {
48 widget_.setupUi(getWidget());
49
50 // TODO(patrick.hegemann): Refactor
51 // armarx::CMakePackageFinder finder("ArmarXSimulation");
52 // std::filesystem::path objectSetsPath = finder.getDataDir();
53 // objectSetsPath /= "ArmarXSimulation/random_objects";
54 // ARMARX_INFO << "Finding object sets in " << objectSetsPath;
55 // QString pathText(objectSetsPath.c_str());
56 // widget_.lineEditObjectsOutputPath->setText(pathText);
57 // widget_.lineEditObjectsInputPath->setText(pathText);
58
60
62 }
63
65
66 void
70
71 void
75
76 void
81
82 void
84 {
85 // Scene generation tab
86 connect(widget_.pushButtonRefreshObjectSets,
87 &QPushButton::clicked,
88 this,
90 connect(widget_.pushButtonGenerateNewScene,
91 &QPushButton::clicked,
92 this,
94
95 connect(widget_.checkBoxAutoPoseConstraints,
96 &QCheckBox::stateChanged,
97 this,
99 connect(widget_.spinBoxTableX,
100 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
101 this,
103 connect(widget_.spinBoxTableY,
104 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
105 this,
107 connect(widget_.spinBoxTableZ,
108 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
109 this,
111 connect(widget_.spinBoxTableW,
112 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
113 this,
115 connect(widget_.spinBoxTableH,
116 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
117 this,
119 connect(widget_.spinBoxTableD,
120 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
121 this,
123
124 simulator_ = getProxy<SimulatorInterfacePrx>(simulatorProxyName_);
125 }
126
127 void
131
132 std::map<std::string, simulation::scene_generation::ObjectSet>
133 ClutteredSceneGeneratorWidgetController::getObjectSets(const armarx::PackagePath& packagePath)
134 {
135 const auto& directoryPackagePath = packagePath.serialize();
136 std::map<std::string, simulation::scene_generation::ObjectSet> sets;
137
138 // TODO(patrick.hegemann): Refactor
139 ARMARX_INFO << "Finding objects in " << packagePath.toSystemPath();
140
141 for (const auto& setEntry : std::filesystem::directory_iterator(packagePath.toSystemPath()))
142 {
143 if (!setEntry.is_directory())
144 {
145 continue;
146 }
147 const std::string setName = setEntry.path().filename();
148
149 std::vector<simulation::scene_generation::ObjectSource> objectSources;
150 for (const auto& objectEntry : std::filesystem::directory_iterator(setEntry.path()))
151 {
152 if (objectEntry.path().extension().string() == ".xml")
153 {
154 std::filesystem::path newPath(directoryPackagePath.path);
155 newPath /= setName / objectEntry.path().filename();
156 PackagePath objectPackagePath(directoryPackagePath.package, newPath);
157
158 simulation::scene_generation::ObjectSource objectSource = {
159 .path = objectPackagePath,
161 .objectID = std::nullopt};
162 objectSources.push_back(objectSource);
163 }
164 }
165 simulation::scene_generation::ObjectSet currentObjectSet{.objects = objectSources};
166
167 sets[setName] = currentObjectSet;
168 ARMARX_INFO << "added set " << setName;
169 }
170
171 return sets;
172 }
173
174 void
176 {
177 // boost::filesystem::path path(widget_.lineEditObjectsInputPath->text().toStdString());
178 PackagePath path("ArmarXSimulation", "random_objects");
179 objectSets_ = getObjectSets(path);
180
181 // Clear list and delete all old items
182 widget_.listWidgetObjectSets->clear();
183 objectSetListItems_.clear();
184 for (auto& item : objectSetListItems_)
185 {
186 delete item;
187 }
188
189 // Fill list widget
190 for (const auto& [setName, _] : objectSets_)
191 {
192 auto* item = new QListWidgetItem;
193 objectSetListItems_.push_back(item);
194
195 // TODO(patrick.hegemann): Find a standard method to get the name of a directory
196 std::string basename = setName.substr(setName.find_last_of('/') + 1);
197 item->setText(QString::fromStdString(basename));
198 item->setData(1, QString::fromStdString(setName));
199 item->setFlags((item->flags() | Qt::ItemIsUserCheckable) & ~Qt::ItemIsSelectable);
200 item->setCheckState(Qt::Checked);
201 widget_.listWidgetObjectSets->addItem(item);
202 }
203 }
204
205 void
207 {
208 if (widget_.checkBoxAutoPoseConstraints->isChecked())
209 {
210 const double tableX = widget_.spinBoxTableX->value();
211 const double tableY = widget_.spinBoxTableY->value();
212 const double tableZ = widget_.spinBoxTableZ->value();
213 const double tableW = widget_.spinBoxTableW->value();
214 const double tableH = widget_.spinBoxTableH->value();
215 const double tableD = widget_.spinBoxTableD->value();
216 const double margin = widget_.spinBoxMarginBoxWalls->value();
217
218 const double minX = tableX - tableW / 2 + margin;
219 const double minY = tableY - tableH / 2 + margin;
220 const double maxX = tableX + tableW / 2 - margin;
221 const double maxY = tableY + tableH / 2 - margin;
222 const double minZ = tableZ + tableD + 150;
223
224 widget_.spinBoxObjectMinX->setValue(minX);
225 widget_.spinBoxObjectMinY->setValue(minY);
226 widget_.spinBoxObjectMaxX->setValue(maxX);
227 widget_.spinBoxObjectMaxY->setValue(maxY);
228 widget_.spinBoxObjectMinZ->setValue(minZ);
229 }
230 }
231
232 void
234 {
235 simulation::scene_generation::ClutteredSceneGenerator generator(simulator_, getGenConfig());
236 int seed = widget_.spinBoxSceneSeed->value();
237 generator.generateScene(seed);
238 }
239
241 ClutteredSceneGeneratorWidgetController::getGenConfig()
242 {
244
245 // Set selected object sets
246 std::vector<simulation::scene_generation::ObjectSet> selectedSets;
247
248 for (int i = 0; i < widget_.listWidgetObjectSets->count(); ++i)
249 {
250 auto* item = widget_.listWidgetObjectSets->item(i);
251 if (item->checkState() == Qt::CheckState::Checked)
252 {
253 std::string setPath = item->data(1).toString().toStdString();
254 selectedSets.push_back(objectSets_[setPath]);
255 }
256 }
257 genConfig.objectSets = selectedSets;
258
259 genConfig.amountObjects = widget_.spinBoxSceneObjectAmount->value();
260 // genConfig.objectsPerSetLimit = widget_.checkBoxLimitOnePerSet->isChecked() ? 1 : 0;
261 genConfig.fallingSteps = widget_.spinBoxObjectFallingSteps->value();
262 genConfig.autoResetInvalidObjects = widget_.checkBoxResetInvalidObjects->isChecked();
263 genConfig.maxResetTries = widget_.spinBoxMaxResetAttempts->value();
264
265 genConfig.boxX = static_cast<float>(widget_.spinBoxTableX->value());
266 genConfig.boxY = static_cast<float>(widget_.spinBoxTableY->value());
267 genConfig.boxZ = static_cast<float>(widget_.spinBoxTableZ->value());
268 genConfig.boxW = static_cast<float>(widget_.spinBoxTableW->value());
269 genConfig.boxH = static_cast<float>(widget_.spinBoxTableH->value());
270 genConfig.boxD = static_cast<float>(widget_.spinBoxTableD->value());
271
272 genConfig.objectMarginSide = static_cast<float>(widget_.spinBoxMarginBoxWalls->value());
273 genConfig.objectSpacingZ = static_cast<float>(widget_.spinBoxObjectSpacingZ->value());
274
275 genConfig.minObjectX = static_cast<float>(widget_.spinBoxObjectMinX->value());
276 genConfig.minObjectY = static_cast<float>(widget_.spinBoxObjectMinY->value());
277 genConfig.minObjectZ = static_cast<float>(widget_.spinBoxObjectMinZ->value());
278 genConfig.maxObjectX = static_cast<float>(widget_.spinBoxObjectMaxX->value());
279 genConfig.maxObjectY = static_cast<float>(widget_.spinBoxObjectMaxY->value());
280
281 genConfig.minObjectZOtherwiseReset =
282 static_cast<float>(widget_.spinBoxZPosResetting->value());
283
284 return genConfig;
285 }
286} // namespace armarx
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
virtual ~ClutteredSceneGeneratorWidgetController()
Controller destructor.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
void setName(std::string name)
Override name of well-known object.
data::PackagePath serialize() const
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
Brief description of class ClutteredSceneGenerator.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
This file offers overloads of toIce() and fromIce() functions for STL container types.
uint fallingSteps
Number of simulation steps executed for letting objects fall onto the table.
uint maxResetTries
Maximum number of retries when resetting objects.
bool autoResetInvalidObjects
Whether to automatically reset invalid objects after scene generation.