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
85  {
86  }
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
144  {
145  }
146 
147  void
149  {
150  }
151 
152  std::string
154  {
155  return Component::defaultName;
156  }
157 
158  std::string
160  {
161  return Component::defaultName;
162  }
163 
164  inline armarx::PackagePath
165  toPackagePath(const armarx::PackageFileLocation& packageFileLocation)
166  {
167  return {packageFileLocation.package, packageFileLocation.relativePath};
168  }
169 
171  Component::getObjectClasses()
172  {
173  ARMARX_TRACE;
174  scene_generation::ObjectSet objectSet;
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  {
199  ARMARX_TRACE;
200  scene_generation::ClutteredSceneGenerator gen(simulator_, config);
201  gen.generateScene(seed);
202  }
203 
204  objects::Scene
205  Component::getScene()
206  {
207  ARMARX_TRACE;
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  {
239  ARMARX_TRACE;
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
armarx::simulation::components::cluttered_scene_generator::Component::GetDefaultName
static std::string GetDefaultName()
Get the component's default name.
Definition: Component.cpp:159
Component.h
armarx::ObjectID
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition: ObjectID.h:10
armarx::simulation::scene_generation::ObjectSource
Definition: SimulatedObject.h:44
armarx::simulation::components::cluttered_scene_generator::Component::onExitComponent
void onExitComponent() override
Definition: Component.cpp:148
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
armarx::simulation::components::cluttered_scene_generator::Component::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: Component.cpp:54
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config
Definition: ClutteredSceneGenerator.h:52
Pose.h
armarx::simulation::scene_generation::ObjectSet::objects
std::vector< ObjectSource > objects
Definition: SimulatedObject.h:54
armarx::simulation::components::cluttered_scene_generator::Component::getDefaultName
std::string getDefaultName() const override
Definition: Component.cpp:153
armarx::simulation::scene_generation::AsObject
@ AsObject
Definition: SimulatedObject.h:39
armarx::simulation::components::cluttered_scene_generator
Definition: Component.cpp:49
armarx::PackageFileLocation
Definition: ObjectInfo.h:22
armarx::PackageFileLocation::relativePath
std::string relativePath
Relative to the package's data directory.
Definition: ObjectInfo.h:28
Scene.h
armarx::simulation::scene_generation::ObjectSet
Definition: SimulatedObject.h:52
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::simulation::scene_generation::ObjectSource::path
armarx::PackagePath path
Definition: SimulatedObject.h:46
armarx::ObjectFinder
Used to find objects in the ArmarX objects repository [1] (formerly [2]).
Definition: ObjectFinder.h:22
json_conversions.h
armarx::ObjectFinder::findAllObjectsOfDataset
std::vector< ObjectInfo > findAllObjectsOfDataset(const std::string &dataset, bool checkPaths=true) const
Definition: ObjectFinder.cpp:208
armarx::PackagePath::toSystemPath
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
Definition: PackagePath.cpp:47
ObjectID.h
ObjectInfo.h
Eigen::Quaternionf
Quaternion< float, 0 > Quaternionf
Definition: EigenForwardDeclarations.h:61
SimulatedObject.h
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::fromIce
void fromIce(const std::map< IceKeyT, IceValueT > &iceMap, boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
Definition: ice_conversions_boost_templates.h:27
armarx::objects::Scene
Definition: Scene.h:55
armarx::simulation::components::cluttered_scene_generator::toPackagePath
armarx::PackagePath toPackagePath(const armarx::PackageFileLocation &packageFileLocation)
Definition: Component.cpp:165
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT >>
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:351
armarx::PackageFileLocation::package
std::string package
Name of the ArmarX package.
Definition: ObjectInfo.h:25
ExpressionException.h
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
Decoupled.h
armarx::simulation::components::cluttered_scene_generator::Component::onInitComponent
void onInitComponent() override
Definition: Component.cpp:84
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::objectSets
std::vector< ObjectSet > objectSets
Definition: ClutteredSceneGenerator.h:55
armarx::simulation::components::cluttered_scene_generator::Component::onDisconnectComponent
void onDisconnectComponent() override
Definition: Component.cpp:143
armarx::simulation::components::cluttered_scene_generator::Component::onConnectComponent
void onConnectComponent() override
Definition: Component.cpp:89
armarx::aron::write
requires data::isWriter< WriterT > void write(WriterT &aron_w, const Eigen::Matrix< EigenT, rows, cols, options > &input, typename WriterT::ReturnType &ret, const armarx::aron::Path &aron_p=armarx::aron::Path())
Definition: eigen.h:138
ClutteredSceneGenerator.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::PackagePath
Definition: PackagePath.h:52
armarx::ObjectInfo
Accessor for the object files.
Definition: ObjectInfo.h:36
ObjectFinder.h
PackagePath.h