AbstractRecordingStrategy.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package visionx::imrec
17  * @author Christian R. G. Dreher <christian.dreher@student.kit.edu>
18  * @date 2018
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 
24 // Metadata version to handle potential breaking changes in the future.
25 #define METADATA_VERSION "2.0"
26 
27 
29 
30 
31 // STD/STL
32 #include <filesystem>
33 
34 // OpenCV 2
35 #include <opencv2/opencv.hpp>
36 
37 // IVT
38 #include <Image/ByteImage.h>
39 
40 // ArmarX
43 
45 
47 {
48  // pass
49 }
50 
52  const std::filesystem::path& file_path) :
53  m_file_path{file_path}, m_recording{false}
54 {
55  // pass
56 }
57 
59 {
60  if (m_recording)
61  {
62  stopRecording();
63  }
64 }
65 
66 bool
68 {
69  return m_recording;
70 }
71 
72 void
74 {
75  ARMARX_CHECK_EXPRESSION(not m_recording)
76  << "Instance has already been initialised for recording";
77  ARMARX_CHECK_EXPRESSION(not std::filesystem::exists(m_file_path)) << "File already exists";
78 
79  std::filesystem::create_directories(m_file_path.parent_path());
80 
81  m_recording = true;
82 }
83 
84 void
86  const std::chrono::microseconds time)
87 {
88  // Default implementations of recordFrame just convert the parameter and call the other recordFrame method.
89  // This way only one method needs to be overridden in the interface-implementing classes
90 
91  // Call cv::Mat variant of recordFrame(...)
92  cv::Mat cv_frame;
93  visionx::imrec::convert(frame, cv_frame);
94  recordFrame(cv_frame, time);
95 }
96 
97 void
99  const std::chrono::microseconds time)
100 {
101  // Default implementations of recordFrame just convert the parameter and call the other recordFrame method.
102  // This way only one method needs to be overridden in the interface-implementing classes
103 
104  // Call CByteImage variant of recordFrame(...)
105  CByteImage ivt_frame;
106  visionx::imrec::convert(frame, ivt_frame);
107  recordFrame(ivt_frame, time);
108 }
109 
110 void
112 {
113  writeMetadataLine("frame_count", "unsigned int", std::to_string(m_sequence_number));
114  m_recording = false;
115  if (m_metadata_file.is_open())
116  {
117  m_metadata_file.close();
118  }
119 }
120 
121 std::filesystem::path
123 {
124  return m_file_path;
125 }
126 
127 std::filesystem::path
129 {
130  return m_file_path.parent_path();
131 }
132 
133 std::filesystem::path
135 {
136  return m_file_path.stem();
137 }
138 
139 std::filesystem::path
141 {
142  return m_file_path.extension();
143 }
144 
145 std::filesystem::path
147 {
148  std::filesystem::path path = getPath();
149  std::filesystem::path filename = getStem().string() + "_metadata.csv";
150  return std::filesystem::canonical(path) / filename;
151 }
152 
153 std::tuple<unsigned int, std::string>
155  const CByteImage& frame,
156  const std::chrono::microseconds timestamp)
157 {
158  writeMetadataLine(
159  "frame_height", "unsigned int", std::to_string(static_cast<unsigned int>(frame.height)));
160  writeMetadataLine(
161  "frame_width", "unsigned int", std::to_string(static_cast<unsigned int>(frame.width)));
162  return writeMetadataFrameFileInfo(timestamp);
163 }
164 
165 std::tuple<unsigned int, std::string>
167  const cv::Mat& frame,
168  const std::chrono::microseconds timestamp)
169 {
170  writeMetadataLine("frame_height",
171  "unsigned int",
172  std::to_string(static_cast<unsigned int>(frame.size().height)));
173  writeMetadataLine("frame_width",
174  "unsigned int",
175  std::to_string(static_cast<unsigned int>(frame.size().width)));
176  return writeMetadataFrameFileInfo(timestamp);
177 }
178 
179 std::tuple<unsigned int, std::string>
180 visionx::imrec::AbstractRecordingStrategy::writeMetadataFrameFileInfo(
181  const std::chrono::microseconds timestamp)
182 {
183  const unsigned int sequence_number = m_sequence_number++;
184 
185  // Write local system reference time of not already done.
186  if (m_reference_time.count() == 0)
187  {
188  m_reference_time = timestamp;
189  writeMetadataDatetime("frame_0_system_reference_time", timestamp);
190  }
191 
192  // Normalize time to time since frame_0.
193  const std::chrono::microseconds normalized_time = timestamp - m_reference_time;
194  const std::string normalized_time_str = timestamp_to_string(normalized_time);
195 
196  // Write frame_<SEQUENCE_NUMBER> = <FRAME_NAME>.
197  writeMetadataLine("frame_" + std::to_string(sequence_number), "string", normalized_time_str);
198 
199  return {sequence_number, normalized_time_str};
200 }
201 
202 void
204  const std::string& var_name,
205  const std::chrono::microseconds timestamp)
206 {
207  writeMetadataLine(var_name + "_us", "long", std::to_string(timestamp.count()));
208  writeMetadataLine(var_name + "_hr", "string", datetime_to_string(timestamp));
209 }
210 
211 void
213  const std::string_view var_type,
214  const std::string_view var_value)
215 {
216  if (not m_metadata_file.is_open())
217  {
218  m_metadata_file.open(getMetadataPath());
219  writeMetadataLine("name", "type", "value");
220  writeMetadataLine("metadata_version", "string", METADATA_VERSION);
221  }
222 
223  // If the given variable was already written, do nothing
224  if (m_written_metadata_variables.insert(var_name).second == false)
225  {
226  return;
227  }
228 
229  m_metadata_file << var_name << "," << var_type << "," << var_value << "\n";
230  m_metadata_file.flush();
231 }
visionx::imrec::AbstractRecordingStrategy::AbstractRecordingStrategy
AbstractRecordingStrategy()
Default constructor to start the recording manually.
Definition: AbstractRecordingStrategy.cpp:46
visionx::imrec::AbstractRecordingStrategy::isRecording
virtual bool isRecording() const
Indicates whether this instance is already initialised for recording.
Definition: AbstractRecordingStrategy.cpp:67
visionx::imrec::AbstractRecordingStrategy::stopRecording
virtual void stopRecording()
Stops the recording.
Definition: AbstractRecordingStrategy.cpp:111
visionx::imrec::AbstractRecordingStrategy::writeMetadataFrame
virtual std::tuple< unsigned int, std::string > writeMetadataFrame(const CByteImage &frame, std::chrono::microseconds timestamp)
Definition: AbstractRecordingStrategy.cpp:154
visionx::imrec::AbstractRecordingStrategy::getStem
virtual std::filesystem::path getStem() const
Gets the stem of the configured file (filename without extension)
Definition: AbstractRecordingStrategy.cpp:134
visionx::imrec::AbstractRecordingStrategy::writeMetadataLine
virtual void writeMetadataLine(const std::string &var_name, std::string_view var_type, std::string_view var_value)
Definition: AbstractRecordingStrategy.cpp:212
METADATA_VERSION
#define METADATA_VERSION
Definition: AbstractRecordingStrategy.cpp:25
visionx::imrec::AbstractRecordingStrategy::getDotExtension
virtual std::filesystem::path getDotExtension() const
Gets the extension plus preceeded dot of the configured file (e.g.
Definition: AbstractRecordingStrategy.cpp:140
visionx::imrec::AbstractRecordingStrategy::~AbstractRecordingStrategy
virtual ~AbstractRecordingStrategy()
Destructor.
Definition: AbstractRecordingStrategy.cpp:58
visionx::imrec::convert
void convert(const CByteImage &in, cv::Mat &out)
Converts an IVT CByteImage to OpenCV's BGR Mat.
Definition: helper.cpp:40
AbstractRecordingStrategy.h
visionx::imrec::AbstractRecordingStrategy::writeMetadataDatetime
virtual void writeMetadataDatetime(const std::string &var_name, std::chrono::microseconds timestamp)
Definition: AbstractRecordingStrategy.cpp:203
visionx::imrec::AbstractRecordingStrategy::getPath
virtual std::filesystem::path getPath() const
Gets the path to the recording without filename.
Definition: AbstractRecordingStrategy.cpp:128
filename
std::string filename
Definition: VisualizationRobot.cpp:86
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
visionx::imrec::timestamp_to_string
std::string timestamp_to_string(std::chrono::microseconds ts)
Definition: helper.cpp:112
ExpressionException.h
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
visionx::imrec::AbstractRecordingStrategy::recordFrame
virtual void recordFrame(const CByteImage &frame, std::chrono::microseconds timestamp)
Adds the given frame to the recording.
Definition: AbstractRecordingStrategy.cpp:85
visionx::imrec::AbstractRecordingStrategy::startRecording
virtual void startRecording()
Starts the recording manually if constructed empty.
Definition: AbstractRecordingStrategy.cpp:73
visionx::imrec::AbstractRecordingStrategy::getMetadataPath
virtual std::filesystem::path getMetadataPath() const
Definition: AbstractRecordingStrategy.cpp:146
visionx::imrec::datetime_to_string
std::string datetime_to_string(std::chrono::microseconds ts)
Definition: helper.cpp:77
visionx::imrec::AbstractRecordingStrategy::getFilePath
virtual std::filesystem::path getFilePath() const
Gets the raw file path for the recording as configured.
Definition: AbstractRecordingStrategy.cpp:122
Logging.h
helper.h