Visual Servoing Platform  version 3.5.1 under development (2022-07-05)
vpImageQueue.h
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image queue for storage helper.
33  *
34  *****************************************************************************/
35 
36 #ifndef vpImageQueue_h
37 #define vpImageQueue_h
38 
39 #include <visp3/core/vpConfig.h>
40 
41 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
42 
43 #include <condition_variable>
44 #include <mutex>
45 #include <queue>
46 #include <string>
47 #include <thread>
48 
49 #include <visp3/core/vpDisplay.h>
50 #include <visp3/core/vpIoTools.h>
51 
63 template <class Type> class vpImageQueue
64 {
65 public:
66  struct cancelled {
67  };
68 
75  vpImageQueue(const std::string &seqname, int record_mode)
76  : m_cancelled(false), m_cond(), m_queue_image(), m_queue_data(), m_maxQueueSize(1024 * 8), m_mutex(),
77  m_seqname(seqname), m_recording_mode(record_mode), m_start_recording(false), m_directory_to_create(false),
78  m_recording_trigger(false)
79  {
80  m_directory = vpIoTools::getParent(seqname);
81  if (!m_directory.empty()) {
82  if (!vpIoTools::checkDirectory(m_directory)) {
83  m_directory_to_create = true;
84  }
85  }
86  m_text_record_mode =
87  std::string("Record mode: ") + (m_recording_mode ? std::string("single") : std::string("continuous"));
88  }
89 
93  void cancel()
94  {
95  std::lock_guard<std::mutex> lock(m_mutex);
96  std::cout << "Wait to finish saving images..." << std::endl;
97  m_cancelled = true;
98  m_cond.notify_all();
99  }
100 
104  int getRecordingMode() const { return m_recording_mode; }
105 
109  bool getRecordingTrigger() const { return m_recording_trigger; }
110 
114  std::string getSeqName() const { return m_seqname; }
115 
123  void pop(vpImage<Type> &I, std::string &data)
124  {
125  std::unique_lock<std::mutex> lock(m_mutex);
126 
127  while (m_queue_image.empty()) {
128  if (m_cancelled) {
129  throw cancelled();
130  }
131 
132  m_cond.wait(lock);
133 
134  if (m_cancelled) {
135  throw cancelled();
136  }
137  }
138 
139  I = m_queue_image.front();
140 
141  m_queue_image.pop();
142 
143  if (!m_queue_data.empty()) {
144  data = m_queue_data.front();
145  m_queue_data.pop();
146  }
147  }
148 
155  void push(const vpImage<Type> &I, std::string *data)
156  {
157  std::lock_guard<std::mutex> lock(m_mutex);
158 
159  m_queue_image.push(I);
160 
161  if (data != NULL) {
162  m_queue_data.push(*data);
163  }
164 
165  // Pop extra data in the queue
166  while (m_queue_image.size() > m_maxQueueSize) {
167  m_queue_image.pop();
168  }
169 
170  if (data != NULL) {
171  while (m_queue_data.size() > m_maxQueueSize) {
172  m_queue_data.pop();
173  }
174  }
175 
176  m_cond.notify_one();
177  }
178 
186  bool record(const vpImage<Type> &I, std::string *data = NULL, bool trigger_recording = false,
187  bool disable_left_click = false)
188  {
189  if (I.display) {
190  if (!m_seqname.empty()) {
191  if (!disable_left_click) {
192  if (!m_recording_mode) { // continuous
193  if (m_start_recording) {
195  10 * vpDisplay::getDownScalingFactor(I), "Left click: stop recording",
196  vpColor::red);
197  } else {
199  10 * vpDisplay::getDownScalingFactor(I), "Left click: start recording",
200  vpColor::red);
201  }
202  } else {
204  "Left click: record image", vpColor::red);
205  }
206  }
208  "Right click: quit", vpColor::red);
209  } else {
211  "Click to quit", vpColor::red);
212  }
213 
214  if (!m_seqname.empty()) {
216  m_text_record_mode, vpColor::red);
217  }
219  if (vpDisplay::getClick(I, button, false)) {
220  if (!m_seqname.empty()) { // Recording requested
221  if (button == vpMouseButton::button1 && !disable_left_click) { // enable/disable recording
222  m_start_recording = !m_start_recording;
223  } else if (button == vpMouseButton::button3) { // quit
224  return true;
225  }
226  } else { // any button to quit
227  return true;
228  }
229  }
230  } else if (!m_seqname.empty()) {
231  m_start_recording = true;
232  }
233 
234  if (trigger_recording) {
235  m_start_recording = true;
236  }
237 
238  m_recording_trigger = m_start_recording;
239 
240  if (m_start_recording) {
241 
242  if (m_directory_to_create) {
243  std::cout << "Create directory \"" << m_directory << "\"" << std::endl;
244  vpIoTools::makeDirectory(m_directory);
245  m_directory_to_create = false;
246  }
247 
248  push(I, data);
249 
250  if (m_recording_mode == 1) { // single shot mode
251  m_start_recording = false;
252  }
253  }
254  return false;
255  }
256 
261  void setMaxQueueSize(const size_t max_queue_size) { m_maxQueueSize = max_queue_size; }
262 
263 private:
264  bool m_cancelled;
265  std::condition_variable m_cond;
266  std::queue<vpImage<Type> > m_queue_image;
267  std::queue<std::string> m_queue_data;
268  size_t m_maxQueueSize;
269  std::mutex m_mutex;
270  std::string m_seqname;
271  std::string m_directory;
272  int m_recording_mode;
273  bool m_start_recording;
274  std::string m_text_record_mode;
275  bool m_directory_to_create;
276  bool m_recording_trigger;
277 };
278 
279 #endif
280 #endif
static const vpColor red
Definition: vpColor.h:217
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
unsigned int getDownScalingFactor()
Definition: vpDisplay.h:235
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
int getRecordingMode() const
Definition: vpImageQueue.h:104
void pop(vpImage< Type > &I, std::string &data)
Definition: vpImageQueue.h:123
bool getRecordingTrigger() const
Definition: vpImageQueue.h:109
vpImageQueue(const std::string &seqname, int record_mode)
Definition: vpImageQueue.h:75
bool record(const vpImage< Type > &I, std::string *data=NULL, bool trigger_recording=false, bool disable_left_click=false)
Definition: vpImageQueue.h:186
std::string getSeqName() const
Definition: vpImageQueue.h:114
void cancel()
Definition: vpImageQueue.h:93
void setMaxQueueSize(const size_t max_queue_size)
Definition: vpImageQueue.h:261
void push(const vpImage< Type > &I, std::string *data)
Definition: vpImageQueue.h:155
Definition of the vpImage class member functions.
Definition: vpImage.h:73
vpDisplay * display
Definition: vpImage.h:144
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:418
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:568
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1620