34 #include <geometry_msgs/Vector3Stamped.h> 49 double observation_keep_time;
50 double expected_update_rate;
51 double transform_tolerance;
52 double obstacle_range;
53 double raytrace_range;
54 double min_obstacle_height;
55 double max_obstacle_height;
56 double min_clearing_height;
57 double max_clearing_height;
58 std::string topic =
"";
59 std::string sensor_frame =
"";
74 private_nh.
param(
"min_obstacle_height", min_obstacle_height, 0.0);
75 private_nh.
param(
"max_obstacle_height", max_obstacle_height, 2.0);
76 private_nh.
param(
"min_clearing_height", min_clearing_height, -std::numeric_limits<double>::infinity());
77 private_nh.
param(
"max_clearing_height", max_clearing_height, std::numeric_limits<double>::infinity());
89 private_nh.
param(
"observation_persistence", observation_keep_time, 0.0);
92 private_nh.
param(
"expected_update_rate", expected_update_rate, 0.0);
95 private_nh.
param(
"transform_tolerance", transform_tolerance, 0.5);
97 std::string raytrace_range_param_name, obstacle_range_param_name;
100 obstacle_range = 2.5;
101 if (private_nh.
searchParam(
"obstacle_range", obstacle_range_param_name))
103 private_nh.
getParam(obstacle_range_param_name, obstacle_range);
107 raytrace_range = 3.0;
108 if (private_nh.
searchParam(
"raytrace_range", raytrace_range_param_name))
110 private_nh.
getParam(raytrace_range_param_name, raytrace_range);
115 expected_update_rate, min_obstacle_height, max_obstacle_height,
117 sensor_frame, transform_tolerance));
121 min_obstacle_height = 0.0;
125 expected_update_rate, min_clearing_height, max_clearing_height,
127 sensor_frame, transform_tolerance));
138 std::string camera_depth_topic, camera_info_topic;
139 private_nh.
param(
"depth_topic", camera_depth_topic,
140 std::string(
"/head_camera/depth_downsample/image_raw"));
141 private_nh.
param(
"info_topic", camera_info_topic,
142 std::string(
"/head_camera/depth_downsample/camera_info"));
160 const sensor_msgs::CameraInfo::ConstPtr& msg)
163 boost::unique_lock<boost::mutex> lock(
mutex_K_);
165 float focal_pixels_ = msg->P[0];
166 float center_x_ = msg->P[2];
167 float center_y_ = msg->P[6];
169 if (msg->binning_x == msg->binning_y)
171 if (msg->binning_x > 0)
173 K_ = (cv::Mat_<double>(3, 3) <<
174 focal_pixels_/msg->binning_x, 0.0, center_x_/msg->binning_x,
175 0.0, focal_pixels_/msg->binning_x, center_y_/msg->binning_x,
180 K_ = (cv::Mat_<double>(3, 3) <<
181 focal_pixels_, 0.0, center_x_,
182 0.0, focal_pixels_, center_y_,
188 ROS_ERROR(
"binning_x is not equal to binning_y");
193 const sensor_msgs::Image::ConstPtr& msg)
196 boost::unique_lock<boost::mutex> lock(
mutex_K_);
211 ROS_ERROR(
"cv_bridge exception: %s", e.what());
218 for (
int i = 0; i < cv_ptr->image.rows * cv_ptr->image.cols; i++)
220 if (std::isnan(cv_ptr->image.at<
float>(i)))
221 cv_ptr->image.at<
float>(i) = 25.0;
227 depthTo3d(cv_ptr->image,
K_, points3d);
230 cv::Vec4f ground_plane;
238 cv_ptr->image.depth(),
242 (*normals_estimator_)(points3d, normals);
260 std::vector<cv::Vec4f> plane_coefficients;
261 (*plane_estimator_)(points3d, normals, planes_mask, plane_coefficients);
263 for (
size_t i = 0; i < plane_coefficients.size(); i++)
270 ground_plane = plane_coefficients[i];
279 geometry_msgs::Vector3Stamped vector;
283 vector.header.frame_id =
"base_link";
286 ground_plane[0] = vector.vector.x;
287 ground_plane[1] = vector.vector.y;
288 ground_plane[2] = vector.vector.z;
291 geometry_msgs::TransformStamped transform;
293 transform =
tf_->
lookupTransform(
"base_link", msg->header.frame_id, msg->header.stamp);
294 ground_plane[3] = transform.transform.translation.z;
296 ROS_WARN(
"Failed to lookup transform!");
302 if (ground_plane[0] == 0.0 && ground_plane[1] == 0.0 &&
303 ground_plane[2] == 0.0 && ground_plane[3] == 0.0)
310 cv::split(points3d, channels);
312 sensor_msgs::PointCloud clearing_points;
313 clearing_points.header.stamp = msg->header.stamp;
314 clearing_points.header.frame_id = msg->header.frame_id;
316 sensor_msgs::PointCloud marking_points;
317 marking_points.header.stamp = msg->header.stamp;
318 marking_points.header.frame_id = msg->header.frame_id;
321 for (
size_t i = 0; i < points3d.rows; i++)
323 for (
size_t j = 0; j < points3d.cols; j++)
326 geometry_msgs::Point32 current_point;
327 current_point.x = channels[0].at<
float>(i, j);
328 current_point.y = channels[1].at<
float>(i, j);
329 current_point.z = channels[2].at<
float>(i, j);
331 if (current_point.x != 0.0 &&
332 current_point.y != 0.0 &&
333 current_point.z != 0.0 &&
334 !std::isnan(current_point.x) &&
335 !std::isnan(current_point.y) &&
336 !std::isnan(current_point.z))
341 clearing_points.points.push_back(current_point);
356 clearing_points.points.push_back(current_point);
360 if (fabs(ground_plane[0] * current_point.x +
361 ground_plane[1] * current_point.y +
362 ground_plane[2] * current_point.z +
370 for (
int x = -1; x < 2; x++)
372 for (
int y = -1; y < 2; y++)
374 if (x == 0 && y == 0)
378 float px = channels[0].at<
float>(i+x, j+y);
379 float py = channels[1].at<
float>(i+x, j+y);
380 float pz = channels[2].at<
float>(i+x, j+y);
381 if (px != 0.0 && py != 0.0 && pz != 0.0 &&
382 !std::isnan(px) && !std::isnan(py) && !std::isnan(pz))
384 if ( fabs(px - current_point.x) < 0.1 &&
385 fabs(py - current_point.y) < 0.1 &&
386 fabs(pz - current_point.z) < 0.1)
396 marking_points.points.push_back(current_point);
408 sensor_msgs::PointCloud2 clearing_cloud2;
411 ROS_ERROR(
"Failed to convert a PointCloud to a PointCloud2, dropping message");
426 sensor_msgs::PointCloud2 marking_cloud2;
429 ROS_ERROR(
"Failed to convert a PointCloud to a PointCloud2, dropping message");
T & transform(const T &in, T &out, const std::string &target_frame, ros::Duration timeout=ros::Duration(0.0)) const
bool publish_observations_
ros::Subscriber camera_info_sub_
std::vector< boost::shared_ptr< costmap_2d::ObservationBuffer > > marking_buffers_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
virtual ~FetchDepthLayer()
Destructor for the depth costmap layer.
cv::Ptr< RgbdNormals > normals_estimator_
std::vector< boost::shared_ptr< tf2_ros::MessageFilterBase > > observation_notifiers_
#define ROS_DEBUG_NAMED(name,...)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
void publish(const boost::shared_ptr< M > &message) const
void depthImageCallback(const sensor_msgs::Image::ConstPtr &msg)
void cameraInfoCallback(const sensor_msgs::CameraInfo::ConstPtr &msg)
virtual void onInitialize()
cv::Ptr< RgbdPlane > plane_estimator_
bool getParam(const std::string &key, std::string &s) const
const std::string TYPE_32FC1
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
std::vector< boost::shared_ptr< message_filters::SubscriberBase > > observation_subscribers_
bool clear_with_skipped_rays_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double observations_threshold_
virtual void onInitialize()
Initialization function for the DepthLayer.
ros::Publisher clearing_pub_
bool searchParam(const std::string &key, std::string &result) const
std::vector< boost::shared_ptr< costmap_2d::ObservationBuffer > > clearing_buffers_
boost::shared_ptr< tf2_ros::MessageFilter< sensor_msgs::Image > > depth_image_filter_
boost::shared_ptr< costmap_2d::ObservationBuffer > marking_buf_
static bool convertPointCloudToPointCloud2(const sensor_msgs::PointCloud &input, sensor_msgs::PointCloud2 &output)
ros::Publisher marking_pub_
A costmap layer that extracts ground plane and clears it.
boost::shared_ptr< message_filters::Subscriber< sensor_msgs::Image > > depth_image_sub_
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
boost::shared_ptr< costmap_2d::ObservationBuffer > clearing_buf_
std::vector< boost::shared_ptr< costmap_2d::ObservationBuffer > > observation_buffers_
std::string global_frame_
FetchDepthLayer()
Constructor.