image_processing_nodelet.cpp
Go to the documentation of this file.
2 
3 #include <std_msgs/Float32.h>
5 
7 {
9  DiagnosticNodelet::onInit();
11  initParams();
13  }
14 
16  }
17 
19  publish_once_ = true;
20 
21  pnh_->param("resize_scale_x", resize_x_, 1.0);
22  NODELET_INFO("resize_scale_x : %f", resize_x_);
23  pnh_->param("resize_scale_y", resize_y_, 1.0);
24  NODELET_INFO("resize_scale_y : %f", resize_y_);
25 
26  pnh_->param("width", dst_width_, 0);
27  NODELET_INFO("width : %d", dst_width_);
28  pnh_->param("height", dst_height_, 0);
29  NODELET_INFO("height : %d", dst_height_);
30  pnh_->param("use_camera_subscriber", use_camera_subscriber_, false);
31  pnh_->param("max_queue_size", max_queue_size_, 5);
32  pnh_->param("use_snapshot", use_snapshot_, false);
33  pnh_->param("use_messages", use_messages_, true);
34  if (use_messages_) {
35  double d_period;
36  pnh_->param("period", d_period, 1.0);
37  period_ = ros::Duration(d_period);
38  NODELET_INFO("use_messages : %d", use_messages_);
39  NODELET_INFO("message period : %f", period_.toSec());
40  }
41  pnh_->param("use_bytes", use_bytes_, false);
42  pnh_->param("use_camera_info", use_camera_info_, true);
43  }
44 
46  {
47  if (use_snapshot_) {
48  sub_.shutdown();
49  }
50  if (use_camera_info_) {
52  cs_.shutdown();
53  }
54  else {
57  }
58  }
59  else {
61  }
62  }
63 
65  {
66  if (use_snapshot_) {
67  sub_ = pnh_->subscribe("snapshot", 1, &ImageProcessing::snapshot_msg_cb, this);
68  }
69  if (use_camera_info_) {
71  cs_ = it_->subscribeCamera("input/image", max_queue_size_,
73  }
74  else {
75  camera_info_sub_ = nh_->subscribe(image_transport::getCameraInfoTopic(pnh_->resolveName("input/image")),
76  1,
78  this);
79  image_nonsync_sub_ = it_->subscribe("input/image",
80  1,
82  this);
83  }
84  }
85  else {
86  image_sub_ = pnh_->subscribe("input/image", max_queue_size_, &ImageProcessing::image_cb, this);
87  }
88  }
89 
90 
92  double vital_rate;
93  pnh_->param("vital_rate", vital_rate, 1.0);
94  image_vital_.reset(
95  new jsk_topic_tools::VitalChecker(1 / vital_rate));
96  info_vital_.reset(
97  new jsk_topic_tools::VitalChecker(1 / vital_rate));
99  std::string img = nh_->resolveName("image");
100  std::string cam = nh_->resolveName("camera");
101  if (img.at(0) == '/') {
102  img.erase(0, 1);
103  }
104  NODELET_INFO("camera = %s", cam.c_str());
105  NODELET_INFO("image = %s", img.c_str());
106 
107  width_scale_pub_ = advertise<std_msgs::Float32>(*pnh_, "output/width_scale", max_queue_size_);
108  height_scale_pub_ = advertise<std_msgs::Float32>(*pnh_, "output/height_scale", max_queue_size_);
109 
110  if (use_snapshot_) {
111  publish_once_ = false;
112  srv_ = pnh_->advertiseService("snapshot", &ImageProcessing::snapshot_srv_cb, this);
113  }
114 
115  if (use_camera_info_) {
116 #ifdef USE_2_0_9_ADVERTISE_CAMERA
117  cp_ = advertiseCamera(*pnh_, *it_, "output/image", max_queue_size_);
118 #else
119  cp_ = advertiseCamera(*pnh_, "output/image", max_queue_size_);
120 #endif
121  }
122  else {
123  image_pub_ = advertise<sensor_msgs::Image>(*pnh_, "output/image", max_queue_size_);
124  }
125 
126  }
127 
128  void ImageProcessing::snapshot_msg_cb (const std_msgs::EmptyConstPtr msg) {
129  boost::mutex::scoped_lock lock(mutex_);
130  publish_once_ = true;
131  }
132 
133  bool ImageProcessing::snapshot_srv_cb (std_srvs::Empty::Request &req,
134  std_srvs::Empty::Response &res) {
135  boost::mutex::scoped_lock lock(mutex_);
136 
137  publish_once_ = true;
138  return true;
139  }
140 
141  void ImageProcessing::info_cb(const sensor_msgs::CameraInfoConstPtr &msg) {
142  boost::mutex::scoped_lock lock(mutex_);
143  info_vital_->poke();
144  info_msg_ = msg;
145  }
146 
147  void ImageProcessing::image_nonsync_cb(const sensor_msgs::ImageConstPtr& msg) {
148  {
149  boost::mutex::scoped_lock lock(mutex_);
150  image_vital_->poke();
151  if (!info_msg_) {
152  NODELET_WARN_THROTTLE(1, "camera info is not yet available");
153  return;
154  }
155  }
156  callback(msg, info_msg_);
157  }
158 
160  {
161  boost::mutex::scoped_lock lock(mutex_);
162 
163  if (!image_vital_ || !info_vital_) {
164  // initialization is not finished
165  return;
166  }
167 
168  // common
169  stat.add("use_camera_info", use_camera_info_);
170  stat.add("use_snapshot", use_snapshot_);
171  stat.add("input image", pnh_->resolveName("input/image"));
172  stat.add("output image", pnh_->resolveName("output/image"));
173  // summary
174  if (!image_vital_->isAlive()) {
175  stat.summary(diagnostic_error_level_,
176  "no image input. Is " + pnh_->resolveName("input/image") + " active?");
177  }
178  else {
179  if (use_camera_info_) {
180  if (!info_vital_->isAlive()) {
181  stat.summary(diagnostic_error_level_,
182  "no info input. Is " + camera_info_sub_.getTopic() + " active?");
183  }
184  else {
185  stat.summary(diagnostic_msgs::DiagnosticStatus::OK,
186  "running");
187  }
188  stat.add("input info", camera_info_sub_.getTopic());
189  stat.add("info_last_received_time", info_vital_->lastAliveTimeRelative());
190  }
191  else {
192  stat.summary(diagnostic_msgs::DiagnosticStatus::OK,
193  "running");
194  }
195  }
196  stat.add("image_last_received_time", image_vital_->lastAliveTimeRelative());
197  ros::Time now = ros::Time::now();
198  float duration = (now - last_rosinfo_time_).toSec();
199  int in_time_n = in_times.size();
200  int out_time_n = out_times.size();
201  double in_time_mean = 0, in_time_rate = 1.0, in_time_std_dev = 0.0, in_time_max_delta, in_time_min_delta;
202  double out_time_mean = 0, out_time_rate = 1.0, out_time_std_dev = 0.0, out_time_max_delta, out_time_min_delta;
203 
204  std::for_each( in_times.begin(), in_times.end(), (in_time_mean += boost::lambda::_1) );
205  in_time_mean /= in_time_n;
206  in_time_rate /= in_time_mean;
207  std::for_each( in_times.begin(), in_times.end(), (in_time_std_dev += (boost::lambda::_1 - in_time_mean)*(boost::lambda::_1 - in_time_mean) ) );
208  in_time_std_dev = sqrt(in_time_std_dev/in_time_n);
209  if (in_time_n > 1) {
210  in_time_min_delta = *std::min_element(in_times.begin(), in_times.end());
211  in_time_max_delta = *std::max_element(in_times.begin(), in_times.end());
212  }
213 
214  std::for_each( out_times.begin(), out_times.end(), (out_time_mean += boost::lambda::_1) );
215  out_time_mean /= out_time_n;
216  out_time_rate /= out_time_mean;
217  std::for_each( out_times.begin(), out_times.end(), (out_time_std_dev += (boost::lambda::_1 - out_time_mean)*(boost::lambda::_1 - out_time_mean) ) );
218  out_time_std_dev = sqrt(out_time_std_dev/out_time_n);
219  if (out_time_n > 1) {
220  out_time_min_delta = *std::min_element(out_times.begin(), out_times.end());
221  out_time_max_delta = *std::max_element(out_times.begin(), out_times.end());
222  }
223 
224  double in_byte_mean = 0, out_byte_mean = 0;
225  std::for_each( in_bytes.begin(), in_bytes.end(), (in_byte_mean += boost::lambda::_1) );
226  std::for_each( out_bytes.begin(), out_bytes.end(), (out_byte_mean += boost::lambda::_1) );
227  in_byte_mean /= duration;
228  out_byte_mean /= duration;
229  stat.add("compressed rate", in_byte_mean / out_byte_mean);
230  stat.add("input bandwidth (Kbps)", in_byte_mean / 1000 * 8);
231  stat.add("input bandwidth (Mbps)", in_byte_mean / 1000 / 1000 * 8);
232  stat.add("input rate (hz)", in_time_rate);
233  stat.add("input min delta (s)", in_time_min_delta);
234  stat.add("input max delta (s)", in_time_max_delta);
235  stat.add("input std_dev delta (s)", in_time_std_dev);
236  stat.add("input times (n)", in_time_n);
237  stat.add("output bandwidth (Kbps)", out_byte_mean / 1000 * 8);
238  stat.add("output bandwidth (Mbps)", out_byte_mean / 1000 / 1000 * 8);
239  stat.add("output rate (hz)", out_time_rate);
240  stat.add("output min delta (s)", out_time_min_delta);
241  stat.add("output max delta (s)", out_time_max_delta);
242  stat.add("output std_dev delta (s)", out_time_std_dev);
243  stat.add("output times (n)", out_time_n);
244  in_times.clear();
245  in_bytes.clear();
246  out_times.clear();
247  out_bytes.clear();
248  last_rosinfo_time_ = now;
249 
250  }
251 
252  void ImageProcessing::image_cb(const sensor_msgs::ImageConstPtr &img){
253  image_vital_->poke();
254  callback(img, sensor_msgs::CameraInfo::ConstPtr());
255  }
256 
257  void ImageProcessing::callback(const sensor_msgs::ImageConstPtr &img,
258  const sensor_msgs::CameraInfoConstPtr &info) {
259  boost::mutex::scoped_lock lock(mutex_);
260  ros::Time now = ros::Time::now();
261  ROS_DEBUG("image processing callback");
262  if ( !publish_once_ || (cp_.getNumSubscribers () == 0 && image_pub_.getNumSubscribers () == 0 )) {
263  ROS_DEBUG("number of subscribers is 0, ignoring image");
264  return;
265  }
266  if (use_messages_ && now - last_publish_time_ < period_) {
267  ROS_DEBUG("to reduce load, ignoring image");
268  return;
269  }
270  in_times.push_front((now - last_subscribe_time_).toSec());
271  in_bytes.push_front(img->data.size());
272 
273  try {
274  sensor_msgs::ImagePtr dst_img;
275  sensor_msgs::CameraInfo dst_info;
276  process(img, info, dst_img, dst_info);
277 
278 
279  if (use_camera_info_) {
280  cp_.publish(dst_img,
281  boost::make_shared<sensor_msgs::CameraInfo> (dst_info));
282  }
283  else {
284  image_pub_.publish(dst_img);
285  }
286 
287  // TODO: it does not support dst_width_ and dst_height_
288  std_msgs::Float32 width_scale;
289  width_scale.data = resize_x_;
290  std_msgs::Float32 height_scale;
291  height_scale.data = resize_y_;
292  width_scale_pub_.publish(width_scale);
293  height_scale_pub_.publish(height_scale);
294 
295  out_times.push_front((now - last_publish_time_).toSec());
296  out_bytes.push_front(dst_img->step * dst_img->height);
297 
298  last_publish_time_ = now;
299  }
300  catch (cv::Exception& e) {
301  ROS_ERROR("%s", e.what());
302  }
303 
304  last_subscribe_time_ = now;
305 
306  if (use_snapshot_) {
307  publish_once_ = false;
308  }
309  }
310 }
311 
Subscriber subscribe(const std::string &base_topic, uint32_t queue_size, const boost::function< void(const sensor_msgs::ImageConstPtr &)> &callback, const ros::VoidPtr &tracked_object=ros::VoidPtr(), const TransportHints &transport_hints=TransportHints())
image_transport::CameraPublisher advertiseCamera(ros::NodeHandle &nh, image_transport::ImageTransport &it, const std::string &topic, int queue_size)
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
void callback(const sensor_msgs::ImageConstPtr &img, const sensor_msgs::CameraInfoConstPtr &info)
jsk_topic_tools::VitalChecker::Ptr info_vital_
void publish(const boost::shared_ptr< M > &message) const
img
boost::circular_buffer< double > in_times
bool snapshot_srv_cb(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
virtual void process(const sensor_msgs::ImageConstPtr &src_img, const sensor_msgs::CameraInfoConstPtr &src_info, sensor_msgs::ImagePtr &dst_img, sensor_msgs::CameraInfo &dst_info)=0
void summary(unsigned char lvl, const std::string s)
CameraSubscriber subscribeCamera(const std::string &base_topic, uint32_t queue_size, const CameraSubscriber::Callback &callback, const ros::VoidPtr &tracked_object=ros::VoidPtr(), const TransportHints &transport_hints=TransportHints())
uint32_t getNumSubscribers() const
void image_nonsync_cb(const sensor_msgs::ImageConstPtr &img)
void info_cb(const sensor_msgs::CameraInfoConstPtr &info)
boost::circular_buffer< double > out_times
boost::circular_buffer< double > in_bytes
jsk_topic_tools::VitalChecker::Ptr image_vital_
void image_cb(const sensor_msgs::ImageConstPtr &img)
virtual void updateDiagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
#define NODELET_WARN_THROTTLE(rate,...)
boost::shared_ptr< ros::NodeHandle > pnh_
std::string getTopic() const
void snapshot_msg_cb(const std_msgs::EmptyConstPtr msg)
boost::circular_buffer< double > out_bytes
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
IMAGE_TRANSPORT_DECL std::string getCameraInfoTopic(const std::string &base_topic)
#define NODELET_INFO(...)
uint32_t getNumSubscribers() const
static Time now()
void add(const std::string &key, const T &val)
boost::shared_ptr< ros::NodeHandle > nh_
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


resized_image_transport
Author(s): Yohei Kakiuchi
autogenerated on Mon May 3 2021 03:03:39