ArvizIntrospector.cpp
Go to the documentation of this file.
1 #include "ArvizIntrospector.h"
2 
3 #include <iterator>
4 #include <string>
5 
6 #include <Eigen/Geometry>
7 
8 #include <SimoxUtility/algorithm/apply.hpp>
9 #include <SimoxUtility/algorithm/get_map_keys_values.h>
10 #include <SimoxUtility/color/Color.h>
11 #include <SimoxUtility/color/ColorMap.h>
12 #include <SimoxUtility/color/cmaps/colormaps.h>
13 #include <VirtualRobot/Robot.h>
14 
19 
23 
30 
31 #include <range/v3/algorithm/max.hpp>
32 #include <range/v3/algorithm/max_element.hpp>
33 #include <range/v3/view/enumerate.hpp>
34 
36 {
37 
38  inline armarx::PackagePath
39  asPackagePath(const std::string& absfilepath)
40  {
41  const std::vector<std::string> packages =
43  const std::string package = armarx::ArmarXDataPath::getProject(packages, absfilepath);
44 
45  // make sure that the relative path is without the 'package/' prefix
46  const std::string relPath = [&absfilepath, &package]() -> std::string
47  {
48  if (simox::alg::starts_with(absfilepath, package))
49  {
50  // remove "package" + "/"
51  return absfilepath.substr(package.size() + 1, -1);
52  }
53 
54  return absfilepath;
55  }();
56 
57  return {package, relPath};
58  }
59 
61  const VirtualRobot::RobotPtr& robot,
62  const objpose::ObjectPoseClient& objClient) :
63  arviz(arviz), robot(robot), objClient(objClient)
64  // visualization(arviz,
65  // util::Visualization::Params{.robotModelFileName = asPackagePath(robot->getFilename())})
66  {
67  robotPosesLayer = arviz.layer("robot_poses");
68  }
69 
70  // TODO maybe run with predefined frequency instead of
71 
72  void
74  {
75  ARMARX_DEBUG << "ArvizIntrospector::onGlobalPlannerResult";
76 
77  drawGlobalTrajectory(result.trajectory);
78  arviz.commit(simox::alg::get_values(layers));
79 
80 
81  // visualization.visualize(result.trajectory);
82  }
83 
84  void
86  const std::optional<local_planning::LocalPlannerResult>& result)
87  {
88  if (result)
89  {
90  drawLocalTrajectory(result.value().trajectory);
91  }
92  else
93  {
94  drawLocalTrajectory(std::nullopt);
95  }
96 
97  arviz.commit(simox::alg::get_values(layers));
98  }
99 
100  // void
101  // ArvizIntrospector::onTrajectoryControllerResult(
102  // const traj_ctrl::TrajectoryControllerResult& result)
103  // {
104  // std::lock_guard g{mtx};
105 
106  // drawRawVelocity(result.twist);
107  // }
108 
109  // void
110  // ArvizIntrospector::onSafetyControllerResult(const safe_ctrl::SafetyControllerResult& result)
111  // {
112  // std::lock_guard g{mtx};
113 
114  // drawSafeVelocity(result.twist);
115  // }
116 
117  void
119  {
120  auto layer = arviz.layer("goal");
121  layer.add(viz::Pose("goal").pose(goal).scale(3));
122 
123  robotPosesLayer.clear();
124 
125  // arviz.commit({layer, robotPosesLayer});
126  arviz.commit({layer});
127 
128  // visualization.setTarget(goal);
129  }
130 
131  void
133  {
134 
135  constexpr float eps = 50; // [mm]
136 
137  if (not lastPose)
138  {
139  lastPose = pose;
140  }
141  else
142  {
143  // only draw poses every `eps` mm
144  if ((lastPose->translation() - pose.translation()).norm() < eps)
145  {
146  return;
147  }
148 
149  lastPose = pose;
150  }
151 
152  robotPosesLayer.add(viz::Pose("pose" + std::to_string(robotPosesLayer.size())).pose(pose));
153  arviz.commit(robotPosesLayer);
154  }
155 
156  void
157  ArvizIntrospector::onGlobalShortestPath(const std::vector<core::Pose>& path)
158  {
159  auto layer = arviz.layer("graph_shortest_path");
160 
161  const auto toPosition = [](const core::Pose& pose) -> core::Position
162  { return pose.translation(); };
163 
164 
165  std::vector<core::Position> pts;
166  pts.reserve(path.size());
167  std::transform(path.begin(), path.end(), std::back_inserter(pts), toPosition);
168 
169 
170  // layer.add(viz::Path("shortest_path").points(pts).color(viz::Color::purple()));
171 
172  for (size_t i = 0; i < (pts.size() - 1); i++)
173  {
174  layer.add(viz::Arrow("segment_" + std::to_string(i))
175  .fromTo(pts.at(i), pts.at(i + 1))
177  }
178 
179 
180  arviz.commit(layer);
181  }
182 
183  // private methods
184 
185  void
186  ArvizIntrospector::drawGlobalTrajectory(const core::GlobalTrajectory& trajectory)
187  {
188  auto layer = arviz.layer("global_planner");
189 
190  layer.add(
191  viz::Path("path").points(trajectory.positions()).color(simox::color::Color::blue()));
192 
193  const auto cmap = simox::color::cmaps::viridis();
194 
195  const float maxVelocity = ranges::max_element(trajectory.points(),
196  [](const auto& a, const auto& b)
197  { return a.velocity < b.velocity; })
198  ->velocity;
199 
200 
201  for (const auto& [idx, tp] : trajectory.points() | ranges::views::enumerate)
202  {
203  const float scale = tp.velocity;
204 
205  const Eigen::Vector3f target =
206  scale * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
207 
208  layer.add(
209  viz::Arrow("velocity_" + std::to_string(idx))
210  .fromTo(tp.waypoint.pose.translation(), tp.waypoint.pose.translation() + target)
211  .color(cmap.at(tp.velocity / maxVelocity)));
212  }
213 
214  layers[layer.data_.name] = std::move(layer);
215  }
216 
217  void
218  ArvizIntrospector::drawLocalTrajectory(const std::optional<core::LocalTrajectory>& input)
219  {
220  if (!input)
221  {
222  // no local trajectory found, remove old one
223  auto layer = arviz.layer("local_planner");
224  auto velLayer = arviz.layer("local_planner_velocity");
225 
226  layers[layer.data_.name] = std::move(layer);
227  layers[velLayer.data_.name] = std::move(velLayer);
228  return;
229  }
230 
231  const auto trajectory = input.value();
232 
233  auto layer = arviz.layer("local_planner");
234 
235  const std::vector<Eigen::Vector3f> points =
236  simox::alg::apply(trajectory.points(),
237  [](const core::LocalTrajectoryPoint& pt) -> Eigen::Vector3f
238  { return pt.pose.translation(); });
239 
240  layer.add(viz::Path("path").points(points).color(simox::Color::green()));
241 
242 
243  // Visualize trajectory speed
244  auto velLayer = arviz.layer("local_planner_velocity");
245 
246  simox::ColorMap cm = simox::color::cmaps::inferno();
247  cm.set_vmin(0);
248  cm.set_vmax(0.6);
249 
250  for (size_t i = 0; i < trajectory.points().size() - 1; i++)
251  {
252  const core::LocalTrajectoryPoint start = trajectory.points().at(i);
253  const core::LocalTrajectoryPoint end = trajectory.points().at(i + 1);
254 
255  const Duration dT = end.timestamp - start.timestamp;
256  const Eigen::Vector3f distance = end.pose.translation() - start.pose.translation();
257  const float speed = distance.norm() / 1000 / dT.toSecondsDouble();
258 
259  const Eigen::Vector3f pos = start.pose.translation() + distance / 2;
260  const simox::Color color = cm.at(speed);
261 
262  velLayer.add(
263  viz::Sphere("velocity_" + std::to_string(i)).position(pos).radius(50).color(color));
264  }
265 
266  layers[layer.data_.name] = std::move(layer);
267  layers[velLayer.data_.name] = std::move(velLayer);
268  }
269 
270  void
271  ArvizIntrospector::drawRawVelocity(const core::Twist& twist)
272  {
273  auto layer = arviz.layer("trajectory_controller");
274 
275  layer.add(viz::Arrow("linear_velocity")
276  .fromTo(robot->getGlobalPosition(),
277  core::Pose(robot->getGlobalPose()) * twist.linear)
279 
280  layers[layer.data_.name] = std::move(layer);
281  }
282 
283  void
284  ArvizIntrospector::drawSafeVelocity(const core::Twist& twist)
285  {
286  auto layer = arviz.layer("safety_controller");
287 
288  layer.add(viz::Arrow("linear_velocity")
289  .fromTo(robot->getGlobalPosition(),
290  core::Pose(robot->getGlobalPose()) * twist.linear)
292 
293  layers[layer.data_.name] = std::move(layer);
294  }
295 
297  arviz{other.arviz}, robot{other.robot}, layers(std::move(other.layers)) //,
298  // visualization(std::move(other.visualization))
299  {
300  }
301 
302  void
304  {
305  // clear all layers
306  for (auto& [name, layer] : layers)
307  {
308  layer.markForDeletion();
309  }
310  arviz.commit(simox::alg::get_values(layers));
311  layers.clear();
312 
313  // some special internal layers of TEB
314  arviz.commitDeleteLayer("local_planner_obstacles");
315  arviz.commitDeleteLayer("local_planner_velocity");
316  arviz.commitDeleteLayer("local_planner_path_alternatives");
317  }
318 
321  {
322  return *this;
323  }
324 
325  void
327  {
328  auto layer = arviz.layer("global_planning_graph");
329 
330  const objpose::ObjectPoseMap objects = objClient.fetchObjectPosesAsMap();
331  const std::vector<ObjectInfo> info = objClient.getObjectFinder().findAllObjects();
332 
333  for (const auto& edge : graph.edges())
334  {
335 
336  const auto sourcePose = graph.vertex(edge.sourceDescriptor()).attrib().getPose();
337  const auto targetPose = graph.vertex(edge.targetDescriptor()).attrib().getPose();
338 
339 
340  const viz::Color color = [&]()
341  {
342  if (edge.attrib().cost() > 100'000) // "NaN check"
343  {
344  return viz::Color::red();
345  }
346 
347  return viz::Color::green();
348  }();
349 
350  const auto from = core::resolveLocation(objects, info, sourcePose);
351  const auto to = core::resolveLocation(objects, info, sourcePose);
352 
353  if (from.pose.has_value() && to.pose.has_value())
354  {
355  layer.add(
356  viz::Arrow(std::to_string(edge.sourceObjectID().t) + " -> " +
357  std::to_string(edge.targetObjectID().t))
358  .fromTo(from.pose.value().translation(), to.pose.value().translation())
359  .color(color));
360  }
361  }
362 
363  arviz.commit(layer);
364  }
365 
366  void
367  ArvizIntrospector::success()
368  {
369  clear();
370 
371  // visualization.success();
372  }
373 
374  void
375  ArvizIntrospector::failure()
376  {
377  clear();
378 
379  // visualization.failed();
380  }
381 
382 
383 } // namespace armarx::navigation::server
armarx::navigation::core::GlobalTrajectory
Definition: Trajectory.h:68
armarx::viz::Client::commit
CommitResult commit(StagedCommit const &commit)
Definition: Client.cpp:80
armarx::navigation::server::ArvizIntrospector::onRobotPose
void onRobotPose(const core::Pose &pose) override
Definition: ArvizIntrospector.cpp:132
armarx::navigation::server::ArvizIntrospector::onGlobalShortestPath
void onGlobalShortestPath(const std::vector< core::Pose > &path) override
Definition: ArvizIntrospector.cpp:157
Path.h
armarx::navigation::server::asPackagePath
armarx::PackagePath asPackagePath(const std::string &absfilepath)
Definition: ArvizIntrospector.cpp:39
StackResult.h
armarx::viz::Color::purple
static Color purple(int p=255, int a=255)
2 Blue + 1 Red
Definition: Color.h:149
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::ObjectFinder::findAllObjects
std::vector< ObjectInfo > findAllObjects(bool checkPaths=true) const
Definition: ObjectFinder.cpp:144
armarx::viz::Layer::clear
void clear()
Definition: Layer.h:23
basic_types.h
Visualization.h
armarx::CMakePackageFinder::FindAllArmarXSourcePackages
static std::vector< std::string > FindAllArmarXSourcePackages()
Definition: CMakePackageFinder.cpp:438
armarx::viz::Client::commitDeleteLayer
void commitDeleteLayer(std::string const &name)
Definition: Client.h:169
armarx::navigation::global_planning::GlobalPlannerResult::trajectory
core::GlobalTrajectory trajectory
Definition: GlobalPlanner.h:40
armarx::navigation::server::ArvizIntrospector::ArvizIntrospector
ArvizIntrospector(armarx::viz::Client arviz, const VirtualRobot::RobotPtr &robot, const objpose::ObjectPoseClient &objClient)
Definition: ArvizIntrospector.cpp:60
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:688
armarx::viz::Arrow
Definition: Elements.h:198
armarx::viz::Layer::add
void add(ElementT const &element)
Definition: Layer.h:29
armarx::starts_with
bool starts_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:43
armarx::navigation::server::ArvizIntrospector::clear
void clear()
Definition: ArvizIntrospector.cpp:303
armarx::objpose::ObjectPoseClient
Provides access to the armarx::objpose::ObjectPoseStorageInterface (aka the object memory).
Definition: ObjectPoseClient.h:18
armarx::viz::Sphere
Definition: Elements.h:134
Elements.h
armarx::navigation::server
This file is part of ArmarX.
Definition: EventPublishingInterface.h:10
armarx::objpose::ObjectPoseClient::getObjectFinder
const ObjectFinder & getObjectFinder() const
Get the internal object finder.
Definition: ObjectPoseClient.cpp:97
armarx::navigation::server::ArvizIntrospector::onLocalPlannerResult
void onLocalPlannerResult(const std::optional< local_planning::LocalPlannerResult > &result) override
Definition: ArvizIntrospector.cpp:85
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
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:51
LocationUtils.h
Color.h
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::aron::input
ReaderT::InputType & input
Definition: rw.h:19
armarx::navigation::core::Graph
Definition: Graph.h:88
armarx::viz::Color
Definition: Color.h:13
armarx::viz::Pose
Definition: Elements.h:179
armarx::navigation::global_planning::GlobalPlannerResult
Definition: GlobalPlanner.h:38
armarx::navigation::server::ArvizIntrospector::onGlobalPlannerResult
void onGlobalPlannerResult(const global_planning::GlobalPlannerResult &result) override
Definition: ArvizIntrospector.cpp:73
armarx::navigation::server::ArvizIntrospector::onGoal
void onGoal(const core::Pose &goal) override
Definition: ArvizIntrospector.cpp:118
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::viz::Arrow::fromTo
Arrow & fromTo(const Eigen::Vector3f &from, const Eigen::Vector3f &to)
Definition: Elements.h:218
CMakePackageFinder.h
armarx::viz::ElementOps::pose
DerivedT & pose(Eigen::Matrix4f const &pose)
Definition: ElementOps.h:159
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:315
armarx::viz::ElementOps::color
DerivedT & color(Color color)
Definition: ElementOps.h:195
armarx::navigation::server::ArvizIntrospector::operator=
ArvizIntrospector & operator=(ArvizIntrospector &&) noexcept
Definition: ArvizIntrospector.cpp:320
armarx::navigation::core::GlobalTrajectory::positions
std::vector< Position > positions() const noexcept
Definition: Trajectory.cpp:330
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
armarx::viz::Layer::size
std::size_t size() const noexcept
Definition: Layer.h:48
armarx::navigation::server::ArvizIntrospector::onGlobalGraph
void onGlobalGraph(const core::Graph &graph) override
Definition: ArvizIntrospector.cpp:326
armarx::viz::ScopedClient::layer
Layer layer(std::string const &name) const
Definition: ScopedClient.cpp:34
Logging.h
armarx::navigation::core::Position
Eigen::Vector3f Position
Definition: basic_types.h:36
armarx::viz::Path
Definition: Path.h:31
armarx::viz::Client::layer
Layer layer(std::string const &name) const
Definition: Client.cpp:73
Trajectory.h
armarx::viz::Client
Definition: Client.h:109
ArmarXDataPath.h
armarx::PackagePath
Definition: PackagePath.h:55
armarx::navigation::server::ArvizIntrospector
Definition: ArvizIntrospector.h:52
armarx::navigation::core::GlobalTrajectory::points
const std::vector< GlobalTrajectoryPoint > & points() const
Definition: Trajectory.cpp:732
armarx::orange
QColor orange()
Definition: StyleSheets.h:80
types.h
armarx::armem::Duration
armarx::core::time::Duration Duration
Definition: forward_declarations.h:14
armarx::green
QColor green()
Definition: StyleSheets.h:72
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:18
ArvizIntrospector.h
PackagePath.h
armarx::objpose::ObjectPoseMap
std::map< ObjectID, ObjectPose > ObjectPoseMap
Definition: forward_declarations.h:21