34 #include <tango_client_api.h> 35 #include <tango_support_api.h> 61 if(point_cloud->num_points>0)
63 app->
cloudReceived(cv::Mat(1, point_cloud->num_points, CV_32FC4, point_cloud->points[0]), point_cloud->timestamp);
72 if(color->format == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
74 tangoImage = cv::Mat(color->height, color->width, CV_8UC4, color->data);
76 else if(color->format == TANGO_HAL_PIXEL_FORMAT_YV12)
78 tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
80 else if(color->format == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
82 tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
84 else if(color->format == 35)
86 tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
90 LOGE(
"Not supported color format : %d.", color->format);
93 if(!tangoImage.empty())
95 app->
rgbReceived(tangoImage, (
unsigned int)color->format, color->timestamp);
101 if(pose->status_code == TANGO_POSE_VALID)
120 colorCamera_(colorCamera),
121 decimation_(decimation),
122 rawScanPublished_(publishRawScan),
140 double xu,
double yu,
double w,
double w_inverse,
double two_tan_w_div_two,
141 double* xd,
double* yd) {
142 double ru =
sqrt(xu * xu + yu * yu);
144 if (w < epsilon || ru < epsilon) {
148 double rd_div_ru =
std::atan(ru * two_tan_w_div_two) * w_inverse / ru;
149 *xd = xu * rd_div_ru;
150 *yd = yu * rd_div_ru;
162 cv::Mat & mapX, cv::Mat & mapY) {
163 const double & fx = fisheyeModel.
K().at<
double>(0,0);
164 const double & fy = fisheyeModel.
K().at<
double>(1,1);
165 const double & cx = fisheyeModel.
K().at<
double>(0,2);
166 const double & cy = fisheyeModel.
K().at<
double>(1,2);
167 const double & w = fisheyeModel.
D().at<
double>(0,0);
168 mapX.create(fisheyeModel.
imageSize(), CV_32FC1);
169 mapY.create(fisheyeModel.
imageSize(), CV_32FC1);
170 LOGD(
"initFisheyeRectificationMap: fx=%f fy=%f, cx=%f, cy=%f, w=%f", fx, fy, cx, cy, w);
172 const double fy_inverse = 1.0 / fy;
173 const double fx_inverse = 1.0 / fx;
174 const double w_inverse = 1 / w;
175 const double two_tan_w_div_two = 2.0 *
std::tan(w * 0.5);
179 for(
int iu = 0; iu < fisheyeModel.
imageHeight(); ++iu) {
180 for (
int ju = 0; ju < fisheyeModel.
imageWidth(); ++ju) {
181 double xu = (ju - cx) * fx_inverse;
182 double yu = (iu - cy) * fy_inverse;
184 applyFovModel(xu, yu, w, w_inverse, two_tan_w_div_two, &xd, &yd);
185 double jd = cx + xd * fx;
186 double id = cy + yd * fy;
187 mapX.at<
float>(iu, ju) = jd;
188 mapY.at<
float>(iu, ju) =
id;
197 TangoSupport_initialize(TangoService_getPoseAtTime, TangoService_getCameraIntrinsics);
200 LOGI(
"NativeRTABMap: Setup tango config");
201 tango_config_ = TangoService_getConfig(TANGO_CONFIG_DEFAULT);
204 LOGE(
"NativeRTABMap: Failed to get default config form");
209 bool is_atuo_recovery =
true;
210 int ret = TangoConfig_setBool(
tango_config_,
"config_enable_auto_recovery", is_atuo_recovery);
211 if (ret != TANGO_SUCCESS)
213 LOGE(
"NativeRTABMap: config_enable_auto_recovery() failed with error code: %d", ret);
220 ret = TangoConfig_setBool(
tango_config_,
"config_enable_color_camera",
true);
221 if (ret != TANGO_SUCCESS)
223 LOGE(
"NativeRTABMap: config_enable_color_camera() failed with error code: %d", ret);
229 ret = TangoConfig_setBool(
tango_config_,
"config_enable_depth",
true);
230 if (ret != TANGO_SUCCESS)
232 LOGE(
"NativeRTABMap: config_enable_depth() failed with error code: %d", ret);
237 ret = TangoConfig_setInt32(
tango_config_,
"config_depth_mode", TANGO_POINTCLOUD_XYZC);
238 if (ret != TANGO_SUCCESS)
240 LOGE(
"Failed to set 'depth_mode' configuration flag with error code: %d", ret);
248 ret = TangoConfig_setBool(
tango_config_,
"config_enable_low_latency_imu_integration",
true);
249 if (ret != TANGO_SUCCESS)
251 LOGE(
"NativeRTABMap: Failed to enable low latency imu integration.");
270 ret = TangoConfig_getString(
tango_config_,
"tango_service_library_version", tango_core_version, kVersionStringLength);
271 if (ret != TANGO_SUCCESS)
273 LOGE(
"NativeRTABMap: get tango core version failed with error code: %d", ret);
276 LOGI(
"NativeRTABMap: Tango version : %s", tango_core_version);
280 LOGI(
"NativeRTABMap: Setup callbacks");
284 if (ret != TANGO_SUCCESS)
286 LOGE(
"NativeRTABMap: Failed to connect to point cloud callback with error code: %d", ret);
291 if (ret != TANGO_SUCCESS)
293 LOGE(
"NativeRTABMap: Failed to connect to color callback with error code: %d", ret);
299 TangoCoordinateFramePair pair;
301 pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE;
302 pair.target = TANGO_COORDINATE_FRAME_DEVICE;
304 if (ret != TANGO_SUCCESS)
306 LOGE(
"NativeRTABMap: Failed to connect to pose callback with error code: %d", ret);
313 if (ret != TANGO_SUCCESS)
315 LOGE(
"PointCloudApp: Failed to connect to event callback with error code: %d", ret);
320 LOGI(
"NativeRTABMap: Connect to tango service");
322 if (ret != TANGO_SUCCESS)
324 LOGE(
"NativeRTABMap: Failed to connect to the Tango service with error code: %d", ret);
329 LOGI(
"NativeRTABMap: Update extrinsics");
330 TangoPoseData pose_data;
331 TangoCoordinateFramePair frame_pair;
338 frame_pair.base = TANGO_COORDINATE_FRAME_DEVICE;
339 frame_pair.target =
colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE;
340 ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data);
341 if (ret != TANGO_SUCCESS)
343 LOGE(
"NativeRTABMap: Failed to get transform between the color camera frame and device frames");
347 pose_data.translation[0],
348 pose_data.translation[1],
349 pose_data.translation[2],
350 pose_data.orientation[0],
351 pose_data.orientation[1],
352 pose_data.orientation[2],
353 pose_data.orientation[3]);
357 TangoCameraIntrinsics color_camera_intrinsics;
358 ret = TangoService_getCameraIntrinsics(
colorCamera_?TANGO_CAMERA_COLOR:TANGO_CAMERA_FISHEYE, &color_camera_intrinsics);
359 if (ret != TANGO_SUCCESS)
361 LOGE(
"NativeRTABMap: Failed to get the intrinsics for the color camera with error code: %d.", ret);
365 LOGD(
"Calibration: fx=%f fy=%f cx=%f cy=%f width=%d height=%d",
366 color_camera_intrinsics.fx,
367 color_camera_intrinsics.fy,
368 color_camera_intrinsics.cx,
369 color_camera_intrinsics.cy,
370 color_camera_intrinsics.width,
371 color_camera_intrinsics.height);
373 cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
374 K.at<
double>(0,0) = color_camera_intrinsics.fx;
375 K.at<
double>(1,1) = color_camera_intrinsics.fy;
376 K.at<
double>(0,2) = color_camera_intrinsics.cx;
377 K.at<
double>(1,2) = color_camera_intrinsics.cy;
378 cv::Mat D = cv::Mat::zeros(1, 5, CV_64FC1);
379 LOGD(
"Calibration type = %d", color_camera_intrinsics.calibration_type);
380 if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_5_PARAMETERS ||
381 color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_EQUIDISTANT)
383 D.at<
double>(0,0) = color_camera_intrinsics.distortion[0];
384 D.at<
double>(0,1) = color_camera_intrinsics.distortion[1];
385 D.at<
double>(0,2) = color_camera_intrinsics.distortion[2];
386 D.at<
double>(0,3) = color_camera_intrinsics.distortion[3];
387 D.at<
double>(0,4) = color_camera_intrinsics.distortion[4];
389 else if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_3_PARAMETERS)
391 D.at<
double>(0,0) = color_camera_intrinsics.distortion[0];
392 D.at<
double>(0,1) = color_camera_intrinsics.distortion[1];
393 D.at<
double>(0,2) = 0.;
394 D.at<
double>(0,3) = 0.;
395 D.at<
double>(0,4) = color_camera_intrinsics.distortion[2];
397 else if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_2_PARAMETERS)
399 D.at<
double>(0,0) = color_camera_intrinsics.distortion[0];
400 D.at<
double>(0,1) = color_camera_intrinsics.distortion[1];
401 D.at<
double>(0,2) = 0.;
402 D.at<
double>(0,3) = 0.;
403 D.at<
double>(0,4) = 0.;
406 cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
409 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));
411 cv::Size(color_camera_intrinsics.width, color_camera_intrinsics.height),
413 deviceTColorCamera_);
420 LOGI(
"deviceTColorCameraRtabmap =%s", deviceTColorCamera_.prettyPrint().c_str());
430 LOGI(
"TangoService_disconnect()");
431 TangoService_disconnect();
432 LOGI(
"TangoService_disconnect() done.");
446 UASSERT(cloud.type() == CV_32FC4);
464 if(dt >= 0.0 && dt < 0.5)
470 double cloudStamp = timestamp;
478 LOGD(
"tangoColorType=%d", tangoColorType);
479 if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
481 cv::cvtColor(tangoImage, rgb, cv::COLOR_RGBA2BGR);
483 else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YV12)
485 cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV2BGR_YV12);
487 else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
489 cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV2BGR_NV21);
491 else if(tangoColorType == 35)
493 cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV420sp2GRAY);
497 LOGE(
"Not supported color format : %d.", tangoColorType);
534 TangoPoseData pose_color_image_t1_T_depth_image_t0;
535 if (TangoSupport_calculateRelativePose(
536 rgbStamp,
colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE, cloudStamp,
537 TANGO_COORDINATE_FRAME_CAMERA_DEPTH,
538 &pose_color_image_t1_T_depth_image_t0) == TANGO_SUCCESS)
545 "SynchronizationApplication: Could not find a valid relative pose at " 546 "time for color and " 552 LOGE(
"Very large color to depth error detected (%s)! Ignoring this frame!", colorToDepth.
prettyPrint().c_str());
556 if(!colorToDepth.
isNull())
561 LOGD(
"rgb=%dx%d cloud size=%d", rgb.cols, rgb.rows, (
int)cloud.total());
571 closeROI[0] = depth.cols/4;
572 closeROI[1] = 3*(depth.cols/4);
573 closeROI[2] = depth.rows/4;
574 closeROI[3] = 3*(depth.rows/4);
575 unsigned short minDepthValue=10000;
576 for(
unsigned int i=0; i<cloud.total(); ++i)
578 const float * p = cloud.ptr<
float>(0,i);
583 scanData.at(oi++) = pt;
586 int pixel_x_l, pixel_y_l, pixel_x_h, pixel_y_h;
588 pixel_x_l =
static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx());
589 pixel_y_l =
static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy());
590 pixel_x_h =
static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx() + 0.5f);
591 pixel_y_h =
static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy() + 0.5f);
592 unsigned short depth_value(pt.z * 1000.0f);
594 if(pixel_x_l>=closeROI[0] && pixel_x_l<closeROI[1] &&
595 pixel_y_l>closeROI[2] && pixel_y_l<closeROI[3] &&
599 if(depth_value < minDepthValue)
601 minDepthValue = depth_value;
605 bool pixelSet =
false;
606 if(pixel_x_l>=0 && pixel_x_l<depth.cols &&
607 pixel_y_l>0 && pixel_y_l<depth.rows &&
610 unsigned short & depthPixel = depth.at<
unsigned short>(pixel_y_l, pixel_x_l);
611 if(depthPixel == 0 || depthPixel > depth_value)
613 depthPixel = depth_value;
617 if(pixel_x_h>=0 && pixel_x_h<depth.cols &&
618 pixel_y_h>0 && pixel_y_h<depth.rows &&
621 unsigned short & depthPixel = depth.at<
unsigned short>(pixel_y_h, pixel_x_h);
622 if(depthPixel == 0 || depthPixel > depth_value)
624 depthPixel = depth_value;
634 if(closePoints > 100)
641 scan = cv::Mat(1, oi, CV_32FC3, scanData.data()).clone();
647 LOGE(
"color to depth pose is null?!? (rgb stamp=%f) (depth stamp=%f)", rgbStamp, cloudStamp);
650 if(!rgb.empty() && !depth.empty())
691 LOGE(
"Could not get depth and rgb images!?!");
700 LOGD(
"process cloud received %fs", timer.
ticks());
708 if(!tangoImage.empty())
736 tangoPose->translation[0],
737 tangoPose->translation[1],
738 tangoPose->translation[2],
739 tangoPose->orientation[0],
740 tangoPose->orientation[1],
741 tangoPose->orientation[2],
742 tangoPose->orientation[3]);
751 TangoPoseData pose_start_service_T_device;
752 TangoCoordinateFramePair frame_pair;
753 frame_pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE;
754 frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE;
755 TangoErrorType status = TangoService_getPoseAtTime(timestamp, frame_pair, &pose_start_service_T_device);
756 if (status != TANGO_SUCCESS)
759 "PoseData: Failed to get transform between the Start of service and " 760 "device frames at timestamp %lf",
763 if (pose_start_service_T_device.status_code != TANGO_POSE_VALID)
766 "PoseData: Failed to get transform between the Start of service and " 767 "device frames at timestamp %lf",
785 glBindTexture(GL_TEXTURE_EXTERNAL_OES,
textureId_);
786 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
787 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
788 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
789 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
795 double video_overlay_timestamp;
796 TangoErrorType status = TangoService_updateTextureExternalOes(TANGO_CAMERA_COLOR,
textureId_, &video_overlay_timestamp);
798 if (status == TANGO_SUCCESS)
810 TangoDoubleMatrixTransformData matrix_transform;
811 status = TangoSupport_getDoubleMatrixTransformAtTime(
812 video_overlay_timestamp,
813 TANGO_COORDINATE_FRAME_CAMERA_COLOR,
814 TANGO_COORDINATE_FRAME_START_OF_SERVICE,
815 TANGO_SUPPORT_ENGINE_OPENGL,
816 TANGO_SUPPORT_ENGINE_OPENGL,
817 static_cast<TangoSupportRotation>(rotation),
819 if (matrix_transform.status_code == TANGO_POSE_VALID)
822 TangoCameraIntrinsics color_camera_intrinsics;
823 int ret = TangoSupport_getCameraIntrinsicsBasedOnDisplayRotation(
825 static_cast<TangoSupportRotation>(rotation),
826 &color_camera_intrinsics);
828 if (ret == TANGO_SUCCESS) {
829 float image_width =
static_cast<float>(color_camera_intrinsics.width);
830 float image_height =
static_cast<float>(color_camera_intrinsics.height);
831 float fx =
static_cast<float>(color_camera_intrinsics.fx);
832 float fy =
static_cast<float>(color_camera_intrinsics.fy);
833 float cx =
static_cast<float>(color_camera_intrinsics.cx);
834 float cy =
static_cast<float>(color_camera_intrinsics.cy);
843 image_width, image_height, fx, fy, cx, cy, 0.3, 50);
864 UERROR(
"TangoSupport_getCameraIntrinsicsBasedOnDisplayRotation failed!");
869 UERROR(
"TangoSupport_getDoubleMatrixTransformAtTime failed!");
874 UERROR(
"TangoService_updateTextureExternalOes failed!");
virtual SensorData captureImage(CameraInfo *info=0)
void setLocalTransform(const Transform &transform)
glm::mat4 glmFromTransform(const rtabmap::Transform &transform)
cv::Mat fisheyeRectifyMapY_
const cv::Size & imageSize() const
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)
void cloudReceived(const cv::Mat &cloud, double timestamp)
0 degree rotation (natural orientation)
const Transform & getOriginOffset() const
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
CameraModel scaled(double scale) const
void onTangoEventAvailableRouter(void *context, const TangoEvent *event)
const float kTextureCoords0[]
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
const float maxDepthError
float transformed_uvs_[8]
GLM_FUNC_DECL genType e()
static const rtabmap::Transform rtabmap_world_T_opengl_world(0.0f, 0.0f,-1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f)
static glm::mat4 ProjectionMatrixForCameraIntrinsics(float width, float height, float fx, float fy, float cx, float cy, float near, float far)
void poseReceived(const Transform &pose)
void post(UEvent *event, bool async=true) const
const float kTextureCoords270[]
cv::Mat fisheyeRectifyMapX_
const int scanDownsampling
GLM_FUNC_DECL bool isNull(detail::tmat2x2< T, P > const &m, T const &epsilon)
#define UASSERT(condition)
static const rtabmap::Transform tango_device_T_rtabmap_world(0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f)
Transform deviceTColorCamera_
const int kVersionStringLength
cv::Mat RTABMAP_EXP decimate(const cv::Mat &image, int d)
GLM_FUNC_DECL genType atan(genType const &y, genType const &x)
static const rtabmap::Transform opengl_world_T_rtabmap_world(0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f)
const Transform & localTransform() const
const float kTextureCoords90[]
ScreenRotation getScreenRotation() const
CameraTango(bool colorCamera, int decimation, bool publishRawScan, bool smoothing)
const float kTextureCoords180[]
void tangoEventReceived(int type, const char *key, const char *value)
GLM_FUNC_DECL detail::tquat< T, P > rotation(detail::tvec3< T, P > const &orig, detail::tvec3< T, P > const &dest)
const Transform & groundTruth() const
GLM_FUNC_DECL genType tan(genType const &angle)
void onPoseAvailableRouter(void *context, const TangoPoseData *pose)
GLM_FUNC_DECL detail::tmat4x4< T, defaultp > make_mat4(T const *const ptr)
virtual std::string getSerial() const
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)
void setOcclusionImage(const cv::Mat &image, const CameraModel &model)
void setGroundTruth(const Transform &pose)
void initFisheyeRectificationMap(const CameraModel &fisheyeModel, cv::Mat &mapX, cv::Mat &mapY)
void rgbReceived(const cv::Mat &tangoImage, int type, double timestamp)
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())
rtabmap::Transform tangoPoseToTransform(const TangoPoseData *tangoPose) const
void applyFovModel(double xu, double yu, double w, double w_inverse, double two_tan_w_div_two, double *xd, double *yd)
glm::mat4 projectionMatrix_
rtabmap::Transform getPoseAtTimestamp(double timestamp)
GLM_FUNC_DECL matType< T, P > inverse(matType< T, P > const &m)