YARP
Yet Another Robot Platform
FrameGrabberOf_Responder-inl.h
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 
6 #ifndef YARP_FRAMEGRABBER_PROTOCOL_FRAMEGRABBEROF_RESPONDER_INL_H
7 #define YARP_FRAMEGRABBER_PROTOCOL_FRAMEGRABBEROF_RESPONDER_INL_H
8 
9 #include <yarp/os/LogComponent.h>
10 #include <yarp/os/LogStream.h>
11 
13 #include <yarp/sig/ImageUtils.h>
14 
15 namespace {
16 YARP_LOG_COMPONENT(FRAMEGRABBEROF_RESPONDER, "yarp.proto.framegrabber.FrameGrabberOf_Responder")
17 }
18 
19 namespace yarp {
20 namespace proto {
21 namespace framegrabber {
22 
23 
24 template <typename ImageType,
25  yarp::conf::vocab32_t IfVocab,
26  yarp::conf::vocab32_t ImgVocab>
28 {
29  if (!interface) {
30  yCError(FRAMEGRABBEROF_RESPONDER) << "Invalid IFrameGrabberOf interface received";
31  return false;
32  }
33 
34  iFrameGrabberOf = interface;
35  return true;
36 }
37 
38 template <typename ImageType,
39  yarp::conf::vocab32_t IfVocab,
40  yarp::conf::vocab32_t ImgVocab>
42 {
43  if (!iFrameGrabberOf) {
44  reply.addVocab32(VOCAB_FAILED);
45  // FIXME C++17
46  if /* constexpr */ (std::is_same<ImageType, yarp::sig::ImageOf<yarp::sig::PixelRgb>>::value) {
47  reply.addString("Selected camera device has no IFrameGrabberImage interface");
48  yCError(FRAMEGRABBEROF_RESPONDER) << "Selected camera device has no IFrameGrabberImage interface";
49  } else if /* constexpr */ (std::is_same<ImageType, yarp::sig::ImageOf<yarp::sig::PixelMono>>::value) {
50  reply.addString("Selected camera device has no IFrameGrabberImageRaw interface");
51  yCError(FRAMEGRABBEROF_RESPONDER) << "Selected camera device has no IFrameGrabberImageRaw interface";
52  } else {
53  reply.addString("Selected camera device has no IFrameGrabberOf<ImageType> interface");
54  yCError(FRAMEGRABBEROF_RESPONDER) << "Selected camera device has no IFrameGrabberOf<ImageType> interface";
55  }
56  return false;
57  }
58 
59  if (cmd.get(0).asVocab32() != IfVocab) {
60  reply.addVocab32(VOCAB_FAILED);
61  yCError(FRAMEGRABBEROF_RESPONDER) << "Received a command not belonging to this interface.";
62  return false;
63  }
64 
65  switch (cmd.get(1).asVocab32()) {
66  case VOCAB_GET: {
67  switch (cmd.get(2).asVocab32()) {
68  case VOCAB_HEIGHT:
69  reply.clear();
70  reply.addVocab32(IfVocab);
71  reply.addVocab32(VOCAB_HEIGHT);
72  reply.addVocab32(VOCAB_IS);
73  reply.addInt32(iFrameGrabberOf->height());
74  break;
75  case VOCAB_WIDTH:
76  reply.clear();
77  reply.addVocab32(IfVocab);
78  reply.addVocab32(VOCAB_WIDTH);
79  reply.addVocab32(VOCAB_IS);
80  reply.addInt32(iFrameGrabberOf->width());
81  break;
82  case ImgVocab: {
83  reply.clear();
84  ImageType image;
85  iFrameGrabberOf->getImage(image);
86 
87  if (image.width() == 0 || image.height() == 0 || image.getRawImage() == nullptr) {
88  reply.addVocab32(VOCAB_FAILED);
89  reply.addString("Could not retrieve image from device.");
90  yCError(FRAMEGRABBEROF_RESPONDER) << "Could not retrieve image from device.";
91  return false;
92  }
93 
94  reply.addVocab32(IfVocab);
95  reply.addVocab32(ImgVocab);
96  reply.addVocab32(VOCAB_IS);
97  auto& b = reply.addList();
99  } break;
100  case VOCAB_CROP: {
101  reply.clear();
102  // If the device driver support it, use the device implementation, because it may be more efficient.
103  // If not, acquire the whole image and crop it here before sending it.
104 
105  if (cmd.size() != 5) {
106  reply.addVocab32(VOCAB_FAILED);
107  reply.addString("GetImageCrop failed: Invalid command received.");
108  yCError(FRAMEGRABBEROF_RESPONDER) << "GetImageCrop failed: Invalid command received, got " << cmd.toString();
109  return false;
110  }
111 
112  yarp::os::Bottle* list = cmd.get(4).asList();
113  if (!list) {
114  reply.addVocab32(VOCAB_FAILED);
115  reply.addString("GetImageCrop failed: Empty vertices list received.");
116  yCError(FRAMEGRABBEROF_RESPONDER) << "GetImageCrop failed: Empty vertices list received.";
117  return false;
118  }
119 
120  size_t nPoints = list->size() / 2; // divided by 2 because each pixel is identified by 2 numbers (u,v)
121 
123  vertices.resize(nPoints);
124 
125  for (size_t i = 0; i < nPoints; i++) {
126  vertices[i].first = list->get(i * 2).asInt32();
127  vertices[i].second = list->get(i * 2 + 1).asInt32();
128  }
129 
130  ImageType cropped;
131 
132  if (iFrameGrabberOf->getImageCrop(static_cast<cropType_id_t>(cmd.get(3).asVocab32()), vertices, cropped)) {
133  // use the device output
134  } else {
135  // In case the device has not yet implemented this feature, do it here (less efficient)
136  if (cmd.get(3).asVocab32() == YARP_CROP_RECT) {
137  if (nPoints != 2) {
138  reply.addVocab32(VOCAB_FAILED);
139  reply.addString("GetImageCrop failed: RECT mode requires 2 vertices.");
140  yCError(FRAMEGRABBEROF_RESPONDER) << "GetImageCrop failed: RECT mode requires 2 vertices, got " << nPoints;
141  return false;
142  }
143  ImageType full;
144  iFrameGrabberOf->getImage(full);
145 
146  if (!yarp::sig::utils::cropRect(full, vertices[0], vertices[1], cropped)) {
147  reply.addVocab32(VOCAB_FAILED);
148  reply.addString("GetImageCrop failed: utils::cropRect error.");
149  yCError(FRAMEGRABBEROF_RESPONDER, "GetImageCrop failed: utils::cropRect error: (%d, %d) (%d, %d)",
150  vertices[0].first,
151  vertices[0].second,
152  vertices[1].first,
153  vertices[1].second);
154  return false;
155  }
156  } else if (cmd.get(3).asVocab32() == YARP_CROP_LIST) {
157  reply.addVocab32(VOCAB_FAILED);
158  reply.addString("List type not yet implemented");
159  yCError(FRAMEGRABBEROF_RESPONDER) << "List type not yet implemented";
160  return false;
161  } else {
162  reply.addVocab32(VOCAB_FAILED);
163  reply.addString("Crop type unknown");
164  yCError(FRAMEGRABBEROF_RESPONDER) << "Crop type unknown";
165  return false;
166  }
167  }
168 
169  reply.addVocab32(IfVocab);
170  reply.addVocab32(VOCAB_CROP);
171  reply.addVocab32(VOCAB_IS);
172  auto& b = reply.addList();
174  return true;
175  } break;
176  }
177  break;
178 
179  case VOCAB_SET: // Nothing to do here yet
180  default:
181  reply.addVocab32(VOCAB_FAILED);
182  reply.addString("Received an unknown command");
183  yCError(FRAMEGRABBEROF_RESPONDER) << "Received an unknown command " << cmd.toString();
184  break;
185  }
186  }
187  return true;
188 }
189 
190 } // namespace framegrabber
191 } // namespace proto
192 } // namespace yarp
193 
194 
195 #endif // YARP_FRAMEGRABBER_PROTOCOL_FRAMEGRABBEROF_RESPONDER_INL_H
constexpr yarp::conf::vocab32_t VOCAB_CROP
Definition: CameraVocabs.h:38
constexpr yarp::conf::vocab32_t VOCAB_IS
Definition: GenericVocabs.h:14
constexpr yarp::conf::vocab32_t VOCAB_WIDTH
Definition: GenericVocabs.h:41
constexpr yarp::conf::vocab32_t VOCAB_GET
Definition: GenericVocabs.h:13
constexpr yarp::conf::vocab32_t VOCAB_FAILED
Definition: GenericVocabs.h:16
constexpr yarp::conf::vocab32_t VOCAB_SET
Definition: GenericVocabs.h:12
constexpr yarp::conf::vocab32_t VOCAB_HEIGHT
Definition: GenericVocabs.h:42
cropType_id_t
@ YARP_CROP_LIST
@ YARP_CROP_RECT
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:164
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
Definition: Bottle.cpp:182
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:121
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:140
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:211
static bool copyPortable(const PortWriter &writer, PortReader &reader)
Copy one portable to another, via writing and reading.
Definition: Portable.cpp:16
virtual yarp::conf::vocab32_t asVocab32() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:228
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
bool configure(yarp::dev::IFrameGrabberOf< ImageType > *interface)
bool respond(const yarp::os::Bottle &cmd, yarp::os::Bottle &response) override
Respond to a message.
Provides:
Definition: Vector.h:119
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:222
#define yCError(component,...)
Definition: LogComponent.h:154
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
std::int32_t vocab32_t
Definition: numeric.h:78
bool cropRect(const yarp::sig::Image &inImg, const std::pair< unsigned int, unsigned int > &vertex1, const std::pair< unsigned int, unsigned int > &vertex2, yarp::sig::Image &outImg)
Crop a rectangle area out of an image given two opposite vertices.
Definition: ImageUtils.cpp:113
The main, catch-all namespace for YARP.
Definition: dirs.h:16