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