Visu.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::NavigationMemory
17  * @author Rainer Kartmann ( rainer dot kartmann 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 
23 #include "Visu.h"
24 
25 #include <map>
26 #include <memory>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 #include <Ice/LocalException.h>
32 
33 #include <SimoxUtility/color/Color.h>
34 #include <SimoxUtility/color/GlasbeyLUT.h>
35 
40 
53 #include <RobotAPI/libraries/armem_locations/aron/Location.aron.generated.h>
56 
58 #include <armarx/navigation/algorithms/aron/Room.aron.generated.h>
64 #include <armarx/navigation/core/aron/Graph.aron.generated.h>
67 #include <armarx/navigation/human/aron/Human.aron.generated.h>
70 
72 {
73 
75  const armem::server::wm::CoreSegment& locSegment,
76  const armem::server::wm::CoreSegment& graphSegment,
77  const armem::server::wm::CoreSegment& costmapSegment,
78  const armem::server::wm::CoreSegment& humanSegment,
79  const armem::server::wm::CoreSegment& roomsSegment) :
80  arviz(arviz),
81  locSegment(locSegment),
82  graphSegment(graphSegment),
83  costmapSegment(costmapSegment),
84  humanSegment(humanSegment),
85  roomsSegment(roomsSegment),
86  visu(std::make_unique<graph::GraphVisu>())
87  {
88  }
89 
91  {
92  }
93 
94  void
96  const std::vector<ObjectInfo>& info,
97  viz::Layer& layer)
98  {
99  using namespace armem::server;
100 
101  std::map<armem::MemoryID, location::arondto::Location> locations;
103  [&]()
104  {
106  [&](const wm::Entity& entity)
107  {
108  if (const wm::EntityInstance* instance = entity.findLatestInstance())
109  {
110  locations[entity.id()].fromAron(instance->data());
111  }
112  });
113  });
114 
115  for (auto& [id, location] : locations)
116  {
117  FramedPose framedPose;
118  fromAron(location.framedPose, framedPose);
119 
120  const auto res = core::resolveLocation(objects, info, framedPose);
121  if (res.pose.has_value())
122  {
123  visu->vertex->draw(layer, id.str(), res.pose.value());
124  }
125  }
126  }
127 
128  void
130  const std::vector<ObjectInfo>& info,
131  std::vector<viz::Layer>& layers,
132  bool enabled)
133  {
134  using namespace armem::server;
135 
136  std::map<armem::MemoryID, core::Graph> graphs;
138  [&]()
139  {
141  [&](const wm::Entity& entity)
142  {
143  core::Graph& graph = graphs[entity.id()];
144  if (enabled)
145  {
146  if (const wm::EntityInstance* instance = entity.findLatestInstance())
147  {
148  navigation::core::arondto::Graph aron;
149  aron.fromAron(instance->data());
150  fromAron(aron, graph);
151  }
152  }
153  // else: empty layer
154  });
155  });
156 
157  for (auto& [id, graph] : graphs)
158  {
159  viz::Layer& layer = layers.emplace_back(arviz.layer(id.str()));
160  if (enabled)
161  {
163  visu->draw(layer, graph, {objects, info});
164  }
165  // else: clear layer
166  }
167  }
168 
169  void
170  Visu::drawLocations(std::vector<viz::Layer>& layers, bool enabled)
171  {
172  viz::Layer& layer = layers.emplace_back(arviz.layer(locSegment.id().str()));
173  if (enabled)
174  {
175  const objpose::ObjectPoseMap objects;
176  const std::vector<ObjectInfo> info;
177  drawLocations(objects, info, layer);
178  }
179  }
180 
181  void
183  std::vector<viz::Layer>& layers,
184  bool enabled)
185  {
186  viz::Layer& layer = layers.emplace_back(arviz.layer(locSegment.id().str()));
187  if (enabled and objClient.isConnected())
188  {
189  try
190  {
191  // this call might fail => "no object with id 'ObjectMemory' registered."
192  const objpose::ObjectPoseMap objects = objClient.fetchObjectPosesAsMap();
193 
194  auto objectFinder = objClient.getObjectFinder();
195  objectFinder.setLogObjectDiscoveryError(false);
196  const std::vector<ObjectInfo> info = objectFinder.findAllObjects();
197 
198  drawLocations(objects, info, layer);
199  }
200  catch (const ::Ice::NotRegisteredException& e)
201  {
202  ARMARX_VERBOSE << "Failed to retrieve objects from ObjectMemory: " << e.what();
203  }
204  }
205  }
206 
207  void
208  Visu::drawGraphs(std::vector<viz::Layer>& layers, bool enabled)
209  {
210  const objpose::ObjectPoseMap objects;
211  const std::vector<ObjectInfo> info;
212  drawGraphs(objects, info, layers, enabled);
213  }
214 
215  void
217  std::vector<viz::Layer>& layers,
218  bool enabled)
219  {
220  if (enabled and objClient.isConnected())
221  {
222  try
223  {
224  // this call might fail => "no object with id 'ObjectMemory' registered."
225  const objpose::ObjectPoseMap objects = objClient.fetchObjectPosesAsMap();
226 
227  auto objectFinder = objClient.getObjectFinder();
228  objectFinder.setLogObjectDiscoveryError(false);
229  const std::vector<ObjectInfo> info = objectFinder.findAllObjects();
230 
231  drawGraphs(objects, info, layers, enabled);
232  }
233  catch (const ::Ice::NotRegisteredException& e)
234  {
235  ARMARX_VERBOSE << "Failed to retrieve objects from ObjectMemory: " << e.what();
236  }
237  }
238  }
239 
240  namespace
241  {
242 
243  inline void
244  visualize(const human::Humans& humans, viz::Layer& layer, const bool visuTransparent)
245  {
246 
247  const Eigen::Translation3f human_T_mmm(Eigen::Vector3f{0, 0, 1000});
248 
249  ARMARX_VERBOSE << deactivateSpam(1) << "Visualizing " << humans.size() << " humans";
250  for (const auto& human : humans)
251  {
252  // viz::Cylinder cylinder(std::to_string(layer.size()));
253  // cylinder.fromTo(conv::to3D(human.pose.translation()),
254  // conv::to3D(human.pose.translation()) + Eigen::Vector3f{0, 0, 10});
255 
256 
257  // cylinder.color(simox::Color::orange());
258  // cylinder.radius(300);
259  // layer.add(cylinder);
260 
261  core::Pose human3d = conv::to3D(human.pose) * human_T_mmm;
262 
263  viz::Robot mmm(std::to_string(layer.size()));
264  mmm.file("RobotAPI", "RobotAPI/robots/MMM/mmm.xml");
265  mmm.pose(human3d);
266  mmm.scale(1.7); // 1.7m
267  mmm.overrideColor(viz::Color::orange(255, visuTransparent ? 100 : 255));
268  layer.add(mmm);
269 
270 
271  if (human.linearVelocity != Eigen::Vector2f::Zero())
272  {
273  core::Pose vel3d = human3d;
274  vel3d.translation().head<2>() += human.linearVelocity * 2;
275  auto arrow = viz::Arrow(std::to_string(layer.size()))
276  .fromTo(human3d.translation(), vel3d.translation())
277  .color(simox::Color::red());
278  layer.add(arrow);
279  }
280  }
281  }
282 
283  } // namespace
284 
285  void
286  Visu::drawCostmaps(std::vector<viz::Layer>& layers, const bool enabled, const float zOffset)
287  {
288  if (not enabled)
289  {
290  return;
291  }
292 
293  std::map<std::string, std::vector<std::pair<std::string, algorithms::Costmap>>>
294  namedProviderCostmaps;
295 
297  [&]()
298  {
299  using namespace armem::server;
300 
302  [&](const wm::Entity& entity)
303  {
304  if (const wm::EntityInstance* instance = entity.findLatestInstance())
305  {
306  const auto it =
307  lastCostmapVisualization_.find(instance->id().getEntityID().str());
308  // only visualize this costmap if it's timestamp is newer than the last one'
309  if (it == lastCostmapVisualization_.end() ||
310  it->second < instance->id().timestamp)
311  {
312  navigation::algorithms::Costmap costmap =
313  algorithms::fromAron(*instance);
314 
315  namedProviderCostmaps[instance->id().providerSegmentName]
316  .emplace_back(instance->id().entityName, std::move(costmap));
317 
318  lastCostmapVisualization_[instance->id().getEntityID().str()] =
319  instance->id().timestamp;
320  }
321  }
322  });
323  });
324 
325  for (const auto& [providerName, namedCostmaps] : namedProviderCostmaps)
326  {
327  for (const auto& [name, costmap] : namedCostmaps)
328  {
329  viz::Layer& layer =
330  layers.emplace_back(arviz.layer("costmaps_" + providerName + "_" + name));
331  algorithms::visualize(costmap, layer, name, zOffset);
332  }
333  }
334  }
335 
336  void
337  Visu::drawRooms(std::vector<viz::Layer>& layers, const bool enabled)
338  {
339  using namespace armem::server;
340 
341  std::map<armem::MemoryID, algorithms::Room> rooms;
343  [&]()
344  {
346  [&](const wm::Entity& entity)
347  {
348  algorithms::Room& room = rooms[entity.id()];
349  if (enabled)
350  {
351  if (const wm::EntityInstance* instance = entity.findLatestInstance())
352  {
353  navigation::algorithms::arondto::Room aron;
354  aron.fromAron(instance->data());
355  fromAron(aron, room);
356  }
357  }
358  // else: empty layer
359  });
360  });
361 
362  int i = 0;
363  for (auto& [id, room] : rooms)
364  {
365  viz::Layer& layer = layers.emplace_back(arviz.layer(id.str()));
366  if (enabled)
367  {
368  const auto color = simox::color::GlasbeyLUT::at(i++);
369 
370  drawRoom(layer, room, color);
371  }
372  // else: clear layer
373  }
374  }
375 
376  void
377  Visu::drawRoom(viz::Layer& layer, const algorithms::Room& room, const simox::Color& color) const
378  {
379  viz::Polygon polygon(room.name);
380  viz::Path path(room.name + "path");
381 
382  for (const auto& point : room.polygon)
383  {
384  polygon.addPoint(conv::to3D(point));
385  path.addPoint(conv::to3D(point));
386  }
387 
388  // close polygon
389  path.addPoint(conv::to3D(room.polygon.front()));
390 
391  polygon.color(color.with_alpha(50));
392  polygon.lineColor(simox::Color::black());
393  polygon.lineWidth(0);
394 
395  layer.add(polygon);
396 
397  layer.add(path);
398  }
399 
400  void
401  Visu::drawHumans(std::vector<viz::Layer>& layers,
402  const bool enabled,
403  const bool visuTransparent,
404  const Duration maxAge)
405  {
406  if (not enabled)
407  {
408  return;
409  }
410 
411  std::map<std::string, navigation::human::Humans> namedProviderHumans;
412  const DateTime timestamp = Clock::Now();
413 
415  [&]()
416  {
417  using namespace armem::server;
418 
420  [&](const wm::Entity& entity)
421  {
422  namedProviderHumans[entity.id().providerSegmentName];
423  entity.getLatestSnapshot().forEachInstance(
424  [&namedProviderHumans, &timestamp, &maxAge](
425  const armarx::armem::wm::EntityInstance& instance)
426  {
427  const Duration dtToNow =
428  timestamp - instance.metadata().referencedTime;
429 
430  if (dtToNow < maxAge and dtToNow.isPositive())
431  {
432  const auto dto = navigation::human::arondto::Human::FromAron(
433  instance.data());
434 
435  navigation::human::Human human;
436  fromAron(dto, human);
437 
438  namedProviderHumans[instance.id().providerSegmentName]
439  .emplace_back(std::move(human));
440  };
441  });
442  });
443  });
444 
445  for (const auto& [providerName, humans] : namedProviderHumans)
446  {
447  viz::Layer& layer = layers.emplace_back(arviz.layer("humans_" + providerName));
448  visualize(humans, layer, visuTransparent);
449  }
450  }
451 
452 
453 } // namespace armarx::navigation::memory
Client.h
Visu.h
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::navigation::memory::Visu::drawLocations
void drawLocations(std::vector< viz::Layer > &layers, bool enabled)
Definition: Visu.cpp:170
armarx::navigation::core::resolveLocations
void resolveLocations(Graph &graph, const MemoryContainerT &locationContainer)
Definition: Graph.h:141
armarx::navigation::algorithms::Room::name
std::string name
Definition: Room.h:35
Robot.h
armarx::armem::server::wm::EntityInstance
armem::wm::EntityInstance EntityInstance
Definition: forward_declarations.h:65
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:43
Path.h
armarx::navigation::core::resolveLocation
void resolveLocation(Graph::Vertex &vertex, const aron::data::DictPtr &locationData)
Definition: Graph.cpp:250
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
framed.h
armarx::navigation::memory::fromAron
void fromAron(const arondto::Circle &dto, Circle &bo)
Definition: aron_conversions.cpp:56
armarx::navigation::memory
Definition: ComponentInterface.ice:37
basic_types.h
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::FramedPose
The FramedPose class.
Definition: FramedPose.h:280
aron_conversions.h
armarx::armem::base::detail::GetLatestSnapshotMixin::getLatestSnapshot
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.
Definition: lookup_mixins.h:199
MemoryID.h
DateTime.h
armarx::navigation::memory::Visu::graphSegment
const armem::server::wm::CoreSegment & graphSegment
Definition: Visu.h:87
armarx::armem::MemoryID::str
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
Definition: MemoryID.cpp:102
armarx::navigation::memory::Visu::drawCostmaps
void drawCostmaps(std::vector< viz::Layer > &layers, bool enabled, float zOffset)
Definition: Visu.cpp:286
Duration.h
armarx::rooms
Brief description of class rooms.
Definition: rooms.h:38
armarx::viz::Arrow
Definition: Elements.h:196
types.h
armarx::navigation::memory::Visu::arviz
viz::ScopedClient arviz
Definition: Visu.h:84
armarx::viz::Layer::add
void add(ElementT const &element)
Definition: Layer.h:31
armarx::navigation::human::Humans
std::vector< Human > Humans
Definition: types.h:48
armarx::ObjectFinder::setLogObjectDiscoveryError
void setLogObjectDiscoveryError(bool logEnabled)
Definition: ObjectFinder.cpp:397
armarx::armem::server::wm::Entity
Definition: memory_definitions.h:27
armarx::objpose::ObjectPoseClient
Provides access to the armarx::objpose::ObjectPoseStorageInterface (aka the object memory).
Definition: ObjectPoseClient.h:17
armarx::armem::base::detail::ForEachEntityMixin::forEachEntity
bool forEachEntity(FunctionT &&func)
Definition: iteration_mixins.h:259
armarx::navigation::memory::Visu::humanSegment
const armem::server::wm::CoreSegment & humanSegment
Definition: Visu.h:89
Elements.h
armarx::core::time::Duration::isPositive
bool isPositive() const
Tests whether the duration is positive (value in µs > 0).
Definition: Duration.cpp:168
Clock.h
armarx::navigation::memory::Visu::drawHumans
void drawHumans(std::vector< viz::Layer > &layers, bool enabled, bool visuTransparent, Duration maxAge)
Definition: Visu.cpp:401
armarx::objpose::ObjectPoseClient::getObjectFinder
const ObjectFinder & getObjectFinder() const
Get the internal object finder.
Definition: ObjectPoseClient.cpp:102
memory_definitions.h
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
armarx::navigation::memory::Visu::~Visu
~Visu()
Definition: Visu.cpp:90
armarx::navigation::memory::Visu::Visu
Visu(viz::Client arviz, const armem::server::wm::CoreSegment &locSegment, const armem::server::wm::CoreSegment &graphSegment, const armem::server::wm::CoreSegment &costmapSegment, const armem::server::wm::CoreSegment &humanSegment, const armem::server::wm::CoreSegment &roomsSegment)
Definition: Visu.cpp:74
armarx::navigation::algorithms::Room::polygon
std::vector< Eigen::Vector2f > polygon
Definition: Room.h:37
Color
uint32_t Color
RGBA color.
Definition: color.h:8
armarx::objpose::ObjectPoseClient::fetchObjectPosesAsMap
ObjectPoseMap fetchObjectPosesAsMap() const
Fetch all known object poses.
Definition: ObjectPoseClient.cpp:45
armarx::navigation::memory::Visu::locSegment
const armem::server::wm::CoreSegment & locSegment
Definition: Visu.h:86
LocationUtils.h
armarx::navigation::memory::Visu::roomsSegment
const armem::server::wm::CoreSegment & roomsSegment
Definition: Visu.h:90
FramedPose.h
Color.h
armarx::navigation::memory::Visu::visu
std::unique_ptr< navigation::graph::GraphVisu > visu
Definition: Visu.h:92
armarx::navigation::algorithms::Room
Definition: Room.h:33
Visu.h
enabled
std::atomic< bool > * enabled
Definition: RemoteGuiWidgetController.cpp:75
ObjectPoseClient.h
aron_conversions.h
armarx::viz::Robot
Definition: Robot.h:10
armarx::Graph
boost::subgraph< CloudGraph > Graph
Definition: Common.h:58
ObjectInfo.h
armarx::armem::base::EntityBase::findLatestInstance
auto * findLatestInstance(int instanceIndex=0)
Definition: EntityBase.h:355
armarx::viz::Polygon
Definition: Elements.h:260
armarx::armem::base::detail::MemoryItem::id
MemoryID & id()
Definition: MemoryItem.h:25
armarx::armem::server::wm::CoreSegment::doLocked
auto doLocked(FunctionT &&function) const
Definition: memory_definitions.h:110
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::red
QColor red()
Definition: StyleSheets.h:78
memory_definitions.h
armarx::armem::server::wm::CoreSegment
base::CoreSegmentBase
Definition: memory_definitions.h:75
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
forward_declarations.h
Graph.h
armarx::navigation::algorithms::visualize
void visualize(const algorithms::Costmap &costmap, viz::Layer &layer, const std::string &name, const float zOffset)
Definition: visualization.cpp:25
armarx::navigation::memory::Visu::drawRooms
void drawRooms(std::vector< viz::Layer > &layers, bool enabled)
Definition: Visu.cpp:337
std
Definition: Application.h:66
armarx::core::time::Duration
Represents a duration.
Definition: Duration.h:16
armarx::viz::Color::orange
static Color orange(int o=255, int a=255)
2 Red + 1 Green
Definition: Color.h:132
armarx::navigation::conv::to3D
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition: eigen.cpp:14
armarx::navigation::memory::Visu::drawGraphs
void drawGraphs(std::vector< viz::Layer > &layers, bool enabled)
Definition: Visu.cpp:208
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:93
armarx::viz::Layer::size
std::size_t size() const noexcept
Definition: Layer.h:52
armarx::viz::ScopedClient::layer
Layer layer(std::string const &name) const
Definition: ScopedClient.cpp:34
armarx::navigation::memory::Visu::costmapSegment
const armem::server::wm::CoreSegment & costmapSegment
Definition: Visu.h:88
eigen.h
Logging.h
armarx::viz::Path
Definition: Path.h:31
armarx::armem::base::EntityInstanceBase::metadata
MetadataT & metadata()
Definition: EntityInstanceBase.h:117
armarx::viz::Client
Definition: Client.h:117
Room.h
armarx::viz::Layer
Definition: Layer.h:12
armarx::objpose::ObjectPoseClient::isConnected
bool isConnected() const
Indicate whether this client is connected to an object pose storage.
Definition: ObjectPoseClient.cpp:28
visualization.h
ObjectFinder.h
armarx::objpose::ObjectPoseMap
std::map< ObjectID, ObjectPose > ObjectPoseMap
Definition: forward_declarations.h:21