YARP
Yet Another Robot Platform
RGBDSensorClient.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
9 #include "RGBDSensorClient.h"
11 #include <yarp/os/Portable.h>
12 #include <yarp/os/LogComponent.h>
13 #include <yarp/os/LogStream.h>
14 #include <yarp/dev/GenericVocabs.h>
15 
16 using namespace yarp::os;
17 using namespace yarp::sig;
18 using namespace yarp::dev;
19 
20 #define RGBD_INTERFACE_PROTOCOL_VERSION_MAJOR 1
21 #define RGBD_INTERFACE_PROTOCOL_VERSION_MINOR 0
22 
23 YARP_LOG_COMPONENT(RGBDSENSORCLIENT, "yarp.devices.RGBDSensorClient")
24 
25 
28  RgbMsgSender(new Implement_RgbVisualParams_Sender(rpcPort)),
29  DepthMsgSender(new Implement_DepthVisualParams_Sender(rpcPort)),
30  streamingReader(new RGBDSensor_StreamingMsgParser)
31 {
32 }
33 
35 {
36  close();
37  delete RgbMsgSender;
38  delete DepthMsgSender;
39  delete streamingReader;
40 }
41 
43 {
44  if(verbose >= 5)
45  yCTrace(RGBDSENSORCLIENT) << "\n Paramerters are: \n" << config.toString();
46 
47  if(!fromConfig(config))
48  {
49  yCError(RGBDSENSORCLIENT) << "Device RGBDSensorClient failed to open, check previous log for error messages.";
50  return false;
51  }
52 
53  sensorId= "RGBDSensorClient for " + local_depthFrame_StreamingPort_name;
54 
55  if(!initialize_YARP(config) )
56  {
57  yCError(RGBDSENSORCLIENT) << sensorId << "\n\t* Error initializing YARP ports *";
58  return false;
59  }
60 
61  if(!initialize_ROS(config) )
62  {
63  yCError(RGBDSENSORCLIENT) << sensorId << "\n\t* Error initializing ROS topic *";
64  return false;
65  }
66  return true;
67 }
68 
69 
71 {
72  Bottle &rosGroup = config.findGroup("ROS");
73  if(rosGroup.isNull())
74  {
75  if(verbose >= 3)
76  yCInfo(RGBDSENSORCLIENT) << "RGBDSensorClient: ROS configuration parameters are not set, skipping ROS topic initialization.";
77  use_ROS = false;
78  }
79  else
80  {
81  if(verbose >= 2)
82  yCWarning(RGBDSENSORCLIENT) << "RGBDSensorClient: ROS topic support is not yet implemented";
83  use_ROS = false;
84  }
85 
86  if(!use_ROS) // default
87  {
88  // Parse LOCAL port names
89  // TBD: check if user types '...' as port name, how to create RPC port names
90  if (!config.check("localImagePort", "full name of the port for streaming color image"))
91  {
92  yCError(RGBDSENSORCLIENT) << "RGBDSensorClient: missing 'localImagePort' parameter. Check you configuration file; it must be like:";
93  yCError(RGBDSENSORCLIENT) << " localImagePort: Full name of the local port to open, e.g. /myApp/image_camera";
94  return false;
95  }
96  else
97  {
98  local_colorFrame_StreamingPort_name = config.find("localImagePort").asString();
99  }
100 
101  if (!config.check("localDepthPort", "full name of the port for streaming depth image"))
102  {
103  yCError(RGBDSENSORCLIENT) << "RGBDSensorClient: missing 'localDepthPort' parameter. Check you configuration file; it must be like:";
104  yCError(RGBDSENSORCLIENT) << " localDepthPort: Full name of the local port to open, e.g. /myApp/depth_camera";
105  return false;
106  }
107  else
108  {
109  local_depthFrame_StreamingPort_name = config.find("localDepthPort").asString();
110  }
111 
112  // Parse REMOTE port names
113  if (!config.check("remoteImagePort", "full name of the port for streaming color image"))
114  {
115  yCError(RGBDSENSORCLIENT) << "RGBDSensorClient: missing 'remoteImagePort' parameter. Check you configuration file; it must be like:";
116  yCError(RGBDSENSORCLIENT) << " remoteImagePort: Full name of the port to read color images from, e.g. /robotName/image_camera";
117  return false;
118  }
119  else
120  {
121  remote_colorFrame_StreamingPort_name = config.find("remoteImagePort").asString();
122  }
123 
124  if (!config.check("remoteDepthPort", "full name of the port for streaming depth image"))
125  {
126  yCError(RGBDSENSORCLIENT) << "RGBDSensorClient: missing 'remoteDepthPort' parameter. Check you configuration file; it must be like:";
127  yCError(RGBDSENSORCLIENT) << " remoteDepthPort: Full name of the port to read depth images from, e.g. /robotName/depth_camera ";
128  return false;
129  }
130  else
131  {
132  remote_depthFrame_StreamingPort_name = config.find("remoteDepthPort").asString();
133  }
134 
135  // Single RPC port
136  if (!config.check("localRpcPort", "full name of the port for streaming depth image"))
137  {
138  yCError(RGBDSENSORCLIENT) << "RGBDSensorClient: missing 'localRpcPort' parameter. Check you configuration file; it must be like:";
139  yCError(RGBDSENSORCLIENT) << " localRpcPort: Full name of the local RPC port to open, e.g. /myApp/RGBD/rpc";
140  return false;
141  }
142  else
143  {
144  local_rpcPort_name = config.find("localRpcPort").asString();
145  }
146 
147  if (!config.check("remoteRpcPort", "full name of the port for streaming depth image"))
148  {
149  yCError(RGBDSENSORCLIENT) << "RGBDSensorClient: missing 'remoteRpcPort' parameter. Check you configuration file; it must be like:";
150  yCError(RGBDSENSORCLIENT) << " remoteRpcPort: Full name of the remote RPC port, e.g. /robotName/RGBD/rpc";
151  return false;
152  }
153  else
154  {
155  remote_rpcPort_name = config.find("remoteRpcPort").asString();
156  }
157 
158  image_carrier_type = "udp";
159  depth_carrier_type = "udp";
160 
161  if (config.check("ImageCarrier", "carrier for the image stream"))
162  {
163  image_carrier_type = config.find("ImageCarrier").asString();
164  }
165 
166  if (config.check("DepthCarrier", "carrier for the depth tream"))
167  {
168  depth_carrier_type = config.find("DepthCarrier").asString();
169  }
170 
171  /*
172  * When using multiple RPC ports
173  *
174  local_colorFrame_rpcPort_Name = local_colorFrame_StreamingPort_Name + "/rpc:i";
175  remote_colorFrame_rpcPort_Name = remote_colorFrame_StreamingPort_Name + "/rpc:i";
176  local_depthFrame_rpcPort_Name = local_depthFrame_StreamingPort_Name + "/rpc:i";
177  remote_depthFrame_rpcPort_Name = remote_depthFrame_StreamingPort_Name + "/rpc:i";
178 
179  */
180  }
181 
182  yarp::os::Bottle &ROS_parameters = config.findGroup("ROS");
183  if(!ROS_parameters.isNull())
184  {
185  if(verbose >= 5)
186  yCInfo(RGBDSENSORCLIENT) << "RGBDSensorClient: found 'ROS' group in config file, parsing ROS specific parameters.";
187  return false;
188  }
189  else
190  {
191  if(verbose >= 5)
192  yCInfo(RGBDSENSORCLIENT) << "RGBDSensorClient: 'ROS' group was NOT found in config file, skipping ROS specific parameters.";
193  }
194 
195  return true;
196 }
197 
199 {
200  bool ret;
201 
202  // Opening Streaming ports
203  ret = colorFrame_StreamingPort.open(local_colorFrame_StreamingPort_name);
204  ret &= depthFrame_StreamingPort.open(local_depthFrame_StreamingPort_name);
205 
206  if(!ret)
207  {
208  yCError(RGBDSENSORCLIENT) << sensorId << " cannot open local streaming ports.";
209  colorFrame_StreamingPort.close();
210  depthFrame_StreamingPort.close();
211  }
212 
213  if(! yarp::os::Network::connect(remote_colorFrame_StreamingPort_name, colorFrame_StreamingPort.getName(), image_carrier_type) )
214  {
215  yCError(RGBDSENSORCLIENT) << colorFrame_StreamingPort.getName() << " cannot connect to remote port " << remote_colorFrame_StreamingPort_name << "with carrier " << image_carrier_type;
216  return false;
217  }
218 
219  if(! yarp::os::Network::connect(remote_depthFrame_StreamingPort_name, depthFrame_StreamingPort.getName(), depth_carrier_type) )
220  {
221  yCError(RGBDSENSORCLIENT) << depthFrame_StreamingPort.getName() << " cannot connect to remote port " << remote_depthFrame_StreamingPort_name << "with carrier " << depth_carrier_type;
222  return false;
223  }
224 
225 
226  // Single RPC port
227  ret = rpcPort.open(local_rpcPort_name);
228 
229  if(!ret)
230  {
231  yCError(RGBDSENSORCLIENT) << sensorId << " cannot open local RPC port " << local_rpcPort_name;
232  colorFrame_StreamingPort.close();
233  depthFrame_StreamingPort.close();
234  rpcPort.close();
235  }
236 
237  if(! rpcPort.addOutput(remote_rpcPort_name) )
238  {
239  yCError(RGBDSENSORCLIENT) << sensorId << " cannot connect to port " << remote_rpcPort_name;
240  colorFrame_StreamingPort.close();
241  depthFrame_StreamingPort.close();
242  rpcPort.close();
243  return false;
244  }
245 
246  // Check protocol version
247  yarp::os::Bottle cmd, response;
249  cmd.addVocab(VOCAB_GET);
251  rpcPort.write(cmd, response);
252  int major = response.get(3).asInt32();
253  int minor = response.get(4).asInt32();
254 
256  {
257  yCError(RGBDSENSORCLIENT) << "Major protocol number does not match, please verify client and server are updated. \
258  Expected: " << RGBD_INTERFACE_PROTOCOL_VERSION_MAJOR << " received: " << major;
259  return false;
260  }
261 
262 
264  {
265  yCWarning(RGBDSENSORCLIENT) << "Minor protocol number does not match, please verify client and server are updated.\
266  Expected: " << RGBD_INTERFACE_PROTOCOL_VERSION_MINOR << " received: " << minor;
267  }
268 
269  /*
270  * Multiple RPC ports
271  *
272  ret &= colorFrame_rpcPort.open(local_colorFrame_rpcPort_Name.c_str() );
273  ret &= depthFrame_rpcPort.open(local_depthFrame_rpcPort_Name.c_str() );
274 
275  if(!ret)
276  yCError(RGBDSENSORCLIENT) << "sensorId cannot open ports";
277 
278  // doing connections: How to correctly handle YARP_PORT_PREFIX for remote port names??
279  if(! colorFrame_rpcPort.addOutput(remote_colorFrame_rpcPort_Name.c_str()) ) // This will handle local port names only
280  {
281  yCError(RGBDSENSORCLIENT) << sensorId << " cannot add output " << remote_colorFrame_rpcPort_Name;
282  return false;
283  }
284 
285  if(! depthFrame_rpcPort.addOutput(remote_depthFrame_rpcPort_Name.c_str()) ) // This will handle local port names only
286  {
287  yCError(RGBDSENSORCLIENT) << sensorId << " cannot add output " << remote_depthFrame_rpcPort_Name;
288  return false;
289  }
290  */
291 
292 
293  streamingReader->attach(&colorFrame_StreamingPort, &depthFrame_StreamingPort);
294 
295  return true;
296 }
297 
299 {
300  if(use_ROS)
301  {
302  yCError(RGBDSENSORCLIENT) << sensorId << "ROS topic is not supported yet";
303  return false;
304  }
305  return true;
306 }
307 
309 {
310  colorFrame_StreamingPort.close();
311  depthFrame_StreamingPort.close();
312  rpcPort.close();
313  return true;
314 }
315 
316 /*
317  * IDepthVisualParams interface. Look at IVisualParams.h for documentation
318  *
319  * Implemented by Implement_DepthVisualParams_Sender
320  */
321 
322 /*
323  * IDepthVisualParams interface. Look at IVisualParams.h for documentation
324  *
325  * Implemented by Implement_DepthVisualParams_Sender
326  */
327 
328 
329 /*
330  * IRGBDSensor specific interface methods
331  */
332 
334 {
335  yarp::os::Bottle cmd, response;
337  cmd.addVocab(VOCAB_GET);
339  rpcPort.write(cmd, response);
340 
341  // Minimal check on response, we suppose the response is always correctly formatted
342  if((response.get(0).asVocab()) == VOCAB_FAILED)
343  {
344  extrinsic.zero();
345  return false;
346  }
347 
348  return Property::copyPortable(response.get(3), extrinsic); // will it really work??
349 }
350 
351 
353 {
354  yarp::os::Bottle cmd, response;
356  cmd.addVocab(VOCAB_GET);
357  cmd.addVocab(VOCAB_STATUS);
358  rpcPort.write(cmd, response);
359  return (IRGBDSensor::RGBDSensor_status) response.get(3).asInt32();
360 }
361 
362 
364 {
365  yarp::os::Bottle cmd, response;
367  cmd.addVocab(VOCAB_GET);
369  rpcPort.write(cmd, response);
370  return response.get(3).asString();
371 }
372 
374 {
375  if(timeStamp)
376  timeStamp->update(yarp::os::Time::now());
377  return streamingReader->readRgb(rgbImage);
378 }
379 
381 {
382  if(timeStamp)
383  timeStamp->update(yarp::os::Time::now());
384  return streamingReader->readDepth(depthImage);
385 }
386 
387 bool RGBDSensorClient::getImages(FlexImage &rgbImage, ImageOf<PixelFloat> &depthImage, Stamp *rgbStamp, Stamp *depthStamp)
388 {
389  bool ret = true;
390  ret &= streamingReader->readRgb(rgbImage);
391  ret &= streamingReader->readDepth(depthImage);
392 
393  if(rgbStamp)
394  rgbStamp->update(yarp::os::Time::now());
395 
396  if(depthStamp)
397  depthStamp->update(yarp::os::Time::now());
398  return ret;
399 }
400 
401 //
402 // IFrame Grabber Control 2 interface is implemented by FrameGrabberControls2_Sender
403 //
404 
405 //
406 // Rgb
407 //
409 {
410  return RgbMsgSender->getRgbHeight();
411 }
412 
414 {
415  return RgbMsgSender->getRgbWidth();
416 }
418 {
419  return RgbMsgSender->getRgbSupportedConfigurations(configurations);
420 }
421 bool RGBDSensorClient::getRgbResolution(int &width, int &height){
422  return RgbMsgSender->getRgbResolution(width, height);
423 }
424 
425 bool RGBDSensorClient::setRgbResolution(int width, int height)
426 {
427  return RgbMsgSender->setRgbResolution(width, height);
428 }
429 bool RGBDSensorClient::getRgbFOV(double &horizontalFov, double &verticalFov)
430 {
431  return RgbMsgSender->getRgbFOV(horizontalFov, verticalFov);
432 }
433 bool RGBDSensorClient::setRgbFOV(double horizontalFov, double verticalFov)
434 {
435  return RgbMsgSender->getRgbFOV(horizontalFov, verticalFov);
436 }
438 {
439  return RgbMsgSender->getRgbIntrinsicParam(intrinsic);
440 }
441 
443 {
444  return RgbMsgSender->getRgbMirroring(mirror);
445 }
446 
448 {
449  return RgbMsgSender->setRgbMirroring(mirror);
450 }
451 
452 //
453 // Depth
454 //
456 {
457  return DepthMsgSender->getDepthHeight();
458 }
460 {
461  return DepthMsgSender->getDepthWidth();
462 }
463 bool RGBDSensorClient::setDepthResolution(int width, int height)
464 {
465  return DepthMsgSender->setDepthResolution(width, height);
466 }
467 bool RGBDSensorClient::getDepthFOV(double &horizontalFov, double &verticalFov)
468 {
469  return DepthMsgSender->getDepthFOV(horizontalFov, verticalFov);
470 }
471 bool RGBDSensorClient::setDepthFOV(double horizontalFov, double verticalFov)
472 {
473  return DepthMsgSender->setDepthFOV(horizontalFov, verticalFov);
474 }
476 {
477  return DepthMsgSender->getDepthAccuracy();
478 }
480 {
481  return DepthMsgSender->setDepthAccuracy(accuracy);
482 }
483 bool RGBDSensorClient::getDepthClipPlanes(double &nearPlane, double &farPlane)
484 {
485  return DepthMsgSender->getDepthClipPlanes(nearPlane, farPlane);
486 }
487 bool RGBDSensorClient::setDepthClipPlanes(double nearPlane, double farPlane)
488 {
489  return DepthMsgSender->setDepthClipPlanes(nearPlane, farPlane);
490 }
492 {
493  return DepthMsgSender->getDepthIntrinsicParam(intrinsic);
494 }
495 
497 {
498  return DepthMsgSender->getDepthMirroring(mirror);
499 }
500 
502 {
503  return DepthMsgSender->setDepthMirroring(mirror);
504 }
constexpr yarp::conf::vocab32_t VOCAB_GET
Definition: GenericVocabs.h:16
constexpr yarp::conf::vocab32_t VOCAB_FAILED
Definition: GenericVocabs.h:19
constexpr yarp::conf::vocab32_t VOCAB_RGBD_SENSOR
Definition: IRGBDSensor.h:22
constexpr yarp::conf::vocab32_t VOCAB_EXTRINSIC_PARAM
Definition: IRGBDSensor.h:26
constexpr yarp::conf::vocab32_t VOCAB_RGBD_PROTOCOL_VERSION
Definition: IRGBDSensor.h:23
constexpr yarp::conf::vocab32_t VOCAB_STATUS
Definition: IRGBDSensor.h:31
constexpr yarp::conf::vocab32_t VOCAB_ERROR_MSG
Definition: IRGBDSensor.h:27
bool ret
const yarp::os::LogComponent & RGBDSENSORCLIENT()
#define RGBD_INTERFACE_PROTOCOL_VERSION_MINOR
#define RGBD_INTERFACE_PROTOCOL_VERSION_MAJOR
bool getRgbResolution(int &width, int &height) override
Get the resolution of the rgb image from the camera.
bool setRgbFOV(double horizontalFov, double verticalFov) override
Set the field of view (FOV) of the rgb camera.
int getDepthWidth() override
Return the height of each frame.
bool getRgbMirroring(bool &mirror) override
Get the mirroring setting of the sensor.
bool setDepthMirroring(bool mirror) override
Set the mirroring setting of the sensor.
bool getDepthClipPlanes(double &near, double &far) override
Get the clipping planes of the sensor.
bool getRgbImage(yarp::sig::FlexImage &rgbImage, yarp::os::Stamp *timeStamp=NULL) override
Get the rgb frame from the device.
bool setRgbResolution(int width, int height) override
Set the resolution of the rgb image from the camera.
bool setDepthAccuracy(double accuracy) override
Set the minimum detectable variation in distance [meter] when possible.
bool getRgbSupportedConfigurations(yarp::sig::VectorOf< yarp::dev::CameraConfig > &configurations) override
Get the possible configurations of the camera.
int getRgbWidth() override
Return the width of each frame.
bool setDepthResolution(int width, int height) override
Set the resolution of the depth image from the camera.
bool getDepthIntrinsicParam(yarp::os::Property &intrinsic) override
Get the intrinsic parameters of the depth camera.
bool getDepthFOV(double &horizontalFov, double &verticalFov) override
Get the field of view (FOV) of the depth camera.
bool initialize_YARP(yarp::os::Searchable &config)
bool setDepthClipPlanes(double near, double far) override
Set the clipping planes of the sensor.
bool getDepthMirroring(bool &mirror) override
Get the mirroring setting of the sensor.
bool getRgbFOV(double &horizontalFov, double &verticalFov) override
Get the field of view (FOV) of the rgb camera.
~RGBDSensorClient() override
bool getDepthImage(yarp::sig::ImageOf< yarp::sig::PixelFloat > &depthImage, yarp::os::Stamp *timeStamp=NULL) override
Get the depth frame from the device.
bool close() override
Close the DeviceDriver.
double getDepthAccuracy() override
Get the minimum detectable variation in distance [meter].
bool getImages(yarp::sig::FlexImage &colorFrame, yarp::sig::ImageOf< yarp::sig::PixelFloat > &depthFrame, yarp::os::Stamp *colorStamp=NULL, yarp::os::Stamp *depthStamp=NULL) override
Get the both the color and depth frame in a single call.
bool fromConfig(yarp::os::Searchable &config)
bool setDepthFOV(double horizontalFov, double verticalFov) override
Set the field of view (FOV) of the depth camera.
bool initialize_ROS(yarp::os::Searchable &config)
bool getExtrinsicParam(yarp::sig::Matrix &extrinsic) override
Get the extrinsic parameters from the device.
int getDepthHeight() override
Return the height of each frame.
std::string getLastErrorMsg(yarp::os::Stamp *timeStamp=NULL) override
Return an error message in case of error.
IRGBDSensor::RGBDSensor_status getSensorStatus() override
Get the surrent status of the sensor, using enum type.
bool getRgbIntrinsicParam(yarp::os::Property &intrinsic) override
Get the intrinsic parameters of the rgb camera.
bool open(yarp::os::Searchable &config) override
Create and configure a device, by name.
int getRgbHeight() override
Return the height of each frame.
bool setRgbMirroring(bool mirror) override
Set the mirroring setting of the sensor.
This classes implement a sender / parser for IFrameGrabberControls interface messages.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
void addVocab(int x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:167
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
bool isNull() const override
Checks if the object is invalid.
Definition: Bottle.cpp:373
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition: Network.cpp:685
static bool copyPortable(const PortWriter &writer, PortReader &reader)
Copy one portable to another, via writing and reading.
Definition: Portable.cpp:19
A class for storing options and configuration information.
Definition: Property.h:37
A base class for nested structures that can be searched.
Definition: Searchable.h:69
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.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:25
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:113
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:207
virtual std::int32_t asVocab() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:231
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
Image class with user control of representation details.
Definition: Image.h:403
A class for a Matrix.
Definition: Matrix.h:46
void zero()
Zero the matrix.
Definition: Matrix.cpp:308
Provides:
Definition: Vector.h:122
#define yCInfo(component,...)
Definition: LogComponent.h:135
#define yCError(component,...)
Definition: LogComponent.h:157
#define yCTrace(component,...)
Definition: LogComponent.h:88
#define yCWarning(component,...)
Definition: LogComponent.h:146
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
An interface for the device drivers.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:25
constexpr char accuracy[]