7 #include <Eigen/Geometry>
9 #include <SimoxUtility/algorithm/get_map_keys_values.h>
10 #include <SimoxUtility/algorithm/string/string_tools.h>
11 #include <SimoxUtility/math/pose.h>
12 #include <SimoxUtility/math/rescale.h>
13 #include <VirtualRobot/Nodes/Sensor.h>
14 #include <VirtualRobot/XML/RobotIO.h>
19 #include <ArmarXCore/interface/core/PackagePath.h>
36 descriptionSegment(descriptionSegment),
37 proprioceptionSegment(proprioceptionSegment),
38 localizationSegment(localizationSegment)
47 p.enabled, prefix +
"enabled",
"Enable or disable visualization of objects.");
48 defs->optional(p.frequencyHz, prefix +
"frequenzyHz",
"Frequency of visualization.");
49 defs->optional(p.framesEnabled,
50 prefix +
"framesEnabled",
51 "Enable or disable visualization of frames.");
52 defs->optional(p.forceTorque.enabled,
53 prefix +
"forceTorque.enabled",
54 "Enable or disable visualization of force torque sensors.");
55 defs->optional(p.forceTorque.forceScale,
56 prefix +
"forceTorque.forceScale",
57 "Scaling of force arrows.");
58 defs->optional(p.collisionModelEnabled,
59 prefix +
"collisionModelEnabled",
60 "Enable visualization of collision model.");
74 bool batchMode =
true;
95 const armarx::data::PackagePath xmlPath = robot.description.xml.serialize();
97 const auto* robotModel = getRobotModel(robot.description);
99 std::map<std::string, float> jointMap = robot.config.jointMap;
102 if (robotModel !=
nullptr)
104 for (
const auto& [jointName, jointValue] : robotModel->model->getJointValues())
106 if (jointMap.count(jointName) == 0)
108 jointMap[jointName] = jointValue;
115 .file(xmlPath.package, xmlPath.package +
"/" + xmlPath.path)
117 .pose(robot.config.globalPose);
129 layer.
add(robotVisu);
134 Visu::visualizeFrames(
136 const std::unordered_map<std::string, std::vector<Eigen::Isometry3f>>& frames)
138 for (
const auto& [robotName, robotFrames] : frames)
143 for (
const auto& frame : robotFrames)
145 Eigen::Isometry3f from = pose;
146 Eigen::Isometry3f to = pose * frame;
151 .fromTo(from.translation(), to.translation()));
157 Visu::visualizeFramesIndividual(
159 const std::unordered_map<std::string, std::vector<Eigen::Isometry3f>>& frames)
162 std::vector<std::string> FRAME_NAMES{
"map",
"odom",
"robot"};
164 for (
const auto& [robotName, robotFrames] : frames)
167 for (
const auto& frame : robotFrames)
178 CycleUtil cycle(
static_cast<int>(1000 / p.frequencyHz));
179 while (updateTask and not updateTask->isStopped())
188 visualizeOnce(timestamp);
190 catch (
const std::out_of_range& e)
192 ARMARX_WARNING <<
"Caught std::out_of_range while visualizing robots: \n"
195 catch (
const std::exception& e)
197 ARMARX_WARNING <<
"Caught exception while visualizing robots: \n" << e.what();
201 ARMARX_WARNING <<
"Caught unknown exception while visualizing robots.";
204 if (debugObserver.has_value())
206 debugObserver->sendDebugObserverBatch();
209 cycle.waitForCycleDuration();
214 Visu::visualizeOnce(
const Time& timestamp)
239 debugObserver ? &*debugObserver :
nullptr);
254 <<
"\n- " << robotDescriptions.size() <<
" descriptions"
255 <<
"\n- " << globalPoses.size() <<
" global poses"
256 <<
"\n- " << sensorValues.size() <<
" joint positions";
259 combine(robotDescriptions, globalPoses, sensorValues, timestamp);
262 std::vector<viz::Layer> layers;
266 visualizeRobots(layer,
robots,
false);
269 if (p.collisionModelEnabled)
272 visualizeRobots(layer,
robots,
true);
278 viz::Layer& layer = layers.emplace_back(arviz.
layer(
"Localization Frames"));
279 visualizeFrames(layer, frames);
285 viz::Layer& layer = layers.emplace_back(arviz.
layer(
"Localization Frames Individual"));
286 visualizeFramesIndividual(layer, frames);
289 if (p.forceTorque.enabled)
291 viz::Layer& layerForceTorque = layers.emplace_back(arviz.
layer(
"Force Torque"));
292 std::stringstream log;
296 const std::string& robotName = robot.description.name;
298 auto itSensorValues = sensorValues.find(robotName);
299 if (itSensorValues == sensorValues.end())
301 log <<
"\nNo robot '" << robotName <<
"' in sensor values. Available are: ";
302 log << simox::alg::join(simox::alg::get_keys(sensorValues),
", ");
306 visualizeForceTorque(layerForceTorque, robot, itSensorValues->second);
309 if (not log.str().empty())
311 ARMARX_INFO <<
"While visualizing robot force torques: " << log.str();
325 if (debugObserver.has_value())
327 const std::string p =
"Visu | ";
328 debugObserver->setDebugObserverDatafield(p +
"t Total (ms)",
329 tVisuTotal.toMilliSecondsDouble());
330 debugObserver->setDebugObserverDatafield(p +
"t 1 Get Data (ms)",
331 tVisuGetData.toMilliSecondsDouble());
332 debugObserver->setDebugObserverDatafield(p +
"t 1.1 Descriptions (ms)",
333 tRobotDescriptions.toMilliSecondsDouble());
334 debugObserver->setDebugObserverDatafield(p +
"t 1.2 Global Poses (ms)",
335 tGlobalPoses.toMilliSecondsDouble());
336 debugObserver->setDebugObserverDatafield(p +
"t 1.3 Frames (ms)",
337 tRobotFramePoses.toMilliSecondsDouble());
338 debugObserver->setDebugObserverDatafield(p +
"t 1.4 Sensor Values (ms)",
339 tSensorValues.toMilliSecondsDouble());
340 debugObserver->setDebugObserverDatafield(p +
"t 2 Build Layers (ms)",
341 tVisuBuildLayers.toMilliSecondsDouble());
342 debugObserver->setDebugObserverDatafield(p +
"t 3 Commit (ms)",
343 tVisuCommit.toMilliSecondsDouble());
348 Visu::getRobotModel(
const armem::robot_state::description::RobotDescription& robotDescription)
350 const std::string& robotName = robotDescription.name;
352 RobotModel* robotModel =
nullptr;
353 if (
auto it = models.find(robotName); it != models.end())
355 robotModel = &it->second;
359 const std::filesystem::path robotPath = robotDescription.xml.toSystemPath();
360 ARMARX_INFO <<
"Loading robot model for '" << robotName <<
"' from " << robotPath
361 <<
" for visualization.";
362 auto [it2, _] = models.emplace(robotName, robotPath);
363 robotModel = &it2->second;
371 const proprioception::SensorValues& sensorValues)
374 Visu::RobotModel* robotModel = getRobotModel(robot.description);
376 if (robotModel ==
nullptr)
382 robotModel->model->setJointValues(robot.config.jointMap);
383 robotModel->model->setGlobalPose(robot.config.globalPose.matrix());
386 sensorValues.forceTorqueValuesMap;
388 for (
const auto& [side, ft] : forceTorques)
394 const std::string forceTorqueSensorName =
395 robotModel->nameHelper->getArm(side).getForceTorqueSensor();
398 robotModel->model->getSensor(forceTorqueSensorName)->getGlobalPose();
400 const std::string xyz =
"XYZ";
402 const Eigen::Vector3f from = simox::math::position(forceTorqueSensorPose);
403 for (
int i = 0; i < 3; ++i)
410 const float length = p.forceTorque.forceScale * ft.force(i);
414 const Eigen::Vector3f to =
415 from + length * simox::math::orientation(forceTorqueSensorPose).col(i);
417 std::stringstream key;
419 key << side <<
" Force " << xyz.at(i);
427 Visu::RobotModel::RobotModel(
const std::filesystem::path& robotPath) :
429 VirtualRobot::RobotIO::loadRobot(robotPath, VirtualRobot::RobotIO::eStructure),