gazebo_noisydepth_plugin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Michael Pantic, ASL, ETH Zurich, Switzerland
3  *
4  * Forked from Openni/Kinect Depth Plugin, retaining original copyright header:
5  * Copyright 2013 Open Source Robotics Foundation
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *
20  * Desc: GazeboNoisyDepth plugin for simulating cameras in Gazebo
21  * Author: Michael Pantic / John Hsu (original Depth Plugin)
22  * Date: 03 Dez 18
23  */
25 
26 #include <algorithm>
27 #include <assert.h>
28 
29 #include <boost/bind.hpp>
30 #include <boost/thread/thread.hpp>
31 #include <gazebo/sensors/Sensor.hh>
32 #include <gazebo/sensors/SensorTypes.hh>
33 #include <sdf/sdf.hh>
34 #include <tf/tf.h>
35 
36 namespace gazebo {
37 // Register this plugin with the simulator
38 GZ_REGISTER_SENSOR_PLUGIN(GazeboNoisyDepth)
39 
41  this->depth_info_connect_count_ = 0;
42  this->depth_image_connect_count_ = 0;
43  this->last_depth_image_camera_info_update_time_ = common::Time(0);
44 }
45 
47 
48 void GazeboNoisyDepth::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf) {
49  DepthCameraPlugin::Load(_parent, _sdf);
50 
51  // copying from DepthCameraPlugin into GazeboRosCameraUtils
52  this->parentSensor_ = this->parentSensor;
53  this->width_ = this->width;
54  this->height_ = this->height;
55  this->depth_ = this->depth;
56  this->format_ = this->format;
57  this->camera_ = this->depthCamera;
58 
59  // using a different default
60  if (!_sdf->HasElement("imageTopicName")) {
61  this->image_topic_name_ = "ir/image_raw";
62  }
63 
64  if (!_sdf->HasElement("cameraInfoTopicName")) {
65  this->camera_info_topic_name_ = "ir/camera_info";
66  }
67 
68  // depth image stuff
69  if (!_sdf->HasElement("depthImageTopicName")) {
70  this->depth_image_topic_name_ = "depth/image_raw";
71  } else {
73  _sdf->GetElement("depthImageTopicName")->Get<std::string>();
74  }
75 
76  if (!_sdf->HasElement("depthImageCameraInfoTopicName")) {
77  this->depth_image_camera_info_topic_name_ = "depth/camera_info";
78  } else {
80  _sdf->GetElement("depthImageCameraInfoTopicName")->Get<std::string>();
81  }
82 
83  // noise model stuff
84  std::string noise_model;
85  if (!_sdf->HasElement("depthNoiseModelName")) {
86  noise_model = "Kinect";
87  ROS_WARN_NAMED("NoisyDepth",
88  "depthNoiseModelName not defined, assuming 'Kinect'");
89  } else {
90  noise_model = _sdf->GetElement("depthNoiseModelName")->Get<std::string>();
91  }
92 
93  if (boost::iequals(noise_model, "Kinect")) {
94  this->noise_model.reset(new KinectDepthNoiseModel());
95 
96  /* no other properties for Kinect */
97  } else if(boost::iequals(noise_model, "PMD")) {
98  this->noise_model.reset(new PMDDepthNoiseModel());
99 
100  /* no other properties for PMD */
101  }
102 
103  else if (boost::iequals(noise_model, "D435")) {
105  this->noise_model.reset(model);
106 
107  if (_sdf->HasElement("horizontal_fov")) {
108  model->h_fov = _sdf->GetElement("horizontal_fov")->Get<float>();
109  }
110 
111  if (_sdf->HasElement("baseline")) {
112  model->baseline = _sdf->GetElement("baseline")->Get<float>();
113  }
114 
115  /* Load D435 specific noise params if available*/
116  if (_sdf->HasElement("D435NoiseSubpixelErr")) {
117  model->subpixel_err =
118  _sdf->GetElement("D435NoiseSubpixelErr")->Get<float>();
119  }
120 
121  if (_sdf->HasElement("D435MaxStdev")) {
122  model->max_stdev = _sdf->GetElement("D435MaxStdev")->Get<float>();
123  }
124 
126  "NoisyDepth", "D435 Depth noise configuration: "
127  << "\tHorizontal FoV: " << model->h_fov << std::endl
128  << "\tBaseline: " << model->baseline << std::endl
129  << "\tSubpixel Err: " << model->subpixel_err
130  << std::endl
131  << "\tNoise StDev cutoff: " << model->max_stdev);
132  } else {
133  ROS_WARN_NAMED("NoisyDepth",
134  "Invalid depthNoiseModelName (%s), assuming 'Kinect'",
135  noise_model.c_str());
136  this->noise_model.reset(new KinectDepthNoiseModel());
137  }
138 
139  /* Load properties that apply for all noise model */
140  /* Note that these min/max values may not be the same as near/far clip range
141  * of the camera */
142  if (_sdf->HasElement("depthNoiseMinDist")) {
143  this->noise_model->min_depth =
144  _sdf->GetElement("depthNoiseMinDist")->Get<float>();
145  }
146 
147  if (_sdf->HasElement("depthNoiseMaxDist")) {
148  this->noise_model->max_depth =
149  _sdf->GetElement("depthNoiseMaxDist")->Get<float>();
150  }
151 
153 
154  GazeboRosCameraUtils::Load(_parent, _sdf);
155 }
156 
158  ros::AdvertiseOptions depth_image_ao =
159  ros::AdvertiseOptions::create<sensor_msgs::Image>(
160  this->depth_image_topic_name_, 1,
161  boost::bind(&GazeboNoisyDepth::DepthImageConnect, this),
162  boost::bind(&GazeboNoisyDepth::DepthImageDisconnect, this),
163  ros::VoidPtr(), &this->camera_queue_);
164 
165  this->depth_image_pub_ = this->rosnode_->advertise(depth_image_ao);
166 
167  ros::AdvertiseOptions depth_image_camera_info_ao =
168  ros::AdvertiseOptions::create<sensor_msgs::CameraInfo>(
170  boost::bind(&GazeboNoisyDepth::DepthInfoConnect, this),
171  boost::bind(&GazeboNoisyDepth::DepthInfoDisconnect, this),
172  ros::VoidPtr(), &this->camera_queue_);
173 
174  this->depth_image_camera_info_pub_ = this->rosnode_->advertise(depth_image_camera_info_ao);
175 }
176 
179  this->parentSensor->SetActive(true);
180 }
181 
184 }
185 
188 }
189 
192 }
193 
194 void GazeboNoisyDepth::OnNewDepthFrame(const float *_image, unsigned int _width,
195  unsigned int _height,
196  unsigned int _depth,
197  const std::string &_format) {
198  if (!this->initialized_ || this->height_ <= 0 || this->width_ <= 0) return;
199 
200  this->depth_sensor_update_time_ = this->parentSensor->LastMeasurementTime();
201 
202  // check if there are subscribers, if not disable parent, else process images..
203  if (this->parentSensor->IsActive()) {
204  if (this->depth_image_connect_count_ <= 0 && (*this->image_connect_count_) <= 0) {
205  this->parentSensor->SetActive(false);
206  } else {
207  if (this->depth_image_connect_count_ > 0) this->FillDepthImage(_image);
208  }
209  }
210  else {
211  // if parent is disabled, but has subscribers, enable it.
212  if ((*this->image_connect_count_) > 0){
213  this->parentSensor->SetActive(true);
214  }
215  }
217 }
218 
219 void GazeboNoisyDepth::OnNewImageFrame(const unsigned char *_image,
220  unsigned int _width,
221  unsigned int _height,
222  unsigned int _depth,
223  const std::string &_format) {
224  if (!this->initialized_ || this->height_ <= 0 || this->width_ <= 0) return;
225 
226  this->sensor_update_time_ = this->parentSensor_->LastMeasurementTime();
227 
228  // check if there are subscribers, if not disable parent, else process images..
229  if (this->parentSensor->IsActive()) {
230  if (this->depth_image_connect_count_ <= 0 &&
231  (*this->image_connect_count_) <= 0) {
232  this->parentSensor->SetActive(false);
233  } else {
234  if ((*this->image_connect_count_) > 0) this->PutCameraData(_image);
235  }
236  } else {
237  if ((*this->image_connect_count_) > 0) {
238  // if parent is disabled, but has subscribers, enable it.
239  this->parentSensor->SetActive(true);
240  }
241  }
242 }
243 
244 void GazeboNoisyDepth::FillDepthImage(const float *_src) {
245  this->lock_.lock();
246  // copy data into image
247  this->depth_image_msg_.header.frame_id = this->frame_name_;
248  this->depth_image_msg_.header.stamp.sec = this->depth_sensor_update_time_.sec;
249  this->depth_image_msg_.header.stamp.nsec = this->depth_sensor_update_time_.nsec;
250 
251  // copy from depth to depth image message
252  if(FillDepthImageHelper(this->height, this->width,this->skip_, _src, &this->depth_image_msg_)){
254  }
255 
256  this->lock_.unlock();
257 }
258 
259 bool GazeboNoisyDepth::FillDepthImageHelper(const uint32_t rows_arg,
260  const uint32_t cols_arg,
261  const uint32_t step_arg,
262  const float *data_arg,
263  sensor_msgs::Image *image_msg) {
264  if(data_arg == nullptr){
265  ROS_WARN_NAMED("NoisyDepth", "Invalid data array received - nullptr.");
266  return false;
267  }
268 
269  image_msg->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
270  image_msg->height = rows_arg;
271  image_msg->width = cols_arg;
272  image_msg->step = sizeof(float) * cols_arg;
273  image_msg->data.resize(rows_arg * cols_arg * sizeof(float));
274  image_msg->is_bigendian = 0;
275 
276  float *dest = (float *)(&(image_msg->data[0]));
277  memcpy(dest, data_arg, sizeof(float) * width * height);
278 
279  noise_model->ApplyNoise(width, height, dest);
280 
281  return true;
282 }
283 
285 
286  // first publish parent camera info (ir camera)
288 
289  if (this->depth_info_connect_count_ > 0) {
290  this->sensor_update_time_ = this->parentSensor_->LastMeasurementTime();
291 #if GAZEBO_MAJOR_VERSION >= 8
292  common::Time cur_time = this->world_->SimTime();
293 #else
294  common::Time cur_time = this->world_->GetSimTime();
295 #endif
296 
297  if (this->sensor_update_time_ -
301  }
302  }
303 }
304 }
std::string format(const std::string &fmt, Args ... args)
virtual void OnNewImageFrame(const unsigned char *_image, unsigned int _width, unsigned int _height, unsigned int _depth, const std::string &_format)
virtual void Advertise()
Advertise depth image.
#define ROS_WARN_NAMED(name,...)
event::ConnectionPtr load_connection_
GZ_REGISTER_SENSOR_PLUGIN(GazeboGpsPlugin)
virtual void Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
Load the plugin.
void Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf, const std::string &_camera_name_suffix="")
void FillDepthImage(const float *_src)
#define ROS_INFO_STREAM_NAMED(name, args)
ros::CallbackQueue camera_queue_
physics::WorldPtr world_
boost::shared_ptr< int > image_connect_count_
void publish(const boost::shared_ptr< M > &message) const
event::ConnectionPtr OnLoad(const boost::function< void()> &)
const std::string TYPE_32FC1
common::Time last_depth_image_camera_info_update_time_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void PutCameraData(const unsigned char *_src)
rendering::CameraPtr camera_
std::unique_ptr< DepthNoiseModel > noise_model
ros::NodeHandle * rosnode_
bool FillDepthImageHelper(const uint32_t rows_arg, const uint32_t cols_arg, const uint32_t step_arg, const float *data_arg, sensor_msgs::Image *image_msg)
sensors::SensorPtr parentSensor_
virtual void OnNewDepthFrame(const float *_image, unsigned int _width, unsigned int _height, unsigned int _depth, const std::string &_format)
boost::shared_ptr< void > VoidPtr


rotors_gazebo_plugins
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Mon Feb 28 2022 23:39:03