34 #include <tango_client_api.h> 35 #include <tango_support_api.h> 49 if(app->
isRunning() && point_cloud->num_points>0)
51 app->
cloudReceived(cv::Mat(1, point_cloud->num_points, CV_32FC4, point_cloud->points[0]), point_cloud->timestamp);
61 if(color->format == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
63 tangoImage = cv::Mat(color->height, color->width, CV_8UC4, color->data);
65 else if(color->format == TANGO_HAL_PIXEL_FORMAT_YV12)
67 tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
69 else if(color->format == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
71 tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
73 else if(color->format == 35)
75 tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
79 LOGE(
"Not supported color format : %d.", color->format);
82 if(!tangoImage.empty())
84 app->
rgbReceived(tangoImage, (
unsigned int)color->format, color->timestamp);
91 if(pose->status_code == TANGO_POSE_VALID)
114 stampEpochOffset_(0.0),
115 colorCamera_(colorCamera),
116 decimation_(decimation),
117 rawScanPublished_(publishRawScan),
118 smoothing_(smoothing),
122 colorCameraToDisplayRotation_(ROTATION_0),
139 double xu,
double yu,
double w,
double w_inverse,
double two_tan_w_div_two,
140 double* xd,
double* yd) {
141 double ru =
sqrt(xu * xu + yu * yu);
143 if (w < epsilon || ru < epsilon) {
147 double rd_div_ru =
std::atan(ru * two_tan_w_div_two) * w_inverse / ru;
148 *xd = xu * rd_div_ru;
149 *yd = yu * rd_div_ru;
161 cv::Mat & mapX, cv::Mat & mapY) {
162 const double & fx = fisheyeModel.
K().at<
double>(0,0);
163 const double & fy = fisheyeModel.
K().at<
double>(1,1);
164 const double & cx = fisheyeModel.
K().at<
double>(0,2);
165 const double & cy = fisheyeModel.
K().at<
double>(1,2);
166 const double & w = fisheyeModel.
D().at<
double>(0,0);
167 mapX.create(fisheyeModel.
imageSize(), CV_32FC1);
168 mapY.create(fisheyeModel.
imageSize(), CV_32FC1);
169 LOGD(
"initFisheyeRectificationMap: fx=%f fy=%f, cx=%f, cy=%f, w=%f", fx, fy, cx, cy, w);
171 const double fy_inverse = 1.0 / fy;
172 const double fx_inverse = 1.0 / fx;
173 const double w_inverse = 1 / w;
174 const double two_tan_w_div_two = 2.0 *
std::tan(w * 0.5);
178 for(
int iu = 0; iu < fisheyeModel.
imageHeight(); ++iu) {
179 for (
int ju = 0; ju < fisheyeModel.
imageWidth(); ++ju) {
180 double xu = (ju - cx) * fx_inverse;
181 double yu = (iu - cy) * fy_inverse;
183 applyFovModel(xu, yu, w, w_inverse, two_tan_w_div_two, &xd, &yd);
184 double jd = cx + xd * fx;
185 double id = cy + yd * fy;
186 mapX.at<
float>(iu, ju) = jd;
187 mapY.at<
float>(iu, ju) =
id;
196 TangoSupport_initialize(TangoService_getPoseAtTime, TangoService_getCameraIntrinsics);
199 LOGI(
"NativeRTABMap: Setup tango config");
200 tango_config_ = TangoService_getConfig(TANGO_CONFIG_DEFAULT);
203 LOGE(
"NativeRTABMap: Failed to get default config form");
208 bool is_atuo_recovery =
true;
209 int ret = TangoConfig_setBool(
tango_config_,
"config_enable_auto_recovery", is_atuo_recovery);
210 if (ret != TANGO_SUCCESS)
212 LOGE(
"NativeRTABMap: config_enable_auto_recovery() failed with error code: %d", ret);
219 ret = TangoConfig_setBool(
tango_config_,
"config_enable_color_camera",
true);
220 if (ret != TANGO_SUCCESS)
222 LOGE(
"NativeRTABMap: config_enable_color_camera() failed with error code: %d", ret);
228 ret = TangoConfig_setBool(
tango_config_,
"config_enable_depth",
true);
229 if (ret != TANGO_SUCCESS)
231 LOGE(
"NativeRTABMap: config_enable_depth() failed with error code: %d", ret);
236 ret = TangoConfig_setInt32(
tango_config_,
"config_depth_mode", TANGO_POINTCLOUD_XYZC);
237 if (ret != TANGO_SUCCESS)
239 LOGE(
"Failed to set 'depth_mode' configuration flag with error code: %d", ret);
247 ret = TangoConfig_setBool(
tango_config_,
"config_enable_low_latency_imu_integration",
true);
248 if (ret != TANGO_SUCCESS)
250 LOGE(
"NativeRTABMap: Failed to enable low latency imu integration.");
269 ret = TangoConfig_getString(
tango_config_,
"tango_service_library_version", tango_core_version, kVersionStringLength);
270 if (ret != TANGO_SUCCESS)
272 LOGE(
"NativeRTABMap: get tango core version failed with error code: %d", ret);
275 LOGI(
"NativeRTABMap: Tango version : %s", tango_core_version);
279 LOGI(
"NativeRTABMap: Setup callbacks");
283 if (ret != TANGO_SUCCESS)
285 LOGE(
"NativeRTABMap: Failed to connect to point cloud callback with error code: %d", ret);
290 if (ret != TANGO_SUCCESS)
292 LOGE(
"NativeRTABMap: Failed to connect to color callback with error code: %d", ret);
298 TangoCoordinateFramePair pair;
300 pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE;
301 pair.target = TANGO_COORDINATE_FRAME_DEVICE;
303 if (ret != TANGO_SUCCESS)
305 LOGE(
"NativeRTABMap: Failed to connect to pose callback with error code: %d", ret);
312 if (ret != TANGO_SUCCESS)
314 LOGE(
"PointCloudApp: Failed to connect to event callback with error code: %d", ret);
319 LOGI(
"NativeRTABMap: Connect to tango service");
321 if (ret != TANGO_SUCCESS)
323 LOGE(
"NativeRTABMap: Failed to connect to the Tango service with error code: %d", ret);
328 LOGI(
"NativeRTABMap: Update extrinsics");
329 TangoPoseData pose_data;
330 TangoCoordinateFramePair frame_pair;
337 frame_pair.base = TANGO_COORDINATE_FRAME_DEVICE;
338 frame_pair.target =
colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE;
339 ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data);
340 if (ret != TANGO_SUCCESS)
342 LOGE(
"NativeRTABMap: Failed to get transform between the color camera frame and device frames");
346 pose_data.translation[0],
347 pose_data.translation[1],
348 pose_data.translation[2],
349 pose_data.orientation[0],
350 pose_data.orientation[1],
351 pose_data.orientation[2],
352 pose_data.orientation[3]);
355 TangoCameraIntrinsics color_camera_intrinsics;
356 ret = TangoService_getCameraIntrinsics(
colorCamera_?TANGO_CAMERA_COLOR:TANGO_CAMERA_FISHEYE, &color_camera_intrinsics);
357 if (ret != TANGO_SUCCESS)
359 LOGE(
"NativeRTABMap: Failed to get the intrinsics for the color camera with error code: %d.", ret);
363 LOGD(
"Calibration: fx=%f fy=%f cx=%f cy=%f width=%d height=%d",
364 color_camera_intrinsics.fx,
365 color_camera_intrinsics.fy,
366 color_camera_intrinsics.cx,
367 color_camera_intrinsics.cy,
368 color_camera_intrinsics.width,
369 color_camera_intrinsics.height);
371 cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
372 K.at<
double>(0,0) = color_camera_intrinsics.fx;
373 K.at<
double>(1,1) = color_camera_intrinsics.fy;
374 K.at<
double>(0,2) = color_camera_intrinsics.cx;
375 K.at<
double>(1,2) = color_camera_intrinsics.cy;
376 cv::Mat D = cv::Mat::zeros(1, 5, CV_64FC1);
377 LOGD(
"Calibration type = %d", color_camera_intrinsics.calibration_type);
378 if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_5_PARAMETERS ||
379 color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_EQUIDISTANT)
381 D.at<
double>(0,0) = color_camera_intrinsics.distortion[0];
382 D.at<
double>(0,1) = color_camera_intrinsics.distortion[1];
383 D.at<
double>(0,2) = color_camera_intrinsics.distortion[2];
384 D.at<
double>(0,3) = color_camera_intrinsics.distortion[3];
385 D.at<
double>(0,4) = color_camera_intrinsics.distortion[4];
387 else if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_3_PARAMETERS)
389 D.at<
double>(0,0) = color_camera_intrinsics.distortion[0];
390 D.at<
double>(0,1) = color_camera_intrinsics.distortion[1];
391 D.at<
double>(0,2) = 0.;
392 D.at<
double>(0,3) = 0.;
393 D.at<
double>(0,4) = color_camera_intrinsics.distortion[2];
395 else if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_2_PARAMETERS)
397 D.at<
double>(0,0) = color_camera_intrinsics.distortion[0];
398 D.at<
double>(0,1) = color_camera_intrinsics.distortion[1];
399 D.at<
double>(0,2) = 0.;
400 D.at<
double>(0,3) = 0.;
401 D.at<
double>(0,4) = 0.;
404 cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
407 LOGD(
"Distortion params: %f, %f, %f, %f, %f", D.at<
double>(0,0), D.at<
double>(0,1), D.at<
double>(0,2), D.at<
double>(0,3), D.at<
double>(0,4));
409 cv::Size(color_camera_intrinsics.width, color_camera_intrinsics.height),
432 LOGI(
"TangoService_disconnect()");
433 TangoService_disconnect();
434 LOGI(
"TangoService_disconnect() done.");
456 UASSERT(cloud.type() == CV_32FC4);
473 if(dt >= 0.0 && dt < 0.5)
475 bool notify =
cloud_.empty();
490 if(this->
isRunning() && !tangoImage.empty())
503 1.0
f, 0.0
f, 0.0
f, 0.0
f,
504 0.0
f, -1.0
f, 0.0
f, 0.0
f,
505 0.0
f, 0.0
f, -1.0
f, 0.0
f);
554 tangoPose->translation[0],
555 tangoPose->translation[1],
556 tangoPose->translation[2],
557 tangoPose->orientation[0],
558 tangoPose->orientation[1],
559 tangoPose->orientation[2],
560 tangoPose->orientation[3]);
569 TangoPoseData pose_start_service_T_device;
570 TangoCoordinateFramePair frame_pair;
571 frame_pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE;
572 frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE;
573 TangoErrorType status = TangoService_getPoseAtTime(timestamp, frame_pair, &pose_start_service_T_device);
574 if (status != TANGO_SUCCESS)
577 "PoseData: Failed to get transform between the Start of service and " 578 "device frames at timestamp %lf",
581 if (pose_start_service_T_device.status_code != TANGO_POSE_VALID)
584 "PoseData: Failed to get transform between the Start of service and " 585 "device frames at timestamp %lf",
606 LOGE(
"Not received any frames since 2 seconds, try to restart the camera again.");
612 UERROR(
"cloud and image were set!?");
626 double cloudStamp = 0.0;
627 double rgbStamp = 0.0;
628 int tangoColorType = 0;
644 LOGD(
"tangoColorType=%d", tangoColorType);
645 if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
647 cv::cvtColor(tangoImage, rgb, CV_RGBA2BGR);
649 else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YV12)
651 cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_YV12);
653 else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
655 cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_NV21);
657 else if(tangoColorType == 35)
659 cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV420sp2GRAY);
663 LOGE(
"Not supported color format : %d.", tangoColorType);
699 TangoPoseData pose_color_image_t1_T_depth_image_t0;
700 if (TangoSupport_calculateRelativePose(
701 rgbStamp,
colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE, cloudStamp,
702 TANGO_COORDINATE_FRAME_CAMERA_DEPTH,
703 &pose_color_image_t1_T_depth_image_t0) == TANGO_SUCCESS)
710 "SynchronizationApplication: Could not find a valid relative pose at " 711 "time for color and " 717 LOGE(
"Very large color to depth error detected (%s)! Ignoring this frame!", colorToDepth.
prettyPrint().c_str());
721 if(!colorToDepth.
isNull())
726 LOGD(
"rgb=%dx%d cloud size=%d", rgb.cols, rgb.rows, (
int)cloud.total());
736 closeROI[0] = depth.cols/4;
737 closeROI[1] = 3*(depth.cols/4);
738 closeROI[2] = depth.rows/4;
739 closeROI[3] = 3*(depth.rows/4);
740 unsigned short minDepthValue=10000;
741 for(
unsigned int i=0; i<cloud.total(); ++i)
743 float * p = cloud.ptr<
float>(0,i);
748 scanData.at(oi++) = pt;
751 int pixel_x_l, pixel_y_l, pixel_x_h, pixel_y_h;
753 pixel_x_l =
static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx());
754 pixel_y_l =
static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy());
755 pixel_x_h =
static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx() + 0.5f);
756 pixel_y_h =
static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy() + 0.5f);
757 unsigned short depth_value(pt.z * 1000.0f);
759 if(pixel_x_l>=closeROI[0] && pixel_x_l<closeROI[1] &&
760 pixel_y_l>closeROI[2] && pixel_y_l<closeROI[3] &&
764 if(depth_value < minDepthValue)
766 minDepthValue = depth_value;
770 bool pixelSet =
false;
771 if(pixel_x_l>=0 && pixel_x_l<depth.cols &&
772 pixel_y_l>0 && pixel_y_l<depth.rows &&
775 unsigned short & depthPixel = depth.at<
unsigned short>(pixel_y_l, pixel_x_l);
776 if(depthPixel == 0 || depthPixel > depth_value)
778 depthPixel = depth_value;
782 if(pixel_x_h>=0 && pixel_x_h<depth.cols &&
783 pixel_y_h>0 && pixel_y_h<depth.rows &&
786 unsigned short & depthPixel = depth.at<
unsigned short>(pixel_y_h, pixel_x_h);
787 if(depthPixel == 0 || depthPixel > depth_value)
789 depthPixel = depth_value;
799 if(closePoints > 100)
806 scan = cv::Mat(1, oi, CV_32FC3, scanData.data()).clone();
812 LOGE(
"color to depth pose is null?!? (rgb stamp=%f) (depth stamp=%f)", rgbStamp, cloudStamp);
815 if(!rgb.empty() && !depth.empty())
842 cv::Mat rgbt(rgb.cols, rgb.rows, rgb.type());
844 cv::transpose(rgb,rgbt);
846 cv::Mat deptht(depth.cols, depth.rows, depth.type());
847 cv::flip(depth,depth,1);
848 cv::transpose(depth,deptht);
851 model =
CameraModel(model.fy(), model.fx(), model.cy(), model.cx()>0?model.imageWidth()-model.cx():0, model.localTransform()*
rtabmap::Transform(0,0,0,0,0,1.57079632679489661923132169163975144));
858 cv::flip(depth,depth,1);
859 cv::flip(depth,depth,0);
864 model.cx()>0?model.imageWidth()-model.cx():0,
865 model.cy()>0?model.imageHeight()-model.cy():0,
866 model.localTransform()*
rtabmap::Transform(0,0,0,0,0,1.57079632679489661923132169163975144*2.0));
871 cv::Mat rgbt(rgb.cols, rgb.rows, rgb.type());
872 cv::transpose(rgb,rgbt);
873 cv::flip(rgbt,rgbt,1);
875 cv::Mat deptht(depth.cols, depth.rows, depth.type());
876 cv::transpose(depth,deptht);
877 cv::flip(deptht,deptht,1);
880 model =
CameraModel(model.fy(), model.fx(), model.cy()>0?model.imageHeight()-model.cy():0, model.cx(), model.localTransform()*
rtabmap::Transform(0,0,0,0,0,-1.57079632679489661923132169163975144));
913 LOGE(
"Could not get depth and rgb images!?!");
953 info.
reg.
covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.0001);
954 LOGI(
"Publish odometry message (variance=%f)", firstFrame?9999:0.0001);
961 LOGW(
"Odometry lost");
967 UERROR(
"Camera not initialized, cannot start thread.");
virtual SensorData captureImage(CameraInfo *info=0)
cv::Mat fisheyeRectifyMapY_
void cloudReceived(const cv::Mat &cloud, double timestamp)
void setImageSize(const cv::Size &size)
const cv::Size & imageSize() const
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
void onTangoEventAvailableRouter(void *context, const TangoEvent *event)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
TangoSupportRotation colorCameraToDisplayRotation_
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
const float maxDepthError
static const rtabmap::Transform rtabmap_world_T_tango_world(0.0f, 1.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f)
GLM_FUNC_DECL genType e()
cv::Mat RTABMAP_EXP fastBilateralFiltering(const cv::Mat &depth, float sigmaS=15.0f, float sigmaR=0.05f, bool earlyDivision=false)
static const float bilateralFilteringSigmaR
void setGPS(const GPS &gps)
virtual bool isCalibrated() const
bool acquire(int n=1, int ms=0)
const Transform & groundTruth() const
cv::Mat fisheyeRectifyMapX_
static rtabmap::Transform opticalRotation(1.0f, 0.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f)
void setGPS(const GPS &gps)
const int scanDownsampling
void post(UEvent *event, bool async=true) const
#define UASSERT(condition)
void poseReceived(const Transform &pose)
const int kVersionStringLength
virtual std::string getSerial() const
cv::Mat RTABMAP_EXP decimate(const cv::Mat &image, int d)
GLM_FUNC_DECL genType atan(genType const &y, genType const &x)
UTimer cameraStartedTime_
CameraTango(bool colorCamera, int decimation, bool publishRawScan, bool smoothing)
void tangoEventReceived(int type, const char *key, const char *value)
void uSleep(unsigned int ms)
bool isValidForProjection() const
GLM_FUNC_DECL genType tan(genType const &angle)
virtual void mainLoopBegin()
void onPoseAvailableRouter(void *context, const TangoPoseData *pose)
static const float bilateralFilteringSigmaS
cv::Mat RTABMAP_EXP fillDepthHoles(const cv::Mat &depth, int maximumHoleSize=1, float errorRatio=0.02f)
ULogger class and convenient macros.
void onFrameAvailableRouter(void *context, TangoCameraId id, const TangoImageBuffer *color)
Transform deviceTColorCamera_
void setStamp(double stamp)
void setGroundTruth(const Transform &pose)
static const rtabmap::Transform tango_device_T_rtabmap_device(0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,-1.0f, 0.0f, 0.0f, 0.0f)
void initFisheyeRectificationMap(const CameraModel &fisheyeModel, cv::Mat &mapX, cv::Mat &mapY)
void rgbReceived(const cv::Mat &tangoImage, int type, double timestamp)
void setDepthOrRightRaw(const cv::Mat &depthOrImageRaw)
void onPointCloudAvailableRouter(void *context, const TangoPointCloud *point_cloud)
static LaserScan backwardCompatibility(const cv::Mat &oldScanFormat, int maxPoints=0, int maxRange=0, const Transform &localTransform=Transform::getIdentity())
void applyFovModel(double xu, double yu, double w, double w_inverse, double two_tan_w_div_two, double *xd, double *yd)
CameraModel scaled(double scale) const
const Transform & localTransform() const
rtabmap::Transform getPoseAtTimestamp(double timestamp)
rtabmap::Transform tangoPoseToTransform(const TangoPoseData *tangoPose) const
const double & stamp() const