BinaryIO.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <fstream>
4 #include <istream>
5 #include <ostream>
6 
7 #include "../VoxelGrid.hpp"
8 
9 #include "exceptions.h"
10 
11 
12 namespace visionx::voxelgrid::io
13 {
14  class BinaryIO
15  {
16  public:
17 
18  // VOXEL READ/WRITE
19 
20  /**
21  * @brief Read a voxel from the out stream.
22  *
23  * This is a free template method used by voxel_grid_io::read(),
24  * so you can specialize it if necessary.
25  */
26  template <typename VoxelT>
27  static void readVoxel(std::istream& is, VoxelT& voxel);
28 
29 
30  /**
31  * @brief Write a voxel to the out stream.
32  *
33  * This is a free template method used by voxel_grid_io::write(),
34  * so you can specialize it if necessary.
35  */
36  template <typename VoxelT>
37  static void writeVoxel(std::ostream& os, const VoxelT& voxel);
38 
39 
40 
41  // VOXEL GRID READ
42 
43  /**
44  * @brief Read a voxel grid from the file.
45  *
46  * Sets `voxelGrid`'s layout and fills the voxel data.
47  */
48  template <typename VoxelT>
49  static void read(VoxelGrid<VoxelT>& voxelGrid, const std::string& filename);
50 
51  /**
52  * @brief Read a voxel grid from the in-stream.
53  *
54  * Sets `voxelGrid`'s layout and fills the voxel data.
55  * `is` must be open in binary mode with a valid voxel grid file.
56  */
57  template <typename VoxelT>
58  static void read(VoxelGrid<VoxelT>& voxelGrid, std::istream& is);
59 
60 
61  /**
62  * @brief Read a voxel grid from the filename.
63  *
64  * The specified voxel grid type `VoxelGridT` must provide a default constructor.
65  * Sets `voxelGrid`'s layout and fills the voxel data.
66  * `is` must be open in binary mode with a valid voxel grid file.
67  */
68  template <typename VoxelGridT>
69  static VoxelGridT read(const std::string& filename);
70 
71  /**
72  * @brief Read a voxel grid from the in-stream.
73  *
74  * The specified voxel grid type `VoxelGridT` must provide a default constructor.
75  * Sets `voxelGrid`'s layout and fills the voxel data.
76  * `is` must be open in binary mode with a valid voxel grid file.
77  */
78  template <typename VoxelGridT>
79  static VoxelGridT read(std::istream& is);
80 
81 
82  // VOXEL GRID WRITE
83 
84  /**
85  * @brief Write a voxel grid to a file.
86  */
87  template <typename VoxelT>
88  static void write(const VoxelGrid<VoxelT>& voxelGrid, const std::string& filename);
89 
90  /**
91  * @brief Write a voxel grid to an out-stream.
92  *
93  * The out-stream `os` must be open in binary mode.
94  */
95  template <typename VoxelT>
96  static void write(const VoxelGrid<VoxelT>& voxelGrid, std::ostream& os);
97 
98 
99  private:
100 
101  /// Throws an exception if value is not positive 0.
102  static void checkPositive(int value);
103  static void checkPositive(float value);
104 
105  };
106 }
107 
108 // IMPLEMENTATIONS
109 
111 {
112 
113  template <typename DataT>
114  void readData(std::istream& is, DataT& data)
115  {
116  is.read(reinterpret_cast<char*>(&data), sizeof(DataT));
117  }
118 
119  template <typename DataT>
120  void writeData(std::ostream& os, const DataT& data)
121  {
122  os.write(reinterpret_cast<const char*>(&data), sizeof(DataT));
123  }
124 
125  template <typename ReadT, typename Derived>
126  void readEigen(std::istream& is, Eigen::MatrixBase<Derived>& matrix)
127  {
129 
130  auto cast = matrix.template cast<ReadT>().eval();
131  is.read(reinterpret_cast<char*>(cast.data()), cast.size() * sizeof(Scalar));
132 
133  matrix = cast.template cast<Scalar>();
134  }
135 
136  template <typename WriteT, typename Derived>
137  void writeEigen(std::ostream& os, const Eigen::MatrixBase<Derived>& matrix)
138  {
139  auto eval = matrix.template cast<WriteT>().eval();
140  os.write(reinterpret_cast<const char*>(eval.data()),
141  eval.size() * sizeof(WriteT));
142  }
143 
144 }
145 
146 
147 namespace visionx::voxelgrid::io
148 {
149  template <typename VoxelT>
150  void BinaryIO::readVoxel(std::istream& is, VoxelT& voxel)
151  {
152  detail::readData<VoxelT>(is, voxel);
153  }
154 
155  template <typename VoxelT>
156  void BinaryIO::writeVoxel(std::ostream& os, const VoxelT& voxel)
157  {
158  detail::writeData<VoxelT>(os, voxel);
159  }
160 
161 
162  template <typename VoxelGridT>
163  VoxelGridT BinaryIO::read(const std::string& filename)
164  {
165  VoxelGridT grid;
166  read(grid, filename);
167  return grid;
168  }
169 
170  template <typename VoxelGridT>
171  VoxelGridT BinaryIO::read(std::istream& is)
172  {
173  VoxelGridT grid;
174  read(grid, is);
175  return grid;
176  }
177 
178  template<typename VoxelT>
179  void BinaryIO::read(VoxelGrid<VoxelT>& voxelGrid, const std::string& filename)
180  {
181  std::ifstream ifs;
182  ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
183 
184  try
185  {
186  ifs.open(filename, std::ios_base::binary | std::ios_base::in);
187  }
188  catch (const std::ios_base::failure& e)
189  {
190  throw error::io::BinaryIOError("read", filename, "Failed to open file.", e);
191  }
192 
193  try
194  {
195  read(voxelGrid, ifs);
196  }
197  catch (const std::ios_base::failure& e)
198  {
199  throw error::io::BinaryIOError("read", filename, "Error while reading file.", e);
200  }
201  }
202 
203  template<typename VoxelT>
204  void BinaryIO::read(VoxelGrid<VoxelT>& voxelGrid, std::istream& is)
205  {
206  Eigen::Vector3f voxelSizes = Eigen::Vector3f::Zero();
207  Eigen::Vector3f gridSizes = Eigen::Vector3f::Zero();
208  Eigen::Vector3f origin = Eigen::Vector3f::Zero();
209  Eigen::Vector4f orientationCoeffs = Eigen::Vector4f::Zero();
210 
211  try
212  {
213  // read voxel sizes
214  detail::readEigen<float>(is, voxelSizes);
215  // read grid sizes (as float to be uniform)
216  detail::readEigen<float>(is, gridSizes);
217  // read grid origin
218  detail::readEigen<float>(is, origin);
219  // read orientation coeffs in [w x y z] order
220  detail::readEigen<float>(is, orientationCoeffs);
221  }
222  catch (const std::ios_base::failure& e)
223  {
224  throw error::io::BinaryReadError("Failed to read voxel grid structure.", e);
225  }
226 
227  checkPositive(voxelSizes.minCoeff());
228  checkPositive(gridSizes.minCoeff());
229 
230  Eigen::Quaternionf orientation;
231  orientation.w() = orientationCoeffs(0);
232  orientation.coeffs().head<3>() = orientationCoeffs.tail<3>();
233 
234  voxelGrid.setVoxelSizes(voxelSizes);
235  voxelGrid.setGridSizes(gridSizes.cast<int>());
236  voxelGrid.setOrigin(origin);
237  voxelGrid.setOrientation(orientation);
238 
239  // read voxel data
240  for (std::size_t i = 0; i < voxelGrid.numVoxels(); ++i)
241  {
242  try
243  {
244  readVoxel<VoxelT>(is, voxelGrid.getVoxel(i));
245  }
246  catch (const std::ios_base::failure& e)
247  {
248  std::stringstream ss;
249  ss << "Failed to read voxel " << i << " of " << voxelGrid.numVoxels() << ".";
250  throw error::io::BinaryReadError(ss.str(), e);
251  }
252  }
253  }
254 
255 
256  template <typename VoxelT>
257  void BinaryIO::write(const VoxelGrid<VoxelT>& voxelGrid, const std::string& filename)
258  {
259  std::ofstream ofs;
260  ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit);
261 
262  try
263  {
264  ofs.open(filename, std::ios_base::binary | std::ios_base::out);
265  }
266  catch (const std::ios_base::failure& e)
267  {
268  throw error::io::BinaryIOError("write", filename, "Failed to open file.", e);
269  }
270 
271  try
272  {
273  write(voxelGrid, ofs);
274  }
275  catch (const std::ios_base::failure& e)
276  {
277  throw error::io::BinaryIOError("write", filename, "Error while reading file.", e);
278  }
279  }
280 
281  template <typename VoxelT>
282  void BinaryIO::write(const VoxelGrid<VoxelT>& voxelGrid, std::ostream& os)
283  {
284  const Eigen::Vector3f voxelSizes = voxelGrid.getVoxelSizes();
285  const Eigen::Vector3i gridSizes = voxelGrid.getGridSizes();
286  const Eigen::Vector3f origin = voxelGrid.getOrigin();
287  const Eigen::Quaternionf orientation = voxelGrid.getOrientation();
288 
289  // orientation in [w x y z] order
290  Eigen::Vector4f orientationCoeffs;
291  orientationCoeffs(0) = orientation.w();
292  orientationCoeffs.tail<3>() = orientation.coeffs().head<3>();
293 
294  // write voxel sizes
295  detail::writeEigen<float>(os, voxelSizes);
296  // write grid sizes (as float to be uniform)
297  detail::writeEigen<float>(os, gridSizes.cast<float>());
298  // write grid origin
299  detail::writeEigen<float>(os, origin);
300  // write grid orientation
301  detail::writeEigen<float>(os, orientationCoeffs);
302 
303  // write voxel data
304  for (std::size_t i = 0; i < voxelGrid.numVoxels(); ++i)
305  {
306  writeVoxel<VoxelT>(os, voxelGrid.getVoxel(i));
307  }
308  }
309 
310 }
311 
visionx::voxelgrid::io
Definition: BinaryIO.cpp:6
visionx::voxelgrid::VoxelGrid::setGridSizes
void setGridSizes(float gridSizes)
Set the grid size for a cubic grid. Resets the grid data.
Definition: VoxelGrid.hpp:182
visionx::voxelgrid::VoxelGrid< VoxelT >
visionx::voxelgrid::io::BinaryIO
Definition: BinaryIO.h:14
armarx::conversions::cast
CvT cast(const auto &pt)
Definition: opencv.h:32
visionx::voxelgrid::VoxelGrid::getVoxelSizes
Eigen::Vector3f getVoxelSizes() const
Get the voxel size.
Definition: VoxelGrid.hpp:195
visionx::voxelgrid::error::io::BinaryReadError
Definition: exceptions.h:33
visionx::voxelgrid::io::BinaryIO::writeVoxel
static void writeVoxel(std::ostream &os, const VoxelT &voxel)
Write a voxel to the out stream.
Definition: BinaryIO.h:156
exceptions.h
visionx::voxelgrid::VoxelGrid::setOrientation
void setOrientation(const Eigen::Quaternionf &value)
Set the grid orienation in the world frame.
Definition: VoxelGrid.hpp:288
visionx::voxelgrid::VoxelGrid::getVoxel
VoxelT & getVoxel(std::size_t index)
Get the voxel with the given index.
Definition: VoxelGrid.hpp:104
visionx::voxelgrid::error::io::BinaryIOError
Indicates that voxel data with an invalid number of voxels has been passed to a VoxelGrid.
Definition: exceptions.h:25
visionx::voxelgrid::VoxelGrid::numVoxels
std::size_t numVoxels() const
Get the number of voxels in the grid.
Definition: VoxelGrid.hpp:165
visionx::voxelgrid::io::detail::writeEigen
void writeEigen(std::ostream &os, const Eigen::MatrixBase< Derived > &matrix)
Definition: BinaryIO.h:137
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
visionx::voxelgrid::VoxelGrid::setOrigin
void setOrigin(const Eigen::Vector3f &value)
Set the grid origin the world frame (center of voxel [0 0 0]).
Definition: VoxelGrid.hpp:277
filename
std::string filename
Definition: VisualizationRobot.cpp:83
visionx::voxelgrid::io::detail::readEigen
void readEigen(std::istream &is, Eigen::MatrixBase< Derived > &matrix)
Definition: BinaryIO.h:126
visionx::voxelgrid::io::BinaryIO::write
static void write(const VoxelGrid< VoxelT > &voxelGrid, const std::string &filename)
Write a voxel grid to a file.
Definition: BinaryIO.h:257
visionx::voxelgrid::VoxelGrid::getOrientation
Eigen::Quaternionf getOrientation() const
Get the grid orienation in the world frame.
Definition: VoxelGrid.hpp:283
visionx::voxelgrid::io::BinaryIO::read
static void read(VoxelGrid< VoxelT > &voxelGrid, const std::string &filename)
Read a voxel grid from the file.
Definition: BinaryIO.h:179
visionx::voxelgrid::VoxelGrid::getOrigin
Eigen::Vector3f getOrigin() const
Get the grid origin in the world frame (center of voxel [0 0 0]).
Definition: VoxelGrid.hpp:270
visionx::voxelgrid::io::BinaryIO::readVoxel
static void readVoxel(std::istream &is, VoxelT &voxel)
Read a voxel from the out stream.
Definition: BinaryIO.h:150
visionx::voxelgrid::io::detail
Definition: BinaryIO.h:110
armarx::Quaternion< float, 0 >
Scalar
float Scalar
Definition: basic.h:14
visionx::voxelgrid::VoxelGrid::setVoxelSizes
void setVoxelSizes(float voxelSize)
Set the voxel size of cubic voxels. The grid data is not updated.
Definition: VoxelGrid.hpp:200
visionx::voxelgrid::VoxelGrid::getGridSizes
Eigen::Vector3i getGridSizes() const
Get the grid size.
Definition: VoxelGrid.hpp:177
visionx::voxelgrid::io::detail::writeData
void writeData(std::ostream &os, const DataT &data)
Definition: BinaryIO.h:120
visionx::voxelgrid::io::detail::readData
void readData(std::istream &is, DataT &data)
Definition: BinaryIO.h:114