11#include <Eigen/Geometry>
13#include <range/v3/algorithm/max_element.hpp>
15#include <SimoxUtility/algorithm/apply.hpp>
16#include <SimoxUtility/algorithm/get_map_keys_values.h>
17#include <SimoxUtility/algorithm/string/string_tools.h>
18#include <SimoxUtility/color/Color.h>
19#include <SimoxUtility/color/ColorMap.h>
20#include <SimoxUtility/color/cmaps/colormaps.h>
21#include <VirtualRobot/Robot.h>
22#include <VirtualRobot/VirtualRobot.h>
53 constexpr float markerSpacing = 200.F;
61 std::vector<std::size_t>
62 subsample(
const std::vector<core::GlobalTrajectoryPoint>& points,
const float spacing)
64 if (points.size() < 2)
66 return points.empty() ? std::vector<std::size_t>{} : std::vector<std::size_t>{0};
69 std::vector<std::size_t>
indices{0};
70 float sinceLast = 0.F;
72 for (std::size_t i = 1; i + 1 < points.size(); i++)
74 sinceLast += (points.at(i).waypoint.pose.translation() -
75 points.at(i - 1).waypoint.pose.translation())
78 if (sinceLast >= spacing)
85 indices.push_back(points.size() - 1);
91 inline armarx::PackagePath
94 const std::vector<std::string> packages =
96 const std::string
package = armarx::ArmarXDataPath::getProject(packages, absfilepath);
99 const std::string relPath = [&absfilepath, &package]() -> std::string
101 if (simox::alg::starts_with(absfilepath, package))
104 return absfilepath.substr(package.size() + 1, -1);
110 return {package, relPath};
114 const VirtualRobot::RobotConstPtr& robot,
116 arviz(arviz), robot(robot), objClient(objClient)
120 robotPosesLayer = arviz.layer(
"robot_poses");
128 ARMARX_DEBUG <<
"ArvizIntrospector::onGlobalPlannerResult";
138 auto layer = arviz.layer(
"global_helper_trajectory");
139 layers[layer.data_.name] = std::move(layer);
141 arviz.commit(simox::alg::get_values(layers));
150 ARMARX_DEBUG <<
"ArvizIntrospector::onGlobalPlannerSubdivision";
152 drawGlobalPathSubdivision(subdivision);
161 auto layer = arviz.layer(
"global_helper_trajectory");
162 layers[layer.data_.name] = std::move(layer);
165 arviz.commit(simox::alg::get_values(layers));
170 const std::optional<local_planning::LocalPlannerResult>& result)
174 drawLocalTrajectory(result.value().trajectory);
178 drawLocalTrajectory(std::nullopt);
181 arviz.commit(simox::alg::get_values(layers));
204 auto layer = arviz.layer(
"goal");
205 layer.add(
viz::Pose(
"goal").pose(goal).scale(3));
211 robotPosesLayer.clear();
213 arviz.commit({layer, robotPosesLayer});
223 constexpr float recordingSpacing = 50.F;
225 if (lastPose and (lastPose->translation() - pose.translation()).norm() < recordingSpacing)
231 travelled.push_back(pose);
236 robotPosesLayer.clear();
238 std::vector<core::Position> positions;
239 positions.reserve(travelled.size());
240 std::transform(travelled.begin(),
242 std::back_inserter(positions),
246 viz::Path(
"travelled").points(positions).color(viz::Color::orange()).width(10));
248 const auto markerStride =
249 static_cast<std::size_t
>(std::max(1.F, markerSpacing / recordingSpacing));
251 for (std::size_t i = 0; i < travelled.size(); i += markerStride)
253 robotPosesLayer.add(
viz::Pose(
"pose" + std::to_string(i)).pose(travelled.at(i)));
256 arviz.commit(robotPosesLayer);
262 auto layer = arviz.layer(
"graph_shortest_path");
265 {
return pose.translation(); };
268 std::vector<core::Position> pts;
269 pts.reserve(path.size());
270 std::transform(path.begin(), path.end(), std::back_inserter(pts), toPosition);
275 for (
size_t i = 0; i < (pts.size() - 1); i++)
277 layer.add(
viz::Arrow(
"segment_" + std::to_string(i))
278 .fromTo(pts.at(i), pts.at(i + 1))
279 .
color(viz::Color::purple()));
292 drawGlobalTrajectory(
trajectory,
"global_planner", simox::Color::blue());
298 drawGlobalTrajectory(
trajectory,
"global_helper_trajectory", simox::Color::gray());
302 ArvizIntrospector::drawGlobalTrajectory(
const core::GlobalTrajectory&
trajectory,
303 const std::string layerName,
304 simox::color::Color color)
306 auto layer = arviz.
layer(layerName);
310 const auto cmap = simox::color::cmaps::viridis();
312 const float maxVelocity = ranges::max_element(
trajectory.points(),
318 for (
const std::size_t idx : subsample(
trajectory.points(), markerSpacing))
320 const core::GlobalTrajectoryPoint& tp =
trajectory.points().at(idx);
321 const float scale = tp.velocity;
323 const Eigen::Vector3f target =
324 scale * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
328 .fromTo(tp.waypoint.pose.translation(), tp.waypoint.pose.translation() + target)
329 .
color(cmap.at(tp.velocity / maxVelocity)));
332 layers[layer.data_.name] = std::move(layer);
338 if (subdivision.subdivision.empty())
341 drawGlobalTrajectory(subdivision.plan.trajectory);
345 auto layer = arviz.layer(
"global_path_subdivision");
347 for (
const auto& segment : subdivision.subdivision)
349 viz::Path path(
"segment_" + std::to_string(segment.s));
351 const auto& subTrajectory = subdivision.plan.trajectory.getSubTrajectory(
352 segment.s, std::min(segment.t + 1, subdivision.plan.trajectory.points().size()));
353 path.points(subTrajectory.positions());
355 path.color(segment.useLocalPlanner ? simox::Color::blue() : simox::Color::red()));
358 const auto cmap = simox::color::cmaps::viridis();
359 const float maxVelocity = ranges::max_element(subdivision.plan.trajectory.points(),
364 for (
const std::size_t idx :
365 subsample(subdivision.plan.trajectory.points(), markerSpacing))
367 const core::GlobalTrajectoryPoint& tp = subdivision.plan.trajectory.points().at(idx);
368 const float scale = tp.velocity;
370 const Eigen::Vector3f
target =
371 scale * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
374 viz::Arrow(
"velocity_" + std::to_string(idx))
375 .fromTo(tp.waypoint.pose.translation(), tp.waypoint.pose.translation() + target)
376 .color(cmap.at(tp.velocity / maxVelocity)));
379 layers[layer.data_.name] = std::move(layer);
383 ArvizIntrospector::drawLocalTrajectory(
const std::optional<core::LocalTrajectory>& input)
388 auto layer = arviz.layer(
"local_planner");
389 auto velLayer = arviz.layer(
"local_planner_velocity");
391 layers[layer.data_.name] = std::move(layer);
392 layers[velLayer.data_.name] = std::move(velLayer);
396 const auto trajectory = input.value();
398 auto layer = arviz.layer(
"local_planner");
400 const std::vector<Eigen::Vector3f> points =
401 simox::alg::apply(trajectory.points(),
402 [](
const core::LocalTrajectoryPoint& pt) -> Eigen::Vector3f
403 { return pt.pose.translation(); });
405 layer.add(viz::Path(
"path").points(points).color(simox::Color::green()));
409 auto velLayer = arviz.layer(
"local_planner_velocity");
411 simox::ColorMap cm = simox::color::cmaps::inferno();
415 for (
size_t i = 0; i < trajectory.points().size() - 1; i++)
417 const core::LocalTrajectoryPoint start = trajectory.points().at(i);
418 const core::LocalTrajectoryPoint end = trajectory.points().at(i + 1);
420 const Duration dT = end.timestamp - start.timestamp;
421 const Eigen::Vector3f
distance = end.pose.translation() - start.pose.translation();
424 const Eigen::Vector3f pos = start.pose.translation() +
distance / 2;
425 const simox::Color color = cm.at(speed);
428 viz::Sphere(
"velocity_" + std::to_string(i)).position(pos).radius(50).color(color));
431 layers[layer.data_.name] = std::move(layer);
432 layers[velLayer.data_.name] = std::move(velLayer);
436 ArvizIntrospector::drawRawVelocity(
const core::Twist& twist)
438 auto layer = arviz.layer(
"trajectory_controller");
440 layer.add(viz::Arrow(
"linear_velocity")
441 .fromTo(robot->getGlobalPosition(),
442 core::Pose(robot->getGlobalPose()) * twist.linear)
443 .color(simox::Color::orange()));
445 layers[layer.data_.name] = std::move(layer);
449 ArvizIntrospector::drawSafeVelocity(
const core::Twist& twist)
451 auto layer = arviz.layer(
"safety_guard");
453 layer.add(viz::Arrow(
"linear_velocity")
454 .fromTo(robot->getGlobalPosition(),
455 core::Pose(robot->getGlobalPose()) * twist.linear)
456 .color(simox::Color::green()));
458 layers[layer.data_.name] = std::move(layer);
464 layers(std::move(other.layers)),
465 lastPose(other.lastPose),
466 travelled(std::move(other.travelled)),
471 robotPosesLayer(std::move(other.robotPosesLayer))
480 for (
auto& [name, layer] : layers)
482 layer.markForDeletion();
484 arviz.commit(simox::alg::get_values(layers));
488 arviz.commitDeleteLayer(
"local_planner_obstacles");
489 arviz.commitDeleteLayer(
"local_planner_velocity");
490 arviz.commitDeleteLayer(
"local_planner_path_alternatives");
502 auto layer = arviz.layer(
"global_planning_graph");
505 const std::vector<ObjectInfo> info = objClient.getObjectFinder().findAllObjects();
507 for (
const auto& edge :
graph.edges())
510 const auto sourcePose =
graph.vertex(edge.sourceDescriptor()).attrib().getPose();
511 const auto targetPose =
graph.vertex(edge.targetDescriptor()).attrib().getPose();
516 if (edge.attrib().cost() > 100'000)
518 return viz::Color::red();
521 return viz::Color::green();
527 if (from.pose.has_value() && to.pose.has_value())
530 viz::Arrow(std::to_string(edge.sourceObjectID().t) +
" -> " +
531 std::to_string(edge.targetObjectID().t))
532 .
fromTo(from.pose.value().translation(), to.pose.value().translation())
static std::vector< std::string > FindAllArmarXSourcePackages()
double toSecondsDouble() const
Returns the amount of seconds.
void onRobotPose(const core::Pose &pose) override
ArvizIntrospector(armarx::viz::Client arviz, const VirtualRobot::RobotConstPtr &robot, const objpose::ObjectPoseClient &objClient)
void onGlobalShortestPath(const std::vector< core::Pose > &path) override
void onGlobalGraph(const core::Graph &graph) override
void onGlobalPlannerResult(const global_planning::GlobalPlannerResult &result) override
ArvizIntrospector & operator=(ArvizIntrospector &&) noexcept
void callGenericDrawFunction(std::function< void(viz::Client &)>) override
void onGlobalPlannerSubdivision(const GlobalPathSubdivision &subdivision) override
void onGoal(const core::Pose &goal) override
void onLocalPlannerResult(const std::optional< local_planning::LocalPlannerResult > &result) override
Provides access to the armarx::objpose::ObjectPoseStorageInterface (aka the object memory).
DerivedT & color(Color color)
Layer layer(std::string const &name) const override
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
armarx::core::time::Duration Duration
void resolveLocation(Graph::Vertex &vertex, const aron::data::DictPtr &locationData)
This file is part of ArmarX.
This file is part of ArmarX.
armarx::PackagePath asPackagePath(const std::string &absfilepath)
std::map< ObjectID, ObjectPose > ObjectPoseMap
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
pcl::PointIndices::Ptr indices(const PCG &g)
Retrieve the indices of the points of the point cloud stored in a point cloud graph that actually bel...
double distance(const Point &a, const Point &b)
core::GlobalTrajectory trajectory
std::optional< core::GlobalTrajectory > helperTrajectory
Optional helper trajectory that can be used for visualization or debugging purposes.
global_planning::GlobalPlannerResult plan
Arrow & fromTo(const Eigen::Vector3f &from, const Eigen::Vector3f &to)
void add(ElementT const &element)