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 navigation::ArmarXObjects::distance_to_obstacle_costmap_provider
17  * @author Fabian Reister ( fabian dot reister at kit dot edu )
18  * @date 2022
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 
24 #include "Component.h"
25 
26 #include <optional>
27 
28 #include <SimoxUtility/algorithm/string/string_tools.h>
29 #include <VirtualRobot/SceneObjectSet.h>
30 #include <VirtualRobot/VirtualRobot.h>
31 
38 
41 
44 
45 #include <range/v3/view/for_each.hpp>
46 
48 {
50  {
51  addPlugin(virtualRobotReaderPlugin);
52  addPlugin(costmapWriterPlugin);
53  addPlugin(articulatedObjectReaderPlugin);
54  }
55 
56  const std::string Component::defaultName = "distance_to_obstacle_costmap_provider";
57 
60  {
63 
64  def->required(properties.robotName, "p.robotName", "Robot name.");
65 
66  def->optional(properties.costmapBuilderParams.binaryGrid, "p.costmapBuilderParams.binaryGrid");
67  def->optional(properties.costmapBuilderParams.cellSize, "p.costmapBuilderParams.cellSize");
68  def->optional(properties.costmapBuilderParams.sceneBoundsMargin, "p.costmapBuilderParams.sceneBoundsMargin");
69 
70  def->optional(properties.colModel, "p.colModel");
71 
72  return def;
73  }
74 
75  void
77  {
78  // Topics and properties defined above are automagically registered.
79 
80  // Keep debug observer data until calling `sendDebugObserverBatch()`.
81  // (Requies the armarx::DebugObserverComponentPluginUser.)
82  // setDebugObserverBatchModeEnabled(true);
83  }
84 
85  void
87  {
88  // Do things after connecting to topics and components.
89 
90  /* (Requies the armarx::DebugObserverComponentPluginUser.)
91  // Use the debug observer to log data over time.
92  // The data can be viewed in the ObserverView and the LivePlotter.
93  // (Before starting any threads, we don't need to lock mutexes.)
94  {
95  setDebugObserverDatafield("numBoxes", properties.numBoxes);
96  setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
97  sendDebugObserverBatch();
98  }
99  */
100 
101  /* (Requires the armarx::ArVizComponentPluginUser.)
102  // Draw boxes in ArViz.
103  // (Before starting any threads, we don't need to lock mutexes.)
104  drawBoxes(properties, arviz);
105  */
106 
107  /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
108  // Setup the remote GUI.
109  {
110  createRemoteGuiTab();
111  RemoteGui_startRunningTask();
112  }
113  */
114 
115  runningTask = new RunningTask<Component>(this, &Component::run, "createAndStoreCostmap");
116  runningTask->start();
117  }
118 
119  void
121  {
122  // FIXME: whenever the static scene changes, update the costmap
123 
125  }
126 
127  bool
129  {
130  const std::vector<std::string> primitiveModelIds = [&]() -> std::vector<std::string>
131  {
132  if (not properties.primitiveModelIds.empty())
133  {
134  const std::vector<std::string> primitiveModelIds =
135  simox::alg::split(properties.primitiveModelIds, ",", true, false);
136  ARMARX_INFO << VAROUT(primitiveModelIds);
137  return primitiveModelIds;
138  }
139 
140  return {};
141  }();
142 
143  const auto loadMode = primitiveModelIds.empty()
144  ? VirtualRobot::RobotIO::RobotDescription::eCollisionModel
145  : VirtualRobot::RobotIO::RobotDescription::eStructure;
146 
147  const auto robot = virtualRobotReaderPlugin->get().getRobotWaiting(
148  properties.robotName, armarx::DateTime::Invalid(), loadMode);
149 
150  ARMARX_CHECK_NOT_NULL(robot);
151 
152  if (not primitiveModelIds.empty())
153  {
154  ARMARX_INFO << "Using primitive approximation model";
155  robot->setPrimitiveApproximationModel(primitiveModelIds);
156  }
157 
158  const auto objectPoseClient = ObjectPoseClientPluginUser::getClient();
159 
160  const objpose::ObjectPoseSeq objectPoses = objectPoseClient.fetchObjectPoses();
161 
162  // remove those objects that belong to an object dataset. the manipulation object / distance computation is broken
163  const objpose::ObjectPoseSeq objectPosesStatic =
165 
166  const objpose::ObjectPoseSeq objectPosesStaticNonArticulated =
168  const objpose::ObjectPoseSeq objectPosesStaticArticulated =
170 
171  const VirtualRobot::SceneObjectSetPtr objects =
172  armarx::navigation::util::asSceneObjects(objectPosesStaticNonArticulated);
173 
174  std::vector<VirtualRobot::RobotPtr> articulatedObjects;
175  for (const auto& objectPoseStaticArticulated : objectPosesStaticArticulated)
176  {
177  const auto articulatedObject =
178  articulatedObjectReaderPlugin->get().getArticulatedObject(
179  objectPoseStaticArticulated.objectID.getClassID().str(),
180  Clock::Now(),
181  std::nullopt,
182  objectPoseStaticArticulated.objectID.instanceName());
183 
184  ARMARX_CHECK_NOT_NULL(articulatedObject)
185  << objectPoseStaticArticulated.objectID.getClassID().str();
186 
187  ARMARX_CHECK(articulatedObjectReaderPlugin->get().synchronizeArticulatedObject(
188  *articulatedObject, Clock::Now(), std::nullopt));
189 
190  std::set<std::string> primitiveIDs;
191  articulatedObject->getPrimitiveApproximationIDs(primitiveIDs);
192 
193  if (articulatedObject->getCollisionModels().empty())
194  {
195  ARMARX_INFO << "The articualted object `" << articulatedObject->getType() << "/"
196  << articulatedObject->getName()
197  << "` does not have a collision model. Using primitive model instead.";
198 
199  // use all primitive ids
200  // TODO: refine selection?
201  const std::vector<std::string> usedPrimitiveModelIDs(primitiveIDs.begin(),
202  primitiveIDs.end());
203  articulatedObject->setPrimitiveApproximationModel(usedPrimitiveModelIDs);
204  }
205 
206  articulatedObjects.push_back(articulatedObject);
207  }
208 
209 
210  ARMARX_CHECK_NOT_NULL(objects);
211  ARMARX_INFO << objects->getSize() << " objects in the scene";
212 
213  ARMARX_INFO << "Static objects (non-articulated)";
214  for (const objpose::ObjectPose& objectPose : objectPosesStaticNonArticulated)
215  {
216  ARMARX_INFO << " - " << objectPose.objectID;
217  }
218 
219  ARMARX_INFO << "Static objects (articulated)";
220  for (const auto& object : articulatedObjects)
221  {
222  ARMARX_INFO << " - " << object->getType() << "/" << object->getName();
223  }
224 
225  ARMARX_INFO << "Creating costmap";
226 
227  // FIXME: move costmap creation out of this component
228  // FIXME create costmap writer enum: type of costmaps
229  algorithms::CostmapBuilder costmapBuilder(
230  robot,
231  objects,
233  properties.costmapBuilderParams,
234  properties.colModel);
235 
236  const auto costmap = costmapBuilder.create();
237 
238  ARMARX_INFO << "Storing costmap in the memory.";
239  return costmapWriterPlugin->get().store(
240  costmap, "distance_to_obstacles", getName(), armarx::Clock::Now());
241  }
242 
243  void
245  {
246  runningTask->stop();
247  }
248 
249  void
251  {
252  }
253 
254  std::string
256  {
257  return Component::defaultName;
258  }
259 
260  std::string
262  {
263  return Component::defaultName;
264  }
265 
266  /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
267  void
268  Component::createRemoteGuiTab()
269  {
270  using namespace armarx::RemoteGui::Client;
271 
272  // Setup the widgets.
273 
274  tab.boxLayerName.setValue(properties.boxLayerName);
275 
276  tab.numBoxes.setValue(properties.numBoxes);
277  tab.numBoxes.setRange(0, 100);
278 
279  tab.drawBoxes.setLabel("Draw Boxes");
280 
281  // Setup the layout.
282 
283  GridLayout grid;
284  int row = 0;
285  {
286  grid.add(Label("Box Layer"), {row, 0}).add(tab.boxLayerName, {row, 1});
287  ++row;
288 
289  grid.add(Label("Num Boxes"), {row, 0}).add(tab.numBoxes, {row, 1});
290  ++row;
291 
292  grid.add(tab.drawBoxes, {row, 0}, {2, 1});
293  ++row;
294  }
295 
296  VBoxLayout root = {grid, VSpacer()};
297  RemoteGui_createTab(getName(), root, &tab);
298  }
299 
300 
301  void
302  Component::RemoteGui_update()
303  {
304  if (tab.boxLayerName.hasValueChanged() || tab.numBoxes.hasValueChanged())
305  {
306  std::scoped_lock lock(propertiesMutex);
307  properties.boxLayerName = tab.boxLayerName.getValue();
308  properties.numBoxes = tab.numBoxes.getValue();
309 
310  {
311  setDebugObserverDatafield("numBoxes", properties.numBoxes);
312  setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
313  sendDebugObserverBatch();
314  }
315  }
316  if (tab.drawBoxes.wasClicked())
317  {
318  // Lock shared variables in methods running in seperate threads
319  // and pass them to functions. This way, the called functions do
320  // not need to think about locking.
321  std::scoped_lock lock(propertiesMutex, arvizMutex);
322  drawBoxes(properties, arviz);
323  }
324  }
325  */
326 
327 
328  /* (Requires the armarx::ArVizComponentPluginUser.)
329  void
330  Component::drawBoxes(const Component::Properties& p, viz::Client& arviz)
331  {
332  // Draw something in ArViz (requires the armarx::ArVizComponentPluginUser.
333  // See the ArVizExample in RobotAPI for more examples.
334 
335  viz::Layer layer = arviz.layer(p.boxLayerName);
336  for (int i = 0; i < p.numBoxes; ++i)
337  {
338  layer.add(viz::Box("box_" + std::to_string(i))
339  .position(Eigen::Vector3f(i * 100, 0, 0))
340  .size(20).color(simox::Color::blue()));
341  }
342  arviz.commit(layer);
343  }
344  */
345 
346 
348 
349 } // namespace armarx::navigation::components::distance_to_obstacle_costmap_provider
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::createAndStoreCostmap
bool createAndStoreCostmap()
Definition: Component.cpp:128
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::onDisconnectComponent
void onDisconnectComponent() override
Definition: Component.cpp:244
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::GetDefaultName
static std::string GetDefaultName()
Get the component's default name.
Definition: Component.cpp:261
armarx::objpose::ObjectPoseSeq
std::vector< ObjectPose > ObjectPoseSeq
Definition: forward_declarations.h:20
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::onConnectComponent
void onConnectComponent() override
Definition: Component.cpp:86
DateTime.h
CostmapBuilder.h
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: Component.cpp:59
armarx::ManagedIceObject::addPlugin
PluginT * addPlugin(const std::string prefix="", ParamsT &&...params)
Definition: ManagedIceObject.h:182
RunningTask.h
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:35
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
Clock.h
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::onInitComponent
void onInitComponent() override
Definition: Component.cpp:76
util.h
armarx::navigation::util::nonArticulatedObjects
objpose::ObjectPoseSeq nonArticulatedObjects(objpose::ObjectPoseSeq objects)
Definition: util.cpp:77
armarx::navigation::util::articulatedObjects
objpose::ObjectPoseSeq articulatedObjects(objpose::ObjectPoseSeq objects)
Definition: util.cpp:95
ObjectPose.h
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::run
void run()
Definition: Component.cpp:120
armarx::navigation::util::asSceneObjects
VirtualRobot::SceneObjectSetPtr asSceneObjects(const objpose::ObjectPoseSeq &objectPoses)
Definition: util.cpp:146
armarx::navigation::algorithms::CostmapBuilder
Definition: CostmapBuilder.h:31
armarx::navigation::components::distance_to_obstacle_costmap_provider::ARMARX_REGISTER_COMPONENT_EXECUTABLE
ARMARX_REGISTER_COMPONENT_EXECUTABLE(Component, Component::GetDefaultName())
Component.h
armarx::armem::client::plugins::ReaderWriterPlugin::get
T & get()
Definition: ReaderWriterPlugin.h:87
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
armarx::armem::articulated_object::ArticulatedObjectReader::synchronizeArticulatedObject
bool synchronizeArticulatedObject(VirtualRobot::Robot &object, const armem::Time &timestamp, const std::optional< std::string > &providerName)
Definition: ArticulatedObjectReader.cpp:71
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component
Definition: Component.h:42
Decoupled.h
forward_declarations.h
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:70
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::navigation::algorithms::CostmapBuilder::create
Costmap create(const SceneBounds &init=SceneBounds())
Definition: CostmapBuilder.cpp:61
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::onExitComponent
void onExitComponent() override
Definition: Component.cpp:250
armarx::navigation::util::staticObjects
objpose::ObjectPoseSeq staticObjects(objpose::ObjectPoseSeq objects)
Definition: util.cpp:67
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:97
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:107
Logging.h
armarx::ObjectPoseClientPluginUser::getClient
objpose::ObjectPoseClient getClient() const
Definition: ObjectPoseClientPlugin.cpp:64
armarx::armem::articulated_object::ArticulatedObjectReader::getArticulatedObject
VirtualRobot::RobotPtr getArticulatedObject(const std::string &typeName, const armem::Time &timestamp, const std::optional< std::string > &providerName, const std::string &instanceName="", VirtualRobot::RobotIO::RobotDescription loadMode=VirtualRobot::RobotIO::eStructure)
Definition: ArticulatedObjectReader.cpp:29
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::Component
Component()
Definition: Component.cpp:49
armarx::core::time::DateTime::Invalid
static DateTime Invalid()
Definition: DateTime.cpp:60
armarx::objpose::ObjectPose
An object pose as stored by the ObjectPoseStorage.
Definition: ObjectPose.h:36
armarx::navigation::components::distance_to_obstacle_costmap_provider
Definition: Component.cpp:47
armarx::navigation::components::distance_to_obstacle_costmap_provider::Component::getDefaultName
std::string getDefaultName() const override
Definition: Component.cpp:255
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36