diff --git a/CMakeLists.txt b/CMakeLists.txt index b715fb48266..75a7362f0fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,6 +297,17 @@ if(WITH_ENSENSO) endif(ENSENSO_FOUND) endif(WITH_ENSENSO) +# David Vision Systems - davidSDK +option(WITH_DAVIDSDK "Build davidSDK support" TRUE) +if(WITH_DAVIDSDK) + set(DAVIDSDK_ABI_DIR "davidSDK_ABI_DIR-NOTFOUND" CACHE PATH "directory of davidSDK ABI") + find_package(davidSDK) # FinddavidSDK.cmake + if (DAVIDSDK_FOUND) + set(HAVE_DAVIDSDK ON) + include_directories(SYSTEM "${DAVIDSDK_INCLUDE_DIRS}") + endif(DAVIDSDK_FOUND) +endif(WITH_DAVIDSDK) + # Intel Perceptional Computing Interface (PXCAPI) option(WITH_PXCAPI "Build PXC Device support" TRUE) if(WITH_PXCAPI) diff --git a/PCLConfig.cmake.in b/PCLConfig.cmake.in index 2b4bf834389..c3c3c342f60 100644 --- a/PCLConfig.cmake.in +++ b/PCLConfig.cmake.in @@ -277,6 +277,36 @@ macro(find_ensenso) endif(ENSENSO_FOUND) endmacro(find_ensenso) +#remove this as soon as the davidSDK is shipped with FinddavidSDK.cmake +macro(find_davidSDK) + if(NOT davidSDK_ROOT AND ("ON" STREQUAL "ON")) + get_filename_component(DAVIDSDK_ABI_HINT @DAVIDSDK_INCLUDE_DIR@ PATH) + endif(NOT davidSDK_ROOT AND ("ON" STREQUAL "ON")) + + find_path(DAVIDSDK_INCLUDE_DIR david.h + HINTS ${DAVIDSDK_ABI_HINT} + /usr/local/include/davidSDK + "$ENV{PROGRAMFILES}/davidSDK" "$ENV{PROGRAMW6432}/davidSDK" + PATH_SUFFIXES include/) + + find_library(DAVIDSDK_LIBRARY QUIET NAMES davidSDK + HINTS ${DAVIDSDK_ABI_HINT} + "$ENV{PROGRAMFILES}/davidSDK" "$ENV{PROGRAMW6432}/davidSDK" + PATH_SUFFIXES lib/) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(DAVIDSDK DEFAULT_MSG + DAVIDSDK_LIBRARY DAVIDSDK_INCLUDE_DIR) + + if(DAVIDSDK_FOUND) + get_filename_component(DAVIDSDK_LIBRARY_PATH ${DAVIDSDK_LIBRARY} PATH) + set(DAVIDSDK_INCLUDE_DIRS ${DAVIDSDK_INCLUDE_DIR}) + set(DAVIDSDK_LIBRARY_DIRS ${DAVIDSDK_LIBRARY_PATH}) + set(DAVIDSDK_LIBRARIES "${DAVIDSDK_LIBRARY}") + set(DAVIDSDK_REDIST_DIR $ENV{DAVIDSDK_REDIST${DAVIDSDK_SUFFIX}}) + endif(DAVIDSDK_FOUND) +endmacro(find_davidSDK) + #remove this as soon as flann is shipped with FindFlann.cmake macro(find_flann) if(PCL_ALL_IN_ONE_INSTALLER) @@ -474,6 +504,8 @@ macro(find_external_library _component _lib _is_optional) find_openni2() elseif("${_lib}" STREQUAL "ensenso") find_ensenso() + elseif("${_lib}" STREQUAL "davidSDK") + find_davidSDK() elseif("${_lib}" STREQUAL "vtk") find_VTK() elseif("${_lib}" STREQUAL "libusb-1.0") @@ -750,7 +782,7 @@ endif(NOT "${PCL_DEFINITIONS}" STREQUAL "") pcl_remove_duplicate_libraries(PCL_LIBRARIES PCL_DEDUP_LIBRARIES) set(PCL_LIBRARIES ${PCL_DEDUP_LIBRARIES}) # Add 3rd party libraries, as user code might include our .HPP implementations -list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${FLANN_LIBRARIES} ${VTK_LIBRARIES}) +list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${davidSDK_LIBRARIES} ${FLANN_LIBRARIES} ${VTK_LIBRARIES}) find_package_handle_standard_args(PCL DEFAULT_MSG PCL_LIBRARIES PCL_INCLUDE_DIRS) mark_as_advanced(PCL_LIBRARIES PCL_INCLUDE_DIRS PCL_LIBRARY_DIRS) diff --git a/cmake/Modules/FinddavidSDK.cmake b/cmake/Modules/FinddavidSDK.cmake new file mode 100644 index 00000000000..9b3b0aacc06 --- /dev/null +++ b/cmake/Modules/FinddavidSDK.cmake @@ -0,0 +1,35 @@ +############################################################################### +# - Try to find davidSDK (David Vision Systems) +# Once done this will define +# DAVIDSDK_FOUND - System has davidSDK +# DAVIDSDK_INCLUDE_DIRS - The davidSDK include directories +# DAVIDSDK_LIBRARIES - The libraries needed to use davidSDK +# DAVIDSDK_DEFINITIONS - Compiler switches required for using davidSDK +# ----------------------- + +find_path(DAVIDSDK_INCLUDE_DIR david.h + HINTS ${DAVIDSDK_ABI_HINT} + /usr/local/include/davidSDK + "$ENV{PROGRAMFILES}/davidSDK" "$ENV{PROGRAMW6432}/davidSDK" + PATH_SUFFIXES include/) + +find_library(DAVIDSDK_LIBRARY QUIET NAMES davidSDK + HINTS ${DAVIDSDK_ABI_HINT} + "$ENV{PROGRAMFILES}/davidSDK" "$ENV{PROGRAMW6432}/davidSDK" + PATH_SUFFIXES lib/) + +set(DAVIDSDK_LIBRARIES ${DAVIDSDK_LIBRARY}) +set(DAVIDSDK_INCLUDE_DIRS ${DAVIDSDK_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set DAVIDSDK_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(davidSDK DEFAULT_MSG + DAVIDSDK_LIBRARY DAVIDSDK_INCLUDE_DIR) + +mark_as_advanced(DAVIDSDK_INCLUDE_DIR DAVIDSDK_LIBRARY) + +if(DAVIDSDK_FOUND) + message(STATUS "davidSDK found") +endif(DAVIDSDK_FOUND) + diff --git a/doc/doxygen/doxyfile.in b/doc/doxygen/doxyfile.in index 6c2ed11c95d..1cf00cdad05 100644 --- a/doc/doxygen/doxyfile.in +++ b/doc/doxygen/doxyfile.in @@ -279,6 +279,7 @@ INCLUDE_FILE_PATTERNS = *.h PREDEFINED = = "HAVE_QHULL=1" \ "HAVE_OPENNI=1" \ "HAVE_ENSENSO=1" \ + "HAVE_DAVIDSDK=1" \ "PCL_DEPRECATED(x)=" EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES diff --git a/doc/tutorials/content/davidsdk.rst b/doc/tutorials/content/davidsdk.rst new file mode 100644 index 00000000000..8afe76d4d70 --- /dev/null +++ b/doc/tutorials/content/davidsdk.rst @@ -0,0 +1,121 @@ +.. _david_sdk: + +===================================================== +Grabbing point clouds / meshes from davidSDK scanners +===================================================== + +In this tutorial we will learn how to use the `davidSDK `_ through PCL. This tutorial will show you how to configure PCL and how to use the examples to fetch point clouds/meshes/images from a davidSDK compliant device (such as the `SLS-2 `_). + +.. contents:: + +Install davidSDK +================ + +You need a davidSDK to run the SDK on the server side, the official davidSDK does not come with a Makefile or a CMake project. An un-official fork provides a CMake project that enables to easily use the SDK under Linux (with minor tweaks) + + * `Official davidSDK download page `_ + * `Victor Lamoine davidSDK fork `_ + +Please test `the example project `_ before going further. + +.. note:: If you use the trial version of the server, the only format available is OBJ (used by default) + +Configuring PCL +=============== + +You need at least PCL 1.8.0 to be able to use the davidSDK. You need to make sure ``WITH_DAVIDSDK`` is set to ``true`` in the CMake configuration (it should be set to true by default if you have used the un-official davidSDK fork). + +The default following values can be tweaked into CMake if you don't have a standard installation, for example: + +.. code-block:: cmake + + DAVIDSDK_ABI_DIR /opt/davidsdk + +You can deactivate building the davidSDK support by setting ``BUILD_DAVIDSDK`` to false. Compile and install PCL. + +Platform specific directives +============================ + +It should be easy to use the davidSDK PCL support if you are using PCL on the davidSDK server; the meshes are locally exported on the storage drive and then loaded into PCL as point clouds/meshes. If you are using a Linux distribution you will need to configure more things for the davidSDK PCL implementation to work, create a temporary directory for the davidSDK meshes storage: + +.. code-block:: bash + + mkdir -p /var/tmp/davidsdk + sudo chmod 755 /var/tmp/davidsdk + +Edit samba configuration (samba must be installed first): + +.. code-block:: bash + + echo -e "[davidsdk]\n\ + path = /var/tmp/davidsdk\n\ + public = yes\n\ + writeable = yes\n\ + browseable = yes\n\ + guest ok = yes\n\ + create mask = 0775" |\ + sudo tee -a /etc/samba/smb.conf + +Restard samba server: +.. code-block:: bash + + sudo service smbd restart + +Use the :pcl:`setLocalAndRemotePaths ` function to set the local and remote paths, if you use the same path as above; this doesn't have to be called if the server is running of the same machine as the client. + +.. code-block:: cpp + + davidsdk_ptr->setLocalAndRemotePaths ("/var/tmp/davidsdk/", "\\\\name_of_machine\\davidsdk\\"); + +.. note:: + + If you get a Error_Fail = -107 error, it is most probably a write access missing in the temporary directory. + +File formats +============ + +Three file formats are available to export the meshes / clouds. + +* STL: No texture support, binary format +* OBJ: Texture support, no binary format available +* PLY: Texture support, binary format is available but davidSDK uses ASCII format + +Use the :pcl:`setFileFormatToOBJ `, +:pcl:`setFileFormatToPLY `, +:pcl:`setFileFormatToSTL ` to choose between the different formats. + +The default format used is OBJ. (it is compatible with davidSDK server trial version) + +Calibration +=========== + +In order to use the davidSDK scanner the camera and the projector must be calibrated. This can be done by calling the :pcl:`calibrate ` function of the DavidSDKGrabber object, if the calibration fails, please check `the wiki `_. + +The davidSDK will only allow you to scan if the scanner is calibrated, the davidSDK provides functions to load and save configuration files for the calibration. Also note that the davidSDK server will automatically reload the last calibration data when restarted. + +Using the example +================== + +The `pcl_davidsdk_viewer `_ example shows how to display a point cloud grabbed from an davidSDK device using the :pcl:`DavidSDKGrabber ` class. + +When using the DavidSDKGrabber you must connect to the server first; if the server is running locally you don't need to specify an IP address. If you are using davidSDK over a network just call :pcl:`connect ` with the address IP as a string, please also check that the connection didn't failed: + +.. code-block:: cpp + + davidsdk_ptr->connect ("192.168.1.50"); + if (!davidsdk_ptr->isConnected ()) + { + PCL_ERROR ("Cannot connect to davidSDK server.\n"); + return (-1); + } + +.. image:: images/davidsdk/davidsdk_viewer.jpg + :height: 550 + +.. warning:: + + Fetching clouds/meshes from the davidSDK is very slow because the point clouds/meshes are sent through the JSON interface. + Do not expect better performance than 0.07 FPS (using STL format gives best performance). + +Another example is available in `PCL sources `_, it uses OpenCV to display davidSDK images and the PCLVisualizer to display the point cloud at the same time. + diff --git a/doc/tutorials/content/images/davidsdk/david.png b/doc/tutorials/content/images/davidsdk/david.png new file mode 100644 index 00000000000..a09443b8a2d Binary files /dev/null and b/doc/tutorials/content/images/davidsdk/david.png differ diff --git a/doc/tutorials/content/images/davidsdk/davidsdk_viewer.jpg b/doc/tutorials/content/images/davidsdk/davidsdk_viewer.jpg new file mode 100644 index 00000000000..82da909a884 Binary files /dev/null and b/doc/tutorials/content/images/davidsdk/davidsdk_viewer.jpg differ diff --git a/doc/tutorials/content/index.rst b/doc/tutorials/content/index.rst index 722bb05ba8f..21deb904c95 100644 --- a/doc/tutorials/content/index.rst +++ b/doc/tutorials/content/index.rst @@ -616,6 +616,20 @@ I/O .. |i_o7| image:: images/ensenso/ids.png :height: 165px + * :ref:`david_sdk` + + ====== ====== + |i_o8| Title: **Grabbing point clouds / meshes from davidSDK scanners** + + Author: *Victor Lamoine* + + Compatibility: >= PCL 1.8.0 + + In this tutorial, we will learn how to acquire point cloud or mesh data from an davidSDK scanner. + ====== ====== + + .. |i_o8| image:: images/davidsdk/david.png + :height: 70px .. _keypoints_tutorial: diff --git a/doc/tutorials/content/sources/davidsdk/CMakeLists.txt b/doc/tutorials/content/sources/davidsdk/CMakeLists.txt new file mode 100644 index 00000000000..2336dcb2520 --- /dev/null +++ b/doc/tutorials/content/sources/davidsdk/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +project(pcl-davidSDK_images_viewer) + +find_package(PCL 1.8.0 REQUIRED) +find_package(OpenCV REQUIRED) + +include_directories(${PCL_INCLUDE_DIRS}) +link_directories(${PCL_LIBRARY_DIRS}) +add_definitions(${PCL_DEFINITIONS}) + +add_executable(davidsdk_images_viewer davidsdk_images_viewer.cpp) +target_link_libraries(davidsdk_images_viewer ${PCL_LIBRARIES} ${OpenCV_LIBS}) diff --git a/doc/tutorials/content/sources/davidsdk/davidsdk_images_viewer.cpp b/doc/tutorials/content/sources/davidsdk/davidsdk_images_viewer.cpp new file mode 100644 index 00000000000..540f6937840 --- /dev/null +++ b/doc/tutorials/content/sources/davidsdk/davidsdk_images_viewer.cpp @@ -0,0 +1,116 @@ +#include +#include +#include + +#include +#include + +/** @brief A pointer to the PCL DavidSDKGrabber object */ +pcl::DavidSDKGrabber::Ptr davidsdk_ptr; + +/** @brief Get OpenCV image type corresponding to the parameters given + * @param channels number of channels in the image + * @param bpe bytes per element + * @param isFlt is float + * @returns the OpenCV type + */ +int +getOpenCVType (std::string type) +{ + if (type == "CV_32FC1") + return CV_32FC1; + else if (type == "CV_32FC2") + return CV_32FC2; + else if (type == "CV_32FC3") + return CV_32FC3; + else if (type == "CV_32FC4") + return CV_32FC4; + else if (type == "CV_64FC1") + return CV_64FC1; + else if (type == "CV_64FC2") + return CV_64FC2; + else if (type == "CV_64FC3") + return CV_64FC3; + else if (type == "CV_64FC4") + return CV_64FC4; + else if (type == "CV_8UC1") + return CV_8UC1; + else if (type == "CV_8UC2") + return CV_8UC2; + else if (type == "CV_8UC3") + return CV_8UC3; + else if (type == "CV_8UC4") + return CV_8UC4; + else if (type == "CV_16UC1") + return CV_16UC1; + else if (type == "CV_16UC2") + return CV_16UC2; + else if (type == "CV_16UC3") + return CV_16UC3; + else if (type == "CV_16UC4") + return CV_16UC4; + else if (type == "CV_32SC1") + return CV_32SC1; + else if (type == "CV_32SC2") + return CV_32SC2; + else if (type == "CV_32SC3") + return CV_32SC3; + else if (type == "CV_32SC4") + return CV_32SC4; + + return (-1); +} + +/** @brief Process and/or display DavidSDKGrabber image + * @param[in] image davidSDK image */ +void +grabberCallback (const boost::shared_ptr& image) +{ + unsigned char *image_array = reinterpret_cast (&image->data[0]); + + int type = getOpenCVType (image->encoding); + cv::Mat cv_image (image->height, image->width, type, image_array); + + cv::imshow ("davidSDK images", cv_image); + cv::waitKey (5); +} + +/** @brief Asks the user to press enter to continue + * @param[in] str Message to display */ +void +waitForUser (std::string str = "Press enter to continue") +{ + PCL_WARN (str.c_str ()); + std::cout.flush (); + getc (stdin); +} + +/** @brief Main function + * @param argc + * @param argv + * @return Exit status */ +int +main (int argc, + char *argv[]) +{ + if (argc != 2) + { + PCL_ERROR ("Usage:\n%s 192.168.100.65\n", argv[0]); + return (-1); + } + + davidsdk_ptr.reset (new pcl::DavidSDKGrabber); + davidsdk_ptr->connect (argv[1]); + + if (!davidsdk_ptr->isConnected ()) + return (-1); + PCL_WARN ("davidSDK connected\n"); + + boost::function &)> f = boost::bind (&grabberCallback, _1); + davidsdk_ptr->registerCallback (f); + davidsdk_ptr->start (); + waitForUser ("Press enter to quit"); + + return (0); +} diff --git a/io/CMakeLists.txt b/io/CMakeLists.txt index 5444955c161..f9a7f79cb96 100644 --- a/io/CMakeLists.txt +++ b/io/CMakeLists.txt @@ -5,9 +5,9 @@ set(SUBSYS_DEPS common octree) set(build TRUE) PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON) if(WIN32) - PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso pcap png vtk) + PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK pcap png vtk) else(WIN32) - PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso pcap png vtk libusb-1.0) + PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK pcap png vtk libusb-1.0) endif(WIN32) PCL_ADD_DOC("${SUBSYS_NAME}") @@ -154,6 +154,23 @@ if(build) ) endif(ENSENSO_FOUND) + ## davidSDK + OPTION(BUILD_DAVIDSDK "Build the davidSDK Grabber." ON) + MARK_AS_ADVANCED(BUILD_DAVIDSDK) + if(NOT BUILD_DAVIDSDK) + # Set DAVIDSDK_FOUND to false locally to avoid building anything davidSDK related + # Remember that other modules (libraries) need to check explicitly for BUILD_DAVIDSDK + set(DAVIDSDK_FOUND FALSE) + endif() + if(DAVIDSDK_FOUND) + set(DAVIDSDK_GRABBER_INCLUDES + include/pcl/io/davidsdk_grabber.h + ) + set(DAVIDSDK_GRABBER_SOURCES + src/davidsdk_grabber.cpp + ) + endif(DAVIDSDK_FOUND) + if(PXCAPI_FOUND) set(PXC_GRABBER_INCLUDES include/pcl/io/pxc_grabber.h @@ -225,6 +242,7 @@ if(build) ${DINAST_GRABBER_SOURCES} ${FZAPI_GRABBER_SOURCES} ${ENSENSO_GRABBER_SOURCES} + ${DAVIDSDK_GRABBER_SOURCES} ${PXC_GRABBER_SOURCES} ) if(PNG_FOUND) @@ -269,6 +287,7 @@ if(build) ${DINAST_GRABBER_INCLUDES} ${FZAPI_GRABBER_INCLUDES} ${ENSENSO_GRABBER_INCLUDES} + ${DAVIDSDK_GRABBER_INCLUDES} ${PXC_GRABBER_INCLUDES} ) @@ -340,6 +359,10 @@ if(build) target_link_libraries(${LIB_NAME} ${ENSENSO_LIBRARIES}) endif(ENSENSO_FOUND) + if(DAVIDSDK_FOUND) + target_link_libraries(${LIB_NAME} ${DAVIDSDK_LIBRARIES}) + endif(DAVIDSDK_FOUND) + if(PXCAPI_FOUND) link_directories(${PXCAPI_LIB_DIRS}) target_link_libraries("${LIB_NAME}" ${PXCAPI_LIBS}) diff --git a/io/include/pcl/io/davidsdk_grabber.h b/io/include/pcl/io/davidsdk_grabber.h new file mode 100644 index 00000000000..879e797cece --- /dev/null +++ b/io/include/pcl/io/davidsdk_grabber.h @@ -0,0 +1,269 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Victor Lamoine (victor.lamoine@gmail.com) + */ + +#include + +#ifndef __PCL_IO_DAVIDSDK_GRABBER__ +#define __PCL_IO_DAVIDSDK_GRABBER__ + +#include +#include +#include +#include +#include + +#include + +namespace pcl +{ + struct PointXYZ; + template class PointCloud; + + /** @brief Grabber for davidSDK structured light compliant devices.\n + * The davidSDK SDK allows to use a structured light scanner to + * fetch clouds/meshes.\n + * The purpose of this grabber is NOT to provide all davidSDK functionalities but rather provide a PCL-unified interface to the sensor for + * basic operations.\n + * Please consult the David-3d wiki for more information. + * @author Victor Lamoine (victor.lamoine@gmail.com)\n + * @ingroup io + */ + class PCL_EXPORTS DavidSDKGrabber : public Grabber + { + public: + /** @cond */ + typedef boost::shared_ptr Ptr; + typedef boost::shared_ptr ConstPtr; + + // Define callback signature typedefs + typedef void + (sig_cb_davidsdk_point_cloud) (const pcl::PointCloud::Ptr &); + + typedef void + (sig_cb_davidsdk_mesh) (const pcl::PolygonMesh::Ptr &); + + typedef void + (sig_cb_davidsdk_image) (const boost::shared_ptr &); + + typedef void + (sig_cb_davidsdk_point_cloud_image) (const pcl::PointCloud::Ptr &, + const boost::shared_ptr &); + + typedef void + (sig_cb_davidsdk_mesh_image) (const pcl::PolygonMesh::Ptr &, + const boost::shared_ptr &); + /** @endcond */ + + /** @brief Constructor */ + DavidSDKGrabber (); + + /** @brief Destructor inherited from the Grabber interface. It never throws. */ + virtual + ~DavidSDKGrabber () throw (); + + /** @brief Connect client + * @param[in] address + * @param[in] port + * @return Server info*/ + david::ServerInfo + connect (const std::string & address = "127.0.0.1", + uint16_t port = david::DAVID_SDK_DefaultPort); + + /** @brief Disconnect client + * @param[in] stop_server */ + void + disconnect (const bool stop_server); + + /** @brief Start the point cloud and or image acquisition */ + void + start (); + + /** @brief Stop the data acquisition */ + void + stop (); + + /** @brief Check if the data acquisition is still running + * @return True if running, false otherwise */ + bool + isRunning () const; + + /** @brief Check if the client is connected + * @return True if connected, false otherwise */ + bool + isConnected () const; + + /** @brief Get class name + * @returns A string containing the class name */ + std::string + getName () const; + + /** @brief Get @ref local_path_ path directory + * @returns the path */ + std::string + getLocalPath (); + + /** @brief Get @ref remote_path_ path directory + * @returns the path */ + std::string + getRemotePath (); + + /** @brief Set @ref file_format_ to "obj" */ + void + setFileFormatToOBJ (); + + /** @brief Set @ref file_format_ to "ply" + * @warning This format is NOT available with trial versions of davidSDK server! */ + void + setFileFormatToPLY (); + + /** @brief Set @ref file_format_ to "stl" */ + void + setFileFormatToSTL (); + + /** @brief Get @ref file_format_ + * @returns the file format */ + std::string + getFileFormat (); + + /** @brief Set @ref local_path_ path directory for scanning files + * @param[in] path The directory path + * + * If the path is empty, using default value ("C:/temp") */ + void + setLocalPath (std::string path); + + /** @brief Set @ref remote_path_ path directory for scanning files + * @param[in] path The directory path + * + * If the string is empty, @ref remote_path_ = @ref local_path_ */ + void + setRemotePath (std::string path); + + /** @brief Set @ref local_path_ and @ref remote_path_ directory paths + * @param[in] local_path + * @param[in] remote_path + * + * If the path is empty, using default value ("C:/temp") */ + void + setLocalAndRemotePaths (std::string local_path, + std::string remote_path); + + /** @brief Calibrate the scanner + * @param[in] grid_size Size of the calibration grid in millimeters + * @return True if successful, false otherwise + * + * More information here.\n + * Also see ImportCalibration.\n + * and ExportCalibration. + * + * @warning You MUST perform calibration each time you modify the camera/projector focus or move the camera relatively to the projector.\n + */ + bool + calibrate (double grid_size); + + /** @brief Capture a single point cloud and store it + * @param[out] cloud The cloud to be filled + * @return True if successful, false otherwise + * @warning Calls DeleteAllMeshes() */ + bool + grabSingleCloud (pcl::PointCloud &cloud); + + /** @brief Capture a single mesh and store it + * @param[out] mesh The mesh to be filled + * @return True if successful, false otherwise + * @warning Calls DeleteAllMeshes() */ + bool + grabSingleMesh (pcl::PolygonMesh &mesh); + + /** @brief Obtain the number of frames per second (FPS) */ + float + getFramesPerSecond () const; + + /** @brief davidSDK client */ + david::Client david_; + + protected: + /** @brief Grabber thread */ + boost::thread grabber_thread_; + + /** @brief Boost point cloud signal */ + boost::signals2::signal* point_cloud_signal_; + + /** @brief Boost mesh signal */ + boost::signals2::signal* mesh_signal_; + + /** @brief Boost image signal */ + boost::signals2::signal* image_signal_; + + /** @brief Boost image + point cloud signal */ + boost::signals2::signal* point_cloud_image_signal_; + + /** @brief Boost mesh + image signal */ + boost::signals2::signal* mesh_image_signal_; + + /** @brief Whether the client is connected */ + bool client_connected_; + + /** @brief Whether an davidSDK device is running or not */ + bool running_; + + /** @brief Local path of directory where the scanning file will be located.\n + * Default value is @c C:/temp */ + std::string local_path_; + + /** @brief Remote path of directory where the scanning file will be located.\n + * If this is empty, the @ref local_path_ will be used instead + * Default value is @c C:/temp */ + std::string remote_path_; + + /** @brief Export file extension, available formats for PCL are OBJ, PLY */ + std::string file_format_; + + /** @brief processGrabbing capture/processing frequency */ + pcl::EventFrequency frequency_; + + /** @brief Mutual exclusion for FPS computation */ + mutable boost::mutex fps_mutex_; + + /** @brief Continuously asks for images and or point clouds/meshes data from the device and publishes them if available. */ + void + processGrabbing (); + }; +} // namespace pcl + +#endif // __PCL_IO_DAVIDSDK_GRABBER__ diff --git a/io/src/davidsdk_grabber.cpp b/io/src/davidsdk_grabber.cpp new file mode 100644 index 00000000000..dc8d83dc62b --- /dev/null +++ b/io/src/davidsdk_grabber.cpp @@ -0,0 +1,445 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Victor Lamoine (victor.lamoine@gmail.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Possible improvements: +// TODO: Add presets for david::CodedLightPhaseShiftParams to enable easy scan quality changing +// TODO: Add texture support (call .Scan () instead of .Scan (false) and properly convert data +// TODO: Use mesh IDs rather than clearing all meshes every time +// TODO: In processGrabbing, start scanning again while transferring the mesh (not possible with SDK 1.5.2 because ExportMesh() is blocking) + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +pcl::DavidSDKGrabber::DavidSDKGrabber () : + client_connected_ (false), + running_ (false), + local_path_ ("C:/temp"), + remote_path_ ("C:/temp"), + file_format_ ("stl") +{ + point_cloud_signal_ = createSignal (); + mesh_signal_ = createSignal (); + image_signal_ = createSignal (); + point_cloud_image_signal_ = createSignal (); + mesh_image_signal_ = createSignal (); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +pcl::DavidSDKGrabber::~DavidSDKGrabber () throw () +{ + try + { + stop (); + + disconnect_all_slots (); + disconnect_all_slots (); + disconnect_all_slots (); + disconnect_all_slots (); + disconnect_all_slots (); + } + catch (...) + { + // destructor never throws + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +david::ServerInfo +pcl::DavidSDKGrabber::connect (const std::string &address, + uint16_t port) +{ + david::ServerInfo server_info; + + if (client_connected_) + return (server_info); + + try + { + david_.Connect (address, port); + client_connected_ = true; + } + catch (david::Exception& e) + { + e.PrintError (); + } + + return (server_info); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::disconnect (const bool stop_server) +{ + if (!client_connected_) + return; + + try + { + david_.Disconnect (stop_server); + } + catch (david::Exception& e) + { + e.PrintError (); + } + + client_connected_ = false; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::start () +{ + if (isRunning ()) + return; + + frequency_.reset (); + running_ = true; + grabber_thread_ = boost::thread (&pcl::DavidSDKGrabber::processGrabbing, this); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::stop () +{ + if (running_) + { + running_ = false; // Stop processGrabbing () callback + + grabber_thread_.join (); // join () waits for the thread to finish it's last iteration + // See: http://www.boost.org/doc/libs/1_54_0/doc/html/thread/thread_management.html#thread.thread_management.thread.join + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::DavidSDKGrabber::isRunning () const +{ + return (running_); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::DavidSDKGrabber::isConnected () const +{ + return (client_connected_); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +std::string +pcl::DavidSDKGrabber::getName () const +{ + return ("DavidSDKGrabber"); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +std::string +pcl::DavidSDKGrabber::getLocalPath () +{ + return (local_path_); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +std::string +pcl::DavidSDKGrabber::getRemotePath () +{ + return (remote_path_); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::setFileFormatToOBJ () +{ + file_format_ = "obj"; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::setFileFormatToPLY () +{ + file_format_ = "ply"; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::setFileFormatToSTL () +{ + file_format_ = "stl"; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +std::string +pcl::DavidSDKGrabber::getFileFormat () +{ + return (file_format_); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::setLocalPath (std::string path) +{ + local_path_ = path; + + if (path.empty ()) + local_path_ = "C:/temp"; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::setRemotePath (std::string path) +{ + remote_path_ = path; + + if (path.empty ()) + remote_path_ = local_path_; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::setLocalAndRemotePaths (std::string local_path, + std::string remote_path) +{ + setLocalPath (local_path); + setRemotePath (remote_path); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::DavidSDKGrabber::calibrate (double grid_size) +{ + if (!client_connected_ || running_) + return (false); + + try + { + david_.sls ().Calibrate (grid_size); + } + catch (david::Exception& e) + { + e.PrintError (); + return (false); + } + return (true); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::DavidSDKGrabber::grabSingleCloud (pcl::PointCloud &cloud) +{ + if (!client_connected_ || running_) + return (false); + + try + { + david_.sls ().Scan (false); + david_.fusion ().DeleteAllMeshes (); + david_.sls ().AddScanToShapeFusion (); + david_.sls ().ExportMesh (remote_path_ + "scan." + file_format_); + + pcl::PolygonMesh mesh; + if (file_format_ == "obj") + { + if (pcl::io::loadPolygonFileOBJ (local_path_ + "scan." + file_format_, mesh) == 0) + return (false); + } + else if (file_format_ == "ply") + { + if (pcl::io::loadPolygonFilePLY (local_path_ + "scan." + file_format_, mesh) == 0) + return (false); + } + else if (file_format_ == "stl") + { + if (pcl::io::loadPolygonFileSTL (local_path_ + "scan." + file_format_, mesh) == 0) + return (false); + } + else + return (false); + + pcl::fromPCLPointCloud2 (mesh.cloud, cloud); + } + catch (david::Exception& e) + { + e.PrintError (); + return (false); + } + return (true); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::DavidSDKGrabber::grabSingleMesh (pcl::PolygonMesh &mesh) +{ + if (!client_connected_ || running_) + return (false); + + try + { + david_.sls ().Scan (false); + david_.fusion ().DeleteAllMeshes (); + david_.sls ().AddScanToShapeFusion (); + david_.sls ().ExportMesh (remote_path_ + "scan." + file_format_); + + if (file_format_ == "obj") + { + if (pcl::io::loadPolygonFileOBJ (local_path_ + "scan." + file_format_, mesh) == 0) + return (false); + } + else if (file_format_ == "ply") + { + if (pcl::io::loadPolygonFilePLY (local_path_ + "scan." + file_format_, mesh) == 0) + return (false); + } + else if (file_format_ == "stl") + { + if (pcl::io::loadPolygonFileSTL (local_path_ + "scan." + file_format_, mesh) == 0) + return (false); + } + else + return (false); + + } + catch (david::Exception& e) + { + e.PrintError (); + return (false); + } + return (true); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float +pcl::DavidSDKGrabber::getFramesPerSecond () const +{ + boost::mutex::scoped_lock lock (fps_mutex_); + return (frequency_.getFrequency ()); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::DavidSDKGrabber::processGrabbing () +{ + bool continue_grabbing = running_; + while (continue_grabbing) + { + try + { + // Publish cloud / images + if (num_slots () > 0 || num_slots () > 0 || num_slots () > 0 + || num_slots () > 0 || num_slots () > 0) + { + pcl::PolygonMesh::Ptr mesh; + pcl::PointCloud::Ptr cloud; + boost::shared_ptr image; + + fps_mutex_.lock (); + frequency_.event (); + fps_mutex_.unlock (); + + // We need the image + if (num_slots () > 0 || num_slots () > 0 || num_slots () > 0) + { + image.reset (new pcl::PCLImage); + int width, height; + david_.sls ().GetLiveImage (image->data, width, height); + image->width = (uint32_t) width; + image->height = (uint32_t) height; + image->encoding = "CV_8UC1"; + } + + // We need the cloud or mesh + if (num_slots () > 0 || num_slots () > 0 || num_slots () > 0 + || num_slots () > 0) + { + mesh.reset (new pcl::PolygonMesh); + david_.sls ().Scan (false); + david_.fusion ().DeleteAllMeshes (); + david_.sls ().AddScanToShapeFusion (); + david_.sls ().ExportMesh (remote_path_ + "scan." + file_format_); + + if (file_format_ == "obj") + { + if (pcl::io::loadPolygonFileOBJ (local_path_ + "scan." + file_format_, *mesh) == 0) + return; + } + else if (file_format_ == "ply") + { + if (pcl::io::loadPolygonFilePLY (local_path_ + "scan." + file_format_, *mesh) == 0) + return; + } + else if (file_format_ == "stl") + { + if (pcl::io::loadPolygonFileSTL (local_path_ + "scan." + file_format_, *mesh) == 0) + return; + } + else + return; + + if (num_slots () > 0 || num_slots () > 0) + { + cloud.reset (new PointCloud); + pcl::fromPCLPointCloud2 (mesh->cloud, *cloud); + } + } + + // Publish signals + if (num_slots () > 0) + point_cloud_image_signal_->operator () (cloud, image); + if (num_slots () > 0) + mesh_image_signal_->operator () (mesh, image); + else if (num_slots () > 0) + point_cloud_signal_->operator () (cloud); + else if (num_slots () > 0) + mesh_signal_->operator () (mesh); + else if (num_slots () > 0) + image_signal_->operator () (image); + } + continue_grabbing = running_; + } + catch (david::Exception& e) + { + e.PrintError (); + } + } +} diff --git a/pcl_config.h.in b/pcl_config.h.in index da86f52d229..e3aafff0851 100644 --- a/pcl_config.h.in +++ b/pcl_config.h.in @@ -28,6 +28,8 @@ #cmakedefine HAVE_ENSENSO 1 +#cmakedefine HAVE_DAVIDSDK 1 + // SSE macros #cmakedefine HAVE_POSIX_MEMALIGN #cmakedefine HAVE_MM_MALLOC diff --git a/visualization/CMakeLists.txt b/visualization/CMakeLists.txt index 62018486d6e..92499875088 100644 --- a/visualization/CMakeLists.txt +++ b/visualization/CMakeLists.txt @@ -14,7 +14,7 @@ else(NOT VTK_FOUND) endif(NOT VTK_FOUND) PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") -PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS vtk OPT_DEPS openni openni2 ensenso) +PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS vtk OPT_DEPS openni openni2 ensenso davidSDK) if (ANDROID) set (build FALSE) @@ -162,6 +162,9 @@ if(build) if(ENSENSO_FOUND) list(APPEND EXT_DEPS ensenso) endif(ENSENSO_FOUND) + if(DAVIDSDK_FOUND) + list(APPEND EXT_DEPS davidSDK) + endif(DAVIDSDK_FOUND) PCL_MAKE_PKGCONFIG("${LIB_NAME}" "${SUBSYS_NAME}" "${SUBSYS_DESC}" "${SUBSYS_DEPS}" "${EXT_DEPS}" "" "" "") diff --git a/visualization/tools/CMakeLists.txt b/visualization/tools/CMakeLists.txt index 70010dce28b..fd584266c5e 100644 --- a/visualization/tools/CMakeLists.txt +++ b/visualization/tools/CMakeLists.txt @@ -43,3 +43,8 @@ if(ENSENSO_FOUND AND BUILD_ENSENSO) PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_ensenso_viewer ${SUBSYS_NAME} ensenso_viewer.cpp) target_link_libraries(pcl_ensenso_viewer pcl_common pcl_io pcl_visualization) endif() + +if(DAVIDSDK_FOUND AND BUILD_DAVIDSDK) + PCL_ADD_EXECUTABLE_OPT_BUNDLE(pcl_davidsdk_viewer ${SUBSYS_NAME} davidsdk_viewer.cpp) + target_link_libraries(pcl_davidsdk_viewer pcl_common pcl_io pcl_visualization) +endif() diff --git a/visualization/tools/davidsdk_viewer.cpp b/visualization/tools/davidsdk_viewer.cpp new file mode 100644 index 00000000000..ee25e7bbce4 --- /dev/null +++ b/visualization/tools/davidsdk_viewer.cpp @@ -0,0 +1,108 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2014-, Open Perception, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Victor Lamoine (victor.lamoine@gmail.com) + */ + +#include +#include +#include + +/** @brief Convenience typedef */ +typedef pcl::visualization::CloudViewer CloudViewer; + +/** @brief Convenience typedef for XYZ point clouds */ +typedef pcl::PointCloud PointCloudXYZ; + +/** @brief CloudViewer pointer */ +boost::shared_ptr viewer_ptr; + +/** @brief PCL DavidSDK object pointer */ +pcl::DavidSDKGrabber::Ptr davidsdk_ptr; + +/** @brief Process and/or display DavidSDK grabber clouds + * @param[in] cloud DavidSDK cloud */ +void +grabberCallback (const PointCloudXYZ::Ptr& cloud) +{ + if (!viewer_ptr->wasStopped ()) + viewer_ptr->showCloud (cloud); +} + +/** @brief Main function + * @param[in] argc + * @param[in] argv + * @return Exit status */ +int +main (int argc, + char *argv[]) +{ + if (argc != 2) + { + PCL_ERROR ("Usage:\n%s 192.168.100.65\n", argv[0]); + return (-1); + } + + viewer_ptr.reset (new CloudViewer ("davidSDK 3D cloud viewer")); + davidsdk_ptr.reset (new pcl::DavidSDKGrabber); + davidsdk_ptr->connect (argv[1]); + + if (!davidsdk_ptr->isConnected ()) + return (-1); + PCL_WARN ("davidSDK connected\n"); + +#ifndef _WIN32// || _WIN64 + PCL_WARN ("Linux / Mac OSX detected, setting local_path_ to /var/tmp/davidsdk/ and remote_path_ to \\\\m6700\\davidsdk\\\n"); + davidsdk_ptr->setLocalAndRemotePaths ("/var/tmp/davidsdk/", "\\\\m6700\\davidsdk\\"); +#endif + + //davidsdk_ptr->setFileFormatToPLY(); + std::cout << "Using " << davidsdk_ptr->getFileFormat () << " file format" << std::endl; + + boost::function f = boost::bind (&grabberCallback, _1); + davidsdk_ptr->registerCallback (f); + davidsdk_ptr->start (); + + while (!viewer_ptr->wasStopped ()) + { + boost::this_thread::sleep (boost::posix_time::seconds (20)); + std::cout << "FPS: " << davidsdk_ptr->getFramesPerSecond () << std::endl; + } + + davidsdk_ptr->stop (); + return (0); +} +