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
44 
45 
47  m_recording{false}
48 {
49  // pass
50 }
51 
52 
54  m_file_path{file_path},
55  m_recording{false}
56 {
57  // pass
58 }
59 
60 
62 {
63  if (m_recording)
64  {
65  stopRecording();
66  }
67 }
68 
69 
70 bool
72 {
73  return m_recording;
74 }
75 
76 
77 void
79 {
80  ARMARX_CHECK_EXPRESSION(not m_recording) << "Instance has already been initialised for recording";
81  ARMARX_CHECK_EXPRESSION(not std::filesystem::exists(m_file_path)) << "File already exists";
82 
83  std::filesystem::create_directories(m_file_path.parent_path());
84 
85  m_recording = true;
86 }
87 
88 
89 void
90 visionx::imrec::AbstractRecordingStrategy::recordFrame(const CByteImage& frame, const std::chrono::microseconds time)
91 {
92  // Default implementations of recordFrame just convert the parameter and call the other recordFrame method.
93  // This way only one method needs to be overridden in the interface-implementing classes
94 
95  // Call cv::Mat variant of recordFrame(...)
96  cv::Mat cv_frame;
97  visionx::imrec::convert(frame, cv_frame);
98  recordFrame(cv_frame, time);
99 }
100 
101 
102 void
103 visionx::imrec::AbstractRecordingStrategy::recordFrame(const cv::Mat& frame, const std::chrono::microseconds time)
104 {
105  // Default implementations of recordFrame just convert the parameter and call the other recordFrame method.
106  // This way only one method needs to be overridden in the interface-implementing classes
107 
108  // Call CByteImage variant of recordFrame(...)
109  CByteImage ivt_frame;
110  visionx::imrec::convert(frame, ivt_frame);
111  recordFrame(ivt_frame, time);
112 }
113 
114 
115 void
117 {
118  writeMetadataLine("frame_count", "unsigned int", std::to_string(m_sequence_number));
119  m_recording = false;
120  if (m_metadata_file.is_open())
121  {
122  m_metadata_file.close();
123  }
124 }
125 
126 
127 std::filesystem::path
129 {
130  return m_file_path;
131 }
132 
133 
134 std::filesystem::path
136 {
137  return m_file_path.parent_path();
138 }
139 
140 
141 std::filesystem::path
143 {
144  return m_file_path.stem();
145 }
146 
147 
148 std::filesystem::path
150 {
151  return m_file_path.extension();
152 }
153 
154 
155 std::filesystem::path
157 {
158  std::filesystem::path path = getPath();
159  std::filesystem::path filename = getStem().string() + "_metadata.csv";
160  return std::filesystem::canonical(path) / filename;
161 }
162 
163 
164 std::tuple<unsigned int, std::string>
165 visionx::imrec::AbstractRecordingStrategy::writeMetadataFrame(const CByteImage& frame, const std::chrono::microseconds timestamp)
166 {
167  writeMetadataLine("frame_height", "unsigned int", std::to_string(static_cast<unsigned int>(frame.height)));
168  writeMetadataLine("frame_width", "unsigned int", std::to_string(static_cast<unsigned int>(frame.width)));
169  return writeMetadataFrameFileInfo(timestamp);
170 }
171 
172 
173 std::tuple<unsigned int, std::string>
174 visionx::imrec::AbstractRecordingStrategy::writeMetadataFrame(const cv::Mat& frame, const std::chrono::microseconds timestamp)
175 {
176  writeMetadataLine("frame_height", "unsigned int", std::to_string(static_cast<unsigned int>(frame.size().height)));
177  writeMetadataLine("frame_width", "unsigned int", std::to_string(static_cast<unsigned int>(frame.size().width)));
178  return writeMetadataFrameFileInfo(timestamp);
179 }
180 
181 
182 std::tuple<unsigned int, std::string>
183 visionx::imrec::AbstractRecordingStrategy::writeMetadataFrameFileInfo(const std::chrono::microseconds timestamp)
184 {
185  const unsigned int sequence_number = m_sequence_number++;
186 
187  // Write local system reference time of not already done.
188  if (m_reference_time.count() == 0)
189  {
190  m_reference_time = timestamp;
191  writeMetadataDatetime("frame_0_system_reference_time", timestamp);
192  }
193 
194  // Normalize time to time since frame_0.
195  const std::chrono::microseconds normalized_time = timestamp - m_reference_time;
196  const std::string normalized_time_str = timestamp_to_string(normalized_time);
197 
198  // Write frame_<SEQUENCE_NUMBER> = <FRAME_NAME>.
199  writeMetadataLine("frame_" + std::to_string(sequence_number), "string", normalized_time_str);
200 
201  return {sequence_number, normalized_time_str};
202 }
203 
204 
205 void
206 visionx::imrec::AbstractRecordingStrategy::writeMetadataDatetime(const std::string& var_name, const std::chrono::microseconds timestamp)
207 {
208  writeMetadataLine(var_name + "_us", "long", std::to_string(timestamp.count()));
209  writeMetadataLine(var_name + "_hr", "string", datetime_to_string(timestamp));
210 }
211 
212 
213 void
214 visionx::imrec::AbstractRecordingStrategy::writeMetadataLine(const std::string& var_name, const std::string_view var_type, 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:71
visionx::imrec::AbstractRecordingStrategy::stopRecording
virtual void stopRecording()
Stops the recording.
Definition: AbstractRecordingStrategy.cpp:116
visionx::imrec::AbstractRecordingStrategy::writeMetadataFrame
virtual std::tuple< unsigned int, std::string > writeMetadataFrame(const CByteImage &frame, std::chrono::microseconds timestamp)
Definition: AbstractRecordingStrategy.cpp:165
visionx::imrec::AbstractRecordingStrategy::getStem
virtual std::filesystem::path getStem() const
Gets the stem of the configured file (filename without extension)
Definition: AbstractRecordingStrategy.cpp:142
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:214
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:149
visionx::imrec::AbstractRecordingStrategy::~AbstractRecordingStrategy
virtual ~AbstractRecordingStrategy()
Destructor.
Definition: AbstractRecordingStrategy.cpp:61
visionx::imrec::convert
void convert(const CByteImage &in, cv::Mat &out)
Converts an IVT CByteImage to OpenCV's Mat.
Definition: helper.cpp:41
AbstractRecordingStrategy.h
visionx::imrec::AbstractRecordingStrategy::writeMetadataDatetime
virtual void writeMetadataDatetime(const std::string &var_name, std::chrono::microseconds timestamp)
Definition: AbstractRecordingStrategy.cpp:206
visionx::imrec::AbstractRecordingStrategy::getPath
virtual std::filesystem::path getPath() const
Gets the path to the recording without filename.
Definition: AbstractRecordingStrategy.cpp:135
filename
std::string filename
Definition: VisualizationRobot.cpp:84
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
visionx::imrec::timestamp_to_string
std::string timestamp_to_string(std::chrono::microseconds ts)
Definition: helper.cpp:103
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:90
visionx::imrec::AbstractRecordingStrategy::startRecording
virtual void startRecording()
Starts the recording manually if constructed empty.
Definition: AbstractRecordingStrategy.cpp:78
visionx::imrec::AbstractRecordingStrategy::getMetadataPath
virtual std::filesystem::path getMetadataPath() const
Definition: AbstractRecordingStrategy.cpp:156
visionx::imrec::datetime_to_string
std::string datetime_to_string(std::chrono::microseconds ts)
Definition: helper.cpp:67
visionx::imrec::AbstractRecordingStrategy::getFilePath
virtual std::filesystem::path getFilePath() const
Gets the raw file path for the recording as configured.
Definition: AbstractRecordingStrategy.cpp:128
Logging.h
helper.h