GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: test/serialization.cpp Lines: 136 136 100.0 %
Date: 2024-02-09 12:57:42 Branches: 431 857 50.3 %

Line Branch Exec Source
1
/*
2
 *  Software License Agreement (BSD License)
3
 *
4
 *  Copyright (c) 2021-2022 INRIA.
5
 *  All rights reserved.
6
 *
7
 *  Redistribution and use in source and binary forms, with or without
8
 *  modification, are permitted provided that the following conditions
9
 *  are met:
10
 *
11
 *   * Redistributions of source code must retain the above copyright
12
 *     notice, this list of conditions and the following disclaimer.
13
 *   * Redistributions in binary form must reproduce the above
14
 *     copyright notice, this list of conditions and the following
15
 *     disclaimer in the documentation and/or other materials provided
16
 *     with the distribution.
17
 *   * Neither the name of Willow Garage, Inc. nor the names of its
18
 *     contributors may be used to endorse or promote products derived
19
 *     from this software without specific prior written permission.
20
 *
21
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 *  POSSIBILITY OF SUCH DAMAGE.
33
 */
34
35
#define BOOST_TEST_MODULE FCL_SERIALIZATION
36
#include <fstream>
37
#include <boost/test/included/unit_test.hpp>
38
39
#include <hpp/fcl/collision.h>
40
#include <hpp/fcl/distance.h>
41
#include <hpp/fcl/BV/OBBRSS.h>
42
#include <hpp/fcl/BVH/BVH_model.h>
43
44
#include <hpp/fcl/serialization/collision_data.h>
45
#include <hpp/fcl/serialization/AABB.h>
46
#include <hpp/fcl/serialization/BVH_model.h>
47
#include <hpp/fcl/serialization/hfield.h>
48
#include <hpp/fcl/serialization/geometric_shapes.h>
49
#include <hpp/fcl/serialization/convex.h>
50
#include <hpp/fcl/serialization/memory.h>
51
52
#include "utility.h"
53
#include "fcl_resources/config.h"
54
55
#include <boost/archive/tmpdir.hpp>
56
#include <boost/archive/text_iarchive.hpp>
57
#include <boost/archive/text_oarchive.hpp>
58
#include <boost/archive/xml_iarchive.hpp>
59
#include <boost/archive/xml_oarchive.hpp>
60
#include <boost/archive/binary_iarchive.hpp>
61
#include <boost/archive/binary_oarchive.hpp>
62
#include <boost/filesystem.hpp>
63
64
#include <boost/asio/streambuf.hpp>
65
66
namespace utf = boost::unit_test::framework;
67
68
using namespace hpp::fcl;
69
70
template <typename T>
71
38
void saveToBinary(const T& object, boost::asio::streambuf& buffer) {
72
76
  boost::archive::binary_oarchive oa(buffer);
73
38
  oa & object;
74
38
}
75
76
template <typename T>
77
38
inline void loadFromBinary(T& object, boost::asio::streambuf& buffer) {
78
76
  boost::archive::binary_iarchive ia(buffer);
79
38
  ia >> object;
80
38
}
81
82
template <typename T>
83
212
bool check(const T& value, const T& other) {
84
212
  return value == other;
85
}
86
87
enum SerializationMode { TXT = 1, XML = 2, BIN = 4, STREAM = 8 };
88
89
template <typename T>
90
38
void test_serialization(const T& value, T& other_value,
91
                        const int mode = TXT | XML | BIN | STREAM) {
92
76
  const boost::filesystem::path tmp_path(boost::archive::tmpdir());
93
76
  const boost::filesystem::path txt_path("file.txt");
94
76
  const boost::filesystem::path bin_path("file.bin");
95
76
  const boost::filesystem::path txt_filename(tmp_path / txt_path);
96
76
  const boost::filesystem::path bin_filename(tmp_path / bin_path);
97
98
  // TXT
99
38
  if (mode & 0x1) {
100
    {
101
68
      std::ofstream ofs(txt_filename.c_str());
102
103
68
      boost::archive::text_oarchive oa(ofs);
104
34
      oa << value;
105
    }
106



34
    BOOST_CHECK(check(value, value));
107
108
    {
109
68
      std::ifstream ifs(txt_filename.c_str());
110
68
      boost::archive::text_iarchive ia(ifs);
111
112
34
      ia >> other_value;
113
    }
114



34
    BOOST_CHECK(check(value, other_value));
115
  }
116
117
  // BIN
118
38
  if (mode & 0x4) {
119
    {
120
68
      std::ofstream ofs(bin_filename.c_str(), std::ios::binary);
121
68
      boost::archive::binary_oarchive oa(ofs);
122
34
      oa << value;
123
    }
124



34
    BOOST_CHECK(check(value, value));
125
126
    {
127
68
      std::ifstream ifs(bin_filename.c_str(), std::ios::binary);
128
68
      boost::archive::binary_iarchive ia(ifs);
129
130
34
      ia >> other_value;
131
    }
132



34
    BOOST_CHECK(check(value, other_value));
133
  }
134
135
  // Stream Buffer
136
38
  if (mode & 0x8) {
137
76
    boost::asio::streambuf buffer;
138
38
    saveToBinary(value, buffer);
139



38
    BOOST_CHECK(check(value, value));
140
141
38
    loadFromBinary(other_value, buffer);
142



38
    BOOST_CHECK(check(value, other_value));
143
  }
144
38
}
145
146
template <typename T>
147
12
void test_serialization(const T& value,
148
                        const int mode = TXT | XML | BIN | STREAM) {
149
14
  T other_value;
150
12
  test_serialization(value, other_value, mode);
151
12
}
152
153
















