Component.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::ArmarXObjects::cluttered_scene_generator
17 * @author Patrick Hegemann ( 335495-patrickhegemann at users dot noreply dot gitlab dot com )
18 * @date 2022
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "Component.h"
24
25#include <algorithm>
26#include <iterator>
27
28#include <Eigen/src/Core/Matrix.h>
29#include <Eigen/src/Geometry/Quaternion.h>
30
31#include <SimoxUtility/json/io.h>
32#include <SimoxUtility/math/pose/pose.h>
33
37
44
45#include <ArmarXSimulation/interface/simulator/SimulatorInterface.h>
48
50{
51 const std::string Component::defaultName = "ClutteredSceneGenerator";
52
55 {
58
59 // Use (and depend on) another component (passing the ComponentInterfacePrx).
60 def->component(simulator_);
61 def->component(objectMemoryToSimulation_);
62
63 // Add a required property. (The component won't start without a value being set.)
64 // def->required(properties.boxLayerName, "p.box.LayerName", "Name of the box layer in ArViz.");
65
66 def->optional(properties_.out.packageName, "p.out.packageName");
67 def->optional(properties_.out.packagePath, "p.out.packagePath");
68
69 def->optional(properties_.gen.initialSeed,
70 "p.initialSeed",
71 "Initial random seed for scene generation");
72
73 def->optional(properties_.gen.nScenes, "p.gen.nScenes", "Number of scenes to generate");
74 def->optional(properties_.gen.nObjects, "p.gen.nObjects", "Number of objects to generate");
75 def->optional(properties_.gen.verticalSpacing,
76 "p.gen.verticalSpacing",
77 "Vertical spacing between objects as they are generated");
78 // def->op
79
80 return def;
81 }
82
83 void
87
88 void
90 {
92 // Do things after connecting to topics and components.
93
94 /* (Requires the armarx::ArVizComponentPluginUser.)
95 // Draw boxes in ArViz.
96 // (Before starting any threads, we don't need to lock mutexes.)
97 drawBoxes(properties, arviz);
98 */
99
100 /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
101 // Setup the remote GUI.
102 {
103 createRemoteGuiTab();
104 RemoteGui_startRunningTask();
105 }
106 */
107
108 scene_generation::ObjectSet objectClasses = getObjectClasses();
109
110 // TODO(patrick.hegemann): Refactor
112 .objectSets = {objectClasses},
113 .amountObjects = properties_.gen.nObjects,
114 .objectSpacingZ = properties_.gen.verticalSpacing,
115 .minObjectX = -200,
116 .minObjectY = 800,
117 .maxObjectX = 200,
118 .maxObjectY = 1200,
119 .minObjectZ = 1000,
120 };
121
122 for (uint i = 0; i < properties_.gen.nScenes; ++i)
123 {
124 simulator_->reInitialize();
125 objectMemoryToSimulation_->synchronizeSimulator();
126
127 int seed = properties_.gen.initialSeed + static_cast<int>(i);
128 generateScene(config, seed);
129
130 objects::Scene scene = getScene();
131
132 if (!properties_.out.packageName.empty() && !properties_.out.packagePath.empty())
133 {
134 armarx::PackagePath path(properties_.out.packageName, properties_.out.packagePath);
135 std::filesystem::path sceneFileName =
136 path.toSystemPath() / ("scene_" + std::to_string(i) + ".json");
137 storeScene(scene, sceneFileName);
138 }
139 }
140 }
141
142 void
146
147 void
151
152 std::string
154 {
155 return Component::defaultName;
156 }
157
158 std::string
160 {
161 return Component::defaultName;
162 }
163
165 toPackagePath(const armarx::PackageFileLocation& packageFileLocation)
166 {
167 return {packageFileLocation.package, packageFileLocation.relativePath};
168 }
169
171 Component::getObjectClasses()
172 {
175
176 ObjectFinder f;
177 std::vector<ObjectInfo> objectInfos = f.findAllObjectsOfDataset("KIT");
178
179 auto makeObjectSource = [&](const ObjectInfo& info)
180 {
182 .path = toPackagePath(info.simoxXML()),
184 .objectID = info.id()};
185 };
186
187 std::transform(objectInfos.begin(),
188 objectInfos.end(),
189 std::back_inserter(objectSet.objects),
190 makeObjectSource);
191
192 return objectSet;
193 }
194
195 void
196 Component::generateScene(const scene_generation::ClutteredSceneGenerator::Config& config,
197 const int seed)
198 {
200 scene_generation::ClutteredSceneGenerator gen(simulator_, config);
201 gen.generateScene(seed);
202 }
203
204 objects::Scene
205 Component::getScene()
206 {
208
209 objects::Scene scene;
210 armarx::SceneVisuData sceneData = simulator_->getScene();
211
212 auto makeSceneObject = [](const armarx::ObjectVisuData& simObject)
213 {
214 const armarx::ObjectID objectID(simObject.name);
215 // const armarx::ObjectID objectID(simObject.project, simObject.objectClassName, simObject.name);
216 Eigen::Matrix4f objectPose{armarx::fromIce(simObject.objectPoses.at(simObject.name))};
217
218 return objects::SceneObject{
219 .className = objectID.getClassID().str(),
220 .instanceName = objectID.instanceName(),
221 .collection = objectID.dataset(),
222 .position = simox::math::position(objectPose),
223 .orientation = Eigen::Quaternionf(simox::math::orientation(objectPose)),
224 .isStatic = false,
225 .jointValues = {}};
226 };
227
228 std::transform(sceneData.objects.begin(),
229 sceneData.objects.end(),
230 std::back_inserter(scene.objects),
231 makeSceneObject);
232
233 return scene;
234 }
235
236 void
237 Component::storeScene(const objects::Scene& scene, const std::filesystem::path& path)
238 {
240
241 ARMARX_INFO << "Storing scene snapshot at: \n\t" << path;
242 try
243 {
244 simox::json::write(path, scene, 2);
245 }
246 catch (const simox::json::error::JsonError& e)
247 {
248 ARMARX_WARNING << "Storing scene snapshot failed: \n" << e.what();
249 }
250 }
251
252 /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
253 void
254 Component::createRemoteGuiTab()
255 {
256 using namespace armarx::RemoteGui::Client;
257
258 // Setup the widgets.
259
260 tab.boxLayerName.setValue(properties.boxLayerName);
261
262 tab.numBoxes.setValue(properties.numBoxes);
263 tab.numBoxes.setRange(0, 100);
264
265 tab.drawBoxes.setLabel("Draw Boxes");
266
267 // Setup the layout.
268
269 GridLayout grid;
270 int row = 0;
271 {
272 grid.add(Label("Box Layer"), {row, 0}).add(tab.boxLayerName, {row, 1});
273 ++row;
274
275 grid.add(Label("Num Boxes"), {row, 0}).add(tab.numBoxes, {row, 1});
276 ++row;
277
278 grid.add(tab.drawBoxes, {row, 0}, {2, 1});
279 ++row;
280 }
281
282 VBoxLayout root = {grid, VSpacer()};
283 RemoteGui_createTab(getName(), root, &tab);
284 }
285
286
287 void
288 Component::RemoteGui_update()
289 {
290 if (tab.boxLayerName.hasValueChanged() || tab.numBoxes.hasValueChanged())
291 {
292 std::scoped_lock lock(propertiesMutex);
293 properties.boxLayerName = tab.boxLayerName.getValue();
294 properties.numBoxes = tab.numBoxes.getValue();
295
296 {
297 setDebugObserverDatafield("numBoxes", properties.numBoxes);
298 setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
299 sendDebugObserverBatch();
300 }
301 }
302 if (tab.drawBoxes.wasClicked())
303 {
304 // Lock shared variables in methods running in seperate threads
305 // and pass them to functions. This way, the called functions do
306 // not need to think about locking.
307 std::scoped_lock lock(propertiesMutex, arvizMutex);
308 drawBoxes(properties, arviz);
309 }
310 }
311 */
312
313
314 /* (Requires the armarx::ArVizComponentPluginUser.)
315 void
316 Component::drawBoxes(const Component::Properties& p, viz::Client& arviz)
317 {
318 // Draw something in ArViz (requires the armarx::ArVizComponentPluginUser.
319 // See the ArVizExample in RobotAPI for more examples.
320
321 viz::Layer layer = arviz.layer(p.boxLayerName);
322 for (int i = 0; i < p.numBoxes; ++i)
323 {
324 layer.add(viz::Box("box_" + std::to_string(i))
325 .position(Eigen::Vector3f(i * 100, 0, 0))
326 .size(20).color(simox::Color::blue()));
327 }
328 arviz.commit(layer);
329 }
330 */
331
332 // TODO(patrick.hegemann): enable after migration:
333 // ARMARX_REGISTER_COMPONENT_EXECUTABLE(Component, Component::GetDefaultName());
334
335} // namespace armarx::simulation::components::cluttered_scene_generator
Default component property definition container.
Definition Component.h:70
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
Used to find objects in the ArmarX objects repository [1] (formerly [2]).
std::vector< ObjectInfo > findAllObjectsOfDataset(const std::string &dataset, bool checkPaths=true) const
Accessor for the object files.
Definition ObjectInfo.h:37
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition Component.cpp:54
static std::string GetDefaultName()
Get the component's default name.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
Quaternion< float, 0 > Quaternionf
armarx::PackagePath toPackagePath(const armarx::PackageFileLocation &packageFileLocation)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
void fromIce(const std::map< IceKeyT, IceValueT > &iceMap, boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
std::string package
Name of the ArmarX package.
Definition ObjectInfo.h:25
std::string relativePath
Relative to the package's data directory.
Definition ObjectInfo.h:28
#define ARMARX_TRACE
Definition trace.h:77