YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
FrameGrabber_nws_ros2.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2023 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
7
9#include <yarp/os/LogStream.h>
10#include <yarp/dev/PolyDriver.h>
11
12#include <sensor_msgs/image_encodings.hpp>
13#include <Ros2Utils.h>
14
15namespace {
16YARP_LOG_COMPONENT(FRAMEGRABBER_NWS_ROS2, "yarp.device.frameGrabber_nws_ros2")
17
18// FIXME Copied from rgbdSensor_nws_ros2
19std::string yarp2RosPixelCode(int code)
20{
21 switch (code)
22 {
23 case VOCAB_PIXEL_BGR:
24 return sensor_msgs::image_encodings::BGR8;
26 return sensor_msgs::image_encodings::BGRA8;
28 return sensor_msgs::image_encodings::BAYER_BGGR16;
30 return sensor_msgs::image_encodings::BAYER_BGGR8;
32 return sensor_msgs::image_encodings::BAYER_GBRG16;
34 return sensor_msgs::image_encodings::BAYER_GBRG8;
36 return sensor_msgs::image_encodings::BAYER_GRBG16;
38 return sensor_msgs::image_encodings::BAYER_GRBG8;
40 return sensor_msgs::image_encodings::BAYER_RGGB16;
42 return sensor_msgs::image_encodings::BAYER_RGGB8;
44 return sensor_msgs::image_encodings::MONO8;
46 return sensor_msgs::image_encodings::MONO16;
47 case VOCAB_PIXEL_RGB:
48 return sensor_msgs::image_encodings::RGB8;
50 return sensor_msgs::image_encodings::RGBA8;
52 return sensor_msgs::image_encodings::TYPE_32FC1;
53 default:
54 return sensor_msgs::image_encodings::RGB8;
55 }
56}
57} // namespace
58
60 PeriodicThread(s_default_period)
61{
62}
63
64
69
70
72{
73 if (!m_active) {
74 return false;
75 }
76 m_active = false;
77
78 detach();
79
80 return true;
81}
82
83
85{
86 if (m_active) {
87 yCError(FRAMEGRABBER_NWS_ROS2, "Device is already opened");
88 return false;
89 }
90 parseParams(config);
91
93 publisher_image = m_node->create_publisher<sensor_msgs::msg::Image>(m_topic_name, 10);
94
95
96 // set "cameraInfoTopicName" and open publisher
97 std::string cameraInfoTopicName = m_topic_name.substr(0,m_topic_name.rfind('/')) + "/camera_info";
98 publisher_cameraInfo = m_node->create_publisher<sensor_msgs::msg::CameraInfo>(cameraInfoTopicName, 10);
99
100 yCInfo(FRAMEGRABBER_NWS_ROS2) << "Running, waiting for attach...";
101
102 m_active = true;
103
104 return true;
105}
106
108{
109 if (!poly->isValid()) {
110 yCError(FRAMEGRABBER_NWS_ROS2) << "Device " << poly << " to attach to is not valid ... cannot proceed";
111 return false;
112 }
113
114 PeriodicThread::setPeriod(m_period);
115
116 poly->view(iRgbVisualParams);
117 poly->view(iFrameGrabberImage);
118 poly->view(iPreciselyTimed);
119
120 if (iFrameGrabberImage == nullptr) {
121 yCError(FRAMEGRABBER_NWS_ROS2) << "IFrameGrabberImage interface is not available on the device";
122 return false;
123 }
124
125 if (iRgbVisualParams == nullptr) {
126 yCWarning(FRAMEGRABBER_NWS_ROS2) << "IRgbVisualParams interface is not available on the device";
127 }
128
129 return PeriodicThread::start();
130}
131
132
134{
137 }
138
139 iRgbVisualParams = nullptr;
140 iFrameGrabberImage = nullptr;
141 iPreciselyTimed = nullptr;
142
143 return true;
144}
145
147{
149 return true;
150}
151
153{
154 delete yarpimg;
155 yarpimg = nullptr;
156}
157
158
159// Publish the images on the buffered port
161{
162// if (false /* FIXME Can we check if there are subscribers connected in ROS2? */) {
163// // If no subscribers are connected, do not call getImage on the interface.
164// return;
165// }
166
167 if (iPreciselyTimed) {
168 m_stamp = iPreciselyTimed->getLastInputStamp();
169 } else {
170 m_stamp.update(yarp::os::Time::now());
171 }
172
173 if (iFrameGrabberImage)
174 {
175 if (iFrameGrabberImage->getImage(*yarpimg))
176 {
177 sensor_msgs::msg::Image rosimg;
178 rosimg.data.resize(yarpimg->getRawImageSize());
179 rosimg.width = yarpimg->width();
180 rosimg.height = yarpimg->height();
181 rosimg.encoding = yarp2RosPixelCode(yarpimg->getPixelCode());
182 rosimg.step = yarpimg->getRowSize();
183 rosimg.header.frame_id = m_frame_id;
184 // rosimg.header.stamp.sec = static_cast<int>(m_stamp.getTime()); // FIXME
185 // rosimg.header.stamp.nanosec = static_cast<int>(1000000000UL * (m_stamp.getTime() - int(m_stamp.getTime()))); // FIXME
186 rosimg.is_bigendian = 0;
187 memcpy(rosimg.data.data(), yarpimg->getRawImage(), yarpimg->getRawImageSize());
188 publisher_image->publish(rosimg);
189 }
190 else
191 {
192 yCError(FRAMEGRABBER_NWS_ROS2) << "Image not captured (getImage failed). Check hardware configuration.";
193 }
194 }
195 else
196 {
197 yCError(FRAMEGRABBER_NWS_ROS2) << "Invalid call to interface iFrameGrabberImage";
198 }
199
200 if (iRgbVisualParams)
201 {
202 sensor_msgs::msg::CameraInfo cameraInfo;
203 if (setCamInfo(cameraInfo)) {
204 publisher_cameraInfo->publish(cameraInfo);
205 }
206 }
207 else
208 {
209 yCError(FRAMEGRABBER_NWS_ROS2) << "Invalid call to interface iRgbVisualParams";
210 }
211}
212
213namespace {
214template <class T>
215struct param
216{
217 param(T& inVar, std::string inName) :
218 var(&inVar),
219 parname(std::move(inName))
220 {
221 }
222 T* var;
223 std::string parname;
224};
225} // namespace
226
227bool FrameGrabber_nws_ros2::setCamInfo(sensor_msgs::msg::CameraInfo& cameraInfo)
228{
229 yarp::os::Property camData;
230 if (!iRgbVisualParams->getRgbIntrinsicParam(camData)) {
231 yCErrorThreadOnce(FRAMEGRABBER_NWS_ROS2) << "Unable to get intrinsic param from rgb sensor!";
232 return false;
233 }
234
235 if (!camData.check("distortionModel")) {
236 yCWarning(FRAMEGRABBER_NWS_ROS2) << "Missing distortion model";
237 return false;
238 }
239
240 std::string distModel = camData.find("distortionModel").asString();
241 if (distModel != "plumb_bob") {
242 yCError(FRAMEGRABBER_NWS_ROS2) << "Distortion model not supported";
243 return false;
244 }
245
246 double phyF = 0.0;
247 double fx = 0.0;
248 double fy = 0.0;
249 double cx = 0.0;
250 double cy = 0.0;
251 double k1 = 0.0;
252 double k2 = 0.0;
253 double t1 = 0.0;
254 double t2 = 0.0;
255 double k3 = 0.0;
256
257 std::vector<param<double>> parVector;
258 parVector.emplace_back(phyF,"physFocalLength");
259 parVector.emplace_back(fx,"focalLengthX");
260 parVector.emplace_back(fy,"focalLengthY");
261 parVector.emplace_back(cx,"principalPointX");
262 parVector.emplace_back(cy,"principalPointY");
263 parVector.emplace_back(k1,"k1");
264 parVector.emplace_back(k2,"k2");
265 parVector.emplace_back(t1,"t1");
266 parVector.emplace_back(t2,"t2");
267 parVector.emplace_back(k3,"k3");
268
269 for(auto& par : parVector) {
270 if(!camData.check(par.parname)) {
271 yCWarning(FRAMEGRABBER_NWS_ROS2) << "Driver has not the param:" << par.parname;
272 return false;
273 }
274 *(par.var) = camData.find(par.parname).asFloat64();
275 }
276
277 cameraInfo.header.frame_id = m_frame_id;
278// cameraInfo.header.stamp.sec = static_cast<int>(m_stamp.getTime()); // FIXME
279// cameraInfo.header.stamp.nanosec = static_cast<int>(1000000000UL * (m_stamp.getTime() - int(m_stamp.getTime()))); // FIXME
280 cameraInfo.width = iRgbVisualParams->getRgbWidth();
281 cameraInfo.height = iRgbVisualParams->getRgbHeight();
282 cameraInfo.distortion_model = distModel;
283
284 cameraInfo.d.resize(5);
285 cameraInfo.d[0] = k1;
286 cameraInfo.d[1] = k2;
287 cameraInfo.d[2] = t1;
288 cameraInfo.d[3] = t2;
289 cameraInfo.d[4] = k3;
290
291 cameraInfo.k[0] = fx; cameraInfo.k[1] = 0; cameraInfo.k[2] = cx;
292 cameraInfo.k[3] = 0; cameraInfo.k[4] = fy; cameraInfo.k[5] = cy;
293 cameraInfo.k[6] = 0; cameraInfo.k[7] = 0; cameraInfo.k[8] = 1;
294
295 /*
296 * ROS documentation on cameraInfo message:
297 * "Rectification matrix (stereo cameras only)
298 * A rotation matrix aligning the camera coordinate system to the ideal
299 * stereo image plane so that epipolar lines in both stereo images are
300 * parallel."
301 * useless in our case, it will be an identity matrix
302 */
303
304 cameraInfo.r[0] = 1; cameraInfo.r[1] = 0; cameraInfo.r[2] = 0;
305 cameraInfo.r[3] = 0; cameraInfo.r[4] = 1; cameraInfo.r[5] = 0;
306 cameraInfo.r[6] = 0; cameraInfo.r[7] = 0; cameraInfo.r[8] = 1;
307
308 cameraInfo.p[0] = fx; cameraInfo.p[1] = 0; cameraInfo.p[2] = cx; cameraInfo.p[3] = 0;
309 cameraInfo.p[4] = 0; cameraInfo.p[5] = fy; cameraInfo.p[6] = cy; cameraInfo.p[7] = 0;
310 cameraInfo.p[8] = 0; cameraInfo.p[9] = 0; cameraInfo.p[10] = 1; cameraInfo.p[11] = 0;
311
312 cameraInfo.binning_x = cameraInfo.binning_y = 0;
313 cameraInfo.roi.height = cameraInfo.roi.width = cameraInfo.roi.x_offset = cameraInfo.roi.y_offset = 0;
314 cameraInfo.roi.do_rectify = false;
315 return true;
316}
@ VOCAB_PIXEL_ENCODING_BAYER_BGGR16
Definition Image.h:59
@ VOCAB_PIXEL_RGBA
Definition Image.h:45
@ VOCAB_PIXEL_MONO16
Definition Image.h:43
@ VOCAB_PIXEL_ENCODING_BAYER_BGGR8
Definition Image.h:58
@ VOCAB_PIXEL_BGRA
Definition Image.h:46
@ VOCAB_PIXEL_BGR
Definition Image.h:49
@ VOCAB_PIXEL_MONO_FLOAT
Definition Image.h:53
@ VOCAB_PIXEL_ENCODING_BAYER_RGGB8
Definition Image.h:62
@ VOCAB_PIXEL_ENCODING_BAYER_GRBG8
Definition Image.h:56
@ VOCAB_PIXEL_ENCODING_BAYER_GBRG16
Definition Image.h:61
@ VOCAB_PIXEL_ENCODING_BAYER_GRBG16
Definition Image.h:57
@ VOCAB_PIXEL_ENCODING_BAYER_GBRG8
Definition Image.h:60
@ VOCAB_PIXEL_MONO
Definition Image.h:42
@ VOCAB_PIXEL_ENCODING_BAYER_RGGB16
Definition Image.h:63
@ VOCAB_PIXEL_RGB
Definition Image.h:44
bool parseParams(const yarp::os::Searchable &config) override
Parse the DeviceDriver parameters.
void run() override
Loop function.
bool threadInit() override
Initialization method.
bool detach() override
Detach the object (you must have first called attach).
void threadRelease() override
Release method.
bool attach(yarp::dev::PolyDriver *poly) override
Attach to another object.
bool close() override
Close the DeviceDriver.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
static rclcpp::Node::SharedPtr createNode(std::string name)
Definition Ros2Utils.cpp:9
bool view(T *&x)
Get an interface to the device driver.
virtual bool getImage(ImageType &image)=0
Get an image from the frame grabber.
virtual yarp::os::Stamp getLastInputStamp()=0
Return the time stamp relative to the last acquisition.
virtual bool getRgbIntrinsicParam(yarp::os::Property &intrinsic)=0
Get the intrinsic parameters of the rgb camera.
virtual int getRgbHeight()=0
Return the height of each frame.
virtual int getRgbWidth()=0
Return the width of each frame.
A container for a device driver.
Definition PolyDriver.h:23
bool isValid() const
Check if device is valid.
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
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
A base class for nested structures that can be searched.
Definition Searchable.h:31
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition Stamp.cpp:124
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
Typed image class.
Definition Image.h:605
int getPixelCode() const override
Gets pixel type identifier.
Definition Image.h:721
size_t width() const
Gets width of image in pixels.
Definition Image.h:171
size_t getRowSize() const
Size of the underlying image buffer rows.
Definition Image.h:197
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition Image.cpp:479
size_t getRawImageSize() const
Access to the internal buffer size information (this is how much memory has been allocated for the im...
Definition Image.cpp:488
size_t height() const
Gets height of image in pixels.
Definition Image.h:177
#define yCInfo(component,...)
#define yCError(component,...)
#define yCWarning(component,...)
#define YARP_LOG_COMPONENT(name,...)
#define yCErrorThreadOnce(component,...)
STL namespace.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121