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>
9#include <yarp/os/LogStream.h>
10#include "rosPixelCode.h"
14
15using namespace RGBDToPointCloudImpl;
16using namespace yarp::sig;
17using namespace yarp::dev;
18using namespace yarp::os;
19
20YARP_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
94bool 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
201bool 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);
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:88
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:23
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:23
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:33
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:63
void write(bool forceStrict=false)
Write the current object being returned by Publisher::prepare.
Definition: Publisher.h:148
T & prepare()
Access the object which will be transmitted by the next call to yarp::os::Publisher::write.
Definition: Publisher.h:123
A base class for nested structures that can be searched.
Definition: Searchable.h:63
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.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:21
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:163
void setExternal(const void *data, size_t imgWidth, size_t imgHeight)
Use this to wrap an external image.
Definition: Image.cpp:904
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:542
size_t height() const
Gets height of image in pixels.
Definition: Image.h:169
virtual size_t width() const
virtual bool isDense() const
virtual size_t height() const
The PointCloud class.
Definition: PointCloud.h:22
const char * getRawData() const override
Get the pointer to the data.
Definition: PointCloud.h:80
size_t dataSizeBytes() const override
Get the size of the data in terms of number of bytes.
Definition: PointCloud.h:100
#define yCInfo(component,...)
Definition: LogComponent.h:171
#define yCError(component,...)
Definition: LogComponent.h:213
#define yCTrace(component,...)
Definition: LogComponent.h:84
#define yCWarning(component,...)
Definition: LogComponent.h:192
#define yCDebug(component,...)
Definition: LogComponent.h:128
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:76
For streams capable of holding different kinds of content, check what they actually have.
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...
The IntrinsicParams struct to handle the intrinsic parameter of cameras(RGB and RGBD either).
Packed RGB pixel type.
Definition: Image.h:460