JsonIO.h
Go to the documentation of this file.
1#pragma once
2
3#include <fstream>
4#include <functional>
5#include <iostream>
6#include <map>
7
8#include <SimoxUtility/json/json.hpp>
9
11
12#include "../VoxelGrid.hpp"
13#include "to_from_json.h"
14
16{
17
18 /// Function to get an attribute of a voxel.
19 template <class VoxelT>
20 using VoxelAttributeGetter = std::function<nlohmann::json(const VoxelT& voxel)>;
21 /// Function to set an attribute of a voxel.
22 template <class VoxelT>
23 using VoxelAttributeSetter = std::function<void(const nlohmann::json& j, VoxelT& voxel)>;
24
25 /// Map of attribute name to attribute getter.
26 template <class VoxelT>
27 using VoxelAttributeGetterMap = std::map<std::string, VoxelAttributeGetter<VoxelT>>;
28 /// Map of attribute name to attribute setter.
29 template <class VoxelT>
30 using VoxelAttributeSetterMap = std::map<std::string, VoxelAttributeSetter<VoxelT>>;
31
32 /// Make an attribute getter getting a member variable.
33 /// Usage: `makeGetter(&MyVoxel::myVar)`
34 template <class VoxelT, class MemberT>
36 makeGetter(MemberT VoxelT::*memberVariable)
37 {
38 return [memberVariable](const VoxelT& v) { return nlohmann::json(v.*memberVariable); };
39 }
40
41 /// Make an attribute getter calling a member function.
42 /// Usage: `makeGetter(&MyVoxel::myGetter)`
43 template <class VoxelT, class MemberT>
45 makeGetter(MemberT (VoxelT::*memberFunc)() const)
46 {
47 return [memberFunc](const VoxelT& v) { return (v.*memberFunc)(); };
48 }
49
50 /// Make an attribute setter setting a member variable.
51 /// Usage: `makeSetter(&MyVoxel::myVariable)`
52 template <class VoxelT, class MemberT>
54 makeSetter(MemberT VoxelT::*memberVariable)
55 {
56 return [memberVariable](const nlohmann::json& j, VoxelT& v)
57 { return v.*memberVariable = j.get<MemberT>(); };
58 }
59
60 /// Make an attribute setter calling a member function.
61 /// Usage: `makeSetter(&MyVoxel::mySetter)`
62 template <class VoxelT, class MemberT>
64 makeSetter(void (VoxelT::*memberFunc)(const MemberT&))
65 {
66 return [memberFunc](const nlohmann::json& j, VoxelT& v)
67 { return (v.*memberFunc)(j.get<MemberT>()); };
68 }
69
70 /**
71 * @brief Class to store voxel grids in a vectorized JSON format.
72 *
73 * The methods in class can be used to store voxel grids in JSON format.
74 * A voxel grid essentially consists of its structure (grid and voxel
75 * size, pose) and its voxel data.
76 *
77 * In the format produced by this class, there is one top-level JSON
78 * element for each voxel attribute to store. Each of this elements
79 * is an array storing the attribute value of each voxel.
80 *
81 * For example, if a voxel has two attributes, `int foo` and `float bar`,
82 * the produces JSON object would look like this:
83 * @code
84 * {
85 * "structure: { ... },
86 * "foo": [0 1 1 2 ... -1 0],
87 * "bar": [0.0, 1.0, 1.1, ... , 0.0, -1.0]
88 * }
89 * @endcode
90 *
91 * This is done to reduce the redundancy of JSON for a large number of voxels.
92 */
93 class JsonIO
94 {
95 public:
96 // WRITE
97
98 /// Write a voxel grid to file.
99 template <class VoxelT>
100 static void
101 write(const std::string& filename,
102 const VoxelGrid<VoxelT>& grid,
103 const VoxelAttributeGetterMap<VoxelT>& attributeMap,
104 int indent = -1,
105 char indentChar = ' ')
106 {
107 writeJson(filename, toJson(grid, attributeMap), indent, indentChar);
108 }
109
110 /// Write a voxel grid to `os`.
111 template <class VoxelT>
112 static void
113 write(std::ostream& os,
114 const VoxelGrid<VoxelT>& grid,
115 const VoxelAttributeGetterMap<VoxelT>& attributeMap,
116 int indent = -1,
117 char indentChar = ' ')
118 {
119 writeJson(os, toJson(grid, attributeMap), indent, indentChar);
120 }
121
122 // READ
123
124 /// Read a voxel grid from file.
125 template <class VoxelT>
126 static void
127 read(const std::string& filename,
128 VoxelGrid<VoxelT>& grid,
129 const VoxelAttributeGetterMap<VoxelT>& attributeMap)
130 {
131 fromJson(readJson(filename), grid, attributeMap);
132 }
133
134 /// Read a voxel grid from file.
135 template <class VoxelT>
136 static VoxelGrid<VoxelT> read(const std::string& filename,
137 const VoxelAttributeGetterMap<VoxelT>& attributeMap);
138
139 /// Read a voxel grid from `is`.
140 template <class VoxelT>
141 static void
142 read(std::istream& is,
143 VoxelGrid<VoxelT>& grid,
144 const VoxelAttributeGetterMap<VoxelT>& attributeMap)
145 {
146 fromJson(readJson(is), grid, attributeMap);
147 }
148
149 /// Read a voxel grid from `is`.
150 template <class VoxelT>
151 static VoxelGrid<VoxelT> read(std::istream& is,
152 const VoxelAttributeGetterMap<VoxelT>& attributeMap);
153
154
155 // Grid -> JSON
156
157 /// Serialize a voxel grid to JSON.
158 template <class VoxelT>
159 static void toJson(nlohmann::json& j,
160 const VoxelGrid<VoxelT>& grid,
161 const VoxelAttributeGetterMap<VoxelT>& attributeMap);
162
163 /// Serialize a voxel grid to JSON.
164 template <class VoxelT>
165 static nlohmann::json toJson(const VoxelGrid<VoxelT>& grid,
166 const VoxelAttributeGetterMap<VoxelT>& attributeMap);
167
168 /// Serialize a voxel grid to JSON with plain voxel array (with name `voxelArrayName`).
169 /// VoxelT must provide an implementation of `to_json()`.
170 template <class VoxelT>
171 static void toJson(nlohmann::json& j,
172 const VoxelGrid<VoxelT>& grid,
173 const std::string& voxelArrayName = "voxels");
174
175 /// Serialize a voxel grid to JSON with plain voxel array (with name `voxelArrayName`).
176 /// VoxelT must provide an implementation of `to_json()`.
177 template <class VoxelT>
178 static nlohmann::json toJson(const VoxelGrid<VoxelT>& grid,
179 const std::string& voxelArrayName = "voxels");
180
181
182 // JSON -> Grid
183
184 /// Deserialize a voxel grid from JSON.
185 template <class VoxelT>
186 static void fromJson(const nlohmann::json& j,
187 VoxelGrid<VoxelT>& grid,
188 const VoxelAttributeSetterMap<VoxelT>& attributeMap);
189
190
191 /// Deserialize a voxel grid from JSON with plain voxel array (with name `voxelArrayName`).
192 /// VoxelT must provide an implementation of `from_json()`.
193 template <class VoxelT>
194 static void fromJson(const nlohmann::json& j,
195 VoxelGrid<VoxelT>& grid,
196 const std::string& voxelArrayName = "voxels");
197
198
199 /// Write JSON json to file.
200 static void writeJson(const std::string& filename,
201 const nlohmann::json& j,
202 int indent = -1,
203 char indentChar = ' ');
204 /// Write JSON json to `os`.
205 static void writeJson(std::ostream& os,
206 const nlohmann::json& j,
207 int indent = -1,
208 char indentChar = ' ');
209
210 /// Read JSON from file.
211 static nlohmann::json readJson(const std::string& filename);
212 /// Read JSON json `is`.
213 static nlohmann::json readJson(std::istream& is);
214 };
215
216 template <class VoxelT>
218 JsonIO::read(const std::string& filename, const VoxelAttributeGetterMap<VoxelT>& attributeMap)
219 {
221 read(filename, grid, attributeMap);
222 return grid;
223 }
224
225 template <class VoxelT>
227 JsonIO::read(std::istream& is, const VoxelAttributeGetterMap<VoxelT>& attributeMap)
228 {
230 read(is, grid, attributeMap);
231 return grid;
232 }
233
234 template <class VoxelT>
235 nlohmann::json
237 const VoxelAttributeGetterMap<VoxelT>& attributeMap)
238 {
239 nlohmann::json j;
240 toJson(j, grid, attributeMap);
241 return j;
242 }
243
244 template <class VoxelT>
245 void
246 JsonIO::toJson(nlohmann::json& j,
247 const VoxelGrid<VoxelT>& grid,
248 const VoxelAttributeGetterMap<VoxelT>& attributeMap)
249 {
250 // Serialize structure.
251 j["structure"] = grid.getStructure();
252
253 // Serialize voxel data.
254
255 // Insert array elements.
256 for (const auto& item : attributeMap)
257 {
258 j[item.first] = nlohmann::json::array();
259 }
260
261 // Add data.
262 for (const VoxelT& voxel : grid)
263 {
264 for (const auto& item : attributeMap)
265 {
266 // Fetch serialized attribute from voxel.
267 j[item.first].push_back(item.second(voxel));
268 }
269 }
270 }
271
272 template <class VoxelT>
273 void
274 JsonIO::toJson(nlohmann::json& j,
275 const VoxelGrid<VoxelT>& grid,
276 const std::string& voxelArrayName)
277 {
278 // Serialize structure.
279 j["structure"] = grid.getStructure();
280 // Serialize voxel data.
281 j[voxelArrayName] = grid.getVoxels();
282 }
283
284 template <class VoxelT>
285 nlohmann::json
286 JsonIO::toJson(const VoxelGrid<VoxelT>& grid, const std::string& voxelArrayName)
287 {
288 nlohmann::json j;
289 toJson(j, grid, voxelArrayName);
290 return j;
291 }
292
293 template <class VoxelT>
294 void
295 JsonIO::fromJson(const nlohmann::json& j,
296 VoxelGrid<VoxelT>& grid,
297 const VoxelAttributeSetterMap<VoxelT>& attributeMap)
298 {
299 // Deserialize structure.
300 grid.resetStructure(j.at("structure").get<VoxelGridStructure>());
301
302 ARMARX_CHECK_EQUAL(grid.getVoxels().size(), grid.getStructure().getNumVoxels());
303
304 // Deserialize voxel data.
305 for (std::size_t i = 0; i < grid.numVoxels(); ++i)
306 {
307 VoxelT& voxel = grid[i];
308 for (const auto& item : attributeMap)
309 {
310 // Deserialize and set voxel attribute.
311 item.second(j[item.first].at(i), voxel);
312 }
313 }
314 }
315
316 template <class VoxelT>
317 void
318 JsonIO::fromJson(const nlohmann::json& j,
319 VoxelGrid<VoxelT>& grid,
320 const std::string& voxelArrayName)
321 {
322 // Deserialize structure.
323 grid.resetStructure(j.at("structure").get<VoxelGridStructure>());
324 ARMARX_CHECK_EQUAL(grid.getVoxels().size(), grid.getStructure().getNumVoxels());
325
326 // Deserialize voxel data.
327 grid.setVoxels(j.at(voxelArrayName).get<std::vector<VoxelT>>());
328 }
329
330} // namespace visionx::voxelgrid::io
Geometric structure of a 3D voxel grid.
std::size_t getNumVoxels() const
Get the number of voxels contained in the structure.
A 3D grid of voxels of type _VoxelT.
Definition VoxelGrid.hpp:50
VoxelGridStructure getStructure() const
Get the voxel grid structure.
Definition VoxelGrid.hpp:87
void resetStructure(const VoxelGridStructure &structure)
Set the voxel grid structure and reset voxel data.
Definition VoxelGrid.hpp:94
std::size_t numVoxels() const
Get the number of voxels in the grid.
const std::vector< VoxelT > & getVoxels() const
Get the voxels.
void setVoxels(const std::vector< VoxelT > &voxels)
Set the voxels.
Class to store voxel grids in a vectorized JSON format.
Definition JsonIO.h:93
static void read(const std::string &filename, VoxelGrid< VoxelT > &grid, const VoxelAttributeGetterMap< VoxelT > &attributeMap)
Read a voxel grid from file.
Definition JsonIO.h:126
static void write(const std::string &filename, const VoxelGrid< VoxelT > &grid, const VoxelAttributeGetterMap< VoxelT > &attributeMap, int indent=-1, char indentChar=' ')
Write a voxel grid to file.
Definition JsonIO.h:100
static void toJson(nlohmann::json &j, const VoxelGrid< VoxelT > &grid, const VoxelAttributeGetterMap< VoxelT > &attributeMap)
Serialize a voxel grid to JSON.
Definition JsonIO.h:245
static void fromJson(const nlohmann::json &j, VoxelGrid< VoxelT > &grid, const VoxelAttributeSetterMap< VoxelT > &attributeMap)
Deserialize a voxel grid from JSON.
Definition JsonIO.h:294
static nlohmann::json readJson(const std::string &filename)
Read JSON from file.
Definition JsonIO.cpp:24
static void writeJson(const std::string &filename, const nlohmann::json &j, int indent=-1, char indentChar=' ')
Write JSON json to file.
Definition JsonIO.cpp:8
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
double v(double t, double v0, double a0, double j)
Definition CtrlUtil.h:39
std::map< std::string, VoxelAttributeGetter< VoxelT > > VoxelAttributeGetterMap
Map of attribute name to attribute getter.
Definition JsonIO.h:27
std::map< std::string, VoxelAttributeSetter< VoxelT > > VoxelAttributeSetterMap
Map of attribute name to attribute setter.
Definition JsonIO.h:30
std::function< nlohmann::json(const VoxelT &voxel)> VoxelAttributeGetter
Function to get an attribute of a voxel.
Definition JsonIO.h:20
std::function< void(const nlohmann::json &j, VoxelT &voxel)> VoxelAttributeSetter
Function to set an attribute of a voxel.
Definition JsonIO.h:23