MultiViewPointCloudProcessor.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::MultiViewPointCloudProcessor
17  * @author Raphael Grimm ( raphael dot grimm 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 
24 
25 #include <pcl/common/transforms.h>
26 #include <pcl/filters/approximate_voxel_grid.h>
27 
29 
31 
32 #include <VisionX/interface/components/Calibration.h>
33 #include <VisionX/interface/core/PointCloudProcessorInterface.h>
34 
35 #define call_template_function(F) \
36  switch (_pointCloudProviderInfo.pointCloudFormat->type) \
37  { \
38  case visionx::PointContentType::ePoints: \
39  F<pcl::PointXYZ>(); \
40  break; \
41  case visionx::PointContentType::eColoredPoints: \
42  F<pcl::PointXYZRGBA>(); \
43  break; \
44  case visionx::PointContentType::eColoredOrientedPoints: \
45  F<pcl::PointXYZRGBNormal>(); \
46  break; \
47  case visionx::PointContentType::eLabeledPoints: \
48  F<pcl::PointXYZL>(); \
49  break; \
50  case visionx::PointContentType::eColoredLabeledPoints: \
51  F<pcl::PointXYZRGBL>(); \
52  break; \
53  case visionx::PointContentType::eIntensity: \
54  F<pcl::PointXYZI>(); \
55  break; \
56  case visionx::PointContentType::eOrientedPoints: \
57  ARMARX_ERROR << "eOrientedPoints NOT HANDLED IN VISIONX"; \
58  [[fallthrough]]; \
59  default: \
60  ARMARX_ERROR << "Could not call " #F ", because format '" \
61  << _pointCloudProviderInfo.pointCloudFormat->type << "' is unknown"; \
62  } \
63  do \
64  { \
65  } while (false)
66 
67 //common
68 namespace armarx
69 {
70  std::string
72  {
73  return "MultiViewPointCloudProcessor";
74  }
75 
78  {
81  prop->defineOptionalProperty<std::string>(
82  "ProviderReferenceFrame",
83  "",
84  "Name of the point cloud refence frame (empty = autodetect)");
85  std::lock_guard guard{_cfgBufWriteMutex};
86  prop->optional(_cfgBuf.getWriteBuffer(), "", "");
87  return prop;
88  }
89 } // namespace armarx
90 
91 //gui
92 namespace armarx
93 {
96  {
97  std::lock_guard guard{_cfgBufWriteMutex};
101  .addChild(RemoteGui::makeButton("start"))
102  .addChild(RemoteGui::makeButton("stop"))
103  .addChild(RemoteGui::makeButton("clear"))
104  .addHSpacer());
105  }
106 
107  void
109  {
110  prx.receiveUpdates();
111  std::lock_guard guard{_cfgBufWriteMutex};
112 
113  prx.getValue(_cfgBuf.getWriteBuffer(), "cfg");
114  if (prx.getButtonClicked("start"))
115  {
117  }
118  if (prx.getButtonClicked("stop"))
119  {
121  }
122  if (prx.getButtonClicked("clear"))
123  {
124  clearViewPoints();
125  }
126  prx.sendUpdates();
127  _cfgBuf.commitWrite();
128  }
129 } // namespace armarx
130 
131 //hooks
132 namespace armarx
133 {
134  void
136  {
137  _pointCloudProviderName = getProperty<std::string>("ProviderName");
138  usingPointCloudProvider(_pointCloudProviderName);
139  }
140 
141  void
143  {
144  //provider
145  {
146  _pointCloudProviderInfo = getPointCloudProvider(_pointCloudProviderName, true);
147  _pointCloudProvider = _pointCloudProviderInfo.proxy;
148  _pointCloudProviderRefFrame = getProperty<std::string>("ProviderReferenceFrame");
149  if (_pointCloudProviderRefFrame.empty())
150  {
151  _pointCloudProviderRefFrame = "root";
152  auto frameprov =
153  visionx::ReferenceFrameInterfacePrx::checkedCast(_pointCloudProvider);
154  if (frameprov)
155  {
156  _pointCloudProviderRefFrame = frameprov->getReferenceFrame();
157  }
158  }
159  ARMARX_INFO << VAROUT(_pointCloudProviderRefFrame);
160 
161  if (!_providerThread.joinable())
162  {
163  //result cloud of point type
165  _providerThread = std::thread{[&] { call_template_function(doProvide); }};
166  }
167  }
168  //robot
169  {
170  _robot = addRobot("_robot", VirtualRobot::RobotIO::eStructure);
171  }
172  //gui
174  [this](RemoteGui::TabProxy& prx) { processGui(prx); });
175  }
176 
177  void
179  {
180  _stopProviding = true;
181  _providerThread.join();
182  }
183 } // namespace armarx
184 
185 //Ice methods
186 namespace armarx
187 {
188  void
190  {
191  ++_currentViewpoint;
192  _doRecord = true;
193  }
194 
195  void
197  {
198  _doRecord = false;
199  }
200 
201  void
203  {
204  _doClear = true;
205  }
206 
207  void
209  {
210  std::lock_guard guard{_cfgBufWriteMutex};
211  _cfgBuf.getWriteBuffer().maxNumberOfFramesPerViewPoint = n;
212  _cfgBuf.commitWrite();
213  }
214 
215  void
217  {
218  std::lock_guard guard{_cfgBufWriteMutex};
219  _cfgBuf.getWriteBuffer().gridSize = s;
220  _cfgBuf.commitWrite();
221  }
222 
223  void
225  {
226  std::lock_guard guard{_cfgBufWriteMutex};
227  _cfgBuf.getWriteBuffer().frameRate = r;
228  _cfgBuf.commitWrite();
229  }
230 } // namespace armarx
231 
232 //process
233 namespace armarx
234 {
235  void
237  {
239  }
240 
241  template <class PointType>
242  void
244  {
246  {
248  };
249  const auto doRecord = _doRecord.load();
250  if (_doClear)
251  {
252  std::lock_guard guard{_viewPointsMutex};
253  _viewPoints.clear();
254  _currentViewpoint = doRecord ? 0 : -1;
255  _doClear = false;
256  }
257  if (!doRecord)
258  {
259  return;
260  }
261  const auto currentViewpoint = _currentViewpoint.load();
262  ARMARX_CHECK_GREATER_EQUAL(currentViewpoint, 0);
263  using cloud_t = pcl::PointCloud<PointType>;
264  using cloud_ptr_t = typename cloud_t::Ptr;
265 
266  std::unique_lock lock{_cfgBufReadMutex};
267  const auto buf = _cfgBuf.getUpToDateReadBuffer();
268  lock.unlock();
269  setDebugObserverDatafield("cfg", buf);
270  setDebugObserverDatafield("currentViewpoint", currentViewpoint);
271  setDebugObserverDatafield("doRecord", doRecord);
272 
273  //get cloud + transform to global
274  cloud_ptr_t transformedCloud;
275  {
276  if (!waitForPointClouds(_pointCloudProviderName, 100))
277  {
278  ARMARX_INFO << deactivateSpam(10, _pointCloudProviderName)
279  << "Timeout or error while waiting for point cloud data of provider "
280  << _pointCloudProviderName;
281  return;
282  }
283  cloud_ptr_t inputCloud(new cloud_t);
284  getPointClouds(_pointCloudProviderName, inputCloud);
285  synchronizeLocalClone(_robot);
286 
287  const Eigen::Matrix4f providerInRootFrame = [&]() -> Eigen::Matrix4f
288  {
289  FramedPose fp{
290  Eigen::Matrix4f::Identity(), _pointCloudProviderRefFrame, _robot->getName()};
291  fp.changeFrame(_robot, "Global");
292  return fp.toEigen();
293  }();
294 
295  transformedCloud = cloud_ptr_t(new cloud_t);
296  pcl::transformPointCloud(*inputCloud, *transformedCloud, providerInRootFrame);
297  }
298  setDebugObserverDatafield("cloud_size_in", transformedCloud->size());
299  std::lock_guard guard{_viewPointsMutex};
300  const auto p = static_cast<std::size_t>(currentViewpoint);
301  if (p + 1 > _viewPoints.size())
302  {
303  _viewPoints.resize(p + 1);
304  }
305  _viewPoints.at(p).clouds.emplace_back(transformedCloud);
306  if (buf.maxNumberOfFramesPerViewPoint > 0)
307  {
308  while (_viewPoints.at(p).clouds.size() >
309  static_cast<std::size_t>(buf.maxNumberOfFramesPerViewPoint))
310  {
311  _viewPoints.at(p).clouds.pop_front();
312  }
313  }
314  setDebugObserverDatafield("current_view_num_clouds", _viewPoints.at(p).clouds.size());
315  }
316 
317  template <class PointType>
318  void
320  {
321  using cloud_t = pcl::PointCloud<PointType>;
322  using cloud_ptr_t = typename cloud_t::Ptr;
323  std::deque<std::uint64_t> idxVec;
324  while (!_stopProviding)
325  {
326  const auto timeBeg = std::chrono::high_resolution_clock::now();
327 
328  std::unique_lock lock{_cfgBufReadMutex};
329  const auto buf = _cfgBuf.getUpToDateReadBuffer();
330  lock.unlock();
331 
332  cloud_ptr_t cloud(new cloud_t);
333  {
334  std::lock_guard guard{_viewPointsMutex};
335  if (idxVec.size() < _viewPoints.size())
336  {
337  idxVec.resize(_viewPoints.size());
338  }
339  for (std::size_t i = 0; i < idxVec.size(); ++i)
340  {
341  const auto& inVec = _viewPoints.at(i).clouds;
342  const auto idx = (idxVec.at(i)++) % inVec.size();
343  const auto& in = *std::any_cast<cloud_ptr_t>(inVec.at(idx));
344  auto& out = cloud->points;
345  out.insert(out.end(), in.begin(), in.end());
346  }
347  }
348  //downsample
349  if (buf.gridSize > 0)
350  {
351  pcl::ApproximateVoxelGrid<PointType> grid;
352  grid.setLeafSize(Eigen::Vector3f::Constant(buf.gridSize));
353  grid.setInputCloud(cloud);
354  cloud_ptr_t tempCloud(new cloud_t);
355  grid.filter(*tempCloud);
356  tempCloud.swap(cloud);
357  }
358  //provide
360 
361  //sleep for frame rate
362  if (frameRate > 0)
363  {
364  const long dtms = 1 / frameRate * 1000;
365  std::this_thread::sleep_until(timeBeg + std::chrono::milliseconds{dtms});
366  }
367  }
368  }
369 } // namespace armarx
armarx::RemoteGui::MakeGuiConfig
RemoteGui::WidgetPtr MakeGuiConfig(const std::string &name, const T &val)
Definition: MakeGuiConfig.h:9
armarx::RemoteGui::makeVBoxLayout
detail::VBoxLayoutBuilder makeVBoxLayout(std::string const &name="")
Definition: LayoutWidgets.h:286
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:919
armarx::MultiViewPointCloudProcessor::onInitPointCloudProcessor
void onInitPointCloudProcessor() override
Setup the vision component.
Definition: MultiViewPointCloudProcessor.cpp:135
armarx::RemoteGui::makeHBoxLayout
detail::HBoxLayoutBuilder makeHBoxLayout(std::string const &name="")
Definition: LayoutWidgets.h:268
OnScopeExit.h
armarx::RemoteGui::makeButton
detail::ButtonBuilder makeButton(std::string const &name)
Definition: IntegerWidgets.h:52
armarx::MultiViewPointCloudProcessor::process
void process() override
Process the vision component.
Definition: MultiViewPointCloudProcessor.cpp:236
armarx::FramedPose
The FramedPose class.
Definition: FramedPose.h:280
armarx::WriteBufferedTripleBuffer::commitWrite
void commitWrite()
Definition: TripleBuffer.h:383
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
armarx::DebugObserverComponentPluginUser::setDebugObserverDatafield
void setDebugObserverDatafield(Ts &&... ts) const
Definition: DebugObserverComponentPlugin.h:86
visionx::PointCloudProviderInfo::proxy
PointCloudProviderInterfacePrx proxy
Proxy to PointCloud provider.
Definition: PointCloudProcessor.h:86
armarx::MultiViewPointCloudProcessor::setDownsamplingGridSize
void setDownsamplingGridSize(Ice::Float s, const Ice::Current &=Ice::emptyCurrent) override
Definition: MultiViewPointCloudProcessor.cpp:216
ARMARX_ON_SCOPE_EXIT
#define ARMARX_ON_SCOPE_EXIT
Executes given code when the enclosing scope is left.
Definition: OnScopeExit.h:120
armarx::RemoteGuiComponentPluginUser::createOrUpdateRemoteGuiTab
void createOrUpdateRemoteGuiTab(Ts &&... ts)
Definition: RemoteGuiComponentPlugin.h:239
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:418
armarx::MultiViewPointCloudProcessor::setFrameRate
void setFrameRate(Ice::Float r, const Ice::Current &=Ice::emptyCurrent) override
Definition: MultiViewPointCloudProcessor.cpp:224
armarx::RobotStateComponentPluginUser::addRobot
VirtualRobot::RobotPtr addRobot(const std::string &id, const VirtualRobot::RobotPtr &robot, const VirtualRobot::RobotNodeSetPtr &rns={}, const VirtualRobot::RobotNodePtr &node={})
Definition: RobotStateComponentPlugin.cpp:405
armarx::RobotStateComponentPluginUser::synchronizeLocalClone
bool synchronizeLocalClone(const VirtualRobot::RobotPtr &robot) const
Definition: RobotStateComponentPlugin.cpp:470
armarx::MultiViewPointCloudProcessor::onConnectPointCloudProcessor
void onConnectPointCloudProcessor() override
Implement this method in the PointCloudProcessor in order execute parts when the component is fully i...
Definition: MultiViewPointCloudProcessor.cpp:142
armarx::RemoteGui::TabProxy
Definition: WidgetProxy.h:17
armarx::MultiViewPointCloudProcessor::getDefaultName
std::string getDefaultName() const override
Definition: MultiViewPointCloudProcessor.cpp:71
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
armarx::MultiViewPointCloudProcessor::setMaxNumberOfFramesPerViewPoint
void setMaxNumberOfFramesPerViewPoint(Ice::Int n, const Ice::Current &=Ice::emptyCurrent) override
Definition: MultiViewPointCloudProcessor.cpp:208
armarx::RemoteGui::TabProxy::receiveUpdates
void receiveUpdates()
Definition: WidgetProxy.h:135
visionx::PointCloudProcessor::provideResultPointClouds
void provideResultPointClouds(const PointCloudPtrT &pointClouds, std::string providerName="")
sends result PointClouds for visualization
Definition: PointCloudProcessor.h:288
armarx::RemoteGui::detail::ChildrenMixin::addChild
Derived & addChild(WidgetPtr const &child)
Definition: LayoutWidgets.h:27
armarx::MultiViewPointCloudProcessor::clearViewPoints
void clearViewPoints(const Ice::Current &=Ice::emptyCurrent) override
Definition: MultiViewPointCloudProcessor.cpp:202
FramedPose.h
armarx::MultiViewPointCloudProcessor::startRecordingNextViewPoint
void startRecordingNextViewPoint(const Ice::Current &=Ice::emptyCurrent) override
Definition: MultiViewPointCloudProcessor.cpp:189
visionx::PointCloudProcessor::waitForPointClouds
bool waitForPointClouds(int milliseconds=1000)
Wait for new PointClouds.
Definition: PointCloudProcessor.cpp:458
armarx::MultiViewPointCloudProcessor::stopRecordingViewPoint
void stopRecordingViewPoint(const Ice::Current &=Ice::emptyCurrent) override
Definition: MultiViewPointCloudProcessor.cpp:196
armarx::MultiViewPointCloudProcessor::buildGui
RemoteGui::WidgetPtr buildGui()
Definition: MultiViewPointCloudProcessor.cpp:95
armarx::WriteBufferedTripleBuffer::getWriteBuffer
T & getWriteBuffer()
Definition: TripleBuffer.h:325
visionx::PointCloudProcessorPropertyDefinitions
Properties of PointCloudProcessor.
Definition: PointCloudProcessor.h:166
visionx::PointCloudProcessor::getPointClouds
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
Definition: PointCloudProcessor.h:380
ARMARX_CHECK_GREATER_EQUAL
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
Definition: ExpressionException.h:123
MultiViewPointCloudProcessor.h
visionx::PointCloudProcessor::frameRate
float frameRate
Definition: PointCloudProcessor.h:652
armarx::WidgetDescription::WidgetPtr
::IceInternal::Handle<::armarx::WidgetDescription::Widget > WidgetPtr
Definition: NJointControllerBase.h:67
armarx::RemoteGui::TabProxy::getValue
ValueProxy< T > getValue(std::string const &name)
Definition: WidgetProxy.h:167
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
armarx::RemoteGui::TabProxy::getButtonClicked
bool getButtonClicked(std::string const &name)
Definition: WidgetProxy.cpp:12
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::DebugObserverComponentPluginUser::sendDebugObserverBatch
void sendDebugObserverBatch()
Definition: DebugObserverComponentPlugin.cpp:135
IceUtil::Handle< class PropertyDefinitionContainer >
visionx::PointCloudProcessor::usingPointCloudProvider
void usingPointCloudProvider(std::string providerName)
Registers a delayed topic subscription and a delayed provider proxy retrieval which will be available...
Definition: PointCloudProcessor.cpp:279
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:917
armarx::RemoteGui::TabProxy::sendUpdates
void sendUpdates()
Definition: WidgetProxy.h:151
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
visionx::PointCloudProcessor::getPointCloudProvider
PointCloudProviderInfo getPointCloudProvider(std::string name, bool waitForProxy=false)
Select an PointCloudProvider.
Definition: PointCloudProcessor.cpp:325
armarx::MultiViewPointCloudProcessor::onExitPointCloudProcessor
void onExitPointCloudProcessor() override
Exit the ImapeProcessor component.
Definition: MultiViewPointCloudProcessor.cpp:178
armarx::MultiViewPointCloudProcessor::processGui
void processGui(RemoteGui::TabProxy &prx)
Definition: MultiViewPointCloudProcessor.cpp:108
armarx::MultiViewPointCloudProcessor::doProvide
void doProvide()
Definition: MultiViewPointCloudProcessor.cpp:319
armarx::WriteBufferedTripleBuffer::getUpToDateReadBuffer
const T & getUpToDateReadBuffer() const
Definition: TripleBuffer.h:346
armarx::MultiViewPointCloudProcessor::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: MultiViewPointCloudProcessor.cpp:77
visionx::PointCloudProcessor::enableResultPointClouds
void enableResultPointClouds(std::string resultProviderName="")
Enables visualization.
Definition: PointCloudProcessor.h:233
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
call_template_function
#define call_template_function(F)
Definition: MultiViewPointCloudProcessor.cpp:35