1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage, Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
35
36 #include <pcl/console/parse.h>
37 #include <pcl/filters/extract_indices.h>
38 #include <pcl/filters/voxel_grid.h>
39 #include <pcl/io/openni_camera/openni_driver.h>
40 #include <pcl/io/openni_grabber.h>
41 #include <pcl/sample_consensus/method_types.h>
42 #include <pcl/sample_consensus/model_types.h>
43 #include <pcl/segmentation/sac_segmentation.h>
44 #include <pcl/visualization/cloud_viewer.h>
45 #include <pcl/point_cloud.h>
46 #include <pcl/point_types.h>
47
48 #include <mutex>
49
50 template <typename PointType>
51 class OpenNIPlanarSegmentation {
52 public:
53 using Cloud = pcl::PointCloud<PointType>;
54 using CloudPtr = typename Cloud::Ptr;
55 using CloudConstPtr = typename Cloud::ConstPtr;
56
OpenNIPlanarSegmentation(const std::string & device_id="",double threshold=0.01)57 OpenNIPlanarSegmentation(const std::string& device_id = "", double threshold = 0.01)
58 : viewer("PCL OpenNI Planar Segmentation Viewer"), device_id_(device_id)
59 {
60 grid_.setFilterFieldName("z");
61 grid_.setFilterLimits(0.0f, 3.0f);
62 grid_.setLeafSize(0.01f, 0.01f, 0.01f);
63
64 seg_.setOptimizeCoefficients(true);
65 seg_.setModelType(pcl::SACMODEL_PLANE);
66 seg_.setMethodType(pcl::SAC_RANSAC);
67 seg_.setMaxIterations(1000);
68 seg_.setDistanceThreshold(threshold);
69
70 extract_.setNegative(false);
71 }
72
73 void
cloud_cb_(const CloudConstPtr & cloud)74 cloud_cb_(const CloudConstPtr& cloud)
75 {
76 set(cloud);
77 }
78
79 void
set(const CloudConstPtr & cloud)80 set(const CloudConstPtr& cloud)
81 {
82 // lock while we set our cloud;
83 std::lock_guard<std::mutex> lock(mtx_);
84 cloud_ = cloud;
85 }
86
87 CloudPtr
get()88 get()
89 {
90 // lock while we swap our cloud and reset it.
91 std::lock_guard<std::mutex> lock(mtx_);
92 CloudPtr temp_cloud(new Cloud);
93 CloudPtr temp_cloud2(new Cloud);
94
95 grid_.setInputCloud(cloud_);
96 grid_.filter(*temp_cloud);
97
98 pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
99 pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
100
101 seg_.setInputCloud(temp_cloud);
102 seg_.segment(*inliers, *coefficients);
103
104 extract_.setInputCloud(temp_cloud);
105 extract_.setIndices(inliers);
106 extract_.filter(*temp_cloud2);
107
108 return temp_cloud2;
109 }
110
111 void
run()112 run()
113 {
114 pcl::OpenNIGrabber interface{device_id_};
115
116 std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
117 cloud_cb_(cloud);
118 };
119 boost::signals2::connection c = interface.registerCallback(f);
120
121 interface.start();
122
123 while (!viewer.wasStopped()) {
124 if (cloud_) {
125 // the call to get() sets the cloud_ to null;
126 viewer.showCloud(get());
127 }
128 }
129
130 interface.stop();
131 }
132
133 pcl::visualization::CloudViewer viewer;
134 pcl::VoxelGrid<PointType> grid_;
135 pcl::SACSegmentation<PointType> seg_;
136 pcl::ExtractIndices<PointType> extract_;
137
138 std::string device_id_;
139 std::mutex mtx_;
140 CloudConstPtr cloud_;
141 };
142
143 void
usage(char ** argv)144 usage(char** argv)
145 {
146 std::cout << "usage: " << argv[0] << " <device_id> <options>\n\n"
147 << "where options are:\n -thresh X :: set the planar "
148 "segmentation threshold (default: 0.5)\n";
149
150 openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance();
151 if (driver.getNumberDevices() > 0) {
152 for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices(); ++deviceIdx) {
153 // clang-format off
154 std::cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName (deviceIdx) << ", product: " << driver.getProductName (deviceIdx)
155 << ", connected: " << driver.getBus (deviceIdx) << " @ " << driver.getAddress (deviceIdx) << ", serial number: \'" << driver.getSerialNumber (deviceIdx) << "\'" << std::endl;
156 std::cout << "device_id may be #1, #2, ... for the first second etc device in the list or" << std::endl
157 << " bus@address for the device connected to a specific usb-bus / address combination (works only in Linux) or" << std::endl
158 << " <serial-number> (only in Linux and for devices which provide serial numbers)" << std::endl;
159 // clang-format on
160 }
161 }
162 else
163 std::cout << "No devices connected." << std::endl;
164 }
165
166 int
main(int argc,char ** argv)167 main(int argc, char** argv)
168 {
169 if (argc < 2) {
170 usage(argv);
171 return 1;
172 }
173
174 std::string arg(argv[1]);
175
176 if (arg == "--help" || arg == "-h") {
177 usage(argv);
178 return 1;
179 }
180
181 double threshold = 0.05;
182 pcl::console::parse_argument(argc, argv, "-thresh", threshold);
183
184 pcl::OpenNIGrabber grabber(arg);
185 if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
186 OpenNIPlanarSegmentation<pcl::PointXYZRGBA> v(arg, threshold);
187 v.run();
188 }
189 else {
190 OpenNIPlanarSegmentation<pcl::PointXYZ> v(arg, threshold);
191 v.run();
192 }
193
194 return 0;
195 }
196