iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test-serialization.C
Go to the documentation of this file.
1 /*! @file
2  @author Shane Grant
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 #include <nrt/config.h>
35 
36 #include <nrt/Eigen/Eigen.H>
39 #include <nrt/External/cereal/archives/binary.hpp>
42 #include <nrt/Graphics/Shapes.H>
43 
44 #include <random>
45 
46 #define BOOST_TEST_DYN_LINK
47 #define BOOST_TEST_MODULE SerializationTest
48 #include <boost/test/unit_test.hpp>
49 
50 
51 // ######################################################################
52 BOOST_AUTO_TEST_CASE( eigen )
53 {
54  std::stringstream ss;
55  cereal::BinaryOutputArchive oar(ss);
56 
57  Eigen::Vector3d ovec3d(1, 2, 3);
58 
59  Eigen::MatrixXf omatxf(4, 4);
60  omatxf << 1, 2, 3, 4,
61  5, 6, 7, 8,
62  9, 10, 11, 12,
63  13, 14, 15, 16;
64 
65  oar(ovec3d);
66  oar(omatxf);
67 
68  cereal::BinaryInputArchive iar(ss);
69  Eigen::Vector3d ivec3d;
70  Eigen::MatrixXf imatxf;
71  iar(ivec3d);
72  iar(imatxf);
73 
74  BOOST_CHECK_EQUAL(ovec3d, ivec3d);
75  BOOST_CHECK_EQUAL(omatxf, imatxf);
76 }
77 
78 // ######################################################################
79 nrt::blackboard::ModulePortSummary makeModulePortSummary()
80 {
81  return {"msg",
82  "ret",
83  "port",
84  "desc",
85  "topic",
86  true,
87  false};
88 }
89 
92 {
93  return l.msgtype == r.msgtype &&
94  l.rettype == r.rettype &&
95  l.portname == r.portname &&
96  l.description == r.description &&
97  l.topi == r.topi &&
98  l.splittable == r.splittable &&
99  l.issplit == r.issplit;
100 }
101 
102 BOOST_AUTO_TEST_CASE( moduleportsummary )
103 {
104  std::stringstream ss;
105  cereal::BinaryOutputArchive oar(ss);
106 
107  auto output = makeModulePortSummary();
108  oar( output );
109 
110  cereal::BinaryInputArchive iar(ss);
111  decltype(output) input;
112  iar( input );
113 
114  BOOST_CHECK_EQUAL( input.msgtype, output.msgtype );
115  BOOST_CHECK_EQUAL( input.rettype, output.rettype );
116  BOOST_CHECK_EQUAL( input.portname, output.portname );
117  BOOST_CHECK_EQUAL( input.description, output.description );
118  BOOST_CHECK_EQUAL( input.topi, output.topi );
119  BOOST_CHECK_EQUAL( input.splittable, output.splittable );
120 }
121 
122 // ######################################################################
123 nrt::ParameterSummary makeParameterSummary()
124 {
125  nrt::ParameterSummary output;
126  output.descriptor = "aaa";
127  output.name = "bbb";
128  output.description = "ccc";
129  output.valuetype = "ddd";
130  output.defaultvalue = "eee";
131  output.value = "fff";
132  output.validvalues = "ggg";
133  output.category = "hhh";
134  output.categorydescription = "iii";
135  return output;
136 }
137 
138 bool operator==( nrt::ParameterSummary const & l, nrt::ParameterSummary const & r )
139 {
140  return l.descriptor == r.descriptor &&
141  l.name == r.name &&
142  l.description == r.description &&
143  l.valuetype == r.valuetype &&
144  l.defaultvalue == r.defaultvalue &&
145  l.value == r.value &&
146  l.validvalues == r.validvalues &&
147  l.category == r.category &&
149 }
150 
151 BOOST_AUTO_TEST_CASE( parametersummary )
152 {
153  std::stringstream ss;
154  cereal::BinaryOutputArchive oar(ss);
155 
156  auto output = makeParameterSummary();
157  oar( output );
158 
159  cereal::BinaryInputArchive iar(ss);
160  decltype(output) input;
161  iar( input );
162 
163  input == output;
164 
165  BOOST_CHECK_EQUAL( input.descriptor, output.descriptor );
166  BOOST_CHECK_EQUAL( input.name, output.name );
167  BOOST_CHECK_EQUAL( input.description, output.description );
168  BOOST_CHECK_EQUAL( input.valuetype, output.valuetype );
169  BOOST_CHECK_EQUAL( input.defaultvalue, output.defaultvalue );
170  BOOST_CHECK_EQUAL( input.value, output.value );
171  BOOST_CHECK_EQUAL( input.validvalues, output.validvalues );
172  BOOST_CHECK_EQUAL( input.category, output.category );
173  BOOST_CHECK_EQUAL( input.categorydescription, output.categorydescription );
174 }
175 
176 // ######################################################################
177 nrt::blackboard::ModuleSummary makeModuleSummary()
178 {
179  nrt::blackboard::ModuleSummary ms("a/b/class", "inst", "par");
180  for(size_t i = 0; i < 10; ++i)
181  {
182  ms.posters.push_back(makeModulePortSummary());
183  ms.checkers.push_back(makeModulePortSummary());
184  ms.subscribers.push_back(makeModulePortSummary());
185  }
186  return ms;
187 }
188 
191 {
192  bool ret = l.logicalpath == r.logicalpath &&
193  l.instance == r.instance &&
194  l.parent == r.parent;
195 
196  if(l.posters.size() == r.posters.size())
197  for(size_t i = 0; i < l.posters.size(); ++i)
198  ret &= l.posters[i] == r.posters[i];
199  else
200  return false;
201 
202  if(l.checkers.size() == r.checkers.size())
203  for(size_t i = 0; i < l.checkers.size(); ++i)
204  ret &= l.checkers[i] == r.checkers[i];
205  else
206  return false;
207 
208  if(l.subscribers.size() == r.subscribers.size())
209  for(size_t i = 0; i < l.subscribers.size(); ++i)
210  ret &= l.subscribers[i] == r.subscribers[i];
211  else
212  return false;
213 
214  return ret;
215 }
216 
217 BOOST_AUTO_TEST_CASE( modulesummary )
218 {
219  std::stringstream ss;
220  cereal::BinaryOutputArchive oar(ss);
221 
222  auto output = makeModuleSummary();
223  oar( output );
224 
225  cereal::BinaryInputArchive iar(ss);
226  decltype(output) input;
227  iar( input );
228 
229  BOOST_CHECK( input == output );
230 }
231 
232 // #####################################################################j
233 nrt::blackboard::ConnectorSummary makeConnectorSummary()
234 {
235  return {"msg", "ret", "inst", nrt::ConnectorType::Border, "top", "filt"};
236 }
237 
240 {
241  return l.msgtype == r.msgtype &&
242  l.rettype == r.rettype &&
243  l.instance == r.instance &&
244  l.type == r.type &&
245  l.topic == r.topic &&
246  l.topicfilt == r.topicfilt;
247 }
248 
249 BOOST_AUTO_TEST_CASE( connectorsummary )
250 {
251  std::stringstream ss;
252  cereal::BinaryOutputArchive oar(ss);
253 
254  auto output = makeConnectorSummary();
255  oar( output );
256 
257  cereal::BinaryInputArchive iar(ss);
258  decltype(output) input;
259  iar( input );
260 
261  BOOST_CHECK( input == output );
262 }
263 
264 // #####################################################################j
265 nrt::blackboard::BlackboardSummary makeBlackboardSummary()
266 {
267  nrt::blackboard::BlackboardSummary bs;
268 
269  for(size_t i = 0; i < 10; ++i)
270  {
271  auto & map = bs.modules[std::to_string(i)];
272  auto & map2 = bs.pconnectors[std::to_string(i)];
273  auto & map3 = bs.cconnectors[std::to_string(i)];
274  auto & map4 = bs.sconnectors[std::to_string(i)];
275  for(size_t j = 0; j < 10; ++j)
276  {
277  map[std::to_string(j)] = makeModuleSummary();
278  map2[std::to_string(j)] = makeConnectorSummary();
279  map3[std::to_string(j)] = makeConnectorSummary();
280  map4[std::to_string(j)] = makeConnectorSummary();
281  }
282  }
283 
284  return bs;
285 }
286 
287 bool operator==(nrt::blackboard::BlackboardSummary const & l,
288  nrt::blackboard::BlackboardSummary const & r)
289 {
290  bool ret = true;
291 
292  BOOST_TEST_CHECKPOINT("Checking modules");
293  if(l.modules.size() == r.modules.size())
294  for(size_t i = 0; i < 10; ++i)
295  {
296  auto lmap = l.modules.find(std::to_string(i));
297  auto rmap = r.modules.find(std::to_string(i));
298 
299  BOOST_CHECK(lmap != l.modules.end());
300  BOOST_CHECK(rmap != r.modules.end());
301 
302  ret &= (lmap->first == rmap->first);
303 
304  for(size_t j = 0; j < 10; ++j)
305  {
306  BOOST_CHECK(lmap->second.find(std::to_string(j)) != lmap->second.end());
307  BOOST_CHECK(rmap->second.find(std::to_string(j)) != rmap->second.end());
308 
309  ret &= lmap->second.find(std::to_string(j))->first == rmap->second.find(std::to_string(j))->first;
310  ret &= lmap->second.find(std::to_string(j))->second == rmap->second.find(std::to_string(j))->second;
311  }
312  }
313  else
314  return false;
315 
316  BOOST_TEST_CHECKPOINT("Checking pconnectors");
317  if(l.pconnectors.size() == r.pconnectors.size())
318  for(size_t i = 0; i < 10; ++i)
319  {
320  auto lmap = l.pconnectors.find(std::to_string(i));
321  auto rmap = r.pconnectors.find(std::to_string(i));
322  ret &= lmap->first == rmap->first;
323 
324  for(size_t j = 0; j < 10; ++j)
325  {
326  ret &= lmap->second.find(std::to_string(j))->first == rmap->second.find(std::to_string(j))->first;
327  ret &= lmap->second.find(std::to_string(j))->second == rmap->second.find(std::to_string(j))->second;
328  }
329  }
330  else
331  return false;
332 
333  BOOST_TEST_CHECKPOINT("Checking cconnectors");
334  if(l.cconnectors.size() == r.cconnectors.size())
335  for(size_t i = 0; i < 10; ++i)
336  {
337  auto lmap = l.cconnectors.find(std::to_string(i));
338  auto rmap = r.cconnectors.find(std::to_string(i));
339  ret &= lmap->first == rmap->first;
340 
341  for(size_t j = 0; j < 10; ++j)
342  {
343  ret &= lmap->second.find(std::to_string(j))->first == rmap->second.find(std::to_string(j))->first;
344  ret &= lmap->second.find(std::to_string(j))->second == rmap->second.find(std::to_string(j))->second;
345  }
346  }
347  else
348  return false;
349 
350  BOOST_TEST_CHECKPOINT("Checking sconnectors");
351  if(l.sconnectors.size() == r.sconnectors.size())
352  for(size_t i = 0; i < 10; ++i)
353  {
354  auto lmap = l.sconnectors.find(std::to_string(i));
355  auto rmap = r.sconnectors.find(std::to_string(i));
356  ret &= lmap->first == rmap->first;
357 
358  for(size_t j = 0; j < 10; ++j)
359  {
360  ret &= lmap->second.find(std::to_string(j))->first == rmap->second.find(std::to_string(j))->first;
361  ret &= lmap->second.find(std::to_string(j))->second == rmap->second.find(std::to_string(j))->second;
362  }
363  }
364  else
365  return false;
366 
367  return ret;
368 }
369 
370 BOOST_AUTO_TEST_CASE( blackboardsummary )
371 {
372  std::stringstream ss;
373  cereal::BinaryOutputArchive oar(ss);
374 
375  auto output = makeBlackboardSummary();
376 
377  oar( output );
378 
379  cereal::BinaryInputArchive iar(ss);
380  decltype(output) input;
381  iar( input );
382 
383  BOOST_CHECK( input == output );
384 }
385 
386 nrt::PointCloud2 createRandomCloud( int size )
387 {
388  std::random_device rd;
389  std::mt19937 gen(rd());
390 
391  std::uniform_real_distribution<float> posdist(-3.0F, 3.0F);
392  auto posgen = [&]() { return posdist(gen); };
393 
394  std::uniform_int_distribution<uint8_t> coldist(0, 255);
395  auto colgen = [&]() { return coldist(gen); };
396 
397  nrt::PointCloud2 cloud = nrt::PointCloud2::create<nrt::PixGray<uint8_t>>();
398  cloud.resize( size );
399 
400  for(auto p : cloud.range<nrt::PixGray<uint8_t>>())
401  p = {{posgen(), posgen(), posgen()}, colgen()};
402 
403  return cloud;
404 }
405 
406 class FakeGraphicsCloud : public nrt::graphics::Shape
407 {
408  public:
409  FakeGraphicsCloud(nrt::PointCloud2 const & pointcloud_ = nrt::PointCloud2(),
410  float const pointsize_ = 1.0F,
411  Eigen::Affine3f const & frame_ = Eigen::Affine3f::Identity(),
412  nrt::Duration const & lifetime_ = nrt::forev(),
413  nrt::graphics::Pen const & pen_ = nrt::graphics::Pen(),
414  nrt::graphics::Brush const & brush_ = nrt::graphics::Brush() ) :
415  nrt::graphics::Shape(frame_, lifetime_, pen_, brush_), pointcloud(pointcloud_), pointsize(pointsize_)
416  {}
417 
418 
419  //! Virtual destructor for safe inheritance
420  virtual ~FakeGraphicsCloud() {}
421 
422  //! Render this shape into a ShapeRenderer (e.g., OpenGL window).
423  virtual void render(nrt::graphics::ShapeRenderer & sr) const {}
424  nrt::PointCloud2 pointcloud;
425  float pointsize;
426 
427  public:
428  //! Serialization
429  template <class Archive> void serialize(Archive & ar)
430  {
431  ar( cereal::base_class<Shape>(this) );
432  ar( pointcloud, pointsize );
433 
434  std::cout << "--------" << std::endl;
435  std::cout << pointcloud.size() << std::endl;
436  std::cout << pointsize << std::endl;
437  std::cout << this->frame.matrix() << std::endl;
438  std::cout << this->endtime.time_since_epoch().count() << std::endl;
439  std::cout << this->pen.color << std::endl;
440  std::cout << this->brush.texturename << std::endl;
441  }
442 };
443 
444 CEREAL_REGISTER_TYPE(FakeGraphicsCloud);
445 
446 BOOST_AUTO_TEST_CASE( graphicsmessage )
447 {
448  std::stringstream ss;
449 
450  std::shared_ptr<nrt::graphics::Shape> cloudshape =
451  std::make_shared<FakeGraphicsCloud>( createRandomCloud( 1024 ),
452  32.0f,
453  Eigen::Affine3f(Eigen::AngleAxisf(1.234f, Eigen::Vector3f(1, 2, 3))),
454  std::chrono::hours(1) );
455 
456 
457  {
458  cereal::BinaryOutputArchive oar(ss);
459 
461  msg.shapes.emplace_back(std::make_shared<nrt::graphics::Grid>());
462  msg.shapes.emplace_back(std::make_shared<nrt::graphics::Axes>());
463  msg.shapes.emplace_back(std::make_shared<nrt::graphics::Line>());
464  msg.shapes.emplace_back(std::make_shared<nrt::graphics::Rectangle>());
465  msg.shapes.push_back( cloudshape );
466 
467  //msg.shapes.emplace_back(std::make_shared<FakeShape>(
468  // Eigen::Affine3f(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ())),
469  // {1, 2, 3},
470  // {nrt::graphics::BasicMaterial::Emerald});
471 
472  oar( msg );
473  }
474 
475  {
476  cereal::BinaryInputArchive iar(ss);
477 
479 
480  iar( msg );
481 
482  BOOST_CHECK_EQUAL(msg.shapes.size(), 5);
483  BOOST_CHECK( std::dynamic_pointer_cast<nrt::graphics::Grid>(msg.shapes[0]));
484  BOOST_CHECK( std::dynamic_pointer_cast<nrt::graphics::Axes>(msg.shapes[1]));
485  BOOST_CHECK( std::dynamic_pointer_cast<nrt::graphics::Line>(msg.shapes[2]));
486  BOOST_CHECK( std::dynamic_pointer_cast<nrt::graphics::Rectangle>(msg.shapes[3]));
487 
488  // check cloud is same
489  {
490  auto cloud1 = std::dynamic_pointer_cast<FakeGraphicsCloud>(cloudshape)->pointcloud;
491  auto cloud2 = std::dynamic_pointer_cast<FakeGraphicsCloud>(msg.shapes[4])->pointcloud;
492  BOOST_CHECK_EQUAL( cloud1.size(), cloud2.size() );
493 
494  auto cloudIter1 = cloud1.begin<nrt::PixGray<uint8_t>>();
495  auto cloudEnd1 = cloud1.end<nrt::PixGray<uint8_t>>();
496  auto cloudIter2 = cloud2.begin<nrt::PixGray<uint8_t>>();
497 
498  for( ; cloudIter1 != cloudEnd1; ++cloudIter1, ++cloudIter2 )
499  {
500  BOOST_CHECK_EQUAL( cloudIter1->geometry(), cloudIter2->geometry() );
501  BOOST_CHECK_EQUAL( cloudIter1->get<nrt::PixGray<uint8_t>>(),
502  cloudIter2->get<nrt::PixGray<uint8_t>>() );
503  }
504  }
505  }
506 }
507