7#include <Eigen/Geometry>
9#include <SimoxUtility/algorithm/apply.hpp>
10#include <SimoxUtility/algorithm/get_map_keys_values.h>
11#include <SimoxUtility/color/Color.h>
12#include <SimoxUtility/color/ColorMap.h>
13#include <SimoxUtility/color/hsv.h>
14#include <SimoxUtility/math/pose.h>
19#include <ArmarXCore/interface/core/PackagePath.h>
27#include <RobotAPI/interface/components/TrajectoryPlayerInterface.h>
29#include <RobotAPI/libraries/armem_laser_scans/aron/LaserScan.aron.generated.h>
46 p.enabled, prefix +
"enabled",
"Enable or disable visualization of objects.");
47 defs->optional(p.frequencyHz, prefix +
"frequenzyHz",
"Frequency of visualization.");
49 p.uniformColor, prefix +
"uniformColor",
"If enabled, points will be drawn in red.");
50 defs->optional(p.maxRobotAgeMs,
51 prefix +
"maxRobotAgeMs",
52 "Maximum age of robot state before a new one is retrieved in milliseconds.");
53 defs->optional(p.colorByIntensity,
"colorByIntensity",
"");
60 this->coreSegment = coreSegment;
61 this->virtualRobotReader = virtualRobotReader;
70 bool batchMode =
true;
87 CycleUtil cycle(
static_cast<int>(1000 / p.frequencyHz));
88 while (updateTask and not updateTask->
isStopped())
99 catch (
const std::exception& e)
101 ARMARX_WARNING <<
"Caught exception while visualizing robots: \n" << e.what();
105 ARMARX_WARNING <<
"Caught unknown exception while visualizing robots.";
108 if (debugObserver.has_value())
110 debugObserver->sendDebugObserverBatch();
113 cycle.waitForCycleDuration();
118 Visu::visualizeScan(
const std::vector<ScanPoint>& points,
119 const std::string& sensorName,
120 const std::string& agentName,
121 const viz::Color& color)
123 viz::PointCloud pointCloud(
"laser_scan");
125 ARMARX_VERBOSE <<
"Point cloud with " << points.size() <<
" points";
127 for (
const auto& point : points)
131 const viz::Color specificColor = [&point, &color,
this]() -> viz::Color
133 if (p.colorByIntensity)
135 Eigen::Vector3f hsv = simox::color::rgb_to_hsv(
136 Eigen::Vector3f(
static_cast<float>(color.r) / 255.f,
137 static_cast<float>(color.g) / 255.f,
138 static_cast<float>(color.b) / 255.f));
142 hsv(2) = std::clamp<float>(point.intensity, 0., 1.);
144 const Eigen::Vector3f rgb = simox::color::hsv_to_rgb(hsv);
146 return viz::Color{rgb(0), rgb(1), rgb(2)};
152 pointCloud.addPoint(point.point.x(), point.point.y(), point.point.z(), specificColor);
155 pointCloud.pointSizeInPixels(3);
157 viz::Layer l = arviz.layer(agentName +
"/" + sensorName);
163 std::vector<ScanPoint>
165 const Eigen::Isometry3f& global_T_sensor)
167 const auto scanCartesian =
170 std::vector<ScanPoint> points;
171 points.reserve(scan.
data.size());
173 for (std::size_t i = 0; i < scan.
data.size(); i++)
175 const auto& point = scanCartesian.at(i);
176 const auto& raw = scan.
data.at(i);
178 const Eigen::Vector3f pointGlobal = global_T_sensor * point;
179 points.push_back(
ScanPoint{.point = pointGlobal, .intensity = raw.intensity});
227 std::map<std::string, armem::laser_scans::LaserScanStamped>
228 Visu::getCurrentLaserScans()
235 const std::optional<armarx::armem::laser_scans::arondto::LaserScanStamped>
dto =
243 const auto ndArrayNavigator =
248 laserScanStamped.
data =
253 return laserScanStamped;
256 std::map<std::string, armem::laser_scans::LaserScanStamped> scans;
260 const auto scan =
convert(instance);
261 scans[instance.id().providerSegmentName +
"/" + instance.id().entityName] = scan;
264 const auto applyToEntity = [&](
const wm::Entity& entity)
271 const auto& snapshot = entity.getLatestSnapshot();
273 snapshot.forEachInstance(applyToInstance);
276 const auto applyToProviderSegment = [&](
const auto& providerSegment)
277 { providerSegment.forEachEntity(applyToEntity); };
279 coreSegment->forEachProviderSegment(applyToProviderSegment);
288 std::map<std::string, armem::laser_scans::LaserScanStamped> currentLaserScans =
289 getCurrentLaserScans();
293 for (
const auto& [provider, scan] : currentLaserScans)
297 const auto global_T_sensor = [&]() -> Eigen::Isometry3f
299 const auto robot = getSynchronizedRobot(scan.header.agent, scan.header.timestamp);
304 return Eigen::Isometry3f::Identity();
307 const auto sensorNode = robot->getRobotNode(scan.header.frame);
309 <<
"` for robot `" << scan.header.agent <<
"`";
311 ARMARX_VERBOSE <<
"Sensor position for sensor `" << scan.header.frame <<
"` is "
312 << sensorNode->getGlobalPosition();
313 return Eigen::Isometry3f{sensorNode->getGlobalPose()};
319 const auto color = [&]() -> simox::Color
323 return simox::Color::red();
326 return simox::color::GlasbeyLUT::at(i++);
329 visualizeScan(points, scan.header.frame, scan.header.agent, color);
334 Visu::getSynchronizedRobot(
const std::string& name,
const DateTime&
timestamp)
336 if (robots.count(name) == 0)
339 const auto robot = virtualRobotReader->getRobot(name);
351 auto& entry = robots.at(name);
352 if (entry.second.isInvalid() ||
355 if (virtualRobotReader->synchronizeRobotPose(*entry.first,
timestamp))
This util class helps with keeping a cycle time during a control cycle.
static DateTime Invalid()
Brief description of class DebugObserverHelper.
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
void setTag(const LogTag &tag)
bool isStopped()
Retrieve whether stop() has been called.
The VirtualRobotReader class.
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="visu.")
void connect(const viz::Client &arviz, DebugObserverInterfacePrx debugObserver=nullptr)
void init(const wm::CoreSegment *coreSegment, armem::robot_state::VirtualRobotReader *virtualRobotReader)
static PointerType DynamicCast(const VariantPtr &n)
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
std::shared_ptr< class Robot > RobotPtr
EigenVectorT toCartesian(const LaserScanStep &laserScanStep)
SensorHeader fromAron(const arondto::SensorHeader &aronSensorHeader)
This file is part of ArmarX.
std::vector< ScanPoint > convertScanToGlobal(const armem::laser_scans::LaserScanStamped &scan, const Eigen::Isometry3f &global_T_sensor)
armem::wm::EntityInstance EntityInstance
void fromAron(const arondto::MemoryID &dto, MemoryID &bo)
armarx::core::time::DateTime Time
std::string toStringMilliSeconds(const Time &time, int decimals=3)
Returns time as e.g.
std::optional< AronClass > tryCast(const wm::EntityInstance &item)
Tries to cast a armem::EntityInstance to AronClass.
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
armem::articulated_object::ArticulatedObject convert(const VirtualRobot::Robot &obj, const armem::Time ×tamp)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
SimpleRunningTask(Ts...) -> SimpleRunningTask< std::function< void(void)> >
void add(ElementT const &element)