1 #include <opencv2/core/core.hpp> 2 #include <opencv2/highgui/highgui.hpp> 3 #include <opencv2/imgproc/imgproc.hpp> 4 #include <opencv2/opencv.hpp> 9 #include <sensor_msgs/Image.h> 10 #include <sensor_msgs/CameraInfo.h> 13 #include <sensor_msgs/Imu.h> 17 #include <boost/thread/thread.hpp> 18 #include <boost/make_shared.hpp> 22 #include "calibration_parameters.h" 23 #include "init_parameters.h" 31 void CompatDistCoeffs(cv::Mat &distCoeffs) {
32 int w = distCoeffs.cols;
42 distCoeffs = distCoeffs.row(0).colRange(0,w);
75 #ifdef VERBOSE_TO_FILE 76 std::ofstream file_imus;
80 const std::string &encodingType,
81 const std::string &frameId,
83 sensor_msgs::ImagePtr ptr = boost::make_shared<sensor_msgs::Image>();
84 sensor_msgs::Image& imgMessage = *ptr;
85 imgMessage.header.stamp = stamp;
86 imgMessage.header.frame_id = frameId;
87 imgMessage.height = img.rows;
88 imgMessage.width = img.cols;
89 imgMessage.encoding = encodingType;
91 imgMessage.is_bigendian = !(*(
char *) &num == 1);
92 imgMessage.step = img.cols * img.elemSize();
93 size_t size = imgMessage.step * img.rows;
94 imgMessage.data.resize(size);
96 if (img.isContinuous())
97 memcpy((
char*) (&imgMessage.data[0]), img.data, size);
99 uchar* opencvData = img.data;
100 uchar* rosData = (uchar*) (&imgMessage.data[0]);
101 for (
unsigned int i = 0; i < img.rows; i++) {
102 memcpy(rosData, opencvData, imgMessage.step);
103 rosData += imgMessage.step;
104 opencvData += img.step;
113 const std::string &img_frame_id,
119 depth.convertTo(depth, CV_16UC1);
124 sensor_msgs::Imu msg;
126 msg.header.stamp = stamp;
129 msg.linear_acceleration.x = imudata.accel_x * 9.8;
130 msg.linear_acceleration.y = imudata.accel_y * 9.8;
131 msg.linear_acceleration.z = imudata.accel_z * 9.8;
133 msg.linear_acceleration_covariance[0] = 0.04;
134 msg.linear_acceleration_covariance[1] = 0;
135 msg.linear_acceleration_covariance[2] = 0;
137 msg.linear_acceleration_covariance[3] = 0;
138 msg.linear_acceleration_covariance[4] = 0.04;
139 msg.linear_acceleration_covariance[5] = 0;
141 msg.linear_acceleration_covariance[6] = 0;
142 msg.linear_acceleration_covariance[7] = 0;
143 msg.linear_acceleration_covariance[8] = 0.04;
145 msg.angular_velocity.x = imudata.gyro_x / 57.2956;
146 msg.angular_velocity.y = imudata.gyro_y / 57.2956;
147 msg.angular_velocity.z = imudata.gyro_z / 57.2956;
149 msg.angular_velocity_covariance[0] = 0.02;
150 msg.angular_velocity_covariance[1] = 0;
151 msg.angular_velocity_covariance[2] = 0;
153 msg.angular_velocity_covariance[3] = 0;
154 msg.angular_velocity_covariance[4] = 0.02;
155 msg.angular_velocity_covariance[5] = 0;
157 msg.angular_velocity_covariance[6] = 0;
158 msg.angular_velocity_covariance[7] = 0;
159 msg.angular_velocity_covariance[8] = 0.02;
168 cam_info_msg->header.stamp = stamp;
169 cam_info_msg->header.seq = seq;
170 pub_cam_info.
publish(cam_info_msg);
175 mynteye::CalibrationParameters* calibration_parameters,
176 const sensor_msgs::CameraInfoPtr &left_cam_info_msg,
177 const sensor_msgs::CameraInfoPtr &right_cam_info_msg,
178 const std::string &left_frame_id,
179 const std::string &right_frame_id) {
180 int width = resolution.width;
181 int height = resolution.height;
186 left_cam_info_msg->D.resize(5);
187 right_cam_info_msg->D.resize(5);
189 left_cam_info_msg->D[0] = calibration_parameters->D1.at<
double>(0, 0);
190 right_cam_info_msg->D[0] = calibration_parameters->D2.at<
double>(0, 0);
192 left_cam_info_msg->D[1] = calibration_parameters->D1.at<
double>(0, 1);
193 right_cam_info_msg->D[1] = calibration_parameters->D2.at<
double>(0, 1);
195 left_cam_info_msg->D[2] = calibration_parameters->D1.at<
double>(0, 7);
196 right_cam_info_msg->D[2] = calibration_parameters->D2.at<
double>(0, 7);
198 left_cam_info_msg->D[3] = 0.0;
199 right_cam_info_msg->D[3] = 0.0;
201 left_cam_info_msg->D[4] = 0.0;
202 right_cam_info_msg->D[4] = 0.0;
204 for(
int i = 0; i < 3; i++) {
205 for(
int j = 0; j < 3; j++) {
206 left_cam_info_msg->K[i * 3 + j] = calibration_parameters->M1.at<
double>(i, j);
207 right_cam_info_msg->K[i * 3 + j] = calibration_parameters->M2.at<
double>(i, j);
209 left_cam_info_msg->R[i * 3 + j] = calibration_parameters->R.at<
double>(i, j);
210 right_cam_info_msg->R[i * 3 + j] = calibration_parameters->R.at<
double>(i, j);
214 cv::Size img_size(width, height);
215 cv::Mat R1, R2, P1, P2, Q;
216 cv::Rect leftROI, rightROI;
218 CompatDistCoeffs(calibration_parameters->D1);
219 CompatDistCoeffs(calibration_parameters->D2);
221 cv::stereoRectify(calibration_parameters->M1, calibration_parameters->D1,
222 calibration_parameters->M2, calibration_parameters->D2, img_size,
223 calibration_parameters->R, calibration_parameters->T, R1, R2, P1, P2, Q,
224 cv::CALIB_ZERO_DISPARITY, 0, img_size, &leftROI, &rightROI);
226 for(
int i = 0; i < R1.rows; i++) {
227 for(
int j = 0; j < R1.cols; j++) {
228 left_cam_info_msg->R[i * R1.cols + j] = R1.at<
double>(i, j);
229 right_cam_info_msg->R[i * R1.cols + j] = R2.at<
double>(i, j);
232 for(
int i = 0; i < P1.rows; i++) {
233 for(
int j = 0; j < P1.cols; j++) {
234 left_cam_info_msg->P[i * P1.cols + j] = P1.at<
double>(i, j);
235 right_cam_info_msg->P[i * P1.cols + j] = P2.at<
double>(i, j);
238 left_cam_info_msg->width = right_cam_info_msg->width = width;
239 left_cam_info_msg->height = right_cam_info_msg->height = height;
245 static std::uint32_t img_time_beg = -1;
246 static double img_ros_time_beg;
251 if (img_time_beg == -1) {
252 img_time_beg = cam.GetTimestamp();
255 return ros::Time(img_ros_time_beg + (cam.GetTimestamp() - img_time_beg) * 0.0001
f);
259 static std::uint32_t imu_time_beg = -1;
260 static double imu_ros_time_beg;
265 if (imu_time_beg == -1) {
266 imu_time_beg = imudata->time;
269 return ros::Time(imu_ros_time_beg + (imudata->time - imu_time_beg) * 0.0001f);
273 using namespace mynteye;
277 cam.SetMode(Mode::MODE_CPU);
282 resolution = cam.GetResolution();
284 InitParameters params(std::to_string(device_name));
287 if (!cam.IsOpened()) {
288 std::cerr <<
"Error: Open camera failed" << std::endl;
293 cam.ActivateDepthMapFeature();
296 CalibrationParameters *calib_params =
nullptr;
297 calib_params =
new CalibrationParameters(cam.GetCalibrationParameters());
298 cv::Mat img_left, img_right,depthmap,leftImRGB,rightImRGB;
300 sensor_msgs::CameraInfoPtr left_cam_info_msg(
new sensor_msgs::CameraInfo());
301 sensor_msgs::CameraInfoPtr right_cam_info_msg(
new sensor_msgs::CameraInfo());
303 fillCamInfo(resolution, calib_params, left_cam_info_msg, right_cam_info_msg, left_frame_id, right_frame_id);
305 std::vector<IMUData> imudatas;
306 std::uint32_t timestamp = 0;
309 std::uint64_t img_count = 0;
310 std::uint64_t imu_count = 0;
313 #ifdef VERBOSE_TO_FILE 314 std::uint64_t imu_get_count = 0;
321 if (cam.Grab() != ErrorCode::SUCCESS)
continue;
329 bool runLoop = (left_SubNumber + left_raw_SubNumber + right_SubNumber + right_raw_SubNumber + depth_SubNumber + imu_SubNumber) > 0;
331 bool img_get =
false;
332 if (left_SubNumber > 0 &&
333 cam.RetrieveImage(leftImRGB, View::VIEW_LEFT) == ErrorCode::SUCCESS) {
338 if (left_raw_SubNumber > 0 &&
339 cam.RetrieveImage(img_left, View::VIEW_LEFT_UNRECTIFIED) == ErrorCode::SUCCESS) {
344 if (right_SubNumber > 0 &&
345 cam.RetrieveImage(rightImRGB, View::VIEW_RIGHT) == ErrorCode::SUCCESS) {
350 if (right_raw_SubNumber > 0 &&
351 cam.RetrieveImage(img_right, View::VIEW_RIGHT_UNRECTIFIED) == ErrorCode::SUCCESS) {
356 if (enable_depth && depth_SubNumber > 0) {
357 if (cam.RetrieveImage(depthmap, View::VIEW_DEPTH_MAP) == ErrorCode::SUCCESS) {
368 std::cout <<
"Img count: " << img_count << std::endl;
369 std::cout <<
" time: " << cam.GetTimestamp()
375 if (imu_SubNumber > 0) {
376 if (cam.RetrieveIMUData(imudatas, timestamp) == ErrorCode::SUCCESS && !imudatas.empty()) {
377 size_t size = imudatas.size();
381 std::cout <<
"IMU count: " << imu_count << std::endl;
382 #ifdef VERBOSE_TO_FILE 383 if (imu_get_count == 0) {
386 file_imus = std::ofstream(
"imus_publish.txt", std::ios::out);
388 file_imus << (++imu_get_count) <<
", " << size <<
" IMUs, " << imu_count <<
" in total." << std::endl;
392 for (
size_t i = 0, n = size-1; i <= n; ++i) {
393 auto &imudata = imudatas[i];
397 std::cout <<
" IMU[" << i <<
"]" 398 <<
" accel(" << imudata.accel_x <<
"," << imudata.accel_y <<
"," << imudata.accel_z <<
")" 399 <<
", gyro(" << imudata.gyro_x <<
"," << imudata.gyro_y <<
"," << imudata.gyro_z <<
")" 401 std::cout <<
" time: " << imudata.time
402 <<
", stamp: " << imu_ros_time
403 <<
", time_offset: " << imudata.time_offset << std::endl;
404 #ifdef VERBOSE_TO_FILE 405 file_imus <<
"IMU[" << i <<
"] stamp: " << std::fixed << imu_ros_time
406 <<
", accel(" << imudata.accel_x <<
"," << imudata.accel_y <<
"," << imudata.accel_z <<
")" 407 <<
", gyro(" << imudata.gyro_x <<
"," << imudata.gyro_y <<
"," << imudata.gyro_z <<
")" 412 if (imu_SubNumber > 0)
publishIMU(imudata, imu_ros_time);
417 std::cout << std::endl;
418 #ifdef VERBOSE_TO_FILE 419 file_imus << std::endl;
434 #ifdef VERBOSE_TO_FILE 435 if (imu_SubNumber <= 0 && imu_get_count > 0) {
437 double elapsed = imu_get_end - imu_get_beg;
438 file_imus <<
"time beg: " << std::fixed << imu_get_beg <<
" s" << std::endl
439 <<
"time end: " << std::fixed << imu_get_end <<
" s" << std::endl
440 <<
"time cost: " << elapsed <<
" s" << std::endl << std::endl
441 <<
"imu: " << (imu_count / imu_get_count) <<
" per frame, " 442 << imu_count <<
" in total, " << (imu_count / elapsed) <<
" Hz" << std::endl;
453 std::string img_topic =
"image_rect_color";
454 std::string img_raw_topic =
"image_raw_color";
456 std::string left_topic =
"left/" + img_topic;
457 std::string left_raw_topic =
"left/" + img_raw_topic;
458 std::string left_cam_info_topic =
"left/camera_info";
459 left_frame_id =
"/mynt_left_frame";
461 std::string right_topic =
"right/" + img_topic;
462 std::string right_raw_topic =
"right/" + img_raw_topic;
463 std::string right_cam_info_topic =
"right/camera_info";
464 right_frame_id =
"/mynt_right_frame";
466 std::string depth_topic =
"depth/depth_registered";
467 depth_frame_id =
"/mynt_depth_frame";
469 std::string imu_topic =
"imu";
470 imu_frame_id =
"/mynt_imu_frame";
474 enable_depth =
false;
478 nh_ns.
getParam(
"device_name", device_name);
479 nh_ns.
getParam(
"enable_cpu", enable_cpu);
480 nh_ns.
getParam(
"enable_depth", enable_depth);
481 nh_ns.
getParam(
"left_topic", left_topic);
482 nh_ns.
getParam(
"left_raw_topic", left_raw_topic);
483 nh_ns.
getParam(
"left_cam_info_topic", left_cam_info_topic);
484 nh_ns.
getParam(
"right_topic", right_topic);
485 nh_ns.
getParam(
"right_raw_topic", right_raw_topic);
486 nh_ns.
getParam(
"right_cam_info_topic", right_cam_info_topic);
487 nh_ns.
getParam(
"depth_topic", depth_topic);
488 nh_ns.
getParam(
"imu_topic", imu_topic);
492 pub_left = it_mynteye.
advertise(left_topic, 1);
494 pub_raw_left = it_mynteye.
advertise(left_raw_topic, 1);
496 pub_left_cam_info = nh.
advertise<sensor_msgs::CameraInfo>(left_cam_info_topic, 1);
499 pub_right = it_mynteye.
advertise(right_topic, 1);
500 NODELET_INFO_STREAM(
"Advertized on topic " << right_topic);
501 pub_raw_right = it_mynteye.
advertise(right_raw_topic, 1);
502 NODELET_INFO_STREAM(
"Advertized on topic " << right_raw_topic);
503 pub_right_cam_info = nh.
advertise<sensor_msgs::CameraInfo>(right_cam_info_topic, 1);
504 NODELET_INFO_STREAM(
"Advertized on topic " << right_cam_info_topic);
506 pub_depth = it_mynteye.
advertise(depth_topic, 1);
507 NODELET_INFO_STREAM(
"Advertized on topic " << depth_topic);
509 pub_imu = nh.
advertise<sensor_msgs::Imu>(imu_topic, 1);
510 NODELET_INFO_STREAM(
"Advertized on topic " << imu_topic);
#define NODELET_INFO_STREAM(...)
ros::Time getImgStamp(bool reset=false)
ros::Time getIMUStamp(mynteye::IMUData *imudata, bool reset=false)
void publishCamInfo(const sensor_msgs::CameraInfoPtr &cam_info_msg, const ros::Publisher &pub_cam_info, const ros::Time &stamp)
void fillCamInfo(const mynteye::Resolution &resolution, mynteye::CalibrationParameters *calibration_parameters, const sensor_msgs::CameraInfoPtr &left_cam_info_msg, const sensor_msgs::CameraInfoPtr &right_cam_info_msg, const std::string &left_frame_id, const std::string &right_frame_id)
void publish(const boost::shared_ptr< M > &message) const
ros::Publisher pub_right_cam_info
void publishImage(const cv::Mat &img, const image_transport::Publisher &pub_img, const std::string &img_frame_id, const ros::Time &stamp)
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
image_transport::Publisher pub_depth
ros::NodeHandle & getMTNodeHandle() const
uint32_t getNumSubscribers() const
ros::Publisher pub_left_cam_info
void publishDepth(cv::Mat &depth, const ros::Time &stamp)
ros::NodeHandle & getMTPrivateNodeHandle() const
sensor_msgs::ImagePtr imageToROSmsg(const cv::Mat &img, const std::string &encodingType, const std::string &frameId, const ros::Time &stamp)
void publish(const sensor_msgs::Image &message) const
std::string left_frame_id
image_transport::Publisher pub_raw_left
const std::string PLUMB_BOB
mynteye::Resolution resolution
PLUGINLIB_EXPORT_CLASS(mynt_wrapper::MYNTWrapperNodelet, nodelet::Nodelet)
const std::string TYPE_16UC1
void publishIMU(const mynteye::IMUData &imudata, const ros::Time &stamp)
boost::shared_ptr< boost::thread > device_poll_thread
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::string depth_frame_id
image_transport::Publisher pub_right
TFSIMD_FORCE_INLINE const tfScalar & w() const
uint32_t getNumSubscribers() const
bool getParam(const std::string &key, std::string &s) const
image_transport::Publisher pub_raw_right
std::string right_frame_id
image_transport::Publisher pub_left