6 #include <sensor_msgs/Image.h> 15 #include <sensor_msgs/CameraInfo.h> 18 #include <dynamic_reconfigure/server.h> 19 #include <ensenso/CameraParametersConfig.h> 21 #include <ensenso/RawStereoPattern.h> 22 #include <geometry_msgs/PoseStamped.h> 23 #include <sensor_msgs/PointCloud2.h> 24 #include <std_msgs/String.h> 26 #include <ensenso/CalibrateHandEye.h> 27 #include <ensenso/CollectPattern.h> 28 #include <ensenso/EstimatePatternPose.h> 30 #include <boost/thread/thread.hpp> 87 rgb_available_(false),
89 enable_images_(false),
91 is_streaming_images_(false),
92 is_streaming_cloud_(false),
93 is_streaming_depth_(false),
94 stream_calib_pattern_(false),
101 std::string serial, monoserial;
102 nh_private_.
param(std::string(
"serial"), serial, std::string(
"150534"));
103 if (!nh_private_.
hasParam(
"serial"))
104 ROS_WARN_STREAM(
"Parameter [~serial] not found, using default: " << serial);
105 nh_private_.
param(std::string(
"monoserial"), monoserial, std::string(
"4103203953"));
106 if (!nh_private_.
hasParam(
"monoserial"))
107 ROS_WARN_STREAM(
"Parameter [~monoserial] not found, using default: " << monoserial);
108 nh_private_.
param(
"camera_frame_id", camera_frame_id_, std::string(
"ensenso_optical_frame"));
109 if (!nh_private_.
hasParam(
"camera_frame_id"))
110 ROS_WARN_STREAM(
"Parameter [~camera_frame_id] not found, using default: " << camera_frame_id_);
111 nh_private_.
param(
"rgb_camera_frame_id", rgb_camera_frame_id_, std::string(
"ensenso_rgb_optical_frame"));
112 if (!nh_private_.
hasParam(
"rgb_camera_frame_id"))
113 ROS_WARN_STREAM(
"Parameter [~rgb_camera_frame_id] not found, using default: " << rgb_camera_frame_id_);
114 nh_private_.
param(
"stream_calib_pattern", stream_calib_pattern_,
false);
115 if (!nh_private_.
hasParam(
"stream_calib_pattern"))
116 ROS_WARN_STREAM(
"Parameter [~stream_calib_pattern] not found, using default: " << (stream_calib_pattern_ ?
"TRUE":
"FALSE"));
124 l_raw_pub_ = it_.
advertiseCamera(
"left/image_raw", 1, image_issc, image_issc, image_rssc, image_rssc);
125 r_raw_pub_ = it_.
advertiseCamera(
"right/image_raw", 1, image_issc, image_issc, image_rssc, image_rssc);
127 l_rectified_pub_ = it_.
advertise(
"left/image_rect", 1, image_issc, image_issc);
128 r_rectified_pub_ = it_.
advertise(
"right/image_rect", 1, image_issc, image_issc);
130 depth_pub_ = it_.
advertiseCamera(
"depth/image_rect", 1, depth_issc, depth_issc, depth_rssc, depth_rssc);
132 cloud_pub_ = nh_.
advertise<sensor_msgs::PointCloud2 >(
"depth/points", 1, cloud_rssc, cloud_rssc);
136 ensenso_ptr_->openDevice(serial);
139 if (ensenso_ptr_->openMonoDevice(monoserial))
141 rgb_available_ =
true;
145 rgb_raw_pub_ = it_.
advertiseCamera(
"rgb/image_raw", 1, image_issc, image_issc, image_rssc, image_rssc);
146 rgb_rectified_pub_ = it_.
advertise(
"rgb/image_rect_color", 1, image_issc, image_issc);
148 ensenso_ptr_->setUseRGB(
true);
151 catch (pcl::IOException e)
153 rgb_available_ =
false;
157 ensenso_ptr_->openTcpPort();
158 ensenso_ptr_->storeCalibrationPattern(stream_calib_pattern_);
160 dynamic_reconfigure::Server<ensenso::CameraParametersConfig>::CallbackType
f;
162 reconfigure_server_.setCallback(f);
164 ensenso_ptr_->start();
166 ROS_INFO(
"Finished [ensenso_driver] initialization");
171 cloud_connection_.disconnect();
172 image_connection_.disconnect();
173 depth_connection_.disconnect();
174 ensenso_ptr_->closeDevices();
175 ensenso_ptr_->closeTcpPort();
178 bool calibrateHandEyeCB(ensenso::CalibrateHandEye::Request& req, ensenso::CalibrateHandEye::Response &res)
180 bool was_running = ensenso_ptr_->isRunning();
182 ensenso_ptr_->stop();
184 if ( req.robot_poses.poses.size() != ensenso_ptr_->getPatternCount() )
186 ROS_WARN(
"The number of robot_poses differs from the pattern count in the camera buffer");
188 ensenso_ptr_->start();
192 std::vector<Eigen::Affine3d, Eigen::aligned_allocator<Eigen::Affine3d> > robot_eigen_list;
193 for (
size_t i = 0; i < req.robot_poses.poses.size(); i++) {
194 Eigen::Affine3d pose;
196 robot_eigen_list.push_back(pose);
199 Eigen::Affine3d camera_seed, pattern_seed, estimated_camera_pose, estimated_pattern_pose;
202 ROS_INFO(
"calibrateHandEye: It may take up to 5 minutes...");
203 res.success = ensenso_ptr_->calibrateHandEye(robot_eigen_list, camera_seed, pattern_seed,
204 req.setup, estimated_camera_pose, estimated_pattern_pose, res.iterations,
205 res.reprojection_error);
208 ROS_INFO(
"Calibration computation finished");
213 ensenso_ptr_->start();
220 std::string trigger_mode, profile;
221 switch (config.TriggerMode)
224 trigger_mode =
"Software";
227 trigger_mode =
"FallingEdge";
230 trigger_mode =
"RisingEdge";
233 trigger_mode =
"Software";
235 switch (config.OptimizationProfile)
241 profile =
"Diagonal";
244 profile =
"AlignedAndDiagonal";
247 profile =
"AlignedAndDiagonal";
251 ROS_DEBUG_STREAM(
"AutoBlackLevel: " << std::boolalpha << config.AutoBlackLevel);
252 ROS_DEBUG_STREAM(
"AutoExposure: " << std::boolalpha << config.AutoExposure);
262 ROS_DEBUG_STREAM(
"HardwareGamma: " << std::boolalpha << config.HardwareGamma);
269 ROS_DEBUG_STREAM(
"DisparityMapAOI: " << std::boolalpha << config.DisparityMapAOI);
275 ROS_DEBUG(
"Advanced Matching Parameters");
281 if (!config.FindPattern)
283 ROS_WARN_STREAM(
"The calibration pattern will not be searched for, calibration will not work.");
287 ROS_DEBUG_STREAM(
"SpeckleComponentThreshold: "<< config.SpeckleComponentThreshold);
292 ROS_DEBUG_STREAM(
"SurfaceConnectivity: " << std::boolalpha << config.SurfaceConnectivity);
301 #ifdef CUDA_IMPLEMENTED 304 ROS_DEBUG_STREAM(
"CUDA is not supported. Upgrade EnsensoSDK to Version >= 2.1.7 in order to use CUDA.");
308 enable_cloud_ = config.Cloud;
309 enable_images_ = config.Images;
310 enable_depth_ = config.Depth;
313 if (config.FindPattern && !find_pattern_)
315 pattern_raw_pub_ = nh_.
advertise<ensenso::RawStereoPattern> (
"pattern/stereo", 1,
false);
316 pattern_pose_pub_ = nh_.
advertise<geometry_msgs::PoseStamped> (
"pattern/pose", 1,
false);
321 find_pattern_ = config.FindPattern;
323 ensenso_ptr_->setAutoBlackLevel(config.AutoBlackLevel);
324 ensenso_ptr_->setAutoExposure(config.AutoExposure);
325 ensenso_ptr_->setAutoGain(config.AutoGain);
326 ensenso_ptr_->setBlackLevelOffset(config.BlackLevelOffset);
327 ensenso_ptr_->setExposure(config.Exposure);
328 ensenso_ptr_->setFrontLight(config.FrontLight);
329 ensenso_ptr_->setGain(config.Gain);
330 ensenso_ptr_->setGainBoost(config.GainBoost);
331 ensenso_ptr_->setHardwareGamma(config.HardwareGamma);
332 ensenso_ptr_->setHdr(config.Hdr);
333 ensenso_ptr_->setPixelClock(config.PixelClock);
334 ensenso_ptr_->setProjector(config.Projector);
335 ensenso_ptr_->setRGBTriggerDelay(config.RGBTriggerDelay);
336 ensenso_ptr_->setTargetBrightness(config.TargetBrightness);
337 ensenso_ptr_->setTriggerMode(trigger_mode);
338 ensenso_ptr_->setUseDisparityMapAreaOfInterest(config.DisparityMapAOI);
340 if (trigger_mode.compare(
"Software") == 0 && config.Projector)
342 ensenso_ptr_->setBinning(config.Binning);
343 ensenso_ptr_->setFlexView(config.FlexView, config.FlexViewImages);
346 ensenso_ptr_->setMinimumDisparity(config.MinimumDisparity);
347 ensenso_ptr_->setNumberOfDisparities(config.NumberOfDisparities);
348 ensenso_ptr_->setOptimizationProfile(profile);
349 ensenso_ptr_->setScaling(config.Scaling);
350 ensenso_ptr_->setDepthChangeCost(config.DepthChangeCost);
351 ensenso_ptr_->setDepthStepCost(config.DepthStepCost);
352 ensenso_ptr_->setShadowingThreshold(config.ShadowingThreshold);
354 ensenso_ptr_->setUniquenessRatio(config.UniquenessRatio);
355 ensenso_ptr_->setMedianFilterRadius(config.MedianFilterRadius);
356 ensenso_ptr_->setSpeckleComponentThreshold(config.SpeckleComponentThreshold);
357 ensenso_ptr_->setSpeckleRegionSize(config.SpeckleRegionSize);
358 ensenso_ptr_->setFillBorderSpread(config.FillBorderSpread);
359 ensenso_ptr_->setFillRegionSize(config.FillRegionSize);
360 ensenso_ptr_->setFindPattern(config.FindPattern);
362 ensenso_ptr_->setSurfaceConnectivity(config.SurfaceConnectivity);
363 ensenso_ptr_->setNearPlane(config.NearPlane);
364 ensenso_ptr_->setFarPlane(config.FarPlane);
365 ensenso_ptr_->setUseOpenGL(config.UseOpenGL);
367 #ifdef CUDA_IMPLEMENTED 368 ensenso_ptr_->setEnableCUDA(config.EnableCUDA);
371 if (trigger_mode_ != config.TriggerMode)
373 trigger_mode_ = config.TriggerMode;
374 if (ensenso_ptr_->isRunning())
376 ensenso_ptr_->stop();
377 ensenso_ptr_->start();
386 bool collectPatternCB(ensenso::CollectPattern::Request& req, ensenso::CollectPattern::Response &res)
388 bool was_running = ensenso_ptr_->isRunning();
390 ensenso_ptr_->stop();
392 if (!req.decode && req.grid_spacing <= 0)
394 ROS_WARN(
"grid_spacing not specify. Forgot to set the request.decode = True?");
396 ensenso_ptr_->start();
400 if (req.clear_buffer)
401 ensenso_ptr_->discardPatterns();
405 res.grid_spacing = ensenso_ptr_->decodePattern();
407 if (res.grid_spacing <= 0)
409 ROS_WARN(
"Couldn't decode calibration pattern");
411 ensenso_ptr_->start();
416 res.grid_spacing = req.grid_spacing;
417 ensenso_ptr_->setGridSpacing(res.grid_spacing);
419 int prev_pattern_count = ensenso_ptr_->getPatternCount();
420 res.pattern_count = ensenso_ptr_->collectPattern(req.add_to_buffer);
421 res.success = (res.pattern_count == prev_pattern_count+1);
423 ensenso_ptr_->start();
429 bool was_running = ensenso_ptr_->isRunning();
431 ensenso_ptr_->stop();
432 res.success = ensenso_ptr_->getPatternCount() > 0;
435 Eigen::Affine3d pattern_pose;
436 res.success = ensenso_ptr_->estimatePatternPose(pattern_pose, req.average);
440 ensenso_ptr_->start();
453 sensor_msgs::PointCloud2 cloud_msg;
454 cloud_msg.header.stamp = stamp;
469 sensor_msgs::PointCloud2 cloud_msg;
470 cloud_msg.header.stamp = stamp;
482 sensor_msgs::CameraInfo linfo, rinfo;
483 ensenso_ptr_->getCameraInfo(
"Left", linfo);
484 ensenso_ptr_->getCameraInfo(
"Right", rinfo);
485 linfo.header.stamp = stamp;
487 rinfo.header.stamp = stamp;
491 l_raw_pub_.
publish(*
toImageMsg(rawimages->first, stamp, camera_frame_id_), linfo, stamp);
493 r_raw_pub_.
publish(*
toImageMsg(rawimages->second, stamp, camera_frame_id_), rinfo, stamp);
495 l_rectified_pub_.
publish(
toImageMsg(rectifiedimages->first, stamp, camera_frame_id_));
497 r_rectified_pub_.
publish(
toImageMsg(rectifiedimages->second, stamp, camera_frame_id_));
509 sensor_msgs::CameraInfo linfo, rinfo, rgbinfo;
510 ensenso_ptr_->getCameraInfo(
"Left", linfo);
511 ensenso_ptr_->getCameraInfo(
"Right", rinfo);
512 ensenso_ptr_->getCameraInfo(
"RGB", rgbinfo);
513 linfo.header.stamp = stamp;
515 rinfo.header.stamp = stamp;
517 rgbinfo.header.stamp = stamp;
521 l_raw_pub_.
publish(*
toImageMsg(rawimages->first, stamp, camera_frame_id_), linfo, stamp);
523 r_raw_pub_.
publish(*
toImageMsg(rawimages->second, stamp, camera_frame_id_), rinfo, stamp);
525 l_rectified_pub_.
publish(
toImageMsg(rectifiedimages->first, stamp, camera_frame_id_));
527 r_rectified_pub_.
publish(
toImageMsg(rectifiedimages->second, stamp, camera_frame_id_));
529 rgb_raw_pub_.
publish(*
toImageMsg(rgbimages->first, stamp, rgb_camera_frame_id_), rgbinfo, stamp);
531 rgb_rectified_pub_.
publish(
toImageMsg(rgbimages->second, stamp, rgb_camera_frame_id_));
540 std::string frame_id = rgb_available_ ? rgb_camera_frame_id_ :
camera_frame_id_;
545 sensor_msgs::CameraInfo dinfo;
546 ensenso_ptr_->getCameraInfo(
"Depth", dinfo);
547 dinfo.header.stamp = stamp;
548 dinfo.header.frame_id = frame_id;
556 if (!ensenso_ptr_->getTFLeftToRGB(ensenso_tf))
560 geometry_msgs::TransformStamped
tf;
564 tf.transform.rotation.x = ensenso_tf.
qx;
565 tf.transform.rotation.y = ensenso_tf.
qy;
566 tf.transform.rotation.z = ensenso_tf.
qz;
567 tf.transform.rotation.w = ensenso_tf.
qw;
568 tf.transform.translation.x = ensenso_tf.
tx;
569 tf.transform.translation.y = ensenso_tf.
ty;
570 tf.transform.translation.z = ensenso_tf.
tz;
578 if (stream_calib_pattern_)
580 if ((pose_subs <= 0) && (raw_subs <= 0))
584 Eigen::Affine3d pattern_pose;
585 std::vector<int> grid_size;
586 std::vector<Eigen::Vector2d> left_points, right_points;
587 if ( ensenso_ptr_->getLastCalibrationPattern (grid_size, grid_spacing, left_points, right_points, pattern_pose) )
592 ensenso::RawStereoPattern msg;
594 msg.header.stamp = now;
595 msg.grid_spacing = grid_spacing;
596 msg.grid_size = grid_size;
597 num_points = grid_size[0]*grid_size[1];
598 msg.left_points.resize(num_points);
599 msg.right_points.resize(num_points);
600 for (uint i = 0; i < left_points.size(); ++i)
602 msg.left_points[i].x = left_points[i][0];
603 msg.left_points[i].y = left_points[i][1];
604 msg.right_points[i].x = left_points[i][0];
605 msg.right_points[i].y = left_points[i][1];
612 geometry_msgs::PoseStamped pose_msg;
614 pose_msg.header.stamp = now;
616 pattern_pose_pub_.
publish(pose_msg);
622 template <
typename T>
625 unsigned char *image_array =
reinterpret_cast<unsigned char *
>(&pcl_image.
data[0]);
630 header.frame_id = frame_id;
632 if (pcl_image.encoding ==
"CV_32FC1")
638 if (pcl_image.encoding ==
"CV_8UC3")
643 cv::Mat image_mat(pcl_image.height, pcl_image.width, type, image_array);
654 if (enable_images_ && need_images && !is_streaming_images_)
658 boost::function<void(
662 image_connection_ = ensenso_ptr_->registerCallback(f);
666 boost::function<void(
669 image_connection_ = ensenso_ptr_->registerCallback(f);
671 if (!ensenso_ptr_->isRunning())
673 ensenso_ptr_->start();
675 is_streaming_images_ =
true;
677 else if (( !enable_images_ || !need_images ) && is_streaming_images_)
679 image_connection_.disconnect();
680 is_streaming_images_ =
false;
681 if (!is_streaming_cloud_ && !is_streaming_depth_)
683 ensenso_ptr_->stop();
692 if (enable_cloud_ && need_cloud && !is_streaming_cloud_)
696 boost::function<void(
698 cloud_connection_ = ensenso_ptr_->registerCallback(f);
702 boost::function<void(
704 cloud_connection_ = ensenso_ptr_->registerCallback(f);
706 if (!ensenso_ptr_->isRunning())
708 ensenso_ptr_->start();
710 is_streaming_cloud_ =
true;
712 else if ( (!enable_cloud_ || !need_cloud) && is_streaming_cloud_)
714 cloud_connection_.disconnect();
715 is_streaming_cloud_ =
false;
716 if (!is_streaming_depth_ && !is_streaming_images_)
718 ensenso_ptr_->stop();
726 if (enable_depth_ && need_depth && !is_streaming_depth_)
728 boost::function<void(
730 depth_connection_ = ensenso_ptr_->registerCallback(f);
731 is_streaming_depth_ =
true;
732 if (!ensenso_ptr_->isRunning())
734 ensenso_ptr_->start();
737 else if ((!enable_depth_ || !need_depth) && is_streaming_depth_)
739 depth_connection_.disconnect();
740 is_streaming_depth_ =
false;
741 if (!is_streaming_cloud_ && !is_streaming_images_)
743 ensenso_ptr_->stop();
750 int main(
int argc,
char **argv)
752 ros::init (argc, argv,
"ensenso_driver");
bool estimatePatternPoseCB(ensenso::EstimatePatternPose::Request &req, ensenso::EstimatePatternPose::Response &res)
ros::Publisher pattern_raw_pub_
std::string rgb_camera_frame_id_
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
bool stream_calib_pattern_
void cloudCallback(const boost::shared_ptr< PointCloudXYZ > &cloud)
void publish(const boost::shared_ptr< M > &message) const
image_transport::CameraPublisher rgb_raw_pub_
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
bool is_streaming_images_
dynamic_reconfigure::Server< ensenso::CameraParametersConfig > reconfigure_server_
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
uint32_t getNumSubscribers() const
tf2_ros::TransformBroadcaster tf_br_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void imagesCallback(const boost::shared_ptr< PairOfImages > &rawimages, const boost::shared_ptr< PairOfImages > &rectifiedimages)
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void cloudSubscribeCallback()
image_transport::Publisher r_rectified_pub_
pcl::PointXYZRGBA PointXYZRGBA
uint32_t getNumSubscribers() const
image_transport::Publisher l_rectified_pub_
boost::signals2::connection image_connection_
ROSCPP_DECL void spin(Spinner &spinner)
boost::signals2::connection depth_connection_
image_transport::ImageTransport it_
ros::ServiceServer pattern_srv_
void imagesRGBCallback(const boost::shared_ptr< PairOfImages > &rawimages, const boost::shared_ptr< PairOfImages > &rectifiedimages, const boost::shared_ptr< PairOfImages > &rgbimages)
void fromPCL(const pcl::uint64_t &pcl_stamp, ros::Time &stamp)
CameraPublisher advertiseCamera(const std::string &base_topic, uint32_t queue_size, bool latch=false)
ros::Publisher cloud_pub_
void depthCallback(const boost::shared_ptr< pcl::PCLGenImage< float > > &depthimage)
Grabber for IDS-Imaging Ensenso's devices.
std::pair< pcl::PCLGenImage< pcl::uint8_t >, pcl::PCLGenImage< pcl::uint8_t > > PairOfImages
void cloudRGBCallback(const boost::shared_ptr< PointCloudXYZRGBA > &cloud)
void publish(const sensor_msgs::Image &message) const
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
ros::Publisher pattern_pose_pub_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void publishCalibrationPattern(const ros::Time &now)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
pcl::EnsensoGrabber::Ptr ensenso_ptr_
ros::ServiceServer collect_srv_
#define ROS_WARN_STREAM(args)
bool calibrateHandEyeCB(ensenso::CalibrateHandEye::Request &req, ensenso::CalibrateHandEye::Response &res)
#define ROS_DEBUG_STREAM(args)
bool collectPatternCB(ensenso::CollectPattern::Request &req, ensenso::CollectPattern::Response &res)
ros::NodeHandle nh_private_
image_transport::Publisher rgb_rectified_pub_
boost::signals2::connection cloud_connection_
int main(int argc, char **argv)
uint32_t getNumSubscribers() const
image_transport::CameraPublisher depth_pub_
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
image_transport::CameraPublisher r_raw_pub_
pcl::PointCloud< PointXYZRGBA > PointCloudXYZRGBA
ROSCPP_DECL void shutdown()
void imagesSubscribeCallback()
bool hasParam(const std::string &key) const
pcl::PointCloud< PointXYZ > PointCloudXYZ
std::string camera_frame_id_
void cameraParametersCallback(ensenso::CameraParametersConfig &config, uint32_t level)
sensor_msgs::ImagePtr toImageMsg(pcl::PCLGenImage< T > &pcl_image, ros::Time now, std::string frame_id)
ros::ServiceServer calibrate_srv_
sensor_msgs::ImagePtr toImageMsg() const
void depthSubscribeCallback()
image_transport::CameraPublisher l_raw_pub_