2727
2828#include < fl/util/profiling.hpp>
2929
30+ #include < ros/ros.h>
31+ #include < sensor_msgs/JointState.h>
3032#include < sensor_msgs/Image.h>
33+ #include < sensor_msgs/fill_image.h>
34+ #include < sensor_msgs/distortion_models.h>
35+ #include < image_transport/image_transport.h>
3136
3237#include < dbot/camera_data.hpp>
3338#include < dbot/object_model.hpp>
@@ -71,19 +76,31 @@ class RobotEmulator
7176 dilation_(dilation),
7277 image_publishing_delay_(image_publishing_delay),
7378 image_timestamp_delay_(image_timestamp_delay),
74- paused_(false )
79+ paused_(false ),
80+ node_handle_(" ~" )
7581 {
82+ std::string prefix = " " ;
83+
7684 robot_publisher_ = std::make_shared<RobotPublisher<State>>(
77- urdf_kinematics_, " " , " " );
85+ urdf_kinematics_, prefix, " " );
86+
87+ // camera publisher
88+ pub_camera_info_ = node_handle_.advertise <sensor_msgs::CameraInfo>(
89+ prefix + " /XTION/depth/camera_info" , 0 );
90+ boost::shared_ptr<image_transport::ImageTransport> it (
91+ new image_transport::ImageTransport (node_handle_));
92+ pub_depth_image_ = it->advertise (prefix + " /XTION/depth/image" , 0 );
93+
94+
7895 }
7996
8097 void run ()
8198 {
8299 running_ = true ;
83100 joint_sensor_thread_ =
84- std::thread (&RobotEmulator::run_joint_sensors, this );
101+ std::thread (&RobotEmulator::run_joint_sensors, this );
85102 visual_sensor_thread_ =
86- std::thread (&RobotEmulator::run_visual_sensors, this );
103+ std::thread (&RobotEmulator::run_visual_sensors, this );
87104 }
88105
89106 void pause () { paused_ = true ; }
@@ -138,41 +155,42 @@ class RobotEmulator
138155
139156 Eigen::VectorXd depth_image;
140157 renderer_->Render (
141- state, depth_image, std::numeric_limits<double >::quiet_NaN ());
158+ state, depth_image, std::numeric_limits<double >::quiet_NaN ());
142159
143160 auto end = std::chrono::system_clock::now ();
144161 auto elapsed_time =
145- std::chrono::duration<double >(end - start).count ();
162+ std::chrono::duration<double >(end - start).count ();
146163
147164 // publish in parallel
148165 std::thread (
149- [state,
150- timestamp,
151- elapsed_time,
152- depth_image,
153- image_publishing_delay_,
154- &publisher_mutex_,
155- &camera_data_,
156- &robot_publisher_]()
157- {
158- double remaining_delay =
166+ [state,
167+ timestamp,
168+ elapsed_time,
169+ depth_image,
170+ image_publishing_delay_,
171+ &publisher_mutex_,
172+ &camera_data_,
173+ &robot_publisher_,
174+ this ]()
175+ {
176+ double remaining_delay =
159177 std::max (image_publishing_delay_ - elapsed_time, 0.0 );
160178
161- ROS_INFO_STREAM (" Visual simulation computation delay "
162- << elapsed_time);
179+ ROS_INFO_STREAM (" Visual simulation computation delay "
180+ << elapsed_time);
163181
164- std::this_thread::sleep_for (
165- std::chrono::duration<double >(remaining_delay));
182+ std::this_thread::sleep_for (
183+ std::chrono::duration<double >(remaining_delay));
166184
167- std::lock_guard<std::mutex> publisher_lock (
168- publisher_mutex_);
169- robot_publisher_ ->publish_camera_info (camera_data_,
170- ros::Time (timestamp));
171- robot_publisher_ ->publish_image (
172- depth_image, camera_data_, ros::Time (timestamp));
185+ std::lock_guard<std::mutex> publisher_lock (
186+ publisher_mutex_);
187+ this ->publish_camera_info (camera_data_,
188+ ros::Time (timestamp));
189+ this ->publish_image (
190+ depth_image, camera_data_, ros::Time (timestamp));
173191
174- })
175- .detach ();
192+ })
193+ .detach ();
176194 }
177195 }
178196
@@ -202,6 +220,115 @@ class RobotEmulator
202220 // }
203221
204222private:
223+
224+
225+
226+ void convert_to_depth_image_msg (
227+ const std::shared_ptr<dbot::CameraData>& camera_data,
228+ const Eigen::VectorXd& depth_image,
229+ sensor_msgs::Image& image)
230+ {
231+ Eigen::VectorXf float_vector = depth_image.cast <float >();
232+
233+ sensor_msgs::fillImage (image,
234+ sensor_msgs::image_encodings::TYPE_32FC1,
235+ camera_data->resolution ().height ,
236+ camera_data->resolution ().width ,
237+ camera_data->resolution ().width * sizeof (float ),
238+ float_vector.data ());
239+ }
240+
241+
242+
243+ bool has_image_subscribers () const
244+ {
245+ return pub_depth_image_.getNumSubscribers () > 0 ;
246+ }
247+
248+
249+ void publish_image (
250+ const Eigen::VectorXd& depth_image,
251+ const std::shared_ptr<dbot::CameraData>& camera_data,
252+ const ros::Time& time)
253+ {
254+ if (pub_depth_image_.getNumSubscribers () > 0 )
255+ {
256+ sensor_msgs::Image ros_image;
257+ convert_to_depth_image_msg (camera_data, depth_image, ros_image);
258+
259+ ros_image.header .frame_id = camera_data->frame_id ();
260+ ros_image.header .stamp = time;
261+ pub_depth_image_.publish (ros_image);
262+ }
263+ }
264+
265+
266+ void publish_camera_info (
267+ const std::shared_ptr<dbot::CameraData>& camera_data,
268+ const ros::Time& time)
269+ {
270+ auto camera_info = create_camera_info (camera_data, time);
271+ pub_camera_info_.publish (camera_info);
272+ }
273+
274+
275+ sensor_msgs::CameraInfoPtr create_camera_info (
276+ const std::shared_ptr<dbot::CameraData>& camera_data,
277+ const ros::Time& time)
278+ {
279+ sensor_msgs::CameraInfoPtr info_msg =
280+ boost::make_shared<sensor_msgs::CameraInfo>();
281+
282+ info_msg->header .stamp = time;
283+ // if internal registration is used, rgb camera intrinsic parameters are
284+ // used
285+ info_msg->header .frame_id = camera_data->frame_id ();
286+ info_msg->width = camera_data->native_resolution ().width ;
287+ info_msg->height = camera_data->native_resolution ().height ;
288+
289+ #if ROS_VERSION_MINIMUM(1, 3, 0)
290+ info_msg->D = std::vector<double >(5 , 0.0 );
291+ info_msg->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
292+ #else
293+ info_msg->D .assign (0.0 );
294+ #endif
295+ info_msg->K .assign (0.0 );
296+ info_msg->R .assign (0.0 );
297+ info_msg->P .assign (0.0 );
298+
299+ auto camera_matrix = camera_data->camera_matrix ();
300+ camera_matrix.topLeftCorner (2 , 3 ) *=
301+ double (camera_data->downsampling_factor ());
302+
303+ for (size_t col = 0 ; col < 3 ; col++)
304+ for (size_t row = 0 ; row < 3 ; row++)
305+ info_msg->K [col + row * 3 ] = camera_matrix (row, col);
306+
307+ // no rotation: identity
308+ info_msg->R [0 ] = info_msg->R [4 ] = info_msg->R [8 ] = 1.0 ;
309+ // no rotation, no translation => P=K(I|0)=(K|0)
310+ info_msg->P [0 ] = info_msg->P [5 ] = info_msg->K [0 ];
311+ info_msg->P [2 ] = info_msg->K [2 ];
312+ info_msg->P [6 ] = info_msg->K [5 ];
313+ info_msg->P [10 ] = 1.0 ;
314+
315+ return info_msg;
316+ }
317+
318+
319+
320+
321+
322+
323+
324+
325+
326+
327+
328+
329+
330+
331+
205332 double time_;
206333 Eigen::VectorXd state_;
207334 // Eigen::VectorXd obsrv_vector_;
@@ -225,5 +352,10 @@ class RobotEmulator
225352 std::thread joint_sensor_thread_;
226353 std::thread visual_sensor_thread_;
227354 bool paused_;
355+
356+
357+ ros::NodeHandle node_handle_;
358+ ros::Publisher pub_camera_info_;
359+ image_transport::Publisher pub_depth_image_;
228360};
229361}
0 commit comments