4 #include <yarp/conf/numeric.h>
6 #include <yarp/os/all.h>
7 #include <yarp/dev/all.h>
8 #include <yarp/sig/all.h>
9 #include <yarp/math/Math.h>
10 #include <yarp/conf/system.h>
11 #include <yarp/sig/Image.h>
12 #include <yarp/sig/Vector.h>
14 #include "RGBD2PointCloud.hpp"
15 #include <yarp/os/NetFloat32.h>
19 yarp::os::NetFloat32 x;
20 yarp::os::NetFloat32 y;
21 yarp::os::NetFloat32 z;
27 using namespace yarp::os;
28 using namespace yarp::sig;
29 using namespace yarp::dev;
30 using namespace yarp::math;
32 RGBD2PointCloud::RGBD2PointCloud()
34 use_RGBD_client =
false;
37 rosPC_data.header.seq = 0;
38 frame_id =
"/depth_center";
46 RGBD2PointCloud::~RGBD2PointCloud()
51 Bottle RGBD2PointCloud::get_3D_points(
const vector<Vector> &pixels,
bool color)
55 Bottle &points=point_cloud.addList();
58 for (
size_t i=0; i<pixels.size(); i++)
60 Vector pixel=pixels[i];
63 index=rosPC_data.width*(v) + u;
65 char *pointer = (
char*) &rosPC_data.data[0];
66 PC_Point *iter = (PC_Point*) &pointer[index*
sizeof(PC_Point)];
68 Bottle &pp=points.addList();
69 pp.addFloat64(iter->x);
70 pp.addFloat64(iter->y);
71 pp.addFloat64(iter->z);
75 uint8_t a = iter->rgba[2];
87 bool RGBD2PointCloud::attach(RpcServer &source)
89 return this->yarp().attachAsServer(source);
92 bool RGBD2PointCloud::configure(ResourceFinder& rf)
95 string topicName, nodeName;
96 Bottle& rosParam = rf.findGroup(
"ROS");
99 if (rosParam.check(
"ROS_topicName"))
101 topicName = rosParam.find(
"ROS_topicName").asString();
105 topicName =
"/RGBD2PointCloud";
107 if (rosParam.check(
"ROS_nodeName"))
109 nodeName = rosParam.find(
"ROS_nodeName").asString();
113 nodeName =
"/RGBD2PointCloudNode";
121 yInfo() <<
" Required parameters:";
122 yInfo() <<
"\tremoteImagePort: remote port streaming rgb images";
123 yInfo() <<
"\tremoteDepthPort: remote port streaming depth images";
124 yInfo() <<
" Optional parameters:";
125 yInfo() <<
"\tscale: scale factor to apply to depth data. For Gazebo has to be 1, for xtion sensor 0.001 in order to scale data to [m]";
126 yInfo() <<
"\tmirrorX, mirrorY, mirrorZ: add it to mirror the resulting point cloud on the corresponding axes (no param, just '--mirrorx')";
127 yInfo() <<
"\ttf: if present a tf will be published. This requires 7 parameters";
128 yInfo() <<
"\t reference frame name,\n\t x,y,z translations [m], \n\t roll, pitch, yaw rotations [rad]\n";
129 yInfo() <<
"\t For example --tf base_link 0.1 0.0 0.0 1.56 0.0 0.0 -- no parenthesis";
133 if(rf.check(
"frame_id"))
135 frame_id = rf.find(
"frame_id").asString();
139 if(!rf.check(
"remoteImagePort") || !rf.check(
"remoteDepthPort"))
141 yError() <<
"Missing required parameters: remoteImagePort or remoteDepthPort";
145 yInfo() <<
"Node name is " << nodeName;
146 yInfo() <<
"Topic name is " << topicName;
148 rosNode =
new yarp::os::Node(nodeName);
149 if(!pointCloud_outTopic.topic(topicName))
151 yError() <<
" opening " << topicName <<
" Topic, check your yarp-ROS network configuration\n";
158 std::string remoteImagePort_name = rf.find(
"remoteImagePort").asString();
159 std::string remoteDepthPort_name = rf.find(
"remoteDepthPort").asString();
165 yarp::os::Property params;
166 params.put(
"device",
"RGBDSensorClient");
167 params.put(
"localImagePort",
"/RGBD2PointCloud/rgb/in:i");
168 params.put(
"localDepthPort",
"/RGBD2PointCloud/depth/in:i");
169 params.put(
"remoteImagePort",remoteImagePort_name);
170 params.put(
"remoteDepthPort",remoteDepthPort_name);
171 params.put(
"watchdog",
"100");
172 params.put(
"synchPolicy",
"latest");
174 if(!RGBD_Client.open(params))
176 yError() <<
"Cannot open device";
183 ret &= imageFrame_inputPort.open(
"/RGBD2PointCloud/rgb/in:i");
184 ret &= depthFrame_inputPort.open(
"/RGBD2PointCloud/depth/in:i");
185 ret &= rpcPort.open(
"/RGBD2PointCloud/rpc");
189 yError() <<
"Cannot open required ports";
196 ret &= yarp::os::Network::connect(remoteImagePort_name,
"/RGBD2PointCloud/rgb/in:i");
197 ret &= yarp::os::Network::connect(remoteDepthPort_name,
"/RGBD2PointCloud/depth/in:i");
201 yError() <<
"Cannot connect to remote ports";
205 yInfo() <<
"Connection is done!";
233 frame_id = rosParam.check(
"frame_id", Value(frame_id)).asString();
234 rf.check(
"mirrorX") ? mirrorX = -1 : mirrorX = 1;
235 rf.check(
"mirrorY") ? mirrorY = -1 : mirrorY = 1;
236 rf.check(
"mirrorZ") ? mirrorZ = -1 : mirrorZ = 1;
238 yInfo() <<
"Mirrors: x=" << mirrorX <<
" y=" << mirrorY <<
" z= " << mirrorZ;
239 yInfo() <<
"Frame id: " << frame_id;
240 scaleFactor = rf.check(
"scale", Value(1)).asFloat64();
244 rosPC_data.header.seq++;
245 rosPC_data.header.frame_id = frame_id;
247 rosPC_data.fields.resize(4);
248 rosPC_data.fields[0].name =
"x";
249 rosPC_data.fields[0].offset = 0;
250 rosPC_data.fields[0].datatype = 7;
251 rosPC_data.fields[0].count = 1;
253 rosPC_data.fields[1].name =
"y";
254 rosPC_data.fields[1].offset = 4;
255 rosPC_data.fields[1].datatype = 7;
256 rosPC_data.fields[1].count = 1;
258 rosPC_data.fields[2].name =
"z";
259 rosPC_data.fields[2].offset = 8;
260 rosPC_data.fields[2].datatype = 7;
261 rosPC_data.fields[2].count = 1;
263 rosPC_data.fields[3].name =
"rgb";
264 rosPC_data.fields[3].offset = 12;
265 rosPC_data.fields[3].datatype = 6;
266 rosPC_data.fields[3].count = 1;
268 #if defined(YARP_BIG_ENDIAN)
269 rosPC_data.is_bigendian =
true;
270 #elif defined(YARP_LITTLE_ENDIAN)
271 rosPC_data.is_bigendian =
false;
273 #error "Cannot detect endianness"
276 yAssert(
sizeof(PC_Point) == 16);
277 rosPC_data.point_step =
sizeof(PC_Point);
278 rosPC_data.is_dense =
true;
282 double RGBD2PointCloud::getPeriod()
287 bool RGBD2PointCloud::updateModule()
289 static double start = yarp::os::Time::now();
291 if(yarp::os::Time::now() - start > 3.0f)
293 yInfo() <<
"RGBD2PointCloud is running fine.";
294 start = yarp::os::Time::now();
296 return convertRGBD_2_XYZRGB();
299 bool RGBD2PointCloud::convertRGBD_2_XYZRGB()
301 bool ret = imageFrame_inputPort.read(colorImage);
302 ret &= depthFrame_inputPort.read(depthImage);
304 imageFrame_inputPort.getEnvelope(colorStamp);
305 depthFrame_inputPort.getEnvelope(depthStamp);
309 yError() <<
"Cannot read from ports";
313 int d_width = depthImage.width();
314 int d_height = depthImage.height();
315 int c_width = colorImage.width();
316 int c_height = colorImage.height();
318 if( (d_width != c_width) && (d_height != c_height) )
320 yError() <<
"Size does not match";
328 rosPC_data.width = width;
329 rosPC_data.height = height;
330 rosPC_data.row_step = rosPC_data.point_step*width;
332 rosPC_data.header.stamp.nsec = (NetUint32) (modf(depthStamp.getTime(), &tmp_sec)*1000000000);
333 rosPC_data.header.stamp.sec = (NetUint32) tmp_sec;
336 unsigned char* colorDataRaw = (
unsigned char*)colorImage.getRawImage();
337 float* depthDataRaw = (
float*)depthImage.getRawImage();
340 double hfov = 58 * 3.14 / 360;
342 double fl = ((double)this->width) / (2.0 *tan(hfov/2.0));
344 double fovHorizontalDeg = 58.62;
345 double halfFovHorizontalRad = fovHorizontalDeg*M_PI/360.0;
349 double f=(width/2)/sin(halfFovHorizontalRad)*cos(halfFovHorizontalRad);
352 rosPC_data.data.resize(width*height*rosPC_data.point_step);
354 PC_Point *iter = (PC_Point*) &rosPC_data.data[0];
358 for (int32_t j = 0; j < height; j++)
360 for (int32_t i = 0; i < width; i++)
362 depth = depthDataRaw[index++] * scaleFactor;
363 u = -(i - 0.5*(width-1));
364 v = (0.5*(height-1) -j);
365 point.x = -(NetFloat32) depth * u/f;
366 point.y = -(NetFloat32) depth * v/f;
367 point.z = (NetFloat32) depth;
382 point.rgba[2] = (uint8_t) colorDataRaw[(j*width*3) + new_i*3 +0];
383 point.rgba[1] = (uint8_t) colorDataRaw[(j*width*3) + new_i*3 +1];
384 point.rgba[0] = (uint8_t) colorDataRaw[(j*width*3) + new_i*3 +2];
393 pointCloud_outTopic.write(rosPC_data);
409 bool RGBD2PointCloud::interruptModule()
411 yDebug() <<
"Interrupting module";
412 imageFrame_inputPort.interrupt();
413 depthFrame_inputPort.interrupt();
415 imageFrame_inputPort.close();
416 depthFrame_inputPort.close();
418 pointCloud_outTopic.close();
423 bool RGBD2PointCloud::close()