31#include <pcl/common/common.h>
32#include <pcl/common/transforms.h>
33#include <pcl/features/normal_3d.h>
34#include <pcl/filters/extract_indices.h>
35#include <pcl/filters/filter.h>
36#include <pcl/filters/voxel_grid.h>
37#include <pcl/kdtree/kdtree.h>
38#include <pcl/sample_consensus/method_types.h>
39#include <pcl/sample_consensus/model_types.h>
40#include <pcl/segmentation/region_growing.h>
42#include <VirtualRobot/math/FitPlane.h>
71 ARMARX_INFO <<
"Next timeout at " + nextTimeoutAbs.toDateTime();
74 getIceManager()->subscribeTopic(prx.first,
"ServiceRequests");
105 remoteGuiTask->start();
114 remoteGuiTask->stop();
115 remoteGuiTask =
nullptr;
127 pcl::PointCloud<PointT>::Ptr inputCloud(
new pcl::PointCloud<PointT>());
128 pcl::PointCloud<PointT>::Ptr plane(
new pcl::PointCloud<PointT>());
137 ARMARX_INFO <<
"Timeout or error while waiting for point cloud data";
147 if (inputCloud->points.size() == 0)
153 bool calculatePlane =
false;
154 bool includeTabletopPlane =
false;
157 std::unique_lock<std::mutex> lock(prop_mutex);
159 seg.setOptimizeCoefficients(
true);
160 seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
161 seg.setMethodType(pcl::SAC_RANSAC);
162 seg.setMaxIterations(1000);
163 seg.setDistanceThreshold(prop_DistanceThreshold);
164 seg.setAxis(Eigen::Vector3f::UnitZ());
165 seg.setEpsAngle(prop_EpsAngle);
166 seg.setProbability(0.99);
168 hull.setDimension(2);
169 prism.setHeightLimits(prop_HeightMin, prop_HeightMax);
170 prism.setViewPoint(std::numeric_limits<float>::max(),
171 std::numeric_limits<float>::max(),
172 std::numeric_limits<float>::max());
174 ec.setClusterTolerance(prop_ClusterTolerance);
175 ec.setMinClusterSize(prop_MinClusterSize);
176 ec.setMaxClusterSize(prop_MaxClusterSize);
178 includeTabletopPlane = prop_IncludeTabletopPlane;
179 calculatePlane = prop_CalculatePlane;
182 pcl::PointIndices::Ptr inliers(
new pcl::PointIndices);
183 pcl::ModelCoefficients::Ptr coefficients(
new pcl::ModelCoefficients);
184 pcl::PointCloud<PointT>::Ptr tempCloud(
new pcl::PointCloud<PointT>());
188 seg.setInputCloud(inputCloud);
189 seg.segment(*inliers, *coefficients);
191 if (!inliers->indices.size())
198 extract.setInputCloud(inputCloud);
199 extract.setIndices(inliers);
200 extract.setNegative(
false);
201 extract.filter(*plane);
203 extract.setNegative(
true);
204 extract.filter(*tempCloud);
206 pcl::PointCloud<PointT>::Ptr hullPoints(
new pcl::PointCloud<PointT>());
207 hull.setInputCloud(inputCloud);
208 hull.setIndices(inliers);
209 hull.reconstruct(*hullPoints);
211 prism.setInputCloud(tempCloud);
212 prism.setInputPlanarHull(hullPoints);
213 prism.segment(*inliers);
215 extract.setInputCloud(tempCloud);
216 extract.setIndices(inliers);
217 extract.setNegative(
false);
218 extract.filter(*tempCloud);
226 std::vector<Eigen::Vector3f> planePoints;
227 for (
const PointT& p : plane->points)
229 planePoints.emplace_back(Eigen::Vector3f(p.x, p.y, p.z));
231 math::Plane mplane = math::FitPlane::Fit(planePoints);
232 std::unique_lock guard(tablePlaneMutex);
233 Eigen::Vector3f planeNormal = mplane.GetNormal(Eigen::Vector3f::UnitZ());
235 tablePlane =
new visionx::TabletopSegmentationPlane(
new Vector3(mplane.Pos()),
239 pcl::PointCloud<PointL>::Ptr resultCloud(
new pcl::PointCloud<PointL>());
240 extractEuclideanClusters(tempCloud, resultCloud);
242 if (includeTabletopPlane)
244 pcl::PointCloud<PointL>::Ptr planeLabel(
new pcl::PointCloud<PointL>());
245 pcl::copyPointCloud(*plane, *planeLabel);
246 for (
PointL& p : planeLabel->points)
250 pcl::PointCloud<PointL>::Ptr combinedCloud(
new pcl::PointCloud<PointL>());
251 *combinedCloud = *resultCloud + *planeLabel;
252 resultCloud->swap(*combinedCloud);
254 resultCloud->header.stamp = inputCloud->header.stamp;
261armarx::TabletopSegmentation::extractEuclideanClusters(
262 const pcl::PointCloud<PointT>::ConstPtr& inputCloud,
263 const pcl::PointCloud<PointL>::Ptr& resultCloud)
265 pcl::search::KdTree<PointT>::Ptr tree(
new pcl::search::KdTree<PointT>);
266 tree->setInputCloud(inputCloud);
268 std::vector<pcl::PointIndices> clusterIndices;
269 ec.setSearchMethod(tree);
270 ec.setInputCloud(inputCloud);
271 ec.extract(clusterIndices);
274 for (std::vector<pcl::PointIndices>::const_iterator it = clusterIndices.begin();
275 it != clusterIndices.end();
278 for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end();
281 const unsigned int i =
static_cast<unsigned int>(*pit);
282 const PointT& src = inputCloud->points[i];
285 p.getVector3fMap() = src.getVector3fMap();
289 resultCloud->points.push_back(p);
294 resultCloud->width =
static_cast<unsigned int>(resultCloud->points.size());
295 resultCloud->height = 1;
296 resultCloud->is_dense =
false;
300TabletopSegmentation::guiTask()
304 RemoteGui::TabProxy tab(remoteGui,
getName());
306 while (!remoteGuiTask->isStopped())
308 tab.receiveUpdates();
311 c.waitForCycleDuration();
316TabletopSegmentation::guiCreate()
322 grid.addTextLabel(
"Distance Threshold", row, 0);
324 .
value(prop_DistanceThreshold)
328 grid.addChild(slider, row, 1);
332 grid.addTextLabel(
"Eps Angle", row, 0);
334 .
value(prop_EpsAngle)
335 .
min(pcl::deg2rad(1.0))
336 .
max(pcl::deg2rad(30.0))
338 grid.addChild(slider, row, 1);
342 grid.addTextLabel(
"Cluster Tolerance", row, 0);
344 .
value(prop_ClusterTolerance)
348 grid.addChild(slider, row, 1);
352 grid.addTextLabel(
"Min Cluster Size ", row, 0);
354 .
value(prop_MinClusterSize)
357 grid.addChild(slider, row, 1);
361 grid.addTextLabel(
"Max Cluster Size ", row, 0);
363 .
value(prop_MaxClusterSize)
366 grid.addChild(slider, row, 1);
370 grid.addTextLabel(
"Height Min", row, 0);
372 .
value(prop_HeightMin)
376 grid.addChild(slider, row, 1);
380 grid.addTextLabel(
"Height Max", row, 0);
382 .
value(prop_HeightMax)
386 grid.addChild(slider, row, 1);
390 grid.addTextLabel(
"Include Tabletop Plane", row, 0);
393 grid.addChild(checkbox, row, 1);
397 grid.addTextLabel(
"Calculate Plane", row, 0);
399 grid.addChild(checkbox, row, 1);
403 remoteGui->createTab(
getName(), grid);
409 std::unique_lock<std::mutex> lock(prop_mutex);
410#define ARMARX_REMOTE_GUI_GET_PROP(name) \
411 prop_##name = tab.getValue<decltype(prop_##name)>(#name).get()
423#undef ARMARX_REMOTE_GUI_GET_PROP
426visionx::TabletopSegmentationPlanePtr
429 std::unique_lock guard(tablePlaneMutex);
434 const std::function<
void(
int)>& callback) :
435 serviceName(serviceName), callback(callback)
441 Ice::Int relativeTimeoutMs,
444 if (serviceName == this->serviceName)
446 callback(relativeTimeoutMs);
453 return "TabletopSegmentation";
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
#define ARMARX_REMOTE_GUI_GET_PROP(name)
ProxyType getProxyFromProperty(const std::string &propertyName, bool addToDependencies=false, const std::string &endpoints="", bool throwOnProxyError=true)
Get a proxy whose name is specified by the given property.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Property< PropertyType > getProperty(const std::string &name)
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
std::string getName() const
Retrieve name of object.
IceManagerPtr getIceManager() const
Returns the IceManager.
ServiceProvider(const std::string &serviceName, const std::function< void(int)> &callback)
void requestService(const std::string &, Ice::Int relativeTimeoutMs, const Ice::Current &)
Brief description of class TabletopSegmentation.
visionx::TabletopSegmentationPlanePtr getTablePlane(const Ice::Current &) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void onExitPointCloudProcessor() override
void onConnectPointCloudProcessor() override
void onDisconnectPointCloudProcessor() override
static std::string GetDefaultName()
void onInitPointCloudProcessor() override
std::string getDefaultName() const override
Retrieve default name of component.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
void enableResultPointClouds(std::string resultProviderName="")
Enables visualization.
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
bool waitForPointClouds(int milliseconds=1000)
Wait for new PointClouds.
void provideResultPointClouds(const PointCloudPtrT &pointClouds, std::string providerName="")
sends result PointClouds for visualization
#define ARMARX_INFO
The normal logging level.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_VERBOSE
The logging level for verbose information.
detail::CheckBoxBuilder makeCheckBox(std::string const &name)
detail::FloatSliderBuilder makeFloatSlider(std::string const &name)
detail::GridLayoutBuilder makeGridLayout(std::string const &name="")
detail::IntSliderBuilder makeIntSlider(std::string const &name)
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Derived & steps(int steps)
Derived & value(ValueT const &value)