7 #include <Eigen/Geometry>
9 #include <SimoxUtility/algorithm/get_map_keys_values.h>
10 #include <SimoxUtility/math/pose.h>
11 #include <SimoxUtility/math/rescale.h>
12 #include <VirtualRobot/XML/RobotIO.h>
17 #include <ArmarXCore/interface/core/PackagePath.h>
34 descriptionSegment(descriptionSegment),
35 proprioceptionSegment(proprioceptionSegment),
36 localizationSegment(localizationSegment)
45 p.enabled, prefix +
"enabled",
"Enable or disable visualization of objects.");
46 defs->optional(p.frequencyHz, prefix +
"frequenzyHz",
"Frequency of visualization.");
47 defs->optional(p.framesEnabled,
48 prefix +
"framesEnabled",
49 "Enable or disable visualization of frames.");
50 defs->optional(p.forceTorque.enabled,
51 prefix +
"forceTorque.enabled",
52 "Enable or disable visualization of force torque sensors.");
53 defs->optional(p.forceTorque.forceScale,
54 prefix +
"forceTorque.forceScale",
55 "Scaling of force arrows.");
56 defs->optional(p.collisionModelEnabled,
57 prefix +
"collisionModelEnabled",
58 "Enable visualization of collision model.");
72 bool batchMode =
true;
93 const armarx::data::PackagePath xmlPath = robot.description.xml.serialize();
95 const auto* robotModel = getRobotModel(robot.description);
97 std::map<std::string, float> jointMap = robot.config.jointMap;
100 if(robotModel !=
nullptr)
102 for(
const auto& [jointName, jointValue]: robotModel->model->getJointValues())
104 if(jointMap.count(jointName) == 0)
106 jointMap[jointName] = jointValue;
114 .file(xmlPath.package, xmlPath.package +
"/" + xmlPath.path)
116 .pose(robot.config.globalPose);
128 layer.
add(robotVisu);
133 Visu::visualizeFrames(
135 const std::unordered_map<std::string, std::vector<Eigen::Isometry3f>>& frames)
137 for (
const auto& [robotName, robotFrames] : frames)
142 for (
const auto& frame : robotFrames)
144 Eigen::Isometry3f from = pose;
145 Eigen::Isometry3f to = pose * frame;
150 .fromTo(from.translation(), to.translation()));
156 Visu::visualizeFramesIndividual(
158 const std::unordered_map<std::string, std::vector<Eigen::Isometry3f>>& frames)
161 std::vector<std::string> FRAME_NAMES{
"map",
"odom",
"robot"};
163 for (
const auto& [robotName, robotFrames] : frames)
166 for (
const auto& frame : robotFrames)
177 CycleUtil cycle(
static_cast<int>(1000 / p.frequencyHz));
178 while (updateTask and not updateTask->isStopped())
187 visualizeOnce(timestamp);
189 catch (
const std::out_of_range& e)
191 ARMARX_WARNING <<
"Caught std::out_of_range while visualizing robots: \n"
194 catch (
const std::exception& e)
196 ARMARX_WARNING <<
"Caught exception while visualizing robots: \n" << e.what();
200 ARMARX_WARNING <<
"Caught unknown exception while visualizing robots.";
203 if (debugObserver.has_value())
205 debugObserver->sendDebugObserverBatch();
208 cycle.waitForCycleDuration();
213 Visu::visualizeOnce(
const Time& timestamp)
238 debugObserver ? &*debugObserver :
nullptr);
252 ARMARX_DEBUG <<
"Combining robot ..." <<
"\n- " << robotDescriptions.size()
253 <<
" descriptions" <<
"\n- " << globalPoses.size() <<
" global poses" <<
"\n- "
254 << sensorValues.size() <<
" joint positions";
257 combine(robotDescriptions, globalPoses, sensorValues, timestamp);
260 std::vector<viz::Layer> layers;
264 visualizeRobots(layer,
robots,
false);
267 if (p.collisionModelEnabled)
270 visualizeRobots(layer,
robots,
true);
276 viz::Layer& layer = layers.emplace_back(arviz.
layer(
"Localization Frames"));
277 visualizeFrames(layer, frames);
283 viz::Layer& layer = layers.emplace_back(arviz.
layer(
"Localization Frames Individual"));
284 visualizeFramesIndividual(layer, frames);
287 if (p.forceTorque.enabled)
289 viz::Layer& layerForceTorque = layers.emplace_back(arviz.
layer(
"Force Torque"));
290 std::stringstream log;
294 const std::string& robotName = robot.description.name;
296 auto itSensorValues = sensorValues.find(robotName);
297 if (itSensorValues == sensorValues.end())
299 log <<
"\nNo robot '" << robotName <<
"' in sensor values. Available are: ";
300 log << simox::alg::join(simox::alg::get_keys(sensorValues),
", ");
304 visualizeForceTorque(layerForceTorque, robot, itSensorValues->second);
307 if (not log.str().empty())
309 ARMARX_INFO <<
"While visualizing robot force torques: " << log.str();
323 if (debugObserver.has_value())
325 const std::string p =
"Visu | ";
326 debugObserver->setDebugObserverDatafield(p +
"t Total (ms)",
327 tVisuTotal.toMilliSecondsDouble());
328 debugObserver->setDebugObserverDatafield(p +
"t 1 Get Data (ms)",
329 tVisuGetData.toMilliSecondsDouble());
330 debugObserver->setDebugObserverDatafield(p +
"t 1.1 Descriptions (ms)",
331 tRobotDescriptions.toMilliSecondsDouble());
332 debugObserver->setDebugObserverDatafield(p +
"t 1.2 Global Poses (ms)",
333 tGlobalPoses.toMilliSecondsDouble());
334 debugObserver->setDebugObserverDatafield(p +
"t 1.3 Frames (ms)",
335 tRobotFramePoses.toMilliSecondsDouble());
336 debugObserver->setDebugObserverDatafield(p +
"t 1.4 Sensor Values (ms)",
337 tSensorValues.toMilliSecondsDouble());
338 debugObserver->setDebugObserverDatafield(p +
"t 2 Build Layers (ms)",
339 tVisuBuildLayers.toMilliSecondsDouble());
340 debugObserver->setDebugObserverDatafield(p +
"t 3 Commit (ms)",
341 tVisuCommit.toMilliSecondsDouble());
346 Visu::getRobotModel(
const armem::robot_state::description::RobotDescription& robotDescription)
348 const std::string& robotName = robotDescription.name;
350 RobotModel* robotModel =
nullptr;
351 if (
auto it = models.find(robotName); it != models.end())
353 robotModel = &it->second;
357 const std::filesystem::path robotPath = robotDescription.xml.toSystemPath();
358 ARMARX_INFO <<
"Loading robot model for '" << robotName <<
"' from " << robotPath
359 <<
" for visualization.";
360 auto [it2, _] = models.emplace(robotName, robotPath);
361 robotModel = &it2->second;
369 const proprioception::SensorValues& sensorValues)
372 Visu::RobotModel* robotModel = getRobotModel(robot.description);
374 if(robotModel ==
nullptr)
380 robotModel->model->setJointValues(robot.config.jointMap);
381 robotModel->model->setGlobalPose(robot.config.globalPose.matrix());
384 sensorValues.forceTorqueValuesMap;
386 for (
const auto& [side, ft] : forceTorques)
392 const std::string forceTorqueSensorName =
393 robotModel->nameHelper->getArm(side).getForceTorqueSensor();
396 robotModel->model->getSensor(forceTorqueSensorName)->getGlobalPose();
398 const std::string xyz =
"XYZ";
400 const Eigen::Vector3f from = simox::math::position(forceTorqueSensorPose);
401 for (
int i = 0; i < 3; ++i)
408 const float length = p.forceTorque.forceScale * ft.force(i);
412 const Eigen::Vector3f to =
413 from + length * simox::math::orientation(forceTorqueSensorPose).col(i);
415 std::stringstream key;
417 key << side <<
" Force " << xyz.at(i);
425 Visu::RobotModel::RobotModel(
const std::filesystem::path& robotPath) :
427 VirtualRobot::RobotIO::loadRobot(robotPath, VirtualRobot::RobotIO::eStructure),