4
BOOST_AUTO_TEST_CASE(test_aabb) {
154



2
  AABB aabb(-Vec3f::Ones(), Vec3f::Ones());
155
2
  test_serialization(aabb);
156
2
}
157
158
















4
BOOST_AUTO_TEST_CASE(test_collision_data) {
159


2
  Contact contact(NULL, NULL, 1, 2, Vec3f::Ones(), Vec3f::Zero(), -10.);
160
2
  test_serialization(contact);
161
162
2
  CollisionRequest collision_request(CONTACT, 10);
163
2
  test_serialization(collision_request);
164
165
4
  CollisionResult collision_result;
166
2
  collision_result.addContact(contact);
167
2
  collision_result.addContact(contact);
168
2
  collision_result.distance_lower_bound = 0.1;
169
2
  test_serialization(collision_result);
170
171
2
  DistanceRequest distance_request(true, 1., 2.);
172
2
  test_serialization(distance_request);
173
174
2
  DistanceResult distance_result;
175
2
  distance_result.normal.setOnes();
176
2
  distance_result.nearest_points[0].setRandom();
177
2
  distance_result.nearest_points[1].setRandom();
178
2
  test_serialization(distance_result);
179
2
}
180
181
















4
BOOST_AUTO_TEST_CASE(test_BVHModel) {
182
4
  std::vector<Vec3f> p1, p2;
183
4
  std::vector<Triangle> t1, t2;
184
4
  boost::filesystem::path path(TEST_RESOURCES_DIR);
185
186

2
  loadOBJFile((path / "env.obj").string().c_str(), p1, t1);
187

2
  loadOBJFile((path / "rob.obj").string().c_str(), p2, t2);
188
189

4
  BVHModel<OBBRSS> m1, m2;
190
191
2
  m1.beginModel();
192
2
  m1.addSubModel(p1, t1);
193
2
  m1.endModel();
194



2
  BOOST_CHECK(m1 == m1);
195
196
2
  m2.beginModel();
197
2
  m2.addSubModel(p2, t2);
198
2
  m2.endModel();
199



2
  BOOST_CHECK(m2 == m2);
200



2
  BOOST_CHECK(m1 != m2);
201
202
  // Test BVHModel
203
  {
204
4
    BVHModel<OBBRSS> m1_copy;
205
2
    test_serialization(m1, m1_copy);
206
  }
207
  {
208
4
    BVHModel<OBBRSS> m1_copy;
209
2
    test_serialization(m1, m1_copy, STREAM);
210
  }
211
2
}
212
213
#ifdef HPP_FCL_HAS_QHULL
214
BOOST_AUTO_TEST_CASE(test_Convex) {
215
  std::vector<Vec3f> p1;
216
  std::vector<Triangle> t1;
217
  boost::filesystem::path path(TEST_RESOURCES_DIR);
218
219
  loadOBJFile((path / "env.obj").string().c_str(), p1, t1);
220
221
  BVHModel<OBBRSS> m1;
222
223
  m1.beginModel();
224
  m1.addSubModel(p1, t1);
225
  m1.endModel();
226
227
  m1.buildConvexHull(true);
228
229
  Convex<Triangle>& convex = static_cast<Convex<Triangle>&>(*m1.convex.get());
230
231
  // Test Convex
232
  {
233
    Convex<Triangle> convex_copy;
234
    test_serialization(convex, convex_copy);
235
  }
236
}
237
#endif
238
239
















