YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
FakeFrameGrabber.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "FakeFrameGrabber.h"
8
10#include <yarp/os/LogStream.h>
11#include <yarp/sig/ImageDraw.h>
12
13#include <cstdio>
14#include <thread>
15#include <random>
16
17using namespace yarp::os;
18using namespace yarp::dev;
19using namespace yarp::sig;
20using namespace yarp::sig::draw;
21
22namespace {
23YARP_LOG_COMPONENT(FAKEFRAMEGRABBER, "yarp.device.fakeFrameGrabber")
24} // namespace
25
27{
28 yarp::os::Bottle command;
29 yarp::os::Bottle reply;
30 bool ok = command.read(connection);
31 if (!ok) {
32 return false;
33 }
34 reply.clear();
35
36 if (command.get(0).asString()=="help")
37 {
38 reply.addVocab32("many");
39 reply.addString("set_mode <mode>");
40 reply.addString("set_image <file_name>/off");
41 reply.addString("available modes: ball, line, grid, size, rand, none, time");
42 reply.addString("set_noise on/off");
43 reply.addString("set_snr <snr>");
44 reply.addString("");
45 }
46 else if (command.get(0).asString() == "set_mode")
47 {
48 m_mode= command.get(1).asString();
49 reply.addString("ack");
50 }
51 else if (command.get(0).asString() == "set_image")
52 {
53 if (command.get(1).asString() == "off")
54 {
55 m_have_bg=false;
56 reply.addString("ack");
57 }
58 else
59 {
60 if (yarp::sig::file::read(background, command.get(1).asString()))
61 {
62 m_width = background.width();
63 m_height = background.height();
64 m_have_bg = true;
65 reply.addString("ack");
66 }
67 else
68 {
69 m_have_bg = false;
70 reply.addString("err");
71 }
72 }
73 }
74 else if (command.get(0).asString() == "set_noise")
75 {
76 if (command.get(1).asString() == "off") {
77 m_add_noise = false;
78 reply.addString("ack");
79 } else if (command.get(1).asString() == "on") {
80 m_add_noise = true;
81 reply.addString("ack");
82 } else {
83 reply.addString("err");
84 }
85 }
86 else if (command.get(0).asString() == "set_snr")
87 {
88 m_snr = yarp::conf::clamp(command.get(1).asFloat64(), 0.0, 1.0);
89 reply.addString("ack");
90 }
91 else
92 {
93 reply.addString("Unknown command. Type 'help'.");
94 }
95
97 if (returnToSender != nullptr)
98 {
99 reply.write(*returnToSender);
100 }
101
102 return true;
103}
104
106 stop();
107 m_rpcPort.close();
108 return true;
109}
110
112{
113 if (!this->parseParams(config)) {return false;}
114
115 m_intrinsic.put("physFocalLength",m_physFocalLength);
116 m_intrinsic.put("focalLengthX",m_focalLengthX);
117 m_intrinsic.put("focalLengthY",m_focalLengthY);
118 m_intrinsic.put("principalPointX",m_principalPointX);
119 m_intrinsic.put("principalPointY",m_principalPointY);
120
121 Value* val = Value::makeList();
122 auto* bb = val->asList();
123 for (double num : m_rectificationMatrix) { bb->addFloat64(num); }
124 m_intrinsic.put("rectificationMatrix",val);
125
126 m_intrinsic.put("distortionModel", m_distortionModel);
127 m_intrinsic.put("k1",m_k1);
128 m_intrinsic.put("k2",m_k2);
129 m_intrinsic.put("k3",m_k3);
130 m_intrinsic.put("t1",m_t1);
131 m_intrinsic.put("t2",m_t2);
132 //Only for debug
134 conf1.height=128;
135 conf1.width=128;
136 conf1.framerate=60.0;
137 conf1.pixelCoding=VOCAB_PIXEL_RGB;
138 configurations.push_back(conf1);
139
141 conf2.height=256;
142 conf2.width=256;
143 conf2.framerate=30.0;
144 conf2.pixelCoding=VOCAB_PIXEL_BGR;
145 configurations.push_back(conf2);
146
148 conf3.height=512;
149 conf3.width=512;
150 conf3.framerate=15.0;
151 conf3.pixelCoding=VOCAB_PIXEL_MONO;
152 configurations.push_back(conf3);
153
154 if (m_freq>0)
155 {
156 m_period = 1/ m_freq;
157 }
158 else if (m_period>0)
159 {
160 //ok
161 }
162 else
163 {
164 yCWarning(FAKEFRAMEGRABBER, "Either `period` or `freq` parameters must be a valid >0 value");
165 }
166
167 if (!m_src.empty())
168 {
169 if (!yarp::sig::file::read(background, m_src))
170 {
171 yCWarning(FAKEFRAMEGRABBER, "Unable to open file");
172 return false;
173 }
174 }
175 if (background.width()>0)
176 {
177 if (m_width>0 || m_height>0)
178 {
179 yCWarning(FAKEFRAMEGRABBER, "width and height options are ignored when passing a background image");
180 }
181 m_width = background.width();
182 m_height = background.height();
183 m_have_bg = true;
184 }
185
186
187 m_snr = yarp::conf::clamp(m_snr, 0.0, 1.0);
188 m_mono = m_mono || m_bayer;
189
191 "Test grabber period %g / freq %g , mode %s",
192 m_period,
193 (1.0/m_period),
194 m_mode.c_str());
195
196 m_bx = m_width/2;
197 m_by = m_height/2;
198
199 for (auto& buff : buffs) {
200 buff.resize(m_width, m_height);
201 buff.zero();
202 }
203
204 if (!m_rpcPort.open(m_fakeFrameGrabber_rpc_port.c_str()))
205 {
206 yCError(FAKEFRAMEGRABBER, "Failed to open port %s", m_fakeFrameGrabber_rpc_port.c_str());
207 yCError(FAKEFRAMEGRABBER, "Do you have multiple FakeFrameGrabber devices running?");
208 yCError(FAKEFRAMEGRABBER, "If yes, use the `fakeFrameGrabber_rpc_port` parameter to set a different name for each of them");
209 return false;
210 }
211 m_rpcPort.setReader(*this);
212
213 start();
214
215 return true;
216}
217
219 double now = yarp::os::Time::now();
220
221 if (now-prev>1000) {
222 prev = now;
223 }
224 double dt = m_period-(now-prev);
225
226 if (dt>0) {
228 }
229
230 // this is the controlled instant when we consider the
231 // image as going out
232 prev += m_period;
233}
234
236{
237 std::lock_guard<std::mutex> lock(rpc_methods_mutex);
238 return m_height;
239}
240
242{
243 std::lock_guard<std::mutex> lock(rpc_methods_mutex);
244 return m_width;
245}
246
248{
249 while (!isStopping()) {
250 for (size_t i = 0; i < 2 && !isStopping(); ++i) {
251 if (!m_syncro) {
252 std::unique_lock<std::mutex> lk(mutex[i]);
253 createTestImage(buffs[i], buff_ts[i]);
254 timing();
255 lk.unlock();
256
257 curr_buff_mutex.lock();
258 curr_buff = i;
259 curr_buff_mutex.unlock();
260 std::this_thread::yield();
261 } else {
262 std::unique_lock<std::mutex> lk(mutex[i]);
263 img_consumed_cv[i].wait(lk, [&]{ if (img_ready[i]) {img_ready_cv[i].notify_one();} return (isStopping() || img_consumed[i]);});
264 if (isStopping()) {
265 break;
266 }
267 img_ready[i] = false;
268 img_consumed[i] = false;
269 createTestImage(buffs[i], buff_ts[i]);
270 img_ready[i] = true;
271 img_ready_cv[i].notify_all();
272 }
273 }
274 }
275}
276
278{
279 // Unlock any blocked thread.
280 if (m_syncro) {
281 for (size_t i = 0; i < 2; ++i) {
282 std::unique_lock<std::mutex> lk(mutex[i]);
283 img_consumed[i] = true;
284 img_consumed_cv[i].notify_all();
285 img_ready[i] = true;
286 img_ready_cv[i].notify_all();
287 }
288 }
289}
290
291
293{
294 if (!isRunning()) {
295 return ReturnValue::return_code::return_value_error_not_ready;
296 }
297
298 if (!m_syncro) {
299 curr_buff_mutex.lock();
300 size_t cb = curr_buff;
301 std::unique_lock<std::mutex> lk(mutex[cb]);
302 // Release the mutex after we get the lock on current image to avoid
303 // that the image is swapped while we are waiting to read it
304 curr_buff_mutex.unlock();
305 image.copy(buffs[cb]);
306 stamp.update(buff_ts[cb]);
307 } else {
308 curr_buff_mutex.lock();
309 timing();
310 size_t cb = curr_buff;
311 std::unique_lock<std::mutex> lk(mutex[cb]);
312 img_ready_cv[cb].wait(lk, [&]{return (!isRunning() || img_ready[cb]);});
313 if (!isRunning()) {
314 return ReturnValue::return_code::return_value_error_not_ready;
315 }
316
317 image.copy(buffs[cb]);
318 stamp.update(buff_ts[cb]);
319 img_consumed[cb] = true;
320 img_consumed_cv[cb].notify_one();
321
322 curr_buff = (cb + 1) % 2;
323 curr_buff_mutex.unlock();
324 }
325
326 return ReturnValue_ok;
327}
328
330{
331 if (!isRunning()) {
332 return ReturnValue::return_code::return_value_error_not_ready;
333 }
334
335 if (!m_syncro) {
336 curr_buff_mutex.lock();
337 size_t cb = curr_buff;
338 std::unique_lock<std::mutex> lk(mutex[cb]);
339 curr_buff_mutex.unlock();
340 if (m_bayer) {
341 makeSimpleBayer(buffs[cb], image);
342 } else {
343 image.copy(buffs[cb]);
344 }
345 stamp.update(buff_ts[cb]);
346 } else {
347 curr_buff_mutex.lock();
348 timing();
349 size_t cb = curr_buff;
350 std::unique_lock<std::mutex> lk(mutex[cb]);
351 img_ready_cv[cb].wait(lk, [&]{return (!isRunning() || img_ready[cb]);});
352 if (!isRunning()) {
353 return ReturnValue::return_code::return_value_error_not_ready;
354 }
355 if (m_bayer) {
356 makeSimpleBayer(buffs[cb], image);
357 } else {
358 image.copy(buffs[cb]);
359 }
360 stamp.update(buff_ts[cb]);
361 img_consumed[cb] = true;
362 img_consumed_cv[cb].notify_one();
363
364 curr_buff = (cb + 1) % 2;
365 curr_buff_mutex.unlock();
366 }
367
368 return ReturnValue_ok;
369}
370
372 std::vector<yarp::dev::vertex_t> vertices,
374{
375 yCDebugThrottle(FAKEFRAMEGRABBER, 5.0) << "Hardware crop requested!";
377}
378
380 std::vector<yarp::dev::vertex_t> vertices,
382{
383 yCDebugThrottle(FAKEFRAMEGRABBER, 5.0) << "Hardware crop requested!";
385}
386
388{
389 std::lock_guard<std::mutex> lock(rpc_methods_mutex);
390 return stamp;
391}
@ VOCAB_PIXEL_BGR
Definition Image.h:49
@ VOCAB_PIXEL_MONO
Definition Image.h:42
@ VOCAB_PIXEL_RGB
Definition Image.h:44
#define ReturnValue_ok
Definition ReturnValue.h:80
bool parseParams(const yarp::os::Searchable &config) override
Parse the DeviceDriver parameters.
int width() const override
Return the width of each frame.
yarp::os::Stamp getLastInputStamp() override
Return the time stamp relative to the last acquisition.
int height() const override
Return the height of each frame.
bool open(yarp::os::Searchable &config) override
yarp::dev::ReturnValue getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
Get an image from the frame grabber.
yarp::dev::ReturnValue getImageCrop(yarp::dev::cropType_id_t cropType, std::vector< yarp::dev::vertex_t > vertices, yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
Get a crop of the image from the frame grabber.
void run() override
Main body of the new thread.
void onStop() override
Call-back, called while halting the thread (before join).
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
bool close() override
Close the DeviceDriver.
Struct describing a possible camera configuration.
Read a YARP-format image (of a specific type) from a device.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:65
void addVocab32(yarp::conf::vocab32_t x)
Places a 32 bit vocabulary item in the bottle, at the end of the list.
Definition Bottle.cpp:164
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition Bottle.cpp:246
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:252
void clear()
Empties the bottle of any objects it contains.
Definition Bottle.cpp:121
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition Bottle.cpp:236
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition Bottle.cpp:176
A mini-server for performing network communication in the background.
An interface for reading from a network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
An interface for writing to a network connection.
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition Port.cpp:470
void close() override
Stop port activity.
Definition Port.cpp:330
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition Port.cpp:79
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
A base class for nested structures that can be searched.
Definition Searchable.h:31
An abstraction for a time stamp and/or sequence number.
Definition Stamp.h:21
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition Stamp.cpp:124
bool stop()
Stop the thread.
Definition Thread.cpp:81
bool isStopping()
Returns true if the thread is stopping (Thread::stop has been called).
Definition Thread.cpp:99
bool isRunning()
Returns true if the thread is running (Thread::start has been called successfully and the thread has ...
Definition Thread.cpp:105
bool start()
Start the new thread running.
Definition Thread.cpp:93
A single value (typically within a Bottle).
Definition Value.h:44
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition Value.cpp:228
static Value * makeList()
Create a list Value.
Definition Value.cpp:452
virtual Bottle * asList() const
Get list value.
Definition Value.cpp:252
virtual std::string asString() const
Get string value.
Definition Value.cpp:246
Typed image class.
Definition Image.h:603
size_t width() const
Gets width of image in pixels.
Definition Image.h:171
size_t height() const
Gets height of image in pixels.
Definition Image.h:177
#define yCInfo(component,...)
#define yCError(component,...)
#define yCDebugThrottle(component, period,...)
#define yCWarning(component,...)
#define YARP_LOG_COMPONENT(name,...)
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
Definition numeric.h:92
For streams capable of holding different kinds of content, check what they actually have.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
void delay(double seconds)
Wait for a certain number of seconds.
Definition Time.cpp:111
An interface to the operating system, including Port based communication.
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)