cyclical_buffer.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 
40 #include <kfusion/precomp.hpp>
41 
42 bool
43 kfusion::cuda::CyclicalBuffer::checkForShift (cv::Ptr<cuda::TsdfVolume> volume, const Affine3f &cam_pose, const double distance_camera_target, const bool perform_shift, const bool last_shift, const bool record_mode)
44 {
45  bool result = false;
46  //mcwrap_.setCameraDist(distance_camera_target);
47  cv::Vec3f targetPoint(0,0, distance_camera_target);
48  targetPoint = cam_pose * targetPoint;
49  targetPoint[1] = cam_pose.translation()[1];
50  cv::Vec3f center_cube;
51  center_cube[0] = buffer_.origin_metric.x + buffer_.volume_size.x/2.0f;
52  center_cube[1] = buffer_.origin_metric.y + buffer_.volume_size.y/2.0f;
53  center_cube[2] = buffer_.origin_metric.z + buffer_.volume_size.z/2.0f;
54  double dist = norm(targetPoint, center_cube, cv::NORM_L2);
55  //printf(" dist: %f \n", dist);
56  if (dist > distance_threshold_)
57  result = true;
58 
59  // perform shifting operations
60  if (result || last_shift || perform_shift)
61  {
62  performShift (volume, targetPoint, cam_pose, last_shift, record_mode);
63  return true;
64  }
65 
66  return (result);
67 }
68 
69 
70 void
71 kfusion::cuda::CyclicalBuffer::performShift (cv::Ptr<cuda::TsdfVolume> volume, const cv::Vec3f& target_point, const Affine3f &cam_pose, const bool last_shift, const bool record_mode)
72 {
73  //ScopeTime* time = new ScopeTime("Whole Cube shift");
74  // compute new origin and offsets
75  Vec3i offset;
76  Vec3i minBounds;
77  Vec3i maxBounds;
78  if(!last_shift)
79  computeAndSetNewCubeMetricOrigin (volume, target_point, offset);
80  //ScopeTime* slice_time = new ScopeTime("Slice download");
81  // extract current slice from the TSDF volume (coordinates are in indices! (see fetchSliceAsCloud() )
82  if(!no_reconstruct_)
83  {
84  DeviceArray<Point> cloud;
85 
86  // calculate mininum and maximum slice bounds
87  if(last_shift)
88  {
89  minBounds[0] = minBounds[1] = minBounds[2] = 0;
90  maxBounds[0] = maxBounds[1] = maxBounds[2] = 512;
91  }
92  else
93  {
94  calcBounds(offset, minBounds, maxBounds);
95  }
96 
97  cloud = volume->fetchSliceAsCloud(cloud_buffer_device_, &buffer_, minBounds, maxBounds, global_shift_ );
98 
99  cloud_slice_ = cv::Mat(1, (int)cloud.size(), CV_32FC4);
100  cloud.download(cloud_slice_.ptr<Point>());
101 
102  //delete slice_time;
103 
104  Point* tsdf_ptr = cloud_slice_.ptr<Point>();
105  if(cloud.size() > 0)
106  {
107  std::cout << "#### Performing slice number: " << slice_count_ << " with " << cloud.size() << " TSDF values ####" << std::endl;
108  Vec3i fusionShift = global_shift_;
109  Vec3i fusionBackShift = global_shift_;
110  for(int i = 0; i < 3; i++)
111  {
112  if(minBounds[i] == 1 && !last_shift)
113  {
114  fusionShift[i] += maxBounds[i];
115  fusionBackShift[i] += minBounds[i];
116  }
117  else if(last_shift)
118  {
119  fusionShift[i] -= 1000000000;
120  fusionBackShift[i] += maxBounds[i];
121  }
122  else
123  {
124  fusionShift[i] += minBounds[i];
125  fusionBackShift[i] += maxBounds[i];
126  }
127  }
128  TSDFSlice slice;
129  slice.tsdf_values_ = cloud_slice_;
130  slice.offset_ = fusionShift;
131  slice.back_offset_ = fusionBackShift;
132  slice.imgposes_ = imgPoses_;
133  pl_.addTSDFSlice(slice, last_shift);
134  slice_count_++;
135  }
136  }
137  if(!last_shift)
138  {
139  // clear buffer slice and update the world model
140  volume->clearSlice(&buffer_, offset);
141 
142  // shift buffer addresses
143  shiftOrigin (volume, offset);
144  }
145 
146 
147 }
148 
149 void
150 kfusion::cuda::CyclicalBuffer::computeAndSetNewCubeMetricOrigin (cv::Ptr<cuda::TsdfVolume> volume, const cv::Vec3f& target_point, Vec3i& offset)
151 {
152  // compute new origin for the cube, based on the target point
153  float3 new_cube_origin_meters;
154  new_cube_origin_meters.x = target_point[0] - buffer_.volume_size.x/2.0f;
155  new_cube_origin_meters.y = target_point[1] - buffer_.volume_size.y/2.0f;
156  new_cube_origin_meters.z = target_point[2] - buffer_.volume_size.z/2.0f;
157  //printf("The old cube's metric origin was (%f, %f, %f).\n", buffer_.origin_metric.x, buffer_.origin_metric.y, buffer_.origin_metric.z);
158  //printf("The new cube's metric origin is now (%f, %f, %f).\n", new_cube_origin_meters.x, new_cube_origin_meters.y, new_cube_origin_meters.z);
159 
160  // deduce each shift in indices
161  offset[0] = calcIndex((new_cube_origin_meters.x - buffer_.origin_metric.x) * ( buffer_.voxels_size.x / (float) (buffer_.volume_size.x) ));
162  offset[1] = calcIndex((new_cube_origin_meters.y - buffer_.origin_metric.y) * ( buffer_.voxels_size.y / (float) (buffer_.volume_size.y) ));
163  offset[2] = calcIndex((new_cube_origin_meters.z - buffer_.origin_metric.z) * ( buffer_.voxels_size.z / (float) (buffer_.volume_size.z) ));
164 
165  //printf("The shift indices are (X:%d, Y:%d, Z:%d).\n", offset[0], offset[1], offset[2]);
166  // update the cube's metric origin
167  buffer_.origin_metric = new_cube_origin_meters;
168  volume->setPose(Affine3f().translate(Vec3f(new_cube_origin_meters.x, new_cube_origin_meters.y, new_cube_origin_meters.z)));
169 }
170 
171 void kfusion::cuda::CyclicalBuffer::calcBounds(Vec3i& offset, Vec3i& minBounds, Vec3i& maxBounds)
172 {
173 
174  //Compute slice bounds
175  int newX = buffer_.origin_GRID.x + offset[0];
176  int newY = buffer_.origin_GRID.y + offset[1];
177  int newZ = buffer_.origin_GRID.z + offset[2];
178 
179  //X
180  if (newX >= 0)
181  {
182  minBounds[0] = buffer_.origin_GRID.x;
183  maxBounds[0] = newX;
184  }
185  else
186  {
187  minBounds[0] = newX + buffer_.voxels_size.x;
188  maxBounds[0] = buffer_.origin_GRID.x + buffer_.voxels_size.x;
189  }
190 
191  if (minBounds[0] > maxBounds[0])
192  std::swap (minBounds[0], maxBounds[0]);
193 
194  //Y
195  if (newY >= 0)
196  {
197  minBounds[1] = buffer_.origin_GRID.y;
198  maxBounds[1] = newY;
199  }
200  else
201  {
202  minBounds[1] = newY + buffer_.voxels_size.y;
203  maxBounds[1] = buffer_.origin_GRID.y + buffer_.voxels_size.y;
204  }
205 
206  if(minBounds[1] > maxBounds[1])
207  std::swap (minBounds[1], maxBounds[1]);
208 
209  //Z
210  if (newZ >= 0)
211  {
212  minBounds[2] = buffer_.origin_GRID.z;
213  maxBounds[2] = newZ;
214  }
215  else
216  {
217  minBounds[2] = newZ + buffer_.voxels_size.z;
218  maxBounds[2] = buffer_.origin_GRID.z + buffer_.voxels_size.z;
219  }
220 
221  if (minBounds[2] > maxBounds[2])
222  std::swap(minBounds[2], maxBounds[2]);
223 
224  minBounds[0] -= buffer_.origin_GRID.x;
225  maxBounds[0] -= buffer_.origin_GRID.x;
226 
227  minBounds[1] -= buffer_.origin_GRID.y;
228  maxBounds[1] -= buffer_.origin_GRID.y;
229 
230  minBounds[2] -= buffer_.origin_GRID.z;
231  maxBounds[2] -= buffer_.origin_GRID.z;
232 
233  if (minBounds[0] < 0) // We are shifting Left
234  {
235  minBounds[0] += buffer_.voxels_size.x;
236  maxBounds[0] += buffer_.voxels_size.x;
237  }
238 
239 
240  if (minBounds[1] < 0) // We are shifting up
241  {
242  minBounds[1] += buffer_.voxels_size.y;
243  maxBounds[1] += buffer_.voxels_size.y;
244  }
245 
246  if (minBounds[2] < 0) // We are shifting forward
247  {
248  minBounds[2] += buffer_.voxels_size.z;
249  maxBounds[2] += buffer_.voxels_size.z;
250  }
251  for(int i = 0; i < 3; i++)
252  {
253  if(maxBounds[i] > 0)
254  {
255  if(minBounds[i] == 0)
256  {
257  maxBounds[i] += 1;
258  minBounds[i] += 1;
259 
260  }
261  if(maxBounds[i] == 512)
262  {
263  minBounds[i] -= 1;
264  maxBounds[i] -= 1;
265  //offset[i] -=1;
266  }
267  }
268  }
269 
270 
271  //cout << "minBounds: " << minBounds[0] << ", " << minBounds[1] << ", " << minBounds[2] << endl;
272  //cout << "maxBounds: " << maxBounds[0] << ", " << maxBounds[1] << ", " << maxBounds[2] << endl;
273 }
cv::Vec3f Vec3f
Definition: types.hpp:16
std::vector< ImgPose * > imgPoses_
size_t size() const
Returns size in elements.
cv::Affine3f Affine3f
Definition: types.hpp:18
double distance_threshold_
distance threshold (cube&#39;s center to target point) to trigger shift
void shiftOrigin(cv::Ptr< cuda::TsdfVolume > tsdf_volume, Vec3i offset)
updates cyclical buffer origins given offsets on X, Y and Z
DeviceArray< Point > cloud_buffer_device_
buffer used to extract XYZ values from GPU
__kf_hdevice__ void swap(T &a, T &b)
Definition: temp_utils.hpp:10
int3 voxels_size
Number of voxels in the volume, per axis.
Definition: tsdf_buffer.h:66
std::vector< ImgPose * > imgposes_
Definition: types.hpp:42
cv::Vec3i Vec3i
Definition: types.hpp:17
void addTSDFSlice(TSDFSlice slice, const bool last_shift)
Definition: LVRPipeline.cpp:82
void computeAndSetNewCubeMetricOrigin(cv::Ptr< cuda::TsdfVolume > volume, const cv::Vec3f &target_point, Vec3i &offset)
Computes and set the origin of the new cube (relative to the world), centered around a the target poi...
bool checkForShift(cv::Ptr< cuda::TsdfVolume > volume, const Affine3f &cam_pose, const double distance_camera_target, const bool perform_shift=true, const bool last_shift=false, const bool record_mode=false)
Check if shifting needs to be performed, returns true if so. Shifting is considered needed if the tar...
cv::Mat tsdf_values_
Definition: types.hpp:39
void calcBounds(Vec3i &offset, Vec3i &minBounds, Vec3i &maxBounds)
tsdf_buffer buffer_
structure that contains all TSDF buffer&#39;s addresses
void download(T *host_ptr) const
Downloads data from internal buffer to CPU memory.
Vec3i back_offset_
Definition: types.hpp:41
int3 origin_GRID
Internal cube origin for rollign buffer.
Definition: tsdf_buffer.h:58
float3 volume_size
Size of the volume, in meters.
Definition: tsdf_buffer.h:64
float3 origin_metric
Current metric origin of the cube, in world coordinates.
Definition: tsdf_buffer.h:62
void performShift(cv::Ptr< cuda::TsdfVolume > volume, const cv::Vec3f &target_point, const Affine3f &cam_pose, const bool last_shift=false, const bool record_mode=false)
Perform shifting operations: Compute offsets. Extract current slice from TSDF buffer. Extract existing data from world. Clear shifted slice in TSDF buffer. Push existing data into TSDF buffer. Update rolling buffer Update world model.
__kf_device__ float norm(const float3 &v)
Definition: temp_utils.hpp:87


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:06