4
BOOST_AUTO_TEST_CASE(test_HeightField) {
240
2
  const FCL_REAL min_altitude = -1.;
241
2
  const FCL_REAL x_dim = 1., y_dim = 2.;
242
2
  const Eigen::DenseIndex nx = 100, ny = 200;
243

4
  const MatrixXf heights = MatrixXf::Random(ny, nx);
244
245
4
  HeightField<OBBRSS> hfield(x_dim, y_dim, heights, min_altitude);
246
247
  // Test HeightField
248
  {
249
4
    HeightField<OBBRSS> hfield_copy;
250
2
    test_serialization(hfield, hfield_copy);
251
  }
252
  {
253
4
    HeightField<OBBRSS> hfield_copy;
254
2
    test_serialization(hfield, hfield_copy, STREAM);
255
  }
256
2
}
257
258
















4
BOOST_AUTO_TEST_CASE(test_shapes) {
259
  {
260



4
    TriangleP triangle(Vec3f::UnitX(), Vec3f::UnitY(), Vec3f::UnitZ());
261



4
    TriangleP triangle_copy(Vec3f::Random(), Vec3f::Random(), Vec3f::Random());
262
2
    test_serialization(triangle, triangle_copy);
263
  }
264
265
  {
266



4
    Box box(Vec3f::UnitX()), box_copy(Vec3f::Random());
267
2
    test_serialization(box, box_copy);
268
  }
269
270
  {
271

4
    Sphere sphere(1.), sphere_copy(2.);
272
2
    test_serialization(sphere, sphere_copy);
273
  }
274
275
  {
276

4
    Ellipsoid ellipsoid(1., 2., 3.), ellipsoid_copy(0., 0., 0.);
277
2
    test_serialization(ellipsoid, ellipsoid_copy);
278
  }
279
280
  {
281

4
    Capsule capsule(1., 2.), capsule_copy(10., 10.);
282
2
    test_serialization(capsule, capsule_copy);
283
  }
284
285
  {
286

4
    Cone cone(1., 2.), cone_copy(10., 10.);
287
2
    test_serialization(cone, cone_copy);
288
  }
289
290
  {
291

4
    Cylinder cylinder(1., 2.), cylinder_copy(10., 10.);
292
2
    test_serialization(cylinder, cylinder_copy);
293
  }
294
295
  {
296



4
    Halfspace hs(Vec3f::Random(), 1.), hs_copy(Vec3f::Zero(), 0.);
297
2
    test_serialization(hs, hs_copy);
298
  }
299
300
  {
301



4
    Plane plane(Vec3f::Random(), 1.), plane_copy(Vec3f::Zero(), 0.);
302
2
    test_serialization(plane, plane_copy);
303
  }
304
2
}
305
306
















4
BOOST_AUTO_TEST_CASE(test_memory_footprint) {
307
4
  Sphere sphere(1.);
308



2
  BOOST_CHECK(sizeof(Sphere) == computeMemoryFootprint(sphere));
309
310
4
  std::vector<Vec3f> p1;
311
4
  std::vector<Triangle> t1;
312
4
  boost::filesystem::path path(TEST_RESOURCES_DIR);
313
314

2
  loadOBJFile((path / "env.obj").string().c_str(), p1, t1);
315
316
4
  BVHModel<OBBRSS> m1;
317
318
2
  m1.beginModel();
319
2
  m1.addSubModel(p1, t1);
320
2
  m1.endModel();
321
322

2
  std::cout << "computeMemoryFootprint(m1): " << computeMemoryFootprint(m1)
323
2
            << std::endl;
324



2
  BOOST_CHECK(sizeof(BVHModel<OBBRSS>) < computeMemoryFootprint(m1));
325




2
  BOOST_CHECK(static_cast<size_t>(m1.memUsage(false)) ==
326
              computeMemoryFootprint(m1));
327
2
}