Visual Servoing Platform  version 3.5.1 under development (2023-06-08)
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 
188  bool record(const vpImage<Type> &I, std::string *data = NULL, bool trigger_recording = false,
189  bool disable_left_click = false)
190  {
191  if (I.display) {
192  if (!m_seqname.empty()) {
193  if (!disable_left_click) {
194  if (!m_recording_mode) { // continuous
195  if (m_start_recording) {
197  10 * vpDisplay::getDownScalingFactor(I), "Left click: stop recording",
198  vpColor::red);
199  } else {
201  10 * vpDisplay::getDownScalingFactor(I), "Left click: start recording",
202  vpColor::red);
203  }
204  } else {
206  "Left click: record image", vpColor::red);
207  }
208  }
210  "Right click: quit", vpColor::red);
211  } else {
213  "Click to quit", vpColor::red);
214  }
215 
216  if (!m_seqname.empty()) {
218  m_text_record_mode, vpColor::red);
219  }
221  if (vpDisplay::getClick(I, button, false)) {
222  if (!m_seqname.empty()) { // Recording requested
223  if (button == vpMouseButton::button1 && !disable_left_click) { // enable/disable recording
224  m_start_recording = !m_start_recording;
225  } else if (button == vpMouseButton::button3) { // quit
226  return true;
227  }
228  } else { // any button to quit
229  return true;
230  }
231  }
232  } else if (!m_seqname.empty()) {
233  m_start_recording = true;
234  }
235 
236  if (trigger_recording) {
237  m_start_recording = true;
238  }
239 
240  m_recording_trigger = m_start_recording;
241 
242  if (m_start_recording) {
243 
244  if (m_directory_to_create) {
245  std::cout << "Create directory \"" << m_directory << "\"" << std::endl;
246  vpIoTools::makeDirectory(m_directory);
247  m_directory_to_create = false;
248  }
249 
250  push(I, data);
251 
252  if (m_recording_mode == 1) { // single shot mode
253  m_start_recording = false;
254  }
255  }
256  return false;
257  }
258 
263  void setMaxQueueSize(const size_t max_queue_size) { m_maxQueueSize = max_queue_size; }
264 
265 private:
266  bool m_cancelled;
267  std::condition_variable m_cond;
268  std::queue<vpImage<Type> > m_queue_image;
269  std::queue<std::string> m_queue_data;
270  size_t m_maxQueueSize;
271  std::mutex m_mutex;
272  std::string m_seqname;
273  std::string m_directory;
274  int m_recording_mode;
275  bool m_start_recording;
276  std::string m_text_record_mode;
277  bool m_directory_to_create;
278  bool m_recording_trigger;
279 };
280 
281 #endif
282 #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:188
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:263
void push(const vpImage< Type > &I, std::string *data)
Definition: vpImageQueue.h:155
Definition of the vpImage class member functions.
Definition: vpImage.h:74
vpDisplay * display
Definition: vpImage.h:145
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:435
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:585
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1651