YARP
Yet Another Robot Platform
RGBDToPointCloudSensor_nws_ros.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
7 #include <sstream>
8 #include <yarp/os/LogComponent.h>
9 #include <yarp/os/LogStream.h>
10 #include "rosPixelCode.h"
14 
15 using namespace RGBDToPointCloudImpl;
16 using namespace yarp::sig;
17 using namespace yarp::dev;
18 using namespace yarp::os;
19 
20 YARP_LOG_COMPONENT(RGBDTOPOINTCLOUDSENSORNWSROS, "yarp.devices.RGBDToPointCloudSensor_nws_ros");
21 
24 {
25 }
26 
27 
28 /* destructor of the wrapper */
30 {
31  close();
32 }
33 
37 {
38  // check period
39  if (!config.check("period", "refresh period of the broadcasted values in s")) {
40  if(verbose >= 3) {
41  yCInfo(RGBDTOPOINTCLOUDSENSORNWSROS) << "Using default 'period' parameter of " << DEFAULT_THREAD_PERIOD << "s";
42  }
43  }
44  else {
45  period = config.find("period").asFloat64();
46  }
47 
48  // nodename parameter
49  if (!config.check("node_name", "the name of the ros node")) {
50  yCError(RGBDTOPOINTCLOUDSENSORNWSROS) << "missing node_name parameter";
51  return false;
52  }
53  nodeName = config.find("node_name").asString();
54 
55 
56  // baseTopicName parameter
57  if (!config.check("topic_name", "the name of the ros node")) {
58  yCError(RGBDTOPOINTCLOUDSENSORNWSROS) << "missing topic_name parameter, using default one";
59  return false;
60  }
61  pointCloudTopicName = config.find("topic_name").asString();
62 
63  // frame_id parameter
64  if (!config.check("frame_id", "the name of the ros node")) {
65  yCError(RGBDTOPOINTCLOUDSENSORNWSROS) << "missing frame_id parameter";
66  return false;
67  }
68  frameId = config.find("frame_id").asString();
69 
70  // open topics here if needed
71  m_node = new yarp::os::Node(nodeName);
72  nodeSeq = 0;
73  if (!publisherPort_pointCloud.topic(pointCloudTopicName))
74  {
75  yCError(RGBDTOPOINTCLOUDSENSORNWSROS) << "Unable to publish data on " << pointCloudTopicName.c_str() << " topic, check your yarp-ROS network configuration";
76  return false;
77  }
78 
79  // check if we need to create subdevice or if they are
80  // passed later on through attachAll()
81  if(config.check("subdevice")) {
82  if(! openAndAttachSubDevice(config))
83  {
84  yCError(RGBDTOPOINTCLOUDSENSORNWSROS, "Error while opening subdevice");
85  return false;
86  }
87  isSubdeviceOwned=true;
88  } else {
89  isSubdeviceOwned=false;
90  }
91  return true;
92 }
93 
94 bool RGBDToPointCloudSensor_nws_ros::openAndAttachSubDevice(Searchable& prop)
95 {
96  Property p;
97  subDeviceOwned = new PolyDriver;
98  p.fromString(prop.toString());
99 
100  p.setMonitor(prop.getMonitor(), "subdevice"); // pass on any monitoring
101  p.unput("device");
102  p.put("device",prop.find("subdevice").asString()); // subdevice was already checked before
103 
104  // if errors occurred during open, quit here.
105  yCDebug(RGBDTOPOINTCLOUDSENSORNWSROS, "Opening IRGBDSensor subdevice");
106  subDeviceOwned->open(p);
107 
108  if (!subDeviceOwned->isValid())
109  {
110  yCError(RGBDTOPOINTCLOUDSENSORNWSROS, "Opening IRGBDSensor subdevice... FAILED");
111  return false;
112  }
113  isSubdeviceOwned = true;
114  if(!attach(subDeviceOwned)) {
115  return false;
116  }
117 
118  return true;
119 }
120 
122 {
124  detach();
125 
126  // close subdevice if it was created inside the open (--subdevice option)
127  if(isSubdeviceOwned)
128  {
129  if(subDeviceOwned)
130  {
131  delete subDeviceOwned;
132  subDeviceOwned=nullptr;
133  }
134  sensor_p = nullptr;
135  fgCtrl = nullptr;
136  isSubdeviceOwned = false;
137  }
138 
139  if(m_node !=nullptr)
140  {
141  m_node->interrupt();
142  delete m_node;
143  m_node = nullptr;
144  }
145 
146  return true;
147 }
148 
154 {
156  {
158  }
159 
160  //check if we already instantiated a subdevice previously
161  if (isSubdeviceOwned)
162  {
163  return false;
164  }
165  sensor_p = nullptr;
166  return true;
167 }
168 
170 {
171  if(poly)
172  {
173  poly->view(sensor_p);
174  poly->view(fgCtrl);
175  }
176 
177  if(sensor_p == nullptr)
178  {
179  yCError(RGBDTOPOINTCLOUDSENSORNWSROS) << "Attached device has no valid IRGBDSensor interface.";
180  return false;
181  }
182 
183  PeriodicThread::setPeriod(period);
184  return PeriodicThread::start();
185 }
186 
187 /* IRateThread interface */
188 
190 {
191  // Get interface from attached device if any.
192  return true;
193 }
194 
196 {
197  // Detach() calls stop() which in turns calls this functions, therefore no calls to detach here!
198 }
199 
200 
201 bool RGBDToPointCloudSensor_nws_ros::writeData()
202 {
203  //colorImage.setPixelCode(VOCAB_PIXEL_RGB);
204  // depthImage.setPixelCode(VOCAB_PIXEL_MONO_FLOAT);
205 
206  // colorImage.resize(hDim, vDim); // Has this to be done each time? If size is the same what it does?
207  // depthImage.resize(hDim, vDim);
208  if (!sensor_p->getImages(colorImage, depthImage, &colorStamp, &depthStamp))
209  {
210  return false;
211  }
212 
213  static Stamp oldColorStamp = Stamp(0, 0);
214  static Stamp oldDepthStamp = Stamp(0, 0);
215  yarp::os::Property propIntrinsic;
216  bool rgb_data_ok = true;
217  bool depth_data_ok = true;
218 
219  if ((colorStamp.getTime() - oldColorStamp.getTime()) <= 0)
220  {
221  rgb_data_ok=false;
222  //return true;
223  }
224  else { oldColorStamp = colorStamp; }
225 
226  if ((depthStamp.getTime() - oldDepthStamp.getTime()) <= 0)
227  {
228  depth_data_ok=false;
229  //return true;
230  }
231  else { oldDepthStamp = depthStamp; }
232  bool intrinsic_ok = sensor_p->getRgbIntrinsicParam(propIntrinsic);
233 
234 
235  // TBD: We should check here somehow if the timestamp was correctly updated and, if not, update it ourselves.
236  if (rgb_data_ok)
237  {
238  if (depth_data_ok)
239  {
240  if (intrinsic_ok)
241  {
242  yarp::sig::IntrinsicParams intrinsics(propIntrinsic);
243  yarp::sig::ImageOf<yarp::sig::PixelRgb> colorImagePixelRGB;
244  colorImagePixelRGB.setExternal(colorImage.getRawImage(), colorImage.width(), colorImage.height());
245  // create point cloud in yarp format
248  colorImagePixelRGB,
249  intrinsics,
251  PointCloud2Type& pc2Ros = publisherPort_pointCloud.prepare();
252  // filling ros header
254  headerRos.clear();
255  headerRos.seq = nodeSeq;
256  headerRos.frame_id = frameId;
257  headerRos.stamp = depthStamp.getTime();
258 
259  // filling ros point field
260  std::vector<yarp::rosmsg::sensor_msgs::PointField> pointFieldRos;
261  pointFieldRos.push_back(yarp::rosmsg::sensor_msgs::PointField());
262  pointFieldRos.push_back(yarp::rosmsg::sensor_msgs::PointField());
263  pointFieldRos.push_back(yarp::rosmsg::sensor_msgs::PointField());
264  pointFieldRos.push_back(yarp::rosmsg::sensor_msgs::PointField());
265  pointFieldRos[0].name = "x";
266  pointFieldRos[0].offset = 0;
267  pointFieldRos[0].datatype = 7;
268  pointFieldRos[0].count = 1;
269  pointFieldRos[1].name = "y";
270  pointFieldRos[1].offset = 4;
271  pointFieldRos[1].datatype = 7;
272  pointFieldRos[1].count = 1;
273  pointFieldRos[2].name = "z";
274  pointFieldRos[2].offset = 8;
275  pointFieldRos[2].datatype = 7;
276  pointFieldRos[2].count = 1;
277  pointFieldRos[3].name = "rgb";
278  pointFieldRos[3].offset = 16;
279  pointFieldRos[3].datatype = 7;
280  pointFieldRos[3].count = 1;
281  pc2Ros.fields = pointFieldRos;
282 
283  std::vector<unsigned char> vec(yarpCloud.getRawData(), yarpCloud.getRawData() + yarpCloud.dataSizeBytes() );
284  pc2Ros.data = vec;
285  pc2Ros.header = headerRos;
286  pc2Ros.width = yarpCloud.width() * yarpCloud.height();
287  pc2Ros.height = 1;
288  pc2Ros.is_dense = yarpCloud.isDense();
289 
290  pc2Ros.point_step = sizeof (yarp::sig::DataXYZRGBA);
291  pc2Ros.row_step = static_cast<std::uint32_t> (sizeof (yarp::sig::DataXYZRGBA) * pc2Ros.width);
292 
293  publisherPort_pointCloud.write();
294  }
295  }
296  }
297 
298  nodeSeq++;
299 
300  return true;
301 }
302 
304 {
305  if (sensor_p!=nullptr)
306  {
307  static int i = 0;
308  sensorStatus = sensor_p->getSensorStatus();
309  switch (sensorStatus)
310  {
311  case(IRGBDSensor::RGBD_SENSOR_OK_IN_USE) :
312  {
313  if (!writeData()) {
314  yCError(RGBDTOPOINTCLOUDSENSORNWSROS, "Image not captured.. check hardware configuration");
315  }
316  i = 0;
317  }
318  break;
319  case(IRGBDSensor::RGBD_SENSOR_NOT_READY):
320  {
321  if(i < 1000) {
322  if((i % 30) == 0) {
323  yCInfo(RGBDTOPOINTCLOUDSENSORNWSROS) << "Device not ready, waiting...";
324  }
325  } else {
326  yCWarning(RGBDTOPOINTCLOUDSENSORNWSROS) << "Device is taking too long to start..";
327  }
328  i++;
329  }
330  break;
331  default:
332  {
333  if (verbose >= 1) { // better not to print it every cycle anyway, too noisy
334  yCError(RGBDTOPOINTCLOUDSENSORNWSROS, "%s: Sensor returned error", nodeName.c_str());
335  }
336  }
337  }
338  }
339  else
340  {
341  if(verbose >= 6) {
342  yCError(RGBDTOPOINTCLOUDSENSORNWSROS, "%s: Sensor interface is not valid", nodeName.c_str());
343  }
344  }
345 }
const yarp::os::LogComponent & RGBDTOPOINTCLOUDSENSORNWSROS()
constexpr double DEFAULT_THREAD_PERIOD
bool open(yarp::os::Searchable &params) override
Device driver interface.
bool attach(yarp::dev::PolyDriver *poly) override
Specify which sensor this thread has to read from.
void threadRelease() override
Release method.
bool threadInit() override
Initialization method.
bool close() override
Close the DeviceDriver.
bool detach() override
WrapperSingle interface.
bool view(T *&x)
Get an interface to the device driver.
Definition: DeviceDriver.h:74
bool getRgbIntrinsicParam(yarp::os::Property &intrinsic) override=0
Get the intrinsic parameters of the rgb camera.
virtual bool getImages(yarp::sig::FlexImage &colorFrame, yarp::sig::ImageOf< yarp::sig::PixelFloat > &depthFrame, yarp::os::Stamp *colorStamp=nullptr, yarp::os::Stamp *depthStamp=nullptr)=0
Get the both the color and depth frame in a single call.
virtual RGBDSensor_status getSensorStatus()=0
Get the surrent status of the sensor, using enum type.
A container for a device driver.
Definition: PolyDriver.h:24
bool isValid() const
Check if device is valid.
Definition: PolyDriver.cpp:196
bool open(const std::string &txt)
Construct and configure a device by its common name.
Definition: PolyDriver.cpp:140
The Node class.
Definition: Node.h:24
void interrupt()
interrupt delegates the call to the Node port interrupt.
Definition: Node.cpp:597
An abstraction for a periodic thread.
bool isRunning() const
Returns true when the thread is started, false otherwise.
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
A class for storing options and configuration information.
Definition: Property.h:34
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1063
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:1015
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
Definition: Property.cpp:1046
bool topic(const std::string &name)
Set topic to publish to.
Definition: Publisher.h:64
T & prepare()
Access the object which will be transmitted by the next call to yarp::os::Publisher::write.
Definition: Publisher.h:124
void write(bool forceStrict=false)
Write the current object being returned by Publisher::prepare.
Definition: Publisher.h:149
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:22
double getTime() const
Get the time stamp.
Definition: Stamp.cpp:34
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
yarp::rosmsg::TickTime stamp
Definition: Header.h:45
size_t width() const
Gets width of image in pixels.
Definition: Image.h:166
void setExternal(const void *data, size_t imgWidth, size_t imgHeight)
Use this to wrap an external image.
Definition: Image.cpp:903
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:541
size_t height() const
Gets height of image in pixels.
Definition: Image.h:172
virtual size_t width() const
virtual bool isDense() const
virtual size_t height() const
The PointCloud class.
Definition: PointCloud.h:24
const char * getRawData() const override
Get the pointer to the data.
Definition: PointCloud.h:82
size_t dataSizeBytes() const override
Get the size of the data in terms of number of bytes.
Definition: PointCloud.h:102
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCTrace(component,...)
Definition: LogComponent.h:85
#define yCWarning(component,...)
Definition: LogComponent.h:143
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
An interface to the operating system, including Port based communication.
yarp::sig::PointCloud< T1 > depthRgbToPC(const yarp::sig::ImageOf< yarp::sig::PixelFloat > &depth, const yarp::sig::ImageOf< T2 > &color, const yarp::sig::IntrinsicParams &intrinsic, const yarp::sig::utils::OrganizationType organizationType=yarp::sig::utils::OrganizationType::Organized)
depthRgbToPC, compute the colored PointCloud given depth image, color image and the intrinsic paramet...
Signal processing.
Definition: Image.h:22
The IntrinsicParams struct to handle the intrinsic parameter of cameras(RGB and RGBD either).
Packed RGB pixel type.
Definition: Image.h:464