2014-06-15 03:32:25 +00:00
|
|
|
/*
|
2016-07-17 21:57:10 -04:00
|
|
|
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
2014-08-11 17:00:55 +00:00
|
|
|
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 Universite de Sherbrooke 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 HOLDER 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.
|
|
|
|
|
*/
|
2014-06-15 03:32:25 +00:00
|
|
|
|
|
|
|
|
#include "rtabmap/core/CameraRGBD.h"
|
2015-06-26 18:21:32 -04:00
|
|
|
#include "rtabmap/core/CameraStereo.h"
|
2015-08-27 17:16:12 -04:00
|
|
|
#include "rtabmap/core/util2d.h"
|
2014-06-15 03:32:25 +00:00
|
|
|
#include "rtabmap/core/util3d.h"
|
2015-05-13 19:54:23 -04:00
|
|
|
#include "rtabmap/core/util3d_transforms.h"
|
2025-12-21 11:52:38 -08:00
|
|
|
#include "rtabmap/core/SensorCaptureThread.h"
|
|
|
|
|
#include <rtabmap/gui/CameraViewer.h>
|
2014-06-15 03:32:25 +00:00
|
|
|
#include "rtabmap/utilite/ULogger.h"
|
2015-05-13 19:54:23 -04:00
|
|
|
#include "rtabmap/utilite/UMath.h"
|
2015-07-16 11:52:09 -04:00
|
|
|
#include "rtabmap/utilite/UFile.h"
|
|
|
|
|
#include "rtabmap/utilite/UDirectory.h"
|
|
|
|
|
#include "rtabmap/utilite/UConversion.h"
|
2025-12-21 11:52:38 -08:00
|
|
|
#include "rtabmap/utilite/UEventsManager.h"
|
2014-06-15 03:32:25 +00:00
|
|
|
#include <opencv2/highgui/highgui.hpp>
|
2015-04-04 11:29:14 -04:00
|
|
|
#include <opencv2/imgproc/imgproc.hpp>
|
2014-06-15 03:32:25 +00:00
|
|
|
#include <pcl/visualization/cloud_viewer.h>
|
|
|
|
|
#include <stdio.h>
|
2015-07-17 16:24:02 -04:00
|
|
|
#include <signal.h>
|
2025-12-21 11:52:38 -08:00
|
|
|
#include <QApplication>
|
2026-07-01 18:11:28 -07:00
|
|
|
#include <QSurfaceFormat>
|
|
|
|
|
#include <vtkVersionMacros.h>
|
|
|
|
|
#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION==9 && VTK_MINOR_VERSION >= 1)
|
|
|
|
|
#include <QVTKRenderWidget.h>
|
|
|
|
|
#endif
|
2014-06-15 03:32:25 +00:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
void showUsage(const char * executableName)
|
2014-06-15 03:32:25 +00:00
|
|
|
{
|
|
|
|
|
printf("\nUsage:\n"
|
2025-12-21 11:52:38 -08:00
|
|
|
"%s [options] driver\n"
|
2015-04-04 11:29:14 -04:00
|
|
|
" driver Driver number to use: 0=OpenNI-PCL (Kinect)\n"
|
|
|
|
|
" 1=OpenNI2 (Kinect and Xtion PRO Live)\n"
|
|
|
|
|
" 2=Freenect (Kinect)\n"
|
|
|
|
|
" 3=OpenNI-CV (Kinect)\n"
|
|
|
|
|
" 4=OpenNI-CV-ASUS (Xtion PRO Live)\n"
|
|
|
|
|
" 5=Freenect2 (Kinect v2)\n"
|
2015-04-07 12:00:10 -04:00
|
|
|
" 6=DC1394 (Bumblebee2)\n"
|
2015-07-16 11:52:09 -04:00
|
|
|
" 7=FlyCapture2 (Bumblebee2)\n"
|
2016-05-31 19:09:49 -04:00
|
|
|
" 8=ZED stereo\n"
|
2016-07-26 18:39:34 -04:00
|
|
|
" 9=RealSense\n"
|
2017-11-06 00:19:12 -05:00
|
|
|
" 10=Kinect for Windows 2 SDK\n"
|
2018-06-15 12:24:00 -04:00
|
|
|
" 11=RealSense2\n"
|
2019-07-09 20:48:09 -04:00
|
|
|
" 12=Kinect for Azure SDK\n"
|
2020-04-30 00:57:47 -04:00
|
|
|
" 13=MYNT EYE S\n"
|
2021-02-28 10:31:18 -05:00
|
|
|
" 14=ZED Open Capture\n"
|
2021-03-07 12:27:21 -05:00
|
|
|
" 15=depthai-core\n"
|
2024-05-30 16:55:37 +08:00
|
|
|
" 16=XVSDK (SeerSense)\n"
|
2025-10-07 10:22:16 -07:00
|
|
|
" 17=Orbbec SDK\n"
|
2015-07-16 11:52:09 -04:00
|
|
|
" Options:\n"
|
2025-12-21 11:52:38 -08:00
|
|
|
" -r #.# Input rate Hz (default 0=inf)\n"
|
|
|
|
|
" -d # Device ID (number or string)\n"
|
|
|
|
|
" -w # Request a specific image width. Not all camera drivers support this.\n"
|
|
|
|
|
" -h # Request a specific image height. Not all camera drivers support this.\n"
|
|
|
|
|
" -pcl Use PCL's CloudViewer for visualization (legacy).\n",
|
|
|
|
|
executableName);
|
2014-06-15 03:32:25 +00:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-16 11:52:09 -04:00
|
|
|
// catch ctrl-c
|
|
|
|
|
bool running = true;
|
|
|
|
|
void sighandler(int sig)
|
|
|
|
|
{
|
|
|
|
|
printf("\nSignal %d caught...\n", sig);
|
|
|
|
|
running = false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-15 03:32:25 +00:00
|
|
|
int main(int argc, char * argv[])
|
|
|
|
|
{
|
|
|
|
|
ULogger::setType(ULogger::kTypeConsole);
|
2026-07-04 18:16:37 -07:00
|
|
|
ULogger::setLevel(ULogger::kDebug);
|
2015-04-10 17:36:13 -04:00
|
|
|
//ULogger::setPrintTime(false);
|
|
|
|
|
//ULogger::setPrintWhere(false);
|
2014-06-15 03:32:25 +00:00
|
|
|
|
|
|
|
|
int driver = 0;
|
2015-07-16 11:52:09 -04:00
|
|
|
float rate = 0.0f;
|
2019-07-09 20:48:09 -04:00
|
|
|
std::string deviceId;
|
2025-12-21 11:52:38 -08:00
|
|
|
int width = 0;
|
|
|
|
|
int height = 0;
|
|
|
|
|
bool usePCLViz = false;
|
2014-07-21 18:46:48 +00:00
|
|
|
if(argc < 2)
|
2014-06-15 03:32:25 +00:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2014-07-21 18:46:48 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-07-16 11:52:09 -04:00
|
|
|
for(int i=1; i<argc; ++i)
|
2015-04-06 13:35:44 -04:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
if(strcmp(argv[i], "-rate") == 0 || strcmp(argv[i], "-r") == 0)
|
2015-07-16 11:52:09 -04:00
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if(i < argc)
|
|
|
|
|
{
|
|
|
|
|
rate = uStr2Float(argv[i]);
|
|
|
|
|
if(rate < 0.0f)
|
|
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
if (strcmp(argv[i], "-device") == 0 || strcmp(argv[i], "-d") == 0)
|
2019-07-09 20:48:09 -04:00
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if (i < argc)
|
|
|
|
|
{
|
|
|
|
|
deviceId = argv[i];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2019-07-09 20:48:09 -04:00
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
if (strcmp(argv[i], "-w") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if (i < argc)
|
|
|
|
|
{
|
|
|
|
|
width = atoi(argv[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage(argv[0]);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(argv[i], "-h") == 0)
|
|
|
|
|
{
|
|
|
|
|
++i;
|
|
|
|
|
if (i < argc)
|
|
|
|
|
{
|
|
|
|
|
height = atoi(argv[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
showUsage(argv[0]);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(argv[i], "-pcl") == 0)
|
|
|
|
|
{
|
|
|
|
|
usePCLViz = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-07-16 11:52:09 -04:00
|
|
|
if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-help") == 0)
|
|
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
2015-07-16 20:59:33 -04:00
|
|
|
else if(i< argc-1)
|
|
|
|
|
{
|
|
|
|
|
printf("Unrecognized option \"%s\"", argv[i]);
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2015-07-16 20:59:33 -04:00
|
|
|
}
|
2015-07-16 11:52:09 -04:00
|
|
|
|
|
|
|
|
// last
|
|
|
|
|
driver = atoi(argv[i]);
|
2025-10-07 10:22:16 -07:00
|
|
|
if(driver < 0 || driver > 17)
|
2015-07-16 11:52:09 -04:00
|
|
|
{
|
2025-10-07 10:22:16 -07:00
|
|
|
UERROR("driver should be between 0 and 17.");
|
2025-12-21 11:52:38 -08:00
|
|
|
showUsage(argv[0]);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
2014-06-15 03:32:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-07-09 20:48:09 -04:00
|
|
|
UINFO("Using driver %d (device=%s)", driver, deviceId.empty()?"0": deviceId.c_str());
|
2014-06-15 03:32:25 +00:00
|
|
|
|
2015-06-26 18:21:32 -04:00
|
|
|
rtabmap::Camera * camera = 0;
|
2025-10-07 10:22:16 -07:00
|
|
|
if(driver == 0)
|
2014-06-15 03:32:25 +00:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraOpenni(deviceId, rate);
|
2025-10-07 10:22:16 -07:00
|
|
|
}
|
|
|
|
|
else if(driver == 1)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraOpenNI2::available())
|
2014-06-15 03:32:25 +00:00
|
|
|
{
|
2025-10-07 10:22:16 -07:00
|
|
|
UERROR("Not built with OpenNI2 support...");
|
|
|
|
|
exit(-1);
|
2014-06-15 03:32:25 +00:00
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraOpenNI2(deviceId, rtabmap::CameraOpenNI2::kTypeColorDepth, rate);
|
2025-10-07 10:22:16 -07:00
|
|
|
}
|
|
|
|
|
else if(driver == 2)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraFreenect::available())
|
2014-06-15 03:32:25 +00:00
|
|
|
{
|
2025-10-07 10:22:16 -07:00
|
|
|
UERROR("Not built with Freenect support...");
|
|
|
|
|
exit(-1);
|
2014-06-15 03:32:25 +00:00
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraFreenect(deviceId.empty()?0:uStr2Int(deviceId), rtabmap::CameraFreenect::kTypeColorDepth, rate);
|
2025-10-07 10:22:16 -07:00
|
|
|
}
|
|
|
|
|
else if(driver == 3)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraOpenNICV::available())
|
2015-04-02 16:33:35 -04:00
|
|
|
{
|
2025-10-07 10:22:16 -07:00
|
|
|
UERROR("Not built with OpenNI from OpenCV support...");
|
|
|
|
|
exit(-1);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraOpenNICV(false, rate);
|
2025-10-07 10:22:16 -07:00
|
|
|
}
|
|
|
|
|
else if(driver == 4)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraOpenNICV::available())
|
2015-07-16 11:52:09 -04:00
|
|
|
{
|
2025-10-07 10:22:16 -07:00
|
|
|
UERROR("Not built with OpenNI from OpenCV support...");
|
|
|
|
|
exit(-1);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraOpenNICV(true, rate);
|
2025-10-07 10:22:16 -07:00
|
|
|
}
|
|
|
|
|
else if(driver == 5)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraFreenect2::available())
|
2015-07-16 11:52:09 -04:00
|
|
|
{
|
2025-10-07 10:22:16 -07:00
|
|
|
UERROR("Not built with Freenect2 support...");
|
|
|
|
|
exit(-1);
|
2015-04-02 16:33:35 -04:00
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraFreenect2(deviceId.empty()?0:uStr2Int(deviceId), rtabmap::CameraFreenect2::kTypeColor2DepthSD, rate);
|
2015-04-02 16:33:35 -04:00
|
|
|
}
|
2015-04-04 11:29:14 -04:00
|
|
|
else if(driver == 6)
|
|
|
|
|
{
|
2015-04-06 00:28:04 -04:00
|
|
|
if(!rtabmap::CameraStereoDC1394::available())
|
2015-04-04 11:29:14 -04:00
|
|
|
{
|
|
|
|
|
UERROR("Not built with DC1394 support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraStereoDC1394(rate);
|
2015-04-04 11:29:14 -04:00
|
|
|
}
|
2015-04-07 12:00:10 -04:00
|
|
|
else if(driver == 7)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraStereoFlyCapture2::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with FlyCapture2/Triclops support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraStereoFlyCapture2(rate);
|
2015-04-07 12:00:10 -04:00
|
|
|
}
|
2016-05-31 19:09:49 -04:00
|
|
|
else if(driver == 8)
|
|
|
|
|
{
|
|
|
|
|
if(!rtabmap::CameraStereoZed::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with ZED sdk support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2026-07-04 18:16:37 -07:00
|
|
|
camera = new rtabmap::CameraStereoZed(deviceId.empty()?0:uStr2Int(deviceId), -1, 1, 0, 100, false, rate);
|
2016-05-31 19:09:49 -04:00
|
|
|
}
|
2016-07-26 18:39:34 -04:00
|
|
|
else if (driver == 9)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraRealSense::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with RealSense support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraRealSense(deviceId.empty()?0:uStr2Int(deviceId), 0, 0, false, rate);
|
2016-07-26 18:39:34 -04:00
|
|
|
}
|
2017-11-06 00:19:12 -05:00
|
|
|
else if (driver == 10)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraK4W2::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with Kinect for Windows 2 SDK support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraK4W2(deviceId.empty()?0:uStr2Int(deviceId), rtabmap::CameraK4W2::kTypeDepth2ColorSD, rate);
|
2017-11-06 00:19:12 -05:00
|
|
|
}
|
2018-06-15 12:24:00 -04:00
|
|
|
else if (driver == 11)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraRealSense2::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with RealSense2 SDK support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraRealSense2(deviceId, width > 0 && height > 0 ? 0.0f:rate);
|
|
|
|
|
if(width > 0 && height > 0)
|
|
|
|
|
{
|
|
|
|
|
((rtabmap::CameraRealSense2*)camera)->setResolution(width, height, rate);
|
|
|
|
|
}
|
2019-07-09 20:48:09 -04:00
|
|
|
}
|
|
|
|
|
else if (driver == 12)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraK4A::available())
|
|
|
|
|
{
|
2020-04-30 00:57:47 -04:00
|
|
|
UERROR("Not built with Kinect for Azure SDK support...");
|
2019-07-09 20:48:09 -04:00
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraK4A(1, rate);
|
2018-06-15 12:24:00 -04:00
|
|
|
}
|
2020-04-30 00:57:47 -04:00
|
|
|
else if (driver == 13)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraMyntEye::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with Mynt Eye S support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraMyntEye(deviceId, false, false, rate);
|
2020-04-30 00:57:47 -04:00
|
|
|
}
|
2021-02-28 10:31:18 -05:00
|
|
|
else if (driver == 14)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraStereoZedOC::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with Zed Open Capture support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraStereoZedOC(deviceId.empty()?-1:uStr2Int(deviceId), 3, rate);
|
2021-02-28 10:31:18 -05:00
|
|
|
}
|
2021-03-07 12:27:21 -05:00
|
|
|
else if (driver == 15)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraDepthAI::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with depthai-core support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraDepthAI(deviceId, width>0?width:1280, rate);
|
2021-03-07 12:27:21 -05:00
|
|
|
}
|
2024-05-30 16:55:37 +08:00
|
|
|
else if (driver == 16)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraSeerSense::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with XVisio SDK support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
camera = new rtabmap::CameraSeerSense(false, rate);
|
2024-05-30 16:55:37 +08:00
|
|
|
}
|
2025-10-07 10:22:16 -07:00
|
|
|
else if (driver == 17)
|
|
|
|
|
{
|
|
|
|
|
if (!rtabmap::CameraOrbbecSDK::available())
|
|
|
|
|
{
|
|
|
|
|
UERROR("Not built with Orbbec SDK support...");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
if(width>0 && height>0)
|
|
|
|
|
camera = new rtabmap::CameraOrbbecSDK(deviceId, width, height, width, height, rate);
|
|
|
|
|
else
|
|
|
|
|
camera = new rtabmap::CameraOrbbecSDK(deviceId, 800, 600, 800, 600, rate);
|
2025-10-07 10:22:16 -07:00
|
|
|
}
|
2014-06-15 03:32:25 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UFATAL("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!camera->init())
|
|
|
|
|
{
|
2015-04-06 13:35:44 -04:00
|
|
|
printf("Camera init failed! Please select another driver (see \"--help\").\n");
|
2014-06-15 03:32:25 +00:00
|
|
|
delete camera;
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2015-07-16 11:52:09 -04:00
|
|
|
|
2026-07-01 18:11:28 -07:00
|
|
|
#ifdef __APPLE__
|
|
|
|
|
if(usePCLViz)
|
|
|
|
|
{
|
|
|
|
|
// pcl::visualization::CloudViewer creates its render window on its own
|
|
|
|
|
// background thread, but macOS only allows NSWindow creation on the main
|
|
|
|
|
// thread, so it aborts. Fall back to the default (Qt) viewer.
|
|
|
|
|
printf("-pcl is not supported on macOS (pcl::visualization::CloudViewer creates its "
|
|
|
|
|
"window on a background thread, which macOS forbids). Using the default viewer instead.\n");
|
|
|
|
|
usePCLViz = false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
if(usePCLViz)
|
2017-11-06 00:19:12 -05:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
rtabmap::SensorData data = camera->takeData();
|
|
|
|
|
if (data.imageRaw().empty())
|
|
|
|
|
{
|
|
|
|
|
printf("Cloud not get frame from the camera!\n");
|
|
|
|
|
delete camera;
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if(data.imageRaw().cols % data.depthOrRightRaw().cols != 0 || data.imageRaw().rows % data.depthOrRightRaw().rows != 0)
|
|
|
|
|
{
|
|
|
|
|
UWARN("RGB (%d/%d) and depth (%d/%d) frames are not the same size! The registered cloud cannot be shown.",
|
|
|
|
|
data.imageRaw().cols, data.imageRaw().rows, data.depthOrRightRaw().cols, data.depthOrRightRaw().rows);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pcl::visualization::CloudViewer * viewer = 0;
|
|
|
|
|
if((data.stereoCameraModels().empty() || data.stereoCameraModels()[0].isValidForProjection()) &&
|
|
|
|
|
(data.cameraModels().empty() || !data.cameraModels()[0].isValidForProjection()))
|
|
|
|
|
{
|
|
|
|
|
UWARN("Camera not calibrated! The registered cloud cannot be shown.");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
viewer = new pcl::visualization::CloudViewer("cloud");
|
|
|
|
|
}
|
2015-07-16 11:52:09 -04:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
// to catch the ctrl-c
|
|
|
|
|
signal(SIGABRT, &sighandler);
|
|
|
|
|
signal(SIGTERM, &sighandler);
|
|
|
|
|
signal(SIGINT, &sighandler);
|
2015-07-16 11:52:09 -04:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
while(!data.imageRaw().empty() && (viewer==0 || !viewer->wasStopped()) && running)
|
2015-04-02 16:33:35 -04:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
cv::Mat rgb = data.imageRaw();
|
|
|
|
|
if(!data.depthRaw().empty() && (data.depthRaw().type() == CV_16UC1 || data.depthRaw().type() == CV_32FC1))
|
2015-04-04 11:29:14 -04:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
// depth
|
|
|
|
|
cv::Mat depth = data.depthRaw();
|
|
|
|
|
if(depth.type() == CV_32FC1)
|
|
|
|
|
{
|
|
|
|
|
depth = rtabmap::util2d::cvtDepthFromFloat(depth);
|
|
|
|
|
}
|
2014-06-15 03:32:25 +00:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
if(!rgb.empty() && rgb.cols % depth.cols == 0 && rgb.rows % depth.rows == 0 &&
|
|
|
|
|
data.cameraModels().size() &&
|
|
|
|
|
data.cameraModels()[0].isValidForProjection())
|
|
|
|
|
{
|
|
|
|
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = rtabmap::util3d::cloudFromDepthRGB(
|
|
|
|
|
rgb, depth,
|
|
|
|
|
data.cameraModels()[0]);
|
|
|
|
|
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::Transform::opengl_T_rtabmap()*data.cameraModels()[0].localTransform());
|
|
|
|
|
if(viewer)
|
|
|
|
|
viewer->showCloud(cloud, "cloud");
|
|
|
|
|
}
|
|
|
|
|
else if(!depth.empty() &&
|
|
|
|
|
data.cameraModels().size() &&
|
|
|
|
|
data.cameraModels()[0].isValidForProjection())
|
|
|
|
|
{
|
|
|
|
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = rtabmap::util3d::cloudFromDepth(
|
|
|
|
|
depth,
|
|
|
|
|
data.cameraModels()[0]);
|
|
|
|
|
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::Transform::opengl_T_rtabmap()*data.cameraModels()[0].localTransform());
|
2015-07-16 11:52:09 -04:00
|
|
|
viewer->showCloud(cloud, "cloud");
|
2025-12-21 11:52:38 -08:00
|
|
|
}
|
2015-04-10 17:36:13 -04:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
cv::Mat tmp;
|
|
|
|
|
unsigned short min=0, max = 2048;
|
|
|
|
|
uMinMax((unsigned short*)depth.data, depth.rows*depth.cols, min, max);
|
|
|
|
|
depth.convertTo(tmp, CV_8UC1, 255.0/max);
|
2015-04-04 11:29:14 -04:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
cv::imshow("Video", rgb); // show frame
|
|
|
|
|
cv::imshow("Depth", tmp);
|
|
|
|
|
}
|
|
|
|
|
else if(!data.rightRaw().empty())
|
2015-04-04 11:29:14 -04:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
// stereo
|
|
|
|
|
cv::Mat right = data.rightRaw();
|
|
|
|
|
cv::imshow("Left", rgb); // show frame
|
|
|
|
|
cv::imshow("Right", right);
|
|
|
|
|
|
|
|
|
|
if(rgb.cols == right.cols && rgb.rows == right.rows && data.stereoCameraModels().size()==1 && data.stereoCameraModels()[0].isValidForProjection())
|
2015-04-04 11:29:14 -04:00
|
|
|
{
|
2025-12-21 11:52:38 -08:00
|
|
|
if(right.channels() == 3)
|
|
|
|
|
{
|
2026-07-29 22:48:39 -07:00
|
|
|
cv::cvtColor(right, right, cv::COLOR_BGR2GRAY);
|
2025-12-21 11:52:38 -08:00
|
|
|
}
|
|
|
|
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = rtabmap::util3d::cloudFromStereoImages(
|
|
|
|
|
rgb, right,
|
|
|
|
|
data.stereoCameraModels()[0]);
|
|
|
|
|
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::Transform::opengl_T_rtabmap()*data.stereoCameraModels()[0].localTransform());
|
|
|
|
|
if(viewer)
|
|
|
|
|
viewer->showCloud(cloud, "cloud");
|
2015-04-04 11:29:14 -04:00
|
|
|
}
|
|
|
|
|
}
|
2014-06-15 03:32:25 +00:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
int c = cv::waitKey(10); // wait 10 ms or for key stroke
|
|
|
|
|
if(c == 27)
|
|
|
|
|
break; // if ESC, break and quit
|
2014-06-15 03:32:25 +00:00
|
|
|
|
2025-12-21 11:52:38 -08:00
|
|
|
data = camera->takeData();
|
|
|
|
|
}
|
|
|
|
|
printf("Closing...\n");
|
|
|
|
|
if(viewer)
|
|
|
|
|
{
|
|
|
|
|
delete viewer;
|
|
|
|
|
}
|
|
|
|
|
if(usePCLViz)
|
|
|
|
|
{
|
|
|
|
|
cv::destroyWindow("Video");
|
|
|
|
|
cv::destroyWindow("Depth");
|
|
|
|
|
}
|
|
|
|
|
delete camera;
|
2014-06-15 03:32:25 +00:00
|
|
|
}
|
2025-12-21 11:52:38 -08:00
|
|
|
else // Use our own visualizer
|
2015-07-16 11:52:09 -04:00
|
|
|
{
|
2026-07-01 18:11:28 -07:00
|
|
|
#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION==9 && VTK_MINOR_VERSION >= 1)
|
|
|
|
|
// Needed to ensure the appropriate OpenGL context is created for VTK
|
|
|
|
|
// rendering (QVTKOpenGLNativeWidget). Without it the embedded VTK widget
|
|
|
|
|
// gets an incompatible context and VTK calls a null GL function pointer
|
|
|
|
|
// (crash in vtkOpenGLVertexArrayObject::Bind on first paint). Must be set
|
|
|
|
|
// before QApplication is constructed.
|
|
|
|
|
QSurfaceFormat::setDefaultFormat(QVTKRenderWidget::defaultFormat());
|
|
|
|
|
#endif
|
2025-12-21 11:52:38 -08:00
|
|
|
QApplication app(argc, argv);
|
|
|
|
|
|
|
|
|
|
rtabmap::CameraViewer cameraViewer;
|
|
|
|
|
UEventsManager::addHandler(&cameraViewer);
|
|
|
|
|
|
|
|
|
|
cameraViewer.setWindowTitle("Camera view");
|
|
|
|
|
cameraViewer.resize(1280, 480);
|
|
|
|
|
|
|
|
|
|
rtabmap::SensorCaptureThread cameraThread(camera);
|
|
|
|
|
|
|
|
|
|
cameraThread.start();
|
|
|
|
|
cameraViewer.exec();
|
|
|
|
|
cameraThread.join(true);
|
2015-07-16 11:52:09 -04:00
|
|
|
}
|
2026-07-04 18:16:37 -07:00
|
|
|
printf("Exiting cleanly.\n");
|
2014-06-15 03:32:25 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|