PointCloudToArViz.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package VisionX::ArmarXObjects::PointCloudToArViz
17  * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18  * @date 2020
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "PointCloudToArViz.h"
24 
25 #include <pcl/common/transforms.h>
26 #include <pcl/impl/point_types.hpp>
27 #include <pcl/point_types.h>
28 
29 #include <SimoxUtility/math/convert/mat4f_to_pos.h>
30 #include <SimoxUtility/math/convert/mat4f_to_rpy.h>
31 #include <SimoxUtility/math/convert/pos_rpy_to_mat4f.h>
32 
36 
40 
41 namespace visionx
42 {
43 
46  {
47  defineOptionalProperty<int>(
48  "ProviderWaitMs", 100, "Time to wait for each point cloud provider [ms].");
49  }
50 
53  {
56 
57  defs->optional(
58  params.pointSizeInPixels, "viz.pointSizeInPixels", "The point size in pixels.");
59  defs->optional(params.checkFinite,
60  "viz.checkFinite",
61  "Enable to check points for being finite. "
62  "\nEnable this option if the drawn point cloud causes the screen to become "
63  "purely white.");
64  defs->optional(params.labeled,
65  "viz.labeled",
66  "If true and point cloud is labeled, draw colors according to labels.");
67  defs->optional(params.alsoVisualizeNode,
68  "viz.showNode",
69  "If true also the node's coordinate systems is shown.");
70 
71  defs->optional(params.robotName, "robotName", "");
72  defs->optional(
73  params.pointCloudNodeName,
74  "pointCloudNodeName",
75  " If the point cloud header does not provide a frame id, this info is used.");
76 
77  return defs;
78  }
79 
81  {
82  addPlugin(virtualRobotReaderPlugin);
83  }
84 
85  std::string
87  {
88  return "PointCloudToArViz";
89  }
90 
91  void
93  {
94  params.providerWaitTime =
95  IceUtil::Time::milliSeconds(getProperty<int>("ProviderWaitMs").getValue());
96  }
97 
98  void
100  {
101  if (virtualRobotReaderPlugin->isAvailable())
102  {
103  robot = virtualRobotReaderPlugin->get().getRobot(params.robotName);
104  // No need to synchronize the robot here. We synchronize it later anyway.
105  }
106 
109  }
110 
111  void
113  {
114  }
115 
116  void
118  {
119  }
120 
121  void
123  {
124  // Fetch input clouds.
125  for (const std::string& providerName : getPointCloudProviderNames())
126  {
127  if (waitForPointClouds(providerName,
128  static_cast<int>(params.providerWaitTime.toMilliSeconds())))
129  {
130  auto it = cache.find(providerName);
131  if (it == cache.end())
132  {
133  it = cache.emplace(providerName, armarx::viz::PointCloud(providerName)).first;
134  }
135  armarx::viz::PointCloud& vizCloud = it->second;
136 
137  Parameters params;
138  {
139  std::scoped_lock lock(paramMutex);
140  params = this->params;
141  }
142 
143  vizCloud.checkFinite(params.checkFinite);
144  vizCloud.pointSizeInPixels(params.pointSizeInPixels);
145 
146  const PointContentType type = getPointCloudFormat(providerName)->type;
147  std::optional<PointCloudToArViz::OriginInfo> originInfo;
148 
149  if (visionx::tools::isLabeled(type))
150  {
151  pcl::PointCloud<pcl::PointXYZRGBL>::Ptr inputCloud(
152  new pcl::PointCloud<pcl::PointXYZRGBL>);
153  getPointClouds(providerName, inputCloud);
154  originInfo = applyCustomTransform(*inputCloud);
155  vizCloud.pointCloud(*inputCloud, params.labeled);
156  }
157  else
158  {
159  pcl::PointCloud<pcl::PointXYZRGBA>::Ptr inputCloud(
160  new pcl::PointCloud<pcl::PointXYZRGBA>);
161  getPointClouds(providerName, inputCloud);
162  originInfo = applyCustomTransform(*inputCloud);
163  vizCloud.pointCloud(*inputCloud);
164  }
165 
166  armarx::viz::Layer layer = arviz.layer(providerName);
167  if (params.alsoVisualizeNode && originInfo.has_value())
168  {
169  auto originPose = armarx::viz::Pose(originInfo->name);
170  originPose.pose(originInfo->pose);
171  originPose.scale(3);
172  layer.add(originPose);
173  }
174 
175  layer.add(vizCloud);
176  arviz.commit({layer});
177  }
178  else
179  {
180  ARMARX_VERBOSE << "Timeout waiting for point cloud provider " << providerName
181  << ".";
182  }
183  }
184  }
185 
186  void
187  PointCloudToArViz::setPointSizeInPixels(float pointSizeInPixels, const Ice::Current&)
188  {
189  std::scoped_lock lock(paramMutex);
190  params.pointSizeInPixels = pointSizeInPixels;
191  }
192 
193  void
194  PointCloudToArViz::setCustomTransform(const armarx::PoseBasePtr& transformPtr,
195  const Ice::Current&)
196  {
197  return;
198 
199  // std::scoped_lock lock(paramMutex);
200  // params.customTransform = armarx::PosePtr::dynamicCast(transformPtr)->toEigen();
201  // if (params.customTransform->isIdentity())
202  // {
203  // params.customTransform = std::nullopt;
204  // }
205  }
206 
207  template <class PointT>
208  std::optional<PointCloudToArViz::OriginInfo>
209  PointCloudToArViz::applyCustomTransform(pcl::PointCloud<PointT>& pointCloud)
210  {
211  ARMARX_CHECK_NOT_NULL(virtualRobotReaderPlugin);
212  if (not virtualRobotReaderPlugin->isAvailable())
213  {
215  << "The robot reader plugin is deactivated. Won't transform point cloud";
216  return std::nullopt;
217  }
218 
219  ARMARX_CHECK_NOT_NULL(robot);
220  {
221  std::scoped_lock lock(robotMutex);
222  ARMARX_CHECK(virtualRobotReaderPlugin->get().synchronizeRobot(
223  *robot, armarx::core::time::Duration::MicroSeconds(pointCloud.header.stamp)));
224  }
225 
226  const auto pointCloudNodeName = [&]() -> std::string
227  {
228  // highest prio: use frame id of point cloud.
229  if (not pointCloud.header.frame_id.empty())
230  {
231  return pointCloud.header.frame_id;
232  }
233 
234  // check if fallback solution is available
236  << deactivateSpam(100)
237  << "The point cloud header does not provide a frame_id. Using property instead";
238 
239  ARMARX_CHECK_NOT_EMPTY(params.pointCloudNodeName)
240  << "The `pointCloudNodeName` property must be provided as the point cloud "
241  "header "
242  "frame id is not set!";
243 
244  return params.pointCloudNodeName;
245  }();
246 
247  if (not robot)
248  {
250  << "The robot is not available. Won't transform point cloud";
251  return std::nullopt;
252  }
253 
254  Eigen::Matrix4f globalSensorPose = Eigen::Matrix4f::Identity();
255  if (pointCloudNodeName != armarx::GlobalFrame)
256  {
257  {
258  std::scoped_lock lock(robotMutex);
259  ARMARX_CHECK_NOT_NULL(robot);
260  const auto node = robot->getRobotNode(pointCloudNodeName);
262  << "No robot node with name `" << pointCloudNodeName << "`";
263  globalSensorPose = node->getGlobalPose();
264  }
265 
266  pcl::transformPointCloud(pointCloud, pointCloud, globalSensorPose);
267  }
268  else if (not localTransformationNodeName.empty())
269  {
271  << "Local transformation node cannot be set as point cloud is in global "
272  "frame already";
273  }
274 
275  pointCloud.header.frame_id = armarx::GlobalFrame;
276 
277  return OriginInfo{.name = pointCloudNodeName, .pose = globalSensorPose};
278  }
279 
280  void
282  {
283  using namespace armarx::RemoteGui::Client;
284 
285  GridLayout grid;
286  int row = 0;
287 
288  tab.checkFinite.setName("Check Finite");
289  tab.checkFinite.setValue(params.checkFinite);
290 
291  tab.pointSizeInPixels.setName("Point Size [pixels]");
292  tab.pointSizeInPixels.setDecimals(2);
293  tab.pointSizeInPixels.setRange(0, 100);
294  tab.pointSizeInPixels.setSteps(100);
295  tab.pointSizeInPixels.setValue(params.pointSizeInPixels);
296 
297  tab.labeled.setName("Color by Labels");
298  tab.labeled.setValue(params.labeled);
299 
300  grid.add(Label(tab.checkFinite.getName()), {row, 0}).add(tab.checkFinite, {row, 1});
301  row++;
302  grid.add(Label(tab.pointSizeInPixels.getName()), {row, 0})
303  .add(tab.pointSizeInPixels, {row, 1});
304  row++;
305  grid.add(Label(tab.labeled.getName()), {row, 0}).add(tab.labeled, {row, 1});
306  row++;
307 
308  tab.localTransformationNode = ComboBox();
309  tab.localTransformationNode.addOption("");
310  for (const std::string& nodeName : robot->getRobotNodeNames())
311  {
312  tab.localTransformationNode.addOption(nodeName);
313  }
314  grid.add(Label("Local node: "), {row, 0}).add(tab.localTransformationNode, {row, 1});
315  row++;
316 
317  auto createFloatSpinBox = [&](float min, float max, float value)
318  {
319  auto spinBox = FloatSpinBox();
320  spinBox.setRange(min, max);
321  spinBox.setValue(value);
322  tab.transfSpinBoxes.push_back(spinBox);
323  return spinBox;
324  };
325 
326  int col = 0;
327  grid.add(Label("Transformation: "), {row, col++})
328  .add(Label("x"), {row, col++})
329  .add(createFloatSpinBox(-5000, 5000, 0), {row, col++})
330  .add(Label("y"), {row, col++})
331  .add(createFloatSpinBox(-5000, 5000, 0), {row, col++})
332  .add(Label("z"), {row, col++})
333  .add(createFloatSpinBox(-5000, 5000, 0), {row, col++})
334  .add(Label("roll"), {row, col++})
335  .add(createFloatSpinBox(-M_PI, M_PI, 0), {row, col++})
336  .add(Label("pitch"), {row, col++})
337  .add(createFloatSpinBox(-M_PI, M_PI, 0), {row, col++})
338  .add(Label("yaw"), {row, col++})
339  .add(createFloatSpinBox(-M_PI, M_PI, 0), {row, col++});
340  row++;
341 
342  VBoxLayout root = {grid, VSpacer()};
343  RemoteGui_createTab(getName(), root, &tab);
344  }
345 
346  void
348  {
349  std::scoped_lock lock(paramMutex);
350  if (tab.checkFinite.hasValueChanged())
351  {
352  params.checkFinite = tab.checkFinite.getValue();
353  }
354  if (tab.pointSizeInPixels.hasValueChanged())
355  {
356  params.pointSizeInPixels = tab.pointSizeInPixels.getValue();
357  }
358  if (tab.labeled.hasValueChanged())
359  {
360  params.labeled = tab.labeled.getValue();
361  }
362 
363  if (tab.localTransformationNode.hasValueChanged())
364  {
365  localTransformationNodeName = tab.localTransformationNode.getValue();
366 
367  if (not localTransformationNodeName.empty())
368  {
369  const auto localTransf =
370  robot->getRobotNode(localTransformationNodeName)->getLocalTransformation();
371  const Eigen::Vector3f pos = simox::math::mat4f_to_pos(localTransf);
372  const Eigen::Vector3f rpy = simox::math::mat4f_to_rpy(localTransf);
373 
374  for (unsigned int i = 0; i < 3; i++)
375  {
376  tab.transfSpinBoxes.at(i).setValue(pos[i]);
377  }
378  for (unsigned int i = 0; i < 3; i++)
379  {
380  tab.transfSpinBoxes.at(i + 3).setValue(rpy[i]);
381  }
382  }
383  }
384 
385  bool update = false;
386  for (auto& spinBox : tab.transfSpinBoxes)
387  {
388  if (spinBox.hasValueChanged())
389  {
390  update = true;
391  }
392  }
393  if (update)
394  {
395  {
396  std::scoped_lock lock(robotMutex);
397 
398  auto localTransformation =
399  simox::math::pos_rpy_to_mat4f(tab.transfSpinBoxes.at(0).getValue(),
400  tab.transfSpinBoxes.at(1).getValue(),
401  tab.transfSpinBoxes.at(2).getValue(),
402  tab.transfSpinBoxes.at(3).getValue(),
403  tab.transfSpinBoxes.at(4).getValue(),
404  tab.transfSpinBoxes.at(5).getValue());
405 
406  robot->getRobotNode(localTransformationNodeName)
407  ->setLocalTransformation(localTransformation);
408  robot->updatePose();
409 
410  ARMARX_INFO << "Updating localTransformation of " +
411  tab.localTransformationNode.getName() + " to "
412  << localTransformation.matrix();
413  }
414  }
415  }
416 
417 
418 } // namespace visionx
armarx::armem::client::plugins::ReaderWriterPlugin::isAvailable
bool isAvailable() const
Definition: ReaderWriterPlugin.h:80
PointCloudToArViz.h
armarx::viz::Client::commit
CommitResult commit(StagedCommit const &commit)
Definition: Client.cpp:89
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::armem::robot_state::VirtualRobotReader::getRobot
VirtualRobot::RobotPtr getRobot(const std::string &name, const armem::Time &timestamp=armem::Time::Invalid(), const VirtualRobot::RobotIO::RobotDescription &loadMode=VirtualRobot::RobotIO::RobotDescription::eStructure)
Definition: VirtualRobotReader.cpp:79
visionx::PointCloudToArViz::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: PointCloudToArViz.cpp:52
visionx::PointCloudToArViz::setPointSizeInPixels
virtual void setPointSizeInPixels(float pointSizeInPixels, const Ice::Current &=Ice::emptyCurrent) override
Definition: PointCloudToArViz.cpp:187
visionx::PointCloudProcessor::getPointCloudFormat
MetaPointCloudFormatPtr getPointCloudFormat(std::string providerName)
Definition: PointCloudProcessor.cpp:534
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
visionx::PointCloudToArViz::process
void process() override
Definition: PointCloudToArViz.cpp:122
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
visionx::PointCloudToArVizPropertyDefinitions
Property definitions of PointCloudToArViz.
Definition: PointCloudToArViz.h:57
armarx::RemoteGui::Client::VBoxLayout
Definition: Widgets.h:167
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
Pose.h
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
armarx::RemoteGui::Client::GridLayout::add
GridLayout & add(Widget const &child, Pos pos, Span span=Span{1, 1})
Definition: Widgets.cpp:438
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
armarx::RemoteGui::Client::Widget::setName
void setName(std::string const &name)
Definition: Widgets.cpp:19
armarx::armem::robot_state::VirtualRobotReader::synchronizeRobot
bool synchronizeRobot(VirtualRobot::Robot &robot, const armem::Time &timestamp) const
Synchronize both the platform pose and the joint values of a virtual robot, according to the robot st...
Definition: VirtualRobotReader.cpp:26
visionx::tools::isLabeled
bool isLabeled(PointContentType type)
Definition: PointCloudConversions.cpp:131
ARMARX_CHECK_NOT_EMPTY
#define ARMARX_CHECK_NOT_EMPTY(c)
Definition: ExpressionException.h:224
armarx::ManagedIceObject::addPlugin
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
Definition: ManagedIceObject.h:186
armarx::skills::gui::Parameters
aron::data::DictPtr Parameters
Definition: SkillManagerWrapper.h:21
visionx::PointCloudToArVizPropertyDefinitions::PointCloudToArVizPropertyDefinitions
PointCloudToArVizPropertyDefinitions(std::string prefix)
Definition: PointCloudToArViz.cpp:44
armarx::viz::Layer::add
void add(ElementT const &element)
Definition: Layer.h:31
armarx::RemoteGui::Client::VSpacer
Definition: Widgets.h:204
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
Clock.h
visionx::voxelgrid::Label
uint32_t Label
Type of an object label.
Definition: types.h:6
armarx::RemoteGui::Client::GridLayout
Definition: Widgets.h:186
visionx::PointCloudToArViz::PointCloudToArViz
PointCloudToArViz()
Definition: PointCloudToArViz.cpp:80
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
M_PI
#define M_PI
Definition: MathTools.h:17
FramedPose.h
armarx::viz::PointCloud::pointSizeInPixels
PointCloud & pointSizeInPixels(float s)
Definition: PointCloud.h:53
visionx::PointCloudToArViz::RemoteGui_update
void RemoteGui_update() override
Definition: PointCloudToArViz.cpp:347
visionx::PointCloudProcessor::waitForPointClouds
bool waitForPointClouds(int milliseconds=1000)
Wait for new PointClouds.
Definition: PointCloudProcessor.cpp:458
armarx::viz::PointCloud
Definition: PointCloud.h:19
max
T max(T t1, T t2)
Definition: gdiam.h:51
VirtualRobotReader.h
visionx::PointCloudToArViz::getDefaultName
std::string getDefaultName() const override
Definition: PointCloudToArViz.cpp:86
visionx::PointCloudToArViz::onDisconnectPointCloudProcessor
void onDisconnectPointCloudProcessor() override
Definition: PointCloudToArViz.cpp:112
visionx::PointCloudProcessorPropertyDefinitions
Properties of PointCloudProcessor.
Definition: PointCloudProcessor.h:166
armarx::RemoteGui::Client::ComboBox
Definition: Widgets.h:50
visionx::PointCloudProcessor::getPointClouds
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
Definition: PointCloudProcessor.h:380
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:68
visionx::PointCloudToArViz::onInitPointCloudProcessor
void onInitPointCloudProcessor() override
Definition: PointCloudToArViz.cpp:92
armarx::armem::client::plugins::ReaderWriterPlugin::get
T & get()
Definition: ReaderWriterPlugin.h:87
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_startRunningTask
void RemoteGui_startRunningTask()
Definition: LightweightRemoteGuiComponentPlugin.cpp:119
ExpressionException.h
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ArVizComponentPluginUser::arviz
armarx::viz::Client arviz
Definition: ArVizComponentPlugin.h:42
visionx::PointCloudToArViz::createRemoteGuiTab
void createRemoteGuiTab()
Definition: PointCloudToArViz.cpp:281
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_createTab
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
Definition: LightweightRemoteGuiComponentPlugin.cpp:103
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::Logging::deactivateSpam
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.
Definition: Logging.cpp:99
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:108
visionx::PointCloudToArViz::onConnectPointCloudProcessor
void onConnectPointCloudProcessor() override
Definition: PointCloudToArViz.cpp:99
Logging.h
min
T min(T t1, T t2)
Definition: gdiam.h:44
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::viz::Client::layer
Layer layer(std::string const &name) const
Definition: Client.cpp:80
visionx::PointCloudToArViz::onExitPointCloudProcessor
void onExitPointCloudProcessor() override
Definition: PointCloudToArViz.cpp:117
armarx::core::time::Duration::MicroSeconds
static Duration MicroSeconds(std::int64_t microSeconds)
Constructs a duration in microseconds.
Definition: Duration.cpp:24
armarx::RemoteGui::Client
Definition: EigenWidgets.cpp:8
armarx::viz::PointCloud::pointCloud
PointCloud & pointCloud(const PointCloudT &cloud)
Draw a point cloud.
Definition: PointCloud.h:206
armarx::viz::Layer
Definition: Layer.h:12
armarx::RemoteGui::Client::FloatSpinBox
Definition: Widgets.h:93
armarx::viz::PointCloud::checkFinite
PointCloud & checkFinite(bool enabled=true)
Enable or disable checking whether points are finite when adding them (disabled by default).
Definition: PointCloud.h:38
visionx::PointCloudProcessor::getPointCloudProviderNames
std::vector< std::string > getPointCloudProviderNames() const
Get the names of providers for which usingPointCloudProvider() has been called.
Definition: PointCloudProcessor.cpp:404
visionx::PointCloudToArViz::setCustomTransform
virtual void setCustomTransform(const armarx::PoseBasePtr &transform, const Ice::Current &=Ice::emptyCurrent) override
Definition: PointCloudToArViz.cpp:194