Open3D (C++ API)  0.20.0
Loading...
Searching...
No Matches
FillInLinearSystemImpl.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2026 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7
8#if !defined(__CUDACC__)
9#include <tbb/spin_mutex.h>
10#endif
11
15
16namespace open3d {
17namespace t {
18namespace pipelines {
19namespace kernel {
20
21// Computes the 12-element point-to-plane rigid alignment Jacobian for a
22// correspondence pair (frame i, frame j), given the transformed target point
23// q_prime and the rotated source normal normal_p_prime. J_ij[0:6] is the
24// Jacobian w.r.t. frame i's 6-DoF pose; J_ij[6:12] w.r.t. frame j's pose is
25// its negation. Shared by the CPU/CUDA path below and
26// FillInLinearSystemSYCL.cpp.
28 const float *q_prime, const float *normal_p_prime, float *J_ij) {
29 J_ij[0] = -q_prime[2] * normal_p_prime[1] + q_prime[1] * normal_p_prime[2];
30 J_ij[1] = q_prime[2] * normal_p_prime[0] - q_prime[0] * normal_p_prime[2];
31 J_ij[2] = -q_prime[1] * normal_p_prime[0] + q_prime[0] * normal_p_prime[1];
32 J_ij[3] = normal_p_prime[0];
33 J_ij[4] = normal_p_prime[1];
34 J_ij[5] = normal_p_prime[2];
35 for (int k = 0; k < 6; ++k) {
36 J_ij[k + 6] = -J_ij[k];
37 }
38}
39
40#ifndef OPEN3D_SKIP_FILL_IN_LS_MAIN
41#if defined(__CUDACC__)
42void FillInRigidAlignmentTermCUDA
43#else
45#endif
46 (core::Tensor &AtA,
47 core::Tensor &Atb,
48 core::Tensor &residual,
49 const core::Tensor &Ti_ps,
50 const core::Tensor &Tj_qs,
51 const core::Tensor &Ri_normal_ps,
52 int i,
53 int j,
54 float threshold) {
55
56 core::Device device = AtA.GetDevice();
57 int64_t n = Ti_ps.GetLength();
58 if (Tj_qs.GetLength() != n || Ri_normal_ps.GetLength() != n) {
59 utility::LogError(
60 "Unable to setup linear system: input length mismatch.");
61 }
62
63 // First fill in a small 12 x 12 linear system
64 core::Tensor AtA_local =
65 core::Tensor::Zeros({12, 12}, core::Float32, device);
66 core::Tensor Atb_local = core::Tensor::Zeros({12}, core::Float32, device);
67
68 float *AtA_local_ptr = static_cast<float *>(AtA_local.GetDataPtr());
69 float *Atb_local_ptr = static_cast<float *>(Atb_local.GetDataPtr());
70 float *residual_ptr = static_cast<float *>(residual.GetDataPtr());
71
72 const float *Ti_ps_ptr = static_cast<const float *>(Ti_ps.GetDataPtr());
73 const float *Tj_qs_ptr = static_cast<const float *>(Tj_qs.GetDataPtr());
74 const float *Ri_normal_ps_ptr =
75 static_cast<const float *>(Ri_normal_ps.GetDataPtr());
76// The mutexes below are compiled only for the host fallback; the SYCL path
77// uses its own work-group and global atomic reductions.
78#if !defined(__CUDACC__)
79 tbb::spin_mutex fill_alignment_mutex;
80 tbb::profiling::set_name(fill_alignment_mutex,
81 "FillInRigidAlignmentTermCPU");
82#define LOCAL_LAMBDA_CAPTURE =, &fill_alignment_mutex
83#else
84#define LOCAL_LAMBDA_CAPTURE =
85#endif
86
88 AtA.GetDevice(), n,
89 [LOCAL_LAMBDA_CAPTURE] OPEN3D_DEVICE(int64_t workload_idx) {
90 const float *p_prime = Ti_ps_ptr + 3 * workload_idx;
91 const float *q_prime = Tj_qs_ptr + 3 * workload_idx;
92 const float *normal_p_prime =
93 Ri_normal_ps_ptr + 3 * workload_idx;
94
95 float r = (p_prime[0] - q_prime[0]) * normal_p_prime[0] +
96 (p_prime[1] - q_prime[1]) * normal_p_prime[1] +
97 (p_prime[2] - q_prime[2]) * normal_p_prime[2];
98 if (abs(r) > threshold) return;
99
100 float J_ij[12];
101 ComputeRigidAlignmentJacobian(q_prime, normal_p_prime, J_ij);
102
103 // Not optimized; Switch to reduction if necessary.
104#if defined(BUILD_CUDA_MODULE) && defined(__CUDACC__)
105 for (int i_local = 0; i_local < 12; ++i_local) {
106 for (int j_local = 0; j_local < 12; ++j_local) {
107 atomicAdd(&AtA_local_ptr[i_local * 12 + j_local],
108 J_ij[i_local] * J_ij[j_local]);
109 }
110 atomicAdd(&Atb_local_ptr[i_local], J_ij[i_local] * r);
111 }
112 atomicAdd(residual_ptr, r * r);
113#else
114 {
115 tbb::spin_mutex::scoped_lock lock(fill_alignment_mutex);
116 for (int i_local = 0; i_local < 12; ++i_local) {
117 for (int j_local = 0; j_local < 12; ++j_local) {
118 AtA_local_ptr[i_local * 12 + j_local] +=
119 J_ij[i_local] * J_ij[j_local];
120 }
121 Atb_local_ptr[i_local] += J_ij[i_local] * r;
122 }
123 *residual_ptr += r * r;
124 }
125#endif
126 });
127#undef LOCAL_LAMBDA_CAPTURE
128
129 // Then fill-in the large linear system
130 std::vector<int64_t> indices_vec(12);
131 for (int k = 0; k < 6; ++k) {
132 indices_vec[k] = i * 6 + k;
133 indices_vec[k + 6] = j * 6 + k;
134 }
135
136 std::vector<int64_t> indices_i_vec;
137 std::vector<int64_t> indices_j_vec;
138 for (int local_i = 0; local_i < 12; ++local_i) {
139 for (int local_j = 0; local_j < 12; ++local_j) {
140 indices_i_vec.push_back(indices_vec[local_i]);
141 indices_j_vec.push_back(indices_vec[local_j]);
142 }
143 }
144
145 core::Tensor indices(indices_vec, {12}, core::Int64, device);
146 core::Tensor indices_i(indices_i_vec, {12 * 12}, core::Int64, device);
147 core::Tensor indices_j(indices_j_vec, {12 * 12}, core::Int64, device);
148
149 core::Tensor AtA_sub = AtA.IndexGet({indices_i, indices_j});
150 AtA.IndexSet({indices_i, indices_j}, AtA_sub + AtA_local.View({12 * 12}));
151
152 core::Tensor Atb_sub = Atb.IndexGet({indices});
153 Atb.IndexSet({indices}, Atb_sub + Atb_local.View({12, 1}));
154}
155
156#if defined(__CUDACC__)
157void FillInSLACAlignmentTermCUDA
158#else
160#endif
161 (core::Tensor &AtA,
162 core::Tensor &Atb,
163 core::Tensor &residual,
164 const core::Tensor &Ti_Cps,
165 const core::Tensor &Tj_Cqs,
166 const core::Tensor &Cnormal_ps,
167 const core::Tensor &Ri_Cnormal_ps,
168 const core::Tensor &RjT_Ri_Cnormal_ps,
169 const core::Tensor &cgrid_idx_ps,
170 const core::Tensor &cgrid_idx_qs,
171 const core::Tensor &cgrid_ratio_qs,
172 const core::Tensor &cgrid_ratio_ps,
173 int i,
174 int j,
175 int n_frags,
176 float threshold) {
177 int64_t n = Ti_Cps.GetLength();
178 if (Tj_Cqs.GetLength() != n || Cnormal_ps.GetLength() != n ||
179 Ri_Cnormal_ps.GetLength() != n || RjT_Ri_Cnormal_ps.GetLength() != n ||
180 cgrid_idx_ps.GetLength() != n || cgrid_ratio_ps.GetLength() != n ||
181 cgrid_idx_qs.GetLength() != n || cgrid_ratio_qs.GetLength() != n) {
182 utility::LogError(
183 "Unable to setup linear system: input length mismatch.");
184 }
185
186 int n_vars = Atb.GetLength();
187 float *AtA_ptr = static_cast<float *>(AtA.GetDataPtr());
188 float *Atb_ptr = static_cast<float *>(Atb.GetDataPtr());
189 float *residual_ptr = static_cast<float *>(residual.GetDataPtr());
190
191 // Geometric properties
192 const float *Ti_Cps_ptr = static_cast<const float *>(Ti_Cps.GetDataPtr());
193 const float *Tj_Cqs_ptr = static_cast<const float *>(Tj_Cqs.GetDataPtr());
194 const float *Cnormal_ps_ptr =
195 static_cast<const float *>(Cnormal_ps.GetDataPtr());
196 const float *Ri_Cnormal_ps_ptr =
197 static_cast<const float *>(Ri_Cnormal_ps.GetDataPtr());
198 const float *RjT_Ri_Cnormal_ps_ptr =
199 static_cast<const float *>(RjT_Ri_Cnormal_ps.GetDataPtr());
200
201 // Association properties
202 const int *cgrid_idx_ps_ptr =
203 static_cast<const int *>(cgrid_idx_ps.GetDataPtr());
204 const int *cgrid_idx_qs_ptr =
205 static_cast<const int *>(cgrid_idx_qs.GetDataPtr());
206 const float *cgrid_ratio_ps_ptr =
207 static_cast<const float *>(cgrid_ratio_ps.GetDataPtr());
208 const float *cgrid_ratio_qs_ptr =
209 static_cast<const float *>(cgrid_ratio_qs.GetDataPtr());
210
211#if !defined(__CUDACC__)
212 tbb::spin_mutex fill_alignment_mutex;
213 tbb::profiling::set_name(fill_alignment_mutex,
214 "FillInSLACAlignmentTermCPU");
215#define LOCAL_LAMBDA_CAPTURE =, &fill_alignment_mutex
216#else
217#define LOCAL_LAMBDA_CAPTURE =
218#endif
219
221 AtA.GetDevice(), n,
222 [LOCAL_LAMBDA_CAPTURE] OPEN3D_DEVICE(int64_t workload_idx) {
223 const float *Ti_Cp = Ti_Cps_ptr + 3 * workload_idx;
224 const float *Tj_Cq = Tj_Cqs_ptr + 3 * workload_idx;
225 const float *Cnormal_p = Cnormal_ps_ptr + 3 * workload_idx;
226 const float *Ri_Cnormal_p =
227 Ri_Cnormal_ps_ptr + 3 * workload_idx;
228 const float *RjTRi_Cnormal_p =
229 RjT_Ri_Cnormal_ps_ptr + 3 * workload_idx;
230
231 const int *cgrid_idx_p = cgrid_idx_ps_ptr + 8 * workload_idx;
232 const int *cgrid_idx_q = cgrid_idx_qs_ptr + 8 * workload_idx;
233 const float *cgrid_ratio_p =
234 cgrid_ratio_ps_ptr + 8 * workload_idx;
235 const float *cgrid_ratio_q =
236 cgrid_ratio_qs_ptr + 8 * workload_idx;
237
238 float r = (Ti_Cp[0] - Tj_Cq[0]) * Ri_Cnormal_p[0] +
239 (Ti_Cp[1] - Tj_Cq[1]) * Ri_Cnormal_p[1] +
240 (Ti_Cp[2] - Tj_Cq[2]) * Ri_Cnormal_p[2];
241 if (abs(r) > threshold) return;
242
243 // Now we fill in a 60 x 60 sub-matrix: 2 x (6 + 8 x 3)
244 float J[60];
245 int idx[60];
246
247 // Jacobian w.r.t. Ti: 0-6
248 J[0] = -Tj_Cq[2] * Ri_Cnormal_p[1] + Tj_Cq[1] * Ri_Cnormal_p[2];
249 J[1] = Tj_Cq[2] * Ri_Cnormal_p[0] - Tj_Cq[0] * Ri_Cnormal_p[2];
250 J[2] = -Tj_Cq[1] * Ri_Cnormal_p[0] + Tj_Cq[0] * Ri_Cnormal_p[1];
251 J[3] = Ri_Cnormal_p[0];
252 J[4] = Ri_Cnormal_p[1];
253 J[5] = Ri_Cnormal_p[2];
254
255 // Jacobian w.r.t. Tj: 6-12
256 for (int k = 0; k < 6; ++k) {
257 J[k + 6] = -J[k];
258
259 idx[k + 0] = 6 * i + k;
260 idx[k + 6] = 6 * j + k;
261 }
262
263 // Jacobian w.r.t. C over p: 12-36
264 for (int k = 0; k < 8; ++k) {
265 J[12 + k * 3 + 0] = cgrid_ratio_p[k] * Cnormal_p[0];
266 J[12 + k * 3 + 1] = cgrid_ratio_p[k] * Cnormal_p[1];
267 J[12 + k * 3 + 2] = cgrid_ratio_p[k] * Cnormal_p[2];
268
269 idx[12 + k * 3 + 0] = 6 * n_frags + cgrid_idx_p[k] * 3 + 0;
270 idx[12 + k * 3 + 1] = 6 * n_frags + cgrid_idx_p[k] * 3 + 1;
271 idx[12 + k * 3 + 2] = 6 * n_frags + cgrid_idx_p[k] * 3 + 2;
272 }
273
274 // Jacobian w.r.t. C over q: 36-60
275 for (int k = 0; k < 8; ++k) {
276 J[36 + k * 3 + 0] = -cgrid_ratio_q[k] * RjTRi_Cnormal_p[0];
277 J[36 + k * 3 + 1] = -cgrid_ratio_q[k] * RjTRi_Cnormal_p[1];
278 J[36 + k * 3 + 2] = -cgrid_ratio_q[k] * RjTRi_Cnormal_p[2];
279
280 idx[36 + k * 3 + 0] = 6 * n_frags + cgrid_idx_q[k] * 3 + 0;
281 idx[36 + k * 3 + 1] = 6 * n_frags + cgrid_idx_q[k] * 3 + 1;
282 idx[36 + k * 3 + 2] = 6 * n_frags + cgrid_idx_q[k] * 3 + 2;
283 }
284
285 // Not optimized; Switch to reduction if necessary.
286#if defined(__CUDACC__)
287 for (int ki = 0; ki < 60; ++ki) {
288 for (int kj = 0; kj < 60; ++kj) {
289 float AtA_ij = J[ki] * J[kj];
290 int ij = idx[ki] * n_vars + idx[kj];
291 atomicAdd(AtA_ptr + ij, AtA_ij);
292 }
293 float Atb_i = J[ki] * r;
294 atomicAdd(Atb_ptr + idx[ki], Atb_i);
295 }
296 atomicAdd(residual_ptr, r * r);
297#else
298 {
299 tbb::spin_mutex::scoped_lock lock(fill_alignment_mutex);
300 for (int ki = 0; ki < 60; ++ki) {
301 for (int kj = 0; kj < 60; ++kj) {
302 AtA_ptr[idx[ki] * n_vars + idx[kj]] +=
303 J[ki] * J[kj];
304 }
305 Atb_ptr[idx[ki]] += J[ki] * r;
306 }
307 *residual_ptr += r * r;
308 }
309#endif
310 });
311#undef LOCAL_LAMBDA_CAPTURE
312}
313
314#if defined(__CUDACC__)
315void FillInSLACRegularizerTermCUDA
316#else
318#endif
319 (core::Tensor &AtA,
320 core::Tensor &Atb,
321 core::Tensor &residual,
322 const core::Tensor &grid_idx,
323 const core::Tensor &grid_nbs_idx,
324 const core::Tensor &grid_nbs_mask,
325 const core::Tensor &positions_init,
326 const core::Tensor &positions_curr,
327 float weight,
328 int n_frags,
329 int anchor_idx) {
330
331 int64_t n = grid_idx.GetLength();
332 int64_t n_vars = Atb.GetLength();
333
334 float *AtA_ptr = static_cast<float *>(AtA.GetDataPtr());
335 float *Atb_ptr = static_cast<float *>(Atb.GetDataPtr());
336 float *residual_ptr = static_cast<float *>(residual.GetDataPtr());
337
338 const int *grid_idx_ptr = static_cast<const int *>(grid_idx.GetDataPtr());
339 const int *grid_nbs_idx_ptr =
340 static_cast<const int *>(grid_nbs_idx.GetDataPtr());
341 const bool *grid_nbs_mask_ptr =
342 static_cast<const bool *>(grid_nbs_mask.GetDataPtr());
343
344 const float *positions_init_ptr =
345 static_cast<const float *>(positions_init.GetDataPtr());
346 const float *positions_curr_ptr =
347 static_cast<const float *>(positions_curr.GetDataPtr());
348
349#if !defined(__CUDACC__)
350 tbb::spin_mutex fill_alignment_mutex;
351 tbb::profiling::set_name(fill_alignment_mutex,
352 "FillInSLACRegularizerTermCPU");
353#define LOCAL_LAMBDA_CAPTURE =, &fill_alignment_mutex
354#else
355#define LOCAL_LAMBDA_CAPTURE =
356#endif
357
359 AtA.GetDevice(), n,
360 [LOCAL_LAMBDA_CAPTURE] OPEN3D_DEVICE(int64_t workload_idx) {
361 // Enumerate 6 neighbors
362 int idx_i = grid_idx_ptr[workload_idx];
363
364 const int *idx_nbs = grid_nbs_idx_ptr + 6 * workload_idx;
365 const bool *mask_nbs = grid_nbs_mask_ptr + 6 * workload_idx;
366
367 // Build a 3x3 linear system to compute the local R
368 float cov[3][3] = {{0}};
369 float U[3][3], V[3][3], S[3];
370
371 int cnt = 0;
372 for (int k = 0; k < 6; ++k) {
373 bool mask_k = mask_nbs[k];
374 if (!mask_k) continue;
375
376 int idx_k = idx_nbs[k];
377
378 // Now build linear systems
379 float diff_ik_init[3] = {
380 positions_init_ptr[idx_i * 3 + 0] -
381 positions_init_ptr[idx_k * 3 + 0],
382 positions_init_ptr[idx_i * 3 + 1] -
383 positions_init_ptr[idx_k * 3 + 1],
384 positions_init_ptr[idx_i * 3 + 2] -
385 positions_init_ptr[idx_k * 3 + 2]};
386 float diff_ik_curr[3] = {
387 positions_curr_ptr[idx_i * 3 + 0] -
388 positions_curr_ptr[idx_k * 3 + 0],
389 positions_curr_ptr[idx_i * 3 + 1] -
390 positions_curr_ptr[idx_k * 3 + 1],
391 positions_curr_ptr[idx_i * 3 + 2] -
392 positions_curr_ptr[idx_k * 3 + 2]};
393
394 // Build linear system by computing XY^T when formulating Y
395 // = RX Y: curr X: init
396 for (int i = 0; i < 3; ++i) {
397 for (int j = 0; j < 3; ++j) {
398 cov[i][j] += diff_ik_init[i] * diff_ik_curr[j];
399 }
400 }
401 ++cnt;
402 }
403
404 if (cnt < 3) {
405 return;
406 }
407
408 core::linalg::kernel::svd3x3(*cov, *U, S, *V);
409
410 float R[3][3];
413
414 float d = core::linalg::kernel::det3x3(*R);
415
416 if (d < 0) {
417 U[2][0] = -U[2][0];
418 U[2][1] = -U[2][1];
419 U[2][2] = -U[2][2];
421 }
422
423 // Now we have R, we build Hessian and residuals
424 // But first, we need to anchor a point
425 if (idx_i == anchor_idx) {
426 R[0][0] = R[1][1] = R[2][2] = 1;
427 R[0][1] = R[0][2] = R[1][0] = R[1][2] = R[2][0] = R[2][1] =
428 0;
429 }
430 for (int k = 0; k < 6; ++k) {
431 bool mask_k = mask_nbs[k];
432
433 if (mask_k) {
434 int idx_k = idx_nbs[k];
435
436 float diff_ik_init[3] = {
437 positions_init_ptr[idx_i * 3 + 0] -
438 positions_init_ptr[idx_k * 3 + 0],
439 positions_init_ptr[idx_i * 3 + 1] -
440 positions_init_ptr[idx_k * 3 + 1],
441 positions_init_ptr[idx_i * 3 + 2] -
442 positions_init_ptr[idx_k * 3 + 2]};
443 float diff_ik_curr[3] = {
444 positions_curr_ptr[idx_i * 3 + 0] -
445 positions_curr_ptr[idx_k * 3 + 0],
446 positions_curr_ptr[idx_i * 3 + 1] -
447 positions_curr_ptr[idx_k * 3 + 1],
448 positions_curr_ptr[idx_i * 3 + 2] -
449 positions_curr_ptr[idx_k * 3 + 2]};
450 float R_diff_ik_curr[3];
451
452 core::linalg::kernel::matmul3x3_3x1(*R, diff_ik_init,
453 R_diff_ik_curr);
454
455 float local_r[3];
456 local_r[0] = diff_ik_curr[0] - R_diff_ik_curr[0];
457 local_r[1] = diff_ik_curr[1] - R_diff_ik_curr[1];
458 local_r[2] = diff_ik_curr[2] - R_diff_ik_curr[2];
459
460 int offset_idx_i = 3 * idx_i + 6 * n_frags;
461 int offset_idx_k = 3 * idx_k + 6 * n_frags;
462
463#if defined(__CUDACC__)
464 // Update residual
465 atomicAdd(residual_ptr,
466 weight * (local_r[0] * local_r[0] +
467 local_r[1] * local_r[1] +
468 local_r[2] * local_r[2]));
469
470 for (int axis = 0; axis < 3; ++axis) {
471 // Update AtA: 2x2
472 atomicAdd(&AtA_ptr[(offset_idx_i + axis) * n_vars +
473 offset_idx_i + axis],
474 weight);
475 atomicAdd(&AtA_ptr[(offset_idx_k + axis) * n_vars +
476 offset_idx_k + axis],
477 weight);
478 atomicAdd(&AtA_ptr[(offset_idx_i + axis) * n_vars +
479 offset_idx_k + axis],
480 -weight);
481 atomicAdd(&AtA_ptr[(offset_idx_k + axis) * n_vars +
482 offset_idx_i + axis],
483 -weight);
484
485 // Update Atb: 2x1
486 atomicAdd(&Atb_ptr[offset_idx_i + axis],
487 +weight * local_r[axis]);
488 atomicAdd(&Atb_ptr[offset_idx_k + axis],
489 -weight * local_r[axis]);
490 }
491#else
492 {
493 tbb::spin_mutex::scoped_lock lock(
494 fill_alignment_mutex);
495 // Update residual
496 *residual_ptr += weight * (local_r[0] * local_r[0] +
497 local_r[1] * local_r[1] +
498 local_r[2] * local_r[2]);
499
500 for (int axis = 0; axis < 3; ++axis) {
501 // Update AtA: 2x2
502 AtA_ptr[(offset_idx_i + axis) * n_vars +
503 offset_idx_i + axis] += weight;
504 AtA_ptr[(offset_idx_k + axis) * n_vars +
505 offset_idx_k + axis] += weight;
506
507 AtA_ptr[(offset_idx_i + axis) * n_vars +
508 offset_idx_k + axis] -= weight;
509 AtA_ptr[(offset_idx_k + axis) * n_vars +
510 offset_idx_i + axis] -= weight;
511
512 // Update Atb: 2x1
513 Atb_ptr[offset_idx_i + axis] +=
514 weight * local_r[axis];
515 Atb_ptr[offset_idx_k + axis] -=
516 weight * local_r[axis];
517 }
518 }
519#endif
520 }
521 }
522 });
523#undef LOCAL_LAMBDA_CAPTURE
524}
525#endif // OPEN3D_SKIP_FILL_IN_LS_MAIN
526} // namespace kernel
527} // namespace pipelines
528} // namespace t
529} // namespace open3d
#define OPEN3D_HOST_DEVICE
Definition CUDAUtils.h:43
#define OPEN3D_DEVICE
Definition CUDAUtils.h:44
#define OPEN3D_FORCE_INLINE
Definition CUDAUtils.h:42
std::vector< int > indices
Definition PointCloudSmoothing.cpp:133
Real weight
Definition SurfaceReconstructionPoisson.cpp:270
double t
Definition SurfaceReconstructionPoisson.cpp:175
#define LOCAL_LAMBDA_CAPTURE
Definition Device.h:18
Definition Tensor.h:32
T * GetDataPtr()
Definition Tensor.h:1203
Tensor View(const SizeVector &dst_shape) const
Definition Tensor.cpp:766
static Tensor Zeros(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with zeros.
Definition Tensor.cpp:405
void IndexSet(const std::vector< Tensor > &index_tensors, const Tensor &src_tensor)
Advanced indexing getter.
Definition Tensor.cpp:1009
Tensor IndexGet(const std::vector< Tensor > &index_tensors) const
Advanced indexing getter. This will always allocate a new Tensor.
Definition Tensor.cpp:978
OPEN3D_DEVICE OPEN3D_FORCE_INLINE void transpose3x3_(scalar_t *A_3x3)
Definition Matrix.h:163
OPEN3D_DEVICE OPEN3D_FORCE_INLINE void matmul3x3_3x3(const scalar_t *A_3x3, const scalar_t *B_3x3, scalar_t *C_3x3)
Definition Matrix.h:48
OPEN3D_DEVICE OPEN3D_FORCE_INLINE void svd3x3(const scalar_t *A_3x3, scalar_t *U_3x3, scalar_t *S_3x1, scalar_t *V_3x3)
OPEN3D_DEVICE OPEN3D_FORCE_INLINE scalar_t det3x3(const scalar_t *A_3x3)
Definition Matrix.h:101
const Dtype Int64
Definition Dtype.cpp:47
void ParallelFor(const Device &device, int64_t n, const func_t &func)
Definition ParallelFor.h:190
const Dtype Float32
Definition Dtype.cpp:42
void FillInSLACAlignmentTermCPU(core::Tensor &AtA, core::Tensor &Atb, core::Tensor &residual, const core::Tensor &Ti_qs, 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 FillInLinearSystemImpl.h:161
void FillInRigidAlignmentTermCPU(core::Tensor &AtA, core::Tensor &Atb, core::Tensor &residual, const core::Tensor &Ti_qs, const core::Tensor &Tj_qs, const core::Tensor &Ri_normal_ps, int i, int j, float threshold)
Definition FillInLinearSystemImpl.h:46
OPEN3D_HOST_DEVICE OPEN3D_FORCE_INLINE void ComputeRigidAlignmentJacobian(const float *q_prime, const float *normal_p_prime, float *J_ij)
Definition FillInLinearSystemImpl.h:27
void FillInSLACRegularizerTermCPU(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 FillInLinearSystemImpl.h:319
Definition PinholeCameraIntrinsic.cpp:16