11#include <Eigen/Geometry>
13#include <range/v3/algorithm/max_element.hpp>
14#include <range/v3/view/enumerate.hpp>
16#include <SimoxUtility/algorithm/apply.hpp>
17#include <SimoxUtility/algorithm/get_map_keys_values.h>
18#include <SimoxUtility/algorithm/string/string_tools.h>
19#include <SimoxUtility/color/Color.h>
20#include <SimoxUtility/color/ColorMap.h>
21#include <SimoxUtility/color/cmaps/colormaps.h>
22#include <VirtualRobot/Robot.h>
23#include <VirtualRobot/VirtualRobot.h>
49 inline armarx::PackagePath
52 const std::vector<std::string> packages =
54 const std::string
package = armarx::ArmarXDataPath::getProject(packages, absfilepath);
57 const std::string relPath = [&absfilepath, &package]() -> std::string
59 if (simox::alg::starts_with(absfilepath, package))
62 return absfilepath.substr(package.size() + 1, -1);
68 return {package, relPath};
72 const VirtualRobot::RobotConstPtr& robot,
74 arviz(arviz), robot(robot), objClient(objClient)
78 robotPosesLayer = arviz.layer(
"robot_poses");
86 ARMARX_DEBUG <<
"ArvizIntrospector::onGlobalPlannerResult";
96 auto layer = arviz.layer(
"global_helper_trajectory");
97 layers[layer.data_.name] = std::move(layer);
99 arviz.commit(simox::alg::get_values(layers));
108 ARMARX_DEBUG <<
"ArvizIntrospector::onGlobalPlannerSubdivision";
110 drawGlobalPathSubdivision(subdivision);
119 auto layer = arviz.layer(
"global_helper_trajectory");
120 layers[layer.data_.name] = std::move(layer);
123 arviz.commit(simox::alg::get_values(layers));
128 const std::optional<local_planning::LocalPlannerResult>& result)
132 drawLocalTrajectory(result.value().trajectory);
136 drawLocalTrajectory(std::nullopt);
139 arviz.commit(simox::alg::get_values(layers));
162 auto layer = arviz.layer(
"goal");
163 layer.add(
viz::Pose(
"goal").pose(goal).scale(3));
165 robotPosesLayer.clear();
168 arviz.commit({layer});
177 constexpr float eps = 50;
186 if ((lastPose->translation() - pose.translation()).norm() < eps)
194 robotPosesLayer.add(
viz::Pose(
"pose" + std::to_string(robotPosesLayer.size())).
pose(pose));
195 arviz.commit(robotPosesLayer);
201 auto layer = arviz.layer(
"graph_shortest_path");
204 {
return pose.translation(); };
207 std::vector<core::Position> pts;
208 pts.reserve(path.size());
209 std::transform(path.begin(), path.end(), std::back_inserter(pts), toPosition);
214 for (
size_t i = 0; i < (pts.size() - 1); i++)
216 layer.add(
viz::Arrow(
"segment_" + std::to_string(i))
217 .fromTo(pts.at(i), pts.at(i + 1))
218 .
color(viz::Color::purple()));
231 drawGlobalTrajectory(
trajectory,
"global_planner", simox::Color::blue());
237 drawGlobalTrajectory(
trajectory,
"global_helper_trajectory", simox::Color::gray());
241 ArvizIntrospector::drawGlobalTrajectory(
const core::GlobalTrajectory&
trajectory,
242 const std::string layerName,
243 simox::color::Color color)
245 auto layer = arviz.
layer(layerName);
249 const auto cmap = simox::color::cmaps::viridis();
251 const float maxVelocity = ranges::max_element(
trajectory.points(),
257 for (
const auto& [idx, tp] :
trajectory.points() | ranges::views::enumerate)
259 const float scale = tp.velocity;
261 const Eigen::Vector3f target =
262 scale * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
266 .fromTo(tp.waypoint.pose.translation(), tp.waypoint.pose.translation() + target)
267 .
color(cmap.at(tp.velocity / maxVelocity)));
270 layers[layer.data_.name] = std::move(layer);
276 if (subdivision.subdivision.empty())
279 drawGlobalTrajectory(subdivision.plan.trajectory);
283 auto layer = arviz.layer(
"global_path_subdivision");
285 for (
const auto& segment : subdivision.subdivision)
287 viz::Path path(
"segment_" + std::to_string(segment.s));
289 const auto& subTrajectory = subdivision.plan.trajectory.getSubTrajectory(
290 segment.s, std::min(segment.t + 1, subdivision.plan.trajectory.points().size()));
291 path.points(subTrajectory.positions());
293 path.color(segment.useLocalPlanner ? simox::Color::blue() : simox::Color::red()));
296 const auto cmap = simox::color::cmaps::viridis();
297 const float maxVelocity = ranges::max_element(subdivision.plan.trajectory.points(),
302 for (
const auto& [idx, tp] :
303 subdivision.plan.trajectory.points() | ranges::views::enumerate)
305 const float scale = tp.velocity;
307 const Eigen::Vector3f
target =
308 scale * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
311 viz::Arrow(
"velocity_" + std::to_string(idx))
312 .fromTo(tp.waypoint.pose.translation(), tp.waypoint.pose.translation() + target)
313 .color(cmap.at(tp.velocity / maxVelocity)));
316 layers[layer.data_.name] = std::move(layer);
320 ArvizIntrospector::drawLocalTrajectory(
const std::optional<core::LocalTrajectory>& input)
325 auto layer = arviz.layer(
"local_planner");
326 auto velLayer = arviz.layer(
"local_planner_velocity");
328 layers[layer.data_.name] = std::move(layer);
329 layers[velLayer.data_.name] = std::move(velLayer);
333 const auto trajectory = input.value();
335 auto layer = arviz.layer(
"local_planner");
337 const std::vector<Eigen::Vector3f> points =
338 simox::alg::apply(trajectory.points(),
339 [](
const core::LocalTrajectoryPoint& pt) -> Eigen::Vector3f
340 { return pt.pose.translation(); });
342 layer.add(viz::Path(
"path").points(points).color(simox::Color::green()));
346 auto velLayer = arviz.layer(
"local_planner_velocity");
348 simox::ColorMap cm = simox::color::cmaps::inferno();
352 for (
size_t i = 0; i < trajectory.points().size() - 1; i++)
354 const core::LocalTrajectoryPoint start = trajectory.points().at(i);
355 const core::LocalTrajectoryPoint end = trajectory.points().at(i + 1);
357 const Duration dT = end.timestamp - start.timestamp;
358 const Eigen::Vector3f
distance = end.pose.translation() - start.pose.translation();
361 const Eigen::Vector3f pos = start.pose.translation() +
distance / 2;
362 const simox::Color color = cm.at(speed);
365 viz::Sphere(
"velocity_" + std::to_string(i)).position(pos).radius(50).color(color));
368 layers[layer.data_.name] = std::move(layer);
369 layers[velLayer.data_.name] = std::move(velLayer);
373 ArvizIntrospector::drawRawVelocity(
const core::Twist& twist)
375 auto layer = arviz.layer(
"trajectory_controller");
377 layer.add(viz::Arrow(
"linear_velocity")
378 .fromTo(robot->getGlobalPosition(),
379 core::Pose(robot->getGlobalPose()) * twist.linear)
380 .color(simox::Color::orange()));
382 layers[layer.data_.name] = std::move(layer);
386 ArvizIntrospector::drawSafeVelocity(
const core::Twist& twist)
388 auto layer = arviz.layer(
"safety_guard");
390 layer.add(viz::Arrow(
"linear_velocity")
391 .fromTo(robot->getGlobalPosition(),
392 core::Pose(robot->getGlobalPose()) * twist.linear)
393 .color(simox::Color::green()));
395 layers[layer.data_.name] = std::move(layer);
399 arviz{other.arviz}, robot{other.robot}, layers(std::move(other.layers))
408 for (
auto& [name, layer] : layers)
410 layer.markForDeletion();
412 arviz.commit(simox::alg::get_values(layers));
416 arviz.commitDeleteLayer(
"local_planner_obstacles");
417 arviz.commitDeleteLayer(
"local_planner_velocity");
418 arviz.commitDeleteLayer(
"local_planner_path_alternatives");
430 auto layer = arviz.layer(
"global_planning_graph");
433 const std::vector<ObjectInfo> info = objClient.getObjectFinder().findAllObjects();
435 for (
const auto& edge :
graph.edges())
438 const auto sourcePose =
graph.vertex(edge.sourceDescriptor()).attrib().getPose();
439 const auto targetPose =
graph.vertex(edge.targetDescriptor()).attrib().getPose();
444 if (edge.attrib().cost() > 100'000)
446 return viz::Color::red();
449 return viz::Color::green();
455 if (from.pose.has_value() && to.pose.has_value())
458 viz::Arrow(std::to_string(edge.sourceObjectID().t) +
" -> " +
459 std::to_string(edge.targetObjectID().t))
460 .
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 & pose(Eigen::Matrix4f const &pose)
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 &)
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)