32 #include <opencv2/imgproc/types_c.h> 36 #include <k4arecord/playback.h> 55 Camera(imageRate, localTransform)
59 config_(K4A_DEVICE_CONFIG_INIT_DISABLE_ALL),
60 transformationHandle_(
NULL),
62 playbackHandle_(
NULL),
75 const std::string & fileName,
78 Camera(imageRate, localTransform)
82 transformationHandle_(
NULL),
84 playbackHandle_(
NULL),
105 if (playbackHandle_ !=
NULL)
107 k4a_playback_close((k4a_playback_t)playbackHandle_);
108 playbackHandle_ =
NULL;
110 else if (deviceHandle_ !=
NULL)
112 k4a_device_stop_imu(deviceHandle_);
114 k4a_device_stop_cameras(deviceHandle_);
115 k4a_device_close(deviceHandle_);
116 deviceHandle_ =
NULL;
117 config_ = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
120 if (transformationHandle_ !=
NULL)
122 k4a_transformation_destroy((k4a_transformation_t)transformationHandle_);
123 transformationHandle_ =
NULL;
125 previousStamp_ = 0.0;
126 timestampOffset_ = 0.0;
133 rgb_resolution_ = rgb_resolution;
134 framerate_ = framerate;
135 depth_resolution_ = depth_resolution;
136 UINFO(
"setPreferences(): %i %i %i", rgb_resolution, framerate, depth_resolution);
147 bool CameraK4A::init(
const std::string & calibrationFolder,
const std::string & cameraName)
151 if (!fileName_.empty())
155 if (k4a_playback_open(fileName_.c_str(), (k4a_playback_t*)&playbackHandle_) != K4A_RESULT_SUCCEEDED)
157 UERROR(
"Failed to open recording \"%s\"", fileName_.c_str());
161 uint64_t recording_length = k4a_playback_get_last_timestamp_usec((k4a_playback_t)playbackHandle_);
162 UINFO(
"Recording is %lld seconds long", recording_length / 1000000);
164 if (k4a_playback_get_calibration((k4a_playback_t)playbackHandle_, &calibration_))
166 UERROR(
"Failed to get calibration");
172 else if (deviceId_ >= 0)
174 if(deviceHandle_!=
NULL)
179 switch(rgb_resolution_)
181 case 0: config_.color_resolution = K4A_COLOR_RESOLUTION_720P;
break;
182 case 1: config_.color_resolution = K4A_COLOR_RESOLUTION_1080P;
break;
183 case 2: config_.color_resolution = K4A_COLOR_RESOLUTION_1440P;
break;
184 case 3: config_.color_resolution = K4A_COLOR_RESOLUTION_1536P;
break;
185 case 4: config_.color_resolution = K4A_COLOR_RESOLUTION_2160P;
break;
187 default: config_.color_resolution = K4A_COLOR_RESOLUTION_3072P;
break;
192 case 0: config_.camera_fps = K4A_FRAMES_PER_SECOND_5;
break;
193 case 1: config_.camera_fps = K4A_FRAMES_PER_SECOND_15;
break;
195 default: config_.camera_fps = K4A_FRAMES_PER_SECOND_30;
break;
198 switch(depth_resolution_)
200 case 0: config_.depth_mode = K4A_DEPTH_MODE_NFOV_2X2BINNED;
break;
201 case 1: config_.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED;
break;
202 case 2: config_.depth_mode = K4A_DEPTH_MODE_WFOV_2X2BINNED;
break;
204 default: config_.depth_mode = K4A_DEPTH_MODE_WFOV_UNBINNED;
break;
208 config_.color_format = K4A_IMAGE_FORMAT_COLOR_BGRA32;
210 int device_count = k4a_device_get_installed_count();
212 if (device_count == 0)
214 UERROR(
"No k4a devices attached!");
217 else if(deviceId_ > device_count)
219 UERROR(
"Cannot select device %d, only %d devices detected.", deviceId_, device_count);
222 UINFO(
"CameraK4A found %d k4a device(s) attached", device_count);
225 if (K4A_FAILED(k4a_device_open(deviceId_, &deviceHandle_)))
227 UERROR(
"Failed to open k4a device!");
232 size_t serial_size = 0;
233 k4a_device_get_serialnum(deviceHandle_,
NULL, &serial_size);
236 char *serial = (
char*)(malloc(serial_size));
237 k4a_device_get_serialnum(deviceHandle_, serial, &serial_size);
238 serial_number_.assign(serial, serial_size);
241 UINFO(
"Opened K4A device: %s", serial_number_.c_str());
244 if (K4A_FAILED(k4a_device_start_cameras(deviceHandle_, &config_)))
246 UERROR(
"Failed to start cameras!");
251 UINFO(
"K4A camera started successfully");
253 if (K4A_FAILED(k4a_device_get_calibration(deviceHandle_, config_.depth_mode, config_.color_resolution, &calibration_)))
255 UERROR(
"k4a_device_get_calibration() failed!");
262 UERROR(
"k4a_device_get_calibration() no file and no valid device id!");
268 cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
269 K.at<
double>(0,0) = calibration_.depth_camera_calibration.intrinsics.parameters.param.fx;
270 K.at<
double>(1,1) = calibration_.depth_camera_calibration.intrinsics.parameters.param.fy;
271 K.at<
double>(0,2) = calibration_.depth_camera_calibration.intrinsics.parameters.param.cx;
272 K.at<
double>(1,2) = calibration_.depth_camera_calibration.intrinsics.parameters.param.cy;
273 cv::Mat D = cv::Mat::eye(1, 8, CV_64FC1);
274 D.at<
double>(0,0) = calibration_.depth_camera_calibration.intrinsics.parameters.param.k1;
275 D.at<
double>(0,1) = calibration_.depth_camera_calibration.intrinsics.parameters.param.k2;
276 D.at<
double>(0,2) = calibration_.depth_camera_calibration.intrinsics.parameters.param.p1;
277 D.at<
double>(0,3) = calibration_.depth_camera_calibration.intrinsics.parameters.param.p2;
278 D.at<
double>(0,4) = calibration_.depth_camera_calibration.intrinsics.parameters.param.k3;
279 D.at<
double>(0,5) = calibration_.depth_camera_calibration.intrinsics.parameters.param.k4;
280 D.at<
double>(0,6) = calibration_.depth_camera_calibration.intrinsics.parameters.param.k5;
281 D.at<
double>(0,7) = calibration_.depth_camera_calibration.intrinsics.parameters.param.k6;
282 cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
283 cv::Mat
P = cv::Mat::eye(3, 4, CV_64FC1);
284 P.at<
double>(0,0) = K.at<
double>(0,0);
285 P.at<
double>(1,1) = K.at<
double>(1,1);
286 P.at<
double>(0,2) = K.at<
double>(0,2);
287 P.at<
double>(1,2) = K.at<
double>(1,2);
290 cv::Size(calibration_.depth_camera_calibration.resolution_width, calibration_.depth_camera_calibration.resolution_height),
292 this->getLocalTransform());
296 cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
297 K.at<
double>(0,0) = calibration_.color_camera_calibration.intrinsics.parameters.param.fx;
298 K.at<
double>(1,1) = calibration_.color_camera_calibration.intrinsics.parameters.param.fy;
299 K.at<
double>(0,2) = calibration_.color_camera_calibration.intrinsics.parameters.param.cx;
300 K.at<
double>(1,2) = calibration_.color_camera_calibration.intrinsics.parameters.param.cy;
301 cv::Mat D = cv::Mat::eye(1, 8, CV_64FC1);
302 D.at<
double>(0,0) = calibration_.color_camera_calibration.intrinsics.parameters.param.k1;
303 D.at<
double>(0,1) = calibration_.color_camera_calibration.intrinsics.parameters.param.k2;
304 D.at<
double>(0,2) = calibration_.color_camera_calibration.intrinsics.parameters.param.p1;
305 D.at<
double>(0,3) = calibration_.color_camera_calibration.intrinsics.parameters.param.p2;
306 D.at<
double>(0,4) = calibration_.color_camera_calibration.intrinsics.parameters.param.k3;
307 D.at<
double>(0,5) = calibration_.color_camera_calibration.intrinsics.parameters.param.k4;
308 D.at<
double>(0,6) = calibration_.color_camera_calibration.intrinsics.parameters.param.k5;
309 D.at<
double>(0,7) = calibration_.color_camera_calibration.intrinsics.parameters.param.k6;
310 cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
311 cv::Mat
P = cv::Mat::eye(3, 4, CV_64FC1);
312 P.at<
double>(0,0) = K.at<
double>(0,0);
313 P.at<
double>(1,1) = K.at<
double>(1,1);
314 P.at<
double>(0,2) = K.at<
double>(0,2);
315 P.at<
double>(1,2) = K.at<
double>(1,2);
318 cv::Size(calibration_.color_camera_calibration.resolution_width, calibration_.color_camera_calibration.resolution_height),
320 this->getLocalTransform());
322 UASSERT(model_.isValidForRectification());
323 model_.initRectificationMap();
327 UINFO(
"K4A calibration:");
328 std::cout << model_ << std::endl;
331 transformationHandle_ = k4a_transformation_create(&calibration_);
334 k4a_calibration_extrinsics_t* imu_extrinsics;
337 imu_extrinsics = &calibration_.extrinsics[K4A_CALIBRATION_TYPE_ACCEL][K4A_CALIBRATION_TYPE_DEPTH];
341 imu_extrinsics = &calibration_.extrinsics[K4A_CALIBRATION_TYPE_ACCEL][K4A_CALIBRATION_TYPE_COLOR];
344 imu_extrinsics->rotation[0], imu_extrinsics->rotation[1], imu_extrinsics->rotation[2], imu_extrinsics->translation[0] / 1000.0f,
345 imu_extrinsics->rotation[3], imu_extrinsics->rotation[4], imu_extrinsics->rotation[5], imu_extrinsics->translation[1] / 1000.0f,
346 imu_extrinsics->rotation[6], imu_extrinsics->rotation[7], imu_extrinsics->rotation[8], imu_extrinsics->translation[2] / 1000.0f);
348 UINFO(
"camera to imu=%s", imuLocalTransform_.prettyPrint().c_str());
351 UINFO(
"base to imu=%s", imuLocalTransform_.prettyPrint().c_str());
355 if (!fileName_.empty())
357 k4a_record_configuration_t
config;
358 if (k4a_playback_get_record_configuration((k4a_playback_t)playbackHandle_, &config))
360 UERROR(
"Failed to getting recording configuration");
367 if (K4A_FAILED(k4a_device_start_imu(deviceHandle_)))
369 UERROR(
"Failed to start K4A IMU");
374 UINFO(
"K4a IMU started successfully");
377 if (K4A_WAIT_RESULT_SUCCEEDED == k4a_device_get_capture(deviceHandle_, &captureHandle_, K4A_WAIT_INFINITE))
379 k4a_capture_release(captureHandle_);
388 UERROR(
"CameraK4A: RTAB-Map is not built with Kinect for Azure SDK support!");
401 if(!fileName_.empty())
405 return(serial_number_);
417 k4a_image_t ir_image_ =
NULL;
418 k4a_image_t rgb_image_ =
NULL;
419 k4a_imu_sample_t imu_sample_;
423 bool captured =
false;
426 k4a_stream_result_t result = K4A_STREAM_RESULT_FAILED;
428 (K4A_STREAM_RESULT_SUCCEEDED != (result=k4a_playback_get_next_capture(playbackHandle_, &captureHandle_)) ||
429 ((ir_ && (ir_image_=k4a_capture_get_ir_image(captureHandle_)) ==
NULL) || (!ir_ && (rgb_image_=k4a_capture_get_color_image(captureHandle_)) ==
NULL))))
431 k4a_capture_release(captureHandle_);
434 if (result == K4A_STREAM_RESULT_EOF)
437 UINFO(
"End of file reached");
439 else if (result == K4A_STREAM_RESULT_FAILED)
441 UERROR(
"Failed to read entire recording");
443 captured = result == K4A_STREAM_RESULT_SUCCEEDED;
447 k4a_wait_result_t result = K4A_WAIT_RESULT_FAILED;
449 (K4A_WAIT_RESULT_SUCCEEDED != (result=k4a_device_get_capture(deviceHandle_, &captureHandle_, K4A_WAIT_INFINITE)) ||
450 ((ir_ && (ir_image_=k4a_capture_get_ir_image(captureHandle_)) ==
NULL) || (!ir_ && (rgb_image_=k4a_capture_get_color_image(captureHandle_)) ==
NULL))))
452 k4a_capture_release(captureHandle_);
455 captured = result == K4A_WAIT_RESULT_SUCCEEDED;
458 if (captured && (rgb_image_!=
NULL || ir_image_!=
NULL))
464 if (ir_image_ !=
NULL)
467 cv::Mat bgrCV16(k4a_image_get_height_pixels(ir_image_),
468 k4a_image_get_width_pixels(ir_image_),
470 (
void*)k4a_image_get_buffer(ir_image_));
472 bgrCV16.convertTo(bgrCV, CV_8U);
474 bgrCV = model_.rectifyImage(bgrCV);
477 k4a_image_release(ir_image_);
482 if (k4a_image_get_format(rgb_image_) == K4A_IMAGE_FORMAT_COLOR_MJPG)
484 bgrCV =
uncompressImage(cv::Mat(1, (
int)k4a_image_get_size(rgb_image_),
486 (
void*)k4a_image_get_buffer(rgb_image_)));
490 cv::Mat bgra(k4a_image_get_height_pixels(rgb_image_),
491 k4a_image_get_width_pixels(rgb_image_),
493 (
void*)k4a_image_get_buffer(rgb_image_));
495 cv::cvtColor(bgra, bgrCV, CV_BGRA2BGR);
497 bgrCV = model_.rectifyImage(bgrCV);
500 k4a_image_release(rgb_image_);
507 k4a_image_t depth_image_ = k4a_capture_get_depth_image(captureHandle_);
509 if (depth_image_ !=
NULL)
511 double stampDevice = ((double)k4a_image_get_device_timestamp_usec(depth_image_)) / 1000000.0;
513 if(timestampOffset_ == 0.0)
515 timestampOffset_ = stamp - stampDevice;
518 stamp = stampDevice + timestampOffset_;
522 depthCV = cv::Mat(k4a_image_get_height_pixels(depth_image_),
523 k4a_image_get_width_pixels(depth_image_),
525 (
void*)k4a_image_get_buffer(depth_image_));
527 depthCV = model_.rectifyDepth(depthCV);
531 k4a_image_t transformedDepth =
NULL;
532 if (k4a_image_create(k4a_image_get_format(depth_image_),
533 bgrCV.cols, bgrCV.rows, bgrCV.cols * 2, &transformedDepth) == K4A_RESULT_SUCCEEDED)
535 if(k4a_transformation_depth_image_to_color_camera(transformationHandle_, depth_image_, transformedDepth) == K4A_RESULT_SUCCEEDED)
537 depthCV = cv::Mat(k4a_image_get_height_pixels(transformedDepth),
538 k4a_image_get_width_pixels(transformedDepth),
540 (
void*)k4a_image_get_buffer(transformedDepth)).clone();
544 UERROR(
"K4A failed to register depth image");
547 k4a_image_release(transformedDepth);
551 UERROR(
"K4A failed to allocate registered depth image");
554 k4a_image_release(depth_image_);
558 k4a_capture_release(captureHandle_);
564 k4a_playback_seek_timestamp(playbackHandle_, stamp* 1000000+1, K4A_PLAYBACK_SEEK_BEGIN);
565 if(K4A_STREAM_RESULT_SUCCEEDED == k4a_playback_get_previous_imu_sample(playbackHandle_, &imu_sample_))
567 imu =
IMU(cv::Vec3d(imu_sample_.gyro_sample.xyz.x, imu_sample_.gyro_sample.xyz.y, imu_sample_.gyro_sample.xyz.z),
568 cv::Mat::eye(3, 3, CV_64FC1),
569 cv::Vec3d(imu_sample_.acc_sample.xyz.x, imu_sample_.acc_sample.xyz.y, imu_sample_.acc_sample.xyz.z),
570 cv::Mat::eye(3, 3, CV_64FC1),
575 UWARN(
"IMU data NULL");
581 if(K4A_WAIT_RESULT_SUCCEEDED == k4a_device_get_imu_sample(deviceHandle_, &imu_sample_, 60))
583 imu =
IMU(cv::Vec3d(imu_sample_.gyro_sample.xyz.x, imu_sample_.gyro_sample.xyz.y, imu_sample_.gyro_sample.xyz.z),
584 cv::Mat::eye(3, 3, CV_64FC1),
585 cv::Vec3d(imu_sample_.acc_sample.xyz.x, imu_sample_.acc_sample.xyz.y, imu_sample_.acc_sample.xyz.z),
586 cv::Mat::eye(3, 3, CV_64FC1),
596 if (!bgrCV.empty() && !depthCV.empty())
609 UWARN(
"The option to use mkv stamps is set (framerate<0), but there are no stamps saved in the file! Aborting...");
611 else if (previousStamp_ > 0)
614 int sleepTime = 1000.0*(stamp - previousStamp_) / ratio - 1000.0*timer_.getElapsedTime();
615 if (sleepTime > 10000)
617 UWARN(
"Detected long delay (%d sec, stamps = %f vs %f). Waiting a maximum of 10 seconds.",
618 sleepTime / 1000, previousStamp_, stamp);
627 while (timer_.getElapsedTime() < (stamp - previousStamp_) / ratio - 0.000001)
632 double slept = timer_.getElapsedTime();
634 UDEBUG(
"slept=%fs vs target=%fs (ratio=%f)", slept, (stamp - previousStamp_) / ratio, ratio);
636 previousStamp_ = stamp;
641 UERROR(
"CameraK4A: RTAB-Map is not built with Kinect for Azure SDK support!");
virtual SensorData captureImage(CameraInfo *info=0)
virtual std::string getSerial() const
CameraK4A(int deviceId=0, float imageRate=0.0f, const Transform &localTransform=Transform::getIdentity())
#define UASSERT(condition)
void setIRDepthFormat(bool enabled)
const Transform & getLocalTransform() const
void setPreferences(int rgb_resolution, int framerate, int depth_resolution)
static ULogger::Level level()
float getImageRate() const
void uSleep(unsigned int ms)
void setIMU(const IMU &imu)
virtual bool isCalibrated() const
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
cv::Mat RTABMAP_EXP uncompressImage(const cv::Mat &bytes)