Open3D (C++ API)  0.13.0
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
FillInLinearSystemImpl.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2021 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #pragma once
28 
29 #include <fstream>
30 
35 
36 namespace open3d {
37 namespace t {
38 namespace pipelines {
39 namespace slac {
40 
41 using namespace open3d::core::eigen_converter;
42 using core::Tensor;
43 using t::geometry::PointCloud;
44 
45 // Reads pointcloud from filename, and loads on the device as
46 // Tensor PointCloud of Float32 dtype.
47 static PointCloud CreateTPCDFromFile(
48  const std::string& fname,
49  const core::Device& device = core::Device("CPU:0")) {
50  std::shared_ptr<open3d::geometry::PointCloud> pcd =
53 }
54 
55 static void FillInRigidAlignmentTerm(Tensor& AtA,
56  Tensor& Atb,
57  Tensor& residual,
58  PointCloud& tpcd_i,
59  PointCloud& tpcd_j,
60  const Tensor& Ti,
61  const Tensor& Tj,
62  const int i,
63  const int j,
64  const float threshold) {
65  tpcd_i.Transform(Ti);
66  tpcd_j.Transform(Tj);
67 
68  kernel::FillInRigidAlignmentTerm(AtA, Atb, residual, tpcd_i.GetPoints(),
69  tpcd_j.GetPoints(),
70  tpcd_i.GetPointNormals(), i, j, threshold);
71 }
72 
73 void FillInRigidAlignmentTerm(Tensor& AtA,
74  Tensor& Atb,
75  Tensor& residual,
76  const std::vector<std::string>& fnames,
77  const PoseGraph& pose_graph,
78  const SLACOptimizerParams& params,
79  const SLACDebugOption& debug_option) {
80  core::Device device(params.device_);
81 
82  // Enumerate pose graph edges
83  for (auto& edge : pose_graph.edges_) {
84  int i = edge.source_node_id_;
85  int j = edge.target_node_id_;
86 
87  std::string corres_fname = fmt::format("{}/{:03d}_{:03d}.npy",
88  params.GetSubfolderName(), i, j);
89  if (!utility::filesystem::FileExists(corres_fname)) {
90  utility::LogWarning("Correspondence {} {} skipped!", i, j);
91  continue;
92  }
93  Tensor corres_ij = Tensor::Load(corres_fname).To(device);
94  PointCloud tpcd_i = CreateTPCDFromFile(fnames[i], device);
95  PointCloud tpcd_j = CreateTPCDFromFile(fnames[j], device);
96 
97  PointCloud tpcd_i_indexed(
98  tpcd_i.GetPoints().IndexGet({corres_ij.T()[0]}));
99  tpcd_i_indexed.SetPointNormals(
100  tpcd_i.GetPointNormals().IndexGet({corres_ij.T()[0]}));
101  PointCloud tpcd_j_indexed(
102  tpcd_j.GetPoints().IndexGet({corres_ij.T()[1]}));
103 
104  Tensor Ti = EigenMatrixToTensor(pose_graph.nodes_[i].pose_)
105  .To(device, core::Dtype::Float32);
106  Tensor Tj = EigenMatrixToTensor(pose_graph.nodes_[j].pose_)
107  .To(device, core::Dtype::Float32);
108 
109  FillInRigidAlignmentTerm(AtA, Atb, residual, tpcd_i_indexed,
110  tpcd_j_indexed, Ti, Tj, i, j,
111  params.distance_threshold_);
112 
113  if (debug_option.debug_ && i >= debug_option.debug_start_node_idx_) {
114  VisualizePointCloudCorrespondences(tpcd_i, tpcd_j, corres_ij,
115  Tj.Inverse().Matmul(Ti));
116  }
117  }
118 }
119 
120 static void FillInSLACAlignmentTerm(Tensor& AtA,
121  Tensor& Atb,
122  Tensor& residual,
123  ControlGrid& ctr_grid,
124  const PointCloud& tpcd_param_i,
125  const PointCloud& tpcd_param_j,
126  const Tensor& Ti,
127  const Tensor& Tj,
128  const int i,
129  const int j,
130  const int n_fragments,
131  const float threshold) {
132  // Parameterize: setup point cloud -> cgrid correspondences
133  Tensor cgrid_index_ps =
135  Tensor cgrid_ratio_ps =
137 
138  Tensor cgrid_index_qs =
140  Tensor cgrid_ratio_qs =
142 
143  // Deform with control grids
144  PointCloud tpcd_nonrigid_i = ctr_grid.Deform(tpcd_param_i);
145  PointCloud tpcd_nonrigid_j = ctr_grid.Deform(tpcd_param_j);
146 
147  Tensor Cps = tpcd_nonrigid_i.GetPoints();
148  Tensor Cqs = tpcd_nonrigid_j.GetPoints();
149  Tensor Cnormal_ps = tpcd_nonrigid_i.GetPointNormals();
150 
151  Tensor Ri = Ti.Slice(0, 0, 3).Slice(1, 0, 3);
152  Tensor ti = Ti.Slice(0, 0, 3).Slice(1, 3, 4);
153 
154  Tensor Rj = Tj.Slice(0, 0, 3).Slice(1, 0, 3);
155  Tensor tj = Tj.Slice(0, 0, 3).Slice(1, 3, 4);
156 
157  // Transform for required entries
158  Tensor Ti_Cps = (Ri.Matmul(Cps.T())).Add_(ti).T().Contiguous();
159  Tensor Tj_Cqs = (Rj.Matmul(Cqs.T())).Add_(tj).T().Contiguous();
160  Tensor Ri_Cnormal_ps = (Ri.Matmul(Cnormal_ps.T())).T().Contiguous();
161  Tensor RjT_Ri_Cnormal_ps =
162  (Rj.T().Matmul(Ri_Cnormal_ps.T())).T().Contiguous();
163 
165  AtA, Atb, residual, Ti_Cps, Tj_Cqs, Cnormal_ps, Ri_Cnormal_ps,
166  RjT_Ri_Cnormal_ps, cgrid_index_ps, cgrid_index_qs, cgrid_ratio_ps,
167  cgrid_ratio_qs, i, j, n_fragments, threshold);
168 }
169 
170 void FillInSLACAlignmentTerm(Tensor& AtA,
171  Tensor& Atb,
172  Tensor& residual,
173  ControlGrid& ctr_grid,
174  const std::vector<std::string>& fnames,
175  const PoseGraph& pose_graph,
176  const SLACOptimizerParams& params,
177  const SLACDebugOption& debug_option) {
178  core::Device device(params.device_);
179  int n_frags = pose_graph.nodes_.size();
180 
181  // Enumerate pose graph edges.
182  for (auto& edge : pose_graph.edges_) {
183  int i = edge.source_node_id_;
184  int j = edge.target_node_id_;
185 
186  std::string corres_fname = fmt::format("{}/{:03d}_{:03d}.npy",
187  params.GetSubfolderName(), i, j);
188  if (!utility::filesystem::FileExists(corres_fname)) {
189  utility::LogWarning("Correspondence {} {} skipped!", i, j);
190  continue;
191  }
192  Tensor corres_ij = Tensor::Load(corres_fname).To(device);
193 
194  PointCloud tpcd_i = CreateTPCDFromFile(fnames[i], device);
195  PointCloud tpcd_j = CreateTPCDFromFile(fnames[j], device);
196 
197  PointCloud tpcd_i_indexed(
198  tpcd_i.GetPoints().IndexGet({corres_ij.T()[0]}));
199  tpcd_i_indexed.SetPointNormals(
200  tpcd_i.GetPointNormals().IndexGet({corres_ij.T()[0]}));
201 
202  PointCloud tpcd_j_indexed(
203  tpcd_j.GetPoints().IndexGet({corres_ij.T()[1]}));
204  tpcd_j_indexed.SetPointNormals(
205  tpcd_j.GetPointNormals().IndexGet({corres_ij.T()[1]}));
206 
207  // Parameterize points in the control grid.
208  PointCloud tpcd_param_i = ctr_grid.Parameterize(tpcd_i_indexed);
209  PointCloud tpcd_param_j = ctr_grid.Parameterize(tpcd_j_indexed);
210 
211  // Load poses.
212  auto Ti = EigenMatrixToTensor(pose_graph.nodes_[i].pose_)
213  .To(device, core::Dtype::Float32);
214  auto Tj = EigenMatrixToTensor(pose_graph.nodes_[j].pose_)
215  .To(device, core::Dtype::Float32);
216  auto Tij = EigenMatrixToTensor(edge.transformation_)
217  .To(device, core::Dtype::Float32);
218 
219  // Fill In.
220  FillInSLACAlignmentTerm(AtA, Atb, residual, ctr_grid, tpcd_param_i,
221  tpcd_param_j, Ti, Tj, i, j, n_frags,
222  params.distance_threshold_);
223 
224  if (debug_option.debug_ && i >= debug_option.debug_start_node_idx_) {
225  VisualizePointCloudCorrespondences(tpcd_i, tpcd_j, corres_ij,
226  Tj.Inverse().Matmul(Ti));
227  VisualizePointCloudEmbedding(tpcd_param_i, ctr_grid);
228  VisualizePointCloudDeformation(tpcd_param_i, ctr_grid);
229  }
230  }
231 }
232 
234  Tensor& Atb,
235  Tensor& residual,
236  ControlGrid& ctr_grid,
237  int n_frags,
238  const SLACOptimizerParams& params,
239  const SLACDebugOption& debug_option) {
240  Tensor active_addrs, nb_addrs, nb_masks;
241  std::tie(active_addrs, nb_addrs, nb_masks) = ctr_grid.GetNeighborGridMap();
242 
243  Tensor positions_init = ctr_grid.GetInitPositions();
244  Tensor positions_curr = ctr_grid.GetCurrPositions();
245  kernel::FillInSLACRegularizerTerm(AtA, Atb, residual, active_addrs,
246  nb_addrs, nb_masks, positions_init,
247  positions_curr,
248  n_frags * params.regularizer_weight_,
249  n_frags, ctr_grid.GetAnchorIdx());
250  if (debug_option.debug_) {
251  VisualizeGridDeformation(ctr_grid);
252  }
253 }
254 
255 } // namespace slac
256 } // namespace pipelines
257 } // namespace t
258 } // namespace open3d
void FillInSLACRegularizerTerm(Tensor &AtA, Tensor &Atb, Tensor &residual, ControlGrid &ctr_grid, int n_frags, const SLACOptimizerParams &params, const SLACDebugOption &debug_option)
Definition: FillInLinearSystemImpl.h:233
void VisualizePointCloudEmbedding(t::geometry::PointCloud &tpcd_param, ControlGrid &ctr_grid, bool show_lines)
Definition: Visualization.cpp:99
int debug_start_node_idx_
Definition: SLACOptimizer.h:115
static const std::string kGrid8NbIndices
Definition: ControlGrid.h:53
Tensor Inverse() const
Definition: Tensor.cpp:1597
#define LogWarning(...)
Definition: Console.h:95
float distance_threshold_
Distance threshold to filter inconsistent correspondences.
Definition: SLACOptimizer.h:52
int64_t GetAnchorIdx()
Definition: ControlGrid.h:136
void FillInSLACAlignmentTerm(core::Tensor &AtA, core::Tensor &Atb, core::Tensor &residual, const core::Tensor &Ti_ps, const core::Tensor &Tj_qs, const core::Tensor &normal_ps, const core::Tensor &Ri_normal_ps, const core::Tensor &RjT_Ri_normal_ps, const core::Tensor &cgrid_idx_ps, const core::Tensor &cgrid_idx_qs, const core::Tensor &cgrid_ratio_qs, const core::Tensor &cgrid_ratio_ps, int i, int j, int n, float threshold)
Definition: FillInLinearSystem.cpp:85
std::shared_ptr< geometry::PointCloud > CreatePointCloudFromFile(const std::string &filename, const std::string &format, bool print_progress)
Definition: PointCloudIO.cpp:68
Definition: SLACOptimizer.h:109
void VisualizePointCloudDeformation(const geometry::PointCloud &tpcd_param, ControlGrid &ctr_grid)
Definition: Visualization.cpp:159
core::Tensor & GetPoints()
Get the value of the "points" attribute. Convenience function.
Definition: PointCloud.h:135
Tensor Matmul(const Tensor &rhs) const
Definition: Tensor.cpp:1549
void SetPointNormals(const core::Tensor &value)
Set the value of the "normals" attribute. Convenience function.
Definition: PointCloud.h:189
void FillInRigidAlignmentTerm(core::Tensor &AtA, core::Tensor &Atb, core::Tensor &residual, const core::Tensor &Ti_ps, const core::Tensor &Tj_qs, const core::Tensor &Ri_normal_ps, int i, int j, float threshold)
Definition: FillInLinearSystem.cpp:34
Tensor IndexGet(const std::vector< Tensor > &index_tensors) const
Advanced indexing getter.
Definition: Tensor.cpp:704
Tensor T() const
Expects input to be <= 2-D Tensor by swapping dimension 0 and 1.
Definition: Tensor.cpp:772
bool debug_
Enable debug.
Definition: SLACOptimizer.h:111
Data structure defining the pose graph.
Definition: PoseGraph.h:115
geometry::PointCloud Parameterize(const geometry::PointCloud &pcd)
Definition: ControlGrid.cpp:168
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:540
Tensor Contiguous() const
Definition: Tensor.cpp:571
Definition: Device.h:39
std::vector< PoseGraphNode > nodes_
List of PoseGraphNode.
Definition: PoseGraph.h:127
A pointcloud contains a set of 3D points.
Definition: PointCloud.h:95
Definition: EigenConverter.cpp:35
geometry::PointCloud Deform(const geometry::PointCloud &pcd)
Non-rigidly deform a point cloud using the control grid.
Definition: ControlGrid.cpp:258
static const Dtype Float32
Definition: Dtype.h:42
static PointCloud FromLegacyPointCloud(const open3d::geometry::PointCloud &pcd_legacy, core::Dtype dtype=core::Dtype::Float32, const core::Device &device=core::Device("CPU:0"))
Create a PointCloud from a legacy Open3D PointCloud.
Definition: PointCloud.cpp:433
static Tensor Load(const std::string &file_name)
Load tensor from numpy&#39;s npy format.
Definition: Tensor.cpp:1463
Tensor Add_(const Tensor &value)
Definition: Tensor.cpp:803
void VisualizePointCloudCorrespondences(const t::geometry::PointCloud &tpcd_i, const t::geometry::PointCloud &tpcd_j, const core::Tensor correspondences, const core::Tensor &T_ij)
Visualize pairs with correspondences.
Definition: Visualization.cpp:65
void VisualizeGridDeformation(ControlGrid &cgrid)
Definition: Visualization.cpp:207
core::Tensor & GetPointNormals()
Get the value of the "normals" attribute. Convenience function.
Definition: PointCloud.h:141
core::Device device_
Device to use.
Definition: SLACOptimizer.h:61
Definition: PinholeCameraIntrinsic.cpp:35
Definition: Tensor.h:50
std::tuple< core::Tensor, core::Tensor, core::Tensor > GetNeighborGridMap()
Definition: ControlGrid.cpp:134
core::Tensor GetCurrPositions()
Definition: ControlGrid.h:130
const TensorMap & GetPointAttr() const
Getter for point_attr_ TensorMap. Used in Pybind.
Definition: PointCloud.h:125
void FillInSLACRegularizerTerm(core::Tensor &AtA, core::Tensor &Atb, core::Tensor &residual, const core::Tensor &grid_idx, const core::Tensor &grid_nbs_idx, const core::Tensor &grid_nbs_mask, const core::Tensor &positions_init, const core::Tensor &positions_curr, float weight, int n, int anchor_idx)
Definition: FillInLinearSystem.cpp:149
filament::Texture::InternalFormat format
Definition: FilamentResourceManager.cpp:199
Tensor Slice(int64_t dim, int64_t start, int64_t stop, int64_t step=1) const
Definition: Tensor.cpp:656
float regularizer_weight_
Weight of the regularizer.
Definition: SLACOptimizer.h:58
core::Tensor EigenMatrixToTensor(const Eigen::Matrix< T, M, N, A > &matrix)
Converts a Eigen matrix of shape (M, N) with alignment A and type T to a Tensor.
Definition: EigenConverter.h:47
static const std::string kGrid8NbVertexInterpRatios
8 neighbor grid interpolation ratio for vertex per point.
Definition: ControlGrid.h:55
std::string GetSubfolderName() const
Definition: SLACOptimizer.h:65
Definition: ControlGrid.h:49
std::vector< PoseGraphEdge > edges_
List of PoseGraphEdge.
Definition: PoseGraph.h:129
core::Tensor GetInitPositions()
Get control grid original positions directly from tensor keys.
Definition: ControlGrid.h:123
bool FileExists(const std::string &filename)
Definition: FileSystem.cpp:226